@playcraft/cli 0.0.55 → 0.0.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. package/README.md +21 -0
  2. package/REMIX.md +103 -19
  3. package/dist/atom-tree/fusion-hints.js +8 -3
  4. package/dist/atom-tree/fusion-intent.js +62 -0
  5. package/dist/atom-tree/selection.js +3 -1
  6. package/dist/commands/create.js +299 -85
  7. package/dist/commands/image.js +79 -69
  8. package/dist/commands/levels.js +29 -0
  9. package/dist/commands/patterns.js +75 -0
  10. package/dist/commands/remix.js +47 -0
  11. package/dist/commands/skills.js +48 -17
  12. package/dist/index.js +9 -5
  13. package/dist/remix/clone-source.js +208 -0
  14. package/dist/remix/clone.js +255 -0
  15. package/dist/scaffold/templates.js +1 -1
  16. package/dist/utils/agent-api-client.js +10 -3
  17. package/dist/utils/remix-image-attachments.js +4 -32
  18. package/dist/utils/sandbox-path.js +20 -0
  19. package/package.json +3 -3
  20. package/project-template/.claude/agents/creative-director.md +114 -0
  21. package/project-template/.claude/agents/developer.md +5 -2
  22. package/project-template/.claude/agents/game-designer.md +41 -20
  23. package/project-template/.claude/agents/refs/README.md +8 -0
  24. package/project-template/.claude/agents/refs/creative-director-guide.md +35 -0
  25. package/project-template/.claude/agents/refs/creative-director-kickoff-guide.md +52 -0
  26. package/project-template/.claude/agents/refs/creative-discovery-guide.md +76 -0
  27. package/project-template/.claude/agents/refs/creative-north-star-examples.md +82 -0
  28. package/project-template/.claude/agents/refs/developer-dev-handoff.md +1 -1
  29. package/project-template/.claude/agents/refs/game-designer-fusion-depth-playbook.md +28 -0
  30. package/project-template/.claude/agents/refs/game-designer-gameplay-sufficiency.md +4 -4
  31. package/project-template/.claude/agents/reviewer.md +11 -0
  32. package/project-template/.claude/hooks/README.md +12 -12
  33. package/project-template/.claude/hooks/block-developer-preflight.mjs +49 -13
  34. package/project-template/.claude/hooks/block-ring1-tasklist.mjs +1 -1
  35. package/project-template/.claude/hooks/user-prompt.mjs +3 -13
  36. package/project-template/.claude/hooks/validate-workflow-stop.mjs +209 -12
  37. package/project-template/.claude/settings.json +2 -2
  38. package/project-template/.claude/skills/playcraft-playable-optimization/SKILL.md +20 -20
  39. package/project-template/.claude/skills/session-analyzer/scripts/resolve-session.mjs +0 -1
  40. package/project-template/.claude/snapshot.mjs +0 -1
  41. package/project-template/.codebuddy/settings.json +1 -1
  42. package/project-template/.cursor/rules/playcraft-orchestrator.mdc +1 -1
  43. package/project-template/CLAUDE.md +9 -9
  44. package/project-template/docs/project-state.md +1 -1
  45. package/project-template/docs/team/agent-conduct.md +18 -18
  46. package/project-template/docs/team/collaboration.md +19 -7
  47. package/project-template/docs/team/workflow-changelog.md +15 -0
  48. package/project-template/fusion-patterns/catalog.json +77 -0
  49. package/project-template/package.json +2 -0
  50. package/project-template/skills/_shared/scripts/create-playable.mjs +31 -11
  51. package/project-template/skills/_shared/scripts/dev-start.mjs +3 -3
  52. package/project-template/skills/_shared/scripts/disclosure-config.mjs +65 -39
  53. package/project-template/skills/_shared/scripts/harness-smoke.mjs +3 -1
  54. package/project-template/skills/_shared/scripts/lib/fusion-intent.mjs +88 -0
  55. package/project-template/skills/_shared/scripts/lib/skill-fidelity.mjs +185 -0
  56. package/project-template/skills/_shared/scripts/slice-set.mjs +29 -2
  57. package/project-template/skills/_shared/scripts/state-get.mjs +124 -7
  58. package/project-template/skills/_shared/scripts/state-store.mjs +25 -2
  59. package/project-template/skills/_shared/scripts/validate-level-sketch.mjs +444 -0
  60. package/project-template/skills/_shared/scripts/verify-design-consistency.mjs +728 -0
  61. package/project-template/skills/playable-record/scripts/lib/dev-server.mjs +46 -11
  62. package/project-template/skills/playable-record/scripts/record-playable.mjs +2 -1
  63. package/project-template/skills/playable-record/scripts/verify-contract.mjs +4 -4
  64. package/project-template/skills/playable-record/scripts/verify-firstwin.mjs +3 -3
  65. package/project-template/skills/playable-record/scripts/verify-fusion.mjs +37 -2
  66. package/project-template/skills/playable-record/scripts/verify-slice.mjs +2 -2
  67. package/project-template/templates/design-brief.template.md +34 -0
  68. package/project-template/templates/design-methodology.md +1 -2
  69. package/project-template/templates/design.template.md +65 -0
  70. package/project-template/templates/developer-log.template.md +12 -1
  71. package/project-template/templates/five-axis-framework.md +12 -0
  72. package/project-template/templates/game-designer-creative-process.template.md +99 -0
  73. package/project-template/templates/level-sketch.template.json +56 -0
  74. package/project-template/templates/north-star.template.md +43 -0
  75. package/project-template/templates/project-state.template.md +1 -1
  76. package/project-template/vite.config.ts +4 -5
  77. package/project-templates/phaser/.claude/agents/creative-director.md +114 -0
  78. package/project-templates/phaser/.claude/agents/game-designer.md +41 -20
  79. package/project-templates/phaser/.claude/agents/refs/creative-director-guide.md +35 -0
  80. package/project-templates/phaser/.claude/agents/refs/creative-director-kickoff-guide.md +52 -0
  81. package/project-templates/phaser/.claude/agents/refs/creative-discovery-guide.md +76 -0
  82. package/project-templates/phaser/.claude/agents/refs/creative-north-star-examples.md +82 -0
  83. package/project-templates/phaser/.claude/agents/refs/developer-dev-handoff.md +1 -1
  84. package/project-templates/phaser/.claude/agents/refs/game-designer-fusion-depth-playbook.md +28 -0
  85. package/project-templates/phaser/.claude/agents/reviewer.md +11 -0
  86. package/project-templates/phaser/.claude/hooks/block-ring1-tasklist.mjs +2 -2
  87. package/project-templates/phaser/.claude/hooks/user-prompt.mjs +17 -18
  88. package/project-templates/phaser/.claude/hooks/validate-workflow-stop.mjs +209 -12
  89. package/project-templates/phaser/.claude/skills/playcraft-playable-optimization/SKILL.md +20 -20
  90. package/project-templates/phaser/.cursor/rules/playcraft-orchestrator.mdc +1 -1
  91. package/project-templates/phaser/CLAUDE.md +88 -54
  92. package/project-templates/phaser/docs/DESIGN.md +25 -0
  93. package/project-templates/phaser/docs/project-state.md +1 -1
  94. package/project-templates/phaser/docs/team/collaboration.md +19 -7
  95. package/project-templates/phaser/docs/team/workflow-changelog.md +14 -0
  96. package/project-templates/phaser/fusion-patterns/catalog.json +77 -0
  97. package/project-templates/phaser/package.json +3 -1
  98. package/project-templates/phaser/skills/_shared/scripts/dev-start.mjs +3 -3
  99. package/project-templates/phaser/skills/_shared/scripts/disclosure-config.mjs +65 -39
  100. package/project-templates/phaser/skills/_shared/scripts/harness-smoke.mjs +3 -1
  101. package/project-templates/phaser/skills/_shared/scripts/lib/fusion-intent.mjs +88 -0
  102. package/project-templates/phaser/skills/_shared/scripts/lib/skill-fidelity.mjs +185 -0
  103. package/project-templates/phaser/skills/_shared/scripts/state-get.mjs +124 -7
  104. package/project-templates/phaser/skills/_shared/scripts/state-store.mjs +25 -2
  105. package/project-templates/phaser/skills/_shared/scripts/validate-level-sketch.mjs +444 -0
  106. package/project-templates/phaser/skills/_shared/scripts/verify-design-consistency.mjs +728 -0
  107. package/project-templates/phaser/skills/playable-record/scripts/lib/dev-server.mjs +46 -11
  108. package/project-templates/phaser/skills/playable-record/scripts/record-playable.mjs +2 -1
  109. package/project-templates/phaser/skills/playable-record/scripts/verify-contract.mjs +4 -4
  110. package/project-templates/phaser/skills/playable-record/scripts/verify-firstwin.mjs +3 -3
  111. package/project-templates/phaser/skills/playable-record/scripts/verify-fusion.mjs +37 -2
  112. package/project-templates/phaser/skills/playable-record/scripts/verify-slice.mjs +2 -2
  113. package/project-templates/phaser/templates/design-brief.template.md +42 -11
  114. package/project-templates/phaser/templates/design-methodology.md +1 -2
  115. package/project-templates/phaser/templates/design.template.md +77 -0
  116. package/project-templates/phaser/templates/five-axis-framework.md +50 -1
  117. package/project-templates/phaser/templates/game-designer-creative-process.template.md +99 -0
  118. package/project-templates/phaser/templates/level-sketch.template.json +56 -0
  119. package/project-templates/phaser/templates/north-star.template.md +43 -0
  120. package/project-templates/phaser/templates/project-state.template.md +1 -1
  121. package/project-templates/phaser/vite.config.ts +4 -5
  122. package/project-templates/threejs/.claude/agents/creative-director.md +114 -0
  123. package/project-templates/threejs/.claude/agents/game-designer.md +41 -20
  124. package/project-templates/threejs/.claude/agents/refs/creative-director-guide.md +35 -0
  125. package/project-templates/threejs/.claude/agents/refs/creative-director-kickoff-guide.md +52 -0
  126. package/project-templates/threejs/.claude/agents/refs/creative-discovery-guide.md +76 -0
  127. package/project-templates/threejs/.claude/agents/refs/creative-north-star-examples.md +82 -0
  128. package/project-templates/threejs/.claude/agents/refs/developer-dev-handoff.md +1 -1
  129. package/project-templates/threejs/.claude/agents/refs/game-designer-fusion-depth-playbook.md +28 -0
  130. package/project-templates/threejs/.claude/agents/reviewer.md +11 -0
  131. package/project-templates/threejs/.claude/hooks/block-ring1-tasklist.mjs +2 -2
  132. package/project-templates/threejs/.claude/hooks/user-prompt.mjs +17 -18
  133. package/project-templates/threejs/.claude/hooks/validate-workflow-stop.mjs +209 -12
  134. package/project-templates/threejs/.claude/skills/playcraft-playable-optimization/SKILL.md +20 -20
  135. package/project-templates/threejs/.cursor/rules/playcraft-orchestrator.mdc +1 -1
  136. package/project-templates/threejs/CLAUDE.md +88 -54
  137. package/project-templates/threejs/docs/DESIGN.md +25 -0
  138. package/project-templates/threejs/docs/project-state.md +1 -1
  139. package/project-templates/threejs/docs/team/collaboration.md +19 -7
  140. package/project-templates/threejs/docs/team/workflow-changelog.md +14 -0
  141. package/project-templates/threejs/fusion-patterns/catalog.json +77 -0
  142. package/project-templates/threejs/package.json +3 -1
  143. package/project-templates/threejs/skills/_shared/scripts/dev-start.mjs +3 -3
  144. package/project-templates/threejs/skills/_shared/scripts/disclosure-config.mjs +65 -39
  145. package/project-templates/threejs/skills/_shared/scripts/harness-smoke.mjs +3 -1
  146. package/project-templates/threejs/skills/_shared/scripts/lib/fusion-intent.mjs +88 -0
  147. package/project-templates/threejs/skills/_shared/scripts/lib/skill-fidelity.mjs +185 -0
  148. package/project-templates/threejs/skills/_shared/scripts/state-get.mjs +124 -7
  149. package/project-templates/threejs/skills/_shared/scripts/state-store.mjs +25 -2
  150. package/project-templates/threejs/skills/_shared/scripts/validate-level-sketch.mjs +444 -0
  151. package/project-templates/threejs/skills/_shared/scripts/verify-design-consistency.mjs +728 -0
  152. package/project-templates/threejs/skills/playable-record/scripts/lib/dev-server.mjs +46 -11
  153. package/project-templates/threejs/skills/playable-record/scripts/record-playable.mjs +2 -1
  154. package/project-templates/threejs/skills/playable-record/scripts/verify-contract.mjs +4 -4
  155. package/project-templates/threejs/skills/playable-record/scripts/verify-firstwin.mjs +3 -3
  156. package/project-templates/threejs/skills/playable-record/scripts/verify-fusion.mjs +37 -2
  157. package/project-templates/threejs/skills/playable-record/scripts/verify-slice.mjs +2 -2
  158. package/project-templates/threejs/templates/design-brief.template.md +42 -11
  159. package/project-templates/threejs/templates/design-methodology.md +1 -2
  160. package/project-templates/threejs/templates/design.template.md +77 -0
  161. package/project-templates/threejs/templates/five-axis-framework.md +50 -1
  162. package/project-templates/threejs/templates/game-designer-creative-process.template.md +99 -0
  163. package/project-templates/threejs/templates/level-sketch.template.json +56 -0
  164. package/project-templates/threejs/templates/north-star.template.md +43 -0
  165. package/project-templates/threejs/templates/project-state.template.md +1 -1
  166. package/project-templates/threejs/vite.config.ts +4 -5
  167. package/project-template/docs/DESIGN.md +0 -65
