@specship/specship-win32-arm64 0.24.0 → 0.25.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 (139) hide show
  1. package/lib/dist/activation/steering.d.ts +4 -4
  2. package/lib/dist/activation/steering.d.ts.map +1 -1
  3. package/lib/dist/activation/steering.js +6 -6
  4. package/lib/dist/activation/steering.js.map +1 -1
  5. package/lib/dist/bin/specship.js +232 -40
  6. package/lib/dist/bin/specship.js.map +1 -1
  7. package/lib/dist/commands/specship/learn.md +5 -3
  8. package/lib/dist/commands/specship/spec.md +73 -15
  9. package/lib/dist/db/spec-queries.d.ts +73 -3
  10. package/lib/dist/db/spec-queries.d.ts.map +1 -1
  11. package/lib/dist/db/spec-queries.js +139 -5
  12. package/lib/dist/db/spec-queries.js.map +1 -1
  13. package/lib/dist/enforce/changed-files.d.ts +28 -0
  14. package/lib/dist/enforce/changed-files.d.ts.map +1 -0
  15. package/lib/dist/enforce/changed-files.js +72 -0
  16. package/lib/dist/enforce/changed-files.js.map +1 -0
  17. package/lib/dist/enforce/enforce.d.ts +28 -1
  18. package/lib/dist/enforce/enforce.d.ts.map +1 -1
  19. package/lib/dist/enforce/enforce.js +37 -5
  20. package/lib/dist/enforce/enforce.js.map +1 -1
  21. package/lib/dist/extraction/grammars.d.ts +10 -0
  22. package/lib/dist/extraction/grammars.d.ts.map +1 -1
  23. package/lib/dist/extraction/grammars.js +32 -3
  24. package/lib/dist/extraction/grammars.js.map +1 -1
  25. package/lib/dist/extraction/index.d.ts +7 -0
  26. package/lib/dist/extraction/index.d.ts.map +1 -1
  27. package/lib/dist/extraction/index.js.map +1 -1
  28. package/lib/dist/extraction/specs/markdown-spec-extractor.d.ts +7 -0
  29. package/lib/dist/extraction/specs/markdown-spec-extractor.d.ts.map +1 -1
  30. package/lib/dist/extraction/specs/markdown-spec-extractor.js +81 -8
  31. package/lib/dist/extraction/specs/markdown-spec-extractor.js.map +1 -1
  32. package/lib/dist/extraction/wasm/tree-sitter-pascal.wasm.gz +0 -0
  33. package/lib/dist/extraction/wasm/tree-sitter-scala.wasm.gz +0 -0
  34. package/lib/dist/graph/spec-coverage.d.ts +86 -0
  35. package/lib/dist/graph/spec-coverage.d.ts.map +1 -0
  36. package/lib/dist/graph/spec-coverage.js +152 -0
  37. package/lib/dist/graph/spec-coverage.js.map +1 -0
  38. package/lib/dist/index.d.ts +69 -6
  39. package/lib/dist/index.d.ts.map +1 -1
  40. package/lib/dist/index.js +133 -21
  41. package/lib/dist/index.js.map +1 -1
  42. package/lib/dist/installer/index.d.ts +33 -8
  43. package/lib/dist/installer/index.d.ts.map +1 -1
  44. package/lib/dist/installer/index.js +50 -50
  45. package/lib/dist/installer/index.js.map +1 -1
  46. package/lib/dist/installer/init-offer.d.ts +14 -9
  47. package/lib/dist/installer/init-offer.d.ts.map +1 -1
  48. package/lib/dist/installer/init-offer.js +13 -9
  49. package/lib/dist/installer/init-offer.js.map +1 -1
  50. package/lib/dist/installer/install-defaults.d.ts +62 -0
  51. package/lib/dist/installer/install-defaults.d.ts.map +1 -0
  52. package/lib/dist/installer/install-defaults.js +67 -0
  53. package/lib/dist/installer/install-defaults.js.map +1 -0
  54. package/lib/dist/installer/targets/claude.d.ts +14 -0
  55. package/lib/dist/installer/targets/claude.d.ts.map +1 -1
  56. package/lib/dist/installer/targets/claude.js +64 -0
  57. package/lib/dist/installer/targets/claude.js.map +1 -1
  58. package/lib/dist/installer/targets/shared.js +4 -4
  59. package/lib/dist/installer/targets/shared.js.map +1 -1
  60. package/lib/dist/mcp/fitness-tool.d.ts +5 -6
  61. package/lib/dist/mcp/fitness-tool.d.ts.map +1 -1
  62. package/lib/dist/mcp/fitness-tool.js +0 -16
  63. package/lib/dist/mcp/fitness-tool.js.map +1 -1
  64. package/lib/dist/mcp/health-tool.d.ts +26 -0
  65. package/lib/dist/mcp/health-tool.d.ts.map +1 -0
  66. package/lib/dist/mcp/health-tool.js +50 -0
  67. package/lib/dist/mcp/health-tool.js.map +1 -0
  68. package/lib/dist/mcp/maintainability-tool.d.ts +5 -7
  69. package/lib/dist/mcp/maintainability-tool.d.ts.map +1 -1
  70. package/lib/dist/mcp/maintainability-tool.js +0 -16
  71. package/lib/dist/mcp/maintainability-tool.js.map +1 -1
  72. package/lib/dist/mcp/model-context.d.ts +13 -2
  73. package/lib/dist/mcp/model-context.d.ts.map +1 -1
  74. package/lib/dist/mcp/model-context.js +39 -12
  75. package/lib/dist/mcp/model-context.js.map +1 -1
  76. package/lib/dist/mcp/proxy.d.ts.map +1 -1
  77. package/lib/dist/mcp/proxy.js +4 -1
  78. package/lib/dist/mcp/proxy.js.map +1 -1
  79. package/lib/dist/mcp/server-instructions.d.ts +1 -1
  80. package/lib/dist/mcp/server-instructions.d.ts.map +1 -1
  81. package/lib/dist/mcp/server-instructions.js +5 -4
  82. package/lib/dist/mcp/server-instructions.js.map +1 -1
  83. package/lib/dist/mcp/spec-tools.d.ts.map +1 -1
  84. package/lib/dist/mcp/spec-tools.js +213 -28
  85. package/lib/dist/mcp/spec-tools.js.map +1 -1
  86. package/lib/dist/mcp/tools.d.ts +12 -8
  87. package/lib/dist/mcp/tools.d.ts.map +1 -1
  88. package/lib/dist/mcp/tools.js +89 -48
  89. package/lib/dist/mcp/tools.js.map +1 -1
  90. package/lib/dist/resolution/spec-link-resolver.d.ts +44 -2
  91. package/lib/dist/resolution/spec-link-resolver.d.ts.map +1 -1
  92. package/lib/dist/resolution/spec-link-resolver.js +132 -0
  93. package/lib/dist/resolution/spec-link-resolver.js.map +1 -1
  94. package/lib/dist/resolution/test-title-links.d.ts +62 -0
  95. package/lib/dist/resolution/test-title-links.d.ts.map +1 -0
  96. package/lib/dist/resolution/test-title-links.js +108 -0
  97. package/lib/dist/resolution/test-title-links.js.map +1 -0
  98. package/lib/dist/search/query-parser.d.ts.map +1 -1
  99. package/lib/dist/search/query-parser.js +6 -1
  100. package/lib/dist/search/query-parser.js.map +1 -1
  101. package/lib/dist/server/project-registry.js +1 -1
  102. package/lib/dist/server/routes/claude.js +9 -36
  103. package/lib/dist/server/routes/graph.js +53 -7
  104. package/lib/dist/server/routes/mcp.js +4 -3
  105. package/lib/dist/server/routes/projects.js +4 -4
  106. package/lib/dist/server/routes/spec.js +49 -7
  107. package/lib/dist/server/server.js +29 -17
  108. package/lib/dist/skills/spec-author/SKILL.md +164 -0
  109. package/lib/dist/skills/spec-author/references/format.md +210 -0
  110. package/lib/dist/skills/spec-author/references/gap-questions.md +152 -0
  111. package/lib/dist/skills/spec-author/references/quality-rubric.md +125 -0
  112. package/lib/dist/skills/spec-author/references/review-checklist.md +175 -0
  113. package/lib/dist/spec-lint/lint.d.ts +82 -0
  114. package/lib/dist/spec-lint/lint.d.ts.map +1 -0
  115. package/lib/dist/spec-lint/lint.js +430 -0
  116. package/lib/dist/spec-lint/lint.js.map +1 -0
  117. package/lib/dist/statusline/index.js.map +1 -1
  118. package/lib/dist/statusline/render.d.ts +1 -1
  119. package/lib/dist/statusline/render.d.ts.map +1 -1
  120. package/lib/dist/statusline/render.js +3 -1
  121. package/lib/dist/statusline/render.js.map +1 -1
  122. package/lib/dist/ui/assets/index-BzuUWUAE.js +50 -0
  123. package/lib/dist/ui/index.html +1 -1
  124. package/lib/dist/verify/report-ingest.d.ts +88 -0
  125. package/lib/dist/verify/report-ingest.d.ts.map +1 -0
  126. package/lib/dist/verify/report-ingest.js +269 -0
  127. package/lib/dist/verify/report-ingest.js.map +1 -0
  128. package/lib/dist/workflows/defaults/spec-fix.yaml +103 -12
  129. package/lib/dist/workflows/defaults/spec-implement-mixed.yaml +264 -21
  130. package/lib/dist/workflows/defaults/spec-implement.yaml +260 -19
  131. package/lib/dist/workflows/defaults/spec-verify.yaml +60 -9
  132. package/lib/node_modules/.package-lock.json +1 -1
  133. package/lib/package.json +7 -3
  134. package/package.json +1 -1
  135. package/lib/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
  136. package/lib/dist/extraction/wasm/tree-sitter-scala.wasm +0 -0
  137. package/lib/dist/server/ingest/impact-query.js +0 -343
  138. package/lib/dist/server/routes/events.js +0 -152
  139. package/lib/dist/ui/assets/index-CjjaftDw.js +0 -50
