@boyingliu01/xp-gate 0.18.5 → 0.19.0

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 (254) hide show
  1. package/adapter-common.sh +27 -0
  2. package/adapters/gate-3.sh +0 -0
  3. package/adapters/gate-4.sh +0 -0
  4. package/adapters/gate-7.sh +0 -0
  5. package/adapters/gate-8.sh +0 -0
  6. package/adapters/gate-9.sh +0 -0
  7. package/adapters/powershell.sh +85 -33
  8. package/adapters/typescript.sh +8 -8
  9. package/build-integrity/__tests__/import-resolver.test.ts +22 -0
  10. package/build-integrity/__tests__/orchestrator.test.ts +1 -2
  11. package/build-integrity/gate-10.ts +7 -0
  12. package/gate-12-file-hygiene.sh +230 -0
  13. package/hooks/adapter-common.sh +27 -0
  14. package/hooks/gate-10.sh +105 -0
  15. package/hooks/gate-12-file-hygiene.sh +0 -0
  16. package/hooks/lib/validate-code-walkthrough.cjs +125 -0
  17. package/hooks/pre-commit +130 -33
  18. package/hooks/pre-push +15 -91
  19. package/lib/__tests__/check-version.test.js +67 -46
  20. package/lib/__tests__/doctor.test.js +7 -6
  21. package/lib/__tests__/gate-runner.test.js +267 -0
  22. package/lib/__tests__/init.test.js +32 -0
  23. package/lib/__tests__/npm-package.test.js +13 -0
  24. package/lib/__tests__/phase-transition.test.js +604 -12
  25. package/lib/__tests__/sprint-discovery.test.ts +0 -1
  26. package/lib/__tests__/sprint-status-rework.test.js +100 -1
  27. package/lib/__tests__/update-hooks.test.js +143 -10
  28. package/lib/__tests__/upgrade-exec.test.js +73 -45
  29. package/lib/__tests__/upgrade-skill-sync.test.js +1 -1
  30. package/lib/__tests__/upgrade.test.js +12 -11
  31. package/lib/doctor.js +2 -1
  32. package/lib/gate-runner.js +68 -23
  33. package/lib/init.js +34 -5
  34. package/lib/install-skill.js +1 -0
  35. package/lib/mattpocock-license-verdict.json +1 -1
  36. package/lib/phase-transition.js +203 -23
  37. package/lib/shared-paths.js +2 -0
  38. package/lib/sprint-status.js +15 -4
  39. package/lib/test-alignment.ts +3 -13
  40. package/lib/update-hooks.js +129 -15
  41. package/mock-policy/AGENTS.md +5 -5
  42. package/mock-policy/__tests__/gate-m3.test.ts +0 -5
  43. package/mock-policy/__tests__/scope-scanner.test.ts +8 -2
  44. package/mutation/AGENTS.md +4 -4
  45. package/mutation/__tests__/mutmut-runner.test.ts +443 -2
  46. package/mutation/__tests__/update-baseline.test.ts +0 -2
  47. package/mutation/runners/mutmut-runner.ts +67 -17
  48. package/package.json +9 -3
  49. package/plugins/claude-code/.claude-plugin/plugin.json +1 -1
  50. package/plugins/claude-code/skills/clipboard-vision/SKILL.md +47 -0
  51. package/plugins/claude-code/skills/clipboard-vision/__tests__/clipboard-vision-distribution.test.cjs +65 -0
  52. package/plugins/claude-code/skills/clipboard-vision/__tests__/clipboard-vision-security.test.cjs +185 -0
  53. package/plugins/claude-code/skills/clipboard-vision/__tests__/clipboard-vision.Tests.ps1 +138 -0
  54. package/plugins/claude-code/skills/clipboard-vision/__tests__/clipboard-vision.test.cjs +273 -0
  55. package/plugins/claude-code/skills/clipboard-vision/describe-clipboard.ps1 +115 -0
  56. package/plugins/claude-code/skills/clipboard-vision/describe-clipboard.sh +161 -0
  57. package/plugins/claude-code/skills/clipboard-vision/scripts/clipboard-vision.ps1 +86 -0
  58. package/plugins/claude-code/skills/clipboard-vision/scripts/clipboard-vision.sh +137 -0
  59. package/plugins/claude-code/skills/delphi-review/.delphi-config.json.example +24 -27
  60. package/plugins/claude-code/skills/delphi-review/AGENTS.md +13 -12
  61. package/plugins/claude-code/skills/delphi-review/INSTALL.md +15 -17
  62. package/plugins/claude-code/skills/delphi-review/SKILL.md +30 -29
  63. package/plugins/claude-code/skills/delphi-review/opencode.json.delphi.example +6 -10
  64. package/plugins/claude-code/skills/delphi-review/references/code-walkthrough.md +33 -49
  65. package/plugins/claude-code/skills/delphi-review/references/requirements.md +66 -54
  66. package/plugins/claude-code/skills/delphi-review/references/round-templates.md +7 -7
  67. package/plugins/claude-code/skills/sprint-flow/AGENTS.md +5 -5
  68. package/plugins/claude-code/skills/sprint-flow/SKILL.md +4 -4
  69. package/plugins/claude-code/skills/sprint-flow/references/components/skill-invocations.md +2 -2
  70. package/plugins/claude-code/skills/sprint-flow/references/force-levels.md +37 -35
  71. package/plugins/claude-code/skills/sprint-flow/references/orchestration-rules.md +1 -1
  72. package/plugins/claude-code/skills/sprint-flow/references/phase-1-prep.md +1 -1
  73. package/plugins/claude-code/skills/sprint-flow/references/phase-2-design.md +24 -14
  74. package/plugins/claude-code/skills/sprint-flow/references/phase-4-verify.md +6 -6
  75. package/plugins/claude-code/skills/sprint-flow/references/phase-overview.md +2 -2
  76. package/plugins/claude-code/skills/test-specification-alignment/AGENTS.md +4 -4
  77. package/plugins/dsh/README.md +25 -0
  78. package/plugins/dsh/cordis.patch.yml +7 -0
  79. package/plugins/dsh/package.json +70 -0
  80. package/plugins/dsh/scripts/prepack.cjs +82 -0
  81. package/plugins/dsh/skills/admin-template-guidelines/SKILL.md +113 -0
  82. package/plugins/dsh/skills/admin-template-guidelines/references/rule-1.md +91 -0
  83. package/plugins/dsh/skills/admin-template-guidelines/references/rule-2.md +155 -0
  84. package/plugins/dsh/skills/admin-template-guidelines/references/rule-3.md +70 -0
  85. package/plugins/dsh/skills/admin-template-guidelines/references/rule-4.md +154 -0
  86. package/plugins/dsh/skills/admin-template-guidelines/references/rule-5.md +126 -0
  87. package/plugins/dsh/skills/admin-template-guidelines/references/rule-6.md +180 -0
  88. package/plugins/dsh/skills/batch-grill-me/SKILL.md +15 -0
  89. package/plugins/dsh/skills/clipboard-vision/SKILL.md +47 -0
  90. package/plugins/dsh/skills/clipboard-vision/__tests__/clipboard-vision-distribution.test.cjs +65 -0
  91. package/plugins/dsh/skills/clipboard-vision/__tests__/clipboard-vision-security.test.cjs +185 -0
  92. package/plugins/dsh/skills/clipboard-vision/__tests__/clipboard-vision.Tests.ps1 +138 -0
  93. package/plugins/dsh/skills/clipboard-vision/__tests__/clipboard-vision.test.cjs +273 -0
  94. package/plugins/dsh/skills/clipboard-vision/describe-clipboard.ps1 +115 -0
  95. package/plugins/dsh/skills/clipboard-vision/describe-clipboard.sh +161 -0
  96. package/plugins/dsh/skills/clipboard-vision/scripts/clipboard-vision.ps1 +86 -0
  97. package/plugins/dsh/skills/clipboard-vision/scripts/clipboard-vision.sh +137 -0
  98. package/plugins/dsh/skills/delphi-review/.delphi-config.json.example +70 -0
  99. package/plugins/dsh/skills/delphi-review/AGENTS.md +67 -0
  100. package/plugins/dsh/skills/delphi-review/INSTALL.md +150 -0
  101. package/plugins/dsh/skills/delphi-review/SKILL.md +559 -0
  102. package/plugins/dsh/skills/delphi-review/hooks.md +19 -0
  103. package/plugins/dsh/skills/delphi-review/opencode.json.delphi.example +52 -0
  104. package/plugins/dsh/skills/delphi-review/references/code-walkthrough.md +470 -0
  105. package/plugins/dsh/skills/delphi-review/references/orchestrator-dispatch.md +64 -0
  106. package/plugins/dsh/skills/delphi-review/references/requirements.md +402 -0
  107. package/plugins/dsh/skills/delphi-review/references/round-templates.md +134 -0
  108. package/plugins/dsh/skills/delphi-review/scripts/verify-consensus.sh +43 -0
  109. package/plugins/dsh/skills/delphi-review/tools.md +29 -0
  110. package/plugins/dsh/skills/domain-modeling/ADR-FORMAT.md +64 -0
  111. package/plugins/dsh/skills/domain-modeling/CONTEXT-FORMAT.md +60 -0
  112. package/plugins/dsh/skills/domain-modeling/SKILL.md +74 -0
  113. package/plugins/dsh/skills/grill-with-docs/SKILL.md +7 -0
  114. package/plugins/dsh/skills/grilling/SKILL.md +12 -0
  115. package/plugins/dsh/skills/improve-codebase-architecture/SKILL.md +156 -0
  116. package/plugins/dsh/skills/ralph-loop/SKILL.md +198 -0
  117. package/plugins/dsh/skills/ralph-loop/references/components.md +113 -0
  118. package/plugins/dsh/skills/ralph-loop/references/phase-2-build-ralph.md +89 -0
  119. package/plugins/dsh/skills/ralph-loop/references/workflow-details.md +99 -0
  120. package/plugins/dsh/skills/ralph-loop/templates/progress-log.md +36 -0
  121. package/plugins/dsh/skills/sprint-flow/AGENTS.md +103 -0
  122. package/plugins/dsh/skills/sprint-flow/SKILL.md +411 -0
  123. package/plugins/dsh/skills/sprint-flow/__tests__/sprint-flow.test.cjs +457 -0
  124. package/plugins/dsh/skills/sprint-flow/hooks.md +18 -0
  125. package/plugins/dsh/skills/sprint-flow/references/components/memory.md +87 -0
  126. package/plugins/dsh/skills/sprint-flow/references/components/middleware.md +75 -0
  127. package/plugins/dsh/skills/sprint-flow/references/components/skill-invocations.md +105 -0
  128. package/plugins/dsh/skills/sprint-flow/references/components/system-prompt.md +27 -0
  129. package/plugins/dsh/skills/sprint-flow/references/components/tool-descriptions.md +95 -0
  130. package/plugins/dsh/skills/sprint-flow/references/force-levels.md +204 -0
  131. package/plugins/dsh/skills/sprint-flow/references/orchestration-rules.md +236 -0
  132. package/plugins/dsh/skills/sprint-flow/references/phase-1-prep.md +294 -0
  133. package/plugins/dsh/skills/sprint-flow/references/phase-2-design.md +273 -0
  134. package/plugins/dsh/skills/sprint-flow/references/phase-3-build.md +348 -0
  135. package/plugins/dsh/skills/sprint-flow/references/phase-4-verify.md +225 -0
  136. package/plugins/dsh/skills/sprint-flow/references/phase-5-ship.md +222 -0
  137. package/plugins/dsh/skills/sprint-flow/references/phase-6-close.md +266 -0
  138. package/plugins/dsh/skills/sprint-flow/references/phase-overview.md +486 -0
  139. package/plugins/dsh/skills/sprint-flow/scripts/verify-sprint-state.sh +38 -0
  140. package/plugins/dsh/skills/sprint-flow/templates/auto-estimate-learning-log.md +136 -0
  141. package/plugins/dsh/skills/sprint-flow/templates/auto-estimate-output-template.md +110 -0
  142. package/plugins/dsh/skills/sprint-flow/templates/emergent-issues-template.md +120 -0
  143. package/plugins/dsh/skills/sprint-flow/templates/pain-document-template.md +115 -0
  144. package/plugins/dsh/skills/sprint-flow/templates/sprint-progress-template.md +140 -0
  145. package/plugins/dsh/skills/sprint-flow/templates/sprint-summary-template.md +121 -0
  146. package/plugins/dsh/skills/sprint-flow/tools.md +29 -0
  147. package/plugins/dsh/skills/test-driven-development/SKILL.md +371 -0
  148. package/plugins/dsh/skills/test-driven-development/testing-anti-patterns.md +299 -0
  149. package/plugins/dsh/skills/test-specification-alignment/AGENTS.md +56 -0
  150. package/plugins/dsh/skills/test-specification-alignment/SKILL.md +205 -0
  151. package/plugins/dsh/skills/test-specification-alignment/references/alignment-verification-algorithm.md +493 -0
  152. package/plugins/dsh/skills/test-specification-alignment/references/phase2-constraint-enforcement.md +431 -0
  153. package/plugins/dsh/skills/test-specification-alignment/references/specification-format.md +348 -0
  154. package/plugins/dsh/skills/to-issues/SKILL.md +277 -0
  155. package/plugins/dsh/src/command.test.ts +102 -0
  156. package/plugins/dsh/src/command.ts +75 -0
  157. package/plugins/dsh/src/contract.test.ts +62 -0
  158. package/plugins/dsh/src/gate-runner.test.ts +100 -0
  159. package/plugins/dsh/src/gate-runner.ts +58 -0
  160. package/plugins/dsh/src/index.test.ts +97 -0
  161. package/plugins/dsh/src/index.ts +94 -0
  162. package/plugins/dsh/src/skills.test.ts +58 -0
  163. package/plugins/dsh/tsconfig.build.json +13 -0
  164. package/plugins/dsh/tsconfig.json +19 -0
  165. package/plugins/dsh/vitest.config.ts +8 -0
  166. package/plugins/opencode/package.json +1 -1
  167. package/plugins/opencode/scripts/prepack.cjs +1 -0
  168. package/plugins/opencode/skills/clipboard-vision/SKILL.md +47 -0
  169. package/plugins/opencode/skills/clipboard-vision/__tests__/clipboard-vision-distribution.test.cjs +65 -0
  170. package/plugins/opencode/skills/clipboard-vision/__tests__/clipboard-vision-security.test.cjs +185 -0
  171. package/plugins/opencode/skills/clipboard-vision/__tests__/clipboard-vision.Tests.ps1 +138 -0
  172. package/plugins/opencode/skills/clipboard-vision/__tests__/clipboard-vision.test.cjs +273 -0
  173. package/plugins/opencode/skills/clipboard-vision/describe-clipboard.ps1 +115 -0
  174. package/plugins/opencode/skills/clipboard-vision/describe-clipboard.sh +161 -0
  175. package/plugins/opencode/skills/clipboard-vision/scripts/clipboard-vision.ps1 +86 -0
  176. package/plugins/opencode/skills/clipboard-vision/scripts/clipboard-vision.sh +137 -0
  177. package/plugins/opencode/skills/delphi-review/.delphi-config.json.example +24 -27
  178. package/plugins/opencode/skills/delphi-review/AGENTS.md +13 -12
  179. package/plugins/opencode/skills/delphi-review/INSTALL.md +15 -17
  180. package/plugins/opencode/skills/delphi-review/SKILL.md +30 -29
  181. package/plugins/opencode/skills/delphi-review/opencode.json.delphi.example +6 -10
  182. package/plugins/opencode/skills/delphi-review/references/code-walkthrough.md +33 -49
  183. package/plugins/opencode/skills/delphi-review/references/requirements.md +66 -54
  184. package/plugins/opencode/skills/delphi-review/references/round-templates.md +7 -7
  185. package/plugins/opencode/skills/sprint-flow/AGENTS.md +5 -5
  186. package/plugins/opencode/skills/sprint-flow/SKILL.md +4 -4
  187. package/plugins/opencode/skills/sprint-flow/references/components/skill-invocations.md +2 -2
  188. package/plugins/opencode/skills/sprint-flow/references/force-levels.md +37 -35
  189. package/plugins/opencode/skills/sprint-flow/references/orchestration-rules.md +1 -1
  190. package/plugins/opencode/skills/sprint-flow/references/phase-1-prep.md +1 -1
  191. package/plugins/opencode/skills/sprint-flow/references/phase-2-design.md +24 -14
  192. package/plugins/opencode/skills/sprint-flow/references/phase-4-verify.md +6 -6
  193. package/plugins/opencode/skills/sprint-flow/references/phase-overview.md +2 -2
  194. package/plugins/opencode/skills/test-specification-alignment/AGENTS.md +4 -4
  195. package/plugins/qoder/plugin.json +1 -1
  196. package/plugins/qoder/skills/clipboard-vision/SKILL.md +47 -0
  197. package/plugins/qoder/skills/clipboard-vision/__tests__/clipboard-vision-distribution.test.cjs +65 -0
  198. package/plugins/qoder/skills/clipboard-vision/__tests__/clipboard-vision-security.test.cjs +185 -0
  199. package/plugins/qoder/skills/clipboard-vision/__tests__/clipboard-vision.Tests.ps1 +138 -0
  200. package/plugins/qoder/skills/clipboard-vision/__tests__/clipboard-vision.test.cjs +273 -0
  201. package/plugins/qoder/skills/clipboard-vision/clipboard-vision/SKILL.md +47 -0
  202. package/plugins/qoder/skills/clipboard-vision/clipboard-vision/__tests__/clipboard-vision-distribution.test.cjs +65 -0
  203. package/plugins/qoder/skills/clipboard-vision/clipboard-vision/__tests__/clipboard-vision-security.test.cjs +185 -0
  204. package/plugins/qoder/skills/clipboard-vision/clipboard-vision/__tests__/clipboard-vision.Tests.ps1 +138 -0
  205. package/plugins/qoder/skills/clipboard-vision/clipboard-vision/__tests__/clipboard-vision.test.cjs +273 -0
  206. package/plugins/qoder/skills/clipboard-vision/clipboard-vision/scripts/clipboard-vision.ps1 +86 -0
  207. package/plugins/qoder/skills/clipboard-vision/clipboard-vision/scripts/clipboard-vision.sh +137 -0
  208. package/plugins/qoder/skills/clipboard-vision/scripts/clipboard-vision.ps1 +86 -0
  209. package/plugins/qoder/skills/clipboard-vision/scripts/clipboard-vision.sh +137 -0
  210. package/plugins/qoder/skills/delphi-review/.delphi-config.json.example +3 -11
  211. package/plugins/qoder/skills/delphi-review/AGENTS.md +15 -17
  212. package/plugins/qoder/skills/delphi-review/INSTALL.md +12 -12
  213. package/plugins/qoder/skills/delphi-review/SKILL.md +58 -25
  214. package/plugins/qoder/skills/delphi-review/opencode.json.delphi.example +1 -1
  215. package/plugins/qoder/skills/delphi-review/references/code-walkthrough.md +33 -49
  216. package/plugins/qoder/skills/sprint-flow/AGENTS.md +5 -5
  217. package/plugins/qoder/skills/sprint-flow/SKILL.md +2 -2
  218. package/plugins/qoder/skills/sprint-flow/references/force-levels.md +38 -35
  219. package/plugins/qoder/skills/sprint-flow/references/phase-1-prep.md +1 -1
  220. package/plugins/qoder/skills/sprint-flow/references/phase-2-design.md +48 -6
  221. package/plugins/qoder/skills/sprint-flow/references/phase-4-verify.md +5 -6
  222. package/plugins/qoder/skills/test-specification-alignment/AGENTS.md +4 -4
  223. package/principles/AGENTS.md +4 -4
  224. package/scripts/__tests__/sync-package-content.test.js +30 -0
  225. package/scripts/delphi-external-review.cjs +194 -63
  226. package/scripts/sync-package-content.js +9 -2
  227. package/skills/clipboard-vision/SKILL.md +47 -0
  228. package/skills/clipboard-vision/__tests__/clipboard-vision-distribution.test.cjs +65 -0
  229. package/skills/clipboard-vision/__tests__/clipboard-vision-security.test.cjs +185 -0
  230. package/skills/clipboard-vision/__tests__/clipboard-vision.Tests.ps1 +138 -0
  231. package/skills/clipboard-vision/__tests__/clipboard-vision.test.cjs +273 -0
  232. package/skills/clipboard-vision/describe-clipboard.ps1 +115 -0
  233. package/skills/clipboard-vision/describe-clipboard.sh +161 -0
  234. package/skills/clipboard-vision/scripts/clipboard-vision.ps1 +86 -0
  235. package/skills/clipboard-vision/scripts/clipboard-vision.sh +137 -0
  236. package/skills/delphi-review/.delphi-config.json.example +24 -27
  237. package/skills/delphi-review/AGENTS.md +13 -12
  238. package/skills/delphi-review/INSTALL.md +15 -17
  239. package/skills/delphi-review/SKILL.md +30 -29
  240. package/skills/delphi-review/opencode.json.delphi.example +6 -10
  241. package/skills/delphi-review/references/code-walkthrough.md +33 -49
  242. package/skills/delphi-review/references/requirements.md +66 -54
  243. package/skills/delphi-review/references/round-templates.md +7 -7
  244. package/skills/sprint-flow/AGENTS.md +5 -5
  245. package/skills/sprint-flow/SKILL.md +4 -4
  246. package/skills/sprint-flow/references/components/skill-invocations.md +2 -2
  247. package/skills/sprint-flow/references/force-levels.md +37 -35
  248. package/skills/sprint-flow/references/orchestration-rules.md +1 -1
  249. package/skills/sprint-flow/references/phase-1-prep.md +1 -1
  250. package/skills/sprint-flow/references/phase-2-design.md +24 -14
  251. package/skills/sprint-flow/references/phase-4-verify.md +6 -6
  252. package/skills/sprint-flow/references/phase-overview.md +2 -2
  253. package/skills/test-specification-alignment/AGENTS.md +4 -4
  254. package/sprint-gate.sh +291 -0