@@ -1,84 +1,118 @@
1
- # PlayCraft Playable Ads Project
1
+ # CLAUDE.md
2
2
 
3
- ## L0 Quickstart
3
+ This file provides guidance to Claude Code (claude.ai/code) when working in a PlayCraft generated playable-ad project.
4
4
 
5
- You are building a playable ad: a self-contained HTML5 mini-game. Daily work is driven by a **slice queue** (`dispatchPacket`); **growth rings** are the outer budget, convergence boundary, and user Ring Gate.
5
+ ## Project Overview
6
6
 
7
- Start every turn with the smallest possible context:
7
+ This repository is a **PlayCraft playable-ad project**: a mini-game plus the local scripts, docs, and agent tooling used to produce and verify it.
8
+
9
+ **This file is an entry index, not the task spec.** What to do next — role, scope, required files, verifiers — comes from `npm run state:get` each turn. Product and workflow detail lives under `docs/` and `.cursor/rules/` when state or your current action points you there.
10
+
11
+ ## Start Every Turn
12
+
13
+ Run the smallest possible context load first:
8
14
 
9
15
  ```bash
10
16
  npm run workflow:doctor
11
17
  npm run state:get
12
18
  ```
13
19
 
14
- `state:get` tells you the current `iteration`, `loop`, `currentAction`, `next_orchestrator_action`, `contextPacket`, current required files, allowed tasks, forbidden tasks, current verifiers, and next commands. **Use `state:get` as your handoff summary — never open or hand-edit `docs/project-state.md`.** Read `contextPacket` first, then only the files `state:get` lists as required. Pull deeper docs only when the current action names them.
20
+ `state:get` exposes `iteration`, `loop`, `currentAction`, `next_orchestrator_action`, `contextPacket`, **required files**, allowed/forbidden tasks, active verifiers, and next commands.
15
21
 
