@opengsd/gsd-core 1.18.0 → 1.20.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 (308) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +2 -1
  3. package/.opencode/plugins/gsd-core.js +2 -3
  4. package/agents/gsd-code-fixer.compact.md +7 -7
  5. package/agents/gsd-code-fixer.md +13 -7
  6. package/agents/gsd-code-reviewer.compact.md +49 -8
  7. package/agents/gsd-code-reviewer.md +53 -14
  8. package/agents/gsd-executor.md +8 -4
  9. package/agents/gsd-verifier.md +1 -1
  10. package/bin/install.js +422 -103
  11. package/commands/gsd/update.md +5 -2
  12. package/gsd-core/bin/gsd-tools.cjs +179 -30
  13. package/gsd-core/bin/lib/agent-install-check.cjs +29 -3
  14. package/gsd-core/bin/lib/args-terminator.cjs +114 -0
  15. package/gsd-core/bin/lib/broken-windows.cjs +59 -1
  16. package/gsd-core/bin/lib/capability-lifecycle.cjs +1 -12
  17. package/gsd-core/bin/lib/capability-lock.cjs +13 -2
  18. package/gsd-core/bin/lib/capability-registry.cjs +376 -103
  19. package/gsd-core/bin/lib/capability-state.cjs +14 -8
  20. package/gsd-core/bin/lib/capability-validator.cjs +32 -0
  21. package/gsd-core/bin/lib/commands.cjs +27 -17
  22. package/gsd-core/bin/lib/config-loader.cjs +13 -3
  23. package/gsd-core/bin/lib/config.cjs +256 -58
  24. package/gsd-core/bin/lib/core-utils.cjs +45 -0
  25. package/gsd-core/bin/lib/decision-coverage-support.cjs +74 -0
  26. package/gsd-core/bin/lib/frontmatter.cjs +21 -3
  27. package/gsd-core/bin/lib/gate-api-coverage-verify-pre.cjs +2 -2
  28. package/gsd-core/bin/lib/gate-context-drift.cjs +9 -4
  29. package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +6 -1
  30. package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +6 -1
  31. package/gsd-core/bin/lib/gate-evaluation-scope.cjs +134 -13
  32. package/gsd-core/bin/lib/gate-phase-context.cjs +7 -8
  33. package/gsd-core/bin/lib/gate-schema-drift.cjs +1 -1
  34. package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +63 -22
  35. package/gsd-core/bin/lib/gate-ui-safety.cjs +23 -5
  36. package/gsd-core/bin/lib/git-info-exclude.cjs +52 -0
  37. package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +31 -12
  38. package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +9 -7
  39. package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +3 -3
  40. package/gsd-core/bin/lib/health-diagnostic-types.cjs +4 -0
  41. package/gsd-core/bin/lib/health-diagnostic.cjs +52 -1
  42. package/gsd-core/bin/lib/host-integration.cjs +13 -6
  43. package/gsd-core/bin/lib/init.cjs +245 -68
  44. package/gsd-core/bin/lib/install-engine.cjs +246 -32
  45. package/gsd-core/bin/lib/install-profiles.cjs +9 -4
  46. package/gsd-core/bin/lib/installer-migration-report.cjs +2 -0
  47. package/gsd-core/bin/lib/io.cjs +6 -0
  48. package/gsd-core/bin/lib/markdown-line-diff.cjs +147 -0
  49. package/gsd-core/bin/lib/markdown-sectionizer.cjs +147 -1
  50. package/gsd-core/bin/lib/markdown-table.cjs +23 -0
  51. package/gsd-core/bin/lib/mcp-server.cjs +8 -5
  52. package/gsd-core/bin/lib/milestone-lock.cjs +8 -1
  53. package/gsd-core/bin/lib/milestone-release-map.cjs +244 -0
  54. package/gsd-core/bin/lib/milestone-release-tags.cjs +440 -0
  55. package/gsd-core/bin/lib/milestone.cjs +61 -51
  56. package/gsd-core/bin/lib/model-catalog.cjs +8 -0
  57. package/gsd-core/bin/lib/normalize-test-command.cjs +67 -0
  58. package/gsd-core/bin/lib/phase-entry-grammar.cjs +119 -0
  59. package/gsd-core/bin/lib/phase-id-display.cjs +2 -0
  60. package/gsd-core/bin/lib/phase-id.cjs +629 -38
  61. package/gsd-core/bin/lib/phase-lifecycle.cjs +12 -44
  62. package/gsd-core/bin/lib/phase-locator.cjs +328 -19
  63. package/gsd-core/bin/lib/phase.cjs +3066 -653
  64. package/gsd-core/bin/lib/planning-document.cjs +26 -5
  65. package/gsd-core/bin/lib/planning-inspect.cjs +27 -35
  66. package/gsd-core/bin/lib/planning-snapshot.cjs +15 -8
  67. package/gsd-core/bin/lib/planning-workspace.cjs +21 -3
  68. package/gsd-core/bin/lib/pristine-baseline.cjs +11 -3
  69. package/gsd-core/bin/lib/read-only-git-env.cjs +79 -0
  70. package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +2 -2
  71. package/gsd-core/bin/lib/review-lane-descriptor.cjs +57 -2
  72. package/gsd-core/bin/lib/review-lane-invocation.cjs +125 -18
  73. package/gsd-core/bin/lib/review-lane-runner.cjs +33 -4
  74. package/gsd-core/bin/lib/reviewer-step-dispatch.cjs +11 -9
  75. package/gsd-core/bin/lib/roadmap-parser.cjs +735 -137
  76. package/gsd-core/bin/lib/roadmap-progress.cjs +136 -0
  77. package/gsd-core/bin/lib/roadmap-upgrade.cjs +47 -7
  78. package/gsd-core/bin/lib/roadmap.cjs +383 -123
  79. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +381 -14
  80. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +8 -4
  81. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +60 -16
  82. package/gsd-core/bin/lib/shell-command-projection.cjs +151 -19
  83. package/gsd-core/bin/lib/smart-entry.cjs +35 -11
  84. package/gsd-core/bin/lib/state-contract.cjs +39 -15
  85. package/gsd-core/bin/lib/state-document.cjs +344 -27
  86. package/gsd-core/bin/lib/state-transition.cjs +156 -32
  87. package/gsd-core/bin/lib/state.cjs +527 -186
  88. package/gsd-core/bin/lib/surface.cjs +9 -0
  89. package/gsd-core/bin/lib/task-command-router.cjs +5 -25
  90. package/gsd-core/bin/lib/task-content-resolution.cjs +46 -1
  91. package/gsd-core/bin/lib/template.cjs +2 -2
  92. package/gsd-core/bin/lib/validate.cjs +3 -2
  93. package/gsd-core/bin/lib/vendor/re2js.cjs +863 -577
  94. package/gsd-core/bin/lib/vendor/re2js.d.cts +284 -219
  95. package/gsd-core/bin/lib/verification.cjs +96 -9
  96. package/gsd-core/bin/lib/verify.cjs +4 -2
  97. package/gsd-core/bin/lib/workstream-inventory.cjs +26 -20
  98. package/gsd-core/bin/lib/worktree-safety.cjs +22 -1
  99. package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
  100. package/gsd-core/bin/shared/config-schema.manifest.json +1 -0
  101. package/gsd-core/bin/verify-reapply-patches.cjs +411 -10
  102. package/gsd-core/references/cicd-review-patterns.md +45 -0
  103. package/gsd-core/references/git-integration.md +11 -0
  104. package/gsd-core/references/loop-hook-dispatch.md +13 -6
  105. package/gsd-core/references/necessity-review.md +48 -0
  106. package/gsd-core/references/planning-config.md +2 -0
  107. package/gsd-core/references/tdd.md +2 -2
  108. package/gsd-core/templates/DEBUG.md +16 -0
  109. package/gsd-core/templates/config.json +2 -1
  110. package/gsd-core/templates/verification-report.md +1 -1
  111. package/gsd-core/workflows/audit-fix.md +2 -1
  112. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +10 -1
  113. package/gsd-core/workflows/code-review-fix.md +46 -5
  114. package/gsd-core/workflows/code-review.md +64 -7
  115. package/gsd-core/workflows/complete-milestone/steps/project-md-evolution-review.md +145 -0
  116. package/gsd-core/workflows/complete-milestone/steps/release-map.md +80 -0
  117. package/gsd-core/workflows/complete-milestone.md +37 -150
  118. package/gsd-core/workflows/diagnose-issues.md +29 -5
  119. package/gsd-core/workflows/discuss-phase/modes/power.md +1 -1
  120. package/gsd-core/workflows/discuss-phase-assumptions.md +33 -2
  121. package/gsd-core/workflows/discuss-phase-power.md +19 -2
  122. package/gsd-core/workflows/discuss-phase.md +6 -10
  123. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +13 -7
  124. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +7 -2
  125. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -1
  126. package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +2 -2
  127. package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +11 -2
  128. package/gsd-core/workflows/execute-phase.md +10 -6
  129. package/gsd-core/workflows/execute-plan.md +1 -1
  130. package/gsd-core/workflows/health.md +2 -1
  131. package/gsd-core/workflows/import.md +1 -1
  132. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +2 -2
  133. package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +13 -9
  134. package/gsd-core/workflows/plan-phase.md +14 -14
  135. package/gsd-core/workflows/pr-branch.md +2 -0
  136. package/gsd-core/workflows/quick/steps/plan-checker-loop.md +1 -1
  137. package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +8 -1
  138. package/gsd-core/workflows/quick-batch/steps/plan-checker-loop.md +2 -1
  139. package/gsd-core/workflows/quick.md +1 -1
  140. package/gsd-core/workflows/reapply-patches.md +104 -0
  141. package/gsd-core/workflows/review.md +70 -154
  142. package/gsd-core/workflows/section-manifest.json +5 -0
  143. package/gsd-core/workflows/secure-phase.md +1 -1
  144. package/gsd-core/workflows/settings-advanced.md +57 -9
  145. package/gsd-core/workflows/settings.md +1 -0
  146. package/gsd-core/workflows/ship.md +15 -4
  147. package/gsd-core/workflows/spec-phase.md +3 -6
  148. package/gsd-core/workflows/verify-work.md +4 -3
  149. package/hooks/dist/gsd-agent-isolation-guard.js +11 -1
  150. package/hooks/dist/gsd-cursor-subagent-start.js +6 -2
  151. package/hooks/dist/gsd-graphify-update.sh +6 -0
  152. package/hooks/dist/gsd-path-export.js +95 -0
  153. package/hooks/dist/gsd-secret-read-guard.js +172 -39
  154. package/hooks/dist/gsd-statusline.js +37 -3
  155. package/hooks/dist/gsd-windsurf-pre-write.js +29 -2
  156. package/hooks/dist/gsd-workflow-guard.js +3 -2
  157. package/hooks/dist/gsd-worktree-path-guard.js +29 -2
  158. package/hooks/dist/lib/git-probe.js +16 -0
  159. package/hooks/dist/lib/isolation-sentinel.js +44 -0
  160. package/hooks/dist/managed-hooks-registry.cjs +1 -0
  161. package/hooks/gsd-agent-isolation-guard.js +11 -1
  162. package/hooks/gsd-cursor-subagent-start.js +6 -2
  163. package/hooks/gsd-graphify-update.sh +6 -0
  164. package/hooks/gsd-path-export.js +95 -0
  165. package/hooks/gsd-secret-read-guard.js +172 -39
  166. package/hooks/gsd-statusline.js +37 -3
  167. package/hooks/gsd-windsurf-pre-write.js +29 -2
  168. package/hooks/gsd-workflow-guard.js +3 -2
  169. package/hooks/gsd-worktree-path-guard.js +29 -2
  170. package/hooks/hooks.json +1 -0
  171. package/hooks/lib/git-probe.js +16 -0
  172. package/hooks/lib/isolation-sentinel.js +44 -0
  173. package/hooks/managed-hooks-registry.cjs +1 -0
  174. package/package.json +15 -8
  175. package/pi/gsd.cjs +1047 -10
  176. package/pi/package-agents/gsd-advisor-researcher.md +113 -0
  177. package/pi/package-agents/gsd-ai-researcher.md +111 -0
  178. package/pi/package-agents/gsd-assumptions-analyzer.md +110 -0
  179. package/pi/package-agents/gsd-code-fixer.md +774 -0
  180. package/pi/package-agents/gsd-code-reviewer.md +441 -0
  181. package/pi/package-agents/gsd-codebase-mapper.md +850 -0
  182. package/pi/package-agents/gsd-debug-session-manager.md +416 -0
  183. package/pi/package-agents/gsd-debugger.md +1274 -0
  184. package/pi/package-agents/gsd-doc-classifier.md +269 -0
  185. package/pi/package-agents/gsd-doc-synthesizer.md +259 -0
  186. package/pi/package-agents/gsd-doc-verifier.md +212 -0
  187. package/pi/package-agents/gsd-doc-writer.md +626 -0
  188. package/pi/package-agents/gsd-dom-verifier.md +164 -0
  189. package/pi/package-agents/gsd-domain-researcher.md +144 -0
  190. package/pi/package-agents/gsd-eval-auditor.md +185 -0
  191. package/pi/package-agents/gsd-eval-planner.md +149 -0
  192. package/pi/package-agents/gsd-executor.md +898 -0
  193. package/pi/package-agents/gsd-framework-selector.md +159 -0
  194. package/pi/package-agents/gsd-integration-checker.md +476 -0
  195. package/pi/package-agents/gsd-intel-updater.md +338 -0
  196. package/pi/package-agents/gsd-mempalace-curator.md +49 -0
  197. package/pi/package-agents/gsd-nyquist-auditor.md +200 -0
  198. package/pi/package-agents/gsd-pattern-mapper.md +340 -0
  199. package/pi/package-agents/gsd-phase-researcher.md +897 -0
  200. package/pi/package-agents/gsd-plan-checker.md +1077 -0
  201. package/pi/package-agents/gsd-planner.md +1003 -0
  202. package/pi/package-agents/gsd-project-researcher.md +611 -0
  203. package/pi/package-agents/gsd-research-synthesizer.md +259 -0
  204. package/pi/package-agents/gsd-roadmapper.md +779 -0
  205. package/pi/package-agents/gsd-security-auditor.md +171 -0
  206. package/pi/package-agents/gsd-ui-auditor.md +581 -0
  207. package/pi/package-agents/gsd-ui-checker.md +417 -0
  208. package/pi/package-agents/gsd-ui-researcher.md +469 -0
  209. package/pi/package-agents/gsd-user-profiler.md +174 -0
  210. package/pi/package-agents/gsd-verifier.md +963 -0
  211. package/pi/package-agents/manifest.json +39 -0
  212. package/pi/package-skills/gsd-add-tests/SKILL.md +39 -0
  213. package/pi/package-skills/gsd-ai-integration-phase/SKILL.md +36 -0
  214. package/pi/package-skills/gsd-audit-fix/SKILL.md +34 -0
  215. package/pi/package-skills/gsd-audit-milestone/SKILL.md +40 -0
  216. package/pi/package-skills/gsd-audit-uat/SKILL.md +26 -0
  217. package/pi/package-skills/gsd-autonomous/SKILL.md +52 -0
  218. package/pi/package-skills/gsd-capture/SKILL.md +68 -0
  219. package/pi/package-skills/gsd-cleanup/SKILL.md +25 -0
  220. package/pi/package-skills/gsd-code-review/SKILL.md +71 -0
  221. package/pi/package-skills/gsd-complete-milestone/SKILL.md +147 -0
  222. package/pi/package-skills/gsd-config/SKILL.md +60 -0
  223. package/pi/package-skills/gsd-debug/SKILL.md +64 -0
  224. package/pi/package-skills/gsd-discuss-phase/SKILL.md +74 -0
  225. package/pi/package-skills/gsd-docs-update/SKILL.md +50 -0
  226. package/pi/package-skills/gsd-eval-review/SKILL.md +35 -0
  227. package/pi/package-skills/gsd-execute-phase/SKILL.md +62 -0
  228. package/pi/package-skills/gsd-explore/SKILL.md +26 -0
  229. package/pi/package-skills/gsd-extract-learnings/SKILL.md +25 -0
  230. package/pi/package-skills/gsd-fast/SKILL.md +33 -0
  231. package/pi/package-skills/gsd-forensics/SKILL.md +59 -0
  232. package/pi/package-skills/gsd-graphify/SKILL.md +210 -0
  233. package/pi/package-skills/gsd-health/SKILL.md +36 -0
  234. package/pi/package-skills/gsd-help/SKILL.md +37 -0
  235. package/pi/package-skills/gsd-import/SKILL.md +46 -0
  236. package/pi/package-skills/gsd-inbox/SKILL.md +42 -0
  237. package/pi/package-skills/gsd-ingest-docs/SKILL.md +43 -0
  238. package/pi/package-skills/gsd-manager/SKILL.md +46 -0
  239. package/pi/package-skills/gsd-map-codebase/SKILL.md +85 -0
  240. package/pi/package-skills/gsd-mempalace-capture/SKILL.md +111 -0
  241. package/pi/package-skills/gsd-mempalace-recall/SKILL.md +111 -0
  242. package/pi/package-skills/gsd-milestone-summary/SKILL.md +54 -0
  243. package/pi/package-skills/gsd-mvp-phase/SKILL.md +45 -0
  244. package/pi/package-skills/gsd-new-milestone/SKILL.md +49 -0
  245. package/pi/package-skills/gsd-new-project/SKILL.md +49 -0
  246. package/pi/package-skills/gsd-next/SKILL.md +34 -0
  247. package/pi/package-skills/gsd-ns-context/SKILL.md +31 -0
  248. package/pi/package-skills/gsd-ns-ideate/SKILL.md +30 -0
  249. package/pi/package-skills/gsd-ns-manage/SKILL.md +42 -0
  250. package/pi/package-skills/gsd-ns-project/SKILL.md +34 -0
  251. package/pi/package-skills/gsd-ns-review/SKILL.md +35 -0
  252. package/pi/package-skills/gsd-ns-workflow/SKILL.md +44 -0
  253. package/pi/package-skills/gsd-onboard/SKILL.md +46 -0
  254. package/pi/package-skills/gsd-pause-work/SKILL.md +48 -0
  255. package/pi/package-skills/gsd-phase/SKILL.md +61 -0
  256. package/pi/package-skills/gsd-plan-phase/SKILL.md +62 -0
  257. package/pi/package-skills/gsd-plan-review-convergence/SKILL.md +63 -0
  258. package/pi/package-skills/gsd-pr-branch/SKILL.md +31 -0
  259. package/pi/package-skills/gsd-profile-user/SKILL.md +48 -0
  260. package/pi/package-skills/gsd-progress/SKILL.md +51 -0
  261. package/pi/package-skills/gsd-quick/SKILL.md +179 -0
  262. package/pi/package-skills/gsd-quick-batch/SKILL.md +114 -0
  263. package/pi/package-skills/gsd-resume-work/SKILL.md +31 -0
  264. package/pi/package-skills/gsd-review/SKILL.md +50 -0
  265. package/pi/package-skills/gsd-review-backlog/SKILL.md +65 -0
  266. package/pi/package-skills/gsd-secure-phase/SKILL.md +37 -0
  267. package/pi/package-skills/gsd-settings/SKILL.md +30 -0
  268. package/pi/package-skills/gsd-ship/SKILL.md +27 -0
  269. package/pi/package-skills/gsd-sketch/SKILL.md +56 -0
  270. package/pi/package-skills/gsd-spec-phase/SKILL.md +63 -0
  271. package/pi/package-skills/gsd-spike/SKILL.md +53 -0
  272. package/pi/package-skills/gsd-stats/SKILL.md +22 -0
  273. package/pi/package-skills/gsd-surface/SKILL.md +177 -0
  274. package/pi/package-skills/gsd-thread/SKILL.md +29 -0
  275. package/pi/package-skills/gsd-ui-phase/SKILL.md +35 -0
  276. package/pi/package-skills/gsd-ui-review/SKILL.md +35 -0
  277. package/pi/package-skills/gsd-ultraplan-phase/SKILL.md +38 -0
  278. package/pi/package-skills/gsd-undo/SKILL.md +38 -0
  279. package/pi/package-skills/gsd-update/SKILL.md +54 -0
  280. package/pi/package-skills/gsd-validate-phase/SKILL.md +37 -0
  281. package/pi/package-skills/gsd-verify-work/SKILL.md +41 -0
  282. package/pi/package-skills/gsd-workspace/SKILL.md +57 -0
  283. package/pi/package-skills/gsd-workstreams/SKILL.md +73 -0
  284. package/scripts/build-hooks.js +4 -0
  285. package/scripts/ci-next-health.cjs +246 -23
  286. package/scripts/command-contract-helpers.cjs +1 -1
  287. package/scripts/docs-guard-registry.cjs +22 -7
  288. package/scripts/gen-features.cjs +14 -2
  289. package/scripts/gen-health-docs.cjs +13 -1
  290. package/scripts/gen-pi-package-skills.cjs +217 -0
  291. package/scripts/lib/drift-scan.cjs +27 -0
  292. package/scripts/lib/macos-conformance-tier.generated.cjs +17 -1
  293. package/scripts/lib/platform-conformance-tier.generated.cjs +37 -1
  294. package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +3 -3
  295. package/scripts/lint-phase-enumeration-drift.cjs +8 -4
  296. package/scripts/lint-retired-runtime-name.cjs +5 -0
  297. package/scripts/lint-roadmap-progress-drift.cjs +421 -0
  298. package/scripts/mutation-matrix.cjs +23 -1
  299. package/scripts/npm-audit-baseline.cjs +41 -7
  300. package/scripts/reviewed-or-maintainer-policy.cjs +181 -0
  301. package/scripts/select-docs-guards.cjs +1 -1
  302. package/scripts/self-test-report-policy.cjs +350 -0
  303. package/scripts/sync-next-version.cjs +38 -6
  304. package/skills/gsd-update/SKILL.md +5 -2
  305. package/vscode/package.json +1 -1
  306. package/scripts/diagnose-validate-commit-in-tier.cjs +0 -270
  307. package/scripts/diagnose-validate-commit-phases.cjs +0 -348
  308. package/scripts/xtrace-phase-timing.cjs +0 -205
