@opengsd/gsd-core 1.9.1 → 1.11.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 (426) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +2 -3
  3. package/.opencode/plugins/gsd-core.js +8 -1
  4. package/agents/gsd-code-fixer.md +27 -3
  5. package/agents/gsd-debug-session-manager.md +11 -0
  6. package/agents/gsd-debugger.md +12 -246
  7. package/agents/gsd-doc-synthesizer.md +2 -4
  8. package/agents/gsd-executor.md +12 -10
  9. package/agents/gsd-integration-checker.md +3 -0
  10. package/agents/gsd-mempalace-curator.md +5 -2
  11. package/agents/gsd-phase-researcher.md +20 -1
  12. package/agents/gsd-plan-checker.md +46 -0
  13. package/agents/gsd-planner.md +49 -54
  14. package/agents/gsd-roadmapper.md +21 -3
  15. package/agents/gsd-user-profiler.md +3 -0
  16. package/agents/gsd-verifier.md +26 -73
  17. package/bin/install.js +1272 -1238
  18. package/bin/lib/ui-safety-gate.cjs +2 -0
  19. package/commands/gsd/code-review.md +1 -1
  20. package/commands/gsd/execute-phase.md +1 -1
  21. package/commands/gsd/map-codebase.md +1 -1
  22. package/commands/gsd/mempalace-capture.md +2 -2
  23. package/commands/gsd/mempalace-recall.md +1 -1
  24. package/commands/gsd/new-milestone.md +2 -2
  25. package/commands/gsd/plan-phase.md +1 -1
  26. package/commands/gsd/quick.md +1 -1
  27. package/commands/gsd/review-backlog.md +2 -1
  28. package/commands/gsd/verify-work.md +1 -1
  29. package/gsd-core/bin/gsd-tools.cjs +1009 -115
  30. package/gsd-core/bin/lib/active-workstream-store.cjs +153 -12
  31. package/gsd-core/bin/lib/agent-install-check.cjs +268 -38
  32. package/gsd-core/bin/lib/api-coverage.cjs +123 -5
  33. package/gsd-core/bin/lib/artifacts.cjs +3 -0
  34. package/gsd-core/bin/lib/assumption-delta.cjs +2 -4
  35. package/gsd-core/bin/lib/audit-command-router.cjs +9 -2
  36. package/gsd-core/bin/lib/audit.cjs +926 -202
  37. package/gsd-core/bin/lib/broken-windows.cjs +36 -6
  38. package/gsd-core/bin/lib/capability-consent.cjs +149 -15
  39. package/gsd-core/bin/lib/capability-lifecycle.cjs +45 -0
  40. package/gsd-core/bin/lib/capability-registry.cjs +608 -148
  41. package/gsd-core/bin/lib/capability-source.cjs +92 -0
  42. package/gsd-core/bin/lib/capability-trust.cjs +444 -25
  43. package/gsd-core/bin/lib/capability-validator.cjs +507 -24
  44. package/gsd-core/bin/lib/capability-writer.cjs +3 -2
  45. package/gsd-core/bin/lib/check-command-router.cjs +114 -38
  46. package/gsd-core/bin/lib/claude-orchestration.cjs +56 -3
  47. package/gsd-core/bin/lib/codex-agent-toml.cjs +329 -0
  48. package/gsd-core/bin/lib/command-aliases.cjs +94 -0
  49. package/gsd-core/bin/lib/command-roster.cjs +44 -1
  50. package/gsd-core/bin/lib/commands.cjs +665 -99
  51. package/gsd-core/bin/lib/commonjs-marker.cjs +142 -0
  52. package/gsd-core/bin/lib/complexity-trigger.cjs +1172 -0
  53. package/gsd-core/bin/lib/config-loader.cjs +76 -0
  54. package/gsd-core/bin/lib/config.cjs +22 -2
  55. package/gsd-core/bin/lib/context-composer.cjs +278 -0
  56. package/gsd-core/bin/lib/context-predicates.cjs +506 -0
  57. package/gsd-core/bin/lib/core-utils.cjs +217 -40
  58. package/gsd-core/bin/lib/decisions.cjs +23 -0
  59. package/gsd-core/bin/lib/docs.cjs +3 -2
  60. package/gsd-core/bin/lib/external-job.cjs +19 -4
  61. package/gsd-core/bin/lib/fallow-runner.cjs +20 -44
  62. package/gsd-core/bin/lib/frontmatter.cjs +239 -32
  63. package/gsd-core/bin/lib/gap-checker.cjs +68 -7
  64. package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +57 -6
  65. package/gsd-core/bin/lib/git-base-branch.cjs +160 -15
  66. package/gsd-core/bin/lib/graphify.cjs +142 -27
  67. package/gsd-core/bin/lib/gsd2-import.cjs +37 -5
  68. package/gsd-core/bin/lib/health-diagnostic-rules/agent-install.cjs +101 -0
  69. package/gsd-core/bin/lib/health-diagnostic-rules/config-validation.cjs +348 -0
  70. package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +145 -0
  71. package/gsd-core/bin/lib/health-diagnostic-rules/install-surface-shadowing.cjs +98 -0
  72. package/gsd-core/bin/lib/health-diagnostic-rules/milestone-archive-hygiene.cjs +100 -0
  73. package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +222 -0
  74. package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +265 -0
  75. package/gsd-core/bin/lib/health-diagnostic-rules/root-existence.cjs +161 -0
  76. package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +303 -0
  77. package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +173 -0
  78. package/gsd-core/bin/lib/health-diagnostic-types.cjs +68 -0
  79. package/gsd-core/bin/lib/health-diagnostic.cjs +431 -0
  80. package/gsd-core/bin/lib/host-integration.cjs +13 -1
  81. package/gsd-core/bin/lib/host-runtime-detection.cjs +134 -0
  82. package/gsd-core/bin/lib/init-command-router.cjs +83 -8
  83. package/gsd-core/bin/lib/init.cjs +1325 -169
  84. package/gsd-core/bin/lib/install-effort-resolver.cjs +73 -30
  85. package/gsd-core/bin/lib/install-engine.cjs +805 -264
  86. package/gsd-core/bin/lib/install-fs-adapter.cjs +262 -0
  87. package/gsd-core/bin/lib/install-model-override-resolver.cjs +203 -0
  88. package/gsd-core/bin/lib/install-profiles.cjs +160 -57
  89. package/gsd-core/bin/lib/install-scope.cjs +270 -0
  90. package/gsd-core/bin/lib/install-shadow-report.cjs +385 -0
  91. package/gsd-core/bin/lib/installed-surface-resolver.cjs +381 -0
  92. package/gsd-core/bin/lib/installer-migration-authoring.cjs +3 -1
  93. package/gsd-core/bin/lib/installer-migration-report.cjs +4 -0
  94. package/gsd-core/bin/lib/installer-migrations/007-retire-config-root-commonjs-marker.cjs +149 -0
  95. package/gsd-core/bin/lib/installer-migrations/008-cursor-retire-commands-surface.cjs +55 -0
  96. package/gsd-core/bin/lib/installer-migrations/009-pi-retire-reserved-hooks-dir.cjs +199 -0
  97. package/gsd-core/bin/lib/installer-migrations.cjs +206 -13
  98. package/gsd-core/bin/lib/io.cjs +38 -3
  99. package/gsd-core/bin/lib/markdown-sectionizer.cjs +8 -1
  100. package/gsd-core/bin/lib/markdown-table.cjs +133 -20
  101. package/gsd-core/bin/lib/mcp-catalog.cjs +518 -0
  102. package/gsd-core/bin/lib/mcp-server.cjs +135 -3
  103. package/gsd-core/bin/lib/milestone-lock.cjs +248 -0
  104. package/gsd-core/bin/lib/milestone.cjs +821 -109
  105. package/gsd-core/bin/lib/model-catalog.cjs +59 -1
  106. package/gsd-core/bin/lib/model-resolver.cjs +183 -40
  107. package/gsd-core/bin/lib/normalize-test-command.cjs +1 -1
  108. package/gsd-core/bin/lib/pattern.cjs +122 -0
  109. package/gsd-core/bin/lib/phase-estimation.cjs +1 -1
  110. package/gsd-core/bin/lib/phase-id.cjs +507 -36
  111. package/gsd-core/bin/lib/phase-lifecycle.cjs +28 -3
  112. package/gsd-core/bin/lib/phase-locator.cjs +258 -58
  113. package/gsd-core/bin/lib/phase.cjs +891 -156
  114. package/gsd-core/bin/lib/plan-dependency-graph.cjs +303 -0
  115. package/gsd-core/bin/lib/plan-drift-guard.cjs +120 -0
  116. package/gsd-core/bin/lib/plan-scan.cjs +86 -2
  117. package/gsd-core/bin/lib/planning-scope.cjs +31 -0
  118. package/gsd-core/bin/lib/planning-snapshot.cjs +890 -0
  119. package/gsd-core/bin/lib/planning-workspace.cjs +60 -6
  120. package/gsd-core/bin/lib/probe-core.cjs +1 -1
  121. package/gsd-core/bin/lib/profile-output.cjs +1 -1
  122. package/gsd-core/bin/lib/prompt-budget.cjs +128 -165
  123. package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +740 -0
  124. package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +85 -0
  125. package/gsd-core/bin/lib/review-lane-descriptor.cjs +108 -0
  126. package/gsd-core/bin/lib/review-lane-invocation.cjs +30 -0
  127. package/gsd-core/bin/lib/review-lane-runner.cjs +447 -68
  128. package/gsd-core/bin/lib/review-reviewer-selection.cjs +13 -18
  129. package/gsd-core/bin/lib/roadmap-command-router.cjs +76 -9
  130. package/gsd-core/bin/lib/roadmap-parser.cjs +1035 -194
  131. package/gsd-core/bin/lib/roadmap-upgrade.cjs +37 -10
  132. package/gsd-core/bin/lib/roadmap.cjs +405 -84
  133. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +795 -100
  134. package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +14 -2
  135. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +440 -57
  136. package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +3 -2
  137. package/gsd-core/bin/lib/runtime-homes.cjs +220 -41
  138. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +220 -44
  139. package/gsd-core/bin/lib/runtime-name-policy.cjs +3 -1
  140. package/gsd-core/bin/lib/runtime-slash.cjs +27 -9
  141. package/gsd-core/bin/lib/section-manifest.cjs +209 -0
  142. package/gsd-core/bin/lib/security.cjs +104 -5
  143. package/gsd-core/bin/lib/shell-command-projection.cjs +388 -30
  144. package/gsd-core/bin/lib/smart-entry.cjs +154 -22
  145. package/gsd-core/bin/lib/state-command-router.cjs +5 -1
  146. package/gsd-core/bin/lib/state-document.cjs +152 -8
  147. package/gsd-core/bin/lib/state-transition.cjs +424 -105
  148. package/gsd-core/bin/lib/state.cjs +1927 -401
  149. package/gsd-core/bin/lib/surface.cjs +35 -10
  150. package/gsd-core/bin/lib/text-lines.cjs +80 -0
  151. package/gsd-core/bin/lib/token-scanner.cjs +76 -0
  152. package/gsd-core/bin/lib/uat-predicate.cjs +20 -4
  153. package/gsd-core/bin/lib/uat.cjs +706 -64
  154. package/gsd-core/bin/lib/ui-frontend-evidence.cjs +157 -0
  155. package/gsd-core/bin/lib/ui-safety-gate.cjs +14 -5
  156. package/gsd-core/bin/lib/unusable-input.cjs +33 -0
  157. package/gsd-core/bin/lib/update-context.cjs +8 -2
  158. package/gsd-core/bin/lib/user-artifact-staging.cjs +705 -0
  159. package/gsd-core/bin/lib/validate.cjs +20 -6
  160. package/gsd-core/bin/lib/vendor/README.md +37 -0
  161. package/gsd-core/bin/lib/vendor/re2js.cjs +6480 -0
  162. package/gsd-core/bin/lib/vendor/re2js.d.cts +938 -0
  163. package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
  164. package/gsd-core/bin/lib/verification.cjs +287 -20
  165. package/gsd-core/bin/lib/verify.cjs +368 -880
  166. package/gsd-core/bin/lib/workflow-fragments.cjs +557 -0
  167. package/gsd-core/bin/lib/workstream-inventory-builder.cjs +203 -19
  168. package/gsd-core/bin/lib/workstream-inventory.cjs +576 -31
  169. package/gsd-core/bin/lib/workstream.cjs +8 -2
  170. package/gsd-core/bin/lib/worktree-base-ref.cjs +50 -6
  171. package/gsd-core/bin/lib/worktree-safety.cjs +450 -125
  172. package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
  173. package/gsd-core/bin/shared/config-schema.manifest.json +9 -1
  174. package/gsd-core/references/agent-contracts.md +43 -26
  175. package/gsd-core/references/artifact-types.md +10 -3
  176. package/gsd-core/references/autonomous-ui-design-contract.md +42 -0
  177. package/gsd-core/references/checkpoints.md +2 -2
  178. package/gsd-core/references/context-budget.md +1 -1
  179. package/gsd-core/references/debugger-techniques.md +255 -0
  180. package/gsd-core/references/dispatch-isolation-gate.md +138 -0
  181. package/gsd-core/references/doc-conflict-engine.md +1 -1
  182. package/gsd-core/references/execute-mvp-tdd.md +3 -3
  183. package/gsd-core/references/execute-phase-between-wave-reset.md +6 -2
  184. package/gsd-core/references/execute-phase-context-guard.md +1 -1
  185. package/gsd-core/references/execute-phase-response-language.md +1 -1
  186. package/gsd-core/references/execute-phase-wave-guard.md +6 -2
  187. package/gsd-core/references/gate-prompts.md +1 -1
  188. package/gsd-core/references/git-planning-commit.md +2 -1
  189. package/gsd-core/references/loop-hook-dispatch.md +39 -2
  190. package/gsd-core/references/model-profiles.md +12 -4
  191. package/gsd-core/references/mvp-concepts.md +9 -9
  192. package/gsd-core/references/planner-guidance.md +3 -9
  193. package/gsd-core/references/planner-preconditions.md +1 -1
  194. package/gsd-core/references/planner-reviews.md +1 -1
  195. package/gsd-core/references/planning-config.md +8 -6
  196. package/gsd-core/references/research-documentation-lookup.md +5 -3
  197. package/gsd-core/references/revision-loop.md +1 -1
  198. package/gsd-core/references/specless-probe-fallback.md +8 -7
  199. package/gsd-core/references/universal-anti-patterns.md +3 -3
  200. package/gsd-core/references/verifier-phase-gates.md +192 -0
  201. package/gsd-core/references/verifier-wiring-patterns.md +100 -0
  202. package/gsd-core/references/verify-mvp-mode.md +1 -1
  203. package/gsd-core/references/workstream-flag.md +22 -6
  204. package/gsd-core/references/worktree-branch-check.md +2 -2
  205. package/gsd-core/templates/discussion-log.md +1 -1
  206. package/gsd-core/templates/phase-prompt.md +2 -4
  207. package/gsd-core/templates/state.md +4 -4
  208. package/gsd-core/templates/summary-complex.md +2 -0
  209. package/gsd-core/templates/summary-minimal.md +2 -0
  210. package/gsd-core/templates/summary-standard.md +2 -0
  211. package/gsd-core/templates/summary.md +2 -0
  212. package/gsd-core/templates/verification-report.md +9 -1
  213. package/gsd-core/workflows/ai-integration-phase.md +9 -11
  214. package/gsd-core/workflows/audit-milestone.md +3 -0
  215. package/gsd-core/workflows/autonomous/steps/converge-banner.md +1 -0
  216. package/gsd-core/workflows/autonomous/steps/converge-dispatch-bg.md +11 -0
  217. package/gsd-core/workflows/autonomous/steps/converge-dispatch-inline.md +7 -0
  218. package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +21 -0
  219. package/gsd-core/workflows/autonomous/steps/converge-loop.md +7 -0
  220. package/gsd-core/workflows/autonomous.md +33 -70
  221. package/gsd-core/workflows/cleanup.md +62 -3
  222. package/gsd-core/workflows/code-review/steps/dispatch-fix.md +39 -0
  223. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +93 -0
  224. package/gsd-core/workflows/code-review-fix.md +37 -10
  225. package/gsd-core/workflows/code-review.md +74 -166
  226. package/gsd-core/workflows/complete-milestone/steps/git-tag.md +29 -0
  227. package/gsd-core/workflows/complete-milestone.md +160 -95
  228. package/gsd-core/workflows/debug.md +16 -17
  229. package/gsd-core/workflows/diagnose-issues.md +56 -8
  230. package/gsd-core/workflows/discuss-phase/modes/chain.md +2 -1
  231. package/gsd-core/workflows/discuss-phase/modes/default.md +1 -1
  232. package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +15 -0
  233. package/gsd-core/workflows/discuss-phase-assumptions.md +7 -17
  234. package/gsd-core/workflows/docs-update/steps/dispatch-monorepo-packages.md +51 -0
  235. package/gsd-core/workflows/docs-update.md +8 -51
  236. package/gsd-core/workflows/edit-phase.md +26 -1
  237. package/gsd-core/workflows/eval-review.md +3 -5
  238. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +64 -7
  239. package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +50 -0
  240. package/gsd-core/workflows/execute-phase/steps/partial-wave.md +31 -0
  241. package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +77 -0
  242. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +21 -0
  243. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +42 -0
  244. package/gsd-core/workflows/execute-phase/steps/regression-gate.md +43 -37
  245. package/gsd-core/workflows/execute-phase.md +103 -187
  246. package/gsd-core/workflows/execute-plan.md +36 -4
  247. package/gsd-core/workflows/explore.md +131 -4
  248. package/gsd-core/workflows/fast.md +10 -2
  249. package/gsd-core/workflows/health.md +73 -4
  250. package/gsd-core/workflows/help/modes/full.md +6 -1
  251. package/gsd-core/workflows/import.md +4 -4
  252. package/gsd-core/workflows/ingest-docs.md +7 -6
  253. package/gsd-core/workflows/mvp-phase.md +6 -3
  254. package/gsd-core/workflows/new-milestone/steps/project-md-milestone-write.md +16 -0
  255. package/gsd-core/workflows/new-milestone/steps/reset-phase-safety.md +19 -0
  256. package/gsd-core/workflows/new-milestone.md +35 -47
  257. package/gsd-core/workflows/new-project/steps/auto-mode-config.md +176 -0
  258. package/gsd-core/workflows/new-project/steps/auto-mode-detection.md +32 -0
  259. package/gsd-core/workflows/new-project/steps/codebase-map-offer.md +18 -0
  260. package/gsd-core/workflows/new-project.md +27 -240
  261. package/gsd-core/workflows/next.md +12 -0
  262. package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +15 -0
  263. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +110 -0
  264. package/gsd-core/workflows/plan-phase/steps/prd-express-gate.md +8 -0
  265. package/gsd-core/workflows/plan-phase/steps/research-only-early-exit.md +17 -0
  266. package/gsd-core/workflows/plan-phase/steps/research-only-modifiers.md +16 -0
  267. package/gsd-core/workflows/plan-phase/steps/reviews-prerequisite.md +17 -0
  268. package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +149 -0
  269. package/gsd-core/workflows/plan-phase.md +89 -209
  270. package/gsd-core/workflows/plan-review-convergence.md +50 -2
  271. package/gsd-core/workflows/progress/steps/forensic-audit.md +125 -0
  272. package/gsd-core/workflows/progress/steps/mvp-display.md +18 -0
  273. package/gsd-core/workflows/progress.md +45 -159
  274. package/gsd-core/workflows/quick/steps/discussion-phase.md +124 -0
  275. package/gsd-core/workflows/quick/steps/plan-checker-loop.md +111 -0
  276. package/gsd-core/workflows/quick/steps/quick-verification.md +67 -0
  277. package/gsd-core/workflows/quick/steps/research-phase.md +72 -0
  278. package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +37 -0
  279. package/gsd-core/workflows/quick.md +55 -405
  280. package/gsd-core/workflows/resume-project.md +3 -0
  281. package/gsd-core/workflows/review/steps/reviewer-instances-note-1.md +4 -0
  282. package/gsd-core/workflows/review/steps/reviewer-instances-note-2.md +3 -0
  283. package/gsd-core/workflows/review.md +41 -13
  284. package/gsd-core/workflows/section-manifest.json +219 -0
  285. package/gsd-core/workflows/secure-phase.md +1 -1
  286. package/gsd-core/workflows/session-report.md +2 -1
  287. package/gsd-core/workflows/settings.md +66 -2
  288. package/gsd-core/workflows/ship.md +104 -44
  289. package/gsd-core/workflows/sketch.md +1 -1
  290. package/gsd-core/workflows/spec-phase.md +41 -20
  291. package/gsd-core/workflows/spike-wrap-up.md +20 -5
  292. package/gsd-core/workflows/spike.md +50 -16
  293. package/gsd-core/workflows/sync-skills.md +106 -13
  294. package/gsd-core/workflows/transition/steps/workstream-collision-check.md +17 -0
  295. package/gsd-core/workflows/transition.md +53 -31
  296. package/gsd-core/workflows/ui-phase.md +13 -12
  297. package/gsd-core/workflows/ui-review.md +2 -2
  298. package/gsd-core/workflows/update/steps/channel-banner.md +7 -0
  299. package/gsd-core/workflows/update.md +19 -8
  300. package/gsd-core/workflows/validate-phase.md +1 -1
  301. package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +36 -0
  302. package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +21 -0
  303. package/gsd-core/workflows/verify-work.md +17 -65
  304. package/hooks/dist/gsd-agent-isolation-guard.js +517 -0
  305. package/hooks/dist/gsd-check-update-worker.js +64 -12
  306. package/hooks/dist/gsd-check-update.js +19 -1
  307. package/hooks/dist/gsd-cursor-pre-tool.js +0 -3
  308. package/hooks/dist/gsd-cursor-subagent-start.js +607 -26
  309. package/hooks/dist/gsd-cursor-subagent-stop.js +3 -2
  310. package/hooks/dist/gsd-prompt-guard.js +21 -20
  311. package/hooks/dist/gsd-read-injection-scanner.js +45 -24
  312. package/hooks/dist/gsd-statusline.js +90 -6
  313. package/hooks/dist/gsd-update-banner.js +22 -1
  314. package/hooks/dist/gsd-workflow-guard.js +134 -36
  315. package/hooks/dist/gsd-worktree-path-guard.js +2 -1
  316. package/hooks/dist/gsd-write-guard.js +359 -0
  317. package/hooks/dist/lib/git-cmd.js +92 -59
  318. package/hooks/dist/lib/injection-patterns.js +45 -0
  319. package/hooks/dist/lib/isolation-deny-reason.js +39 -0
  320. package/hooks/dist/lib/isolation-sentinel.js +277 -0
  321. package/hooks/dist/managed-hooks-registry.cjs +2 -0
  322. package/hooks/gsd-agent-isolation-guard.js +517 -0
  323. package/hooks/gsd-check-update-worker.js +64 -12
  324. package/hooks/gsd-check-update.js +19 -1
  325. package/hooks/gsd-cursor-pre-tool.js +0 -3
  326. package/hooks/gsd-cursor-subagent-start.js +607 -26
  327. package/hooks/gsd-cursor-subagent-stop.js +3 -2
  328. package/hooks/gsd-prompt-guard.js +21 -20
  329. package/hooks/gsd-read-injection-scanner.js +45 -24
  330. package/hooks/gsd-statusline.js +90 -6
  331. package/hooks/gsd-update-banner.js +22 -1
  332. package/hooks/gsd-workflow-guard.js +134 -36
  333. package/hooks/gsd-worktree-path-guard.js +2 -1
  334. package/hooks/gsd-write-guard.js +359 -0
  335. package/hooks/hooks.json +12 -0
  336. package/hooks/lib/git-cmd.js +92 -59
  337. package/hooks/lib/injection-patterns.js +45 -0
  338. package/hooks/lib/isolation-deny-reason.js +39 -0
  339. package/hooks/lib/isolation-sentinel.js +277 -0
  340. package/hooks/managed-hooks-registry.cjs +2 -0
  341. package/package.json +31 -10
  342. package/pi/gsd.cjs +71 -12
  343. package/scripts/baselines/planning-prompt-drift-baseline.json +4 -0
  344. package/scripts/baselines/planning-snapshot-bypass-baseline.json +12 -0
  345. package/scripts/baselines/unreachable-guard-drift-baseline.json +4 -0
  346. package/scripts/build-hooks.js +9 -0
  347. package/scripts/changeset/lint.cjs +68 -6
  348. package/scripts/changeset/serialize.cjs +5 -1
  349. package/scripts/check-alias-drift.cjs +7 -43
  350. package/scripts/check-contract-drift.cjs +297 -0
  351. package/scripts/ci-test-scope.cjs +19 -2
  352. package/scripts/command-contract-helpers.cjs +903 -1
  353. package/scripts/gen-adr-index.cjs +728 -38
  354. package/scripts/gen-capability-matrix.cjs +1 -1
  355. package/scripts/gen-capability-registry.cjs +3 -15
  356. package/scripts/gen-context-index.cjs +439 -0
  357. package/scripts/gen-health-docs.cjs +390 -0
  358. package/scripts/gen-inventory-manifest.cjs +150 -4
  359. package/scripts/gen-loop-host-contract.cjs +4 -24
  360. package/scripts/gen-prompt-budget-parity-corpus.cjs +645 -0
  361. package/scripts/gen-registry.cjs +3 -14
  362. package/scripts/gen-section-manifest.cjs +638 -0
  363. package/scripts/generate-package-identity.cjs +4 -2
  364. package/scripts/lib/alias-drift-families.cjs +46 -0
  365. package/scripts/lib/drift-scan.cjs +278 -0
  366. package/scripts/lint-allow-test-rule-refs.allowlist.json +15 -54
  367. package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +4 -0
  368. package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +3 -0
  369. package/scripts/lint-canary-version-leak.cjs +73 -0
  370. package/scripts/lint-command-contract.cjs +96 -13
  371. package/scripts/lint-compiled-artifact-sync.cjs +6 -1
  372. package/scripts/lint-completion-predicate-drift.cjs +933 -0
  373. package/scripts/lint-completion-ratio-drift.cjs +214 -0
  374. package/scripts/lint-default-flip-documentation.cjs +193 -0
  375. package/scripts/lint-docs-command-form.cjs +195 -0
  376. package/scripts/lint-docs-required.cjs +9 -1
  377. package/scripts/lint-emitted-drift-ack.cjs +215 -20
  378. package/scripts/lint-eslint-glob-coverage.allowlist.json +34 -0
  379. package/scripts/lint-eslint-glob-coverage.cjs +340 -0
  380. package/scripts/lint-example-parser-parity.cjs +395 -0
  381. package/scripts/lint-frontmatter-scalar-broad-grep.cjs +237 -0
  382. package/scripts/lint-health-diagnostic-rule-table.cjs +404 -0
  383. package/scripts/lint-hooks-runtime-build-seam.cjs +262 -0
  384. package/scripts/lint-milestone-window-drift.cjs +468 -0
  385. package/scripts/lint-phase-enumeration-drift.cjs +479 -0
  386. package/scripts/lint-plan-count-drift.cjs +318 -0
  387. package/scripts/lint-planning-artifact-writer-drift.cjs +398 -0
  388. package/scripts/lint-planning-prompt-drift.cjs +434 -0
  389. package/scripts/lint-planning-snapshot-bypass-drift.cjs +544 -0
  390. package/scripts/lint-regression-test-names.cjs +15 -13
  391. package/scripts/lint-removed-but-needed.cjs +320 -0
  392. package/scripts/lint-state-field-drift.cjs +805 -0
  393. package/scripts/lint-state-write-path-drift.cjs +1045 -0
  394. package/scripts/lint-test-file-count.allowlist.json +40 -3
  395. package/scripts/lint-unreachable-guard-drift.cjs +843 -0
  396. package/scripts/lint-vendored-deps.cjs +124 -0
  397. package/scripts/mutation-matrix.cjs +13 -0
  398. package/scripts/pr-changed-files.cjs +63 -0
  399. package/scripts/pr-template-policy.cjs +14 -4
  400. package/scripts/prompt-injection-scan.sh +52 -6
  401. package/scripts/require-issue-link-policy.cjs +192 -0
  402. package/scripts/state-write-path-drift-baseline.json +19 -0
  403. package/scripts/sync-runtime-launcher.cjs +2 -4
  404. package/skills/gsd-autonomous/SKILL.md +0 -1
  405. package/skills/gsd-code-review/SKILL.md +1 -1
  406. package/skills/gsd-execute-phase/SKILL.md +1 -2
  407. package/skills/gsd-map-codebase/SKILL.md +1 -1
  408. package/skills/gsd-mempalace-capture/SKILL.md +2 -2
  409. package/skills/gsd-mempalace-recall/SKILL.md +1 -1
  410. package/skills/gsd-new-milestone/SKILL.md +2 -2
  411. package/skills/gsd-next/SKILL.md +0 -1
  412. package/skills/gsd-plan-phase/SKILL.md +1 -2
  413. package/skills/gsd-progress/SKILL.md +0 -1
  414. package/skills/gsd-quick/SKILL.md +1 -1
  415. package/skills/gsd-review-backlog/SKILL.md +2 -1
  416. package/skills/gsd-stats/SKILL.md +0 -1
  417. package/skills/gsd-verify-work/SKILL.md +1 -1
  418. package/vscode/package.json +1 -1
  419. package/gsd-core/workflows/discovery-phase.md +0 -298
  420. package/gsd-core/workflows/plan-milestone-gaps.md +0 -281
  421. package/gsd-core/workflows/verify-phase.md +0 -577
  422. package/scripts/affected-tests-lib.cjs +0 -554
  423. package/scripts/gen-emitted-baseline.cjs +0 -145
  424. package/scripts/lint-allow-test-rule-refs.cjs +0 -162
  425. package/scripts/run-affected-tests.cjs +0 -7
  426. package/scripts/run-tests.cjs +0 -1050
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ /**
3
+ * Install Surface Shadowing rule (#2873, epic #2866 Phase 4a — governed by
4
+ * `.gsd/phase/feat-2873-cross-scope-shadowing/40-design.md`).
5
+ *
6
+ * One code, W028, surfacing `install-shadow-report.cts`'s `ShadowReport` as
7
+ * a `/gsd-health` diagnostic — the design doc's row #4 ("one diagnostic,
8
+ * severity WARNING, same projection" as the install-time report). WARNING
9
+ * severity, ADVISE remedy with `risk: NONE`: shadowing is never auto-fixable
10
+ * (there is no single correct scope to remove) so this is advisory only,
11
+ * mirroring `agent-install.cts`'s W010 shape.
12
+ *
13
+ * Reaches OUTSIDE the planning snapshot the same way `agent-install.cts`
14
+ * does for W010: `resolveRuntime(cwd)` (`runtime-slash.cjs`) resolves the
15
+ * runtime id from `process.env.GSD_RUNTIME` / `config.runtime` / the
16
+ * `'claude'` default (never throws), using `snapshot.cwd`
17
+ * (`planning-snapshot.cts`'s `buildPlanningSnapshot` — `path.resolve(cwd)`)
18
+ * as the project directory. `buildShadowReport` is then called with that
19
+ * `cwd` so the local scope resolves against the project actually being
20
+ * health-checked, while `home` is left un-injected so the resolver defaults
21
+ * to `os.homedir()` — the real machine, same production call shape the
22
+ * installer uses.
23
+ *
24
+ * `check(snapshot)` degrades to `[]` (never throws) whenever there is
25
+ * nothing installable to report: `buildShadowReport` itself already
26
+ * degrades an unresolvable runtime (`configHome.kind === 'none'`, e.g.
27
+ * vscode — design row #7) to `reason: RESOLVER_UNAVAILABLE`, which
28
+ * `renderShadowReport` renders as `[]`; the try/catch around both calls
29
+ * below additionally absorbs any other unexpected throw (design row D5),
30
+ * since this rule is advisory and must never make `/gsd-health` itself
31
+ * fail.
32
+ *
33
+ * Design: .gsd/phase/feat-2873-cross-scope-shadowing/40-design.md
34
+ *
35
+ * ADR-457 build-at-publish: source in
36
+ * src/health-diagnostic-rules/install-surface-shadowing.cts, compiled to
37
+ * gsd-core/bin/lib/health-diagnostic-rules/install-surface-shadowing.cjs
38
+ * (gitignored).
39
+ */
40
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
41
+ const healthDiagnosticMod = require("../health-diagnostic-types.cjs");
42
+ const { SEVERITY, adviseRemedy } = healthDiagnosticMod;
43
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
44
+ const installShadowReportMod = require("../install-shadow-report.cjs");
45
+ const { buildShadowReport, renderShadowReport } = installShadowReportMod;
46
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
47
+ const runtimeSlashMod = require("../runtime-slash.cjs");
48
+ const { resolveRuntime } = runtimeSlashMod;
49
+ const package_identity_cjs_1 = require("../package-identity.cjs");
50
+ /**
51
+ * `check(snapshot)` for W028 — see module header for the degrade-to-`[]`
52
+ * cases and the runtime-resolution mechanism reused from `agent-install.cts`.
53
+ */
54
+ function checkInstallSurfaceShadowing(snapshot) {
55
+ let lines;
56
+ let runtime;
57
+ try {
58
+ runtime = resolveRuntime(snapshot.cwd);
59
+ const report = buildShadowReport(runtime, { cwd: snapshot.cwd });
60
+ // `renderShadowReport` returns `[]` for every reason other than
61
+ // SCOPE_SHADOWED (design rows #1, #2, #6, #7, #8, #11), and sanitizes
62
+ // every `declaredRuntime` it interpolates via `sanitizeForRender`
63
+ // internally (`install-shadow-report.cts`) — this rule's `message`
64
+ // reuses that render path rather than re-sanitizing, so the
65
+ // sanitize-at-the-render-seam guarantee (design row #13) holds here too.
66
+ // Trigger names are already SAFE_STEM-gated upstream
67
+ // (`installed-surface-resolver.cts`'s `deriveStemsForKindEntry`) before
68
+ // they ever reach a rendered line — no re-gating needed here either.
69
+ lines = renderShadowReport(report);
70
+ }
71
+ catch {
72
+ // Advisory rule: an unresolvable runtime, a `configHome.kind === 'none'`
73
+ // runtime, or any other unexpected failure degrades to "no finding",
74
+ // never a thrown exception that would break `/gsd-health` itself
75
+ // (design row D5).
76
+ return [];
77
+ }
78
+ if (lines.length === 0)
79
+ return [];
80
+ return [
81
+ {
82
+ code: 'W028',
83
+ severity: SEVERITY.WARNING,
84
+ message: lines.join(' '),
85
+ remedy: adviseRemedy(`Review install scopes for ${runtime}: npx ${package_identity_cjs_1.PACKAGE_NAME}@latest`),
86
+ },
87
+ ];
88
+ }
89
+ const RULES = [
90
+ {
91
+ code: 'W028',
92
+ severity: SEVERITY.WARNING,
93
+ description: 'A GSD-owned install scope shadows another on this machine',
94
+ repairable: false,
95
+ check: checkInstallSurfaceShadowing,
96
+ },
97
+ ];
98
+ module.exports = { RULES };
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ /**
3
+ * Health Diagnostic — Milestone archive + root hygiene rules (Phase 11,
4
+ * #3309, ADR-3180 §8.2/§8.3/§8.5).
5
+ *
6
+ * Group: "Milestone archive + root hygiene" (design doc, "Rule table
7
+ * organization" table) — W018, W019.
8
+ *
9
+ * Ported behavior-preserving from `cmdValidateHealth`
10
+ * (`src/verify.cts:2301-2354`), the exact call sites for W018/W019.
11
+ *
12
+ * Design: .gsd/phase/refactor-3309-health-diagnostic-rule-table/40-design.md
13
+ *
14
+ * ADR-457 build-at-publish: source in
15
+ * src/health-diagnostic-rules/milestone-archive-hygiene.cts, compiled to
16
+ * gsd-core/bin/lib/health-diagnostic-rules/milestone-archive-hygiene.cjs
17
+ * (gitignored).
18
+ */
19
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
20
+ const healthDiagnosticMod = require("../health-diagnostic-types.cjs");
21
+ const { SEVERITY, REMEDY_ACTION, REMEDY_RISK, adviseRemedy } = healthDiagnosticMod;
22
+ const artifacts_cjs_1 = require("../artifacts.cjs");
23
+ // ─── W018 — MILESTONES.md missing archived milestone(s) (verify.cts:2301-2335) ──
24
+ //
25
+ // Condition: `snapshot.milestoneArchiveStatus.value.archivedVersions` (list of
26
+ // versions with a `.planning/milestones/<ver>-ROADMAP.md` snapshot file) minus
27
+ // `.documentedVersions` (list of `## <version>` headings already present in
28
+ // MILESTONES.md) — versions present in the archive but not documented in the
29
+ // registry. ONE aggregate `Diagnostic` listing every missing version, exactly
30
+ // mirroring the original's single `addIssue` call
31
+ // (`verify.cts:2321-2330`, `` `MILESTONES.md missing ${missingFromRegistry.length}
32
+ // archived milestone(s): ${missingFromRegistry.join(', ')}` ``) — the original
33
+ // computes the FULL list first (`missingFromRegistry`), then fires exactly one
34
+ // `addIssue` after the loop, not once per version. No diagnostic at all if the
35
+ // archive dir has zero recognized `-ROADMAP.md` snapshots (mirrors the
36
+ // original's `if (archivedVersions.length > 0)` guard) or if nothing is
37
+ // missing.
38
+ function checkW018(snapshot) {
39
+ const { archivedVersions, documentedVersions } = snapshot.milestoneArchiveStatus.value;
40
+ if (archivedVersions.length === 0)
41
+ return [];
42
+ const documented = new Set(documentedVersions);
43
+ const missingFromRegistry = archivedVersions.filter((ver) => !documented.has(ver));
44
+ if (missingFromRegistry.length === 0)
45
+ return [];
46
+ return [
47
+ {
48
+ code: 'W018',
49
+ severity: SEVERITY.WARNING,
50
+ message: `MILESTONES.md missing ${missingFromRegistry.length} archived milestone(s): ${missingFromRegistry.join(', ')}`,
51
+ remedy: {
52
+ action: REMEDY_ACTION.BACKFILL_MILESTONES,
53
+ risk: REMEDY_RISK.NONE,
54
+ args: {},
55
+ },
56
+ },
57
+ ];
58
+ }
59
+ // ─── W019 — Unrecognized .planning/ root file (verify.cts:2337-2354) ───────
60
+ //
61
+ // Condition: for each filename in `snapshot.planningRootFiles.value` ending in
62
+ // `.md`, call `isCanonicalPlanningFile(filename)` (bare basename, not a path —
63
+ // `src/artifacts.cts:43`); flag any that return false. One `Diagnostic` PER
64
+ // unrecognized file (array return), mirroring the original's `addIssue` call
65
+ // INSIDE the `for` loop (`verify.cts:2343-2349`) — unlike W018 this is not an
66
+ // aggregate. Fix text copied verbatim from `verify.cts:2347`.
67
+ function checkW019(snapshot) {
68
+ const diagnostics = [];
69
+ for (const filename of snapshot.planningRootFiles.value) {
70
+ if (!filename.endsWith('.md'))
71
+ continue;
72
+ if ((0, artifacts_cjs_1.isCanonicalPlanningFile)(filename))
73
+ continue;
74
+ diagnostics.push({
75
+ code: 'W019',
76
+ severity: SEVERITY.WARNING,
77
+ message: `Unrecognized .planning/ file: ${filename} — not a canonical GSD artifact`,
78
+ remedy: adviseRemedy('Move to .planning/milestones/ archive subdir or delete if stale. See templates/README.md for the canonical artifact list.'),
79
+ });
80
+ }
81
+ return diagnostics;
82
+ }
83
+ // ─── Exports ────────────────────────────────────────────────────────────────
84
+ const RULES = [
85
+ {
86
+ code: 'W018',
87
+ severity: SEVERITY.WARNING,
88
+ description: 'MILESTONES.md missing entry for archived milestone snapshot',
89
+ repairable: true,
90
+ check: checkW018,
91
+ },
92
+ {
93
+ code: 'W019',
94
+ severity: SEVERITY.WARNING,
95
+ description: 'Unrecognized .planning/ root file — not a canonical GSD artifact',
96
+ repairable: false,
97
+ check: checkW019,
98
+ },
99
+ ];
100
+ module.exports = { RULES };
@@ -0,0 +1,222 @@
1
+ "use strict";
2
+ /**
3
+ * Health Diagnostic — Phase directory structure rules (Phase 11, #3309,
4
+ * ADR-3180 §8.2/§8.3/§8.5).
5
+ *
6
+ * Group: "Phase directory structure" (design doc, "Rule table organization"
7
+ * table) — W005, W023, I001, W009.
8
+ *
9
+ * Ported behavior-preserving from `cmdValidateHealth`
10
+ * (`src/verify.cts:1893-1990`, the exact call sites for W005/W023/I001/W009),
11
+ * with two disclosed fidelity reductions forced by `PlanningSnapshot`'s
12
+ * current shape (see each rule's own comment below):
13
+ *
14
+ * - I001 cannot name the individual unsummarized PLAN filename (`snapshot.
15
+ * phases.value[i]` exposes only `planCount`/`summaryCount`, not per-plan
16
+ * filenames) — this rule reports a coarser per-PHASE message instead.
17
+ * - W023's original "described" list called `determinePhaseStatus`
18
+ * (`commands.cts:154`), a SIX-way status string ('Not Started'/'Planned'/
19
+ * 'In Progress'/'Executed'/'Needs Review'/'Complete') computed from its own
20
+ * raw `readdirSync` + `*-VERIFICATION.md` frontmatter read of `phaseDir`.
21
+ * This rule cannot re-run that raw read (§8.1 rule 1 forbids ambient I/O in
22
+ * `check`), so `derivePhaseStatusLabel` below reconstructs the same
23
+ * six-way label from fields `PlanningSnapshot` already exposes —
24
+ * `PhaseSnapshot.planCount`/`summaryCount` (the plan/no-plan and
25
+ * in-progress/planned branches, identical inputs to the original) and
26
+ * `PhaseSnapshot.complete`/`verificationStatus` (`isPhaseComplete`'s own
27
+ * §7.4 disk-strict routing of the SAME `*-VERIFICATION.md` file) for the
28
+ * verification-gated branches. This is a disclosed fidelity reduction, not
29
+ * a byte-for-byte guarantee: `verificationStatus` is the DIFFERENT,
30
+ * `readVerificationStatus`-routed vocabulary ('passed'/'gaps_found'/
31
+ * 'human_needed'/'stale'/'unknown'/'missing') and can disagree with a raw
32
+ * frontmatter re-read in edge cases (e.g. a stale-but-frontmatter-"passed"
33
+ * VERIFICATION.md routes to 'stale', not 'passed', under §7.4's staleness
34
+ * handling — this rule reports 'Executed' there, not 'Complete'). No new
35
+ * ambient I/O and no new `PlanningSnapshot` field were needed — every input
36
+ * was already on `PhaseSnapshot`.
37
+ *
38
+ * W009's original message interpolates `${slash('plan-phase')}`
39
+ * (`verify.cts:1982`, ``Re-run ${slash('plan-phase')} with --research to
40
+ * regenerate``), a per-project runtime-resolved value (`formatGsdSlash`,
41
+ * `src/runtime-slash.cts`) this rule's `(snapshot) => Diagnostic[]`
42
+ * signature has no access to. Hardcodes the canonical `/gsd-plan-phase`
43
+ * hyphen form instead, mirroring the sibling "config.json validation"
44
+ * group's W016 rule (`src/health-diagnostic-rules/config-validation.cts`),
45
+ * which hardcodes `/gsd-ai-integration-phase` the same way for the
46
+ * identical reason.
47
+ *
48
+ * Design: .gsd/phase/refactor-3309-health-diagnostic-rule-table/40-design.md
49
+ *
50
+ * ADR-457 build-at-publish: source in
51
+ * src/health-diagnostic-rules/phase-structure.cts, compiled to
52
+ * gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs (gitignored).
53
+ */
54
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
55
+ const healthDiagnosticMod = require("../health-diagnostic-types.cjs");
56
+ const { SEVERITY, adviseRemedy } = healthDiagnosticMod;
57
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
58
+ const validateMod = require("../validate.cjs");
59
+ const { phaseDirNameRe } = validateMod;
60
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
61
+ const phaseIdMod = require("../phase-id.cjs");
62
+ const { extractPhaseToken, normalizePhaseName, comparePhaseNum } = phaseIdMod;
63
+ // ─── W005 — phase directory doesn't follow NN-name format (verify.cts:1893-1902) ─
64
+ function checkW005(snapshot) {
65
+ const diagnostics = [];
66
+ for (const name of snapshot.phaseDirs.value) {
67
+ if (!name.match(phaseDirNameRe)) {
68
+ diagnostics.push({
69
+ code: 'W005',
70
+ severity: SEVERITY.WARNING,
71
+ message: `Phase directory "${name}" doesn't follow NN-name format`,
72
+ remedy: adviseRemedy('Rename to match pattern (e.g., 01-setup)'),
73
+ });
74
+ }
75
+ }
76
+ return diagnostics;
77
+ }
78
+ // ─── W023 — phase directories collide on normalized key (verify.cts:1904-1950) ─
79
+ //
80
+ // Groups `snapshot.phaseDirs.value` by `normalizePhaseName(extractPhaseToken(name))`
81
+ // — the exact same two owners (`phase-id.cjs`) the original `verify.cts:1917-1918`
82
+ // call site uses, relocated verbatim rather than reimplemented. Sorted with
83
+ // `comparePhaseNum` + a `localeCompare` tiebreak, mirroring
84
+ // `verify.cts:1930-1932`'s deterministic-output rationale. See the file-level
85
+ // comment for the disclosed "described" fidelity reduction.
86
+ /**
87
+ * Reconstruct `commands.cts:154`'s `determinePhaseStatus` six-way label from
88
+ * fields `PhaseSnapshot` already exposes (no ambient I/O, no new snapshot
89
+ * field — see file-level comment). `complete`/`verificationStatus` come from
90
+ * `isPhaseComplete`'s §7.4 disk-strict routing of the same `*-VERIFICATION.md`
91
+ * file the original raw read targeted.
92
+ */
93
+ function derivePhaseStatusLabel(planCount, summaryCount, complete, verificationStatus) {
94
+ if (planCount === 0)
95
+ return 'Not Started';
96
+ if (summaryCount < planCount && summaryCount > 0)
97
+ return 'In Progress';
98
+ if (summaryCount < planCount)
99
+ return 'Planned';
100
+ // summaryCount >= planCount > 0 — verification-gated, same as the original's
101
+ // post-count fall-through.
102
+ if (complete)
103
+ return 'Complete';
104
+ if (verificationStatus === 'human_needed')
105
+ return 'Needs Review';
106
+ // gaps_found / stale / missing / unknown all land here, same as the
107
+ // original's "verification exists but unrecognized" and "no verification
108
+ // file" branches both returning 'Executed'.
109
+ return 'Executed';
110
+ }
111
+ function checkW023(snapshot) {
112
+ const groups = new Map();
113
+ for (const name of snapshot.phaseDirs.value) {
114
+ const token = extractPhaseToken(name);
115
+ const key = normalizePhaseName(token);
116
+ const list = groups.get(key);
117
+ if (list)
118
+ list.push(name);
119
+ else
120
+ groups.set(key, [name]);
121
+ }
122
+ const phaseByDir = new Map(snapshot.phases.value.map((p) => [p.dir, p]));
123
+ const diagnostics = [];
124
+ for (const [key, dirs] of groups) {
125
+ if (dirs.length < 2)
126
+ continue;
127
+ const described = dirs
128
+ .slice()
129
+ .sort((a, b) => comparePhaseNum(a, b) || String(a).localeCompare(String(b)))
130
+ .map((d) => {
131
+ const phase = phaseByDir.get(d);
132
+ const plans = phase ? phase.planCount : 0;
133
+ const summaries = phase ? phase.summaryCount : 0;
134
+ const complete = phase ? phase.complete : false;
135
+ const verificationStatus = phase ? phase.verificationStatus : 'missing';
136
+ const status = derivePhaseStatusLabel(plans, summaries, complete, verificationStatus);
137
+ return `${d} (${status})`;
138
+ })
139
+ .join(', ');
140
+ diagnostics.push({
141
+ code: 'W023',
142
+ severity: SEVERITY.WARNING,
143
+ message: `Phase directories collide on normalized key "${key}": ${described}`,
144
+ remedy: adviseRemedy('Inspect each directory; rename or remove the duplicate so only one directory maps to this phase key'),
145
+ });
146
+ }
147
+ return diagnostics;
148
+ }
149
+ // ─── I001 — plan(s) without a matching SUMMARY.md (verify.cts:1952-1965) ───
150
+ //
151
+ // GENUINE FIDELITY GAP (see file-level comment): the original is PER-PLAN
152
+ // (`${e.name}/${plan} has no SUMMARY.md`, `plan` an individual PLAN.md
153
+ // filename from `findUnsummarizedPlans`). `PlanningSnapshot`'s
154
+ // `phases.value[i]` carries only `planCount`/`summaryCount` NUMBERS per
155
+ // phase — no per-plan filenames — so this rule cannot name which plan lacks
156
+ // a summary without reading the phase directory directly inside `check`
157
+ // (forbidden by §8.1 rule 1). This rule instead reports one coarser
158
+ // per-PHASE diagnostic naming the deficit count, not the individual
159
+ // filename(s).
160
+ function checkI001(snapshot) {
161
+ const diagnostics = [];
162
+ for (const phase of snapshot.phases.value) {
163
+ const deficit = phase.planCount - phase.summaryCount;
164
+ if (deficit > 0) {
165
+ diagnostics.push({
166
+ code: 'I001',
167
+ severity: SEVERITY.INFO,
168
+ message: `Phase ${phase.dir} has ${deficit} plan(s) without a matching summary`,
169
+ remedy: adviseRemedy('May be in progress'),
170
+ });
171
+ }
172
+ }
173
+ return diagnostics;
174
+ }
175
+ // ─── W009 — Validation Architecture in RESEARCH.md but no VALIDATION.md ────
176
+ // (verify.cts:1967-1990)
177
+ function checkW009(snapshot) {
178
+ const diagnostics = [];
179
+ for (const entry of snapshot.researchValidationStatus.value) {
180
+ if (entry.hasValidationArchitecture && !entry.hasValidationMd) {
181
+ diagnostics.push({
182
+ code: 'W009',
183
+ severity: SEVERITY.WARNING,
184
+ message: `Phase ${entry.dir}: has Validation Architecture in RESEARCH.md but no VALIDATION.md`,
185
+ remedy: adviseRemedy('Re-run /gsd-plan-phase with --research to regenerate'),
186
+ });
187
+ }
188
+ }
189
+ return diagnostics;
190
+ }
191
+ // ─── Exports ────────────────────────────────────────────────────────────────
192
+ const RULES = [
193
+ {
194
+ code: 'W005',
195
+ severity: SEVERITY.WARNING,
196
+ description: 'Phase directory naming mismatch',
197
+ repairable: false,
198
+ check: checkW005,
199
+ },
200
+ {
201
+ code: 'W023',
202
+ severity: SEVERITY.WARNING,
203
+ description: 'Phase directories collide on normalized key',
204
+ repairable: false,
205
+ check: checkW023,
206
+ },
207
+ {
208
+ code: 'I001',
209
+ severity: SEVERITY.INFO,
210
+ description: 'Plan without SUMMARY (may be in progress)',
211
+ repairable: false,
212
+ check: checkI001,
213
+ },
214
+ {
215
+ code: 'W009',
216
+ severity: SEVERITY.WARNING,
217
+ description: 'Phase has Validation Architecture in RESEARCH.md but no VALIDATION.md',
218
+ repairable: false,
219
+ check: checkW009,
220
+ },
221
+ ];
222
+ module.exports = { RULES };