16
- > **State is programmatic.** `docs/project-state.json` is the machine source of truth, including `handoffContext` shared working memory; `docs/project-state.md` is a GENERATED, read-only view re-rendered after every write. **Read state with `npm run state:get`; write state with `npm run state:set` (or `npm run ring:gate` / STOP hooks).** Do not edit the markdown by hand — your edits will be overwritten on the next write, and the tables you need always exist because the renderer emits them.
22
+ **Use `state:get` as your handoff summary.** Read `contextPacket` first, then only the files `state:get` lists as required. Do not open or hand-edit `docs/project-state.md`.
17
23
 
18
- ## Non-Negotiables
24
+ ## State Files
19
25
 
20
- - First level must guarantee player success.
21
- - Runtime must start at `HOOK`.
22
- - `autoPlay()` must progress from player-reachable actions to `ENDCARD`; do not fake victory by directly setting `ENDCARD`, repainting the whole board into a win, or calling a win screen directly.
23
- - For Ring 1, do not create internal Task lists (`TaskCreate` / `TaskUpdate` / …). **You are the orchestrator** — dispatch role subagents via `Task` / `@game-designer` / temporary ref-flow atom-selection subagent / `@developer`; do **not** role-play Designer, atom selector, or Developer inline in one session.
24
- - Use project scripts only: `npm run ...` or repository-provided `playcraft ...`; never use `npx`.
25
- - Typecheck with `npm run typecheck`.
26
- - Harness pass standard is `window.__playable`; legacy `window.__game` scene hooks are migration-only.
27
- - User Ring Gate is orchestrator-only.
28
- - Follow `state:get` output, not remembered Ring instructions.
26
+ - `docs/project-state.json` — machine source of truth (`handoffContext`, `sliceState`, workflow cursor).
27
+ - `docs/project-state.md` — generated read-only view; rewritten after every write.
28
+ - Read: `npm run state:get`.
29
+ - Write: `npm run state:set`, `npm run slice:set`, `npm run state:advance-ring`, or `npm run ring:gate`.
29
30
 
30
- ## Slice-axis dispatch (primary — orchestrator)
31
+ ## Work Model
31
32
 
32
- When `npm run state:get -- --json dispatchPacket dispatchMode recommendedNextAction` returns **`dispatchMode: true`**:
33
+ Two coordination layers:
33
34
 
34
- 1. **Dispatch unit** = `role + doWhat + flow + sliceId` from `dispatchPacket` — not ring loop names.
35
- 2. Invoke subagents with **packet scope only**; never say "Ring 1 build" or ask them to self-identify Ring / Gate / Loop.
36
- 3. After STOP: trust **`sliceState`** + STOP hook (`verify:slice` / `verify:slice-artist` / `verify:slice-ta`, then `slice:set`) — not handoff markdown as authority.
37
- 4. **`ring:gate`** still runs for objective DoD and user Ring Gate; it aggregates slice queue terminal state but does **not** replace per-slice verify on STOP.
35
+ | Layer | Role |
36
+ | ---------------- | -------------------------------------------------------------------------------------------------------- |
37
+ | **Slice queue** | Daily dispatch when `dispatchPacket` exists — unit of work = `role + doWhat + flow + sliceId`. |
38
+ | **Growth rings** | Outer budget, non-regression boundary, objective DoD (Definition of Done, 完成定义), user **Ring Gate**. |
38
39
 
39
- When **`dispatchPacket` is null** (`dispatchMode: false`): use the legacy growth-ring path below until Designer seeds `sliceState`.
40
+ When `dispatchMode: true`, slice dispatch is primary:
40
41
 
41
- ## Current Workflow
42
+ ```bash
43
+ npm run state:get -- --json dispatchPacket dispatchMode recommendedNextAction
44
+ ```
42
45
 
43
- 1. Read state with `npm run state:get` (never open the generated `docs/project-state.md`).
44
- 2. If `dispatchMode: true` → follow `recommendedNextAction` / `dispatchPacket`; else follow `next_orchestrator_action`.
45
- 3. Keep work inside the current slice (dispatch mode) or current ring (legacy).
46
- 4. After a sub-agent stops, run verifiers from `state:get` (per-slice verify before ring gate when slices are active).
47
- 5. When `ring:gate` says `canAskUser: yes`, the orchestrator asks the user to accept the dev URL.
46
+ When `dispatchPacket` is null, follow `next_orchestrator_action` until Designer seeds `sliceState`.
48
47
 
49
- ## Ring 1 Dispatch Path (legacy growth-rings — orchestrator)
48
+ **Orchestrator protocol** (per-iteration dispatch, STOP hooks, Ring Gate, handoff matrix): `.cursor/rules/playcraft-orchestrator.mdc` and `docs/team/collaboration.md`. Do not duplicate those rules here.
50
49
 
51
- When `state:get` reports `iteration: 1`, **stay orchestrator** — invoke role subagents; do not inline their work.
50
+ ## Non-Negotiables
52
51
 
