@opengsd/gsd-core 1.10.0 → 1.12.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 (544) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/agents/gsd-code-fixer.md +1 -1
  4. package/agents/gsd-debug-session-manager.md +12 -1
  5. package/agents/gsd-debugger.md +1 -1
  6. package/agents/gsd-doc-synthesizer.md +2 -4
  7. package/agents/gsd-dom-verifier.md +169 -0
  8. package/agents/gsd-eval-auditor.md +1 -1
  9. package/agents/gsd-executor.md +22 -14
  10. package/agents/gsd-framework-selector.md +1 -3
  11. package/agents/gsd-intel-updater.md +1 -1
  12. package/agents/gsd-mempalace-curator.md +5 -3
  13. package/agents/gsd-pattern-mapper.md +11 -0
  14. package/agents/gsd-phase-researcher.md +23 -2
  15. package/agents/gsd-plan-checker.md +50 -53
  16. package/agents/gsd-planner.md +50 -50
  17. package/agents/gsd-project-researcher.md +1 -1
  18. package/agents/gsd-research-synthesizer.md +2 -2
  19. package/agents/gsd-roadmapper.md +15 -11
  20. package/agents/gsd-ui-checker.md +63 -4
  21. package/agents/gsd-ui-researcher.md +41 -3
  22. package/agents/gsd-user-profiler.md +3 -0
  23. package/agents/gsd-verifier.md +13 -4
  24. package/bin/install.js +1448 -1103
  25. package/commands/gsd/code-review.md +1 -1
  26. package/commands/gsd/discuss-phase.md +1 -1
  27. package/commands/gsd/execute-phase.md +1 -1
  28. package/commands/gsd/import.md +1 -1
  29. package/commands/gsd/map-codebase.md +1 -1
  30. package/commands/gsd/mempalace-capture.md +1 -1
  31. package/commands/gsd/mempalace-recall.md +1 -1
  32. package/commands/gsd/new-milestone.md +1 -1
  33. package/commands/gsd/quick.md +9 -5
  34. package/commands/gsd/review-backlog.md +2 -1
  35. package/commands/gsd/verify-work.md +1 -1
  36. package/gsd-core/bin/gsd-tools.cjs +1035 -138
  37. package/gsd-core/bin/lib/active-workstream-store.cjs +146 -22
  38. package/gsd-core/bin/lib/adr-parser.cjs +13 -7
  39. package/gsd-core/bin/lib/agent-install-check.cjs +392 -32
  40. package/gsd-core/bin/lib/api-coverage.cjs +33 -14
  41. package/gsd-core/bin/lib/artifacts.cjs +5 -0
  42. package/gsd-core/bin/lib/assumption-delta.cjs +32 -15
  43. package/gsd-core/bin/lib/audit-command-router.cjs +9 -2
  44. package/gsd-core/bin/lib/audit.cjs +1026 -268
  45. package/gsd-core/bin/lib/broken-windows.cjs +306 -28
  46. package/gsd-core/bin/lib/capability-consent.cjs +149 -15
  47. package/gsd-core/bin/lib/capability-lifecycle.cjs +45 -0
  48. package/gsd-core/bin/lib/capability-lock.cjs +10 -4
  49. package/gsd-core/bin/lib/capability-registry.cjs +845 -130
  50. package/gsd-core/bin/lib/capability-source.cjs +92 -0
  51. package/gsd-core/bin/lib/capability-state.cjs +18 -3
  52. package/gsd-core/bin/lib/capability-trust.cjs +444 -25
  53. package/gsd-core/bin/lib/capability-validator.cjs +700 -40
  54. package/gsd-core/bin/lib/capability-writer.cjs +3 -2
  55. package/gsd-core/bin/lib/check-command-router.cjs +216 -42
  56. package/gsd-core/bin/lib/claude-orchestration.cjs +56 -3
  57. package/gsd-core/bin/lib/cli-exit.cjs +496 -10
  58. package/gsd-core/bin/lib/code-review-depth.cjs +288 -0
  59. package/gsd-core/bin/lib/codex-agent-toml.cjs +735 -0
  60. package/gsd-core/bin/lib/command-aliases.cjs +22 -0
  61. package/gsd-core/bin/lib/command-arg-projection.cjs +144 -14
  62. package/gsd-core/bin/lib/command-roster.cjs +44 -1
  63. package/gsd-core/bin/lib/command-routing-hub.cjs +31 -2
  64. package/gsd-core/bin/lib/commands.cjs +1172 -108
  65. package/gsd-core/bin/lib/commonjs-marker.cjs +12 -6
  66. package/gsd-core/bin/lib/complexity-trigger.cjs +1192 -0
  67. package/gsd-core/bin/lib/config-loader.cjs +187 -23
  68. package/gsd-core/bin/lib/config.cjs +102 -3
  69. package/gsd-core/bin/lib/configuration.cjs +129 -37
  70. package/gsd-core/bin/lib/core-utils.cjs +208 -33
  71. package/gsd-core/bin/lib/decisions.cjs +23 -0
  72. package/gsd-core/bin/lib/edge-probe.cjs +9 -1
  73. package/gsd-core/bin/lib/estimate-cli.cjs +55 -11
  74. package/gsd-core/bin/lib/exit-code-registry.cjs +98 -0
  75. package/gsd-core/bin/lib/fallow-runner.cjs +20 -44
  76. package/gsd-core/bin/lib/frontmatter.cjs +899 -229
  77. package/gsd-core/bin/lib/gap-checker.cjs +95 -10
  78. package/gsd-core/bin/lib/git-base-branch.cjs +276 -39
  79. package/gsd-core/bin/lib/gsd2-import.cjs +10 -1
  80. package/gsd-core/bin/lib/health-diagnostic-rules/agent-install.cjs +101 -0
  81. package/gsd-core/bin/lib/health-diagnostic-rules/config-validation.cjs +348 -0
  82. package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +149 -0
  83. package/gsd-core/bin/lib/health-diagnostic-rules/install-surface-shadowing.cjs +98 -0
  84. package/gsd-core/bin/lib/health-diagnostic-rules/milestone-archive-hygiene.cjs +100 -0
  85. package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +222 -0
  86. package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +268 -0
  87. package/gsd-core/bin/lib/health-diagnostic-rules/root-existence.cjs +161 -0
  88. package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +303 -0
  89. package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +187 -0
  90. package/gsd-core/bin/lib/health-diagnostic-types.cjs +68 -0
  91. package/gsd-core/bin/lib/health-diagnostic.cjs +451 -0
  92. package/gsd-core/bin/lib/host-integration.cjs +39 -6
  93. package/gsd-core/bin/lib/host-runtime-detection.cjs +134 -0
  94. package/gsd-core/bin/lib/init-command-router.cjs +118 -21
  95. package/gsd-core/bin/lib/init.cjs +439 -168
  96. package/gsd-core/bin/lib/install-effort-resolver.cjs +73 -30
  97. package/gsd-core/bin/lib/install-engine.cjs +811 -259
  98. package/gsd-core/bin/lib/install-fs-adapter.cjs +262 -0
  99. package/gsd-core/bin/lib/install-model-override-resolver.cjs +235 -0
  100. package/gsd-core/bin/lib/install-profiles.cjs +212 -61
  101. package/gsd-core/bin/lib/install-scope.cjs +270 -0
  102. package/gsd-core/bin/lib/install-shadow-report.cjs +385 -0
  103. package/gsd-core/bin/lib/installed-surface-resolver.cjs +381 -0
  104. package/gsd-core/bin/lib/installer-migration-report.cjs +3 -0
  105. package/gsd-core/bin/lib/installer-migrations/010-antigravity-retire-confighome-artifacts.cjs +169 -0
  106. package/gsd-core/bin/lib/installer-migrations.cjs +148 -38
  107. package/gsd-core/bin/lib/intel.cjs +101 -26
  108. package/gsd-core/bin/lib/io.cjs +170 -15
  109. package/gsd-core/bin/lib/learnings.cjs +85 -14
  110. package/gsd-core/bin/lib/legacy-cleanup.cjs +8 -2
  111. package/gsd-core/bin/lib/markdown-sectionizer.cjs +2 -1
  112. package/gsd-core/bin/lib/markdown-table.cjs +183 -22
  113. package/gsd-core/bin/lib/milestone-lock.cjs +248 -0
  114. package/gsd-core/bin/lib/milestone.cjs +842 -73
  115. package/gsd-core/bin/lib/model-catalog.cjs +232 -16
  116. package/gsd-core/bin/lib/model-resolver.cjs +193 -68
  117. package/gsd-core/bin/lib/normalize-test-command.cjs +1 -1
  118. package/gsd-core/bin/lib/onboard-projection.cjs +5 -1
  119. package/gsd-core/bin/lib/pattern.cjs +122 -0
  120. package/gsd-core/bin/lib/phase-estimation.cjs +18 -9
  121. package/gsd-core/bin/lib/phase-id.cjs +514 -40
  122. package/gsd-core/bin/lib/phase-lifecycle.cjs +52 -19
  123. package/gsd-core/bin/lib/phase-locator.cjs +262 -34
  124. package/gsd-core/bin/lib/phase.cjs +1038 -214
  125. package/gsd-core/bin/lib/plan-dependency-graph.cjs +72 -1
  126. package/gsd-core/bin/lib/plan-document.cjs +263 -0
  127. package/gsd-core/bin/lib/plan-drift-guard.cjs +120 -0
  128. package/gsd-core/bin/lib/plan-scan.cjs +98 -3
  129. package/gsd-core/bin/lib/planning-command-router.cjs +61 -0
  130. package/gsd-core/bin/lib/planning-inspect.cjs +1168 -0
  131. package/gsd-core/bin/lib/planning-scope.cjs +31 -0
  132. package/gsd-core/bin/lib/planning-snapshot.cjs +894 -0
  133. package/gsd-core/bin/lib/planning-workspace.cjs +112 -6
  134. package/gsd-core/bin/lib/probe-core.cjs +5 -2
  135. package/gsd-core/bin/lib/profile-output.cjs +1 -1
  136. package/gsd-core/bin/lib/profile-pipeline-command-router.cjs +50 -7
  137. package/gsd-core/bin/lib/profile-pipeline.cjs +6 -3
  138. package/gsd-core/bin/lib/real-home-guard.cjs +419 -0
  139. package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +766 -0
  140. package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +11 -6
  141. package/gsd-core/bin/lib/review-lane-descriptor.cjs +22 -13
  142. package/gsd-core/bin/lib/review-lane-invocation.cjs +30 -0
  143. package/gsd-core/bin/lib/review-lane-runner.cjs +421 -66
  144. package/gsd-core/bin/lib/review-reviewer-selection.cjs +13 -18
  145. package/gsd-core/bin/lib/roadmap-command-router.cjs +59 -11
  146. package/gsd-core/bin/lib/roadmap-parser.cjs +1006 -184
  147. package/gsd-core/bin/lib/roadmap-upgrade.cjs +37 -10
  148. package/gsd-core/bin/lib/roadmap.cjs +442 -96
  149. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +702 -52
  150. package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +14 -2
  151. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +459 -55
  152. package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +3 -2
  153. package/gsd-core/bin/lib/runtime-homes.cjs +69 -3
  154. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +402 -58
  155. package/gsd-core/bin/lib/runtime-identity.cjs +234 -0
  156. package/gsd-core/bin/lib/runtime-name-policy.cjs +3 -1
  157. package/gsd-core/bin/lib/runtime-slash.cjs +96 -8
  158. package/gsd-core/bin/lib/security.cjs +104 -5
  159. package/gsd-core/bin/lib/shell-command-projection.cjs +342 -7
  160. package/gsd-core/bin/lib/smart-entry.cjs +133 -23
  161. package/gsd-core/bin/lib/spec-section.cjs +12 -7
  162. package/gsd-core/bin/lib/state-command-router.cjs +52 -19
  163. package/gsd-core/bin/lib/state-contract.cjs +359 -0
  164. package/gsd-core/bin/lib/state-document.cjs +338 -8
  165. package/gsd-core/bin/lib/state-md-schema.cjs +221 -0
  166. package/gsd-core/bin/lib/state-transition.cjs +846 -176
  167. package/gsd-core/bin/lib/state.cjs +2589 -369
  168. package/gsd-core/bin/lib/surface.cjs +33 -11
  169. package/gsd-core/bin/lib/task-command-router.cjs +111 -1
  170. package/gsd-core/bin/lib/task-content-resolution.cjs +368 -0
  171. package/gsd-core/bin/lib/teams-status.cjs +4 -1
  172. package/gsd-core/bin/lib/text-lines.cjs +80 -0
  173. package/gsd-core/bin/lib/token-scanner.cjs +76 -0
  174. package/gsd-core/bin/lib/uat-predicate.cjs +67 -23
  175. package/gsd-core/bin/lib/uat.cjs +1761 -167
  176. package/gsd-core/bin/lib/ui-consideration-probe.cjs +9 -1
  177. package/gsd-core/bin/lib/ui-frontend-evidence.cjs +157 -0
  178. package/gsd-core/bin/lib/ui-safety-gate.cjs +51 -12
  179. package/gsd-core/bin/lib/unusable-input.cjs +37 -0
  180. package/gsd-core/bin/lib/update-context.cjs +8 -2
  181. package/gsd-core/bin/lib/user-artifact-staging.cjs +705 -0
  182. package/gsd-core/bin/lib/validate-command-router.cjs +2 -2
  183. package/gsd-core/bin/lib/validate.cjs +20 -6
  184. package/gsd-core/bin/lib/vendor/README.md +75 -0
  185. package/gsd-core/bin/lib/vendor/js-yaml.cjs +3014 -0
  186. package/gsd-core/bin/lib/vendor/re2js.cjs +6480 -0
  187. package/gsd-core/bin/lib/vendor/re2js.d.cts +938 -0
  188. package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
  189. package/gsd-core/bin/lib/verification.cjs +272 -9
  190. package/gsd-core/bin/lib/verify-command-grounding.cjs +846 -0
  191. package/gsd-core/bin/lib/verify.cjs +453 -918
  192. package/gsd-core/bin/lib/workstream-inventory-builder.cjs +53 -32
  193. package/gsd-core/bin/lib/workstream-inventory.cjs +63 -10
  194. package/gsd-core/bin/lib/workstream-name-policy.cjs +25 -4
  195. package/gsd-core/bin/lib/workstream.cjs +2 -2
  196. package/gsd-core/bin/lib/worktree-base-ref.cjs +66 -12
  197. package/gsd-core/bin/lib/worktree-safety.cjs +341 -18
  198. package/gsd-core/bin/shared/config-defaults.manifest.json +8 -1
  199. package/gsd-core/bin/shared/config-schema.manifest.json +12 -1
  200. package/gsd-core/bin/shared/exit-codes.json +8 -0
  201. package/gsd-core/bin/shared/exit-codes.sh +20 -0
  202. package/gsd-core/bin/shared/model-catalog.json +8 -1
  203. package/gsd-core/references/agent-contracts.md +44 -26
  204. package/gsd-core/references/api-coverage.md +24 -2
  205. package/gsd-core/references/autonomous-smart-discuss.md +3 -3
  206. package/gsd-core/references/checkpoints.md +39 -21
  207. package/gsd-core/references/context-budget.md +1 -1
  208. package/gsd-core/references/decimal-phase-calculation.md +5 -5
  209. package/gsd-core/references/dispatch-isolation-gate.md +138 -0
  210. package/gsd-core/references/doc-conflict-engine.md +1 -1
  211. package/gsd-core/references/edge-probe.md +8 -0
  212. package/gsd-core/references/execute-mvp-tdd.md +4 -6
  213. package/gsd-core/references/execute-phase-between-wave-reset.md +15 -14
  214. package/gsd-core/references/execute-phase-context-guard.md +1 -1
  215. package/gsd-core/references/execute-phase-response-language.md +1 -1
  216. package/gsd-core/references/execute-phase-wave-guard.md +17 -11
  217. package/gsd-core/references/failing-direction.md +78 -0
  218. package/gsd-core/references/gate-prompts.md +1 -1
  219. package/gsd-core/references/git-integration.md +5 -5
  220. package/gsd-core/references/git-planning-commit.md +5 -4
  221. package/gsd-core/references/gsd-run-resolver.md +1 -1
  222. package/gsd-core/references/loop-hook-dispatch.md +61 -2
  223. package/gsd-core/references/model-profiles.md +12 -4
  224. package/gsd-core/references/mvp-concepts.md +9 -9
  225. package/gsd-core/references/nyquist-compliance.md +74 -0
  226. package/gsd-core/references/offer-next.md +3 -5
  227. package/gsd-core/references/phase-argument-parsing.md +3 -3
  228. package/gsd-core/references/planner-failing-direction.md +53 -0
  229. package/gsd-core/references/planner-guidance.md +3 -9
  230. package/gsd-core/references/planner-human-verify-mode.md +15 -1
  231. package/gsd-core/references/planner-preconditions.md +1 -1
  232. package/gsd-core/references/planner-reviews.md +1 -1
  233. package/gsd-core/references/planner-revision.md +1 -1
  234. package/gsd-core/references/planner-verify-command-grounding.md +17 -0
  235. package/gsd-core/references/planning-config.md +44 -13
  236. package/gsd-core/references/reviewer-instances.md +31 -0
  237. package/gsd-core/references/revision-loop.md +1 -1
  238. package/gsd-core/references/runtime-aware-dispatch.md +1 -1
  239. package/gsd-core/references/specless-probe-fallback.md +1 -1
  240. package/gsd-core/references/tdd.md +1 -3
  241. package/gsd-core/references/ui-brand.md +65 -21
  242. package/gsd-core/references/ui-consideration-probe.md +1 -1
  243. package/gsd-core/references/universal-anti-patterns.md +5 -5
  244. package/gsd-core/references/verifier-phase-gates.md +192 -0
  245. package/gsd-core/references/verify-command-path-resolvability.md +42 -0
  246. package/gsd-core/references/verify-mvp-mode.md +2 -2
  247. package/gsd-core/references/workstream-flag.md +33 -17
  248. package/gsd-core/templates/README.md +1 -1
  249. package/gsd-core/templates/SECURITY.md +3 -3
  250. package/gsd-core/templates/UI-SPEC.md +25 -3
  251. package/gsd-core/templates/VALIDATION.md +3 -3
  252. package/gsd-core/templates/discussion-log.md +1 -1
  253. package/gsd-core/templates/phase-prompt.md +5 -4
  254. package/gsd-core/templates/state.md +11 -4
  255. package/gsd-core/templates/verification-report.md +9 -1
  256. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
  257. package/gsd-core/workflows/add-backlog.md +1 -1
  258. package/gsd-core/workflows/add-phase.md +3 -3
  259. package/gsd-core/workflows/add-tests.md +3 -8
  260. package/gsd-core/workflows/add-todo.md +1 -1
  261. package/gsd-core/workflows/ai-integration-phase.md +13 -20
  262. package/gsd-core/workflows/audit-fix.md +12 -3
  263. package/gsd-core/workflows/audit-milestone.md +9 -9
  264. package/gsd-core/workflows/audit-uat.md +17 -2
  265. package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +2 -2
  266. package/gsd-core/workflows/autonomous.md +11 -27
  267. package/gsd-core/workflows/check-todos.md +1 -1
  268. package/gsd-core/workflows/cleanup.md +64 -5
  269. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +14 -4
  270. package/gsd-core/workflows/code-review-fix.md +38 -11
  271. package/gsd-core/workflows/code-review.md +159 -52
  272. package/gsd-core/workflows/complete-milestone.md +151 -23
  273. package/gsd-core/workflows/debug.md +12 -8
  274. package/gsd-core/workflows/diagnose-issues.md +47 -15
  275. package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
  276. package/gsd-core/workflows/discuss-phase/modes/chain.md +5 -8
  277. package/gsd-core/workflows/discuss-phase/modes/default.md +1 -1
  278. package/gsd-core/workflows/discuss-phase/modes/text.md +1 -1
  279. package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +1 -3
  280. package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
  281. package/gsd-core/workflows/discuss-phase.md +1 -1
  282. package/gsd-core/workflows/do.md +3 -6
  283. package/gsd-core/workflows/docs-update.md +5 -4
  284. package/gsd-core/workflows/edit-phase.md +27 -2
  285. package/gsd-core/workflows/eval-review.md +7 -14
  286. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
  287. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +142 -15
  288. package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +1 -1
  289. package/gsd-core/workflows/execute-phase/steps/partial-wave.md +1 -1
  290. package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +77 -0
  291. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +24 -4
  292. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +2 -2
  293. package/gsd-core/workflows/execute-phase/steps/protected-branch.md +21 -0
  294. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -2
  295. package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +39 -0
  296. package/gsd-core/workflows/execute-phase.md +72 -100
  297. package/gsd-core/workflows/execute-plan.md +52 -15
  298. package/gsd-core/workflows/explore.md +131 -4
  299. package/gsd-core/workflows/extract-learnings.md +1 -1
  300. package/gsd-core/workflows/fast.md +10 -2
  301. package/gsd-core/workflows/forensics.md +1 -1
  302. package/gsd-core/workflows/graduation.md +5 -5
  303. package/gsd-core/workflows/health.md +76 -10
  304. package/gsd-core/workflows/import.md +18 -15
  305. package/gsd-core/workflows/inbox.md +4 -5
  306. package/gsd-core/workflows/ingest-docs.md +49 -16
  307. package/gsd-core/workflows/insert-phase.md +5 -5
  308. package/gsd-core/workflows/list-seeds.md +5 -3
  309. package/gsd-core/workflows/list-workspaces.md +1 -1
  310. package/gsd-core/workflows/manager.md +12 -23
  311. package/gsd-core/workflows/map-codebase.md +1 -1
  312. package/gsd-core/workflows/milestone-summary.md +1 -1
  313. package/gsd-core/workflows/mvp-phase.md +8 -5
  314. package/gsd-core/workflows/new-milestone.md +22 -29
  315. package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
  316. package/gsd-core/workflows/new-project.md +26 -40
  317. package/gsd-core/workflows/new-workspace.md +1 -1
  318. package/gsd-core/workflows/next.md +14 -2
  319. package/gsd-core/workflows/pause-work.md +1 -1
  320. package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +1 -1
  321. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
  322. package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +2 -4
  323. package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +3 -3
  324. package/gsd-core/workflows/plan-phase.md +162 -59
  325. package/gsd-core/workflows/plan-review-convergence.md +96 -11
  326. package/gsd-core/workflows/plant-seed.md +2 -2
  327. package/gsd-core/workflows/pr-branch.md +187 -51
  328. package/gsd-core/workflows/profile-user.md +16 -14
  329. package/gsd-core/workflows/progress.md +61 -18
  330. package/gsd-core/workflows/quick/steps/discussion-phase.md +1 -3
  331. package/gsd-core/workflows/quick/steps/plan-checker-loop.md +5 -7
  332. package/gsd-core/workflows/quick/steps/quick-verification.md +28 -9
  333. package/gsd-core/workflows/quick/steps/research-phase.md +4 -6
  334. package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +3 -3
  335. package/gsd-core/workflows/quick.md +55 -44
  336. package/gsd-core/workflows/remove-phase.md +4 -4
  337. package/gsd-core/workflows/remove-workspace.md +2 -2
  338. package/gsd-core/workflows/resume-project.md +8 -12
  339. package/gsd-core/workflows/review.md +219 -20
  340. package/gsd-core/workflows/scan.md +1 -1
  341. package/gsd-core/workflows/secure-phase.md +3 -3
  342. package/gsd-core/workflows/session-report.md +2 -1
  343. package/gsd-core/workflows/settings-advanced.md +7 -9
  344. package/gsd-core/workflows/settings-integrations.md +64 -31
  345. package/gsd-core/workflows/settings.md +69 -7
  346. package/gsd-core/workflows/ship.md +116 -50
  347. package/gsd-core/workflows/sketch-wrap-up.md +11 -17
  348. package/gsd-core/workflows/sketch.md +12 -18
  349. package/gsd-core/workflows/smart-entry.md +3 -5
  350. package/gsd-core/workflows/spec-phase.md +53 -13
  351. package/gsd-core/workflows/spike-wrap-up.md +7 -11
  352. package/gsd-core/workflows/spike.md +20 -31
  353. package/gsd-core/workflows/stats.md +2 -2
  354. package/gsd-core/workflows/sync-skills.md +64 -9
  355. package/gsd-core/workflows/thread.md +11 -7
  356. package/gsd-core/workflows/transition.md +49 -14
  357. package/gsd-core/workflows/ui-phase.md +15 -21
  358. package/gsd-core/workflows/ui-review.md +8 -12
  359. package/gsd-core/workflows/ultraplan-phase.md +5 -13
  360. package/gsd-core/workflows/undo.md +8 -16
  361. package/gsd-core/workflows/update.md +7 -11
  362. package/gsd-core/workflows/validate-phase.md +3 -3
  363. package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +25 -1
  364. package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
  365. package/gsd-core/workflows/verify-work.md +66 -25
  366. package/hooks/dist/gsd-agent-isolation-guard.js +158 -30
  367. package/hooks/dist/gsd-check-update-worker.js +56 -13
  368. package/hooks/dist/gsd-check-update.js +19 -1
  369. package/hooks/dist/gsd-config-reload.js +18 -12
  370. package/hooks/dist/gsd-context-monitor.js +19 -10
  371. package/hooks/dist/gsd-cursor-post-tool.js +3 -1
  372. package/hooks/dist/gsd-cursor-pre-tool.js +2 -3
  373. package/hooks/dist/gsd-cursor-session-start.js +2 -1
  374. package/hooks/dist/gsd-cursor-stop.js +2 -1
  375. package/hooks/dist/gsd-cursor-subagent-start.js +83 -3
  376. package/hooks/dist/gsd-cursor-subagent-stop.js +6 -3
  377. package/hooks/dist/gsd-ensure-canonical-path.js +2 -1
  378. package/hooks/dist/gsd-graphify-update.sh +22 -18
  379. package/hooks/dist/gsd-node-runner.sh +76 -0
  380. package/hooks/dist/gsd-phase-boundary.sh +1 -0
  381. package/hooks/dist/gsd-prompt-guard.js +37 -27
  382. package/hooks/dist/gsd-read-guard.js +16 -7
  383. package/hooks/dist/gsd-read-injection-scanner.js +55 -32
  384. package/hooks/dist/gsd-session-state.sh +1 -0
  385. package/hooks/dist/gsd-statusline.js +231 -24
  386. package/hooks/dist/gsd-update-banner.js +22 -1
  387. package/hooks/dist/gsd-validate-commit.sh +80 -6
  388. package/hooks/dist/gsd-windsurf-pre-command.js +16 -11
  389. package/hooks/dist/gsd-windsurf-pre-write.js +22 -13
  390. package/hooks/dist/gsd-workflow-guard.js +162 -46
  391. package/hooks/dist/gsd-worktree-path-guard.js +36 -21
  392. package/hooks/dist/gsd-write-guard.js +35 -25
  393. package/hooks/dist/lib/cli-exit.js +560 -0
  394. package/hooks/dist/lib/exit-code-registry.js +98 -0
  395. package/hooks/dist/lib/git-cmd.js +92 -59
  396. package/hooks/dist/lib/git-probe.js +84 -0
  397. package/hooks/dist/lib/hook-exit.js +81 -0
  398. package/hooks/dist/lib/injection-patterns.js +45 -0
  399. package/hooks/dist/lib/isolation-deny-reason.js +39 -0
  400. package/hooks/dist/lib/isolation-sentinel.js +9 -0
  401. package/hooks/dist/managed-hooks-registry.cjs +3 -0
  402. package/hooks/gsd-agent-isolation-guard.js +158 -30
  403. package/hooks/gsd-check-update-worker.js +56 -13
  404. package/hooks/gsd-check-update.js +19 -1
  405. package/hooks/gsd-config-reload.js +18 -12
  406. package/hooks/gsd-context-monitor.js +19 -10
  407. package/hooks/gsd-cursor-post-tool.js +3 -1
  408. package/hooks/gsd-cursor-pre-tool.js +2 -3
  409. package/hooks/gsd-cursor-session-start.js +2 -1
  410. package/hooks/gsd-cursor-stop.js +2 -1
  411. package/hooks/gsd-cursor-subagent-start.js +83 -3
  412. package/hooks/gsd-cursor-subagent-stop.js +6 -3
  413. package/hooks/gsd-ensure-canonical-path.js +2 -1
  414. package/hooks/gsd-graphify-update.sh +22 -18
  415. package/hooks/gsd-node-runner.sh +76 -0
  416. package/hooks/gsd-phase-boundary.sh +1 -0
  417. package/hooks/gsd-prompt-guard.js +37 -27
  418. package/hooks/gsd-read-guard.js +16 -7
  419. package/hooks/gsd-read-injection-scanner.js +55 -32
  420. package/hooks/gsd-session-state.sh +1 -0
  421. package/hooks/gsd-statusline.js +231 -24
  422. package/hooks/gsd-update-banner.js +22 -1
  423. package/hooks/gsd-validate-commit.sh +80 -6
  424. package/hooks/gsd-windsurf-pre-command.js +16 -11
  425. package/hooks/gsd-windsurf-pre-write.js +22 -13
  426. package/hooks/gsd-workflow-guard.js +162 -46
  427. package/hooks/gsd-worktree-path-guard.js +36 -21
  428. package/hooks/gsd-write-guard.js +35 -25
  429. package/hooks/lib/cli-exit.js +560 -0
  430. package/hooks/lib/exit-code-registry.js +98 -0
  431. package/hooks/lib/git-cmd.js +92 -59
  432. package/hooks/lib/git-probe.js +84 -0
  433. package/hooks/lib/hook-exit.js +81 -0
  434. package/hooks/lib/injection-patterns.js +45 -0
  435. package/hooks/lib/isolation-deny-reason.js +39 -0
  436. package/hooks/lib/isolation-sentinel.js +9 -0
  437. package/hooks/managed-hooks-registry.cjs +3 -0
  438. package/package.json +28 -11
  439. package/pi/gsd.cjs +19 -5
  440. package/scripts/base64-scan.sh +74 -12
  441. package/scripts/baselines/planning-prompt-drift-baseline.json +4 -0
  442. package/scripts/baselines/planning-snapshot-bypass-baseline.json +12 -0
  443. package/scripts/baselines/unreachable-guard-drift-baseline.json +4 -0
  444. package/scripts/build-hooks.js +5 -0
  445. package/scripts/changeset/lint.cjs +60 -5
  446. package/scripts/check-alias-drift.cjs +7 -43
  447. package/scripts/check-contract-drift.cjs +297 -0
  448. package/scripts/check-glossary-refs.cjs +77 -15
  449. package/scripts/check-mutation-score-ratchet.cjs +156 -0
  450. package/scripts/ci-check-job-near-cap.cjs +49 -0
  451. package/scripts/ci-pr-mergeability.cjs +262 -0
  452. package/scripts/ci-test-scope.cjs +64 -14
  453. package/scripts/ci-timeout-report.cjs +230 -0
  454. package/scripts/command-contract-helpers.cjs +903 -1
  455. package/scripts/docs-guard-registry.cjs +396 -0
  456. package/scripts/gen-adr-index.cjs +728 -38
  457. package/scripts/gen-capability-registry.cjs +11 -21
  458. package/scripts/gen-context-index.cjs +2 -11
  459. package/scripts/gen-exit-code-docs.cjs +318 -0
  460. package/scripts/gen-exit-code-registry.cjs +891 -0
  461. package/scripts/gen-features.cjs +836 -0
  462. package/scripts/gen-health-docs.cjs +390 -0
  463. package/scripts/gen-hooks-cli-exit.cjs +239 -0
  464. package/scripts/gen-install-tree-fixtures.cjs +2 -2
  465. package/scripts/gen-inventory-manifest.cjs +50 -4
  466. package/scripts/gen-loop-host-contract.cjs +138 -25
  467. package/scripts/gen-registry.cjs +3 -14
  468. package/scripts/gen-scripts-cli-exit.cjs +185 -0
  469. package/scripts/gen-state-md-docs.cjs +727 -0
  470. package/scripts/{test-failure-reasons.cjs → gsd-test-gate-reasons.cjs} +6 -0
  471. package/scripts/lib/alias-drift-families.cjs +46 -0
  472. package/scripts/lib/ci-job-timing.cjs +72 -0
  473. package/scripts/lib/cli-exit.cjs +546 -44
  474. package/scripts/lib/drift-scan.cjs +308 -0
  475. package/scripts/lib/exit-code-registry.cjs +98 -0
  476. package/scripts/lib/ndjson-reporter.cjs +119 -0
  477. package/scripts/lint-allow-test-rule-refs.allowlist.json +1 -26
  478. package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +4 -0
  479. package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +3 -0
  480. package/scripts/lint-canary-version-leak.cjs +73 -0
  481. package/scripts/lint-command-contract.cjs +96 -13
  482. package/scripts/lint-completion-predicate-drift.cjs +933 -0
  483. package/scripts/lint-completion-ratio-drift.cjs +214 -0
  484. package/scripts/lint-default-flip-documentation.cjs +193 -0
  485. package/scripts/lint-docs-guard-registration.cjs +495 -0
  486. package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +193 -0
  487. package/scripts/lint-eslint-glob-coverage.allowlist.json +38 -0
  488. package/scripts/lint-eslint-glob-coverage.cjs +340 -0
  489. package/scripts/{lint-fix-has-regression-test.cjs → lint-fix-has-regression-tests.cjs} +12 -6
  490. package/scripts/lint-frontmatter-scalar-broad-grep.cjs +237 -0
  491. package/scripts/lint-health-diagnostic-rule-table.cjs +461 -0
  492. package/scripts/lint-hooks-runtime-build-seam.cjs +262 -0
  493. package/scripts/lint-milestone-window-drift.cjs +468 -0
  494. package/scripts/lint-mutation-test-derivation-drift.cjs +86 -0
  495. package/scripts/lint-phase-enumeration-drift.cjs +492 -0
  496. package/scripts/lint-plan-count-drift.cjs +318 -0
  497. package/scripts/lint-planning-artifact-writer-drift.cjs +398 -0
  498. package/scripts/lint-planning-prompt-drift.cjs +471 -0
  499. package/scripts/lint-planning-snapshot-bypass-drift.cjs +544 -0
  500. package/scripts/lint-regression-test-names.cjs +15 -13
  501. package/scripts/lint-removed-but-needed.cjs +488 -0
  502. package/scripts/lint-seam-enforcement.cjs +182 -0
  503. package/scripts/lint-slug-derivation-drift.cjs +921 -0
  504. package/scripts/lint-source-test-name-collision.cjs +241 -0
  505. package/scripts/lint-state-field-drift.cjs +805 -0
  506. package/scripts/lint-state-write-path-drift.cjs +950 -0
  507. package/scripts/lint-test-file-count.allowlist.json +137 -8
  508. package/scripts/lint-test-file-count.cjs +25 -3
  509. package/scripts/lint-unreachable-guard-drift.cjs +830 -0
  510. package/scripts/lint-vendored-deps.cjs +297 -0
  511. package/scripts/mutation-matrix.cjs +599 -50
  512. package/scripts/pr-changed-files.cjs +63 -0
  513. package/scripts/pr-template-policy.cjs +14 -4
  514. package/scripts/prompt-injection-scan.sh +100 -14
  515. package/scripts/require-issue-link-policy.cjs +192 -0
  516. package/scripts/secret-scan.sh +75 -13
  517. package/scripts/select-docs-guards.cjs +56 -0
  518. package/scripts/sync-runtime-launcher.cjs +24 -7
  519. package/skills/gsd-autonomous/SKILL.md +0 -1
  520. package/skills/gsd-code-review/SKILL.md +1 -1
  521. package/skills/gsd-discuss-phase/SKILL.md +1 -1
  522. package/skills/gsd-execute-phase/SKILL.md +1 -2
  523. package/skills/gsd-import/SKILL.md +1 -1
  524. package/skills/gsd-map-codebase/SKILL.md +1 -1
  525. package/skills/gsd-mempalace-capture/SKILL.md +1 -1
  526. package/skills/gsd-mempalace-recall/SKILL.md +1 -1
  527. package/skills/gsd-new-milestone/SKILL.md +1 -1
  528. package/skills/gsd-next/SKILL.md +0 -1
  529. package/skills/gsd-plan-phase/SKILL.md +0 -1
  530. package/skills/gsd-progress/SKILL.md +0 -1
  531. package/skills/gsd-quick/SKILL.md +9 -5
  532. package/skills/gsd-review-backlog/SKILL.md +2 -1
  533. package/skills/gsd-stats/SKILL.md +0 -1
  534. package/skills/gsd-verify-work/SKILL.md +1 -1
  535. package/vscode/package.json +1 -1
  536. package/bin/lib/ui-safety-gate.cjs +0 -107
  537. package/gsd-core/workflows/discovery-phase.md +0 -298
  538. package/gsd-core/workflows/plan-milestone-gaps.md +0 -281
  539. package/gsd-core/workflows/verify-phase.md +0 -574
  540. package/scripts/affected-tests-lib.cjs +0 -554
  541. package/scripts/lint-allow-test-rule-refs.cjs +0 -162
  542. package/scripts/lint-emitted-drift-ack.cjs +0 -344
  543. package/scripts/run-affected-tests.cjs +0 -7
  544. package/scripts/run-tests.cjs +0 -1051
