interaction-design-board
Generate several genuinely different, runnable HTML interaction prototypes for one product surface, combine them in an interactive Design Board, collect structured selection/remix feedback, and only then hand the approved behavior to production implementation. Use when a user asks for multiple clickable UI versions, interaction alternatives, progressive-disclosure options, a Design Board, HTML prototypes, test-time scaling for product design, or says the visual styling is acceptable but the hierarchy, workflow, layout, or interaction still feels unprofessional. Prefer this over static image exploration when the decision depends on what happens after clicking, expanding, selecting, filtering, or moving through states.
1How It Works & Mechanism
Process Gate: First freeze the Decision Contract (user job/decision scope/immutable facts/existing language/first-view invariant/interaction states/stop condition), then propose 3 distinct interaction architecture candidates (families such as command-first/queue-detail/object-dominant/comparison-led/ledger-first, etc.). Each candidate represents an interaction hypothesis rather than a visual reskin, varying only navigation/selection/disclosure/action ownership/information order.
Each candidate embodies a distinct interaction hypothesis rather than a skin.
build_board.py serves as a compliance gate: Reads board.json (schemaVersion=interaction-design-board/v1), validates 2–8 variants, ensures variant files do not escape the manifest directory and are not symlinks, deduplicates via sha256 (rejecting byte-identical files), and enforces that each variant is self-contained HTML (forbids external script/img/link/poster/url() resources and CSS @import, requires a title, forbids <base>), before populating the template to produce a single-file Board.
f"{field} depends on external resource {locator!r}; inline it as CSS, JS, or data URL"
Runtime Isolation = Template-injected CSP + srcdoc sandbox iframe: Each candidate is enclosed in a srcdoc frame where the Board injects a default-src 'none' CSP (permitting only unsafe-inline styles/scripts + data:/blob: media, while completely blocking connect-src/frame-src/object-src/form-action), layered with sandbox='allow-scripts allow-forms allow-modals'.
policy.content = "default-src 'none'; style-src 'unsafe-inline'; script-src 'unsafe-inline'; img-src data: blob:; media-src data: blob:; font-src data:; connect-src 'none'; frame-src 'none'; object-src 'none'; base-uri 'none'; form-action 'none'"
Test-time scaling: When independent worker contexts are available, dispatch one candidate per worker, sharing the same frozen contract while keeping outputs completely isolated from one another to prevent convergence into sibling designs; if workers are unavailable, generate serially but always re-read the frozen contract instead of referencing the previous candidate.
assign one candidate to each worker with the same frozen decision contract and only that candidate's hypothesis. Do not let workers see one another's output.
Feedback Loop: The Board submits feedback.json / feedback-pending.json (including regenerateAction iterate|remix when regenerated:true) → agent retains accepted aspects, alters failed axes, and regenerates only the affected candidates → versions the Board file → sends POST /api/reload (response: {"reloaded":true}) if gstack serve is already active; repeatedly running serve does not count as reload.
curl -sS -X POST "${BOARD_URL%/}/api/reload" \ -H 'Content-Type: application/json' \ -d '{"html":"<absolute-versioned-board-path>"}'
Production Implementation Gate: approved.json is written (recording selected/approved interaction rules/first-view invariant/rejected trade-offs/actual exercised states/remaining unknowns/prototype file identities) only after the user confirms the feedback summary; only then does it proceed to production implementation and verification of the same representative task in a real browser—pixel similarity alone does not count.
Then—and only then—implement in the product.
2Core Capabilities
3External Dependencies
| Kind | Dependency / Endpoint |
|---|---|
| cli | python3(build_board.py,纯 stdlib) |
| cli | gstack design 可执行(可选:serve Board + /api/feedback + /api/reload;未装则开文件直用) |
| cli | curl(可选:Board 重载探测/触发) |
4Recommended Governance & Evidence
- scripts/: Execute local scripts or commands: python3 build_board.py (pure stdlib; reads manifest and variant HTML, writes design-board.html)
- 环境变量 / API Key: Read vendor service credentials: None
- 本地工作目录: File I/O and artifact output: build_board.py writes session-dir/design-board.html; agent writes boa in session-dir following the workflow
5Second-Pass Verification
- [ok] 穿越/symlink/外部资源拒绝 — resolve_variant: symlink 拒 + relative_to(root) 校验;validate_self_contained: RESOURCE_PATTERNS 扫 script/img/link/video/url(),仅放行 data:/blob:/about:。
- [ok] CSP 断网声明 — 模板 241 行 CSP 含 connect-src 'none'; frame-src 'none'; object-src 'none';srcdoc + sandbox allow-scripts allow-forms allow-modals 双保险。
- [ok] sha256 去重与变体数上限 — seen_hashes 重复即 ContractError;'2 <= len(variants) <= 8'。
- [ok] 无网络外发/凭证 — build_board.py imports 仅 stdlib(argparse/hashlib/html/json/re/sys/html.parser/pathlib);无 http/密钥。
- [unlocatable] gstack serve/reload 集成 — 依赖外部 gstack 工具(仓库外),本环境未安装;SKILL 中 serve/reload/反馈端点语义无法端到端验证,代码侧仅见模板对 __GSTACK_SERVER_URL 与 ./api/feedback 的 POST。
- [unlocatable] Board 内候选交互可用性(UI 层) — 模板 434 行含 tab/对比视图/反馈面板 JS,未在浏览器实测;fixtures+test_build_board.py 覆盖构建层而非视觉层。
6Verdict & Scenarios
bb7d5b878d07fe8e…