53
- | `loop` | Orchestrator does |
54
- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
55
- | `clarify` | **Invoke `@game-designer`** — ring 1 clarify (single concise `docs/DESIGN.md`). Do not write `DESIGN.md` yourself. |
56
- | (after GD STOP) | **Spawn a temporary ref-flow atom-selection subagent** — create the minimal ring 1 atom-tree package: engine decision, compact gameplay trunk, selected atoms, and ring 1 verifier metadata. Do not make main orchestrator select atoms inline. |
57
- | (after selector STOP) | Run scaffold gate: `validate-atom-tree-selection` → `init-template --from-atom-tree` → `npm install` → `npm run verify:contract` → `npm run verify:lifecycle`. Set `loop: build`, then **Invoke `@developer`**. |
58
- | `build` | **Invoke `@developer`** — ring 1 build only the smallest verifiable playable spine (placeholder art, one player-reachable action loop, `window.__playable`). Developer self-gates with `verify:contract` + `verify:lifecycle` + `verify:firstwin` + `verify:placeholders` on STOP. |
59
- | `verify` | Run `npm run ring:gate -- --iteration 1` (no `@reviewer` in ring 1). |
52
+ - First level must guarantee player success.
53
+ - Runtime must start at `HOOK`; `autoPlay()` must reach `ENDCARD` through player-reachable actions only.
54
+ - Do not fake victory (direct `ENDCARD`, full-board repaint win, or calling a win screen directly).
55
+ - Harness pass standard is `window.__playable`; legacy `window.__game` hooks are migration-only.
56
+ - Use project scripts only: `npm run ...` or `playcraft ...`; do not use `npx`.
57
+ - Typecheck with `npm run typecheck`.
58
+ - **Ring Gate** is orchestrator-only — sub-agents must not ask the user to accept devUrl.
59
+ - Follow `state:get` output, not remembered workflow instructions.
60
+ - **Orchestrator**: do not create internal Task lists (`TaskCreate` / `TaskUpdate`); invoke role subagents when state directs.
60
61
 
61
- Follow `next_orchestrator_action` from handoff when `subagent_stop: true`. See `docs/team/collaboration.md` § Ring 1 engine scaffold.
62
+ ## Current Workflow
62
63
 
63
- ## Deeper References
64
+ 1. `npm run workflow:doctor` → `npm run state:get`.
65
+ 2. Read `contextPacket`, then required files only.
66
+ 3. If `dispatchMode: true` → dispatch the current `dispatchPacket`; else follow `next_orchestrator_action`.
67
+ 4. After sub-agent STOP → run verifiers from `state:get`.
68
+ 5. When objective DoD is due → `npm run ring:gate -- --iteration N`; ask the user only when `ring:gate` reports `canAskUser: yes`.
69
+
70
+ ## Runtime Contract
71
+
72
+ - Expose `window.__playable` with `autoPlay()` proving a reachable first-win path.
73
+ - Lifecycle: `HOOK` → player actions → `ENDCARD`.
74
+ - Verifier-facing behavior stays engine-neutral; keep asset paths in sync with code.
64
75
 
65
- Use these only when the current action needs them:
76
+ ## Common Commands
77
+
78
+ ```bash
79
+ npm run dev
80
+ npm run typecheck
81
+ npm run build
82
+ npm run verify:contract
83
+ npm run verify:lifecycle
84
+ npm run verify:firstwin
85
+ npm run verify:placeholders
86
+ npm run workflow:doctor
87
+ npm run state:get
88
+ npm run state:set
89
+ npm run ring:gate -- --iteration N
90
+ npm run record:mp4
91
+ npm run verify:ui
92
+ ```
66
93
 
67
- | Need | Read |
68
- | ---------------------------------------------- | ----------------------------------------- |
69
- | Full collaboration and Ring Gate protocol | `docs/team/collaboration.md` |
70
- | Role conduct and MUST/NEVER rules | `docs/team/agent-conduct.md` |
71
- | Runtime model and `window.__playable` boundary | `docs/team/core-model.md` |
72
- | Post-stop verification matrix | `docs/team/agent-runtime-matrix.md` |
73
- | Atom-tree schema and Skill selection | `docs/team/atom-tree-format.md` |
74
- | Legacy harness migration | `docs/team/harness-legacy-deprecation.md` |
94
+ Full script list: `package.json` → `scripts`.
75
95
 
76
96
  ## Directory Map
77
97
 
78
98
  ```text
79
- docs/ project-state, DESIGN, ring-specific specs
80
- game/ runtime implementation
81
- logs/ developer/reviewer/artist/TA logs
82
- assets/ placeholder and production media
83
- skills/ local verifier, record, art, and workflow scripts
99
+ docs/ project state, design contracts, team references
100
+ game/ runtime (after engine scaffold)
101
+ logs/ role logs and review reports
102
+ assets/ placeholder and production media
103
+ skills/ verifiers, record, art, workflow scripts
104
+ templates/ source templates for workflow scripts
84
105
  ```
106
+
107
+ ## Deeper References
108
+
109
+ Pull these only when the current action names them:
110
+
111
+ | Need | Read |
112
+ | ------------------------------------------------ | ----------------------------------------- |
113
+ | Collaboration, per-iteration dispatch, Ring Gate | `docs/team/collaboration.md` |
114
+ | Role MUST/NEVER rules | `docs/team/agent-conduct.md` |
115
+ | `window.__playable` model | `docs/team/core-model.md` |
116
+ | Post-STOP verification matrix | `docs/team/agent-runtime-matrix.md` |
117
+ | Atom-tree / Skill selection | `docs/team/atom-tree-format.md` |
118
+ | Legacy harness migration | `docs/team/harness-legacy-deprecation.md` |
@@ -63,3 +63,28 @@
63
63
  ## 5. Ring 1 HOOK Entry
64
64
 
65
65
  {Describe the starting HOOK state that is visible immediately when the game loads. It should be enough for `verify:lifecycle` to observe `HOOK`, then for `autoPlay()` to advance through player-reachable actions to `ENDCARD`.}
66
+
67
+ ---
68
+
69
+ ## 6. Gameplay Fusion
70
+
71
+ - **Fusion type**: {Single | B1-Passive | B2-Active | C-Sequential | D-Parallel}
72
+ - **Primary mechanic**: {main interaction}
73
+ - **Secondary mechanic** (if fusion): {how it enhances payoff}
74
+ - **Pseudo-fusion decision**: {downgrade reason, risk accepted, or n/a}
75
+
76
+ ---
77
+
78
+ ## 7. Gameplay Seed (Ring 1)
79
+
80
+ ### Player Fantasy
81
+
82
+ {2–4 sentences: what the player sees in 30s, wants to tap, and why they continue.}
83
+
84
+ ### Decision Moment
85
+
86
+ {One scene: the single aha or mis-tap moment — blocked feedback, unlock, or combo payoff.}
87
+
88
+ ### First Level Scenario
89
+
90
+ {Describe opening board state as a **scenario** (not KPI numbers): which paths look free vs blocked, what the first correct tap teaches.}
@@ -55,7 +55,7 @@
55
55
 
56
56
  Each iteration runs inner loops: `clarify` → `build` → `verify` → **Ring Gate** (user acceptance) → next iteration.
57
57
 
58
- <!-- Iteration definitions: see CLAUDE.md § Growth-Ring Model -->
58
+ <!-- Iteration definitions: see docs/team/collaboration.md (growth-rings-v1) -->
59
59
 
60
60
  ## Ring DoD (current iteration)
61
61
 