@@ -9,7 +9,7 @@
9
9
  {
10
10
  "name": "gsd-core",
11
11
  "description": "GSD Core is a meta-prompting, context engineering, and spec-driven development system for AI coding agents.",
12
- "version": "1.18.0",
12
+ "version": "1.20.0",
13
13
  "source": "./",
14
14
  "author": {
15
15
  "name": "open-gsd",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "gsd-core",
3
3
  "displayName": "GSD Core",
4
- "version": "1.18.0",
4
+ "version": "1.20.0",
5
5
  "description": "GSD Core is a meta-prompting, context engineering, and spec-driven development system for AI coding agents.",
6
6
  "author": {
7
7
  "name": "open-gsd",
@@ -18,5 +18,6 @@
18
18
  "claude-code",
19
19
  "gsd"
20
20
  ],
21
+ "commands": [],
21
22
  "skills": "./skills/"
22
23
  }
@@ -365,7 +365,7 @@ function handleHookResult(hookResult, output) {
365
365
  throw new Error(reason);
366
366
  }
367
367
 
368
- // Advisory: inject additionalContext into metadata + log
368
+ // Advisory: inject additionalContext into metadata
369
369
  const advisory =
370
370
  parsed &&
371
371
  parsed.hookSpecificOutput &&
@@ -382,8 +382,7 @@ function handleHookResult(hookResult, output) {
382
382
  }
383
383
  output.metadata._gsdAdvisory.push(advisory);
384
384
  }