@@ -100,9 +100,139 @@ nodes:
100
100
 
101
101
  When done, output a short diff summary (which files changed and why).
102
102
 
103
- - id: verify
103
+ - id: quality_gate
104
104
  kind: bash
105
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]
106
236
  output_type: test_results
107
237
  timeout: 600000
108
238
  bash: |
@@ -111,27 +241,69 @@ nodes:
111
241
  # The VERIFY_RESULT marker is the machine-readable contract the link
112
242
  # node routes on (REQ-IMPLINT-001.A1): a skipped run must never be
113
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.
114
247
  if [ -f package.json ]; then
115
248
  # A fresh worktree has no node_modules/ or build output — a verify
116
249
  # failure must mean the tests failed, not that the environment was
117
250
  # missing (WF-REJECT-DOC, REQ-WFREJ-005).
118
- if [ ! -d node_modules ]; then npm ci --no-audit --no-fund || npm install --no-audit --no-fund; fi
119
- npm run build --if-present
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
120
257
  if npm test; then echo "VERIFY_RESULT=ran-and-passed"; else echo "VERIFY_RESULT=ran-and-failed"; exit 1; fi
121
258
  elif [ -f Cargo.toml ]; then
259
+ if ! cargo build; then echo "VERIFY_RESULT=build-failed"; exit 1; fi
122
260
  if cargo test; then echo "VERIFY_RESULT=ran-and-passed"; else echo "VERIFY_RESULT=ran-and-failed"; exit 1; fi