@@ -90,12 +90,22 @@ See [core-model.md § Command Contract](core-model.md#command-contract) and [har
90
90
 
91
91
  ### Per-ring flow
92
92
 
93
- | Step | Loop | Agent(s) | STOP → next |
94
- | ---- | ------- | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
95
- | 1 | clarify | `@game-designer` → temporary ref-flow selector | Orchestrator → ring 1: context packet + compact atom selection → `init-template` + `verify:contract` first → `loop: build` → `@developer` |
96
- | 2 | build | `@developer` (+ Artist/TA per ring) | Ring 1: Developer self-gate (`verify:contract` + `verify:lifecycle` + `verify:firstwin` + `verify:placeholders`) → `loop: verify` → orchestrator `ring:gate`; ring 2+: → `loop: verify` → `@reviewer` |
97
- | 3 | verify | ring 1: orchestrator only; ring 2+: `@reviewer` | Orchestrator → `npm run ring:gate -- --iteration N` |
98
- | 4 | — | **Orchestrator only** | If pass → Ring Gate `AskUserQuestion` at devUrl → archive ring → `iteration+1`, `loop: clarify` |
93
+ | Step | Loop | Agent(s) | STOP → next |
94
+ | ---- | ------- | ----------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
95
+ | 1 | clarify | `@game-designer` mechanism lock → `@creative-director` (PGS wrap) → `@game-designer` spec → temporary ref-flow selector | Orchestrator → primaryGameplaySkill → north star → design spec (verbatim §0 + PGS) → compact atom selection → `init-template` + `verify:contract` → `loop: build` → `@developer` |
96
+
97
+ #### Ring 1 clarify — `@creative-director` outputs (`CREATIVE_DIRECTOR_SPLIT=1`)
98
+
99
+ | Artifact | Required fields | Notes |
100
+ | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------- |
101
+ | `docs/north-star.md` | **Micro-Story Spine** (Narrative level, Who, Situation, Stakes, Payoff image, Emotional arc) + One-liner + System Dynamic + Why fusion + Rejected vibe | Creative source of truth; default L1/L2; L0 only when user opts out of story |
102
+ | `docs/creative-process.md` | Phase 1 ≥3 candidates (each with Story hook) + Phase 3 Narrative level rationale + Phase 4 Design Intent | L0 opt-out must cite user wording in Phase 3 |
103
+
104
+ Orchestrator spawn brief: translate user mechanism seed → **Creative question** per `creative-director-kickoff-guide.md`. `@game-designer` spec copies §0 One-liner **verbatim** and Micro-Story Spine **field-value match** into `docs/DESIGN.md` §0.
105
+
106
+ | 2 | build | `@developer` (+ Artist/TA per ring) | Ring 1: Developer self-gate (`verify:contract` + `verify:lifecycle` + `verify:firstwin` + `verify:placeholders`) → `loop: verify` → orchestrator `ring:gate`; ring 2+: → `loop: verify` → `@reviewer` |
107
+ | 3 | verify | ring 1: orchestrator only; ring 2+: `@reviewer` | Orchestrator → `npm run ring:gate -- --iteration N` |
108
+ | 4 | — | **Orchestrator only** | If pass → Ring Gate `AskUserQuestion` at devUrl → archive ring → `iteration+1`, `loop: clarify` |
99
109
 
100
110
  ### Ring DoD by iteration
101
111
 
@@ -312,7 +322,9 @@ Full detail: `.claude/agents/<role>.md` § Goals.
312
322
  │
313
323
  ├── docs/project-state.json ⏳ state-store machine truth
314
324
  ├── docs/project-state.md ⏳ generated read-only view
315
- ├── docs/DESIGN.md ⏳ Ring 1 clarify(唯一交付物)
325
+ ├── docs/DESIGN.md ⏳ Ring 1 clarify(Game Designer spec 交付物)
326
+ ├── docs/north-star.md ⏳ Ring 1 clarify(Creative Director 交付物)
327
+ ├── docs/creative-process.md ⏳ Ring 1 clarify(Creative Director 交付物)
316
328
  ├── docs/design-brief.md ⏳ Ring 2+ 过程日志(Ring 1 不创建)
317
329
  ├── docs/atom-tree.json ⏳ 逐环增长
318
330
  ├── docs/layout-spec.md ⏳ Ring 2+ clarify
@@ -6,6 +6,20 @@ Template workflow spec versions for `packages/cli/project-template`. New project
6
6
 
7
7
  **Effective**: project-template default for new playable-ad projects (template `0.3.2-alpha.0`).
8
8
 
9
+ ### 2026-06-28 — Creative Director v2 Micro-Story
10
+
11
+ - **Enhancement**: Ring 1 creative discovery now defaults to **Micro-Story Spine** (Narrative level / Who / Situation / Stakes / Payoff image / Emotional arc) in `docs/north-star.md` § Micro-Story Spine; L1/L2 are default, L0 only on explicit user opt-out.
12
+ - **Orchestrator kickoff**: read `creative-director-kickoff-guide.md` and inject **Creative question** (Hook frame / pressure meaning / first payoff) — do not forward mechanism spec verbatim to `@creative-director`.
13
+ - **Methodology disclosure**: `disclosure-config` `1:creative` exposes `referenceReads` (five-axis-framework, design-methodology, creative-north-star-examples); agents read via `npm run state:get` summary.
14
+ - **`verify:design`**: independent `validateStorySpine()` + `STORY_SPINE_MODE` (default `warn`); L0 exempts mechanism-chain heuristic; CD STOP hook requires Micro-Story Spine section.
15
+
16
+ ### 2026-06-25 — Creative Director split (Ring 1 creative isolation)
17
+
18
+ - **Fix**: North Star v2 alone still produced mechanism-chain §0 when Game Designer optimized validators. Ring 1 clarify now routes `@creative-director` → `@game-designer` spec (default `CREATIVE_DIRECTOR_SPLIT=1`).
19
+ - **Outputs**: `docs/north-star.md` (creative source of truth) + `docs/creative-process.md` before DESIGN / skills / verify.
20
+ - **`disclosure-config`**: new `1:creative` and `1:spec` keys; monolithic `1:clarify` when `CREATIVE_DIRECTOR_SPLIT=0` (harness control arm).
21
+ - **`verify:design`**: mechanism-chain heuristic + north-star ↔ DESIGN §0 verbatim sync when split enabled.
22
+
9
23
  ### 2026-06-23 — Ring 1 responsibility split
10
24
 
11
25
  - **Fix**: split atom-tree selection out of the orchestrator and Game Designer. Ring 1 now routes `@game-designer` → temporary ref-flow atom-selection subagent → scaffold gate → `@developer`.
@@ -0,0 +1,77 @@
1
+ {
2
+ "schemaVersion": 2,
3
+ "patterns": [
4
+ {
5
+ "id": "arrow_pick_match_fusion",
6
+ "intentTags": ["arrow", "elimination", "fusion", "match-3", "消除", "箭头", "融合"],
7
+ "title": "Arrow slide-out + tray match-3",
8
+ "mechanics": "Paths slide into a tray; match-3 clears tray slots. Combines path puzzle dependency with elimination payoff.",
9
+ "playerFantasy": "Tap an arrow path — it slides out. Fill the tray strategically; match-3 clears space before overflow.",
10
+ "decisionMoment": "Choosing which blocked path to unlock first vs filling the tray for a combo clear.",
11
+ "skillRef": "arrow_pick_match_rules.aigameplay",
12
+ "recommendedProfile": "standard",
13
+ "depthHint": "不要写「箭头+三消」就停;写清:棋盘哪一块先解锁、托盘峰值如何迫使颜色顺序、blocked 误点教什么。",
14
+ "antiPatternRef": "8×8 but ≤4 paths or all-free opening — no puzzle identity"
15
+ },
16
+ {
17
+ "id": "path_elimination_puzzle",
18
+ "intentTags": ["arrow", "path", "puzzle", "elimination", "箭头", "路径"],
19
+ "title": "Pure path elimination puzzle",
20
+ "mechanics": "Click arrow heads; paths slide out when unobstructed. Order matters — blocked paths teach dependency.",
21
+ "playerFantasy": "Read arrow directions, find the unlock sequence, clear the board.",
22
+ "decisionMoment": "First tap on a blocked path — shake/highlight feedback — then finding the correct unlock order.",
23
+ "skillRef": "path_elimination_rules.aigameplay",
24
+ "recommendedProfile": "standard",
25
+ "depthHint": "用折线密度与依赖层数定难度,固定 8×8;至少 2 层解锁波次,禁止开局全部 FREE。",
26
+ "antiPatternRef": "All paths FREE at start — zero decision"
27
+ },
28
+ {
29
+ "id": "match3_board",
30
+ "intentTags": ["match-3", "match3", "swap", "三消", "消除"],
31
+ "title": "Classic match-3 board",
32
+ "mechanics": "Swap adjacent tiles; match-3 removes; gravity refills.",
33
+ "playerFantasy": "Swap to create matches; cascades and combos build excitement.",
34
+ "decisionMoment": "Choosing between an obvious match vs setting up a cascade.",
35
+ "skillRef": "match3_core.aigameplay",
36
+ "recommendedProfile": "standard",
37
+ "depthHint": "若与 path 融合,说明主手势是 swap 还是 tap-path,避免异基底双主手势。",
38
+ "antiPatternRef": "Auto-clear board with no player swap"
39
+ },
40
+ {
41
+ "id": "board_phase_unlock",
42
+ "intentTags": ["phase", "unlock", "mask", "分区", "解锁", "board", "fusion"],
43
+ "title": "Board phase unlock (same-grid mask)",
44
+ "mechanics": "Same 8×8 board; masked regions unlock after match clears or path milestones. New paths appear in unlocked zones — board changes via mask, not resize.",
45
+ "playerFantasy": "Clear the first zone to reveal more puzzle — the board grows in complexity without shrinking cells.",
46
+ "decisionMoment": "Spend a tray clear to unlock the next zone vs hoarding colors for a safer combo.",
47
+ "skillRef": "arrow_pick_match_rules.aigameplay",
48
+ "recommendedProfile": "standard",
49
+ "depthHint": "写清每 phase 解锁条件与新增 path 条数;难度靠追加折线而非缩小棋盘。",
50
+ "antiPatternRef": "Resize board to 4×4 for difficulty — use path count instead"
51
+ },
52
+ {
53
+ "id": "match3_tray_puzzle_hybrid",
54
+ "intentTags": ["tray", "match-3", "puzzle", "hybrid", "托盘", "三消", "拼图"],
55
+ "title": "Tray-only match-3 + board path puzzle",
56
+ "mechanics": "Primary gesture: path tap on board. Match-3 happens only inside the tray. Board side is pure dependency puzzle — no swap on grid.",
57
+ "playerFantasy": "Solve the arrow maze; the tray is your pressure valve — match-3 is the relief, not the main puzzle.",
58
+ "decisionMoment": "Push a risky color into a nearly-full tray hoping the next two paths complete the triple.",
59
+ "skillRef": "arrow_pick_match_rules.aigameplay",
60
+ "recommendedProfile": "ring1_min",
61
+ "depthHint": "声明三消仅在托盘;棋盘侧禁止 swap。写托盘峰值曲线与颜色推出顺序。",
62
+ "antiPatternRef": "Board swap match-3 + path tap without interaction contract"
63
+ },
64
+ {
65
+ "id": "match3_board_phase",
66
+ "intentTags": ["match3", "phase", "path", "hybrid", "sequential", "双区"],
67
+ "title": "Match-3 main + path lock zone (high risk)",
68
+ "mechanics": "Primary zone: swap match-3. Secondary zone: path puzzle locked until match milestone. C-Sequential — document pseudo-fusion reducer.",
69
+ "playerFantasy": "Clear tiles to unlock the arrow zone — two systems, one win condition.",
70
+ "decisionMoment": "Finish the match-3 objective vs peeking at the locked path zone.",
71
+ "skillRef": "match3_core.aigameplay",
72
+ "recommendedProfile": "hard",
73
+ "depthHint": "Ring 2+ only.必须写 pseudo-fusion 与单 reducer,避免双主手势抢输入。",
74
+ "antiPatternRef": "Two equal primary gestures with no documented interaction contract"
75
+ }
76
+ ]
77
+ }
@@ -64,7 +64,9 @@
64
64
  "verify:text-overlap": "python3 skills/playable-verify-ui/scripts/verify_text_overlap.py --root=.",
65
65
  "verify:vision": "python3 skills/playable-verify-ui/scripts/verify_vision_evidence.py --root=.",
66
66
  "verify:asset-code-sync": "node skills/_shared/scripts/verify-asset-code-sync.mjs --root=.",
67
- "verify:atom-conformance": "node skills/_shared/scripts/verify-atom-conformance.mjs --project=."
67
+ "verify:atom-conformance": "node skills/_shared/scripts/verify-atom-conformance.mjs --project=.",
68
+ "verify:design": "node skills/_shared/scripts/verify-design-consistency.mjs --root=.",
69
+ "levels:validate": "node skills/_shared/scripts/validate-level-sketch.mjs --root=."
68
70
  },