385
- // Best-effort visibility when metadata isn't surfaced to the model
386
- console.error(advisory);
385
+ // Not written to stderr: the OpenCode TUI draws a plugin's stderr over the prompt input (#5648).
387
386
  // >>> gsd:opencode-parity
388
387
  deliverAdvisory(advisory, output);
389
388
  // <<< gsd:opencode-parity
@@ -73,12 +73,12 @@ After applying each fix:
73
73
  | Language | Check Command |
74
74
  |----------|--------------|
75
75
  | JavaScript | `node -c {file}` (syntax check) |
76
- | TypeScript | `npx tsc --noEmit {file}` (if tsconfig.json exists) |
76
+ | TypeScript | Project-aware check only, output filtered to `{file}`: the project's own typecheck (`npm run typecheck` / `tsc -b`) if it exists, else `npx tsc --noEmit -p <nearest tsconfig*.json>` whose `--listFilesOnly` output lists `{file}`; no config includes `{file}` → Tier 1 only. Never pass `{file}` to `tsc` positionally. |
77
77
  | Python | `python -c "import ast; ast.parse(open('{file}').read())"` |
78
78
  | JSON | `node -e "JSON.parse(require('fs').readFileSync('{file}','utf-8'))"` |
79
79
  | Other | Skip to Tier 1 only |