@@ -16,30 +16,23 @@ exports.pickRollupWinners = pickRollupWinners;
16
16
  exports.isCompletedInventory = isCompletedInventory;
17
17
  exports.buildWorkstreamInventory = buildWorkstreamInventory;
18
18
  const node_path_1 = __importDefault(require("node:path"));
19
+ const phase_lifecycle_cjs_1 = require("./phase-lifecycle.cjs");
19
20
  // Internal helpers
20
21
  function toPosixPath(p) {
21
22
  return p.split('\\').join('/');
22
23
  }
23
- /**
24
- * #2562: verification verdicts that DISQUALIFY a phase from `complete`, even
25
- * when its SUMMARY count meets its PLAN count. Deliberately scoped to the two
26
- * EXPLICIT failing verdicts the verifier emits — `missing`/`unknown` (verifier
27
- * off / not yet run) and `stale` (mtime-derived, #2348) are intentionally left
28
- * untouched so verifier-disabled projects do not regress to never-complete.
29
- *
30
- * #2645: `'unrecorded'` is NOT a verdict the verifier itself ever emits — it
31
- * is an internal sentinel `workstream-inventory.cts`'s verification-deletion
32
- * ledger substitutes for `'missing'` once that workstream has ADOPTED the
33
- * ledger (a `.verification-ledger.json` file exists for it) but has no
34
- * remembered entry for this specific phase. Pre-adoption (no ledger file at
35
- * all) still resolves to plain `'missing'`, which stays OUTSIDE this set —
36
- * that is what keeps a project untouched by this fix until it actually uses
37
- * the verifier at least once. Post-adoption, an unrecorded phase fails
38
- * CLOSED (counted here) rather than open, so a corrupt or evidence-absent
39
- * ledger entry can no longer be read as "safe to complete" the way a bare
40
- * `'missing'` sentinel is.
41
- */
42
- const FAILING_VERIFICATION_STATUSES = new Set(['gaps_found', 'human_needed', 'unrecorded']);
24
+ // #2562/#2645's FAILING_VERIFICATION_STATUSES set (the verdicts that used to
25
+ // disqualify a phase from `complete` when combined with a local
26
+ // summary-count-meets-plan-count check) was removed by ADR-3180 §7.4
27
+ // (#3186): `complete` is now the single canonical owner's verdict
28
+ // (`PhaseFilesCount.complete`, computed via `isPhaseComplete` by the
29
+ // I/O-capable caller — see the loop below), which already requires
30
+ // `verification.status === 'passed'` unconditionally. Disk-strict (#2957)
31
+ // deliberately DROPS the prior "verifier-disabled projects fall back to
32
+ // summaries-met" tolerance that set existed to preserve — a phase with no
33
+ // `*-VERIFICATION.md` (`missing`) is no longer treated as complete just
34
+ // because its summaries meet its plan count. Disclosed in this phase's
35
+ // changeset.
43
36
  /**
44
37
  * #2562 / Bug #2445 / #2645 review: pick ONE winning item per key from a
45
38
  * PRE-SORTED list — newest `mtimeMs` wins; on an exact tie the incumbent
@@ -127,11 +120,20 @@ function buildWorkstreamInventory(inputs) {
127
120
  const counts = countsMap.get(dir);
128
121
  const planCount = counts?.planCount ?? 0;
129
122
  const summaryCount = counts?.summaryCount ?? 0;
130
- // #2562: SUMMARY≥PLAN parity is necessary but not sufficient — a phase whose
131
- // verification verdict is an explicit failing one is still in progress.
132
- const verificationStatus = counts?.verificationStatus ?? 'missing';
133
- const summariesMeetPlans = summaryCount >= planCount && planCount > 0;
134
- const status = summariesMeetPlans && !FAILING_VERIFICATION_STATUSES.has(verificationStatus)
123
+ // ADR-3180 §7.4 (issue #3186): routed through the single canonical owner
124
+ // (`isPhaseComplete`, src/verification.cts) — via `PhaseFilesCount.complete`,
125
+ // which the I/O-capable CALLER computes (this module is a PURE, I/O-free
126
+ // projection — see the module header: "No I/O. No async." — and cannot
127
+ // call the owner itself). The prior local derivation
128
+ // (`summaryCount >= planCount && planCount > 0` combined with a
129
+ // caller-supplied verification status) was this module's OWN completion
130
+ // verdict computed from raw counts — the exact "post-process a canonical
131
+ // result locally" bypass §7.4 rules out, and it reproduced the disk-strict
132
+ // headline case (#3168): a zero-plan phase with a passing verification
133
+ // read `pending` instead of `complete`. `complete` defaults to `false`
134
+ // when absent so a caller that has not been updated to pass it never
135
+ // silently reads as complete.
136
+ const status = (counts?.complete ?? false)
135
137
  ? 'complete'
136
138
  : planCount > 0
137
139
  ? 'in_progress'
@@ -243,12 +245,31 @@ function buildWorkstreamInventory(inputs) {
243
245
  roadmap_phase_count: effectivePhaseCount,
244
246
  total_plans: totalPlans,
245
247
  completed_plans: completedPlans,
246
- // The `Math.min` cap is unreachable under milestone scoping (the invariant
247
- // above throws first) and survives only for the legacy unscoped path, where
248
- // the denominator is a roadmap heading count that a caller cannot guarantee
249
- // bounds the numerator.
250
- progress_percent: effectivePhaseCount > 0
251
- ? Math.min(100, Math.round((completedPhases / effectivePhaseCount) * 100))
252
- : 0,
248
+ // `clampPercent`'s 100 ceiling is unreachable under milestone scoping (the
249
+ // invariant above throws first) and matters only for the legacy unscoped
250
+ // path, where the denominator is a roadmap heading count that a caller
251
+ // cannot guarantee bounds the numerator.
252
+ //
253
+ // #3217 (ADR-3180 §7.6 rule 4) — WRITTEN REASON this site is NOT migrated
254
+ // onto the `SCOPE` enum this phase: `buildWorkstreamInventory` is a pure
255
+ // projection (no I/O — see the module header) fed `BuildWorkstreamInventoryInputs`
256
+ // by `workstream-inventory.cts`. Its own `milestoneScoped` is a pre-ADR-3180
257
+ // bespoke boolean, not a `SCOPE` value, and its caller does not currently
258
+ // thread a real `listMilestonePhaseDirs` scope into these inputs. Doing
259
+ // this honestly requires ONE of: (a) widening `BuildWorkstreamInventoryInputs`
260
+ // with a `Scope` field and `WorkstreamInventory.progress_percent`'s type
261
+ // from `number` to `number | null` — the exact "re-architecting
262
+ // StateProjection/WorkstreamInventory return types" the design phase
263
+ // (`.gsd/phase/refactor-3217-completion-ratio-scoping/40-design.md`,
264
+ // "Known limits") states is OUT of this phase's scope; or (b) silently
265
+ // reusing `milestoneScoped` as a `Scope` stand-in, which would be exactly
266
+ // the kind of proxy-for-a-data-flow-property this same phase's guard
267
+ // section explicitly rejects (a `boolean` cannot distinguish TRUNCATED
268
+ // from UNSCOPED from UNREADABLE, so a caller could not tell which
269
+ // non-answer it got). Left un-migrated rather than done dishonestly;
270
+ // `workstream inventory`'s `progress_percent` can still render a number
271
+ // derived from an under-scoped set (A8 in the phase's test matrix is
272
+ // NOT covered here for that reason — see this phase's PR description).
273
+ progress_percent: (0, phase_lifecycle_cjs_1.clampPercent)(completedPhases, effectivePhaseCount),
253
274
  };
254
275
  }
@@ -27,10 +27,13 @@ const planScan = require("./plan-scan.cjs");
27
27
  const planningWorkspace = require("./planning-workspace.cjs");
28
28
  const { planningPaths, planningRoot, getActiveWorkstream } = planningWorkspace;
29
29
  const state_document_cjs_1 = require("./state-document.cjs");
30
+ // eslint-disable-next-line @typescript-eslint/no-require-imports -- frontmatter.cjs is an export= CommonJS module
31
+ const frontmatterMod = require("./frontmatter.cjs");
32
+ const { extractFrontmatter, stripFrontmatter } = frontmatterMod;
30
33
  const markdown_table_cjs_1 = require("./markdown-table.cjs");
31
34
  // eslint-disable-next-line @typescript-eslint/no-require-imports -- verification.cjs is an export= CommonJS module
32
35
  const verificationMod = require("./verification.cjs");
33
- const { readVerificationStatus } = verificationMod;
36
+ const { isPhaseComplete } = verificationMod;
34
37
  // eslint-disable-next-line @typescript-eslint/no-require-imports -- phase-id.cjs is an export= CommonJS module
35
38
  const phaseIdMod = require("./phase-id.cjs");
36
39
  const { phaseKeyFromDir, phaseKeyFromProse, parentPhaseKey } = phaseIdMod;
@@ -42,11 +45,28 @@ const workstream_inventory_builder_cjs_1 = require("./workstream-inventory-build
42
45
  function workstreamsRoot(cwd) {
43
46
  return node_path_1.default.join(planningRoot(cwd), 'workstreams');
44
47
  }
45
- function countRoadmapPhases(roadmapPath, fallbackCount) {
48
+ /**
49
+ * #3185 (ADR-3180 Decision 1): count the phases the CURRENT milestone
50
+ * declares, not every `Phase` heading in the file.
51
+ *
52
+ * This previously matched `^#{2,4}\s+Phase\s+…` across the whole ROADMAP with
53
+ * no milestone window and no sentinel filter, so it counted 999.* backlog and
54
+ * Phase 0 headings and spanned every milestone the document had ever had.
55
+ * `getMilestonePhaseFilter` already computes exactly this number for the
56
+ * scoped window (`phaseCount`, sentinel-filtered), and `inspectWorkstream` in
57
+ * this same file already passes a resolved `currentVersion` to it — this
58
+ * function was the sibling copy that never got the fix.
59
+ */
60
+ function countRoadmapPhases(roadmapPath, fallbackCount, cwd, ws, versionOverride) {
46
61
  try {
47
- const roadmapContent = node_fs_1.default.readFileSync(roadmapPath, 'utf-8');
48
- const matches = roadmapContent.match(/^#{2,4}\s+Phase\s+[\w][\w.-]*/gm);
49
- return matches ? matches.length : fallbackCount;
62
+ if (!node_fs_1.default.existsSync(roadmapPath))
63
+ return fallbackCount;
64
+ if (!cwd)
65
+ return fallbackCount;
66
+ const filter = getMilestonePhaseFilter(cwd, versionOverride ?? null, null, ws ?? null);
67
+ // A pass-all degrade (phaseCount 0) means the window declared no phases —
68
+ // fall back rather than reporting a confident zero.
69
+ return filter.phaseCount > 0 ? filter.phaseCount : fallbackCount;
50
70
  }
51
71
  catch {
52
72
  return fallbackCount;
@@ -312,13 +332,30 @@ function writeVerificationLedger(wsDir, ledger) {
312
332
  function readStateProjection(statePath) {
313
333
  try {
314
334
  const stateContent = node_fs_1.default.readFileSync(statePath, 'utf-8');
335
+ // #3187: route Status/Current Phase/Last Activity through the single
336
+ // #1760 fallback-chain owner (state-document.cjs's stateFieldValue)
337
+ // instead of a frontmatter-blind stateExtractField(stateContent, …) call,
338
+ // mirroring cmdStateValidate/cmdStateSnapshot — a STATE.md whose fields
339
+ // live only in frontmatter is no longer projected as absent here.
340
+ const fm = extractFrontmatter(stateContent, statePath);
341
+ const body = stripFrontmatter(stateContent);
315
342
  return {
316
- status: (0, state_document_cjs_1.stateExtractField)(stateContent, 'Status') || 'unknown',
317
- current_phase: (0, state_document_cjs_1.stateExtractField)(stateContent, 'Current Phase'),
318
- last_activity: (0, state_document_cjs_1.stateExtractField)(stateContent, 'Last Activity'),
343
+ status: (0, state_document_cjs_1.stateFieldValue)(fm, body, 'status', 'Status').value || 'unknown',
344
+ current_phase: (0, state_document_cjs_1.stateFieldValue)(fm, body, 'current_phase', 'Current Phase').value,
345
+ last_activity: (0, state_document_cjs_1.stateFieldValue)(fm, body, 'last_activity', 'Last Activity').value,
319
346
  };
320
347
  }
321
348
  catch {
349
+ // Read/parse failure (missing file, permission fault, etc.) degrades to
350
+ // an all-unknown projection — unchanged. Not widened to also carry a
351
+ // `scope` here: doing so would ripple `StateProjection`
352
+ // (workstream-inventory-builder.cjs) and every consumer of this
353
+ // read-only rollup — the design doc's blast-radius table rates
354
+ // `readStateProjection` "low"/Tier-2, and this call site's migration is
355
+ // scoped to routing the fallback chain, not to widening the return type.
356
+ // The existing all-unknown degrade already distinguishes "could not
357
+ // read" from any real field value; only its scope-vs-absence *reason*
358
+ // stays uncaptured, same as before this change.
322
359
  return {
323
360
  status: 'unknown',
324
361
  current_phase: null,
@@ -483,7 +520,16 @@ function inspectWorkstream(cwd, name, options = {}) {
483
520
  const rawPhaseEntries = [...phaseDirNames].sort().map(dir => {
484
521
  const phaseDir = node_path_1.default.join(p.phases, dir);
485
522
  const counts = countPhaseFiles(phaseDir);
486
- const verificationResult = readVerificationStatus(phaseDir);
523
+ // ADR-3180 §7.4 (#3186): routed through the single canonical owner
524
+ // (`isPhaseComplete`, src/verification.cts) instead of calling
525
+ // `readVerificationStatus` directly and re-deriving "is this phase
526
+ // complete" locally from its `.status`. `completionResult.value.complete`
527
+ // is threaded down to the builder below (as `PhaseFilesCount.complete`)
528
+ // so `buildWorkstreamInventory` — a pure, I/O-free projection that
529
+ // cannot call the owner itself — consumes the owner's verdict rather
530
+ // than re-deriving a second one from summary/plan counts.
531
+ const completionResult = isPhaseComplete(phaseDir);
532
+ const verificationResult = completionResult.value.verification;
487
533
  // #3057 B3: routing is UNCHANGED — `liveVerificationStatus` below is still
488
534
  // `.status`, exactly as before, so the ledger/rollup logic that consumes
489
535
  // it is unaffected. This only makes an indeterminate staleness check
@@ -502,6 +548,12 @@ function inspectWorkstream(cwd, name, options = {}) {
502
548
  summaryCount: counts.summaryCount,
503
549
  inMilestone: isDirInCurrentMilestone(dir),
504
550
  liveVerificationStatus: verificationResult.status,
551
+ // ADR-3180 §7.4 (#3186): the owner's verdict, read live off disk — never
552
+ // ledger-adjusted (see the phaseFilesCounts map below; the ledger only
553
+ // ever substitutes a 'missing' status with a remembered one, and under
554
+ // disk-strict neither 'missing' nor 'unrecorded' is ever complete, so
555
+ // there is nothing for the ledger to override here).
556
+ complete: completionResult.value.complete,
505
557
  };
506
558
  });
507
559
  // #2645: only the directory Bug #2445's de-dup rollup would actually pick
@@ -573,6 +625,7 @@ function inspectWorkstream(cwd, name, options = {}) {
573
625
  summaryCount: entry.summaryCount,
574
626
  inMilestone: entry.inMilestone,
575
627
  verificationStatus,
628
+ complete: entry.complete,
576
629
  };
577
630
  });
578
631
  // The denominator is the union of what the roadmap DECLARES for the current
@@ -592,7 +645,7 @@ function inspectWorkstream(cwd, name, options = {}) {
592
645
  // declares in its Progress table but never scaffolded — the heading-only
593
646
  // count drops them, even when other headings exist. Union the declared rows
594
647
  // with the phase directories so neither source can silently shrink it.
595
- let fallbackPhaseCount = countRoadmapPhases(p.roadmap, phaseDirNames.length);
648
+ let fallbackPhaseCount = countRoadmapPhases(p.roadmap, phaseDirNames.length, cwd, name, currentVersion);
596
649
  if (!scoped && progressRows.length > 0) {
597
650
  const union = new Set(progressRows.map(row => row.key));
598
651
  for (const entry of phaseFilesCounts)
@@ -6,6 +6,24 @@
6
6
  * byte-for-behaviour from the prior hand-written .cjs; only types are added.
7
7
  *
8
8
  * Used by active-workstream-store.cjs, planning-workspace.cjs, workstream.cjs.
9
+ *
10
+ * #3883 (ADR-3473 §8.3): toWorkstreamSlug delegates to core-utils.cjs's
11
+ * generateSlugInternal (the canonical slug formula), passing `maxLen: null`
12
+ * to preserve this site's pre-migration untruncated contract — the 60-char
13
+ * default collided distinct >60-char workstream names onto the same slug
14
+ * (verified: `"a".repeat(60)+"alpha"` and `"a".repeat(60)+"beta"` truncated
15
+ * identically). core-utils.cjs already
16
+ * requires (transitively, at module-init time) THIS module:
17
+ * core-utils.cjs -> planning-workspace.cjs -> active-workstream-store.cjs ->
18
+ * workstream-name-policy.cjs. A top-level require of core-utils.cjs here
19
+ * would therefore close that cycle and — per this codebase's compiled-.cjs
20
+ * convention of a single `module.exports = {...}` reassignment at the bottom
21
+ * of core-utils.cjs — capture a stale, still-empty exports object forever
22
+ * (verified live: "generateSlugInternal is not a function" whichever module
23
+ * loads first). The require is deferred (lazy, inside toWorkstreamSlug's
24
+ * body) instead, mirroring the same cycle-break already used by
25
+ * core-utils.cts's own getPhaseFileStats/plan-scan.cjs seam and by
26
+ * phase-id.cts's toDir/getPhaseDirFromPhaseId.
9
27
  */
10
28
  Object.defineProperty(exports, "__esModule", { value: true });
11
29
  exports.INVALID_ACTIVE_WORKSTREAM_NAME_MESSAGE = void 0;
@@ -68,10 +86,13 @@ function validateWorkstreamName(name) {
68
86
  * Lowercases, collapses non-alphanumeric runs to hyphens, strips leading/trailing hyphens.
69
87
  */
70
88
  function toWorkstreamSlug(name) {
71
- return String(name ?? '')
72
- .toLowerCase()
73
- .replace(/[^a-z0-9]+/g, '-')
74
- .replace(/^-+|-+$/g, '');
89
+ // #3883 (ADR-3473 §8.3): delegate to the canonical slug formula
90
+ // (generateSlugInternal, core-utils.cts) rather than re-implementing it —
91
+ // this call site previously diverged from it (no transliteration, no
92
+ // 60-char truncation). Lazy require to break the core-utils.cjs cycle
93
+ // (see the module dependency doc comment above).
94
+ // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
95
+ return require('./core-utils.cjs').generateSlugInternal(String(name ?? ''), null) ?? '';
75
96
  }
76
97
  /**
77
98
  * Returns true when `name` is a valid active workstream name:
@@ -134,8 +134,8 @@ function cmdWorkstreamCreate(cwd, name, options, raw) {
134
134
  }
135
135
  else {
136
136
  try {
137
- const milestone = getMilestoneInfo(cwd);
138
- existingWsName = generateSlugInternal(milestone.name) || 'default';
137
+ const milestone = getMilestoneInfo(cwd).value;
138
+ existingWsName = generateSlugInternal(milestone?.name ?? null) || 'default';
139
139
  }
140
140
  catch {
141
141
  existingWsName = 'default';
@@ -94,10 +94,13 @@ function parseJsonc(text) {
94
94
  }
95
95
  // ─── Message constants (verbatim — downstream docs/tests depend on these) ─────
96
96
  function buildMsgDiverged(headSha, forkRef, forkSha) {
97
- return `⚠ Worktree base mismatch: HEAD (${shortSha(headSha)}) differs from ${forkRef} (${shortSha(forkSha)}). Running this phase sequentially on the main working tree. To keep parallel worktrees, set worktree.baseRef:"head" in .claude/settings.local.json (or run: gsd-tools worktree set-baseref). See #683.`;
97
+ return `⚠ Worktree base mismatch: HEAD (${shortSha(headSha)}) differs from ${forkRef} (${shortSha(forkSha)}). Running this phase sequentially on the main working tree. Parallel worktrees return once HEAD is merged/pushed so ${forkRef} matches it. (worktree.baseRef:"head" applies only where GSD itself creates the worktree — the runtime harness does not read it; #48, #3659.)`;
98
98
  }
99
- const MSG_UNKNOWN = `⚠ Cannot determine the worktree fork base (origin/HEAD unresolved). Running this phase sequentially on the main working tree to avoid a base mismatch. To keep parallel worktrees, set worktree.baseRef:"head" in .claude/settings.local.json (or run: gsd-tools worktree set-baseref). See #683.`;
100
- const MSG_HEAD_UNRESOLVABLE = `⚠ Cannot determine the worktree base (git rev-parse HEAD did not return a definitive answer). Running this phase sequentially on the main working tree to avoid an unverified base mismatch. Note: worktree.baseRef:"head" would silence this check without verifying the base — it skips the comparison rather than resolving it. Retry; if it persists, check for a stalled filesystem mount or a stale git index lock (.git/index.lock). See #683, #3050.`;
99
+ const MSG_UNKNOWN = `⚠ Cannot determine the worktree fork base (origin/HEAD unresolved). Running this phase sequentially on the main working tree to avoid a base mismatch. Parallel worktrees return once origin/HEAD resolves and matches HEAD. See #683, #3659.`;
100
+ function buildMsgBaserefHeadIgnored(headSha, forkRef, forkSha) {
101
+ return `⚠ Worktree base mismatch: worktree.baseRef:"head" is set, but the runtime harness does not honor it for isolated dispatch — the fork base stays ${forkRef} (${shortSha(forkSha)}) while HEAD is ${shortSha(headSha)} (#48; upstream claude-code#44965). Running this phase sequentially on the main working tree. Parallel worktrees return once HEAD is merged/pushed so ${forkRef} matches it, or on runtimes where GSD itself manages worktree creation. See #3659.`;
102
+ }
103
+ const MSG_HEAD_UNRESOLVABLE = `⚠ Cannot determine the worktree base (git rev-parse HEAD did not return a definitive answer). Running this phase sequentially on the main working tree to avoid an unverified base mismatch. Note: worktree.baseRef:"head" silences this check only where GSD itself creates the worktree (orchestrator-managed runtimes) — in harness mode it never applied (#48, #3659). Retry; if it persists, check for a stalled filesystem mount or a stale git index lock (.git/index.lock). See #683, #3050.`;
101
104
  /**
102
105
  * Returns true when an execGit result indicates the subprocess was killed by
103
106
  * a timeout. A timeout means the command genuinely could not complete — it
@@ -228,7 +231,20 @@ function resolveEffectiveBaseRef(claudeDir, deps, userClaudeDir) {
228
231
  * deps.userClaudeDir overrides the user/global config directory resolution
229
232
  * (default: getGlobalConfigDir('claude'), which honours CLAUDE_CONFIG_DIR).
230
233
  */
231
- function cmdWorktreeBaseCheck(cwd, _args, deps) {
234
+ function cmdWorktreeBaseCheck(cwd, args, deps) {
235
+ // --mode threads the dispatch isolation mode through to the evaluation
236
+ // (#3659): 'harness-worktree' (default) or 'orchestrator-worktree'. Invalid
237
+ // or missing values after --mode fail closed — a silently defaulted typo
238
+ // would re-open the hole the flag exists to close.
239
+ let isolationMode = 'harness-worktree';
240
+ const modeIdx = args.indexOf('--mode');
241
+ if (modeIdx !== -1) {
242
+ const value = args[modeIdx + 1];
243
+ if (value !== 'harness-worktree' && value !== 'orchestrator-worktree') {
244
+ throw new Error(`worktree base-check: --mode must be harness-worktree or orchestrator-worktree, got ${JSON.stringify(value ?? null)}`);
245
+ }
246
+ isolationMode = value;
247
+ }
232
248
  const claudeDir = node_path_1.default.join(cwd, '.claude');
233
249
  const userClaudeDir = Object.prototype.hasOwnProperty.call(deps ?? {}, 'userClaudeDir')
234
250
  ? deps.userClaudeDir
@@ -238,8 +254,22 @@ function cmdWorktreeBaseCheck(cwd, _args, deps) {
238
254
  cwd,
239
255
  effectiveBaseRef,
240
256
  execGit: deps?.execGit,
257
+ isolationMode,
258
+ });
259
+ // Default emit goes through fs.writeSync(1, …), NOT process.stdout.write:
260
+ // the CLI's --pick capture intercepts writeSync, and command substitution
261
+ // is a pipe — via process.stdout.write a `$(gsd-tools … --pick x)` capture
262
+ // received the full JSON instead of the picked field, so the workflow
263
+ // auto-degrade guards never matched (#3659 review). Short-count loop per
264
+ // io.cjs writeAllSync's rationale (a non-blocking pipe can accept partial
265
+ // writes).
266
+ const write = deps?.write ?? ((s) => {
267
+ const buf = Buffer.from(s, 'utf8');
268
+ let offset = 0;
269
+ while (offset < buf.length) {
270
+ offset += node_fs_1.default.writeSync(1, buf, offset, buf.length - offset);
271
+ }
241
272
  });
242
- const write = deps?.write ?? ((s) => process.stdout.write(s));
243
273
  write(JSON.stringify(result, null, 2) + '\n');
244
274
  return result;
245
275
  }
@@ -295,7 +325,20 @@ function cmdWorktreeSetBaseRef(cwd, _args, deps) {
295
325
  baseRef: 'head',
296
326
  file,
297
327
  };
298
- const write = deps?.write ?? ((s) => process.stdout.write(s));
328
+ // Default emit goes through fs.writeSync(1, …), NOT process.stdout.write:
329
+ // the CLI's --pick capture intercepts writeSync, and command substitution
330
+ // is a pipe — via process.stdout.write a `$(gsd-tools … --pick x)` capture
331
+ // received the full JSON instead of the picked field, so the workflow
332
+ // auto-degrade guards never matched (#3659 review). Short-count loop per
333
+ // io.cjs writeAllSync's rationale (a non-blocking pipe can accept partial
334
+ // writes).
335
+ const write = deps?.write ?? ((s) => {
336
+ const buf = Buffer.from(s, 'utf8');
337
+ let offset = 0;
338
+ while (offset < buf.length) {
339
+ offset += node_fs_1.default.writeSync(1, buf, offset, buf.length - offset);
340
+ }
341
+ });
299
342
  write(JSON.stringify(output, null, 2) + '\n');
300
343
  return output;
301
344
  }
@@ -311,12 +354,19 @@ function evaluateWorktreeBaseDegrade(deps) {
311
354
  const execGit = deps?.execGit ?? shell_command_projection_cjs_1.execGit;
312
355
  const cwd = deps?.cwd;
313
356
  const cwdOpts = cwd ? { cwd } : {};
314
- // a. If baseRef is explicitly 'head' the harness forks from HEAD — no mismatch possible.
315
- // Claude Code's worktree.baseRef accepts only "fresh" (= origin/HEAD, the default) or "head".
316
- // Therefore special-casing "head" here and otherwise comparing HEAD against origin/HEAD is
317
- // complete: any non-"head" value (including "fresh" and absent/null) has fresh/origin-HEAD
318
- // semantics and must be evaluated against origin/HEAD. (Reference: Claude Code worktrees docs, #683.)
319
- if (deps?.effectiveBaseRef === 'head') {
357
+ // a. baseRef 'head' suppresses ONLY where GSD controls the fork start-point
358
+ // (#3659). The former unconditional suppress trusted the harness to honor the
359
+ // setting; #48 verified 5/5 that the Agent-isolation dispatch path never
360
+ // routes through project settings (upstream claude-code#44965), so in
361
+ // harness mode the fork base is always origin/HEAD and 'head' must fall
362
+ // through to the same comparison the fresh path runs. In
363
+ // orchestrator-worktree mode GSD itself runs `git worktree add <path>
364
+ // <start-point>` with the orchestrator HEAD — 'head' is honored by
365
+ // construction there and the suppress is correct. Any non-"head" value
366
+ // (including "fresh" and absent/null) has fresh/origin-HEAD semantics and is
367
+ // evaluated against origin/HEAD as before. (Reference: #683, #48, #3659.)
368
+ const headIgnoredByHarness = deps?.effectiveBaseRef === 'head';
369
+ if (headIgnoredByHarness && (deps?.isolationMode ?? 'harness-worktree') === 'orchestrator-worktree') {
320
370
  return { shouldDegrade: false, reason: 'baseref-head', message: null, headSha: null, forkRef: null, forkSha: null, headAbsenceVerified: null };
321
371
  }
322
372
  // b. Resolve HEAD sha.
@@ -389,6 +439,10 @@ function evaluateWorktreeBaseDegrade(deps) {
389
439
  if (forkSha === headSha) {
390
440
  return { shouldDegrade: false, reason: 'head-matches-fork', message: null, headSha, forkRef, forkSha, headAbsenceVerified: null };
391
441
  }
442
+ if (headIgnoredByHarness) {
443
+ const message = buildMsgBaserefHeadIgnored(headSha, forkRef, forkSha);
444
+ return { shouldDegrade: true, reason: 'baseref-head-ignored-by-harness', message, headSha, forkRef, forkSha, headAbsenceVerified: null };
445
+ }
392
446
  const message = buildMsgDiverged(headSha, forkRef, forkSha);
393
447
  return { shouldDegrade: true, reason: 'head-diverged-from-fork', message, headSha, forkRef, forkSha, headAbsenceVerified: null };
394
448
  }