@specship/specship-win32-arm64 0.25.0 → 0.28.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 (274) hide show
  1. package/bin/specship.cmd +31 -1
  2. package/lib/dist/activation/cheatsheet.d.ts +17 -1
  3. package/lib/dist/activation/cheatsheet.d.ts.map +1 -1
  4. package/lib/dist/activation/cheatsheet.js +47 -3
  5. package/lib/dist/activation/cheatsheet.js.map +1 -1
  6. package/lib/dist/activation/hook-output.d.ts +80 -0
  7. package/lib/dist/activation/hook-output.d.ts.map +1 -0
  8. package/lib/dist/activation/hook-output.js +103 -0
  9. package/lib/dist/activation/hook-output.js.map +1 -0
  10. package/lib/dist/activation/search-intercept.d.ts +60 -29
  11. package/lib/dist/activation/search-intercept.d.ts.map +1 -1
  12. package/lib/dist/activation/search-intercept.js +159 -55
  13. package/lib/dist/activation/search-intercept.js.map +1 -1
  14. package/lib/dist/activation/steering.d.ts +8 -10
  15. package/lib/dist/activation/steering.d.ts.map +1 -1
  16. package/lib/dist/activation/steering.js +21 -6
  17. package/lib/dist/activation/steering.js.map +1 -1
  18. package/lib/dist/behaviour/behaviour-surface.d.ts +47 -0
  19. package/lib/dist/behaviour/behaviour-surface.d.ts.map +1 -1
  20. package/lib/dist/behaviour/behaviour-surface.js +108 -2
  21. package/lib/dist/behaviour/behaviour-surface.js.map +1 -1
  22. package/lib/dist/bin/node-version-check.d.ts +22 -7
  23. package/lib/dist/bin/node-version-check.d.ts.map +1 -1
  24. package/lib/dist/bin/node-version-check.js +39 -9
  25. package/lib/dist/bin/node-version-check.js.map +1 -1
  26. package/lib/dist/bin/specship.js +762 -81
  27. package/lib/dist/bin/specship.js.map +1 -1
  28. package/lib/dist/commands/specship/learn.md +22 -0
  29. package/lib/dist/commands/specship/spec.md +12 -0
  30. package/lib/dist/db/sqlite-adapter.d.ts +7 -5
  31. package/lib/dist/db/sqlite-adapter.d.ts.map +1 -1
  32. package/lib/dist/db/sqlite-adapter.js +11 -9
  33. package/lib/dist/db/sqlite-adapter.js.map +1 -1
  34. package/lib/dist/enforce/changed-files.d.ts +11 -0
  35. package/lib/dist/enforce/changed-files.d.ts.map +1 -1
  36. package/lib/dist/enforce/changed-files.js +42 -0
  37. package/lib/dist/enforce/changed-files.js.map +1 -1
  38. package/lib/dist/enforce/enforce.d.ts +25 -1
  39. package/lib/dist/enforce/enforce.d.ts.map +1 -1
  40. package/lib/dist/enforce/enforce.js +58 -3
  41. package/lib/dist/enforce/enforce.js.map +1 -1
  42. package/lib/dist/enforce/mutation.d.ts +46 -0
  43. package/lib/dist/enforce/mutation.d.ts.map +1 -0
  44. package/lib/dist/enforce/mutation.js +104 -0
  45. package/lib/dist/enforce/mutation.js.map +1 -0
  46. package/lib/dist/enforce/suppressions.d.ts +33 -0
  47. package/lib/dist/enforce/suppressions.d.ts.map +1 -0
  48. package/lib/dist/enforce/suppressions.js +159 -0
  49. package/lib/dist/enforce/suppressions.js.map +1 -0
  50. package/lib/dist/extraction/specs/markdown-spec-extractor.d.ts.map +1 -1
  51. package/lib/dist/extraction/specs/markdown-spec-extractor.js +16 -2
  52. package/lib/dist/extraction/specs/markdown-spec-extractor.js.map +1 -1
  53. package/lib/dist/graph/spec-coverage.d.ts +57 -1
  54. package/lib/dist/graph/spec-coverage.d.ts.map +1 -1
  55. package/lib/dist/graph/spec-coverage.js +129 -5
  56. package/lib/dist/graph/spec-coverage.js.map +1 -1
  57. package/lib/dist/health/smoke-check.js +2 -2
  58. package/lib/dist/health/smoke-check.js.map +1 -1
  59. package/lib/dist/index.d.ts +8 -3
  60. package/lib/dist/index.d.ts.map +1 -1
  61. package/lib/dist/index.js +65 -9
  62. package/lib/dist/index.js.map +1 -1
  63. package/lib/dist/installer/gemini-commands.d.ts +107 -0
  64. package/lib/dist/installer/gemini-commands.d.ts.map +1 -0
  65. package/lib/dist/installer/gemini-commands.js +264 -0
  66. package/lib/dist/installer/gemini-commands.js.map +1 -0
  67. package/lib/dist/installer/index.d.ts +23 -1
  68. package/lib/dist/installer/index.d.ts.map +1 -1
  69. package/lib/dist/installer/index.js +22 -3
  70. package/lib/dist/installer/index.js.map +1 -1
  71. package/lib/dist/installer/install-defaults.d.ts +19 -0
  72. package/lib/dist/installer/install-defaults.d.ts.map +1 -1
  73. package/lib/dist/installer/install-defaults.js +28 -0
  74. package/lib/dist/installer/install-defaults.js.map +1 -1
  75. package/lib/dist/installer/instructions-template.d.ts +22 -0
  76. package/lib/dist/installer/instructions-template.d.ts.map +1 -1
  77. package/lib/dist/installer/instructions-template.js +37 -1
  78. package/lib/dist/installer/instructions-template.js.map +1 -1
  79. package/lib/dist/installer/targets/claude.d.ts +4 -0
  80. package/lib/dist/installer/targets/claude.d.ts.map +1 -1
  81. package/lib/dist/installer/targets/claude.js +8 -25
  82. package/lib/dist/installer/targets/claude.js.map +1 -1
  83. package/lib/dist/installer/targets/gemini.d.ts +85 -12
  84. package/lib/dist/installer/targets/gemini.d.ts.map +1 -1
  85. package/lib/dist/installer/targets/gemini.js +527 -30
  86. package/lib/dist/installer/targets/gemini.js.map +1 -1
  87. package/lib/dist/installer/targets/shared.d.ts +13 -0
  88. package/lib/dist/installer/targets/shared.d.ts.map +1 -1
  89. package/lib/dist/installer/targets/shared.js +18 -0
  90. package/lib/dist/installer/targets/shared.js.map +1 -1
  91. package/lib/dist/installer/targets/types.d.ts +12 -0
  92. package/lib/dist/installer/targets/types.d.ts.map +1 -1
  93. package/lib/dist/jira/auto-publish.d.ts +71 -4
  94. package/lib/dist/jira/auto-publish.d.ts.map +1 -1
  95. package/lib/dist/jira/auto-publish.js +186 -17
  96. package/lib/dist/jira/auto-publish.js.map +1 -1
  97. package/lib/dist/jira/reconcile.d.ts +24 -1
  98. package/lib/dist/jira/reconcile.d.ts.map +1 -1
  99. package/lib/dist/jira/reconcile.js +46 -2
  100. package/lib/dist/jira/reconcile.js.map +1 -1
  101. package/lib/dist/jira/repo-config.d.ts +9 -0
  102. package/lib/dist/jira/repo-config.d.ts.map +1 -1
  103. package/lib/dist/jira/repo-config.js +11 -0
  104. package/lib/dist/jira/repo-config.js.map +1 -1
  105. package/lib/dist/jira/types.d.ts +7 -0
  106. package/lib/dist/jira/types.d.ts.map +1 -1
  107. package/lib/dist/jira/types.js.map +1 -1
  108. package/lib/dist/knowledge/enforce.d.ts +75 -0
  109. package/lib/dist/knowledge/enforce.d.ts.map +1 -0
  110. package/lib/dist/knowledge/enforce.js +250 -0
  111. package/lib/dist/knowledge/enforce.js.map +1 -0
  112. package/lib/dist/knowledge/facts.d.ts +33 -0
  113. package/lib/dist/knowledge/facts.d.ts.map +1 -0
  114. package/lib/dist/knowledge/facts.js +117 -0
  115. package/lib/dist/knowledge/facts.js.map +1 -0
  116. package/lib/dist/knowledge/proposals.d.ts +88 -0
  117. package/lib/dist/knowledge/proposals.d.ts.map +1 -0
  118. package/lib/dist/knowledge/proposals.js +360 -0
  119. package/lib/dist/knowledge/proposals.js.map +1 -0
  120. package/lib/dist/knowledge/stale.d.ts +64 -0
  121. package/lib/dist/knowledge/stale.d.ts.map +1 -0
  122. package/lib/dist/knowledge/stale.js +174 -0
  123. package/lib/dist/knowledge/stale.js.map +1 -0
  124. package/lib/dist/mcp/gemini-session.d.ts +50 -0
  125. package/lib/dist/mcp/gemini-session.d.ts.map +1 -0
  126. package/lib/dist/mcp/gemini-session.js +159 -0
  127. package/lib/dist/mcp/gemini-session.js.map +1 -0
  128. package/lib/dist/mcp/jira-tools.d.ts.map +1 -1
  129. package/lib/dist/mcp/jira-tools.js +25 -0
  130. package/lib/dist/mcp/jira-tools.js.map +1 -1
  131. package/lib/dist/mcp/model-context.d.ts +22 -9
  132. package/lib/dist/mcp/model-context.d.ts.map +1 -1
  133. package/lib/dist/mcp/model-context.js +35 -13
  134. package/lib/dist/mcp/model-context.js.map +1 -1
  135. package/lib/dist/mcp/proxy.js +1 -1
  136. package/lib/dist/mcp/proxy.js.map +1 -1
  137. package/lib/dist/mcp/server-instructions.d.ts +16 -15
  138. package/lib/dist/mcp/server-instructions.d.ts.map +1 -1
  139. package/lib/dist/mcp/server-instructions.js +67 -1
  140. package/lib/dist/mcp/server-instructions.js.map +1 -1
  141. package/lib/dist/mcp/session.js +1 -1
  142. package/lib/dist/mcp/session.js.map +1 -1
  143. package/lib/dist/mcp/spec-tools.d.ts +9 -1
  144. package/lib/dist/mcp/spec-tools.d.ts.map +1 -1
  145. package/lib/dist/mcp/spec-tools.js +69 -21
  146. package/lib/dist/mcp/spec-tools.js.map +1 -1
  147. package/lib/dist/mcp/tools.d.ts +37 -1
  148. package/lib/dist/mcp/tools.d.ts.map +1 -1
  149. package/lib/dist/mcp/tools.js +120 -9
  150. package/lib/dist/mcp/tools.js.map +1 -1
  151. package/lib/dist/pulse/pulse.d.ts +93 -0
  152. package/lib/dist/pulse/pulse.d.ts.map +1 -0
  153. package/lib/dist/pulse/pulse.js +401 -0
  154. package/lib/dist/pulse/pulse.js.map +1 -0
  155. package/lib/dist/reflect/apply.d.ts.map +1 -1
  156. package/lib/dist/reflect/apply.js +38 -3
  157. package/lib/dist/reflect/apply.js.map +1 -1
  158. package/lib/dist/reflect/auto-sweep.d.ts +26 -0
  159. package/lib/dist/reflect/auto-sweep.d.ts.map +1 -0
  160. package/lib/dist/reflect/auto-sweep.js +90 -0
  161. package/lib/dist/reflect/auto-sweep.js.map +1 -0
  162. package/lib/dist/reflect/cli.d.ts +62 -0
  163. package/lib/dist/reflect/cli.d.ts.map +1 -0
  164. package/lib/dist/reflect/cli.js +163 -0
  165. package/lib/dist/reflect/cli.js.map +1 -0
  166. package/lib/dist/reflect/miner.d.ts.map +1 -1
  167. package/lib/dist/reflect/miner.js +119 -0
  168. package/lib/dist/reflect/miner.js.map +1 -1
  169. package/lib/dist/reflect/sweep.d.ts +1 -0
  170. package/lib/dist/reflect/sweep.d.ts.map +1 -1
  171. package/lib/dist/reflect/sweep.js +62 -13
  172. package/lib/dist/reflect/sweep.js.map +1 -1
  173. package/lib/dist/reflect/targets.d.ts +2 -0
  174. package/lib/dist/reflect/targets.d.ts.map +1 -1
  175. package/lib/dist/reflect/targets.js +33 -0
  176. package/lib/dist/reflect/targets.js.map +1 -1
  177. package/lib/dist/reflect/types.d.ts +19 -2
  178. package/lib/dist/reflect/types.d.ts.map +1 -1
  179. package/lib/dist/resolution/test-title-links.d.ts.map +1 -1
  180. package/lib/dist/resolution/test-title-links.js +3 -14
  181. package/lib/dist/resolution/test-title-links.js.map +1 -1
  182. package/lib/dist/server/routes/claude.js +15 -7
  183. package/lib/dist/server/routes/knowledge.js +118 -0
  184. package/lib/dist/server/server.js +2 -0
  185. package/lib/dist/spec-lint/lint.d.ts +1 -1
  186. package/lib/dist/spec-lint/lint.d.ts.map +1 -1
  187. package/lib/dist/spec-lint/lint.js +63 -2
  188. package/lib/dist/spec-lint/lint.js.map +1 -1
  189. package/lib/dist/spec-quality/criterion-ids.d.ts +13 -0
  190. package/lib/dist/spec-quality/criterion-ids.d.ts.map +1 -0
  191. package/lib/dist/spec-quality/criterion-ids.js +38 -0
  192. package/lib/dist/spec-quality/criterion-ids.js.map +1 -0
  193. package/lib/dist/spec-quality/evidence-kind.d.ts +54 -0
  194. package/lib/dist/spec-quality/evidence-kind.d.ts.map +1 -0
  195. package/lib/dist/spec-quality/evidence-kind.js +183 -0
  196. package/lib/dist/spec-quality/evidence-kind.js.map +1 -0
  197. package/lib/dist/spec-quality/link-persist.d.ts +65 -0
  198. package/lib/dist/spec-quality/link-persist.d.ts.map +1 -0
  199. package/lib/dist/spec-quality/link-persist.js +249 -0
  200. package/lib/dist/spec-quality/link-persist.js.map +1 -0
  201. package/lib/dist/spec-quality/plan-scope.d.ts +38 -0
  202. package/lib/dist/spec-quality/plan-scope.d.ts.map +1 -0
  203. package/lib/dist/spec-quality/plan-scope.js +129 -0
  204. package/lib/dist/spec-quality/plan-scope.js.map +1 -0
  205. package/lib/dist/spec-quality/postcheck.d.ts +85 -0
  206. package/lib/dist/spec-quality/postcheck.d.ts.map +1 -0
  207. package/lib/dist/spec-quality/postcheck.js +390 -0
  208. package/lib/dist/spec-quality/postcheck.js.map +1 -0
  209. package/lib/dist/spec-quality/readiness.d.ts +72 -0
  210. package/lib/dist/spec-quality/readiness.d.ts.map +1 -0
  211. package/lib/dist/spec-quality/readiness.js +226 -0
  212. package/lib/dist/spec-quality/readiness.js.map +1 -0
  213. package/lib/dist/workflows/agents/claude.d.ts +16 -0
  214. package/lib/dist/workflows/agents/claude.d.ts.map +1 -0
  215. package/lib/dist/workflows/agents/claude.js +82 -0
  216. package/lib/dist/workflows/agents/claude.js.map +1 -0
  217. package/lib/dist/workflows/agents/gemini.d.ts +21 -0
  218. package/lib/dist/workflows/agents/gemini.d.ts.map +1 -0
  219. package/lib/dist/workflows/agents/gemini.js +124 -0
  220. package/lib/dist/workflows/agents/gemini.js.map +1 -0
  221. package/lib/dist/workflows/agents/index.d.ts +28 -0
  222. package/lib/dist/workflows/agents/index.d.ts.map +1 -0
  223. package/lib/dist/workflows/agents/index.js +104 -0
  224. package/lib/dist/workflows/agents/index.js.map +1 -0
  225. package/lib/dist/workflows/agents/types.d.ts +55 -0
  226. package/lib/dist/workflows/agents/types.d.ts.map +1 -0
  227. package/lib/dist/workflows/agents/types.js +46 -0
  228. package/lib/dist/workflows/agents/types.js.map +1 -0
  229. package/lib/dist/workflows/batch.d.ts +63 -0
  230. package/lib/dist/workflows/batch.d.ts.map +1 -0
  231. package/lib/dist/workflows/batch.js +151 -0
  232. package/lib/dist/workflows/batch.js.map +1 -0
  233. package/lib/dist/workflows/defaults/claude-design-implement.yaml +3 -4
  234. package/lib/dist/workflows/defaults/spec-author.yaml +11 -9
  235. package/lib/dist/workflows/defaults/spec-implement-mixed.yaml +21 -436
  236. package/lib/dist/workflows/defaults/spec-implement.yaml +465 -46
  237. package/lib/dist/workflows/discovery.d.ts +13 -0
  238. package/lib/dist/workflows/discovery.d.ts.map +1 -1
  239. package/lib/dist/workflows/discovery.js +79 -17
  240. package/lib/dist/workflows/discovery.js.map +1 -1
  241. package/lib/dist/workflows/executor.d.ts +18 -0
  242. package/lib/dist/workflows/executor.d.ts.map +1 -1
  243. package/lib/dist/workflows/executor.js +130 -33
  244. package/lib/dist/workflows/executor.js.map +1 -1
  245. package/lib/dist/workflows/gc.d.ts +50 -0
  246. package/lib/dist/workflows/gc.d.ts.map +1 -0
  247. package/lib/dist/workflows/gc.js +120 -0
  248. package/lib/dist/workflows/gc.js.map +1 -0
  249. package/lib/dist/workflows/merge-queue.d.ts +64 -0
  250. package/lib/dist/workflows/merge-queue.d.ts.map +1 -0
  251. package/lib/dist/workflows/merge-queue.js +162 -0
  252. package/lib/dist/workflows/merge-queue.js.map +1 -0
  253. package/lib/dist/workflows/runners/approval.d.ts +1 -1
  254. package/lib/dist/workflows/runners/approval.d.ts.map +1 -1
  255. package/lib/dist/workflows/runners/approval.js +11 -2
  256. package/lib/dist/workflows/runners/approval.js.map +1 -1
  257. package/lib/dist/workflows/runners/bash.d.ts +15 -0
  258. package/lib/dist/workflows/runners/bash.d.ts.map +1 -1
  259. package/lib/dist/workflows/runners/bash.js +50 -1
  260. package/lib/dist/workflows/runners/bash.js.map +1 -1
  261. package/lib/dist/workflows/runners/prompt.d.ts +16 -41
  262. package/lib/dist/workflows/runners/prompt.d.ts.map +1 -1
  263. package/lib/dist/workflows/runners/prompt.js +55 -120
  264. package/lib/dist/workflows/runners/prompt.js.map +1 -1
  265. package/lib/dist/workflows/runners/types.d.ts +12 -0
  266. package/lib/dist/workflows/runners/types.d.ts.map +1 -1
  267. package/lib/dist/workflows/schemas/workflow.d.ts +17 -0
  268. package/lib/dist/workflows/schemas/workflow.d.ts.map +1 -1
  269. package/lib/dist/workflows/schemas/workflow.js +27 -0
  270. package/lib/dist/workflows/schemas/workflow.js.map +1 -1
  271. package/lib/node_modules/.package-lock.json +1 -1
  272. package/lib/package.json +2 -2
  273. package/package.json +5 -3
  274. package/node.exe +0 -4