80
80
 
81
- **Scoping:** TypeScript errors in OTHER files are pre-existing — IGNORE; only fail on errors in the file you edited. `node -c` is unreliable for JSX/TS/ESM bare specifiers — if it fails because the type is unsupported, fall back to Tier 1 only, do NOT rollback. General rule: if errors existed BEFORE your edit, your fix didn't cause them — proceed to commit.
81
+ **Scoping:** TypeScript errors in OTHER files are pre-existing — IGNORE; only fail on errors in the file you edited. A solution-style root `tsconfig.json` (`"files": []` plus `references`) checks no source files and exits 0 — NOT a passing check; use a referenced config whose `--listFilesOnly` lists `{file}`, or fall back to Tier 1. TypeScript procedure: prefer a `typecheck` script in the nearest `package.json`; else walk up from `{file}` to the nearest `tsconfig.json` (solution-style: try each referenced config in turn), run from that config's directory `npx tsc --noEmit -p <config> --listFilesOnly` and keep the first config listing `{file}` (none → Tier 1), then `npx tsc --noEmit -p <config>` (never `-b`: no build artifacts) keeping only output lines for `{file}`; roll back only for errors on lines you changed, otherwise treat as pre-existing and proceed. `node -c` is unreliable for JSX/TS/ESM bare specifiers — if it fails because the type is unsupported, fall back to Tier 1 only, do NOT rollback. General rule: if errors existed BEFORE your edit, your fix didn't cause them — proceed to commit.
82
82
 
83
83
  - Syntax check FAILS with NEW errors in your file → rollback_strategy immediately.
84
84
  - FAILS with pre-existing errors only → proceed to commit.
