@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
@@ -19,6 +19,9 @@ import {
19
19
  } from '../../skills/_shared/scripts/ring-config.mjs';
20
20
  import { normalizeSliceState, readState, stateExists, isSliceResolved } from '../../skills/_shared/scripts/state-store.mjs';
21
21
  import { validateBuildArtifactForSlice } from '../../skills/playable-record/scripts/lib/build-artifact.mjs';
22
+ import { verifyDesignConsistency, validateAnimationSpine, validateStorySpine } from '../../skills/_shared/scripts/verify-design-consistency.mjs';
23
+ import { validateSkillFidelity } from '../../skills/_shared/scripts/lib/skill-fidelity.mjs';
24
+ import { isMechanismLocked } from '../../skills/_shared/scripts/disclosure-config.mjs';
22
25
 
23
26
  const __filename = fileURLToPath(import.meta.url);
24
27
  const require = createRequire(import.meta.url);
@@ -43,9 +46,26 @@ const PLAN_REQUIRED_SUBS = {
43
46
  const PLACEHOLDER_RE = /\{\{[^}]+\}\}/;
44
47
  const MIN_TAKEAWAY_LEN = 8;
45
48
 
49
+ function isCreativeDirectorSplitEnabledForStop() {
50
+ const raw = String(process.env.CREATIVE_DIRECTOR_SPLIT ?? '1').trim().toLowerCase();
51
+ return raw !== '0' && raw !== 'false' && raw !== 'off';
52
+ }
53
+
54
+ /** GD mechanism-lock STOP (before north-star exists). */
55
+ function isGameDesignerMechanismPhase(projectDir) {
56
+ if (!isCreativeDirectorSplitEnabledForStop()) return false;
57
+ if (fs.existsSync(path.join(projectDir, 'docs/north-star.md'))) return false;
58
+ const state = readState(projectDir);
59
+ const ctx = state.handoffContext || {};
60
+ const primarySkill = String(ctx.primaryGameplaySkill ?? '').trim();
61
+ if (!primarySkill || primarySkill === 'unset') return false;
62
+ if (fs.existsSync(path.join(projectDir, 'docs/level-sketch.json'))) return false;
63
+ return isMechanismLocked(projectDir, ctx);
64
+ }
65
+
46
66
  /** Required upstream docs scale with growth ring — ring 1 stays minimal (DESIGN only; design-brief is optional scratch). */
