@specship/specship-win32-arm64 0.24.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.
- package/bin/specship.cmd +31 -1
- package/lib/dist/activation/cheatsheet.d.ts +17 -1
- package/lib/dist/activation/cheatsheet.d.ts.map +1 -1
- package/lib/dist/activation/cheatsheet.js +47 -3
- package/lib/dist/activation/cheatsheet.js.map +1 -1
- package/lib/dist/activation/hook-output.d.ts +80 -0
- package/lib/dist/activation/hook-output.d.ts.map +1 -0
- package/lib/dist/activation/hook-output.js +103 -0
- package/lib/dist/activation/hook-output.js.map +1 -0
- package/lib/dist/activation/search-intercept.d.ts +60 -29
- package/lib/dist/activation/search-intercept.d.ts.map +1 -1
- package/lib/dist/activation/search-intercept.js +159 -55
- package/lib/dist/activation/search-intercept.js.map +1 -1
- package/lib/dist/activation/steering.d.ts +11 -13
- package/lib/dist/activation/steering.d.ts.map +1 -1
- package/lib/dist/activation/steering.js +25 -10
- package/lib/dist/activation/steering.js.map +1 -1
- package/lib/dist/behaviour/behaviour-surface.d.ts +47 -0
- package/lib/dist/behaviour/behaviour-surface.d.ts.map +1 -1
- package/lib/dist/behaviour/behaviour-surface.js +108 -2
- package/lib/dist/behaviour/behaviour-surface.js.map +1 -1
- package/lib/dist/bin/node-version-check.d.ts +22 -7
- package/lib/dist/bin/node-version-check.d.ts.map +1 -1
- package/lib/dist/bin/node-version-check.js +39 -9
- package/lib/dist/bin/node-version-check.js.map +1 -1
- package/lib/dist/bin/specship.js +989 -116
- package/lib/dist/bin/specship.js.map +1 -1
- package/lib/dist/commands/specship/learn.md +27 -3
- package/lib/dist/commands/specship/spec.md +85 -15
- package/lib/dist/db/spec-queries.d.ts +73 -3
- package/lib/dist/db/spec-queries.d.ts.map +1 -1
- package/lib/dist/db/spec-queries.js +139 -5
- package/lib/dist/db/spec-queries.js.map +1 -1
- package/lib/dist/db/sqlite-adapter.d.ts +7 -5
- package/lib/dist/db/sqlite-adapter.d.ts.map +1 -1
- package/lib/dist/db/sqlite-adapter.js +11 -9
- package/lib/dist/db/sqlite-adapter.js.map +1 -1
- package/lib/dist/enforce/changed-files.d.ts +39 -0
- package/lib/dist/enforce/changed-files.d.ts.map +1 -0
- package/lib/dist/enforce/changed-files.js +114 -0
- package/lib/dist/enforce/changed-files.js.map +1 -0
- package/lib/dist/enforce/enforce.d.ts +53 -2
- package/lib/dist/enforce/enforce.d.ts.map +1 -1
- package/lib/dist/enforce/enforce.js +95 -8
- package/lib/dist/enforce/enforce.js.map +1 -1
- package/lib/dist/enforce/mutation.d.ts +46 -0
- package/lib/dist/enforce/mutation.d.ts.map +1 -0
- package/lib/dist/enforce/mutation.js +104 -0
- package/lib/dist/enforce/mutation.js.map +1 -0
- package/lib/dist/enforce/suppressions.d.ts +33 -0
- package/lib/dist/enforce/suppressions.d.ts.map +1 -0
- package/lib/dist/enforce/suppressions.js +159 -0
- package/lib/dist/enforce/suppressions.js.map +1 -0
- package/lib/dist/extraction/grammars.d.ts +10 -0
- package/lib/dist/extraction/grammars.d.ts.map +1 -1
- package/lib/dist/extraction/grammars.js +32 -3
- package/lib/dist/extraction/grammars.js.map +1 -1
- package/lib/dist/extraction/index.d.ts +7 -0
- package/lib/dist/extraction/index.d.ts.map +1 -1
- package/lib/dist/extraction/index.js.map +1 -1
- package/lib/dist/extraction/specs/markdown-spec-extractor.d.ts +7 -0
- package/lib/dist/extraction/specs/markdown-spec-extractor.d.ts.map +1 -1
- package/lib/dist/extraction/specs/markdown-spec-extractor.js +97 -10
- package/lib/dist/extraction/specs/markdown-spec-extractor.js.map +1 -1
- package/lib/dist/extraction/wasm/tree-sitter-pascal.wasm.gz +0 -0
- package/lib/dist/extraction/wasm/tree-sitter-scala.wasm.gz +0 -0
- package/lib/dist/graph/spec-coverage.d.ts +142 -0
- package/lib/dist/graph/spec-coverage.d.ts.map +1 -0
- package/lib/dist/graph/spec-coverage.js +276 -0
- package/lib/dist/graph/spec-coverage.js.map +1 -0
- package/lib/dist/health/smoke-check.js +2 -2
- package/lib/dist/health/smoke-check.js.map +1 -1
- package/lib/dist/index.d.ts +75 -7
- package/lib/dist/index.d.ts.map +1 -1
- package/lib/dist/index.js +191 -23
- package/lib/dist/index.js.map +1 -1
- package/lib/dist/installer/gemini-commands.d.ts +107 -0
- package/lib/dist/installer/gemini-commands.d.ts.map +1 -0
- package/lib/dist/installer/gemini-commands.js +264 -0
- package/lib/dist/installer/gemini-commands.js.map +1 -0
- package/lib/dist/installer/index.d.ts +55 -8
- package/lib/dist/installer/index.d.ts.map +1 -1
- package/lib/dist/installer/index.js +72 -53
- package/lib/dist/installer/index.js.map +1 -1
- package/lib/dist/installer/init-offer.d.ts +14 -9
- package/lib/dist/installer/init-offer.d.ts.map +1 -1
- package/lib/dist/installer/init-offer.js +13 -9
- package/lib/dist/installer/init-offer.js.map +1 -1
- package/lib/dist/installer/install-defaults.d.ts +81 -0
- package/lib/dist/installer/install-defaults.d.ts.map +1 -0
- package/lib/dist/installer/install-defaults.js +95 -0
- package/lib/dist/installer/install-defaults.js.map +1 -0
- package/lib/dist/installer/instructions-template.d.ts +22 -0
- package/lib/dist/installer/instructions-template.d.ts.map +1 -1
- package/lib/dist/installer/instructions-template.js +37 -1
- package/lib/dist/installer/instructions-template.js.map +1 -1
- package/lib/dist/installer/targets/claude.d.ts +18 -0
- package/lib/dist/installer/targets/claude.d.ts.map +1 -1
- package/lib/dist/installer/targets/claude.js +70 -23
- package/lib/dist/installer/targets/claude.js.map +1 -1
- package/lib/dist/installer/targets/gemini.d.ts +85 -12
- package/lib/dist/installer/targets/gemini.d.ts.map +1 -1
- package/lib/dist/installer/targets/gemini.js +527 -30
- package/lib/dist/installer/targets/gemini.js.map +1 -1
- package/lib/dist/installer/targets/shared.d.ts +13 -0
- package/lib/dist/installer/targets/shared.d.ts.map +1 -1
- package/lib/dist/installer/targets/shared.js +22 -4
- package/lib/dist/installer/targets/shared.js.map +1 -1
- package/lib/dist/installer/targets/types.d.ts +12 -0
- package/lib/dist/installer/targets/types.d.ts.map +1 -1
- package/lib/dist/jira/auto-publish.d.ts +71 -4
- package/lib/dist/jira/auto-publish.d.ts.map +1 -1
- package/lib/dist/jira/auto-publish.js +186 -17
- package/lib/dist/jira/auto-publish.js.map +1 -1
- package/lib/dist/jira/reconcile.d.ts +24 -1
- package/lib/dist/jira/reconcile.d.ts.map +1 -1
- package/lib/dist/jira/reconcile.js +46 -2
- package/lib/dist/jira/reconcile.js.map +1 -1
- package/lib/dist/jira/repo-config.d.ts +9 -0
- package/lib/dist/jira/repo-config.d.ts.map +1 -1
- package/lib/dist/jira/repo-config.js +11 -0
- package/lib/dist/jira/repo-config.js.map +1 -1
- package/lib/dist/jira/types.d.ts +7 -0
- package/lib/dist/jira/types.d.ts.map +1 -1
- package/lib/dist/jira/types.js.map +1 -1
- package/lib/dist/knowledge/enforce.d.ts +75 -0
- package/lib/dist/knowledge/enforce.d.ts.map +1 -0
- package/lib/dist/knowledge/enforce.js +250 -0
- package/lib/dist/knowledge/enforce.js.map +1 -0
- package/lib/dist/knowledge/facts.d.ts +33 -0
- package/lib/dist/knowledge/facts.d.ts.map +1 -0
- package/lib/dist/knowledge/facts.js +117 -0
- package/lib/dist/knowledge/facts.js.map +1 -0
- package/lib/dist/knowledge/proposals.d.ts +88 -0
- package/lib/dist/knowledge/proposals.d.ts.map +1 -0
- package/lib/dist/knowledge/proposals.js +360 -0
- package/lib/dist/knowledge/proposals.js.map +1 -0
- package/lib/dist/knowledge/stale.d.ts +64 -0
- package/lib/dist/knowledge/stale.d.ts.map +1 -0
- package/lib/dist/knowledge/stale.js +174 -0
- package/lib/dist/knowledge/stale.js.map +1 -0
- package/lib/dist/mcp/fitness-tool.d.ts +5 -6
- package/lib/dist/mcp/fitness-tool.d.ts.map +1 -1
- package/lib/dist/mcp/fitness-tool.js +0 -16
- package/lib/dist/mcp/fitness-tool.js.map +1 -1
- package/lib/dist/mcp/gemini-session.d.ts +50 -0
- package/lib/dist/mcp/gemini-session.d.ts.map +1 -0
- package/lib/dist/mcp/gemini-session.js +159 -0
- package/lib/dist/mcp/gemini-session.js.map +1 -0
- package/lib/dist/mcp/health-tool.d.ts +26 -0
- package/lib/dist/mcp/health-tool.d.ts.map +1 -0
- package/lib/dist/mcp/health-tool.js +50 -0
- package/lib/dist/mcp/health-tool.js.map +1 -0
- package/lib/dist/mcp/jira-tools.d.ts.map +1 -1
- package/lib/dist/mcp/jira-tools.js +25 -0
- package/lib/dist/mcp/jira-tools.js.map +1 -1
- package/lib/dist/mcp/maintainability-tool.d.ts +5 -7
- package/lib/dist/mcp/maintainability-tool.d.ts.map +1 -1
- package/lib/dist/mcp/maintainability-tool.js +0 -16
- package/lib/dist/mcp/maintainability-tool.js.map +1 -1
- package/lib/dist/mcp/model-context.d.ts +31 -7
- package/lib/dist/mcp/model-context.d.ts.map +1 -1
- package/lib/dist/mcp/model-context.js +70 -21
- package/lib/dist/mcp/model-context.js.map +1 -1
- package/lib/dist/mcp/proxy.d.ts.map +1 -1
- package/lib/dist/mcp/proxy.js +5 -2
- package/lib/dist/mcp/proxy.js.map +1 -1
- package/lib/dist/mcp/server-instructions.d.ts +16 -15
- package/lib/dist/mcp/server-instructions.d.ts.map +1 -1
- package/lib/dist/mcp/server-instructions.js +72 -5
- package/lib/dist/mcp/server-instructions.js.map +1 -1
- package/lib/dist/mcp/session.js +1 -1
- package/lib/dist/mcp/session.js.map +1 -1
- package/lib/dist/mcp/spec-tools.d.ts +9 -1
- package/lib/dist/mcp/spec-tools.d.ts.map +1 -1
- package/lib/dist/mcp/spec-tools.js +282 -49
- package/lib/dist/mcp/spec-tools.js.map +1 -1
- package/lib/dist/mcp/tools.d.ts +49 -9
- package/lib/dist/mcp/tools.d.ts.map +1 -1
- package/lib/dist/mcp/tools.js +210 -58
- package/lib/dist/mcp/tools.js.map +1 -1
- package/lib/dist/pulse/pulse.d.ts +93 -0
- package/lib/dist/pulse/pulse.d.ts.map +1 -0
- package/lib/dist/pulse/pulse.js +401 -0
- package/lib/dist/pulse/pulse.js.map +1 -0
- package/lib/dist/reflect/apply.d.ts.map +1 -1
- package/lib/dist/reflect/apply.js +38 -3
- package/lib/dist/reflect/apply.js.map +1 -1
- package/lib/dist/reflect/auto-sweep.d.ts +26 -0
- package/lib/dist/reflect/auto-sweep.d.ts.map +1 -0
- package/lib/dist/reflect/auto-sweep.js +90 -0
- package/lib/dist/reflect/auto-sweep.js.map +1 -0
- package/lib/dist/reflect/cli.d.ts +62 -0
- package/lib/dist/reflect/cli.d.ts.map +1 -0
- package/lib/dist/reflect/cli.js +163 -0
- package/lib/dist/reflect/cli.js.map +1 -0
- package/lib/dist/reflect/miner.d.ts.map +1 -1
- package/lib/dist/reflect/miner.js +119 -0
- package/lib/dist/reflect/miner.js.map +1 -1
- package/lib/dist/reflect/sweep.d.ts +1 -0
- package/lib/dist/reflect/sweep.d.ts.map +1 -1
- package/lib/dist/reflect/sweep.js +62 -13
- package/lib/dist/reflect/sweep.js.map +1 -1
- package/lib/dist/reflect/targets.d.ts +2 -0
- package/lib/dist/reflect/targets.d.ts.map +1 -1
- package/lib/dist/reflect/targets.js +33 -0
- package/lib/dist/reflect/targets.js.map +1 -1
- package/lib/dist/reflect/types.d.ts +19 -2
- package/lib/dist/reflect/types.d.ts.map +1 -1
- package/lib/dist/resolution/spec-link-resolver.d.ts +44 -2
- package/lib/dist/resolution/spec-link-resolver.d.ts.map +1 -1
- package/lib/dist/resolution/spec-link-resolver.js +132 -0
- package/lib/dist/resolution/spec-link-resolver.js.map +1 -1
- package/lib/dist/resolution/test-title-links.d.ts +62 -0
- package/lib/dist/resolution/test-title-links.d.ts.map +1 -0
- package/lib/dist/resolution/test-title-links.js +97 -0
- package/lib/dist/resolution/test-title-links.js.map +1 -0
- package/lib/dist/search/query-parser.d.ts.map +1 -1
- package/lib/dist/search/query-parser.js +6 -1
- package/lib/dist/search/query-parser.js.map +1 -1
- package/lib/dist/server/project-registry.js +1 -1
- package/lib/dist/server/routes/claude.js +24 -43
- package/lib/dist/server/routes/graph.js +53 -7
- package/lib/dist/server/routes/knowledge.js +118 -0
- package/lib/dist/server/routes/mcp.js +4 -3
- package/lib/dist/server/routes/projects.js +4 -4
- package/lib/dist/server/routes/spec.js +49 -7
- package/lib/dist/server/server.js +31 -17
- package/lib/dist/skills/spec-author/SKILL.md +164 -0
- package/lib/dist/skills/spec-author/references/format.md +210 -0
- package/lib/dist/skills/spec-author/references/gap-questions.md +152 -0
- package/lib/dist/skills/spec-author/references/quality-rubric.md +125 -0
- package/lib/dist/skills/spec-author/references/review-checklist.md +175 -0
- package/lib/dist/spec-lint/lint.d.ts +82 -0
- package/lib/dist/spec-lint/lint.d.ts.map +1 -0
- package/lib/dist/spec-lint/lint.js +491 -0
- package/lib/dist/spec-lint/lint.js.map +1 -0
- package/lib/dist/spec-quality/criterion-ids.d.ts +13 -0
- package/lib/dist/spec-quality/criterion-ids.d.ts.map +1 -0
- package/lib/dist/spec-quality/criterion-ids.js +38 -0
- package/lib/dist/spec-quality/criterion-ids.js.map +1 -0
- package/lib/dist/spec-quality/evidence-kind.d.ts +54 -0
- package/lib/dist/spec-quality/evidence-kind.d.ts.map +1 -0
- package/lib/dist/spec-quality/evidence-kind.js +183 -0
- package/lib/dist/spec-quality/evidence-kind.js.map +1 -0
- package/lib/dist/spec-quality/link-persist.d.ts +65 -0
- package/lib/dist/spec-quality/link-persist.d.ts.map +1 -0
- package/lib/dist/spec-quality/link-persist.js +249 -0
- package/lib/dist/spec-quality/link-persist.js.map +1 -0
- package/lib/dist/spec-quality/plan-scope.d.ts +38 -0
- package/lib/dist/spec-quality/plan-scope.d.ts.map +1 -0
- package/lib/dist/spec-quality/plan-scope.js +129 -0
- package/lib/dist/spec-quality/plan-scope.js.map +1 -0
- package/lib/dist/spec-quality/postcheck.d.ts +85 -0
- package/lib/dist/spec-quality/postcheck.d.ts.map +1 -0
- package/lib/dist/spec-quality/postcheck.js +390 -0
- package/lib/dist/spec-quality/postcheck.js.map +1 -0
- package/lib/dist/spec-quality/readiness.d.ts +72 -0
- package/lib/dist/spec-quality/readiness.d.ts.map +1 -0
- package/lib/dist/spec-quality/readiness.js +226 -0
- package/lib/dist/spec-quality/readiness.js.map +1 -0
- package/lib/dist/statusline/index.js.map +1 -1
- package/lib/dist/statusline/render.d.ts +1 -1
- package/lib/dist/statusline/render.d.ts.map +1 -1
- package/lib/dist/statusline/render.js +3 -1
- package/lib/dist/statusline/render.js.map +1 -1
- package/lib/dist/ui/assets/index-BzuUWUAE.js +50 -0
- package/lib/dist/ui/index.html +1 -1
- package/lib/dist/verify/report-ingest.d.ts +88 -0
- package/lib/dist/verify/report-ingest.d.ts.map +1 -0
- package/lib/dist/verify/report-ingest.js +269 -0
- package/lib/dist/verify/report-ingest.js.map +1 -0
- package/lib/dist/workflows/agents/claude.d.ts +16 -0
- package/lib/dist/workflows/agents/claude.d.ts.map +1 -0
- package/lib/dist/workflows/agents/claude.js +82 -0
- package/lib/dist/workflows/agents/claude.js.map +1 -0
- package/lib/dist/workflows/agents/gemini.d.ts +21 -0
- package/lib/dist/workflows/agents/gemini.d.ts.map +1 -0
- package/lib/dist/workflows/agents/gemini.js +124 -0
- package/lib/dist/workflows/agents/gemini.js.map +1 -0
- package/lib/dist/workflows/agents/index.d.ts +28 -0
- package/lib/dist/workflows/agents/index.d.ts.map +1 -0
- package/lib/dist/workflows/agents/index.js +104 -0
- package/lib/dist/workflows/agents/index.js.map +1 -0
- package/lib/dist/workflows/agents/types.d.ts +55 -0
- package/lib/dist/workflows/agents/types.d.ts.map +1 -0
- package/lib/dist/workflows/agents/types.js +46 -0
- package/lib/dist/workflows/agents/types.js.map +1 -0
- package/lib/dist/workflows/batch.d.ts +63 -0
- package/lib/dist/workflows/batch.d.ts.map +1 -0
- package/lib/dist/workflows/batch.js +151 -0
- package/lib/dist/workflows/batch.js.map +1 -0
- package/lib/dist/workflows/defaults/claude-design-implement.yaml +3 -4
- package/lib/dist/workflows/defaults/spec-author.yaml +11 -9
- package/lib/dist/workflows/defaults/spec-fix.yaml +103 -12
- package/lib/dist/workflows/defaults/spec-implement-mixed.yaml +21 -193
- package/lib/dist/workflows/defaults/spec-implement.yaml +701 -41
- package/lib/dist/workflows/defaults/spec-verify.yaml +60 -9
- package/lib/dist/workflows/discovery.d.ts +13 -0
- package/lib/dist/workflows/discovery.d.ts.map +1 -1
- package/lib/dist/workflows/discovery.js +79 -17
- package/lib/dist/workflows/discovery.js.map +1 -1
- package/lib/dist/workflows/executor.d.ts +18 -0
- package/lib/dist/workflows/executor.d.ts.map +1 -1
- package/lib/dist/workflows/executor.js +130 -33
- package/lib/dist/workflows/executor.js.map +1 -1
- package/lib/dist/workflows/gc.d.ts +50 -0
- package/lib/dist/workflows/gc.d.ts.map +1 -0
- package/lib/dist/workflows/gc.js +120 -0
- package/lib/dist/workflows/gc.js.map +1 -0
- package/lib/dist/workflows/merge-queue.d.ts +64 -0
- package/lib/dist/workflows/merge-queue.d.ts.map +1 -0
- package/lib/dist/workflows/merge-queue.js +162 -0
- package/lib/dist/workflows/merge-queue.js.map +1 -0
- package/lib/dist/workflows/runners/approval.d.ts +1 -1
- package/lib/dist/workflows/runners/approval.d.ts.map +1 -1
- package/lib/dist/workflows/runners/approval.js +11 -2
- package/lib/dist/workflows/runners/approval.js.map +1 -1
- package/lib/dist/workflows/runners/bash.d.ts +15 -0
- package/lib/dist/workflows/runners/bash.d.ts.map +1 -1
- package/lib/dist/workflows/runners/bash.js +50 -1
- package/lib/dist/workflows/runners/bash.js.map +1 -1
- package/lib/dist/workflows/runners/prompt.d.ts +16 -41
- package/lib/dist/workflows/runners/prompt.d.ts.map +1 -1
- package/lib/dist/workflows/runners/prompt.js +55 -120
- package/lib/dist/workflows/runners/prompt.js.map +1 -1
- package/lib/dist/workflows/runners/types.d.ts +12 -0
- package/lib/dist/workflows/runners/types.d.ts.map +1 -1
- package/lib/dist/workflows/schemas/workflow.d.ts +17 -0
- package/lib/dist/workflows/schemas/workflow.d.ts.map +1 -1
- package/lib/dist/workflows/schemas/workflow.js +27 -0
- package/lib/dist/workflows/schemas/workflow.js.map +1 -1
- package/lib/node_modules/.package-lock.json +1 -1
- package/lib/package.json +8 -4
- package/package.json +5 -3
- package/lib/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
- package/lib/dist/extraction/wasm/tree-sitter-scala.wasm +0 -0
- package/lib/dist/server/ingest/impact-query.js +0 -343
- package/lib/dist/server/routes/events.js +0 -152
- package/lib/dist/ui/assets/index-CjjaftDw.js +0 -50
- package/node.exe +0 -4
|
@@ -14,8 +14,9 @@ inputs:
|
|
|
14
14
|
systemPromptAppend: |
|
|
15
15
|
You are implementing a specific requirement. Before editing code, call
|
|
16
16
|
specship_spec($INPUT.SPEC_ID) to see the spec body and any code it
|
|
17
|
-
already links to. After editing,
|
|
18
|
-
|
|
17
|
+
already links to. After editing, record each symbol you implemented as a
|
|
18
|
+
`path:Symbol` bullet under the requirement's `implementations:` block in
|
|
19
|
+
its spec file — links in the spec file survive any reindex.
|
|
19
20
|
|
|
20
21
|
JIRA-backed specs (REQ-JIRAPUB-004): if the spec file's frontmatter
|
|
21
22
|
carries a `jira_issue:` key, EVERY git commit message you write for this
|
|
@@ -41,9 +42,30 @@ nodes:
|
|
|
41
42
|
(b) which code areas / symbols are most relevant, and (c) whether
|
|
42
43
|
any code currently claims to implement it (look at linked_code).
|
|
43
44
|
|
|
45
|
+
- id: readiness
|
|
46
|
+
kind: bash
|
|
47
|
+
depends_on: [fetch_spec]
|
|
48
|
+
output_type: readiness_report
|
|
49
|
+
timeout: 120000
|
|
50
|
+
bash: |
|
|
51
|
+
# REQ-PIPETRUST-004 — implement must not start on a spec that is not
|
|
52
|
+
# ready (lint errors, no criteria, a criterion still [needs review]).
|
|
53
|
+
# Also records the run's base commit so postcheck can diff against it.
|
|
54
|
+
git rev-parse HEAD > "$(git rev-parse --git-dir)/specship-run-base" 2>/dev/null || true
|
|
55
|
+
if [ -n "$SPECSHIP_CLI_SCRIPT" ]; then ss_cli() { "$SPECSHIP_CLI_NODE" "$SPECSHIP_CLI_SCRIPT" "$@"; }; SS=ss_cli
|
|
56
|
+
elif command -v specship >/dev/null 2>&1; then SS=specship
|
|
57
|
+
elif [ -x node_modules/.bin/specship ]; then SS=node_modules/.bin/specship
|
|
58
|
+
else SS=""
|
|
59
|
+
fi
|
|
60
|
+
if [ -z "$SS" ]; then
|
|
61
|
+
echo "READY=unavailable — specship CLI not found; the readiness gate did NOT run"
|
|
62
|
+
exit 1
|
|
63
|
+
fi
|
|
64
|
+
$SS ready $INPUT.SPEC_ID --path .
|
|
65
|
+
|
|
44
66
|
- id: plan
|
|
45
67
|
kind: prompt
|
|
46
|
-
depends_on: [fetch_spec]
|
|
68
|
+
depends_on: [fetch_spec, readiness]
|
|
47
69
|
output_type: plan
|
|
48
70
|
allowed_tools:
|
|
49
71
|
- mcp__specship__specship_explore
|
|
@@ -55,6 +77,17 @@ nodes:
|
|
|
55
77
|
|
|
56
78
|
$fetch_spec.output
|
|
57
79
|
|
|
80
|
+
Readiness + evidence plan (every acceptance criterion needs a test of
|
|
81
|
+
the stated kind, written as a NAMED function passed to it() with the
|
|
82
|
+
criterion id in its title):
|
|
83
|
+
$readiness.output
|
|
84
|
+
|
|
85
|
+
Domain facts that `specship_spec` returns with the requirement are
|
|
86
|
+
constraints, not background: honour each external fact's verified
|
|
87
|
+
version, and treat every `## Enforced` rule (`<glob>` must not match
|
|
88
|
+
`/<regex>/`) as a hard constraint — `specship knowledge check` fails the
|
|
89
|
+
run on a violation (REQ-KNOW-005).
|
|
90
|
+
|
|
58
91
|
The plan should list:
|
|
59
92
|
- Files to create or modify (with project-relative paths)
|
|
60
93
|
- Specific functions/methods/classes to add or change
|
|
@@ -63,23 +96,93 @@ nodes:
|
|
|
63
96
|
|
|
64
97
|
Keep it tight (≤500 words). Do NOT edit code in this step.
|
|
65
98
|
|
|
99
|
+
- id: plan_scope
|
|
100
|
+
kind: bash
|
|
101
|
+
depends_on: [plan]
|
|
102
|
+
output_type: plan_scope
|
|
103
|
+
bash: |
|
|
104
|
+
# REQ-THRU-003 — opt-in auto-approval of a small, in-scope plan. Prints
|
|
105
|
+
# AUTO_APPROVE=yes only when specship.config.json opts in, the plan
|
|
106
|
+
# names only the requirement's implementation files (plus tests, its
|
|
107
|
+
# spec and CHANGELOG.md), and the requirement has few criteria.
|
|
108
|
+
PLAN=$plan.output
|
|
109
|
+
F="$(mktemp)"
|
|
110
|
+
printf '%s\n' "$PLAN" > "$F"
|
|
111
|
+
if [ -n "$SPECSHIP_CLI_SCRIPT" ]; then "$SPECSHIP_CLI_NODE" "$SPECSHIP_CLI_SCRIPT" plan-scope $INPUT.SPEC_ID --plan-file "$F" --path .
|
|
112
|
+
elif command -v specship >/dev/null 2>&1; then specship plan-scope $INPUT.SPEC_ID --plan-file "$F" --path . || echo "AUTO_APPROVE=no"
|
|
113
|
+
else echo "AUTO_APPROVE=no"; echo "- specship CLI not found"
|
|
114
|
+
fi
|
|
115
|
+
rm -f "$F"
|
|
116
|
+
|
|
66
117
|
- id: approve_plan
|
|
67
118
|
kind: approval
|
|
68
|
-
depends_on: [plan]
|
|
119
|
+
depends_on: [plan, plan_scope]
|
|
120
|
+
auto_approve:
|
|
121
|
+
from: plan_scope
|
|
122
|
+
marker: AUTO_APPROVE=yes
|
|
69
123
|
message: |
|
|
70
124
|
Plan ready for $INPUT.SPEC_ID. Review the plan output and approve
|
|
71
125
|
to proceed with implementation, or reject with feedback to revise.
|
|
72
126
|
capture_response: true
|
|
73
127
|
on_reject:
|
|
128
|
+
# The reviewer's rejection reason is appended to this prompt
|
|
129
|
+
# automatically; the revision replaces $plan.output downstream.
|
|
74
130
|
prompt: |
|
|
75
|
-
The plan was rejected
|
|
131
|
+
The plan was rejected (feedback follows). Revise the plan to
|
|
132
|
+
address it and output the full revised plan.
|
|
76
133
|
|
|
77
|
-
|
|
134
|
+
Current plan:
|
|
135
|
+
$plan.output
|
|
136
|
+
revises: plan
|
|
78
137
|
max_attempts: 3
|
|
79
138
|
|
|
139
|
+
- id: quality_baseline
|
|
140
|
+
kind: bash
|
|
141
|
+
depends_on: [approve_plan]
|
|
142
|
+
output_type: quality_report
|
|
143
|
+
timeout: 600000
|
|
144
|
+
bash: |
|
|
145
|
+
# REQ-AUTHG-008.A1 — run the project's quality command BEFORE implement
|
|
146
|
+
# edits anything, so the gate can tell errors this change introduced
|
|
147
|
+
# from errors the worktree already had (a sub-package with no built
|
|
148
|
+
# parent, known lint debt). The baseline lives under the worktree's git
|
|
149
|
+
# dir, so it never shows up in the diff. It is written ONLY when the
|
|
150
|
+
# pre-change command fails: a clean baseline means any later failure is
|
|
151
|
+
# the change's, so the gate keeps its full strictness (A5 fallback).
|
|
152
|
+
qnorm() { sed -E 's/\([0-9]+,[0-9]+\)//g; s/:[0-9]+:[0-9]+/:/g; s/:[0-9]+:/:/g' | sed -E '/^[[:space:]]*$/d' | sort -u; }
|
|
153
|
+
BASELINE="$(git rev-parse --git-dir 2>/dev/null)/specship-quality-baseline.txt"
|
|
154
|
+
rm -f "$BASELINE"
|
|
155
|
+
QUALITY_CMD=""
|
|
156
|
+
if [ -f package.json ]; then
|
|
157
|
+
if [ ! -d node_modules ]; then
|
|
158
|
+
npm ci --no-audit --no-fund >/dev/null 2>&1 || npm install --no-audit --no-fund >/dev/null 2>&1 || true
|
|
159
|
+
fi
|
|
160
|
+
if node -e 'const s=(require("./package.json").scripts)||{};process.exit(s.lint?0:1)' 2>/dev/null; then
|
|
161
|
+
QUALITY_CMD="npm run lint --if-present"
|
|
162
|
+
elif [ -f tsconfig.json ]; then
|
|
163
|
+
QUALITY_CMD="npx --no-install tsc --noEmit"
|
|
164
|
+
fi
|
|
165
|
+
elif [ -f Cargo.toml ]; then
|
|
166
|
+
if command -v cargo >/dev/null 2>&1; then QUALITY_CMD="cargo clippy --no-deps"; fi
|
|
167
|
+
elif [ -f pyproject.toml ] || [ -f requirements.txt ]; then
|
|
168
|
+
if command -v ruff >/dev/null 2>&1; then QUALITY_CMD="ruff check ."; fi
|
|
169
|
+
fi
|
|
170
|
+
if [ -z "$QUALITY_CMD" ]; then
|
|
171
|
+
echo "QUALITY_BASELINE=skipped"
|
|
172
|
+
exit 0
|
|
173
|
+
fi
|
|
174
|
+
if OUT=$($QUALITY_CMD 2>&1); then
|
|
175
|
+
echo "QUALITY_BASELINE=clean"
|
|
176
|
+
else
|
|
177
|
+
printf '%s\n' "$OUT" | qnorm > "$BASELINE"
|
|
178
|
+
echo "QUALITY_BASELINE=recorded"
|
|
179
|
+
echo "QUALITY_BASELINE_LINES=$(wc -l < "$BASELINE" | tr -d ' ')"
|
|
180
|
+
fi
|
|
181
|
+
exit 0
|
|
182
|
+
|
|
80
183
|
- id: implement
|
|
81
184
|
kind: prompt
|
|
82
|
-
depends_on: [approve_plan]
|
|
185
|
+
depends_on: [approve_plan, quality_baseline]
|
|
83
186
|
output_type: diff
|
|
84
187
|
allowed_tools:
|
|
85
188
|
- Read
|
|
@@ -92,17 +195,302 @@ nodes:
|
|
|
92
195
|
prompt: |
|
|
93
196
|
Implement the approved plan. Follow it closely.
|
|
94
197
|
|
|
198
|
+
Domain facts that `specship_spec` returns with the requirement are
|
|
199
|
+
constraints, not background: honour each external fact's verified
|
|
200
|
+
version, and treat every `## Enforced` rule (`<glob>` must not match
|
|
201
|
+
`/<regex>/`) as a hard constraint — `specship knowledge check` fails the
|
|
202
|
+
run on a violation (REQ-KNOW-005).
|
|
203
|
+
|
|
95
204
|
Plan:
|
|
96
205
|
$plan.output
|
|
97
206
|
|
|
98
207
|
Approval feedback (if any):
|
|
99
208
|
$approve_plan.output
|
|
100
209
|
|
|
210
|
+
Readiness + evidence plan (every acceptance criterion needs a test of
|
|
211
|
+
the stated kind, written as a NAMED function passed to it() with the
|
|
212
|
+
criterion id in its title):
|
|
213
|
+
$readiness.output
|
|
214
|
+
|
|
101
215
|
When done, output a short diff summary (which files changed and why).
|
|
102
216
|
|
|
103
|
-
- id:
|
|
217
|
+
- id: quality_gate
|
|
104
218
|
kind: bash
|
|
105
219
|
depends_on: [implement]
|
|
220
|
+
output_type: quality_report
|
|
221
|
+
timeout: 600000
|
|
222
|
+
bash: |
|
|
223
|
+
# REQ-AUTHG-005.A1 — the project's own lint/typecheck, run in the
|
|
224
|
+
# worktree right after implement. The QUALITY_GATE marker is the
|
|
225
|
+
# contract the remediation node routes on: a project with neither a lint
|
|
226
|
+
# script nor a typecheck config says so explicitly, so "nothing ran" can
|
|
227
|
+
# never be mistaken for "clean" (same doctrine as VERIFY_RESULT=skipped).
|
|
228
|
+
QUALITY_CMD=""
|
|
229
|
+
if [ -f package.json ]; then
|
|
230
|
+
# The worktree may not have dependencies yet (verify installs them
|
|
231
|
+
# later) and lint needs them — bootstrap quietly, and treat a failed
|
|
232
|
+
# install as "no gate" rather than as a lint failure.
|
|
233
|
+
if [ ! -d node_modules ]; then
|
|
234
|
+
npm ci --no-audit --no-fund >/dev/null 2>&1 || npm install --no-audit --no-fund >/dev/null 2>&1 || true
|
|
235
|
+
fi
|
|
236
|
+
if node -e 'const s=(require("./package.json").scripts)||{};process.exit(s.lint?0:1)' 2>/dev/null; then
|
|
237
|
+
QUALITY_CMD="npm run lint --if-present"
|
|
238
|
+
elif [ -f tsconfig.json ]; then
|
|
239
|
+
QUALITY_CMD="npx --no-install tsc --noEmit"
|
|
240
|
+
fi
|
|
241
|
+
elif [ -f Cargo.toml ]; then
|
|
242
|
+
if command -v cargo >/dev/null 2>&1; then QUALITY_CMD="cargo clippy --no-deps"; fi
|
|
243
|
+
elif [ -f pyproject.toml ] || [ -f requirements.txt ]; then
|
|
244
|
+
if command -v ruff >/dev/null 2>&1; then QUALITY_CMD="ruff check ."; fi
|
|
245
|
+
fi
|
|
246
|
+
if [ -z "$QUALITY_CMD" ]; then
|
|
247
|
+
echo "QUALITY_GATE=skipped"
|
|
248
|
+
echo "QUALITY_REASON=no lint script and no typecheck configuration in this project"
|
|
249
|
+
exit 0
|
|
250
|
+
fi
|
|
251
|
+
echo "QUALITY_CMD=$QUALITY_CMD"
|
|
252
|
+
qnorm() { sed -E 's/\([0-9]+,[0-9]+\)//g; s/:[0-9]+:[0-9]+/:/g; s/:[0-9]+:/:/g' | sed -E '/^[[:space:]]*$/d' | sort -u; }
|
|
253
|
+
BASELINE="$(git rev-parse --git-dir 2>/dev/null)/specship-quality-baseline.txt"
|
|
254
|
+
if OUT=$($QUALITY_CMD 2>&1); then
|
|
255
|
+
echo "QUALITY_GATE=passed"
|
|
256
|
+
elif [ -f "$BASELINE" ]; then
|
|
257
|
+
# REQ-AUTHG-008.A2/A3 — judge only error lines absent from the
|
|
258
|
+
# pre-change baseline; report pre-existing ones, never hide them.
|
|
259
|
+
NEW=$(printf '%s\n' "$OUT" | qnorm | comm -13 "$BASELINE" - | grep -iE 'error' || true)
|
|
260
|
+
PRE=$(printf '%s\n' "$OUT" | qnorm | comm -12 "$BASELINE" - | grep -ciE 'error' || true)
|
|
261
|
+
if [ -z "$NEW" ]; then
|
|
262
|
+
echo "QUALITY_GATE=passed"
|
|
263
|
+
echo "QUALITY_PREEXISTING=$PRE"
|
|
264
|
+
echo "Pre-existing errors (already failing before implement; not caused by this change), sample:"
|
|
265
|
+
printf '%s\n' "$OUT" | grep -iE 'error' | head -n 5
|
|
266
|
+
else
|
|
267
|
+
echo "QUALITY_GATE=failed"
|
|
268
|
+
echo "QUALITY_PREEXISTING=$PRE"
|
|
269
|
+
echo "New errors introduced by this change:"
|
|
270
|
+
printf '%s\n' "$NEW" | tail -n 80
|
|
271
|
+
fi
|
|
272
|
+
else
|
|
273
|
+
echo "QUALITY_GATE=failed"
|
|
274
|
+
printf '%s\n' "$OUT" | tail -n 80
|
|
275
|
+
fi
|
|
276
|
+
# Exiting 0 on a lint failure is deliberate: the marker — not this node's
|
|
277
|
+
# exit code — drives the revise loop. quality_recheck is what halts.
|
|
278
|
+
|
|
279
|
+
- id: fix_quality
|
|
280
|
+
kind: prompt
|
|
281
|
+
depends_on: [quality_gate]
|
|
282
|
+
output_type: quality_fix
|
|
283
|
+
allowed_tools:
|
|
284
|
+
- Read
|
|
285
|
+
- Edit
|
|
286
|
+
- Write
|
|
287
|
+
- Bash
|
|
288
|
+
- mcp__specship__specship_explore
|
|
289
|
+
- mcp__specship__specship_node
|
|
290
|
+
prompt: |
|
|
291
|
+
Lint / typecheck result for the code you just wrote:
|
|
292
|
+
|
|
293
|
+
$quality_gate.output
|
|
294
|
+
|
|
295
|
+
Route on the QUALITY_GATE marker — do not re-judge the raw output:
|
|
296
|
+
|
|
297
|
+
- QUALITY_GATE=passed or QUALITY_GATE=skipped → change NOTHING. Output
|
|
298
|
+
exactly `FIX_QUALITY=not-needed` and stop.
|
|
299
|
+
- QUALITY_GATE=failed → fix every reported error, then re-run the
|
|
300
|
+
QUALITY_CMD shown above to confirm. Fix the code, never the lint
|
|
301
|
+
configuration; never silence or disable a rule to make it pass.
|
|
302
|
+
|
|
303
|
+
Output `FIX_QUALITY=fixed` (clean re-run) or `FIX_QUALITY=still-failing`
|
|
304
|
+
followed by the errors that remain.
|
|
305
|
+
|
|
306
|
+
- id: quality_recheck
|
|
307
|
+
kind: bash
|
|
308
|
+
depends_on: [fix_quality]
|
|
309
|
+
output_type: quality_result
|
|
310
|
+
timeout: 600000
|
|
311
|
+
bash: |
|
|
312
|
+
# REQ-AUTHG-005.A1 — the authoritative half of the gate. The fix node is
|
|
313
|
+
# a prompt, so its "FIX_QUALITY=fixed" claim is a claim, not evidence:
|
|
314
|
+
# this node re-runs the same command and halts the run while it still
|
|
315
|
+
# fails, so failing lint/typecheck never reaches verify, the link node,
|
|
316
|
+
# or the human gate.
|
|
317
|
+
GATE_OUT=$quality_gate.output
|
|
318
|
+
MARKER=$(printf '%s' "$GATE_OUT" | grep -oE 'QUALITY_GATE=[a-z-]+' | tail -n 1 | cut -d= -f2)
|
|
319
|
+
CMD=$(printf '%s' "$GATE_OUT" | grep -E '^QUALITY_CMD=' | tail -n 1 | cut -d= -f2-)
|
|
320
|
+
if [ "$MARKER" = "skipped" ] || [ -z "$CMD" ]; then
|
|
321
|
+
echo "QUALITY_RESULT=skipped"
|
|
322
|
+
echo "This project has no lint or typecheck gate — nothing was checked."
|
|
323
|
+
exit 0
|
|
324
|
+
fi
|
|
325
|
+
if OUT=$($CMD 2>&1); then
|
|
326
|
+
echo "QUALITY_RESULT=clean"
|
|
327
|
+
exit 0
|
|
328
|
+
fi
|
|
329
|
+
qnorm() { sed -E 's/\([0-9]+,[0-9]+\)//g; s/:[0-9]+:[0-9]+/:/g; s/:[0-9]+:/:/g' | sed -E '/^[[:space:]]*$/d' | sort -u; }
|
|
330
|
+
BASELINE="$(git rev-parse --git-dir 2>/dev/null)/specship-quality-baseline.txt"
|
|
331
|
+
if [ -f "$BASELINE" ]; then
|
|
332
|
+
# REQ-AUTHG-008.A2/A3 — only errors absent from the baseline halt.
|
|
333
|
+
NEW=$(printf '%s\n' "$OUT" | qnorm | comm -13 "$BASELINE" - | grep -iE 'error' || true)
|
|
334
|
+
if [ -z "$NEW" ]; then
|
|
335
|
+
echo "QUALITY_RESULT=clean"
|
|
336
|
+
echo "QUALITY_PREEXISTING=$(printf '%s\n' "$OUT" | qnorm | comm -12 "$BASELINE" - | grep -ciE 'error' || true)"
|
|
337
|
+
exit 0
|
|
338
|
+
fi
|
|
339
|
+
echo "QUALITY_RESULT=failed"
|
|
340
|
+
printf '%s\n' "$NEW" | tail -n 80
|
|
341
|
+
else
|
|
342
|
+
echo "QUALITY_RESULT=failed"
|
|
343
|
+
printf '%s\n' "$OUT" | tail -n 80
|
|
344
|
+
fi
|
|
345
|
+
echo "HALT_CAUSE=lint/typecheck still fails after the fix attempt — the change is not reviewable yet"
|
|
346
|
+
exit 1
|
|
347
|
+
|
|
348
|
+
- id: postcheck
|
|
349
|
+
kind: bash
|
|
350
|
+
depends_on: [quality_recheck]
|
|
351
|
+
output_type: postcheck_report
|
|
352
|
+
timeout: 600000
|
|
353
|
+
bash: |
|
|
354
|
+
# REQ-PIPETRUST-005 — check the agent's work mechanically: verifies
|
|
355
|
+
# bullets are real named test symbols covering every criterion, a src
|
|
356
|
+
# change has a CHANGELOG entry, and project-configured checks pass
|
|
357
|
+
# (their fix commands run first). Exit 0 always: the POSTCHECK marker
|
|
358
|
+
# routes the fix step; postcheck_recheck is what halts.
|
|
359
|
+
if [ -n "$SPECSHIP_CLI_SCRIPT" ]; then ss_cli() { "$SPECSHIP_CLI_NODE" "$SPECSHIP_CLI_SCRIPT" "$@"; }; SS=ss_cli
|
|
360
|
+
elif command -v specship >/dev/null 2>&1; then SS=specship
|
|
361
|
+
elif [ -x node_modules/.bin/specship ]; then SS=node_modules/.bin/specship
|
|
362
|
+
else SS=""
|
|
363
|
+
fi
|
|
364
|
+
if [ -z "$SS" ]; then
|
|
365
|
+
echo "POSTCHECK=failed"
|
|
366
|
+
echo "specship CLI not found — postcheck did NOT run"
|
|
367
|
+
exit 0
|
|
368
|
+
fi
|
|
369
|
+
$SS postcheck $INPUT.SPEC_ID --path . --fix || true
|
|
370
|
+
|
|
371
|
+
- id: fix_postcheck
|
|
372
|
+
kind: prompt
|
|
373
|
+
depends_on: [postcheck]
|
|
374
|
+
output_type: postcheck_fix
|
|
375
|
+
allowed_tools:
|
|
376
|
+
- Read
|
|
377
|
+
- Edit
|
|
378
|
+
- Write
|
|
379
|
+
- Bash
|
|
380
|
+
- mcp__specship__specship_spec
|
|
381
|
+
prompt: |
|
|
382
|
+
Mechanical post-implement check for $INPUT.SPEC_ID:
|
|
383
|
+
|
|
384
|
+
$postcheck.output
|
|
385
|
+
|
|
386
|
+
Route on the POSTCHECK marker — do not re-judge:
|
|
387
|
+
|
|
388
|
+
- POSTCHECK=passed → change NOTHING. Output exactly
|
|
389
|
+
`FIX_POSTCHECK=not-needed` and stop.
|
|
390
|
+
- POSTCHECK=failed → fix every ✗ finding:
|
|
391
|
+
- [verifies] — every acceptance criterion needs a test written as a
|
|
392
|
+
NAMED function passed to it(), with the criterion id in the it()
|
|
393
|
+
title, listed under the requirement's `verifies:` block in its spec
|
|
394
|
+
file as `path:FunctionName` (never an it() title string).
|
|
395
|
+
- [changelog] — add a plain-sentence, user-facing entry under
|
|
396
|
+
`## [Unreleased]` in CHANGELOG.md (no internal paths or symbols).
|
|
397
|
+
- [command] — make the named check pass by fixing the cause.
|
|
398
|
+
A bash step re-runs postcheck after you; any finding left halts the run.
|
|
399
|
+
|
|
400
|
+
Output `FIX_POSTCHECK=fixed` or `FIX_POSTCHECK=still-failing` followed
|
|
401
|
+
by what remains.
|
|
402
|
+
|
|
403
|
+
- id: postcheck_recheck
|
|
404
|
+
kind: bash
|
|
405
|
+
depends_on: [fix_postcheck]
|
|
406
|
+
output_type: postcheck_result
|
|
407
|
+
timeout: 600000
|
|
408
|
+
bash: |
|
|
409
|
+
# REQ-PIPETRUST-005.A5 — the authoritative half: re-run and halt while
|
|
410
|
+
# anything still fails, so an unlinked or undocumented change never
|
|
411
|
+
# reaches verify or the human gate.
|
|
412
|
+
if [ -n "$SPECSHIP_CLI_SCRIPT" ]; then ss_cli() { "$SPECSHIP_CLI_NODE" "$SPECSHIP_CLI_SCRIPT" "$@"; }; SS=ss_cli
|
|
413
|
+
elif command -v specship >/dev/null 2>&1; then SS=specship
|
|
414
|
+
elif [ -x node_modules/.bin/specship ]; then SS=node_modules/.bin/specship
|
|
415
|
+
else SS=""
|
|
416
|
+
fi
|
|
417
|
+
if [ -z "$SS" ]; then
|
|
418
|
+
echo "POSTCHECK_RESULT=failed"
|
|
419
|
+
echo "HALT_CAUSE=specship CLI not found — postcheck did NOT run"
|
|
420
|
+
exit 1
|
|
421
|
+
fi
|
|
422
|
+
if OUT=$($SS postcheck $INPUT.SPEC_ID --path . 2>&1); then
|
|
423
|
+
echo "POSTCHECK_RESULT=clean"
|
|
424
|
+
printf '%s\n' "$OUT"
|
|
425
|
+
exit 0
|
|
426
|
+
fi
|
|
427
|
+
echo "POSTCHECK_RESULT=failed"
|
|
428
|
+
printf '%s\n' "$OUT"
|
|
429
|
+
echo "HALT_CAUSE=postcheck still fails after the fix attempt — the change is not reviewable yet"
|
|
430
|
+
exit 1
|
|
431
|
+
|
|
432
|
+
- id: suppression_gate
|
|
433
|
+
kind: bash
|
|
434
|
+
depends_on: [postcheck_recheck]
|
|
435
|
+
output_type: suppression_report
|
|
436
|
+
bash: |
|
|
437
|
+
# REQ-QGATE-004.A3 — deterministic scan for lint/type suppression
|
|
438
|
+
# comments the change introduces (noqa, eslint-disable, @ts-ignore, …).
|
|
439
|
+
# The fix_quality prompt forbids silencing rules; this node enforces it
|
|
440
|
+
# in code. SUPPRESSION_GATE is the marker contract: a scan that could
|
|
441
|
+
# not run is `skipped`, never `clean`.
|
|
442
|
+
# REQ-PIPETRUST-006.A4 — prefer the CLI running this workflow over any
|
|
443
|
+
# (possibly older) `specship` on PATH.
|
|
444
|
+
if [ -n "$SPECSHIP_CLI_SCRIPT" ]; then ss_cli() { "$SPECSHIP_CLI_NODE" "$SPECSHIP_CLI_SCRIPT" "$@"; }; SS=ss_cli
|
|
445
|
+
elif command -v specship >/dev/null 2>&1; then SS=specship
|
|
446
|
+
elif [ -x node_modules/.bin/specship ]; then SS=node_modules/.bin/specship
|
|
447
|
+
elif [ -x dist/bin/specship.js ]; then SS="node dist/bin/specship.js"
|
|
448
|
+
else SS=""; fi
|
|
449
|
+
if [ -z "$SS" ]; then
|
|
450
|
+
echo "SUPPRESSION_GATE=skipped"
|
|
451
|
+
echo "SUPPRESSION_REASON=specship CLI not found — suppression scan did NOT run"
|
|
452
|
+
exit 0
|
|
453
|
+
fi
|
|
454
|
+
if OUT=$($SS suppressions 2>&1); then
|
|
455
|
+
printf '%s\n' "$OUT"
|
|
456
|
+
else
|
|
457
|
+
printf '%s\n' "$OUT"
|
|
458
|
+
echo "HALT_CAUSE=the change introduces lint/type suppression comments — fix the code instead of silencing the rule"
|
|
459
|
+
exit 1
|
|
460
|
+
fi
|
|
461
|
+
|
|
462
|
+
- id: diff
|
|
463
|
+
kind: bash
|
|
464
|
+
depends_on: [suppression_gate]
|
|
465
|
+
output_type: diff
|
|
466
|
+
bash: |
|
|
467
|
+
# REQ-AUTHG-004.A1 — the full diff, from git, into a run artifact. The
|
|
468
|
+
# human gate and the adversarial reviewer read THIS; the implement node's
|
|
469
|
+
# prose about what it believes it changed is not the change.
|
|
470
|
+
# `git add -A -N` registers new files as intent-to-add so untracked work
|
|
471
|
+
# appears in `git diff HEAD` without staging any content.
|
|
472
|
+
git add -A -N >/dev/null 2>&1 || true
|
|
473
|
+
echo "DIFF_BEGIN"
|
|
474
|
+
git --no-pager diff HEAD | head -c 400000
|
|
475
|
+
echo
|
|
476
|
+
echo "DIFF_END"
|
|
477
|
+
|
|
478
|
+
- id: diff_stat
|
|
479
|
+
kind: bash
|
|
480
|
+
depends_on: [diff]
|
|
481
|
+
output_type: diff_stat
|
|
482
|
+
bash: |
|
|
483
|
+
# REQ-AUTHG-004.A2 — the stat block the final gate shows: file names and
|
|
484
|
+
# insertions/deletions counted by git. Its own small node so the approval
|
|
485
|
+
# message carries the summary while the full diff stays in the `diff`
|
|
486
|
+
# artifact.
|
|
487
|
+
echo "DIFF_STAT_BEGIN"
|
|
488
|
+
git --no-pager diff HEAD --stat
|
|
489
|
+
echo "DIFF_STAT_END"
|
|
490
|
+
|
|
491
|
+
- id: verify
|
|
492
|
+
kind: bash
|
|
493
|
+
depends_on: [diff_stat]
|
|
106
494
|
output_type: test_results
|
|
107
495
|
timeout: 600000
|
|
108
496
|
bash: |
|
|
@@ -111,43 +499,110 @@ nodes:
|
|
|
111
499
|
# The VERIFY_RESULT marker is the machine-readable contract the link
|
|
112
500
|
# node routes on (REQ-IMPLINT-001.A1): a skipped run must never be
|
|
113
501
|
# mistaken for a passing one.
|
|
502
|
+
# Install and build failures fail fast with their own markers
|
|
503
|
+
# (REQ-REVINT-006.A1) — a broken environment or a build break is NOT a
|
|
504
|
+
# test failure, and must never be attributed to one.
|
|
114
505
|
if [ -f package.json ]; then
|
|
115
506
|
# A fresh worktree has no node_modules/ or build output — a verify
|
|
116
507
|
# failure must mean the tests failed, not that the environment was
|
|
117
508
|
# missing (WF-REJECT-DOC, REQ-WFREJ-005).
|
|
118
|
-
if [ ! -d node_modules ]; then
|
|
119
|
-
|
|
120
|
-
|
|
509
|
+
if [ ! -d node_modules ]; then
|
|
510
|
+
if ! { npm ci --no-audit --no-fund || npm install --no-audit --no-fund; }; then
|
|
511
|
+
echo "VERIFY_RESULT=env-failed"; exit 1
|
|
512
|
+
fi
|
|
513
|
+
fi
|
|
514
|
+
if ! npm run build --if-present; then echo "VERIFY_RESULT=build-failed"; exit 1; fi
|
|
515
|
+
# REQ-PIPETRUST-006.A3 — a vitest project also leaves a JSON report in
|
|
516
|
+
# the run's artifacts, ingestible with `specship verify --report`.
|
|
517
|
+
TEST_ARGS=""
|
|
518
|
+
if [ -n "$SPECSHIP_ARTIFACTS_DIR" ] && node -e 'const s=((require("./package.json").scripts)||{}).test||"";process.exit(/^\s*vitest\b/.test(s)?0:1)' 2>/dev/null; then
|
|
519
|
+
mkdir -p "$SPECSHIP_ARTIFACTS_DIR"
|
|
520
|
+
REPORT="$SPECSHIP_ARTIFACTS_DIR/test-report.json"
|
|
521
|
+
TEST_ARGS="-- --reporter=default --reporter=json --outputFile.json=$REPORT"
|
|
522
|
+
echo "VERIFY_REPORT=$REPORT (ingest after merge: specship verify --report $REPORT)"
|
|
523
|
+
fi
|
|
524
|
+
if npm test $TEST_ARGS; then echo "VERIFY_RESULT=ran-and-passed"; else echo "VERIFY_RESULT=ran-and-failed"; exit 1; fi
|
|
121
525
|
elif [ -f Cargo.toml ]; then
|
|
526
|
+
if ! cargo build; then echo "VERIFY_RESULT=build-failed"; exit 1; fi
|
|
122
527
|
if cargo test; then echo "VERIFY_RESULT=ran-and-passed"; else echo "VERIFY_RESULT=ran-and-failed"; exit 1; fi
|
|
123
528
|
elif [ -f pyproject.toml ] || [ -f requirements.txt ]; then
|
|
529
|
+
if ! python -c 'import pytest' 2>/dev/null; then echo "VERIFY_RESULT=env-failed"; exit 1; fi
|
|
124
530
|
if python -m pytest; then echo "VERIFY_RESULT=ran-and-passed"; else echo "VERIFY_RESULT=ran-and-failed"; exit 1; fi
|
|
125
531
|
else
|
|
126
532
|
echo "no recognised test framework; tests did NOT run"
|
|
127
533
|
echo "VERIFY_RESULT=skipped"
|
|
128
534
|
fi
|
|
129
535
|
|
|
536
|
+
- id: route_verify
|
|
537
|
+
kind: bash
|
|
538
|
+
depends_on: [verify]
|
|
539
|
+
output_type: verify_route
|
|
540
|
+
bash: |
|
|
541
|
+
# Deterministic verify routing (REQ-VSTATE-005.A1): the VERIFY_RESULT
|
|
542
|
+
# marker is parsed HERE, in code, and turned into a LINK_ACTION the link
|
|
543
|
+
# node obeys. It used to be a prompt reading a test log — the one decision
|
|
544
|
+
# that governs whether links may be promoted was hallucinable.
|
|
545
|
+
VERIFY_OUT=$verify.output
|
|
546
|
+
MARKER=$(printf '%s' "$VERIFY_OUT" | grep -oE 'VERIFY_RESULT=[a-z-]+' | tail -n 1 | cut -d= -f2)
|
|
547
|
+
[ -n "$MARKER" ] || MARKER=missing
|
|
548
|
+
echo "VERIFY_RESULT=$MARKER"
|
|
549
|
+
# env-failed / build-failed halt BEFORE any link mutation, naming the
|
|
550
|
+
# environment cause (REQ-VSTATE-005.A3) — neither is a test failure.
|
|
551
|
+
case "$MARKER" in
|
|
552
|
+
ran-and-passed)
|
|
553
|
+
echo "LINK_ACTION=assert-and-verify-pass" ;;
|
|
554
|
+
ran-and-failed)
|
|
555
|
+
echo "LINK_ACTION=assert-and-verify-fail" ;;
|
|
556
|
+
skipped)
|
|
557
|
+
echo "LINK_ACTION=assert-only" ;;
|
|
558
|
+
env-failed)
|
|
559
|
+
echo "HALT_CAUSE=environment setup failed (dependency install) — nothing is known about the tests"
|
|
560
|
+
exit 1 ;;
|
|
561
|
+
build-failed)
|
|
562
|
+
echo "HALT_CAUSE=build failed — nothing is known about the tests"
|
|
563
|
+
exit 1 ;;
|
|
564
|
+
*)
|
|
565
|
+
echo "HALT_CAUSE=no VERIFY_RESULT marker found in the verify output — an unknown result is never a pass"
|
|
566
|
+
exit 1 ;;
|
|
567
|
+
esac
|
|
568
|
+
|
|
130
569
|
- id: link
|
|
131
570
|
kind: prompt
|
|
132
|
-
depends_on: [
|
|
571
|
+
depends_on: [route_verify]
|
|
133
572
|
output_type: link_summary
|
|
134
573
|
allowed_tools:
|
|
135
|
-
-
|
|
136
|
-
-
|
|
574
|
+
- Read
|
|
575
|
+
- Edit
|
|
137
576
|
- mcp__specship__specship_spec
|
|
138
577
|
prompt: |
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
-
|
|
149
|
-
|
|
150
|
-
|
|
578
|
+
Record spec→code links for the changes made in the implement step —
|
|
579
|
+
durably, in the spec file (REQ-PIPETRUST-006). Do NOT call
|
|
580
|
+
specship_link_assert or specship_link_verify: runtime links vanish on a
|
|
581
|
+
full reindex, and a headless run cannot be granted them.
|
|
582
|
+
|
|
583
|
+
Open the spec file that declares $INPUT.SPEC_ID. Under the requirement:
|
|
584
|
+
- `implementations:` — one `path:Symbol` bullet per symbol that
|
|
585
|
+
implements it (qualified `Class.method` for methods). Add any that
|
|
586
|
+
are missing; never duplicate an existing bullet.
|
|
587
|
+
- `verifies:` — leave as the postcheck step left it (named test
|
|
588
|
+
functions only). Never add an it() title string.
|
|
589
|
+
|
|
590
|
+
You MUST NOT assert a `tests`-kind link (REQ-REVINT-005.A1) —
|
|
591
|
+
never pass kind: 'tests', and never mint test evidence: it comes only
|
|
592
|
+
from the spec's `verifies:` block or an `@verifies` comment on a test
|
|
593
|
+
symbol.
|
|
594
|
+
|
|
595
|
+
Verification state is not yours to set, so you
|
|
596
|
+
do NOT call specship_link_verify, whatever LINK_ACTION says. On
|
|
597
|
+
LINK_ACTION=assert-and-verify-pass, LINK_ACTION=assert-and-verify-fail
|
|
598
|
+
or LINK_ACTION=assert-only alike, record the implementations bullets
|
|
599
|
+
only: tests that ran are in the run's JSON test report (see the verify
|
|
600
|
+
output) and are ingested with `specship verify --report` after the
|
|
601
|
+
branch merges; tests that did not run are never reported as passing.
|
|
602
|
+
|
|
603
|
+
Routing context (computed by a bash node from VERIFY_RESULT):
|
|
604
|
+
|
|
605
|
+
$route_verify.output
|
|
151
606
|
|
|
152
607
|
Implementation diff summary:
|
|
153
608
|
$implement.output
|
|
@@ -155,39 +610,244 @@ nodes:
|
|
|
155
610
|
Test results:
|
|
156
611
|
$verify.output
|
|
157
612
|
|
|
158
|
-
Output: a short list of "spec_id → file:symbol
|
|
159
|
-
|
|
160
|
-
skipped.
|
|
613
|
+
Output: a short list of "spec_id → file:symbol" lines you recorded,
|
|
614
|
+
ending with the VERIFY_REPORT line from the verify output if present.
|
|
161
615
|
|
|
162
616
|
- id: coverage
|
|
163
|
-
kind:
|
|
617
|
+
kind: bash
|
|
164
618
|
depends_on: [link]
|
|
165
619
|
output_type: coverage_summary
|
|
620
|
+
bash: |
|
|
621
|
+
# The acceptance-criteria coverage line is computed FROM THE DB
|
|
622
|
+
# (REQ-VSTATE-005.A2) — `specship coverage --line` renders the same
|
|
623
|
+
# `getSpecCoverage` report the MCP tool and the dashboard read, so the
|
|
624
|
+
# number on the approval gate cannot disagree with them. It used to be
|
|
625
|
+
# counted by a prompt.
|
|
626
|
+
# REQ-PIPETRUST-006.A4 — prefer the CLI running this workflow over any
|
|
627
|
+
# (possibly older) `specship` on PATH.
|
|
628
|
+
if [ -n "$SPECSHIP_CLI_SCRIPT" ]; then ss_cli() { "$SPECSHIP_CLI_NODE" "$SPECSHIP_CLI_SCRIPT" "$@"; }; SS=ss_cli
|
|
629
|
+
elif command -v specship >/dev/null 2>&1; then SS=specship
|
|
630
|
+
elif [ -x node_modules/.bin/specship ]; then SS=node_modules/.bin/specship
|
|
631
|
+
elif [ -x dist/bin/specship.js ]; then SS="node dist/bin/specship.js"
|
|
632
|
+
else SS=""; fi
|
|
633
|
+
if [ -z "$SS" ]; then
|
|
634
|
+
echo "COVERAGE_UNAVAILABLE=specship CLI not found — acceptance-criteria coverage was NOT computed"
|
|
635
|
+
exit 0
|
|
636
|
+
fi
|
|
637
|
+
LINE=$($SS coverage $INPUT.SPEC_ID --line) || {
|
|
638
|
+
echo "COVERAGE_UNAVAILABLE=specship coverage failed — coverage was NOT computed"
|
|
639
|
+
exit 0
|
|
640
|
+
}
|
|
641
|
+
echo "$LINE"
|
|
642
|
+
N=$(printf '%s' "$LINE" | awk '{print $1}')
|
|
643
|
+
M=$(printf '%s' "$LINE" | awk '{print $3}')
|
|
644
|
+
if [ "$N" != "$M" ]; then
|
|
645
|
+
echo "Close the gap with /specship:spec behaviour $INPUT.SPEC_ID."
|
|
646
|
+
fi
|
|
647
|
+
|
|
648
|
+
- id: adversarial_review
|
|
649
|
+
kind: prompt
|
|
650
|
+
depends_on: [coverage]
|
|
651
|
+
output_type: adversarial_review
|
|
652
|
+
allowed_tools:
|
|
653
|
+
- Read
|
|
654
|
+
- Grep
|
|
655
|
+
- mcp__specship__specship_spec
|
|
656
|
+
- mcp__specship__specship_explore
|
|
657
|
+
- mcp__specship__specship_node
|
|
658
|
+
- mcp__specship__specship_search
|
|
659
|
+
prompt: |
|
|
660
|
+
Adversarial review (REQ-AUTHG-005.A3). You are NOT the implementer — your
|
|
661
|
+
job is to find what the implementation missed. This node is read-only:
|
|
662
|
+
you have no Edit, Write or Bash tool and must not try to fix anything.
|
|
663
|
+
|
|
664
|
+
Call specship_spec($INPUT.SPEC_ID) and read the spec body, including
|
|
665
|
+
every acceptance criterion.
|
|
666
|
+
|
|
667
|
+
The change under review (from git, not from the implementer's summary):
|
|
668
|
+
|
|
669
|
+
$diff.output
|
|
670
|
+
|
|
671
|
+
Report this and nothing else:
|
|
672
|
+
|
|
673
|
+
1. One line per acceptance criterion:
|
|
674
|
+
`<AC id>: satisfied | partial | unaddressed — <one sentence, grounded
|
|
675
|
+
in the diff>`. Judge from the diff and the code you read; "the
|
|
676
|
+
implementer said so" is not evidence.
|
|
677
|
+
2. `Untested new code paths:` the branches/functions this diff adds that
|
|
678
|
+
no test in the diff exercises (`none` if there are none).
|
|
679
|
+
3. `Verdict:` one line — the most serious gap a reviewer should look at
|
|
680
|
+
first, or `no gaps found`.
|
|
681
|
+
|
|
682
|
+
- id: probe_baseline
|
|
683
|
+
kind: bash
|
|
684
|
+
depends_on: [adversarial_review]
|
|
685
|
+
output_type: probe_baseline
|
|
686
|
+
bash: |
|
|
687
|
+
# REQ-THRU-008 — fingerprint every tracked change before the probe step,
|
|
688
|
+
# so the guard can prove the probes touched nothing tracked.
|
|
689
|
+
git add -A -N >/dev/null 2>&1 || true
|
|
690
|
+
git --no-pager diff HEAD | git hash-object --stdin > "$(git rev-parse --git-dir)/specship-probe-baseline"
|
|
691
|
+
echo "PROBE_BASELINE=recorded"
|
|
692
|
+
|
|
693
|
+
- id: review_probes
|
|
694
|
+
kind: prompt
|
|
695
|
+
depends_on: [probe_baseline]
|
|
696
|
+
output_type: review_probes
|
|
166
697
|
allowed_tools:
|
|
698
|
+
- Read
|
|
699
|
+
- Write
|
|
700
|
+
- Bash
|
|
167
701
|
- mcp__specship__specship_spec
|
|
168
702
|
prompt: |
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
703
|
+
Try to BREAK the change for $INPUT.SPEC_ID (REQ-THRU-008). You are not
|
|
704
|
+
the implementer. For EACH acceptance criterion write at least one small
|
|
705
|
+
probe test that would fail if the criterion were not really met — an
|
|
706
|
+
edge case, a boundary, a negative case — ONLY under
|
|
707
|
+
`.specship/review-probes/` (create it). NEVER edit any tracked file: a
|
|
708
|
+
guard step fails the run if you do.
|
|
709
|
+
|
|
710
|
+
Run each probe with the project's test runner. Report one line per
|
|
711
|
+
criterion: `<AC id>: held | broke | unrun — <probe file> — <one
|
|
712
|
+
sentence>`. `unrun` means the probe could not be executed (say why);
|
|
713
|
+
never report a probe you did not run as held.
|
|
714
|
+
|
|
715
|
+
The read-only review already found:
|
|
716
|
+
$adversarial_review.output
|
|
717
|
+
|
|
718
|
+
The change (from git):
|
|
719
|
+
$diff.output
|
|
720
|
+
|
|
721
|
+
- id: review_guard
|
|
722
|
+
kind: bash
|
|
723
|
+
depends_on: [review_probes]
|
|
724
|
+
output_type: review_guard
|
|
725
|
+
bash: |
|
|
726
|
+
# REQ-THRU-008.A2 — the probe step may not change tracked files.
|
|
727
|
+
git add -A -N >/dev/null 2>&1 || true
|
|
728
|
+
NOW=$(git --no-pager diff HEAD | git hash-object --stdin)
|
|
729
|
+
BEFORE=$(cat "$(git rev-parse --git-dir)/specship-probe-baseline" 2>/dev/null)
|
|
730
|
+
if [ -n "$BEFORE" ] && [ "$NOW" != "$BEFORE" ]; then
|
|
731
|
+
echo "REVIEW_GUARD=failed"
|
|
732
|
+
echo "HALT_CAUSE=the probe step changed tracked files — probes belong under .specship/review-probes/"
|
|
733
|
+
git --no-pager diff --stat HEAD
|
|
734
|
+
exit 1
|
|
735
|
+
fi
|
|
736
|
+
echo "REVIEW_GUARD=clean"
|
|
737
|
+
|
|
738
|
+
- id: knowledge_proposals
|
|
739
|
+
kind: prompt
|
|
740
|
+
depends_on: [review_guard]
|
|
741
|
+
output_type: knowledge_proposals
|
|
742
|
+
allowed_tools:
|
|
743
|
+
- Read
|
|
744
|
+
- Write
|
|
745
|
+
- mcp__specship__specship_spec
|
|
746
|
+
- mcp__specship__specship_explore
|
|
747
|
+
prompt: |
|
|
748
|
+
Propose knowledge this change relied on, for a HUMAN to confirm
|
|
749
|
+
(REQ-KNOW-004). Domain knowledge is human-confirmed, never
|
|
750
|
+
auto-extracted (DOM-SPECSHIP-003): you only PROPOSE.
|
|
174
751
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
752
|
+
Write 0–5 proposal files, one fact each, ONLY under
|
|
753
|
+
`.specship/knowledge/proposals/` (create the directory). NEVER edit
|
|
754
|
+
`specs/domain/` or any tracked file. Each file is a domain fact:
|
|
755
|
+
|
|
756
|
+
---
|
|
757
|
+
title: <short name>
|
|
758
|
+
type: term | rule | decision | constraint | external
|
|
759
|
+
area: <AREA, e.g. the prefix used by existing DOM-<AREA>-NNN facts>
|
|
760
|
+
depends_on: $INPUT.SPEC_ID
|
|
761
|
+
# external facts ONLY — verified from the installed dependency, not memory:
|
|
762
|
+
dependency: <package or tool name>
|
|
763
|
+
version: <installed version you verified against>
|
|
764
|
+
source: <file and symbol in that dependency>
|
|
765
|
+
---
|
|
766
|
+
|
|
767
|
+
# <title>
|
|
768
|
+
|
|
769
|
+
<one paragraph: the fact, stated plainly>
|
|
770
|
+
|
|
771
|
+
## Enforced (optional — only for a mechanically checkable rule)
|
|
772
|
+
- `<glob>` must not match `/<regex>/`
|
|
773
|
+
|
|
774
|
+
Propose only what this change actually depended on and a future change
|
|
775
|
+
would otherwise rediscover — especially facts about third-party tools.
|
|
776
|
+
If there is nothing worth keeping, write no files.
|
|
777
|
+
|
|
778
|
+
Implementation diff summary:
|
|
779
|
+
$implement.output
|
|
780
|
+
|
|
781
|
+
Output one line per proposal file you wrote, or `NO_PROPOSALS`.
|
|
782
|
+
|
|
783
|
+
- id: knowledge_publish
|
|
784
|
+
kind: bash
|
|
785
|
+
depends_on: [knowledge_proposals]
|
|
786
|
+
output_type: knowledge_report
|
|
787
|
+
bash: |
|
|
788
|
+
# REQ-KNOW-004.A1 — the proposal step may write ONLY proposals. Any
|
|
789
|
+
# change under specs/domain/ halts the run. Proposals are then copied to
|
|
790
|
+
# the main project's .specship/knowledge/proposals/ (a run worktree's
|
|
791
|
+
# .specship/ is gitignored and would vanish), where
|
|
792
|
+
# `specship knowledge proposals` / `apply` / `reject` find them.
|
|
793
|
+
if [ -n "$(git status --porcelain -- specs/domain 2>/dev/null)" ]; then
|
|
794
|
+
echo "KNOWLEDGE_PROPOSALS=refused"
|
|
795
|
+
echo "HALT_CAUSE=the knowledge step changed specs/domain/ — only a human applies knowledge"
|
|
796
|
+
git status --porcelain -- specs/domain
|
|
797
|
+
exit 1
|
|
798
|
+
fi
|
|
799
|
+
SRC=".specship/knowledge/proposals"
|
|
800
|
+
N=0
|
|
801
|
+
if [ -d "$SRC" ]; then N=$(ls "$SRC"/*.md 2>/dev/null | wc -l | tr -d ' '); fi
|
|
802
|
+
echo "KNOWLEDGE_PROPOSALS=$N"
|
|
803
|
+
if [ "$N" -gt 0 ] && [ -n "$SPECSHIP_ARTIFACTS_DIR" ]; then
|
|
804
|
+
DEST="$(cd "$SPECSHIP_ARTIFACTS_DIR/../../.." 2>/dev/null && pwd)/knowledge/proposals"
|
|
805
|
+
mkdir -p "$DEST"
|
|
806
|
+
for f in "$SRC"/*.md; do
|
|
807
|
+
base=$(basename "$f")
|
|
808
|
+
target="$DEST/$base"
|
|
809
|
+
i=2
|
|
810
|
+
while [ -e "$target" ]; do target="$DEST/${base%.md}-$i.md"; i=$((i+1)); done
|
|
811
|
+
cp "$f" "$target"
|
|
812
|
+
echo "- $(basename "$target") ($(sed -n 's/^title: //p' "$f" | head -1))"
|
|
813
|
+
done
|
|
814
|
+
echo "Review with: specship knowledge proposals · apply <id> · reject <id>"
|
|
815
|
+
fi
|
|
179
816
|
|
|
180
817
|
- id: final_review
|
|
181
818
|
kind: approval
|
|
182
|
-
depends_on: [
|
|
819
|
+
depends_on: [adversarial_review, knowledge_publish]
|
|
183
820
|
message: |
|
|
184
821
|
Implementation complete for $INPUT.SPEC_ID.
|
|
185
822
|
|
|
186
|
-
|
|
823
|
+
Changes (git diff --stat — measured, not summarized):
|
|
824
|
+
$diff_stat.output
|
|
825
|
+
|
|
826
|
+
Lint / typecheck:
|
|
827
|
+
$quality_recheck.output
|
|
828
|
+
|
|
829
|
+
Mechanical postcheck (verifies symbols, CHANGELOG, project checks):
|
|
830
|
+
$postcheck_recheck.output
|
|
831
|
+
|
|
832
|
+
Suppression scan (new noqa / eslint-disable / @ts-ignore):
|
|
833
|
+
$suppression_gate.output
|
|
834
|
+
|
|
835
|
+
Links recorded in the spec (ingest the test report after merge with the
|
|
836
|
+
`specship verify --report` command named here):
|
|
187
837
|
$link.output
|
|
188
838
|
|
|
189
839
|
Acceptance-criteria test coverage:
|
|
190
840
|
$coverage.output
|
|
191
841
|
|
|
842
|
+
Adversarial review:
|
|
843
|
+
$adversarial_review.output
|
|
844
|
+
|
|
845
|
+
Review probes (held | broke | unrun per criterion):
|
|
846
|
+
$review_probes.output
|
|
847
|
+
|
|
848
|
+
Knowledge proposals (nothing is applied until you run
|
|
849
|
+
`specship knowledge apply <id>`):
|
|
850
|
+
$knowledge_publish.output
|
|
851
|
+
|
|
192
852
|
Approve to finalize the run (worktree is left for you to inspect
|
|
193
853
|
and merge), or reject to abandon.
|