@@ -256,17 +256,17 @@ Treat this as a finally-block obligation: even on early exit (config error, no f
256
256
 
257
257
  <step name="load_context">
258
258
  1. Read all `<required_reading>` files if present.
259
- 2. Parse `<config>` block: `phase_dir`, `padded_phase`, `review_path` (full path to REVIEW.md), `fix_scope` ("critical_warning" default, or "all" includes Info), `fix_report_path` (output REVIEW-FIX.md path).
259
+ 2. Parse `<config>` block: `phase_dir`, `padded_phase`, `review_path` (full path to REVIEW.md), `fix_scope` ("critical_warning" default, or "all" includes Info and necessity), `fix_report_path` (output REVIEW-FIX.md path).
260
260
  3. `cat {review_path}`.
261
261
  4. Parse frontmatter `status:`. If `"clean"` or `"skipped"`: exit with "No issues to fix -- REVIEW.md status is {status}." — do NOT create REVIEW-FIX.md, exit 0 (not an error).
262
262
  5. Load project context (`<project_context>`): CLAUDE.md, skills.
263
263
  </step>
264
264
 
265
265
  <step name="parse_findings">
266
- 1. Extract findings via `<finding_parser>` rules: `id`, `severity` (Critical CR-*/BL-*, Warning WR-*, Info IN-*), `title`, `file` (primary), `files` (all referenced, for multi-file fixes), `line` (or null), `issue`, `fix` (may be multi-line/code fences).
267
- 2. Filter by `fix_scope`: `critical_warning` → CR-*/BL-*/WR-* only; `all` → + IN-*.
268
- 3. Sort: Critical first, then Warning, then Info; same-severity keeps document order.
269
- 4. Record `findings_in_scope` count for frontmatter.
266
+ 1. Extract findings via `<finding_parser>` rules: `id`, `severity` (Critical CR-*/BL-*, Warning WR-*, Info IN-*), `category` (`necessity` when the finding carries a `**Category:** necessity` line, #4100 — unnecessary code, not broken code), `title`, `file` (primary), `files` (all referenced, for multi-file fixes), `line` (or null), `issue`, `fix` (may be multi-line/code fences).
267
+ 2. Filter by `fix_scope`: `critical_warning` → CR-*/BL-*/WR-* only, and `critical_warning` excludes necessity findings (removal is the human's scope call; the marker overrides the prefix, so a WR-* carrying `**Category:** necessity` is out of scope and skipped with no edit); `all` → + IN-*, and `all` includes necessity findings, ordered last — record each as `fixed: requires human verification`.
268
+ 3. Sort: Critical first, then Warning, then Info, then necessity; same-severity keeps document order.
269
+ 4. Record `findings_in_scope` count for frontmatter. If `findings_in_scope` is 0, apply nothing: write REVIEW-FIX.md with `fixed: 0`, `skipped: 0`, `status: all_fixed`, and a body stating no finding was in scope and the out-of-scope findings remain in REVIEW.md.
270
270
  </step>
271
271
 
272
272
  <step name="apply_fixes">
@@ -110,13 +110,14 @@ Run syntax/parse check appropriate to file type:
110
110
  | Language | Check Command |
111
111
  |----------|--------------|
112
112
  | JavaScript | `node -c {file}` (syntax check) |
113
- | TypeScript | `npx tsc --noEmit {file}` (if tsconfig.json exists in project) |
113
+ | TypeScript | Project-aware check only, output filtered to `{file}`: the project's own typecheck (`npm run typecheck` / `tsc -b`) if it exists, else `npx tsc --noEmit -p <nearest tsconfig*.json>` whose `--listFilesOnly` output lists `{file}`; no config includes `{file}` → Tier 1 only. Never pass `{file}` to `tsc` positionally. |
114
114
  | Python | `python -c "import ast; ast.parse(open('{file}').read())"` |
115
115
  | JSON | `node -e "JSON.parse(require('fs').readFileSync('{file}','utf-8'))"` |
116
116
  | Other | Skip to Tier 1 only |
117
117
 
118
118
  **Scoping syntax checks:**
119
- - TypeScript: If `npx tsc --noEmit {file}` reports errors in OTHER files (not the file you just edited), those are pre-existing project errors — **IGNORE them**. Only fail if errors reference the specific file you modified.
119
+ - TypeScript: Run the project-aware check from the table above. If it reports errors in OTHER files (not the file you just edited), those are pre-existing project errors — **IGNORE them**. Only fail if errors reference the specific file you modified. A solution-style root `tsconfig.json` (`"files": []` plus `references`) checks no source files and exits 0, so it is NOT a passing check: use a referenced config whose `--listFilesOnly` output includes `{file}`, or fall back to Tier 1.
120
+ - TypeScript procedure: (1) Look for a `typecheck` script in the nearest `package.json` and prefer it. (2) Otherwise start at `{file}`'s directory and walk up to the nearest `tsconfig.json`; if it is solution-style, take each config it references (e.g. `tsconfig.app.json`, `tsconfig.node.json`) and try them in turn. (3) Run from the config's own directory with `npx tsc --noEmit -p <config> --listFilesOnly` and keep the first config whose listing includes `{file}`; if none does, fall back to Tier 1. (4) Run `npx tsc --noEmit -p <config>` (use `-p`, never `-b`, so no build artifacts or `.tsbuildinfo` files are written) and keep only output lines that start with `{file}`'s path as `tsc` prints it relative to that directory. (5) Roll back only for errors on lines you changed; errors you cannot attribute to your edit are pre-existing — fall back to Tier 1 and proceed.
120
121
  - JavaScript: `node -c {file}` is reliable for plain .js but NOT for JSX, TypeScript, or ESM with bare specifiers. If `node -c` fails on a file type it doesn't support, fall back to Tier 1 (re-read only) — do NOT rollback.
121
122
  - General rule: If a syntax check produces errors that existed BEFORE your edit (compare with pre-fix state), the fix did not introduce them. Proceed to commit.
122
123
 
@@ -157,6 +158,8 @@ Each finding starts with:
157
158
 
158
159
  Where ID matches: `CR-\d+` or `BL-\d+` (Critical-tier-equivalent), `WR-\d+` (Warning), or `IN-\d+` (Info)
159
160
 
161
+ A finding whose body carries a `**Category:** necessity` line is a **necessity finding** (#4100): code the reviewer judged unnecessary, not broken. Its prefix still gives its severity.
162
+
160
163
  **Required Fields:**
161
164
 
162
165
  - **File:** line contains primary file path
@@ -438,7 +441,7 @@ This cleanup is unconditional when a worktree was created — register it mental
438
441
  - `phase_dir`: Path to phase directory (e.g., `.planning/phases/02-code-review-command`)
439
442
  - `padded_phase`: Zero-padded phase number (e.g., "02")
440
443
  - `review_path`: Full path to REVIEW.md (e.g., `.planning/phases/02-code-review-command/02-REVIEW.md`)
441
- - `fix_scope`: "critical_warning" (default) or "all" (includes Info findings)
444
+ - `fix_scope`: "critical_warning" (default) or "all" (includes Info and necessity findings)
442
445
  - `fix_report_path`: Full path for REVIEW-FIX.md output (e.g., `.planning/phases/02-code-review-command/02-REVIEW-FIX.md`)
443
446
 
444
447
  **3. Read REVIEW.md:**
@@ -464,6 +467,7 @@ Read `./CLAUDE.md` and check for `.claude/skills/` or `.agents/skills/` (as desc
464
467
  For each finding, extract:
465
468
  - `id`: Finding identifier (e.g., CR-01, WR-03, IN-12)
466
469
  - `severity`: Critical (CR-* or BL-*), Warning (WR-*), Info (IN-*)
470
+ - `category`: `necessity` when the finding carries a `**Category:** necessity` line, otherwise none
467
471
  - `title`: Issue title from `### ` heading
468
472
  - `file`: Primary file path from **File:** line
469
473
  - `files`: ALL file paths referenced in finding (including in Fix section) — for multi-file fixes
@@ -472,15 +476,17 @@ For each finding, extract:
472
476
  - `fix`: Full fix content from **Fix:** section (may be multi-line, may contain code fences)
473
477
 
474
478
  **2. Filter by fix_scope:**
475
- - If `fix_scope == "critical_warning"`: include only CR-*, BL-*, and WR-* findings
476
- - If `fix_scope == "all"`: include CR-*, BL-*, WR-*, and IN-* findings
479
+ - If `fix_scope == "critical_warning"`: include only CR-*, BL-*, and WR-* findings; `critical_warning` excludes necessity findings (removing code is a scope decision for the human, #4100). The marker overrides the prefix: a WR-* finding carrying `**Category:** necessity` is OUT of scope here, and is skipped without applying any edit
480
+ - If `fix_scope == "all"`: include CR-*, BL-*, WR-*, and IN-* findings; `all` includes necessity findings, ordered last. A necessity fix removes code, so record it as `fixed: requires human verification`
477
481
 
478
482
  **3. Sort findings by severity:**
479
- - Critical (CR-* and BL-*) first, then Warning, then Info
483
+ - Critical (CR-* and BL-*) first, then Warning, then Info, then necessity findings
480
484
  - Within same severity, maintain document order
481
485
 
482
486
  **4. Count findings in scope:**
483
487
  Record `findings_in_scope` for REVIEW-FIX.md frontmatter.
488
+
489
+ If `findings_in_scope` is 0, apply nothing: write REVIEW-FIX.md with `fixed: 0`, `skipped: 0`, `status: all_fixed`, and a body stating that no finding was in scope and the out-of-scope findings remain in REVIEW.md.
484
490
  </step>
485
491
 
486
492
  <step name="apply_fixes">
@@ -701,7 +707,7 @@ main checkout after teardown).
701
707
 
702
708
  **DO verify each fix** using 3-tier verification strategy:
703
709
  - Minimum: re-read file, confirm fix present
704
- - Preferred: syntax check (node -c, tsc --noEmit, python ast.parse, etc.)
710
+ - Preferred: syntax check (node -c, project-aware tsc -p, python ast.parse, etc.)
705
711
  - Fallback: accept minimum if no syntax checker available
706
712
 
707
713
  **DO skip findings that cannot be applied cleanly** — do not force broken fixes. Mark as skipped with clear reason.
@@ -49,6 +49,8 @@ Read `./CLAUDE.md` if present — follow project guidelines, security requiremen
49
49
 
50
50
  **3. Code Quality** — dead code, unused imports/variables, poor naming, missing error handling, inconsistent patterns, overly complex functions (high cyclomatic complexity), code duplication, magic numbers, commented-out code
51
51
 
52
+ **4. Necessity** (#4100) — reachable code whose guarded-against problem cannot occur in this stack: impossible-state guard, already-defended-elsewhere, cargo-culted pattern, phantom requirement, generality without instantiation. At `standard`/`deep`, Read `~/.claude/gsd-core/references/necessity-review.md` before classifying; if unreadable, say so in the Summary and omit `necessity:`. `quick` does not assess necessity. Warning when provable from the repo, Info when judgment, Never Critical; cite the evidence the state cannot occur and add a `**Category:** necessity` line.
53
+
52
54
  **Out of Scope (v1):** performance issues (O(n²) algorithms, memory leaks, inefficient queries) — NOT in scope. Focus on correctness, security, maintainability.
53
55
 
54
56
  </review_scope>
@@ -56,10 +58,12 @@ Read `./CLAUDE.md` if present — follow project guidelines, security requiremen
56
58
  <depth_levels>
57
59
 
58
60
  **quick** — pattern-matching only, grep/regex scan for common anti-patterns, no full file reads. Target: <2 min.
59
- Patterns: hardcoded secrets `(password|secret|api_key|token|apikey|api-key)\s*[=:]\s*['"][^'"]+['"]`; dangerous fns `eval\(|innerHTML|dangerouslySetInnerHTML|exec\(|system\(|shell_exec|passthru`; debug artifacts `console\.log|debugger;|TODO|FIXME|XXX|HACK`; empty catch `catch\s*\([^)]*\)\s*\{\s*\}`; commented-out code `^\s*//.*[{};]|^\s*#.*:|^\s*/\*`.
61
+ Checks (commands in `review_by_depth`): Hardcoded secrets; Dangerous functions; Debug artifacts; Empty catch blocks; Commented-out code; Unpinned actions; Non-idempotent install; Missing job timeout.
62
+ The last three: GitHub Actions workflows only.
60
63
 
61
64
  **standard** (default) — Read each changed file, check bugs/security/quality in context, cross-reference imports/exports. Target: 5-15 min.
62
65
  Language-aware checks: **JS/TS** unchecked `.length`, missing `await`, unhandled promise rejection, `as any`, `==` vs `===`, null coalescing issues. **Python** bare `except:`, mutable default args, f-string injection, `eval()`, missing `with` for file ops. **Go** unchecked error returns, goroutine leaks, context not passed, `defer` in loops, race conditions. **C/C++** buffer overflow patterns, use-after-free, null pointer deref, missing bounds checks, memory leaks. **Shell** unquoted variables, `eval`, missing `set -e`, command injection via interpolation.
66
+ **CI/CD pipelines** (by path: `.github/workflows/*.yml`, `Dockerfile*`, `docker-compose*.yml`, deploy scripts): Read `~/.claude/gsd-core/references/cicd-review-patterns.md`; if it cannot be read, say so in the Summary and check: non-idempotent steps (`npm install` vs `npm ci`, unlocked `pip install`, unguarded `mkdir`/`rm`), no job `timeout-minutes`, deploy without `concurrency` + `cancel-in-progress`, per-environment rebuild (not build-once), no health check or rollback, load-bearing `continue-on-error`, static credentials where OIDC works, unpinned actions.
63
67
 
64
68
  **deep** — all of standard + cross-file analysis: trace call chains across imports, check type consistency at API boundaries (TS interfaces, API contracts), verify error propagation (thrown errors caught by callers), check state mutation consistency across modules, detect circular dependencies/coupling. Target: 15-30 min.
65
69
 
@@ -109,6 +113,7 @@ Use its `files`. A `status` of `unresolvable` (exit 69, JSON still printed), or
109
113
  NOTE: do NOT exclude all `.md` — commands, workflows, and agents are source code in this codebase.
110
114
 
111
115
  **2. Group by language/type:** JS/TS (`.js`,`.jsx`,`.ts`,`.tsx`), Python (`.py`), Go (`.go`), C/C++ (`.c`,`.cpp`,`.h`,`.hpp`), Shell (`.sh`,`.bash`), other → generic.
116
+ CI/CD (by path): `.github/workflows/*.yml`/`*.yaml`, `Dockerfile*`, `docker-compose*.yml`, `deploy*.sh` (also Shell).
112
117
 
113
118
  **3. Exit early if empty:** create REVIEW.md with `status: skipped`, all finding counts 0. Body: "No source files to review after filtering. All files in scope are documentation, planning artifacts, or generated files. Use `status: skipped` (not `clean`) because no actual review was performed."
114
119
 
@@ -116,14 +121,47 @@ NOTE: `status: clean` = reviewed, no issues. `status: skipped` = no reviewable f
116
121
  </step>
117
122
 
118
123
  <step name="review_by_depth">
119
- **depth=quick:** run grep patterns from `<depth_levels>` against all files:
124
+ **depth=quick:** run every check from `<depth_levels>`:
120
125
  ```bash
121
- grep -n -E "(password|secret|api_key|token|apikey|api-key)\s*[=:]\s*['\"]\w+['\"]" file
122
- grep -n -E "eval\(|innerHTML|dangerouslySetInnerHTML|exec\(|system\(|shell_exec" file
123
- grep -n -E "console\.log|debugger;|TODO|FIXME|XXX|HACK" file
124
- grep -n -E "catch\s*\([^)]*\)\s*\{\s*\}" file
126
+ # Set FILE per scoped path with: while IFS= read -r FILE (never paste a name into code).
127
+
128
+ # Hardcoded secrets
129
+ grep -n -E -- "(password|secret|api_key|token|apikey|api-key)\s*[=:]\s*['\"][^'\"]+['\"]" "$FILE"
130
+
131
+ # Dangerous functions
132
+ grep -n -E -- "eval\(|innerHTML|dangerouslySetInnerHTML|exec\(|system\(|shell_exec|passthru" "$FILE"
133
+
134
+ # Debug artifacts
135
+ grep -n -E -- "console\.log|debugger;|TODO|FIXME|XXX|HACK" "$FILE"
136
+
137
+ # Empty catch blocks
138
+ grep -n -E -- "catch\s*\([^)]*\)\s*\{\s*\}" "$FILE"
139
+
140
+ # Commented-out code
141
+ grep -n -E -- "^\s*//.*[{};]|^\s*#[[:space:]]*(if|for|while|def|class|elif|else|try|except|with)[[:space:](].*:[[:space:]]*$|^\s*/\*[^*].*[{};]" "$FILE"
142
+
143
+ # Unpinned actions
144
+ grep -n -E -- "^[[:space:]]*(-[[:space:]]+)?uses:[[:space:]]*['\"]?[^[:space:]'\"]+@(main|master|latest)['\"]?([[:space:]]|$)" "$FILE"
145
+
146
+ # Non-idempotent install
147
+ [ -f package-lock.json ] && grep -n -E -- "(^|[^[:alnum:]_-])npm[[:space:]]+(install|i)([[:space:]]|$)" "$FILE" | grep -v -E "^[0-9]+:[[:space:]]*#|[[:space:]](-g|--global)([[:space:]]|$)"
148
+
149
+ # Missing job timeout
150
+ awk '
151
+ function flush() { if (job != "" && runs && !timed) print line ": " job ": no job-level timeout-minutes"; job = "" }
152
+ { sub(/\r$/, "") }
153
+ /^[^[:space:]#]/ { flush(); injobs = ($0 ~ /^jobs:[[:space:]]*(#.*)?$/); jind = -1; next }
154
+ !injobs || /^[[:space:]]*(#.*)?$/ { next }
155
+ { ind = match($0, /[^ ]/) - 1 }
156
+ jind < 0 { jind = ind }
157
+ ind == jind { flush(); job = $0; sub(/^ +/, "", job); sub(/:.*/, "", job); line = NR; kind = -1; runs = 0; timed = 0; next }
158
+ kind < 0 { kind = ind }
159
+ ind == kind && /^ *runs-on:/ { runs = 1 }
160
+ ind == kind && /^ *timeout-minutes:/ { timed = 1 }
161
+ END { flush() }
162
+ ' "$FILE"
125
163
  ```
126
- Severity: secrets/dangerous=Critical, debug=Info, empty catch=Warning.
164
+ Severity: secrets/dangerous=Critical, debug and commented-out code=Info, empty catch and the three CI/CD checks=Warning.
127
165
 
128
166
  **depth=standard:** per file — Read full content, apply language-specific checks, check for: functions >50 lines, deep nesting (>4 levels), missing error handling in async functions, hardcoded config values, type safety issues (TS `any`, loose Python typing). Record findings with file path, line number, description.
129
167
 
@@ -133,7 +171,7 @@ Severity: secrets/dangerous=Critical, debug=Info, empty catch=Warning.
133
171
  <step name="classify_findings">
134
172
  **Critical** — security vulnerabilities, data loss, crashes, auth bypasses: SQL/command/path-traversal injection, hardcoded secrets in production code, null pointer derefs that crash, auth/authz bypasses, unsafe deserialization, buffer overflows.
135
173
 
136
- **Warning** — logic errors, unhandled edge cases, missing error handling, code smells that could cause bugs: unchecked array access, missing async error handling, off-by-one errors, `==` vs `===` coercion, unhandled promise rejections, dead code paths indicating logic errors.
174
+ **Warning** — logic errors, unhandled edge cases, missing error handling, code smells that could cause bugs: unchecked array access, missing async error handling, off-by-one errors, `==` vs `===` coercion, unhandled promise rejections, dead code paths indicating logic errors; CI/CD pipeline findings: every check in the CI/CD entry.
137
175
 
138
176
  **Info** — style, naming, dead code, unused imports, suggestions: unused imports/variables, poor naming (single letters except loop counters), commented-out code, TODO/FIXME, magic numbers, duplication.
139
177
 
@@ -158,10 +196,13 @@ findings:
158
196
  warning: N
159
197
  info: N
160
198
  total: N
199
+ necessity: N
161
200
  status: clean | issues_found
162
201
  ---
163
202
  ```
164
203
 
204
+ `necessity:` only at standard/deep: the necessity findings among `warning` + `info`, never added to `total`.
205
+
165
206
  **3. Body sections (required order):**
166
207
  1) `## Structural Findings (fallow)` — only if structural findings provided; normalized items first.
167
208
  2) `## Narrative Findings (AI reviewer)` — your adversarial findings, including any external claim independently verified (`(external: {slug})`).
@@ -61,6 +61,8 @@ This ensures project-specific patterns, conventions, and best practices are appl
61
61
 
62
62
  **3. Code Quality** — Dead code, unused imports/variables, poor naming conventions, missing error handling, inconsistent patterns, overly complex functions (high cyclomatic complexity), code duplication, magic numbers, commented-out code
63
63
 
64
+ **4. Necessity** (#4100) — reachable code whose guarded-against problem cannot occur in this stack: impossible-state guard, already-defended-elsewhere, cargo-culted pattern, phantom requirement, generality without instantiation. At `standard`/`deep`, Read `~/.claude/gsd-core/references/necessity-review.md` before classifying findings; if it cannot be read, say so in the Summary and omit `necessity:`. `quick` does not assess necessity. Warning when provable from the repo, Info when it rests on judgment, Never Critical; each finding cites the evidence that the state cannot occur and carries a `**Category:** necessity` line.
65
+
64
66
  **Out of Scope (v1):** Performance issues (O(n²) algorithms, memory leaks, inefficient queries) are NOT in scope for v1. Focus on correctness, security, and maintainability.
65
67
 
66
68
  </review_scope>
@@ -71,12 +73,17 @@ This ensures project-specific patterns, conventions, and best practices are appl
71
73
 
72
74
  **quick** — Pattern-matching only. Use grep/regex to scan for common anti-patterns without reading full file contents. Target: under 2 minutes.
73
75
 
74
- Patterns checked:
75
- - Hardcoded secrets: `(password|secret|api_key|token|apikey|api-key)\s*[=:]\s*['"][^'"]+['"]`
76
- - Dangerous functions: `eval\(|innerHTML|dangerouslySetInnerHTML|exec\(|system\(|shell_exec|passthru`
77
- - Debug artifacts: `console\.log|debugger;|TODO|FIXME|XXX|HACK`
78
- - Empty catch blocks: `catch\s*\([^)]*\)\s*\{\s*\}`
79
- - Commented-out code: `^\s*//.*[{};]|^\s*#.*:|^\s*/\*`
76
+ Checks (commands in `review_by_depth`):
77
+ - Hardcoded secrets
78
+ - Dangerous functions
79
+ - Debug artifacts
80
+ - Empty catch blocks
81
+ - Commented-out code
82
+ - Unpinned actions
83
+ - Non-idempotent install
84
+ - Missing job timeout
85
+
86
+ The last three: GitHub Actions workflows only.
80
87
 
81
88
  **standard** (default) — Read each changed file. Check for bugs, security issues, and quality problems in context. Cross-reference imports and exports. Target: 5-15 minutes.
82
89
 
@@ -86,6 +93,7 @@ Language-aware checks:
86
93
  - **Go**: Unchecked error returns, goroutine leaks, context not passed, `defer` in loops, race conditions
87
94
  - **C/C++**: Buffer overflow patterns, use-after-free indicators, null pointer dereferences, missing bounds checks, memory leaks
88
95
  - **Shell**: Unquoted variables, `eval` usage, missing `set -e`, command injection via interpolation
96
+ - **CI/CD pipelines** (by path: `.github/workflows/*.yml`, `Dockerfile*`, `docker-compose*.yml`, deploy scripts): Read `~/.claude/gsd-core/references/cicd-review-patterns.md`; if it cannot be read, say so in the Summary and check: non-idempotent steps (`npm install` vs `npm ci`, unlocked `pip install`, unguarded `mkdir`/`rm`), no job `timeout-minutes`, deploy without `concurrency` + `cancel-in-progress`, per-environment rebuild (not build-once), no health check or rollback, load-bearing `continue-on-error`, static credentials where OIDC works, unpinned actions
89
97
 
90
98
  **deep** — All of standard, plus cross-file analysis. Trace function call chains across imports. Target: 15-30 minutes.
91
99
 
@@ -174,6 +182,7 @@ NOTE: Do NOT exclude all `.md` files — commands, workflows, and agents are sou
174
182
  - Go: `.go`
175
183
  - C/C++: `.c`, `.cpp`, `.h`, `.hpp`
176
184
  - Shell: `.sh`, `.bash`
185
+ - CI/CD (by path): `.github/workflows/*.yml`/`*.yaml`, `Dockerfile*`, `docker-compose*.yml`, `deploy*.sh` (also Shell)
177
186
  - Other: Review generically
178
187
 
179
188
  **3. Exit early if empty:** If no source files remain after filtering, create REVIEW.md with:
@@ -194,22 +203,48 @@ NOTE: `status: clean` means "reviewed and found no issues." `status: skipped` me
194
203
  Branch on depth level:
195
204
 
196
205
  **For depth=quick:**
197
- Run grep patterns (from `<depth_levels>` quick section) against all files:
206
+ Run every check from `<depth_levels>` quick section:
198
207
  ```bash
208
+ # Set FILE per scoped path with: while IFS= read -r FILE (never paste a name into code).
209
+
199
210
  # Hardcoded secrets
200
- grep -n -E "(password|secret|api_key|token|apikey|api-key)\s*[=:]\s*['\"]\w+['\"]" file
211
+ grep -n -E -- "(password|secret|api_key|token|apikey|api-key)\s*[=:]\s*['\"][^'\"]+['\"]" "$FILE"
201
212
 
202
213
  # Dangerous functions
203
- grep -n -E "eval\(|innerHTML|dangerouslySetInnerHTML|exec\(|system\(|shell_exec" file
214
+ grep -n -E -- "eval\(|innerHTML|dangerouslySetInnerHTML|exec\(|system\(|shell_exec|passthru" "$FILE"
204
215
 
205
216
  # Debug artifacts
206
- grep -n -E "console\.log|debugger;|TODO|FIXME|XXX|HACK" file
207
-
208
- # Empty catch
209
- grep -n -E "catch\s*\([^)]*\)\s*\{\s*\}" file
217
+ grep -n -E -- "console\.log|debugger;|TODO|FIXME|XXX|HACK" "$FILE"
218
+
219
+ # Empty catch blocks
220
+ grep -n -E -- "catch\s*\([^)]*\)\s*\{\s*\}" "$FILE"
221
+
222
+ # Commented-out code
223
+ grep -n -E -- "^\s*//.*[{};]|^\s*#[[:space:]]*(if|for|while|def|class|elif|else|try|except|with)[[:space:](].*:[[:space:]]*$|^\s*/\*[^*].*[{};]" "$FILE"
224
+
225
+ # Unpinned actions
226
+ grep -n -E -- "^[[:space:]]*(-[[:space:]]+)?uses:[[:space:]]*['\"]?[^[:space:]'\"]+@(main|master|latest)['\"]?([[:space:]]|$)" "$FILE"
227
+
228
+ # Non-idempotent install
229
+ [ -f package-lock.json ] && grep -n -E -- "(^|[^[:alnum:]_-])npm[[:space:]]+(install|i)([[:space:]]|$)" "$FILE" | grep -v -E "^[0-9]+:[[:space:]]*#|[[:space:]](-g|--global)([[:space:]]|$)"
230
+
231
+ # Missing job timeout
232
+ awk '
233
+ function flush() { if (job != "" && runs && !timed) print line ": " job ": no job-level timeout-minutes"; job = "" }
234
+ { sub(/\r$/, "") }
235
+ /^[^[:space:]#]/ { flush(); injobs = ($0 ~ /^jobs:[[:space:]]*(#.*)?$/); jind = -1; next }
236
+ !injobs || /^[[:space:]]*(#.*)?$/ { next }
237
+ { ind = match($0, /[^ ]/) - 1 }
238
+ jind < 0 { jind = ind }
239
+ ind == jind { flush(); job = $0; sub(/^ +/, "", job); sub(/:.*/, "", job); line = NR; kind = -1; runs = 0; timed = 0; next }
240
+ kind < 0 { kind = ind }
241
+ ind == kind && /^ *runs-on:/ { runs = 1 }
242
+ ind == kind && /^ *timeout-minutes:/ { timed = 1 }
243
+ END { flush() }
244
+ ' "$FILE"
210
245
  ```
211
246
 
212
- Record findings with severity: secrets/dangerous=Critical, debug=Info, empty catch=Warning
247
+ Record findings with severity: secrets/dangerous=Critical, debug and commented-out code=Info, empty catch and the three CI/CD checks=Warning
213
248
 
214
249
  **For depth=standard:**
215
250
  For each file:
@@ -253,6 +288,7 @@ For each finding, assign severity:
253
288
  - Type coercion issues (`==` vs `===`)
254
289
  - Unhandled promise rejections
255
290
  - Dead code paths that indicate logic errors
291
+ - CI/CD pipeline findings: every check in the CI/CD entry
256
292
 
257
293
  **Info** — Style issues, naming improvements, dead code, unused imports, suggestions:
258
294
  - Unused imports/variables
@@ -287,10 +323,13 @@ findings:
287
323
  warning: N
288
324
  info: N
289
325
  total: N
326
+ necessity: N
290
327
  status: clean | issues_found
291
328
  ---
292
329
  ```
293
330
 
331
+ Emit `necessity:` only at standard/deep depth. It counts the necessity findings among `warning` + `info` and is never added to `total`.
332
+
294
333
  **3. Body sections (required order):**
295
334
  1) `## Structural Findings (fallow)` — only when structural findings were provided; list normalized items first.
296
335
  2) `## Narrative Findings (AI reviewer)` — your adversarial findings from direct code review, including any external-reviewer claim you independently verified (`(external: {slug})`, see `load_context` step 5).
@@ -766,7 +766,14 @@ Do NOT skip. Do NOT proceed to state updates if self-check fails.
766
766
  </self_check>
767
767
 
768
768
  <state_updates>
769
- After SUMMARY.md, update STATE.md using `gsd-tools query` state handlers (named flags):
769
+ After SUMMARY.md, update ROADMAP.md progress FIRST, then STATE.md. The ROADMAP write is the step that can decline (`missing_phase_details`), and a decline stops the plan before any STATE.md write, so STATE.md never advances past a plan the ROADMAP did not record:
770
+
771
+ ```bash
772
+ # Update ROADMAP.md progress for this phase (plan counts, status). A decline stops here, before STATE.md moves.
773
+ PROGRESS=$(gsd_run query roadmap.update-plan-progress "${PHASE_NUMBER}") && REASON=$(jq -er '.reason//""' <<<"$PROGRESS") && [ "$REASON" != missing_phase_details ] || { echo "ERROR: ROADMAP update-plan-progress did not complete for ${PHASE_NUMBER}-${PLAN} (missing_phase_details decline, failed query, or jq not installed). STOP: skip this plan's completion steps." >&2; exit 1; }
774
+ ```
775
+
776
+ Then update STATE.md using `gsd-tools query` state handlers (named flags):
770
777
 
771
778
  ```bash
772
779
  # Advance plan counter (handles edge cases automatically)
@@ -793,9 +800,6 @@ gsd_run query state.record-session \
793
800
  ```
794
801
 
795
802
  ```bash
796
- # Update ROADMAP.md progress for this phase (plan counts, status)
797
- gsd_run query roadmap.update-plan-progress "${PHASE_NUMBER}"
798
-
799
803
  # Mark completed requirements from PLAN.md frontmatter
800
804
  # Extract the `requirements` array from the plan's frontmatter, then mark each complete
801
805
  gsd_run query requirements.mark-complete ${REQ_IDS}
@@ -689,7 +689,7 @@ verified: YYYY-MM-DDTHH:MM:SSZ
689
689
  status: passed | gaps_found | human_needed
690
690
  score: N/M must-haves verified
691
691
  covered_files: [...]
692
- covered_digest: "v3:sha256:..."
692
+ covered_digest: "v4:sha256:..."
693
693
  behavior_unverified: 0 # Count of ⚠️ PRESENT_BEHAVIOR_UNVERIFIED truths (present + wired, behavior not exercised); each is detailed in behavior_unverified_items below (and in human_verification when status is human_needed)
694
694
  overrides_applied: 0 # Count of PASSED (override) items included in score
695
695
  overrides: # Only if overrides exist — carried forward or newly added