47
67
  const DEV_REQUIRED_DOCS_BY_RING = {
48
- 1: ['docs/project-state.md', 'docs/DESIGN.md'],
68
+ 1: ['docs/project-state.md', 'docs/DESIGN.md', 'docs/atom-tree.json'],
49
69
  2: [
50
70
  'docs/project-state.md',
51
71
  'docs/design-brief.md',
@@ -95,6 +115,7 @@ const ROLE_LOG = {
95
115
  artist: { log: 'logs/artist-log.md', label: 'Artist' },
96
116
  reviewer: { log: 'logs/review-report.md', label: 'Reviewer' },
97
117
  'game-designer': { log: null, label: 'Game Designer' },
118
+ 'creative-director': { log: null, label: 'Creative Director' },
98
119
  'skill-selector': { log: null, label: 'Temporary Atom Selector' },
99
120
  };
100
121
 
@@ -488,6 +509,7 @@ function detectRole(input) {
488
509
  if (n === 'developer-lead' || n === 'developer' || n === 'dev') return 'developer';
489
510
  if (n === 'artist') return 'artist';
490
511
  if (n === 'reviewer' || n === 'review') return 'reviewer';
512
+ if (n === 'creative-director' || n === 'creative director') return 'creative-director';
491
513
  if (n === 'game-designer' || n === 'game designer' || n === 'designer') return 'game-designer';
492
514
  if (n === 'skill-selector' || n === 'skill selector' || n === 'ref-flow') return 'skill-selector';
493
515
  }
@@ -803,6 +825,88 @@ function validateReviewerStop(projectDir) {
803
825
  return errors;
804
826
  }
805
827
 
828
+ /**
829
+ * @param {string} projectDir
830
+ */
831
+ function validateCreativeDirectorStop(projectDir) {
832
+ const errors = [];
833
+ const handoff = readHandoff(projectDir);
834
+ const state = readState(projectDir);
835
+
836
+ if (handoff.subagent_stop !== 'true') {
837
+ errors.push('Creative Director STOP requires subagent_stop: true');
838
+ }
839
+ if ((handoff.waiting_for || '').toLowerCase() !== 'orchestrator') {
840
+ errors.push('Creative Director STOP requires waiting_for: orchestrator');
841
+ }
842
+ if (!handoff.next_orchestrator_action || handoff.next_orchestrator_action === 'null') {
843
+ errors.push('Creative Director STOP requires next_orchestrator_action (Invoke @game-designer — ring 1 design spec)');
844
+ }
845
+
846
+ for (const doc of ['docs/north-star.md', 'docs/creative-process.md']) {
847
+ errors.push(...validateDocFile(projectDir, doc));
848
+ }
849
+
850
+ const northPath = path.join(projectDir, 'docs/north-star.md');
851
+ if (fs.existsSync(northPath)) {
852
+ const north = fs.readFileSync(northPath, 'utf8');
853
+ if (!/One-liner|一句话/i.test(north) || north.replace(/\s/g, '').length < 80) {
854
+ errors.push('docs/north-star.md: missing substantive One-liner / north star fields');
855
+ }
856
+ if (!/Rejected vibe|拒绝/i.test(north)) {
857
+ errors.push('docs/north-star.md: missing Rejected vibe section');
858
+ }
859
+ if (!/Micro-Story\s*Spine/i.test(north)) {
860
+ errors.push('docs/north-star.md: missing Micro-Story Spine section');
861
+ }
862
+ }
863
+
864
+ const cpPath = path.join(projectDir, 'docs/creative-process.md');
865
+ let creativeProcessText = '';
866
+ if (fs.existsSync(cpPath)) {
867
+ creativeProcessText = fs.readFileSync(cpPath, 'utf8');
868
+ const candidates = (creativeProcessText.match(/###\s*Candidate\s+[ABC]/gi) || []).length;
869
+ if (candidates < 3) {
870
+ errors.push('docs/creative-process.md: Phase 1 requires ≥3 candidates (A/B/C)');
871
+ }
872
+ }
873
+
874
+ if (fs.existsSync(northPath)) {
875
+ const north = fs.readFileSync(northPath, 'utf8');
876
+ const spineResult = validateStorySpine(north, '', creativeProcessText);
877
+ for (const p of spineResult.problems) {
878
+ errors.push(`docs/north-star.md: ${p}`);
879
+ }
880
+ if (spineResult.metrics.narrativeLevel === 'L3') {
881
+ errors.push('docs/north-star.md: Narrative level L3 forbidden — use L2 or below');
882
+ }
883
+ }
884
+
885
+ if (fs.existsSync(path.join(projectDir, 'docs/DESIGN.md'))) {
886
+ const designLen = fs.readFileSync(path.join(projectDir, 'docs/DESIGN.md'), 'utf8').length;
887
+ if (designLen > 200) {
888
+ errors.push('Creative Director must not write substantive docs/DESIGN.md — spec phase is @game-designer');
889
+ }
890
+ }
891
+
892
+ const primarySkill = String(state?.handoffContext?.primaryGameplaySkill ?? '').trim();
893
+ if (!primarySkill || primarySkill === 'unset') {
894
+ errors.push('Creative Director STOP requires handoffContext.primaryGameplaySkill (set during mechanism lock)');
895
+ }
896
+
897
+ if (fs.existsSync(northPath)) {
898
+ const north = fs.readFileSync(northPath, 'utf8');
899
+ const fidelity = validateSkillFidelity(projectDir, { northStarMd: north, payoffOnly: true });
900
+ if (!fidelity.skipped && !fidelity.pass) {
901
+ for (const reason of fidelity.driftReasons) {
902
+ errors.push(`CD PGS fidelity: ${reason}`);
903
+ }
904
+ }
905
+ }
906
+
907
+ return errors;
908
+ }
909
+
806
910
  /**
807
911
  * @param {string} projectDir
808
912
  */
@@ -826,8 +930,41 @@ function validateGameDesignerStop(projectDir) {
826
930
  return errors;
827
931
  }
828
932
 
829
- const ring = Math.min(Math.max(iteration, 1), 4);
830
933
  const state = readState(projectDir);
934
+ const ring = Math.min(Math.max(iteration, 1), 4);
935
+ const mechanismPhase = ring === 1 && isGameDesignerMechanismPhase(projectDir);
936
+
937
+ if (mechanismPhase) {
938
+ const ctx = state.handoffContext || {};
939
+ const primarySkill = String(ctx.primaryGameplaySkill ?? '').trim();
940
+ if (!primarySkill || primarySkill === 'unset') {
941
+ errors.push('Mechanism lock STOP requires handoffContext.primaryGameplaySkill');
942
+ }
943
+ if (!isMechanismLocked(projectDir, ctx)) {
944
+ errors.push('Mechanism lock STOP requires docs/atom-tree.json meta.skillsMatch.items non-empty');
945
+ }
946
+ const atomTreePath = path.join(projectDir, 'docs/atom-tree.json');
947
+ if (!fs.existsSync(atomTreePath)) {
948
+ errors.push('Mechanism lock STOP requires docs/atom-tree.json');
949
+ } else {
950
+ errors.push(...validateHandoffContext(projectDir, 'game-designer'));
951
+ const refs = ctx.lastRole?.artifactRefs || [];
952
+ if (!refs.some((r) => String(r).includes('atom-tree.json'))) {
953
+ errors.push('handoffContext.lastRole.artifactRefs must include docs/atom-tree.json');
954
+ }
955
+ }
956
+ if (fs.existsSync(path.join(projectDir, 'docs/north-star.md'))) {
957
+ errors.push('Mechanism phase must not write docs/north-star.md — creative-director owns north-star');
958
+ }
959
+ if (fs.existsSync(path.join(projectDir, 'docs/DESIGN.md'))) {
960
+ const designLen = fs.readFileSync(path.join(projectDir, 'docs/DESIGN.md'), 'utf8').length;
961
+ if (designLen > 200) {
962
+ errors.push('Mechanism phase must not write substantive docs/DESIGN.md');
963
+ }
964
+ }
965
+ return errors;
966
+ }
967
+
831
968
  const ss = normalizeSliceState(state.sliceState || {});
832
969
  const sliceAxisClarify = ss.slices.length > 0 && (ring === 1 || ring === 2);
833
970
 
@@ -841,7 +978,25 @@ function validateGameDesignerStop(projectDir) {
841
978
  if (ring === 1) {
842
979
  const designPath = path.join(projectDir, 'docs/DESIGN.md');
843
980
  if (fs.existsSync(designPath)) {
844
- errors.push(...validatePlayableSeedDesign(fs.readFileSync(designPath, 'utf8')));
981
+ const designContent = fs.readFileSync(designPath, 'utf8');
982
+ errors.push(...validatePlayableSeedDesign(designContent));
983
+ errors.push(...validateDesignFusionSection(designContent));
984
+ }
985
+ const sketchPath = path.join(projectDir, 'docs/level-sketch.json');
986
+ if (!fs.existsSync(sketchPath) && sliceAxisClarify) {
987
+ errors.push('Ring 1 clarify requires docs/level-sketch.json (executable level sketch)');
988
+ }
989
+ if (ring === 1 && sliceAxisClarify && fs.existsSync(sketchPath)) {
990
+ if (fs.existsSync(designPath)) {
991
+ const designContent = fs.readFileSync(designPath, 'utf8');
992
+ errors.push(...validateAnimationSpine(designContent));
993
+ }
994
+ const designCheck = verifyDesignConsistency(projectDir);
995
+ if (!designCheck.ok) {
996
+ for (const p of designCheck.problems) {
997
+ errors.push(`verify:design: ${p}`);
998
+ }
999
+ }
845
1000
  }
846
1001
  }
847
1002
 
@@ -1318,6 +1473,9 @@ function validateRole(projectDir, role) {
1318
1473
  if (role === 'reviewer') {
1319
1474
  return validateReviewerStop(projectDir);
1320
1475
  }
1476
+ if (role === 'creative-director') {
1477
+ return validateCreativeDirectorStop(projectDir);
1478
+ }
1321
1479
  if (role === 'game-designer') {
1322
1480
  return validateGameDesignerStop(projectDir);
1323
1481
  }
@@ -1393,20 +1551,28 @@ function validateRole(projectDir, role) {
1393
1551
  }
1394
1552
 
1395
1553
  /** Selected atoms that must be linked into .claude/skills/ (excludes bundled playcraft-* skills). */
1396
- function readSelectedAtomsForLink(projectDir) {
1554
+ function readAtomTreeForPreflight(projectDir) {
1397
1555
  const jsonPath = path.join(projectDir, 'docs/atom-tree.json');
1398
- if (!fs.existsSync(jsonPath)) return [];
1556
+ if (!fs.existsSync(jsonPath)) return { exists: false, parseError: false, atoms: [] };
1399
1557
  try {
1400
1558
  const tree = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
1401
1559
  const atoms = Array.isArray(tree?.meta?.selectedAtoms) ? tree.meta.selectedAtoms : [];
1402
- return atoms
1403
- .map((a) => (typeof a === 'string' ? a.trim() : ''))
1404
- .filter((a) => a && !a.startsWith('{{') && !a.startsWith('playcraft-'));
1560
+ return {
1561
+ exists: true,
1562
+ parseError: false,
1563
+ atoms: atoms
1564
+ .map((a) => (typeof a === 'string' ? a.trim() : ''))
1565
+ .filter((a) => a && !a.startsWith('{{') && !a.startsWith('playcraft-')),
1566
+ };
1405
1567
  } catch {
1406
- return [];
1568
+ return { exists: true, parseError: true, atoms: [] };
1407
1569
  }
1408
1570
  }
1409
1571
 
1572
+ function readSelectedAtomsForLink(projectDir) {
1573
+ return readAtomTreeForPreflight(projectDir).atoms;
1574
+ }
1575
+
1410
1576
  /** Extract a markdown section body from `heading` up to the next same-or-higher-level heading. */
1411
1577
  function extractMarkdownSection(content, heading) {
1412
1578
  const start = content.indexOf(heading);
@@ -1437,6 +1603,21 @@ function countFilledTableRows(section) {
1437
1603
  return count;
1438
1604
  }
1439
1605
 
1606
+ function missingSelectedAtomPreflightRows(content, atoms) {
1607
+ const missing = [];
1608
+ if (!content.includes('docs/atom-tree.json')) missing.push('docs/atom-tree.json');
1609
+ const preflight = extractMarkdownSection(content, '## Skill Preflight');
1610
+ if (!preflight) {
1611
+ missing.push('logs/developer-log.md § Skill Preflight');
1612
+ return missing;
1613
+ }
1614
+ for (const atom of atoms) {
1615
+ const skillPath = `.claude/skills/${atom}/SKILL.md`;
1616
+ if (!preflight.includes(atom) || !preflight.includes(skillPath)) missing.push(skillPath);
1617
+ }
1618
+ return missing;
1619
+ }
1620
+
1440
1621
  /**
1441
1622
  * Shared skill-link + Skill Preflight + placeholder materialization evidence gate.
1442
1623
  * Applied at every ring's Developer build STOP so "use placeholders / implement per skill"
@@ -1447,7 +1628,15 @@ function countFilledTableRows(section) {
1447
1628
  */
1448
1629
  function validateSkillAndPlaceholderEvidence(projectDir, content) {
1449
1630
  const errors = [];
1450
- const atoms = readSelectedAtomsForLink(projectDir);
1631
+ const atomTree = readAtomTreeForPreflight(projectDir);
1632
+ const atoms = atomTree.atoms;
1633
+
1634
+ if (!atomTree.exists) {
1635
+ errors.push('Skill Preflight: missing docs/atom-tree.json — dispatchPacket.requiredContext cannot disclose selected atom Skills');
1636
+ }
1637
+ if (atomTree.parseError) {
1638
+ errors.push('Skill Preflight: docs/atom-tree.json must be valid JSON before Developer STOP');
1639
+ }
1451
1640
 
1452
1641
  // 1. Skill link evidence: selected atoms materialized under .claude/skills/
1453
1642
  const skillsDir = path.join(projectDir, '.claude/skills');
@@ -1458,13 +1647,19 @@ function validateSkillAndPlaceholderEvidence(projectDir, content) {
1458
1647
  );
1459
1648
  }
1460
1649
 
1461
- // 2. Skill Preflight filled (one non-template row per atom)
1650
+ // 2. Skill Preflight filled (one exact-path row per atom)
1462
1651
  const preflight = extractMarkdownSection(content, '## Skill Preflight');
1463
1652
  if (!preflight || countFilledTableRows(preflight) < Math.max(1, atoms.length)) {
1464
1653
  errors.push(
1465
1654
  'Skill Preflight: developer-log.md § Skill Preflight is not filled — add one non-template row per selected atom (read .claude/skills/<atom>/SKILL.md: what it provides + how you use it)',
1466
1655
  );
1467
1656
  }
1657
+ const missingRows = missingSelectedAtomPreflightRows(content, atoms);
1658
+ if (missingRows.length > 0) {
1659
+ errors.push(
1660
+ `Skill Preflight: missing required reading evidence for ${missingRows.join(', ')} — read docs/atom-tree.json and add one exact .claude/skills/<atom>/SKILL.md row for every meta.selectedAtoms item`,
1661
+ );
1662
+ }
1468
1663
 
1469
1664
  // 3. Placeholder materialization evidence (placeholder-first, not code-draw-only)
1470
1665
  const placeholder = extractMarkdownSection(content, '### Placeholder materialization');
@@ -1779,6 +1974,8 @@ export {
1779
1974
  validateGameDesignerSeedContext,
1780
1975
  validateGameDesignerSliceQueueSeed,
1781
1976
  validateSkillsMatchSliceRefs,
1977
+ validateSkillAndPlaceholderEvidence,
1978
+ missingSelectedAtomPreflightRows,
1782
1979
  validateDesignFusionSection,
1783
1980
  validateReviewerHandoff,
1784
1981
  validateReviewReportDoD,
@@ -1797,7 +1994,6 @@ export {
1797
1994
  PLAN_HEADING,
1798
1995
  PLAN_REQUIRED_SUBS,
1799
1996
  ROLE_LOG,
1800
- validateSkillAndPlaceholderEvidence,
1801
1997
  validateDevUrlDebugFlag,
1802
1998
  readSelectedAtomsForLink,
1803
1999
  extractMarkdownSection,
@@ -1809,6 +2005,7 @@ async function main() {
1809
2005
  const input = parseHookInput(stdin);
1810
2006
 
1811
2007
  const projectDir =
2008
+ process.env.CODEBUDDY_PROJECT_DIR ||
1812
2009
  process.env.CLAUDE_PROJECT_DIR ||
1813
2010
  process.env.CURSOR_PROJECT_DIR ||
1814
2011
  process.cwd();
@@ -1,5 +1,5 @@
1
1
  {
2
- "defaultMode": "acceptEdits",
2
+ "defaultMode": "bypassPermissions",
3
3
  "env": {
4
4
  "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
5
5
  },
@@ -54,7 +54,7 @@
54
54
  ],
55
55
  "SubagentStop": [
56
56
  {
57
- "matcher": "artist|technical-artist|developer|reviewer|game-designer|skill-selector",
57
+ "matcher": "artist|technical-artist|developer|reviewer|game-designer|creative-director|skill-selector",
58
58
  "hooks": [
59
59
  {
60
60
  "type": "command",
@@ -51,35 +51,35 @@ PlayCraft 是 **Vite** 项目,`ensure-project` 会检测到 `vite.config.ts` +
51
51
 
52
52
  ## 与 PlayCraft growth-rings 的接点
53
53
 
54
- | iteration / loop | 谁调用 | 调用什么 | 产出 |
55
- | ------------------------------ | ----------------------- | ------------------------------------------ | ------------------------------ |
56
- | ring 1 `loop: build`(收尾) | Developer | `state:get` 披露的 contract/lifecycle/firstwin | 轻量 HOOK 生命周期 + 首关可胜 |
57
- | ring 2+ `loop: build`(收尾) | Developer | 仅运行 `state:get.nextCommands` 中的 `verify:ui` / `record:mp4` | 当前 Ring 证据 |
58
- | ring 4 `loop: verify` | Reviewer | `verify:ui` → `playwright-cli` 截图 | asset/layout 先行拦截 |
59
- | ring 4 verify ui_diff fail | Developer / TA / Artist | 读 `playable-validate` 子 skill 做最小 fix | 修复后重跑 verify + record |
60
- | ring 4 optional optimization | Reviewer / Orchestrator | `playable-validate` loop | `validate/PLAYABLE-*.md` + MP4 |
54
+ | iteration / loop | 谁调用 | 调用什么 | 产出 |
55
+ | ----------------------------- | ----------------------- | --------------------------------------------------------------- | ------------------------------ |
56
+ | ring 1 `loop: build`(收尾) | Developer | `state:get` 披露的 contract/lifecycle/firstwin | 轻量 HOOK 生命周期 + 首关可胜 |
57
+ | ring 2+ `loop: build`(收尾) | Developer | 仅运行 `state:get.nextCommands` 中的 `verify:ui` / `record:mp4` | 当前 Ring 证据 |
58
+ | ring 4 `loop: verify` | Reviewer | `verify:ui` → `playwright-cli` 截图 | asset/layout 先行拦截 |
59
+ | ring 4 verify ui_diff fail | Developer / TA / Artist | 读 `playable-validate` 子 skill 做最小 fix | 修复后重跑 verify + record |
60
+ | ring 4 optional optimization | Reviewer / Orchestrator | `playable-validate` loop | `validate/PLAYABLE-*.md` + MP4 |
61
61
 
62
62
  ---
63
63
 
64
64
  ## 一句话指令表
65
65
 
66
- | 用户/Agent 意图 | 命令/入口 |
67
- | ------------------------ | ---------------------------------------------------------------------- |
68
- | 查看当前可运行命令 | `npm run state:get -- --json` |
69
- | 整片优化到可交付 | 读 `skills/playable-validate/SKILL.md` § Agent 入口 |
70
- | 检查 UI / atlas / layout | 仅当 `state:get.nextCommands` 披露:`npm run verify:ui` |
66
+ | 用户/Agent 意图 | 命令/入口 |
67
+ | ------------------------ | ----------------------------------------------------------------------------- |
68
+ | 查看当前可运行命令 | `npm run state:get -- --json` |
69
+ | 整片优化到可交付 | 读 `skills/playable-validate/SKILL.md` § Agent 入口 |
70
+ | 检查 UI / atlas / layout | 仅当 `state:get.nextCommands` 披露:`npm run verify:ui` |
71
71
  | 录完整局 headed MP4 | 仅当 `state:get.nextCommands` 披露:`npm run record:mp4 -- --headed --fps=60` |
72
- | 只录某个 focus zone | `npm run record:focus -- --scope=PHASE --fixture=endcard-win --headed` |
73
- | 优化 match 碎裂 FX | 读 `skills/playable-fx-decompose/SKILL.md` |
74
- | 优化帧光效 / burst | 读 `skills/playable-fx-peak/SKILL.md` |
75
- | 优化动效手感 | 读 `skills/playable-animate/SKILL.md` |
76
- | 局部 L→G 穷举 | `npm run sweep:L1` / `npm run sweep:G1` |
72
+ | 只录某个 focus zone | `npm run record:focus -- --scope=PHASE --fixture=endcard-win --headed` |
73
+ | 优化 match 碎裂 FX | 读 `skills/playable-fx-decompose/SKILL.md` |
74
+ | 优化帧光效 / burst | 读 `skills/playable-fx-peak/SKILL.md` |
75
+ | 优化动效手感 | 读 `skills/playable-animate/SKILL.md` |
76
+ | 局部 L→G 穷举 | `npm run sweep:L1` / `npm run sweep:G1` |
77
77
 
78
78
  ---
79
79
 
80
80
  ## Vite 项目注意事项
81
81
 
82
- PlayCraft 项目用 Vite,`record:mp4` 默认脚本已经带了 `--use-dev --url=http://localhost:3000/`。只在当前 Ring 已披露 `record:mp4` 时运行:
82
+ PlayCraft 项目用 Vite,`record:mp4` 默认脚本已经带了 `--use-dev --url=http://localhost:5173/`。只在当前 Ring 已披露 `record:mp4` 时运行:
83
83
 
84
84
  ```bash
85
85
  npm run record:mp4 -- --headed --fps=60
@@ -88,10 +88,10 @@ npm run record:mp4 -- --headed --fps=60
88
88
  这会:
89
89
 
90
90
  1. 在当前目录启动 `npm run dev`。
91
- 2. 等待 `http://localhost:3000/` 可访问。
91
+ 2. 等待 `http://localhost:5173/` 可访问。
92
92
  3. 用 Playwright 打开该 URL 并录制。
93
93
 
94
- 如果 Vite 端口不是 3000,改 `package.json` 里的 `record:mp4` 脚本,或手动:
94
+ 如果 Vite 端口不是 5173,改 `package.json` 里的 `record:mp4` 脚本,或手动:
95
95
 
96
96
  ```bash
97
97
  # 终端 1
@@ -27,7 +27,6 @@ if (!keyword) {
27
27
  const home = homedir();
28
28
  const stores = [
29
29
  { name: 'Claude Code', path: join(home, '.claude', 'projects') },
30
- { name: 'Claude Internal', path: join(home, '.claude-internal', 'projects') },
31
30
  { name: 'CodeBuddy', path: join(home, '.codebuddy', 'projects') },
32
31
  ];
33
32
 
@@ -86,7 +86,6 @@ function findSessions(projectCwd) {
86
86
  const home = homedir();
87
87
  const stores = [
88
88
  { name: 'claude-code', path: join(home, '.claude', 'projects') },
89
- { name: 'claude-internal', path: join(home, '.claude-internal', 'projects') },
90
89
  { name: 'codebuddy', path: join(home, '.codebuddy', 'projects') },
91
90
  ];
92
91
 
@@ -1,5 +1,5 @@
1
1
  {
2
- "defaultMode": "acceptEdits",
2
+ "defaultMode": "bypassPermissions",
3
3
  "env": {
4
4
  "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
5
5
  },
@@ -123,7 +123,7 @@ When executing `next_orchestrator_action`, **also** update `iteration` / `loop`
123
123
 
124
124
  | iteration | loop | Typical `next_orchestrator_action` |
125
125
  | --------- | ---- | ---------------------------------- |
126
- | 1 | clarify | Invoke `@game-designer` — engine root + core loop spec |
126
+ | 1 | clarify | `@game-designer` mechanism lock → read `creative-director-kickoff-guide.md` → `@creative-director` (PGS wrap) → `@game-designer` spec; `CREATIVE_DIRECTOR_SPLIT=0` for monolithic control |
127
127
  | 1 | build | Invoke `@developer` — engine boot + placeholder core gameplay |
128
128
  | 1 | verify | Developer self-gate → `npm run ring:gate -- --iteration 1` → Ring Gate (no `@reviewer`) |
129
129
  | 2 | clarify | `@game-designer` — periphery atoms (HUD / flow) |
@@ -50,15 +50,15 @@ When **`dispatchPacket` is null** (`dispatchMode: false`): use the legacy growth
50
50
 
51
51
  When `state:get` reports `iteration: 1`, **stay orchestrator** — invoke role subagents; do not inline their work.
52
52
 
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). |
60
-
61
- Follow `next_orchestrator_action` from handoff when `subagent_stop: true`. See `docs/team/collaboration.md` § Ring 1 engine scaffold.
53
+ | `loop` | Orchestrator does |
54
+ | --------------------- | ---------------------------------------------------------------------------------------------------- |
55
+ | `clarify` | **Invoke `@game-designer`**. Do not write design docs or select atoms inline. |
56
+ | (after GD STOP) | **Spawn a temporary ref-flow atom-selection subagent**. Do not select atoms inline. |
57
+ | (after selector STOP) | Run scaffold gate (follow `state:get` → `nextCommands`). Set `loop: build`. **Invoke `@developer`**. |
58
+ | `build` | **Invoke `@developer`**. |
59
+ | `verify` | Run `npm run ring:gate -- --iteration 1`. |
60
+
61
+ Follow `next_orchestrator_action` from handoff when `subagent_stop: true`. Sub-agents receive only the user's original intent — they read their own role cards for workflow, constraints, and output requirements. See `docs/team/collaboration.md` § Ring 1 engine scaffold.
62
62
 
63
63
  ## Deeper References
64
64
 
@@ -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
 
@@ -26,24 +26,24 @@ On every invoke, in order:
26
26
 
27
27
  ## Orchestrator only
28
28
 
29
- | | Rule |
30
- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
31
- | **MUST** | Be the **only** role that uses `AskUserQuestion` for **Ring Gate** confirmations (one per growth ring) |
32
- | **MUST** | After any sub-agent STOP, run `npm run state:get` to read `contextPacket` and routing handoff before spawn / resume / Ring Gate |
33
- | **MUST** | After any sub-agent STOP, verify: `handoffContext` complete, ring DoD evidence complete, logs filled, required preflight done |
34
- | **MUST** | If `waiting_for: user_gate` and `subagent_stop: true` and `ringGateCanAskUser: yes`, run **only** Ring Gate (`AskUserQuestion`) — **do not** invoke sub-agents |
35
- | **MUST** | If `subagent_stop: true` and `waiting_for: orchestrator`, execute **only** `next_orchestrator_action` |
36
- | **MUST** | Before invoke: reset handoff (`subagent_stop: false`, `waiting_for: none`, set `subagent` to target role) |
37
- | **MUST** | Dispatch = WHAT + skill refs + constraints only; do NOT write detailed production steps for sub-agents |
38
- | **MUST** | Before Ring Gate: run `npm run ring:gate -- --iteration N` — do **not** ask user until the script returns pass |
39
- | **MUST** | Before **ring 1 `loop: build`**: ensure `playcraft remix init-template --from-atom-tree` has run, `.playcraft-engine` matches `meta.engineDecision.adapter`, and `npm run verify:contract` passes |
40
- | **MUST** | After ring 1 Game Designer STOP, spawn a temporary ref-flow atom-selection subagent before scaffold; do not select atoms inline as orchestrator |
41
- | **MUST** | Archive Ring Gate snapshots through `ring:gate` / state helpers so the next ring inherits stable decisions, not prior-ring process noise |
42
- | **MUST NOT** | Role-play all five agents in one session when sub-agent invoke is available |
43
- | **MUST NOT** | Advance `iteration` without archiving prior ring in `archivedRings` (non-regression) |
44
- | **MUST NOT** | Invoke `@technical-artist` before ring 4 Artist Wave 1 is `done` |
45
- | **MUST NOT** | Advance `iteration` when a sub-agent could do it — **orchestrator owns** `iteration` / `loop` transitions |
46
- | **MUST NOT** | Advance to next iteration if post-STOP verification fails (required package, logs/evidence, Skill Preflight) |
29
+ | | Rule |
30
+ | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
31
+ | **MUST** | Be the **only** role that uses `AskUserQuestion` for **Ring Gate** confirmations (one per growth ring) |
32
+ | **MUST** | After any sub-agent STOP, run `npm run state:get` to read `contextPacket` and routing handoff before spawn / resume / Ring Gate |
33
+ | **MUST** | After any sub-agent STOP, verify: `handoffContext` complete, ring DoD evidence complete, logs filled, required preflight done |
34
+ | **MUST** | If `waiting_for: user_gate` and `subagent_stop: true` and `ringGateCanAskUser: yes`, run **only** Ring Gate (`AskUserQuestion`) — **do not** invoke sub-agents |
35
+ | **MUST** | If `subagent_stop: true` and `waiting_for: orchestrator`, execute **only** `next_orchestrator_action` |
36
+ | **MUST** | Before invoke: reset handoff (`subagent_stop: false`, `waiting_for: none`, set `subagent` to target role) |
37
+ | **MUST** | Dispatch sub-agents with **only** the user's original intent. Never add: design decisions, engine suggestions, workflow steps, CLI commands, role card summaries, platform constraints, or "you should..." guidance. Sub-agents read their own role cards — orchestrator does not repeat them. |
38
+ | **MUST** | Before Ring Gate: run `npm run ring:gate -- --iteration N` — do **not** ask user until the script returns pass |
39
+ | **MUST** | Before **ring 1 `loop: build`**: ensure `playcraft remix init-template --from-atom-tree` has run, `.playcraft-engine` matches `meta.engineDecision.adapter`, and `npm run verify:contract` passes |
40
+ | **MUST** | After ring 1 Game Designer STOP, spawn a temporary ref-flow atom-selection subagent before scaffold; do not select atoms inline as orchestrator |
41
+ | **MUST** | Archive Ring Gate snapshots through `ring:gate` / state helpers so the next ring inherits stable decisions, not prior-ring process noise |
42
+ | **MUST NOT** | Role-play all five agents in one session when sub-agent invoke is available |
43
+ | **MUST NOT** | Advance `iteration` without archiving prior ring in `archivedRings` (non-regression) |
44
+ | **MUST NOT** | Invoke `@technical-artist` before ring 4 Artist Wave 1 is `done` |
45
+ | **MUST NOT** | Advance `iteration` when a sub-agent could do it — **orchestrator owns** `iteration` / `loop` transitions |
46
+ | **MUST NOT** | Advance to next iteration if post-STOP verification fails (required package, logs/evidence, Skill Preflight) |
47
47
 
48
48
  ## Sub-agents only (Game Designer, Artist, TA, Developer, Reviewer)
49
49
 
@@ -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,21 @@ 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
+ - **Mechanism-first (2026-07)**: adds `1:mechanism` (GD skills read lock) before creative; `verify:design` `mechanismFidelity` vs primary skill PGS — no `mechanism-spine.md`.
22
+ - **`verify:design`**: mechanism-chain heuristic + north-star ↔ DESIGN §0 verbatim sync when split enabled.
23
+
9
24
  ### 2026-06-23 — Ring 1 responsibility split
10
25
 
11
26
  - **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`.