@@ -1,440 +1,25 @@
1
1
  name: spec-implement-mixed
2
2
  description: Implement a spec with mixed models — sonnet plans, haiku executes, tests + gates verify. Same steps and gates as spec-implement at a fraction of the token cost.
3
3
  tags: [spec, default, mixed-model]
4
- requires: [specship, git]
5
4
 
6
- worktree:
7
- enabled: true
8
-
9
- inputs:
10
- - name: SPEC_ID
11
- description: The spec ID to implement (e.g. REQ-AUTH-005)
12
- required: true
13
-
14
- systemPromptAppend: |
15
- You are implementing a specific requirement. Before editing code, call
16
- specship_spec($INPUT.SPEC_ID) to see the spec body and any code it
17
- already links to. After editing, call specship_link_assert with the
18
- spec_id and the symbol you implemented BEFORE reporting done.
19
-
20
- nodes:
21
- - id: fetch_spec
22
- # MIXMODEL-DOC: mechanical step → haiku
23
- model: haiku
24
- kind: prompt
25
- output_type: spec_summary
26
- allowed_tools:
27
- - mcp__specship__specship_spec
28
- - mcp__specship__specship_explore
29
- prompt: |
30
- Spec ID: $INPUT.SPEC_ID
31
-
32
- Call specship_spec to fetch the spec. Then call specship_explore on
33
- a small bag of terms drawn from the spec title and acceptance
34
- criteria to find the relevant code area.
35
-
36
- Output: a short summary (≤300 words) of (a) what the spec asks for,
37
- (b) which code areas / symbols are most relevant, and (c) whether
38
- any code currently claims to implement it (look at linked_code).
39
-
40
- - id: plan
41
- # MIXMODEL-DOC: judgment step → sonnet
42
- model: sonnet
43
- kind: prompt
44
- depends_on: [fetch_spec]
45
- output_type: plan
46
- allowed_tools:
47
- - mcp__specship__specship_explore
48
- - mcp__specship__specship_node
49
- - mcp__specship__specship_spec
50
- - Read
51
- prompt: |
52
- Based on this spec summary, write a concrete implementation plan:
53
-
54
- $fetch_spec.output
55
-
56
- The plan should list:
57
- - Files to create or modify (with project-relative paths)
58
- - Specific functions/methods/classes to add or change
59
- - Tests to add or update
60
- - Order of changes
61
-
62
- Keep it tight (≤500 words). Do NOT edit code in this step.
63
-
64
- - id: approve_plan
65
- kind: approval
66
- depends_on: [plan]
67
- message: |
68
- Plan ready for $INPUT.SPEC_ID. Review the plan output and approve
69
- to proceed with implementation, or reject with feedback to revise.
70
- capture_response: true
71
- on_reject:
72
- prompt: |
73
- The plan was rejected with this feedback. Revise:
74
-
75
- $approve_plan.output
76
- max_attempts: 3
77
-
78
- - id: implement
79
- # MIXMODEL-DOC: mechanical step → haiku
80
- model: haiku
81
- kind: prompt
82
- depends_on: [approve_plan]
83
- output_type: diff
84
- allowed_tools:
85
- - Read
86
- - Edit
87
- - Write
88
- - Bash
89
- - mcp__specship__specship_explore
90
- - mcp__specship__specship_node
91
- - mcp__specship__specship_spec
92
- prompt: |
93
- Implement the approved plan. Follow it closely.
94
-
95
- Plan:
96
- $plan.output
97
-
98
- Approval feedback (if any):
99
- $approve_plan.output
100
-
101
- When done, output a short diff summary (which files changed and why).
102
-
103
- - id: quality_gate
104
- kind: bash
105
- depends_on: [implement]
106
- output_type: quality_report
107
- timeout: 600000
108
- bash: |
109
- # REQ-AUTHG-005.A1 — the project's own lint/typecheck, run in the
110
- # worktree right after implement. The QUALITY_GATE marker is the
111
- # contract the remediation node routes on: a project with neither a lint
112
- # script nor a typecheck config says so explicitly, so "nothing ran" can
113
- # never be mistaken for "clean" (same doctrine as VERIFY_RESULT=skipped).
114
- QUALITY_CMD=""
115
- if [ -f package.json ]; then
116
- # The worktree may not have dependencies yet (verify installs them
117
- # later) and lint needs them — bootstrap quietly, and treat a failed
118
- # install as "no gate" rather than as a lint failure.
119
- if [ ! -d node_modules ]; then
120
- npm ci --no-audit --no-fund >/dev/null 2>&1 || npm install --no-audit --no-fund >/dev/null 2>&1 || true
121
- fi
122
- if node -e 'const s=(require("./package.json").scripts)||{};process.exit(s.lint?0:1)' 2>/dev/null; then
123
- QUALITY_CMD="npm run lint --if-present"
124
- elif [ -f tsconfig.json ]; then
125
- QUALITY_CMD="npx --no-install tsc --noEmit"
126
- fi
127
- elif [ -f Cargo.toml ]; then
128
- if command -v cargo >/dev/null 2>&1; then QUALITY_CMD="cargo clippy --no-deps"; fi
129
- elif [ -f pyproject.toml ] || [ -f requirements.txt ]; then
130
- if command -v ruff >/dev/null 2>&1; then QUALITY_CMD="ruff check ."; fi
131
- fi
132
- if [ -z "$QUALITY_CMD" ]; then
133
- echo "QUALITY_GATE=skipped"
134
- echo "QUALITY_REASON=no lint script and no typecheck configuration in this project"
135
- exit 0
136
- fi
137
- echo "QUALITY_CMD=$QUALITY_CMD"
138
- if OUT=$($QUALITY_CMD 2>&1); then
139
- echo "QUALITY_GATE=passed"
140
- else
141
- echo "QUALITY_GATE=failed"
142
- printf '%s\n' "$OUT" | tail -n 80
143
- fi
144
- # Exiting 0 on a lint failure is deliberate: the marker — not this node's
145
- # exit code — drives the revise loop. quality_recheck is what halts.
146
-
147
- - id: fix_quality
148
- # MIXMODEL-DOC: mechanical step (fix what the linter named) → haiku
149
- model: haiku
150
- kind: prompt
151
- depends_on: [quality_gate]
152
- output_type: quality_fix
153
- allowed_tools:
154
- - Read
155
- - Edit
156
- - Write
157
- - Bash
158
- - mcp__specship__specship_explore
159
- - mcp__specship__specship_node
160
- prompt: |
161
- Lint / typecheck result for the code you just wrote:
162
-
163
- $quality_gate.output
164
-
165
- Route on the QUALITY_GATE marker — do not re-judge the raw output:
166
-
167
- - QUALITY_GATE=passed or QUALITY_GATE=skipped → change NOTHING. Output
168
- exactly `FIX_QUALITY=not-needed` and stop.
169
- - QUALITY_GATE=failed → fix every reported error, then re-run the
170
- QUALITY_CMD shown above to confirm. Fix the code, never the lint
171
- configuration; never silence or disable a rule to make it pass.
172
-
173
- Output `FIX_QUALITY=fixed` (clean re-run) or `FIX_QUALITY=still-failing`
174
- followed by the errors that remain.
175
-
176
- - id: quality_recheck
177
- kind: bash
178
- depends_on: [fix_quality]
179
- output_type: quality_result
180
- timeout: 600000
181
- bash: |
182
- # REQ-AUTHG-005.A1 — the authoritative half of the gate. The fix node is
183
- # a prompt, so its "FIX_QUALITY=fixed" claim is a claim, not evidence:
184
- # this node re-runs the same command and halts the run while it still
185
- # fails, so failing lint/typecheck never reaches verify, the link node,
186
- # or the human gate.
187
- GATE_OUT=$quality_gate.output
188
- MARKER=$(printf '%s' "$GATE_OUT" | grep -oE 'QUALITY_GATE=[a-z-]+' | tail -n 1 | cut -d= -f2)
189
- CMD=$(printf '%s' "$GATE_OUT" | grep -E '^QUALITY_CMD=' | tail -n 1 | cut -d= -f2-)
190
- if [ "$MARKER" = "skipped" ] || [ -z "$CMD" ]; then
191
- echo "QUALITY_RESULT=skipped"
192
- echo "This project has no lint or typecheck gate — nothing was checked."
193
- exit 0
194
- fi
195
- if OUT=$($CMD 2>&1); then
196
- echo "QUALITY_RESULT=clean"
197
- exit 0
198
- fi
199
- echo "QUALITY_RESULT=failed"
200
- printf '%s\n' "$OUT" | tail -n 80
201
- echo "HALT_CAUSE=lint/typecheck still fails after the fix attempt — the change is not reviewable yet"
202
- exit 1
203
-
204
- - id: diff
205
- kind: bash
206
- depends_on: [quality_recheck]
207
- output_type: diff
208
- bash: |
209
- # REQ-AUTHG-004.A1 — the full diff, from git, into a run artifact. The
210
- # human gate and the adversarial reviewer read THIS; the implement node's
211
- # prose about what it believes it changed is not the change.
212
- # `git add -A -N` registers new files as intent-to-add so untracked work
213
- # appears in `git diff HEAD` without staging any content.
214
- git add -A -N >/dev/null 2>&1 || true
215
- echo "DIFF_BEGIN"
216
- git --no-pager diff HEAD | head -c 400000
217
- echo
218
- echo "DIFF_END"
219
-
220
- - id: diff_stat
221
- kind: bash
222
- depends_on: [diff]
223
- output_type: diff_stat
224
- bash: |
225
- # REQ-AUTHG-004.A2 — the stat block the final gate shows: file names and
226
- # insertions/deletions counted by git. Its own small node so the approval
227
- # message carries the summary while the full diff stays in the `diff`
228
- # artifact.
229
- echo "DIFF_STAT_BEGIN"
230
- git --no-pager diff HEAD --stat
231
- echo "DIFF_STAT_END"
232
-
233
- - id: verify
234
- kind: bash
235
- depends_on: [diff_stat]
236
- output_type: test_results
237
- timeout: 600000
238
- bash: |
239
- # Run the project's test suite. The verify node's exit code drives
240
- # the gating for the link node — non-zero halts the workflow.
241
- # The VERIFY_RESULT marker is the machine-readable contract the link
242
- # node routes on (REQ-IMPLINT-001.A1): a skipped run must never be
243
- # mistaken for a passing one.
244
- # Install and build failures fail fast with their own markers
245
- # (REQ-REVINT-006.A1) — a broken environment or a build break is NOT a
246
- # test failure, and must never be attributed to one.
247
- if [ -f package.json ]; then
248
- # A fresh worktree has no node_modules/ or build output — a verify
249
- # failure must mean the tests failed, not that the environment was
250
- # missing (WF-REJECT-DOC, REQ-WFREJ-005).
251
- if [ ! -d node_modules ]; then
252
- if ! { npm ci --no-audit --no-fund || npm install --no-audit --no-fund; }; then
253
- echo "VERIFY_RESULT=env-failed"; exit 1
254
- fi
255
- fi
256
- if ! npm run build --if-present; then echo "VERIFY_RESULT=build-failed"; exit 1; fi
257
- if npm test; then echo "VERIFY_RESULT=ran-and-passed"; else echo "VERIFY_RESULT=ran-and-failed"; exit 1; fi
258
- elif [ -f Cargo.toml ]; then
259
- if ! cargo build; then echo "VERIFY_RESULT=build-failed"; exit 1; fi
260
- if cargo test; then echo "VERIFY_RESULT=ran-and-passed"; else echo "VERIFY_RESULT=ran-and-failed"; exit 1; fi
261
- elif [ -f pyproject.toml ] || [ -f requirements.txt ]; then
262
- if ! python -c 'import pytest' 2>/dev/null; then echo "VERIFY_RESULT=env-failed"; exit 1; fi
263
- if python -m pytest; then echo "VERIFY_RESULT=ran-and-passed"; else echo "VERIFY_RESULT=ran-and-failed"; exit 1; fi
264
- else
265
- echo "no recognised test framework; tests did NOT run"
266
- echo "VERIFY_RESULT=skipped"
267
- fi
268
-
269
- - id: route_verify
270
- kind: bash
271
- depends_on: [verify]
272
- output_type: verify_route
273
- bash: |
274
- # Deterministic verify routing (REQ-VSTATE-005.A1): the VERIFY_RESULT
275
- # marker is parsed HERE, in code, and turned into a LINK_ACTION the link
276
- # node obeys. It used to be a prompt reading a test log — the one decision
277
- # that governs whether links may be promoted was hallucinable.
278
- VERIFY_OUT=$verify.output
279
- MARKER=$(printf '%s' "$VERIFY_OUT" | grep -oE 'VERIFY_RESULT=[a-z-]+' | tail -n 1 | cut -d= -f2)
280
- [ -n "$MARKER" ] || MARKER=missing
281
- echo "VERIFY_RESULT=$MARKER"
282
- # env-failed / build-failed halt BEFORE any link mutation, naming the
283
- # environment cause (REQ-VSTATE-005.A3) — neither is a test failure.
284
- case "$MARKER" in
285
- ran-and-passed)
286
- echo "LINK_ACTION=assert-and-verify-pass" ;;
287
- ran-and-failed)
288
- echo "LINK_ACTION=assert-and-verify-fail" ;;
289
- skipped)
290
- echo "LINK_ACTION=assert-only" ;;
291
- env-failed)
292
- echo "HALT_CAUSE=environment setup failed (dependency install) — nothing is known about the tests"
293
- exit 1 ;;
294
- build-failed)
295
- echo "HALT_CAUSE=build failed — nothing is known about the tests"
296
- exit 1 ;;
297
- *)
298
- echo "HALT_CAUSE=no VERIFY_RESULT marker found in the verify output — an unknown result is never a pass"
299
- exit 1 ;;
300
- esac
301
-
302
- - id: link
303
- # MIXMODEL-DOC: mechanical step → haiku
304
- model: haiku
305
- kind: prompt
306
- depends_on: [route_verify]
307
- output_type: link_summary
308
- allowed_tools:
309
- - mcp__specship__specship_link_assert
310
- - mcp__specship__specship_link_verify
311
- - mcp__specship__specship_spec
312
- prompt: |
313
- Assert spec→code links for the changes made in the implement step.
314
- For each symbol that implements $INPUT.SPEC_ID (or its child
315
- requirements), call specship_link_assert with the spec_id, the
316
- file path, and the qualified symbol name.
317
-
318
- You MUST NOT assert a `tests`-kind link (REQ-REVINT-005.A1). Every
319
- specship_link_assert call here is an implementation link — leave `kind`
320
- at its default and never pass kind: 'tests'. Test evidence is
321
- file-derived only: it comes from the spec's `verifies:` block or an
322
- `@verifies` comment on the test symbol, never from this node. A workflow
323
- that minted its own test evidence would be promoting itself past the
324
- gate that exists to check it.
325
-
326
- Then act on LINK_ACTION, which a bash node already computed from the
327
- VERIFY_RESULT marker (REQ-VSTATE-005.A1). Do NOT re-derive it from the
328
- test log — read it:
329
-
330
- $route_verify.output
331
-
332
- - LINK_ACTION=assert-and-verify-pass → after each assert, call
333
- specship_link_verify with result="pass".
334
- - LINK_ACTION=assert-and-verify-fail → call specship_link_verify with
335
- result="fail" and the failing test name as the reason.
336
- - LINK_ACTION=assert-only → do NOT call specship_link_verify at all;
337
- the links stay in the `implemented` state. Tests that did not run
338
- are never reported as passing.
339
-
340
- A run whose environment or build broke never reaches this node — the
341
- routing step halts it first (REQ-VSTATE-005.A3).
342
-
343
- Implementation diff summary:
344
- $implement.output
345
-
346
- Test results:
347
- $verify.output
348
-
349
- Output: a short list of "spec_id → file:symbol [verified|implemented]"
350
- lines, ending with one line stating whether verification ran or was
351
- skipped.
352
-
353
- - id: coverage
354
- kind: bash
355
- depends_on: [link]
356
- output_type: coverage_summary
357
- bash: |
358
- # The acceptance-criteria coverage line is computed FROM THE DB
359
- # (REQ-VSTATE-005.A2) — `specship coverage --line` renders the same
360
- # `getSpecCoverage` report the MCP tool and the dashboard read, so the
361
- # number on the approval gate cannot disagree with them. It used to be
362
- # counted by a prompt.
363
- if command -v specship >/dev/null 2>&1; then SS=specship
364
- elif [ -x node_modules/.bin/specship ]; then SS=node_modules/.bin/specship
365
- elif [ -x dist/bin/specship.js ]; then SS="node dist/bin/specship.js"
366
- else SS=""; fi
367
- if [ -z "$SS" ]; then
368
- echo "COVERAGE_UNAVAILABLE=specship CLI not found — acceptance-criteria coverage was NOT computed"
369
- exit 0
370
- fi
371
- LINE=$($SS coverage $INPUT.SPEC_ID --line) || {
372
- echo "COVERAGE_UNAVAILABLE=specship coverage failed — coverage was NOT computed"
373
- exit 0
374
- }
375
- echo "$LINE"
376
- N=$(printf '%s' "$LINE" | awk '{print $1}')
377
- M=$(printf '%s' "$LINE" | awk '{print $3}')
378
- if [ "$N" != "$M" ]; then
379
- echo "Close the gap with /specship:spec behaviour $INPUT.SPEC_ID."
380
- fi
381
-
382
- - id: adversarial_review
383
- # MIXMODEL-DOC: judgment step (does this diff satisfy the spec?) → sonnet
384
- model: sonnet
385
- kind: prompt
386
- depends_on: [coverage]
387
- output_type: adversarial_review
388
- allowed_tools:
389
- - Read
390
- - Grep
391
- - mcp__specship__specship_spec
392
- - mcp__specship__specship_explore
393
- - mcp__specship__specship_node
394
- - mcp__specship__specship_search
395
- prompt: |
396
- Adversarial review (REQ-AUTHG-005.A3). You are NOT the implementer — your
397
- job is to find what the implementation missed. This node is read-only:
398
- you have no Edit, Write or Bash tool and must not try to fix anything.
399
-
400
- Call specship_spec($INPUT.SPEC_ID) and read the spec body, including
401
- every acceptance criterion.
402
-
403
- The change under review (from git, not from the implementer's summary):
404
-
405
- $diff.output
406
-
407
- Report this and nothing else:
408
-
409
- 1. One line per acceptance criterion:
410
- `<AC id>: satisfied | partial | unaddressed — <one sentence, grounded
411
- in the diff>`. Judge from the diff and the code you read; "the
412
- implementer said so" is not evidence.
413
- 2. `Untested new code paths:` the branches/functions this diff adds that
414
- no test in the diff exercises (`none` if there are none).
415
- 3. `Verdict:` one line — the most serious gap a reviewer should look at
416
- first, or `no gaps found`.
417
-
418
- - id: final_review
419
- kind: approval
420
- depends_on: [adversarial_review]
421
- message: |
422
- Implementation complete for $INPUT.SPEC_ID.
423
-
424
- Changes (git diff --stat — measured, not summarized):
425
- $diff_stat.output
426
-
427
- Lint / typecheck:
428
- $quality_recheck.output
429
-
430
- Links asserted:
431
- $link.output
432
-
433
- Acceptance-criteria test coverage:
434
- $coverage.output
435
-
436
- Adversarial review:
437
- $adversarial_review.output
438
-
439
- Approve to finalize the run (worktree is left for you to inspect
440
- and merge), or reject to abandon.
5
+ # THROUGHPUT-DOC, REQ-THRU-004 — one source of truth for the implement
6
+ # pipeline. This variant inherits every node, gate and prompt from
7
+ # spec-implement and states only what differs: which model runs each step
8
+ # (MIXMODEL-DOC). Judgment steps are pinned up (sonnet); mechanical steps are
9
+ # pinned down (haiku); bash gates, approvals, verify, routing and coverage are
10
+ # model-free and identical by construction.
11
+ extends: spec-implement
12
+
13
+ node_overrides:
14
+ fetch_spec:
15
+ model: haiku # mechanical: read the spec and summarize
16
+ plan:
17
+ model: sonnet # judgment: the plan the human approves
18
+ implement:
19
+ model: haiku # mechanical: execute the approved plan
20
+ fix_quality:
21
+ model: haiku # mechanical: fix what the linter named
22
+ link:
23
+ model: haiku # mechanical: record implementations bullets
24
+ adversarial_review:
25
+ model: sonnet # judgment: try to break the change