123
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
124
263
  if python -m pytest; then echo "VERIFY_RESULT=ran-and-passed"; else echo "VERIFY_RESULT=ran-and-failed"; exit 1; fi
125
264
  else
126
265
  echo "no recognised test framework; tests did NOT run"
127
266
  echo "VERIFY_RESULT=skipped"
128
267
  fi
129
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
+
130
302
  - id: link
131
303
  # MIXMODEL-DOC: mechanical step → haiku
132
304
  model: haiku
133
305
  kind: prompt
134
- depends_on: [verify]
306
+ depends_on: [route_verify]
135
307
  output_type: link_summary
136
308
  allowed_tools:
137
309
  - mcp__specship__specship_link_assert
@@ -143,14 +315,31 @@ nodes:
143
315
  requirements), call specship_link_assert with the spec_id, the
144
316
  file path, and the qualified symbol name.
145
317
 
146
- Then route on the VERIFY_RESULT marker in the test results below
147
- (REQ-IMPLINT-001):
148
- - VERIFY_RESULT=ran-and-passed → after each assert, call
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
149
333
  specship_link_verify with result="pass".
150
- - VERIFY_RESULT=skipped → do NOT call specship_link_verify at all;
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;
151
337
  the links stay in the `implemented` state. Tests that did not run
152
338
  are never reported as passing.
153
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
+
154
343
  Implementation diff summary:
155
344
  $implement.output
156
345
 
@@ -162,36 +351,90 @@ nodes:
162
351
  skipped.
163
352
 
164
353
  - id: coverage
165
- # MIXMODEL-DOC: mechanical step → haiku
166
- model: haiku
167
- kind: prompt
354
+ kind: bash
168
355
  depends_on: [link]
169
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
170
388
  allowed_tools:
389
+ - Read
390
+ - Grep
171
391
  - mcp__specship__specship_spec
392
+ - mcp__specship__specship_explore
393
+ - mcp__specship__specship_node
394
+ - mcp__specship__specship_search
172
395
  prompt: |
173
- Report acceptance-criteria test coverage for $INPUT.SPEC_ID
174
- (REQ-IMPLINT-002). Call specship_spec with the spec_id, count its
175
- acceptance criteria (the .A<N> children; if the spec has none,
176
- treat the requirement itself as one criterion), and count how many
177
- of them carry a `tests`-kind link.
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:
178
408
 
179
- Output exactly one or two lines:
180
- - "N of M acceptance criteria for $INPUT.SPEC_ID have linked tests."
181
- - If N < M, add: "Close the gap with /specship:spec behaviour
182
- $INPUT.SPEC_ID."
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`.
183
417
 
184
418
  - id: final_review
185
419
  kind: approval
186
- depends_on: [coverage]
420
+ depends_on: [adversarial_review]
187
421
  message: |
188
422
  Implementation complete for $INPUT.SPEC_ID.
189
423
 
424
+ Changes (git diff --stat — measured, not summarized):
425
+ $diff_stat.output
426
+
427
+ Lint / typecheck:
428
+ $quality_recheck.output
429
+
190
430
  Links asserted:
191
431
  $link.output
192
432
 
193
433
  Acceptance-criteria test coverage:
194
434
  $coverage.output
195
435
 
436
+ Adversarial review:
437
+ $adversarial_review.output
438
+
196
439
  Approve to finalize the run (worktree is left for you to inspect
197
440
  and merge), or reject to abandon.