@@ -0,0 +1,457 @@
1
+ /**
2
+ * @test REQ-SF-001 Sprint Flow Trigger Accuracy
3
+ * @intent Verify that sprint-flow SKILL.md trigger detection correctly distinguishes
4
+ * between valid sprint-flow requests and unrelated queries
5
+ * @covers AC-SF-001-01, AC-SF-001-02, AC-SF-001-03
6
+ */
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+
10
+ const SKILL_MD_PATH = path.join(__dirname, '..', 'SKILL.md');
11
+ const REFERENCES_DIR = path.join(__dirname, '..', 'references');
12
+ const PHASE_OVERVIEW_PATH = path.join(REFERENCES_DIR, 'phase-overview.md');
13
+ const PHASE_2_BUILD_PATH = path.join(REFERENCES_DIR, 'phase-3-build.md');
14
+ const ORCHESTRATION_RULES_PATH = path.join(REFERENCES_DIR, 'orchestration-rules.md');
15
+
16
+ let skillContent = '';
17
+ let phaseOverviewContent = '';
18
+
19
+ function loadSkillMd() {
20
+ skillContent = fs.readFileSync(SKILL_MD_PATH, 'utf-8');
21
+ if (fs.existsSync(PHASE_OVERVIEW_PATH)) {
22
+ phaseOverviewContent = fs.readFileSync(PHASE_OVERVIEW_PATH, 'utf-8');
23
+ }
24
+ }
25
+
26
+ // Search across SKILL.md AND references/phase-overview.md (progressive disclosure: sections
27
+ // like "Unique Value Proposition" and "Phase Flow Consistency" moved to reference file).
28
+ function contentIncludes(str) {
29
+ return skillContent.includes(str) || phaseOverviewContent.includes(str);
30
+ }
31
+ function contentSplit(str) {
32
+ // Return the part after str from whichever file contains it.
33
+ // Throws descriptive error instead of returning undefined so callers
34
+ // get a clear assertion message rather than a TypeError crash.
35
+ if (skillContent.includes(str)) return skillContent.split(str)[1];
36
+ if (phaseOverviewContent.includes(str)) return phaseOverviewContent.split(str)[1];
37
+ throw new Error(`Section "${str}" not found in SKILL.md or references/phase-overview.md`);
38
+ }
39
+
40
+ function parseFrontmatter(content) {
41
+ const match = content.match(/^---\n([\s\S]*?)\n---/);
42
+ if (!match) return {};
43
+ const yaml = match[1];
44
+ const result = {};
45
+ // Parse simple YAML key-value pairs and lists
46
+ const lines = yaml.split('\n');
47
+ let currentKey = null;
48
+ for (const line of lines) {
49
+ const trimmed = line.trim();
50
+ if (trimmed === '' || trimmed.startsWith('#')) continue;
51
+ const kvMatch = trimmed.match(/^(\w[\w_]*):\s*(.*)/);
52
+ if (kvMatch) {
53
+ currentKey = kvMatch[1];
54
+ const val = kvMatch[2].trim();
55
+ if (val === '') {
56
+ result[currentKey] = [];
57
+ } else if (val.startsWith('"') || val.startsWith("'")) {
58
+ result[currentKey] = val.slice(1, -1);
59
+ } else {
60
+ result[currentKey] = val;
61
+ }
62
+ } else if (trimmed.startsWith('- ') && currentKey) {
63
+ const item = trimmed.slice(2).trim().replace(/^["'](.*)["'].*$/, '$1');
64
+ if (!Array.isArray(result[currentKey])) result[currentKey] = [];
65
+ result[currentKey].push(item);
66
+ }
67
+ }
68
+ return result;
69
+ }
70
+
71
+ // === Trigger Accuracy Tests ===
72
+
73
+ function testPositiveTriggersArePresent() {
74
+ const frontmatter = parseFrontmatter(skillContent);
75
+ const triggers = frontmatter.triggers || [];
76
+ const required = ['/sprint-flow', 'start sprint', '开发新功能', '一键开发'];
77
+ const missing = required.filter(r => !triggers.some(t => t.includes(r)));
78
+ if (missing.length > 0) {
79
+ throw new Error(`Missing positive triggers: ${missing.join(', ')}`);
80
+ }
81
+ console.log(' ✓ Positive triggers are present');
82
+ }
83
+
84
+ function testNegativeTriggersArePresent() {
85
+ const frontmatter = parseFrontmatter(skillContent);
86
+ const negTriggers = frontmatter.triggers_negative_examples || [];
87
+ if (negTriggers.length < 8) {
88
+ throw new Error(`triggers_negative_examples must have at least 8 entries, got ${negTriggers.length}`);
89
+ }
90
+ console.log(` ✓ Negative triggers have ${negTriggers.length} entries (>= 8 required)`);
91
+ }
92
+
93
+ function testNegativeTriggerPhrases() {
94
+ // These phrases must NOT trigger sprint-flow
95
+ const shouldNotTrigger = [
96
+ '实现排序算法',
97
+ '实现一下',
98
+ '帮我实现这个函数',
99
+ '怎么实现登录功能',
100
+ 'start spring boot',
101
+ '开发环境配置',
102
+ '一键部署',
103
+ '新功能建议',
104
+ 'implement a sort function',
105
+ 'how to implement auth',
106
+ ];
107
+ for (const phrase of shouldNotTrigger) {
108
+ // Verify phrase is in triggers_negative_examples
109
+ const frontmatter = parseFrontmatter(skillContent);
110
+ const negTriggers = frontmatter.triggers_negative_examples || [];
111
+ const found = negTriggers.some(n => n.includes(phrase) || phrase.includes(n));
112
+ if (!found) {
113
+ throw new Error(`Negative trigger phrase "${phrase}" not found in triggers_negative_examples`);
114
+ }
115
+ }
116
+ console.log(` ✓ All ${shouldNotTrigger.length} negative trigger phrases verified`);
117
+ }
118
+
119
+ function testPositiveTriggerPhrases() {
120
+ const shouldTrigger = [
121
+ '开发用户认证模块',
122
+ '/sprint-flow',
123
+ '一键开发 REST API',
124
+ ];
125
+ for (const phrase of shouldTrigger) {
126
+ const frontmatter = parseFrontmatter(skillContent);
127
+ const triggers = frontmatter.triggers || [];
128
+ // Match against frontmatter triggers OR check body trigger table for broader patterns
129
+ const matched = triggers.some(t =>
130
+ phrase.includes(t) || t.includes(phrase) || phrase.includes('/sprint-flow')
131
+ ) || skillContent.includes(phrase);
132
+ if (!matched) {
133
+ throw new Error(`Positive trigger phrase "${phrase}" should match at least one trigger`);
134
+ }
135
+ }
136
+ console.log(` ✓ All ${shouldTrigger.length} positive trigger phrases verified`);
137
+ }
138
+
139
+ function testNegativeTestCasesExist() {
140
+ // Count test case entries by matching "input:" lines in triggers_negative_test_cases YAML block
141
+ const fmMatch = skillContent.match(/^---\n([\s\S]*?)\n---/);
142
+ if (!fmMatch) throw new Error('Frontmatter not found');
143
+ const yaml = fmMatch[1];
144
+
145
+ // Find triggers_negative_test_cases block and count "- input:" lines within it
146
+ const testCasesSection = yaml.split('triggers_negative_test_cases:')[1];
147
+ if (!testCasesSection) throw new Error('triggers_negative_test_cases not found in frontmatter');
148
+
149
+ const count = (testCasesSection.match(/^\s+- input:/gm) || []).length;
150
+ if (count < 11) {
151
+ throw new Error(`triggers_negative_test_cases must have at least 11 entries, got ${count}`);
152
+ }
153
+ console.log(` ✓ Negative test cases have ${count} entries (>= 11 required)`);
154
+ }
155
+
156
+ // === Phase Transition Tests ===
157
+
158
+ function testWorkflowStepsOrder() {
159
+ const frontmatter = parseFrontmatter(skillContent);
160
+ const steps = frontmatter.workflow_steps || [];
161
+ if (steps.length !== 6) {
162
+ throw new Error(`workflow_steps must have exactly 6 entries, got ${steps.length}`);
163
+ }
164
+
165
+ const expectedOrder = [
166
+ 'PREP', 'DESIGN', 'BUILD', 'VERIFY', 'SHIP', 'CLOSE',
167
+ ];
168
+
169
+ for (let i = 0; i < expectedOrder.length; i++) {
170
+ if (!steps[i].includes(expectedOrder[i])) {
171
+ throw new Error(
172
+ `workflow_steps[${i}] should contain "${expectedOrder[i]}", got "${steps[i]}"`
173
+ );
174
+ }
175
+ }
176
+ console.log(' ✓ workflow_steps order matches canonical 6-phase sequence');
177
+ }
178
+
179
+ function testPhaseFlowDiagramOrder() {
180
+ // The Phase Flow diagram in the body must show: PREP → ... → SHIP → CLOSE
181
+ const flowMatch = skillContent.match(/PREP →.*CLOSE/);
182
+ if (!flowMatch) {
183
+ throw new Error('Phase Flow diagram not found in SKILL.md body');
184
+ }
185
+ const flow = flowMatch[0];
186
+
187
+ // Verify VERIFY comes before SHIP
188
+ const verifyPos = flow.indexOf('VERIFY');
189
+ const shipPos = flow.indexOf('SHIP');
190
+ const closePos = flow.indexOf('CLOSE');
191
+ if (verifyPos === -1 || shipPos === -1 || closePos === -1) {
192
+ throw new Error('Phase Flow diagram missing required phases');
193
+ }
194
+ if (verifyPos > shipPos) {
195
+ throw new Error('VERIFY must come before SHIP in phase flow diagram');
196
+ }
197
+ if (shipPos > closePos) {
198
+ throw new Error('SHIP must come before CLOSE in phase flow diagram');
199
+ }
200
+ console.log(' ✓ Phase Flow diagram has correct ordering');
201
+ }
202
+
203
+ function testPhaseFlowConsistencySectionExists() {
204
+ if (!contentIncludes('Phase Flow Consistency')) {
205
+ throw new Error('SKILL.md or references/phase-overview.md must contain "Phase Flow Consistency" section');
206
+ }
207
+ console.log(' ✓ Phase Flow Consistency section exists');
208
+ }
209
+
210
+ function testCanonicalPhaseOrderTableExists() {
211
+ if (!contentIncludes('Canonical Phase Order')) {
212
+ throw new Error('SKILL.md or references/phase-overview.md must contain "Canonical Phase Order" table');
213
+ }
214
+ console.log(' ✓ Canonical Phase Order table exists');
215
+ }
216
+
217
+ function testAll11PhasesInPhaseFlowConsistency() {
218
+ const section = contentSplit('Phase Flow Consistency');
219
+ const requiredPhases = [
220
+ 'PREP', 'DESIGN', 'BUILD', 'VERIFY', 'SHIP', 'CLOSE',
221
+ ];
222
+ for (const phase of requiredPhases) {
223
+ if (!section.includes(phase)) {
224
+ throw new Error(`Phase Flow Consistency section missing phase: ${phase}`);
225
+ }
226
+ }
227
+ console.log(' ✓ All 6 phases referenced in Phase Flow Consistency section');
228
+ }
229
+
230
+ // === Force Levels Tests ===
231
+
232
+ function testForceLevelsDocumentExists() {
233
+ const forceLevelsPath = path.join(REFERENCES_DIR, 'force-levels.md');
234
+ if (!fs.existsSync(forceLevelsPath)) {
235
+ throw new Error('references/force-levels.md must exist');
236
+ }
237
+ const content = fs.readFileSync(forceLevelsPath, 'utf-8');
238
+ if (!content.includes('轻量') || !content.includes('标准') || !content.includes('复杂')) {
239
+ throw new Error('force-levels.md must document lightweight/standard/complex levels');
240
+ }
241
+ console.log(' ✓ force-levels.md exists and documents three levels');
242
+ }
243
+
244
+ function testForceLevelsRequiresDelphi() {
245
+ const forceLevelsContent = fs.readFileSync(
246
+ path.join(REFERENCES_DIR, 'force-levels.md'), 'utf-8'
247
+ );
248
+ if (!forceLevelsContent.includes('Delphi') && !forceLevelsContent.includes('delphi')) {
249
+ throw new Error('force-levels.md must reference Delphi review requirement');
250
+ }
251
+ console.log(' ✓ force-levels.md requires Delphi review for all levels');
252
+ }
253
+
254
+ // === Value Proposition Tests ===
255
+
256
+ function testUniqueValuePropositionExists() {
257
+ if (!contentIncludes('Unique Value Proposition')) {
258
+ throw new Error('SKILL.md or references/phase-overview.md must contain "Unique Value Proposition" section');
259
+ }
260
+ console.log(' ✓ Unique Value Proposition section exists');
261
+ }
262
+
263
+ function testUvpMentionsTokenSavings() {
264
+ const section = contentSplit('Unique Value Proposition');
265
+ if (!section.includes('40') || !section.includes('67') || !section.includes('token')) {
266
+ throw new Error('Unique Value Proposition must mention 40-67% token savings');
267
+ }
268
+ console.log(' ✓ UVP mentions 40-67% token savings');
269
+ }
270
+
271
+ function testUvpMentionsHardGate() {
272
+ const section = contentSplit('Unique Value Proposition');
273
+ if (!section.includes('HARD-GATE')) {
274
+ throw new Error('Unique Value Proposition must mention HARD-GATE discipline');
275
+ }
276
+ console.log(' ✓ UVP mentions HARD-GATE discipline');
277
+ }
278
+
279
+ function testUvpMentionsEmergentRequirements() {
280
+ const section = contentSplit('Unique Value Proposition');
281
+ if (!section.toLowerCase().includes('emergent')) {
282
+ throw new Error('Unique Value Proposition must mention emergent requirements');
283
+ }
284
+ console.log(' ✓ UVP mentions emergent requirements');
285
+ }
286
+
287
+ // === Phase Timing Tests ===
288
+
289
+ function testTimingSectionExists() {
290
+ const phase2BuildContent = fs.readFileSync(PHASE_2_BUILD_PATH, 'utf-8');
291
+ if (!phase2BuildContent.includes('Timing & Stability')) {
292
+ throw new Error('phase-3-build.md must contain "Timing & Stability" section');
293
+ }
294
+ console.log(' ✓ Timing & Stability section exists in phase-3-build.md');
295
+ }
296
+
297
+ function testTimeoutRecommendationsExist() {
298
+ const phase2BuildContent = fs.readFileSync(PHASE_2_BUILD_PATH, 'utf-8');
299
+ const timeoutSection = phase2BuildContent.split('Timing & Stability')[1];
300
+ if (!timeoutSection || !timeoutSection.includes('Timeout')) {
301
+ throw new Error('Timing & Stability section must include timeout recommendations');
302
+ }
303
+ console.log(' ✓ Timeout recommendations exist');
304
+ }
305
+
306
+ function testExecutionTimeEstimatesExist() {
307
+ const phase2BuildContent = fs.readFileSync(PHASE_2_BUILD_PATH, 'utf-8');
308
+ if (!phase2BuildContent.includes('Expected Time')) {
309
+ throw new Error('phase-3-build.md must include expected execution time estimates');
310
+ }
311
+ console.log(' ✓ Expected execution time estimates exist');
312
+ }
313
+
314
+ // === Orchestration Rules Tests ===
315
+
316
+ function testOrchestrationRulesExists() {
317
+ if (!fs.existsSync(ORCHESTRATION_RULES_PATH)) {
318
+ throw new Error('references/orchestration-rules.md must exist');
319
+ }
320
+ console.log(' ✓ orchestration-rules.md exists');
321
+ }
322
+
323
+ function testPhaseSubagentMatrixOrder() {
324
+ const orchContent = fs.readFileSync(ORCHESTRATION_RULES_PATH, 'utf-8');
325
+ // The matrix order reflects file names, but phases should all be present
326
+ for (const phase of ['PREP', 'DESIGN', 'BUILD', 'VERIFY', 'SHIP', 'CLOSE']) {
327
+ if (!orchContent.includes(phase)) {
328
+ throw new Error(`orchestration-rules.md missing phase: ${phase}`);
329
+ }
330
+ }
331
+ console.log(' ✓ Orchestration rules covers all key phases');
332
+ }
333
+
334
+ // === Run All Tests ===
335
+
336
+ function runTests(opts = {}) {
337
+ const { exitOnFail = false } = opts;
338
+ let passed = 0;
339
+ let failed = 0;
340
+ const errors = [];
341
+
342
+ const tests = [
343
+ { name: 'Positive triggers are present', fn: testPositiveTriggersArePresent },
344
+ { name: 'Negative triggers have >= 8 entries', fn: testNegativeTriggersArePresent },
345
+ { name: 'Negative trigger phrases verified', fn: testNegativeTriggerPhrases },
346
+ { name: 'Positive trigger phrases verified', fn: testPositiveTriggerPhrases },
347
+ { name: 'Negative test cases exist (>= 11)', fn: testNegativeTestCasesExist },
348
+ { name: 'workflow_steps order matches canonical', fn: testWorkflowStepsOrder },
349
+ { name: 'Phase Flow diagram has correct ordering', fn: testPhaseFlowDiagramOrder },
350
+ { name: 'Phase Flow Consistency section exists', fn: testPhaseFlowConsistencySectionExists },
351
+ { name: 'Canonical Phase Order table exists', fn: testCanonicalPhaseOrderTableExists },
352
+ { name: 'All 6 phases in consistency section', fn: testAll11PhasesInPhaseFlowConsistency },
353
+ { name: 'force-levels.md exists with three levels', fn: testForceLevelsDocumentExists },
354
+ { name: 'force-levels.md requires Delphi review', fn: testForceLevelsRequiresDelphi },
355
+ { name: 'Unique Value Proposition exists', fn: testUniqueValuePropositionExists },
356
+ { name: 'UVP mentions 40-67% token savings', fn: testUvpMentionsTokenSavings },
357
+ { name: 'UVP mentions HARD-GATE', fn: testUvpMentionsHardGate },
358
+ { name: 'UVP mentions emergent requirements', fn: testUvpMentionsEmergentRequirements },
359
+ { name: 'Timing & Stability section exists', fn: testTimingSectionExists },
360
+ { name: 'Timeout recommendations exist', fn: testTimeoutRecommendationsExist },
361
+ { name: 'Execution time estimates exist', fn: testExecutionTimeEstimatesExist },
362
+ { name: 'orchestration-rules.md exists', fn: testOrchestrationRulesExists },
363
+ { name: 'Orchestration covers all key phases', fn: testPhaseSubagentMatrixOrder },
364
+ { name: 'Uncommitted Changes Gate section exists', fn: testUncommittedGateExists },
365
+ { name: 'Uncommitted gate has escape valve', fn: testUncommittedGateEscapeValve },
366
+ { name: 'Uncommitted gate has log path', fn: testUncommittedGateLogPath },
367
+ ];
368
+
369
+ loadSkillMd();
370
+
371
+ for (const { name, fn } of tests) {
372
+ try {
373
+ fn();
374
+ passed++;
375
+ } catch (e) {
376
+ failed++;
377
+ errors.push(`FAIL: ${name}: ${e.message}`);
378
+ }
379
+ }
380
+
381
+ console.log(`\n=== Results: ${passed} passed, ${failed} failed ===\n`);
382
+ for (const e of errors) console.log(e);
383
+
384
+ if (exitOnFail && failed > 0) {
385
+ process.exit(1);
386
+ }
387
+ return failed > 0 ? 1 : 0;
388
+ }
389
+
390
+ // Uncommitted Changes Gate tests (must run after the section is added)
391
+ function testUncommittedGateExists() {
392
+ const phase2BuildContent = fs.readFileSync(PHASE_2_BUILD_PATH, 'utf-8');
393
+ if (!phase2BuildContent.includes('Uncommitted Changes Gate')) {
394
+ throw new Error('phase-3-build.md must contain "Uncommitted Changes Gate" section');
395
+ }
396
+ console.log(' ✓ Uncommitted Changes Gate section exists');
397
+ }
398
+
399
+ function testUncommittedGateEscapeValve() {
400
+ const phase2BuildContent = fs.readFileSync(PHASE_2_BUILD_PATH, 'utf-8');
401
+ if (!phase2BuildContent.includes('SKIP_UNCOMMITTED_GATE')) {
402
+ throw new Error('Uncommitted Changes Gate must provide SKIP_UNCOMMITTED_GATE escape valve');
403
+ }
404
+ console.log(' ✓ Uncommitted gate has SKIP_UNCOMMITTED_GATE escape valve');
405
+ }
406
+
407
+ function testUncommittedGateLogPath() {
408
+ const phase2BuildContent = fs.readFileSync(PHASE_2_BUILD_PATH, 'utf-8');
409
+ if (!phase2BuildContent.includes('.sprint-state/uncommitted-gate-log.json')) {
410
+ throw new Error('Uncommitted Changes Gate must log to .sprint-state/uncommitted-gate-log.json');
411
+ }
412
+ console.log(' ✓ Uncommitted gate logs to .sprint-state/uncommitted-gate-log.json');
413
+ }
414
+
415
+ // When run directly (node script.js), call with exitOnFail for CLI behavior.
416
+ if (require.main === module) {
417
+ const exitCode = runTests({ exitOnFail: true });
418
+ process.exit(exitCode);
419
+ }
420
+
421
+ // Vitest discovery — wrap each test function as a vitest it() block
422
+ describe('sprint-flow SKILL.md', () => {
423
+ beforeAll(() => { loadSkillMd(); });
424
+
425
+ const tests = [
426
+ { name: 'Positive triggers are present', fn: testPositiveTriggersArePresent },
427
+ { name: 'Negative triggers have >= 8 entries', fn: testNegativeTriggersArePresent },
428
+ { name: 'Negative trigger phrases verified', fn: testNegativeTriggerPhrases },
429
+ { name: 'Positive trigger phrases verified', fn: testPositiveTriggerPhrases },
430
+ { name: 'Negative test cases exist (>= 11)', fn: testNegativeTestCasesExist },
431
+ { name: 'workflow_steps order matches canonical', fn: testWorkflowStepsOrder },
432
+ { name: 'Phase Flow diagram has correct ordering', fn: testPhaseFlowDiagramOrder },
433
+ { name: 'Phase Flow Consistency section exists', fn: testPhaseFlowConsistencySectionExists },
434
+ { name: 'Canonical Phase Order table exists', fn: testCanonicalPhaseOrderTableExists },
435
+ { name: 'All 6 phases in consistency section', fn: testAll11PhasesInPhaseFlowConsistency },
436
+ { name: 'force-levels.md exists with three levels', fn: testForceLevelsDocumentExists },
437
+ { name: 'force-levels.md requires Delphi review', fn: testForceLevelsRequiresDelphi },
438
+ { name: 'Unique Value Proposition exists', fn: testUniqueValuePropositionExists },
439
+ { name: 'UVP mentions 40-67% token savings', fn: testUvpMentionsTokenSavings },
440
+ { name: 'UVP mentions HARD-GATE', fn: testUvpMentionsHardGate },
441
+ { name: 'UVP mentions emergent requirements', fn: testUvpMentionsEmergentRequirements },
442
+ { name: 'Timing & Stability section exists', fn: testTimingSectionExists },
443
+ { name: 'Timeout recommendations exist', fn: testTimeoutRecommendationsExist },
444
+ { name: 'Execution time estimates exist', fn: testExecutionTimeEstimatesExist },
445
+ { name: 'orchestration-rules.md exists', fn: testOrchestrationRulesExists },
446
+ { name: 'Orchestration covers all key phases', fn: testPhaseSubagentMatrixOrder },
447
+ { name: 'Uncommitted Changes Gate section exists', fn: testUncommittedGateExists },
448
+ { name: 'Uncommitted gate has escape valve', fn: testUncommittedGateEscapeValve },
449
+ { name: 'Uncommitted gate has log path', fn: testUncommittedGateLogPath },
450
+ ];
451
+
452
+ for (const { name, fn } of tests) {
453
+ it(name, () => { fn(); });
454
+ }
455
+ });
456
+
457
+ module.exports = { runTests };
@@ -0,0 +1,18 @@
1
+ # Hooks — Sprint Flow
2
+
3
+ Sprint Flow integrates with safety and operational hooks to protect the development environment.
4
+
5
+ ## Security Hooks
6
+
7
+ | Hook | Purpose | Activation |
8
+ |------|---------|------------|
9
+ | `/careful` | Safety guardrails for destructive commands | Activate before any `rm`, `force-push`, or `git reset` |
10
+ | `/freeze` | Restrict edits to sprint worktree directory | Prevent accidental changes outside sprint scope |
11
+ | `/guard` | Full safety mode (careful + freeze) | Maximum protection for high-risk operations |
12
+
13
+ ## Operational Hooks
14
+
15
+ | Hook | Purpose | Activation |
16
+ |------|---------|------------|
17
+ | `/context-save` | Save sprint context before pause or handoff | Before pausing sprint or switching tasks |
18
+ | `/context-restore` | Restore sprint context on resume | When resuming from pause or handoff |
@@ -0,0 +1,87 @@
1
+ # memory.md — Sprint State JSON Schema 与长期记忆(AHE 组件分解)
2
+
3
+ > **本文是 `skills/sprint-flow/SKILL.md` 中状态管理 JSON (L190-334) 的 AHE 对齐展开。**
4
+ > 用于 ablation 实验:AHE 论文显示 Memory 组件单独恢复全局增幅的 95%+。
5
+
6
+ ## 组件职责
7
+
8
+ 定义 Sprint 状态持久化 Schema、Phase 输出合同、长期记忆(learnings)结构。是 AHE 中最关键组件(记忆单独恢复 95%+ 全局增益)。
9
+
10
+ ---
11
+
12
+ ## Sprint State Schema(`.sprint-state/sprint-state.json`)
13
+
14
+ ```json
15
+ {
16
+ "id": "sprint-YYYY-MM-DD-NN",
17
+ "phase": 0,
18
+ "status": "running|paused|completed",
19
+ "outputs": {
20
+ "pain_document": "docs/pain-document.md",
21
+ "specification": "specification.yaml",
22
+ "mvp": "mvp-v1/",
23
+ "review_report": "review-report.md"
24
+ },
25
+ "metrics": {
26
+ "tests_passed": 15,
27
+ "tests_failed": 0,
28
+ "coverage_pct": 85
29
+ }
30
+ }
31
+ ```
32
+
33
+ ### 状态枚举
34
+
35
+ | 字段 | 允许值 | 说明 |
36
+ |------|-------|------|
37
+ | `phase` | 0-6 | 当前执行阶段 |
38
+ | `status` | `pending` / `running` / `paused` / `completed` / `failed` | 统一状态 |
39
+ | `pause_reason` | `none` / `wait_approved` / `wait_gate1` / `wait_uat` / `wait_ship` / `wait_user_confirm` | 暂停原因 |
40
+
41
+ ---
42
+
43
+ ## Phase Output 合同
44
+
45
+ | Phase | 输出文件 | 存储路径 | 必需字段 |
46
+ |-------|---------|---------|---------|
47
+ | Phase 0 | `pain-document.md` | `phase-outputs/pain-document.md` | 结构化设计文档 |
48
+ | Phase 1 | `specification.yaml` | `phase-outputs/specification.yaml` | user_stories[], requirements[], acceptance_criteria[] |
49
+ | Phase 2 | `mvp-v1/` | `phase-outputs/mvp-v1/` | 功能代码 + 测试 |
50
+ | Phase 3 | `review-report.md` | `phase-outputs/review-report.md` | delphi-review 共识报告 |
51
+ | Phase 4 | `emergent-issues.md` | `phase-outputs/emergent-issues.md` | 用户发现的 emergent requirements |
52
+ | Phase 5 | `feedback-log.md` | `phase-outputs/feedback-log.md` | 改进建议 + 调试记录 |
53
+ | Phase 6 | `sprint-summary.md` | `phase-outputs/sprint-summary.md` | 发布记录 + Sprint 2 触发判断 |
54
+
55
+ ---
56
+
57
+ ## Sprint 2 自动触发规则
58
+
59
+ ```
60
+ Phase 6 完成后:
61
+ IF emergent_issues_count == 0 → sprint_completed,结束
62
+ IF emergent_issues_count > 0 → sprint_2_needed:
63
+ ├─ IF 有 Critical → 自动启动 Sprint 2
64
+ ├─ IF 仅有 Major/Minor → 询问用户
65
+ └─ Sprint 2 Pain Document ← emergent-issues.md 转化
66
+ ```
67
+
68
+ ---
69
+
70
+ ## Learnings Schema(长期记忆)
71
+
72
+ ralph-loop 内部分类:
73
+ - `permanent`: 跨 REQ 持久化(通用约束、模式)
74
+ - `contextual`: 当前 REQ 生命周期内有效
75
+
76
+ learnings.md 写入分类: permanent / contextual 通过 `.sprint-history/learnings.md` 持久化(原生,替代原 gstack/learn)。
77
+
78
+ ---
79
+
80
+ ## AHE 分类
81
+
82
+ | 字段 | 值 |
83
+ |------|---|
84
+ | 组件类型 | Long-Term Memory |
85
+ | 修改频率预期 | 低(Schema 稳定) |
86
+ | 消融实验假设 | 移除 memory → Sprint pass rate 下降 5-10% |
87
+ | 参考证据 | AHE 论文: Memory 单独恢复 95%+ 全局增幅(事实性 > 策略性) |
@@ -0,0 +1,75 @@
1
+ # middleware.md — Sprint Flow 状态机与暂停点逻辑(AHE 组件分解)
2
+
3
+ > **本文是 `skills/sprint-flow/SKILL.md` 中完整流程 (L46-68) 和暂停点表 (L72-84) 的 AHE 对齐展开。**
4
+ > 用于 ablation 实验:AHE 论文显示 Middleware 组件贡献占 37%,单独修改可显著影响性能。
5
+
6
+ ## 组件职责
7
+
8
+ 定义 Sprint Flow 的状态机转换逻辑、暂停点(pause-point)触发条件和自动恢复规则。是 phase 间的"胶水层",负责在特定节点暂停等待用户决策。
9
+
10
+ ---
11
+
12
+ ## 完整状态机(7 Phase 流转)
13
+
14
+ ```
15
+ Phase 0: THINK → brainstorming → HARD-GATE: 设计未 APPROVED → 不可编码
16
+ Phase 1: PLAN → autoplan → delphi-review → spec.yaml
17
+ Phase 2: BUILD → GITHOOKS-GATE → ralph-loop/TDD → verification → MVP v1
18
+ Phase 3: REVIEW → code-walkthrough → test-alignment → browse QA
19
+ Phase 4: USER ACCEPTANCE → ⚠️ 必须人工 → Emergent Issues List
20
+ Phase 5: FEEDBACK → learn + retro + systematic-debugging
21
+ Phase 6: SHIP → finishing-a-development-branch → canary → Sprint Summary
22
+ ```
23
+
24
+ ## 暂停点矩阵
25
+
26
+ | Phase | 暂停点标识 | 触发条件 | 用户操作 | 自动恢复条件 |
27
+ |-------|-----------|---------|---------|-------------|
28
+ | Phase 0 | **HARD-GATE** | 设计未 APPROVED | 修改设计文档 | 设计 APPROVED 后继续 |
29
+ | Phase 1 | taste_decisions | autoplan 发现未决议事项 | 用户确认每个决策 | 确认后自动继续 |
30
+ | Phase 1 | delphi-review | 最终 REQUEST_CHANGES(subagent 自动修复仍失败) | 修复并重新 dispatch | APPROVED 后自动继续 |
31
+ | **Phase 2** | **DELPHI-GATE** | delphi-reviewed.json 不存在或 verdict != APPROVED | 返回 Phase 1 完成 delphi-review | APPROVED 后继续 |
32
+ | Phase 2 | 验证失败 | 超过 max 3 次失败 | 用户决定修复或放弃 | 验证通过后自动继续 |
33
+ | Phase 2 | 成本超阈值 | token 成本 > 阈值 | 用户决定继续或暂停 | 用户确认后自动继续 |
34
+ | Phase 3 | browse 发现问题 | QA 失败 | 回退 Phase 2 | 验证通过后自动继续 |
35
+ | **Phase 4** | **必须人工验收** | 进入 Phase 4 | 用户实际使用后确认 | **无法自动恢复** |
36
+ | **Phase 5** | **FEEDBACK 硬门禁** | Phase 4 完成后进入 | 执行 learn + retro → 生成 feedback-log.md | feedback-log.md 存在后继续 |
37
+ | **Phase 6** | **Phase 5 门禁验证** | Phase 5 未完成 | 验证 feedback-log.md → 不存在 → 返回 Phase 5 | feedback-log.md 存在后继续 |
38
+ | Phase 6 | finishing-a-branch | 分支收尾 | 用户 4 选 1 | 确认后自动继续 |
39
+
40
+ > **#218 变更**: Delphi review Round 1→2→3 的自动调度在 subagent 内部完成,不暂停。`delphi-review` 暂停点仅当 subagent 自动修复仍失败时才触发。
41
+ > **#225 变更**: `taste_decisions` 暂停点由 orchestrator 直接执行 autoplan,不 dispatch 到 subagent。
42
+ > **PR 确认冗余移除**: ship PR 创建后不再暂停确认 — 用户已通过 finishing-a-development-branch 选择了 PR 路径。
43
+
44
+ ## 状态转换规则
45
+
46
+ | 当前状态 | 下一状态 | 条件 |
47
+ |---------|---------|------|
48
+ | Phase N 完成 | Phase N+1 | 无阻塞条件 |
49
+ | Phase 0 HARD-GATE 未通过 | Phase 0 (重试) | 设计未 APPROVED |
50
+ | Phase 2 DELPHI-GATE 未通过 | Phase 1 (回退) | delphi-review not APPROVED |
51
+ | Phase 4 人工验收未完成 | Phase 4 (等待) | **永远不可自动跳过** |
52
+ | Phase 4 确认完成 | Phase 5 | **必须执行,不可跳过** |
53
+ | Phase 5 未完成 (feedback-log.md 不存在) | Phase 5 (等待) | **永远不可自动跳过** |
54
+ | Phase 2 验证失败 > 3 次 | BLOCK (用户决策) | 熔断机制 |
55
+ | Phase 2 成本超限 | BLOCK (用户决策) | 熔断机制 |
56
+
57
+ ## 熔断机制 (Circuit Breaker)
58
+
59
+ | 原 xp-consensus 状态 | 新处理方案 |
60
+ |---------------------|-----------|
61
+ | `CIRCUIT_BREAKER_TRIGGERED` | sprint-flow 编排层监控成本,超阈值 BLOCK + 用户决策 |
62
+ | `ROLLBACK_TO_ROUND1` | verification-before-completion 失败 → 修复 max 3 次 → 仍失败 BLOCK |
63
+ | `GATE1_FAILED`/`GATE1_COMPLETE` | verification-before-completion 内置此区分 |
64
+ | `GATE2_RUNNING` | `xp-gate check --all`(Gate 7/8/9)— Phase 1-6 安全审计 |
65
+
66
+ ---
67
+
68
+ ## AHE 分类
69
+
70
+ | 字段 | 值 |
71
+ |------|---|
72
+ | 组件类型 | Middleware |
73
+ | 修改频率预期 | 高(状态机调整频繁) |
74
+ | 消融实验假设 | 修改暂停点逻辑 → Sprint 执行时间变化 ±15% |
75
+ | 参考证据 | AHE 论文: Middleware 组件单独修改带来 +2.2% 总增益 |