69
71
  "engines": {
70
72
  "node": ">=20"
@@ -3,7 +3,7 @@
3
3
  * Start (or stop) the persistent preview dev server and record the real devUrl.
4
4
  *
5
5
  * This removes the LLM from port handling entirely (docs/harness/experiment-lessons.md §9.2):
6
- * Vite runs with strictPort:false, so when 3000 is taken it auto-increments; this
6
+ * Vite runs with strictPort:false, so when 5173 is taken it auto-increments; this
7
7
  * script parses Vite's actual `Local:` URL from the log, appends `?debug=1`, and
8
8
  * writes it back to project-state via the same layer `state:set` uses. The agent
9
9
  * never reads or records a port by hand.
@@ -20,11 +20,11 @@ import { openSync, closeSync, existsSync, readFileSync, writeFileSync, rmSync }
20
20
  import { spawn } from 'node:child_process';
21
21
  import { join, resolve } from 'node:path';
22
22
  import { applyHandoffUpdates, resolveProjectStatePath } from './state-handoff.mjs';
23
- import { parseLocalUrl, waitForHttp } from '../../playable-record/scripts/lib/dev-server.mjs';
23
+ import { parseLocalUrl, waitForHttp, DEFAULT_DEV_URL } from '../../playable-record/scripts/lib/dev-server.mjs';
24
24
 
25
25
  const PID_FILE = '.playcraft-dev.pid';
26
26
  const LOG_FILE = '.playcraft-dev.log';
27
- const PREFERRED_URL = 'http://127.0.0.1:3000/';
27
+ const PREFERRED_URL = DEFAULT_DEV_URL;
28
28
 
29
29
  function parseArgs(argv) {
30
30
  const opts = { root: process.cwd(), stop: false, timeout: 30000 };
@@ -7,6 +7,11 @@
7
7
  * for that surface.
8
8
  */
9
9
 
10
+ import { existsSync, readFileSync } from 'node:fs';
11
+ import { join } from 'node:path';
12
+ import { evaluateSliceQueueForRingGate } from './state-store.mjs';
13
+ import { resolvePrimarySkillId } from './lib/skill-fidelity.mjs';
14
+
10
15
  const COMMON_REQUIRED = ['CLAUDE.md'];
11
16
 
12
17
  export const FUTURE_RING_FILES = [
@@ -22,51 +27,43 @@ export const FUTURE_RING_FILES = [
22
27
  const DISCLOSURE_BY_RING_LOOP = {
23
28
  '1:clarify': {
24
29
  currentAction:
25
- 'Orchestrator: invoke @game-designer for Ring 1 clarify — design-brief discovery + DESIGN seed + playcraft skills match compact refs + minimal developer slice queue (not layout/style/CTA/full plan).',
26
- requiredFiles: [...COMMON_REQUIRED, 'docs/DESIGN.md'],
27
- deferredFiles: FUTURE_RING_FILES.filter((f) => f !== 'docs/design-brief.md'),
30
+ 'Orchestrator: invoke @game-designer with only the user\'s original intent. Do not add design decisions, engine hints, platform constraints, or workflow steps — designer reads its own role card.',
31
+ requiredFiles: [...COMMON_REQUIRED],
32
+ deferredFiles: FUTURE_RING_FILES,
28
33
  nextRole: 'game-designer',
29
- artifactRefs: ['docs/DESIGN.md', 'docs/design-brief.md', 'docs/atom-tree.json', 'sliceState'],
30
- requiredContextFields: ['ring.goal', 'lastRole.summary', 'sharedDecisions.coreAction', 'sharedDecisions.semanticPlaceholders'],
34
+ artifactRefs: [],
35
+ requiredContextFields: [],
31
36
  allowedTasks: [
32
- 'Invoke @game-designer for ring 1 clarify',
33
- 'Game Designer: design-brief discovery + DESIGN seed + playcraft skills match + sliceState queue',
34
- 'Game Designer: run playcraft skills match and write meta.skillsMatch + compact selectedAtoms',
35
- 'Record fromScratchReason when core mechanic is novel',
36
- 'Define first-level win strategy and semantic placeholders (Game Designer subagent)',
37
+ 'Invoke @game-designer with user intent only',
37
38
  ],
38
39
  forbiddenTasks: [
39
40
  'Do not write docs/DESIGN.md as orchestrator',
40
41
  'Do not implement game/ as orchestrator during clarify',
41
- 'Do not require layout-spec or full implementation-plan in Ring 1',
42
- 'Do not build a full atom graph in Ring 1 clarify — compact skillsMatch refs only',
43
- 'Do not design CTA polish or production assets in Ring 1',
44
- 'Do not claim skillRefs implement core mechanic without skills read',
45
- 'Do not run standalone record:mp4 as a Ring 1 blocker',
46
- 'Do not run verify:ui as Ring 1 blockers',
42
+ 'Do not add design decisions, engine hints, or workflow steps to the designer dispatch',
43
+ 'Do not describe what designer should produce — its role card defines outputs',
44
+ 'Do not list designer CLI commands — its role card defines the construction chain',
47
45
  ],
48
46
  nextCommands: [
49
- 'Invoke @game-designer — ring 1 clarify (skills match + design-brief + DESIGN seed + slice queue)',
47
+ 'Invoke @game-designer — pass only the user\'s original intent, nothing more',
50
48
  ],
51
49
  },
52
50
  '1:select': {
53
- currentAction: 'Orchestrator: after Game Designer STOP, spawn a temporary ref-flow atom-selection subagent for compact Ring 1 atom-tree selection.',
51
+ currentAction: 'Orchestrator: after Game Designer STOP, spawn a temporary ref-flow atom-selection subagent.',
54
52
  requiredFiles: [...COMMON_REQUIRED, 'docs/DESIGN.md'],
55
53
  deferredFiles: FUTURE_RING_FILES,
56
54
  nextRole: 'temporary-ref-flow',
57
55
  artifactRefs: ['docs/DESIGN.md', 'docs/atom-tree.json'],
58
- requiredContextFields: ['lastRole.summary', 'lastRole.decisions', 'sharedDecisions.coreAction', 'sharedDecisions.semanticPlaceholders'],
56
+ requiredContextFields: ['lastRole.summary', 'sharedDecisions.coreAction'],
59
57
  allowedTasks: [
60
- 'Spawn temporary ref-flow atom-selection subagent for ring 1 atom-tree selection',
61
- 'Pass DESIGN.md gameplay keywords and constraints to the temporary selector',
58
+ 'Spawn temporary ref-flow atom-selection subagent',
62
59
  ],
63
60
  forbiddenTasks: [
64
61
  'Do not select atoms inline as orchestrator',
65
62
  'Do not run init-template before atom-selection STOP',
66
- 'Do not implement gameplay logic as orchestrator',
63
+ 'Do not add engine or gameplay-trunk hints to the selector dispatch',
67
64
  ],
68
65
  nextCommands: [
69
- 'Spawn temporary ref-flow atom-selection subagent — ring 1 atom-tree selection (engine + compact gameplay trunk)',
66
+ 'Spawn temporary ref-flow atom-selection subagent — read docs/DESIGN.md and follow skill-selector-guide.md',
70
67
  ],
71
68
  },
72
69
  '1:scaffold': {
@@ -95,29 +92,21 @@ const DISCLOSURE_BY_RING_LOOP = {
95
92
  ],
96
93
  },
97
94
  '1:build': {
98
- currentAction: 'Orchestrator: invoke @developer for Ring 1 build. Developer: implement playable spine to first-level win.',
95
+ currentAction: 'Orchestrator: invoke @developer for Ring 1 build.',
99
96
  requiredFiles: [...COMMON_REQUIRED, 'docs/DESIGN.md', 'docs/atom-tree.json', 'docs/scaffold-manifest.md', 'game/'],
100
97
  deferredFiles: FUTURE_RING_FILES.filter((file) => file !== 'logs/review-report.md'),
101
98
  nextRole: 'developer',
102
99
  artifactRefs: ['docs/DESIGN.md', 'docs/atom-tree.json', 'logs/developer-log.md', 'game/'],
103
- requiredContextFields: ['lastRole.summary', 'lastRole.decisions', 'nextRole.mustKnow', 'sharedDecisions.engine', 'sharedDecisions.coreAction', 'sharedDecisions.semanticPlaceholders'],
100
+ requiredContextFields: ['lastRole.summary', 'sharedDecisions.engine', 'sharedDecisions.coreAction', 'sharedDecisions.semanticPlaceholders'],
104
101
  allowedTasks: [
105
102
  'Invoke @developer for ring 1 build',
106
- 'Apply engine scaffold if needed (orchestrator only, before developer)',
107
- 'Implement core gameplay loop (Developer subagent)',
108
- 'Wire window.__playable runtime contract (Developer subagent)',
109
- 'Make autoPlay follow player-reachable actions (Developer subagent)',
110
- 'Record devUrl when ready (Developer subagent)',
111
103
  ],
112
104
  forbiddenTasks: [
113
105
  'Do not implement game/ as orchestrator when @developer should own build',
114
- 'Do not polish HUD',
115
- 'Do not implement CTA fallback as a Ring 1 blocker',
116
- 'Do not run full MP4 as a Ring 1 blocker',
117
- 'Do not produce production assets',
106
+ 'Do not add implementation hints to the developer dispatch — developer reads its dispatchPacket + role card',
118
107
  ],
119
108
  nextCommands: [
120
- 'Invoke @developer — ring 1 build (placeholder art + core loop)',
109
+ 'Invoke @developer — pass the active slice from sliceState, nothing more',
121
110
  'npm run placeholder:gen',
122
111
  'npm run verify:contract',
123
112
  'npm run verify:lifecycle',
@@ -349,6 +338,21 @@ function normalizeIteration(iteration) {
349
338
  return Number.isFinite(n) && n >= 1 && n <= 4 ? n : 1;
350
339
  }
351
340
 
341
+ /** Compatibility export for STOP hook mechanism-phase detection. */
342
+ export function isMechanismLocked(projectRoot, handoffContext = {}) {
343
+ const skill = resolvePrimarySkillId(projectRoot, handoffContext);
344
+ if (!skill) return false;
345
+ const treePath = join(projectRoot, 'docs/atom-tree.json');
346
+ if (!existsSync(treePath)) return false;
347
+ try {
348
+ const tree = JSON.parse(readFileSync(treePath, 'utf8'));
349
+ const items = tree?.meta?.skillsMatch?.items ?? [];
350
+ return items.length > 0;
351
+ } catch {
352
+ return false;
353
+ }
354
+ }
355
+
352
356
  function resolveDisclosureKey({ iteration = 1, loop = 'clarify', handoff = {} } = {}) {
353
357
  const ring = normalizeIteration(iteration);
354
358
  const normalizedLoop = normalizeLoop(loop);
@@ -407,6 +411,11 @@ export function disclosureForSlice(dispatchPacket, { iteration = 1 } = {}) {
407
411
  const status = String(dispatchPacket.status || 'pending').trim();
408
412
  const allowedFiles = Array.isArray(dispatchPacket.allowedFiles) ? dispatchPacket.allowedFiles : [];
409
413
  const packetForbidden = Array.isArray(dispatchPacket.forbiddenTasks) ? dispatchPacket.forbiddenTasks : [];
414
+ const packetRequired = Array.isArray(dispatchPacket.requiredContext?.mustRead)
415
+ ? dispatchPacket.requiredContext.mustRead
416
+ : Array.isArray(dispatchPacket.requiredContext)
417
+ ? dispatchPacket.requiredContext
418
+ : [];
410
419
 
411
420
  const currentAction =
412
421
  `Orchestrator: invoke @${role} for slice "${sliceId}" — ${doWhat} (flow: ${flow}). ` +
@@ -429,7 +438,7 @@ export function disclosureForSlice(dispatchPacket, { iteration = 1 } = {}) {
429
438
  ring,
430
439
  loop: flow,
431
440
  currentAction,
432
- currentRingRequiredFiles: [...COMMON_REQUIRED, ...allowedFiles],
441
+ currentRingRequiredFiles: [...new Set([...COMMON_REQUIRED, ...packetRequired, ...allowedFiles])],
433
442
  deferredFiles: FUTURE_RING_FILES.filter((f) => !allowedFiles.includes(f)),
434
443
  allowedTasks: [
435
444
  `Invoke @${role} with dispatchPacket only (sliceId=${sliceId}, flow=${flow})`,
@@ -443,7 +452,7 @@ export function disclosureForSlice(dispatchPacket, { iteration = 1 } = {}) {
443
452
  ],
444
453
  nextCommands,
445
454
  nextRole: role,
446
- artifactRefs: allowedFiles.length ? allowedFiles : ['dispatchPacket'],
455
+ artifactRefs: [...new Set(['dispatchPacket', ...packetRequired, ...allowedFiles])],
447
456
  requiredContextFields: [
448
457
  'dispatchPacket.sliceId',
449
458
  'dispatchPacket.role',
@@ -455,11 +464,28 @@ export function disclosureForSlice(dispatchPacket, { iteration = 1 } = {}) {
455
464
  };
456
465
  }
457
466
 
458
- /** Unified entry: active dispatchPacket wins; otherwise legacy ring:loop disclosure. */
459
- export function disclosureForProjectState({ iteration = 1, loop = 'clarify', handoff = {}, dispatchPacket = null } = {}) {
467
+ /** Unified entry: active dispatchPacket wins; drained queue promotes to verify + ring:gate. */
468
+ export function disclosureForProjectState({
469
+ iteration = 1,
470
+ loop = 'clarify',
471
+ handoff = {},
472
+ dispatchPacket = null,
473
+ sliceState = null,
474
+ } = {}) {
460
475
  if (dispatchPacket) {
461
476
  return disclosureForSlice(dispatchPacket, { iteration });
462
477
  }
478
+ const ss = sliceState || {};
479
+ const gate = evaluateSliceQueueForRingGate(ss);
480
+ const ringGatePending = String(handoff.ringGate || 'pending').toLowerCase() !== 'passed';
481
+ if (
482
+ ss.activeSliceId === 'none'
483
+ && gate.applicable
484
+ && gate.ok
485
+ && ringGatePending
486
+ ) {
487
+ return disclosureForState({ iteration, loop: 'verify', handoff });
488
+ }
463
489
  return disclosureForState({ iteration, loop, handoff });
464
490
  }
465
491
 
@@ -25,6 +25,8 @@ import { createRequire } from 'node:module';
25
25
  import { dirname, join, resolve } from 'node:path';
26
26
  import { fileURLToPath, pathToFileURL } from 'node:url';
27
27
 
28
+ import { DEFAULT_DEV_URL } from '../../playable-record/scripts/lib/dev-server.mjs';
29
+
28
30
  const require = createRequire(import.meta.url);
29
31
  const __dirname = dirname(fileURLToPath(import.meta.url));
30
32
  const SKILLS_ROOT = resolve(__dirname, '../..');
@@ -171,7 +173,7 @@ async function checkContractLive(projectRoot) {
171
173
  const { runContractProbe } = await import(pathToFileURL(probePath).href);
172
174
  const res = await runContractProbe({
173
175
  root: projectRoot,
174
- url: isVite ? 'http://localhost:3000/' : null,
176
+ url: isVite ? DEFAULT_DEV_URL : null,
175
177
  useDev: isVite,
176
178
  port: 8080,
177
179
  scene: 'MainScene',