@opengsd/gsd-core 1.13.0 → 1.15.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 (441) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.ja-JP.md +3 -3
  4. package/README.ko-KR.md +3 -3
  5. package/README.pt-BR.md +3 -3
  6. package/README.zh-CN.md +3 -3
  7. package/agents/gsd-advisor-researcher.compact.md +85 -0
  8. package/agents/gsd-ai-researcher.compact.md +96 -0
  9. package/agents/gsd-assumptions-analyzer.compact.md +81 -0
  10. package/agents/gsd-code-fixer.compact.md +459 -0
  11. package/agents/gsd-code-fixer.md +9 -8
  12. package/agents/gsd-code-reviewer.compact.md +269 -0
  13. package/agents/gsd-code-reviewer.md +15 -3
  14. package/agents/gsd-codebase-mapper.compact.md +760 -0
  15. package/agents/gsd-debug-session-manager.compact.md +360 -0
  16. package/agents/gsd-debug-session-manager.md +17 -2
  17. package/agents/gsd-debugger.md +2 -2
  18. package/agents/gsd-doc-classifier.compact.md +192 -0
  19. package/agents/gsd-doc-synthesizer.compact.md +200 -0
  20. package/agents/gsd-doc-verifier.compact.md +143 -0
  21. package/agents/gsd-doc-writer.compact.md +440 -0
  22. package/agents/gsd-dom-verifier.compact.md +138 -0
  23. package/agents/gsd-domain-researcher.compact.md +141 -0
  24. package/agents/gsd-eval-auditor.compact.md +160 -0
  25. package/agents/gsd-eval-auditor.md +1 -1
  26. package/agents/gsd-eval-planner.compact.md +137 -0
  27. package/agents/gsd-executor.md +13 -8
  28. package/agents/gsd-framework-selector.compact.md +82 -0
  29. package/agents/gsd-integration-checker.compact.md +245 -0
  30. package/agents/gsd-intel-updater.compact.md +226 -0
  31. package/agents/gsd-intel-updater.md +1 -1
  32. package/agents/gsd-mempalace-curator.compact.md +45 -0
  33. package/agents/gsd-nyquist-auditor.compact.md +179 -0
  34. package/agents/gsd-pattern-mapper.compact.md +275 -0
  35. package/agents/gsd-phase-researcher.md +19 -11
  36. package/agents/gsd-plan-checker.md +8 -7
  37. package/agents/gsd-planner.md +12 -8
  38. package/agents/gsd-project-researcher.compact.md +587 -0
  39. package/agents/gsd-project-researcher.md +1 -1
  40. package/agents/gsd-research-synthesizer.compact.md +212 -0
  41. package/agents/gsd-research-synthesizer.md +1 -1
  42. package/agents/gsd-roadmapper.compact.md +454 -0
  43. package/agents/gsd-roadmapper.md +13 -0
  44. package/agents/gsd-security-auditor.compact.md +162 -0
  45. package/agents/gsd-ui-auditor.compact.md +404 -0
  46. package/agents/gsd-ui-auditor.md +155 -17
  47. package/agents/gsd-ui-checker.compact.md +277 -0
  48. package/agents/gsd-ui-researcher.compact.md +282 -0
  49. package/agents/gsd-ui-researcher.md +1 -1
  50. package/agents/gsd-user-profiler.compact.md +108 -0
  51. package/agents/gsd-verifier.md +10 -9
  52. package/bin/install.js +848 -163
  53. package/commands/gsd/autonomous.md +2 -2
  54. package/commands/gsd/capture.md +1 -1
  55. package/commands/gsd/cleanup.md +1 -0
  56. package/commands/gsd/code-review.md +2 -1
  57. package/commands/gsd/complete-milestone.md +1 -0
  58. package/commands/gsd/config.md +1 -0
  59. package/commands/gsd/debug.md +1 -0
  60. package/commands/gsd/graphify.md +1 -0
  61. package/commands/gsd/health.md +1 -0
  62. package/commands/gsd/mempalace-capture.md +8 -3
  63. package/commands/gsd/mempalace-recall.md +1 -0
  64. package/commands/gsd/new-milestone.md +1 -0
  65. package/commands/gsd/new-project.md +1 -0
  66. package/commands/gsd/next.md +1 -0
  67. package/commands/gsd/pause-work.md +1 -0
  68. package/commands/gsd/phase.md +1 -0
  69. package/commands/gsd/plan-review-convergence.md +6 -6
  70. package/commands/gsd/pr-branch.md +1 -0
  71. package/commands/gsd/progress.md +1 -1
  72. package/commands/gsd/quick-batch.md +1 -1
  73. package/commands/gsd/resume-work.md +1 -0
  74. package/commands/gsd/review-backlog.md +1 -0
  75. package/commands/gsd/review.md +2 -3
  76. package/commands/gsd/settings.md +2 -1
  77. package/commands/gsd/stats.md +1 -0
  78. package/commands/gsd/thread.md +1 -0
  79. package/commands/gsd/workspace.md +1 -0
  80. package/commands/gsd/workstreams.md +1 -0
  81. package/gsd-core/bin/check-latest-version.cjs +8 -3
  82. package/gsd-core/bin/gsd-tools.cjs +672 -146
  83. package/gsd-core/bin/lib/adr-parser.cjs +4 -2
  84. package/gsd-core/bin/lib/artifacts.cjs +2 -1
  85. package/gsd-core/bin/lib/audit.cjs +119 -34
  86. package/gsd-core/bin/lib/broken-windows.cjs +168 -49
  87. package/gsd-core/bin/lib/capability-lifecycle.cjs +10 -6
  88. package/gsd-core/bin/lib/capability-loader.cjs +135 -1
  89. package/gsd-core/bin/lib/capability-registry.cjs +96 -189
  90. package/gsd-core/bin/lib/capability-source.cjs +19 -2
  91. package/gsd-core/bin/lib/capability-validator.cjs +14 -2
  92. package/gsd-core/bin/lib/check-command-router.cjs +213 -49
  93. package/gsd-core/bin/lib/code-review-depth.cjs +2 -2
  94. package/gsd-core/bin/lib/codex-agent-toml.cjs +21 -25
  95. package/gsd-core/bin/lib/commands.cjs +823 -112
  96. package/gsd-core/bin/lib/config-loader.cjs +66 -4
  97. package/gsd-core/bin/lib/config.cjs +186 -45
  98. package/gsd-core/bin/lib/coverage.cjs +1 -1
  99. package/gsd-core/bin/lib/decisions.cjs +164 -45
  100. package/gsd-core/bin/lib/external-descriptor-trust.cjs +29 -14
  101. package/gsd-core/bin/lib/frontmatter.cjs +13 -0
  102. package/gsd-core/bin/lib/graphify.cjs +10 -2
  103. package/gsd-core/bin/lib/gsd2-import.cjs +1 -2
  104. package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +12 -1
  105. package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +1 -1
  106. package/gsd-core/bin/lib/host-runtime-detection.cjs +9 -0
  107. package/gsd-core/bin/lib/init.cjs +614 -86
  108. package/gsd-core/bin/lib/install-engine.cjs +29 -3
  109. package/gsd-core/bin/lib/install-profiles.cjs +14 -0
  110. package/gsd-core/bin/lib/installer-migrations.cjs +41 -5
  111. package/gsd-core/bin/lib/loop-resolver.cjs +50 -31
  112. package/gsd-core/bin/lib/mcp-catalog.cjs +2 -2
  113. package/gsd-core/bin/lib/milestone.cjs +37 -13
  114. package/gsd-core/bin/lib/model-resolver.cjs +253 -53
  115. package/gsd-core/bin/lib/phase-command-router.cjs +16 -2
  116. package/gsd-core/bin/lib/phase-id-card.cjs +32 -0
  117. package/gsd-core/bin/lib/phase-id-display.cjs +78 -0
  118. package/gsd-core/bin/lib/phase-id.cjs +268 -27
  119. package/gsd-core/bin/lib/phase-lifecycle.cjs +61 -0
  120. package/gsd-core/bin/lib/phase-locator.cjs +29 -10
  121. package/gsd-core/bin/lib/phase.cjs +393 -88
  122. package/gsd-core/bin/lib/plan-document.cjs +49 -1
  123. package/gsd-core/bin/lib/planning-document.cjs +459 -0
  124. package/gsd-core/bin/lib/planning-inspect.cjs +52 -19
  125. package/gsd-core/bin/lib/planning-snapshot.cjs +61 -12
  126. package/gsd-core/bin/lib/planning-workspace.cjs +57 -3
  127. package/gsd-core/bin/lib/pr-branch-patterns.cjs +57 -0
  128. package/gsd-core/bin/lib/pristine-baseline.cjs +182 -0
  129. package/gsd-core/bin/lib/probe-core.cjs +7 -1
  130. package/gsd-core/bin/lib/prohibition-enforcement.cjs +91 -4
  131. package/gsd-core/bin/lib/project-root.cjs +41 -2
  132. package/gsd-core/bin/lib/quick-batch.cjs +1 -1
  133. package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +61 -2
  134. package/gsd-core/bin/lib/research-store.cjs +11 -12
  135. package/gsd-core/bin/lib/review-lane-descriptor.cjs +10 -30
  136. package/gsd-core/bin/lib/review-lane-invocation.cjs +23 -0
  137. package/gsd-core/bin/lib/review-reviewer-selection.cjs +2 -2
  138. package/gsd-core/bin/lib/reviewer-step-dispatch.cjs +337 -0
  139. package/gsd-core/bin/lib/roadmap-command-router.cjs +12 -4
  140. package/gsd-core/bin/lib/roadmap-parser.cjs +219 -18
  141. package/gsd-core/bin/lib/roadmap-upgrade.cjs +1539 -13
  142. package/gsd-core/bin/lib/roadmap.cjs +356 -42
  143. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +310 -41
  144. package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +15 -4
  145. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +13 -5
  146. package/gsd-core/bin/lib/runtime-homes.cjs +4 -0
  147. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +408 -37
  148. package/gsd-core/bin/lib/runtime-name-policy.cjs +111 -1
  149. package/gsd-core/bin/lib/security.cjs +126 -7
  150. package/gsd-core/bin/lib/shell-command-projection.cjs +10 -6
  151. package/gsd-core/bin/lib/state-document.cjs +130 -28
  152. package/gsd-core/bin/lib/state-md-schema.cjs +21 -14
  153. package/gsd-core/bin/lib/state-transition.cjs +181 -30
  154. package/gsd-core/bin/lib/state.cjs +265 -27
  155. package/gsd-core/bin/lib/surface.cjs +77 -3
  156. package/gsd-core/bin/lib/task-command-router.cjs +12 -6
  157. package/gsd-core/bin/lib/tdd-red-evidence.cjs +78 -5
  158. package/gsd-core/bin/lib/uat-predicate.cjs +47 -4
  159. package/gsd-core/bin/lib/uat.cjs +9 -1
  160. package/gsd-core/bin/lib/ui-consideration-probe.cjs +15 -2
  161. package/gsd-core/bin/lib/ui-frontend-evidence.cjs +100 -9
  162. package/gsd-core/bin/lib/undo-commit-selection.cjs +131 -0
  163. package/gsd-core/bin/lib/update-context.cjs +30 -24
  164. package/gsd-core/bin/lib/vendor/js-yaml.cjs +11 -3
  165. package/gsd-core/bin/lib/verification.cjs +315 -30
  166. package/gsd-core/bin/lib/verify-command-grounding.cjs +47 -3
  167. package/gsd-core/bin/lib/verify.cjs +320 -48
  168. package/gsd-core/bin/lib/workstream-inventory.cjs +1 -0
  169. package/gsd-core/bin/lib/worktree-base-ref.cjs +482 -73
  170. package/gsd-core/bin/lib/worktree-safety.cjs +797 -58
  171. package/gsd-core/bin/shared/config-defaults.manifest.json +4 -0
  172. package/gsd-core/bin/shared/config-schema.manifest.json +6 -0
  173. package/gsd-core/bin/verify-reapply-patches.cjs +439 -80
  174. package/gsd-core/references/checkpoints.md +5 -3
  175. package/gsd-core/references/compact-content-gate.md +66 -0
  176. package/gsd-core/references/edge-probe-fixtures/01-round-half-even/expected-coverage.json +28 -3
  177. package/gsd-core/references/edge-probe-fixtures/02-merge-intervals/expected-coverage.json +37 -4
  178. package/gsd-core/references/edge-probe-fixtures/03-truncate-graphemes/expected-coverage.json +28 -3
  179. package/gsd-core/references/edge-probe-fixtures/04-money-rounding/expected-coverage.json +28 -3
  180. package/gsd-core/references/edge-probe-fixtures/05-list-dedupe/expected-coverage.json +37 -4
  181. package/gsd-core/references/edge-probe-fixtures/06-resolved-mixed/expected-coverage.json +37 -4
  182. package/gsd-core/references/edge-probe.md +195 -21
  183. package/gsd-core/references/execute-phase-between-wave-reset.md +7 -6
  184. package/gsd-core/references/execute-phase-wave-guard.md +22 -11
  185. package/gsd-core/references/gsd-run-resolver.md +1 -1
  186. package/gsd-core/references/loop-hook-dispatch.md +18 -0
  187. package/gsd-core/references/model-profiles.md +13 -4
  188. package/gsd-core/references/phase-argument-parsing.md +9 -7
  189. package/gsd-core/references/phase-id-convention.md +28 -0
  190. package/gsd-core/references/planner-gap-closure.md +2 -0
  191. package/gsd-core/references/planner-load-graph-context.md +24 -13
  192. package/gsd-core/references/planner-verify-command-grounding.md +14 -0
  193. package/gsd-core/references/planning-config.md +14 -2
  194. package/gsd-core/references/tdd.md +30 -4
  195. package/gsd-core/references/thinking-models-planning.md +18 -2
  196. package/gsd-core/references/ui-consideration-probe.md +10 -5
  197. package/gsd-core/references/verification-patterns.md +17 -4
  198. package/gsd-core/references/verify-command-path-resolvability.md +10 -2
  199. package/gsd-core/references/worktree-path-safety.md +433 -2
  200. package/gsd-core/templates/README.md +7 -1
  201. package/gsd-core/templates/state.md +6 -3
  202. package/gsd-core/templates/summary.compact.md +212 -0
  203. package/gsd-core/templates/user-setup.compact.md +199 -0
  204. package/gsd-core/templates/user-setup.md +0 -9
  205. package/gsd-core/templates/verification-report.md +1 -1
  206. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
  207. package/gsd-core/workflows/add-backlog.md +1 -1
  208. package/gsd-core/workflows/add-phase.md +1 -1
  209. package/gsd-core/workflows/add-tests.md +2 -2
  210. package/gsd-core/workflows/add-todo.md +6 -5
  211. package/gsd-core/workflows/ai-integration-phase.md +11 -3
  212. package/gsd-core/workflows/audit-fix.md +1 -1
  213. package/gsd-core/workflows/audit-milestone.md +1 -1
  214. package/gsd-core/workflows/audit-uat.md +1 -1
  215. package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +9 -18
  216. package/gsd-core/workflows/autonomous.md +29 -16
  217. package/gsd-core/workflows/check-todos.md +6 -4
  218. package/gsd-core/workflows/cleanup.md +5 -3
  219. package/gsd-core/workflows/code-review/steps/dispatch-fix.md +4 -3
  220. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +8 -1
  221. package/gsd-core/workflows/code-review-fix.md +108 -22
  222. package/gsd-core/workflows/code-review.md +216 -73
  223. package/gsd-core/workflows/complete-milestone/detail/elaboration.md +274 -0
  224. package/gsd-core/workflows/complete-milestone.md +41 -264
  225. package/gsd-core/workflows/debug.md +3 -3
  226. package/gsd-core/workflows/diagnose-issues.md +1 -1
  227. package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
  228. package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
  229. package/gsd-core/workflows/discuss-phase-assumptions.md +1 -1
  230. package/gsd-core/workflows/discuss-phase.md +1 -1
  231. package/gsd-core/workflows/do.md +2 -2
  232. package/gsd-core/workflows/docs-update/detail/elaboration.md +179 -0
  233. package/gsd-core/workflows/docs-update.md +17 -158
  234. package/gsd-core/workflows/edit-phase.md +1 -1
  235. package/gsd-core/workflows/eval-review.md +10 -3
  236. package/gsd-core/workflows/execute-phase/detail/elaboration.md +124 -0
  237. package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +1017 -0
  238. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +19 -4
  239. package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +56 -0
  240. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +43 -4
  241. package/gsd-core/workflows/execute-phase/steps/executor-progress-policy.md +43 -0
  242. package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +1 -1
  243. package/gsd-core/workflows/execute-phase/steps/partial-wave.md +1 -1
  244. package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
  245. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -1
  246. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +46 -9
  247. package/gsd-core/workflows/execute-phase/steps/protected-branch.md +1 -1
  248. package/gsd-core/workflows/execute-phase/steps/ready-wave-gate.md +37 -0
  249. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +1 -1
  250. package/gsd-core/workflows/execute-phase/steps/sequential-root-pin.md +35 -0
  251. package/gsd-core/workflows/execute-phase/steps/stale-reverification.md +24 -0
  252. package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +1 -1
  253. package/gsd-core/workflows/execute-phase/steps/threat-id-gate.md +28 -0
  254. package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +1 -1
  255. package/gsd-core/workflows/execute-phase/steps/worktree-base-check.md +25 -0
  256. package/gsd-core/workflows/execute-phase.md +83 -172
  257. package/gsd-core/workflows/execute-plan.md +24 -10
  258. package/gsd-core/workflows/explore.md +3 -3
  259. package/gsd-core/workflows/extract-learnings.md +2 -1
  260. package/gsd-core/workflows/fast.md +1 -1
  261. package/gsd-core/workflows/forensics.md +1 -1
  262. package/gsd-core/workflows/graduation.md +1 -1
  263. package/gsd-core/workflows/health.md +2 -2
  264. package/gsd-core/workflows/help/modes/full.compact.md +398 -0
  265. package/gsd-core/workflows/help/modes/full.md +5 -5
  266. package/gsd-core/workflows/help/modes/topic.md +15 -5
  267. package/gsd-core/workflows/help.md +1 -1
  268. package/gsd-core/workflows/import.md +2 -2
  269. package/gsd-core/workflows/inbox.md +2 -2
  270. package/gsd-core/workflows/ingest-docs.md +3 -3
  271. package/gsd-core/workflows/insert-phase.md +1 -1
  272. package/gsd-core/workflows/list-seeds.md +1 -1
  273. package/gsd-core/workflows/list-workspaces.md +1 -1
  274. package/gsd-core/workflows/manager.md +2 -2
  275. package/gsd-core/workflows/map-codebase.md +52 -5
  276. package/gsd-core/workflows/milestone-summary.md +1 -1
  277. package/gsd-core/workflows/mvp-phase.md +1 -1
  278. package/gsd-core/workflows/new-milestone.md +56 -14
  279. package/gsd-core/workflows/new-project/detail/elaboration.md +216 -0
  280. package/gsd-core/workflows/new-project/steps/auto-mode-config.md +3 -3
  281. package/gsd-core/workflows/new-project/steps/codebase-map-offer.md +1 -1
  282. package/gsd-core/workflows/new-project.md +39 -209
  283. package/gsd-core/workflows/new-workspace.md +2 -2
  284. package/gsd-core/workflows/next.md +1 -1
  285. package/gsd-core/workflows/note.md +1 -1
  286. package/gsd-core/workflows/onboard.md +1 -1
  287. package/gsd-core/workflows/pause-work.md +1 -1
  288. package/gsd-core/workflows/plan-phase/detail/elaboration.md +209 -0
  289. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +17 -5
  290. package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
  291. package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +23 -5
  292. package/gsd-core/workflows/plan-phase.md +45 -187
  293. package/gsd-core/workflows/plan-review-convergence.md +21 -5
  294. package/gsd-core/workflows/plant-seed.md +62 -20
  295. package/gsd-core/workflows/pr-branch.md +132 -20
  296. package/gsd-core/workflows/profile-user.md +2 -2
  297. package/gsd-core/workflows/progress.md +1 -1
  298. package/gsd-core/workflows/quick/steps/plan-checker-loop.md +25 -0
  299. package/gsd-core/workflows/quick/steps/quick-verification.md +1 -1
  300. package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +1 -1
  301. package/gsd-core/workflows/quick-batch/steps/batch-init.md +1 -1
  302. package/gsd-core/workflows/quick-batch/steps/completion.md +1 -1
  303. package/gsd-core/workflows/quick-batch/steps/merge-wave.md +1 -1
  304. package/gsd-core/workflows/quick-batch/steps/planner-wave.md +1 -1
  305. package/gsd-core/workflows/quick-batch/steps/research-phase.md +1 -1
  306. package/gsd-core/workflows/quick-batch/steps/resume-mode.md +1 -1
  307. package/gsd-core/workflows/quick-batch/steps/verification-wave.md +1 -1
  308. package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +1 -1
  309. package/gsd-core/workflows/quick-batch.md +1 -1
  310. package/gsd-core/workflows/quick.md +29 -10
  311. package/gsd-core/workflows/reapply-patches.md +86 -6
  312. package/gsd-core/workflows/remove-phase.md +1 -1
  313. package/gsd-core/workflows/remove-workspace.md +2 -2
  314. package/gsd-core/workflows/resume-project.md +1 -1
  315. package/gsd-core/workflows/review.md +31 -16
  316. package/gsd-core/workflows/scan.md +1 -1
  317. package/gsd-core/workflows/secure-phase.md +3 -2
  318. package/gsd-core/workflows/settings-advanced.md +30 -10
  319. package/gsd-core/workflows/settings-integrations.md +2 -3
  320. package/gsd-core/workflows/settings.md +22 -9
  321. package/gsd-core/workflows/ship.md +3 -2
  322. package/gsd-core/workflows/sketch-wrap-up.md +1 -1
  323. package/gsd-core/workflows/sketch.md +1 -1
  324. package/gsd-core/workflows/smart-entry.md +2 -2
  325. package/gsd-core/workflows/spec-phase.md +15 -5
  326. package/gsd-core/workflows/spike-wrap-up.md +1 -1
  327. package/gsd-core/workflows/spike.md +1 -1
  328. package/gsd-core/workflows/stats.md +1 -1
  329. package/gsd-core/workflows/sync-skills.md +5 -5
  330. package/gsd-core/workflows/thread.md +1 -1
  331. package/gsd-core/workflows/transition.md +1 -1
  332. package/gsd-core/workflows/ui-phase.md +44 -8
  333. package/gsd-core/workflows/ui-review.md +18 -4
  334. package/gsd-core/workflows/ultraplan-phase.md +1 -1
  335. package/gsd-core/workflows/undo.md +339 -20
  336. package/gsd-core/workflows/update.md +14 -12
  337. package/gsd-core/workflows/validate-phase.md +3 -2
  338. package/gsd-core/workflows/verify-work/detail/elaboration.md +230 -0
  339. package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +1 -1
  340. package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
  341. package/gsd-core/workflows/verify-work.md +101 -196
  342. package/hooks/dist/gsd-agent-isolation-guard.js +66 -16
  343. package/hooks/dist/gsd-context-monitor.js +88 -15
  344. package/hooks/dist/gsd-cursor-subagent-start.js +34 -14
  345. package/hooks/dist/gsd-secret-read-guard.js +71 -19
  346. package/hooks/dist/gsd-statusline.js +81 -20
  347. package/hooks/dist/gsd-validate-commit.sh +97 -8
  348. package/hooks/dist/gsd-worktree-path-guard.js +25 -14
  349. package/hooks/dist/gsd-write-guard.js +46 -1
  350. package/hooks/dist/lib/dispatch-identity.js +187 -0
  351. package/hooks/dist/lib/filename-classification.js +64 -0
  352. package/hooks/dist/lib/isolation-deny-reason.js +53 -1
  353. package/hooks/dist/lib/isolation-sentinel.js +58 -19
  354. package/hooks/gsd-agent-isolation-guard.js +66 -16
  355. package/hooks/gsd-context-monitor.js +88 -15
  356. package/hooks/gsd-cursor-subagent-start.js +34 -14
  357. package/hooks/gsd-secret-read-guard.js +71 -19
  358. package/hooks/gsd-statusline.js +81 -20
  359. package/hooks/gsd-validate-commit.sh +97 -8
  360. package/hooks/gsd-worktree-path-guard.js +25 -14
  361. package/hooks/gsd-write-guard.js +46 -1
  362. package/hooks/lib/dispatch-identity.js +187 -0
  363. package/hooks/lib/filename-classification.js +64 -0
  364. package/hooks/lib/isolation-deny-reason.js +53 -1
  365. package/hooks/lib/isolation-sentinel.js +58 -19
  366. package/package.json +11 -6
  367. package/scripts/benchmark-compact-content-variants.cjs +298 -0
  368. package/scripts/benchmark-compact-content.cjs +368 -0
  369. package/scripts/build-hooks.js +15 -6
  370. package/scripts/check-contract-drift.cjs +131 -12
  371. package/scripts/check-env.cjs +36 -8
  372. package/scripts/check-glossary-refs.cjs +25 -21
  373. package/scripts/ci-next-health.cjs +271 -0
  374. package/scripts/ci-prepare-test-scope.cjs +7 -7
  375. package/scripts/ci-test-scope.cjs +126 -20
  376. package/scripts/ci-timeout-report.cjs +1 -1
  377. package/scripts/command-contract-helpers.cjs +3 -0
  378. package/scripts/diff-touches-shipped-paths.cjs +1 -1
  379. package/scripts/docs-guard-registry.cjs +35 -2
  380. package/scripts/gen-adr-index.cjs +8 -2
  381. package/scripts/gen-inventory-manifest.cjs +12 -0
  382. package/scripts/gen-loop-host-contract.cjs +69 -0
  383. package/scripts/gen-platform-conformance-tier.cjs +557 -0
  384. package/scripts/lib/drift-scan.cjs +1 -1
  385. package/scripts/lib/macos-conformance-tier.generated.cjs +224 -0
  386. package/scripts/lib/ndjson-reporter.cjs +3 -2
  387. package/scripts/lib/npm-version-check-diagnosis.cjs +59 -0
  388. package/scripts/lib/platform-conformance-tier.generated.cjs +287 -0
  389. package/scripts/lib/suite-detection.cjs +32 -0
  390. package/scripts/lint-allowed-tools-parity.cjs +221 -0
  391. package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +47 -3
  392. package/scripts/lint-phase-arg-assignment.cjs +257 -0
  393. package/scripts/lint-phase-id-drift.cjs +623 -13
  394. package/scripts/lint-pr-branch-pattern-drift.cjs +148 -0
  395. package/scripts/lint-response-language-coverage.cjs +9 -3
  396. package/scripts/lint-retired-runtime-name.cjs +619 -0
  397. package/scripts/lint-source-test-name-collision.cjs +1 -1
  398. package/scripts/lint-state-write-path-drift.cjs +93 -0
  399. package/scripts/lint-test-file-count.allowlist.json +29 -9
  400. package/scripts/lint-vendored-deps.cjs +128 -17
  401. package/scripts/lint-workflow-shellcheck-baseline.json +100 -0
  402. package/scripts/prompt-injection-scan.sh +18 -0
  403. package/scripts/release-tarball-smoke.cjs +194 -1
  404. package/scripts/workflow-size.cjs +139 -0
  405. package/skills/gsd-autonomous/SKILL.md +2 -2
  406. package/skills/gsd-capture/SKILL.md +1 -1
  407. package/skills/gsd-cleanup/SKILL.md +1 -0
  408. package/skills/gsd-code-review/SKILL.md +2 -1
  409. package/skills/gsd-complete-milestone/SKILL.md +1 -0
  410. package/skills/gsd-config/SKILL.md +1 -0
  411. package/skills/gsd-debug/SKILL.md +1 -0
  412. package/skills/gsd-graphify/SKILL.md +1 -0
  413. package/skills/gsd-health/SKILL.md +1 -0
  414. package/skills/gsd-mempalace-capture/SKILL.md +8 -3
  415. package/skills/gsd-mempalace-recall/SKILL.md +1 -0
  416. package/skills/gsd-new-milestone/SKILL.md +1 -0
  417. package/skills/gsd-new-project/SKILL.md +1 -0
  418. package/skills/gsd-next/SKILL.md +1 -0
  419. package/skills/gsd-pause-work/SKILL.md +1 -0
  420. package/skills/gsd-phase/SKILL.md +1 -0
  421. package/skills/gsd-plan-review-convergence/SKILL.md +5 -5
  422. package/skills/gsd-pr-branch/SKILL.md +1 -0
  423. package/skills/gsd-progress/SKILL.md +1 -1
  424. package/skills/gsd-quick-batch/SKILL.md +1 -1
  425. package/skills/gsd-resume-work/SKILL.md +1 -0
  426. package/skills/gsd-review/SKILL.md +2 -3
  427. package/skills/gsd-review-backlog/SKILL.md +1 -0
  428. package/skills/gsd-settings/SKILL.md +2 -1
  429. package/skills/gsd-stats/SKILL.md +1 -0
  430. package/skills/gsd-thread/SKILL.md +1 -0
  431. package/skills/gsd-workspace/SKILL.md +1 -0
  432. package/skills/gsd-workstreams/SKILL.md +1 -0
  433. package/vscode/package.json +1 -1
  434. package/gsd-core/templates/claude-md.md +0 -145
  435. package/gsd-core/templates/codebase/concerns.md +0 -310
  436. package/gsd-core/templates/codebase/conventions.md +0 -307
  437. package/gsd-core/templates/codebase/integrations.md +0 -280
  438. package/gsd-core/templates/codebase/structure.md +0 -285
  439. package/gsd-core/templates/codebase/testing.md +0 -480
  440. package/gsd-core/templates/debug-subagent-prompt.md +0 -91
  441. package/gsd-core/templates/discovery.md +0 -146
@@ -17,12 +17,28 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
17
17
  return (mod && mod.__esModule) ? mod : { "default": mod };
18
18
  };
19
19
  Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.setExplicitProjectRoot = setExplicitProjectRoot;
21
+ exports.resolveProjectRoot = resolveProjectRoot;
20
22
  exports.findProjectRoot = findProjectRoot;
21
23
  exports.consentProjectRoot = consentProjectRoot;
22
24
  const node_fs_1 = __importDefault(require("node:fs"));
23
25
  const node_path_1 = __importDefault(require("node:path"));
24
26
  const node_os_1 = __importDefault(require("node:os"));
25
27
  const FIND_PROJECT_ROOT_MAX_DEPTH = 10;
28
+ // #4894: an operator-supplied `--project-dir` IS the project root — the
29
+ // dispatcher validates it and skips the ancestor walk-up for `cwd`, but code
30
+ // that derives a root from a PHASE DIRECTORY (verification) never sees `cwd`.
31
+ // The dispatcher records the validated root here, once per process, and those
32
+ // callers resolve through `resolveProjectRoot`. `null` (the default, and what
33
+ // the dispatcher sets when the flag is absent) leaves `findProjectRoot`'s
34
+ // walk-up as the only source of truth, so no-flag behavior is unchanged.
35
+ let explicitProjectRoot = null;
36
+ function setExplicitProjectRoot(root) {
37
+ explicitProjectRoot = root;
38
+ }
39
+ function resolveProjectRoot(startDir) {
40
+ return explicitProjectRoot ?? findProjectRoot(startDir);
41
+ }
26
42
  function findProjectRoot(startDir) {
27
43
  let resolvedStart;
28
44
  try {
@@ -43,12 +59,35 @@ function findProjectRoot(startDir) {
43
59
  catch {
44
60
  // fall through
45
61
  }
62
+ // A `.planning` that is itself a symlink is a deliberate hop into a separate
63
+ // tree (the documented "keep planning content out of the tracked repo"
64
+ // convention: `.planning -> ~/.gsd-external-planning/<project>/`, its own git
65
+ // repo). `fs.existsSync(d + '/.git')` DEREFERENCES `d`, so at `d ===
66
+ // <the .planning symlink path>` it finds the EXTERNAL store's `.git`, and
67
+ // both isInsideGitRepo/nearestGitRoot misread it as a crossed nested-child-
68
+ // repo boundary (#2843's guard). `fs.lstatSync` does not dereference its
69
+ // final path component, so it answers "is `d` ITSELF a symlink" (#4815).
70
+ //
71
+ // Deliberately scoped to a symlink named `.planning`, NOT any symlinked
72
+ // directory: a nested child repo reached through some other symlinked
73
+ // ancestor is still a real repo boundary, and skipping it would reopen
74
+ // #2843 through a different trigger.
75
+ function isSymlinkedPlanningDir(d) {
76
+ if (node_path_1.default.basename(d) !== '.planning')
77
+ return false;
78
+ try {
79
+ return node_fs_1.default.lstatSync(d).isSymbolicLink();
80
+ }
81
+ catch {
82
+ return false;
83
+ }
84
+ }
46
85
  // Walk upward, mirroring isInsideGitRepo from the CJS reference.
47
86
  function isInsideGitRepo(candidateParent) {
48
87
  let d = resolvedStart;
49
88
  while (d !== fsRoot) {
50
89
  try {
51
- if (node_fs_1.default.existsSync(d + node_path_1.default.sep + '.git'))
90
+ if (!isSymlinkedPlanningDir(d) && node_fs_1.default.existsSync(d + node_path_1.default.sep + '.git'))
52
91
  return true;
53
92
  }
54
93
  catch {
@@ -77,7 +116,7 @@ function findProjectRoot(startDir) {
77
116
  if (d === upTo)
78
117
  break;
79
118
  try {
80
- if (node_fs_1.default.existsSync(d + node_path_1.default.sep + '.git'))
119
+ if (!isSymlinkedPlanningDir(d) && node_fs_1.default.existsSync(d + node_path_1.default.sep + '.git'))
81
120
  return d;
82
121
  }
83
122
  catch {
@@ -210,7 +210,7 @@ function parseTaskListFromFile(cwd, filePath) {
210
210
  const root = planningRoot(cwd);
211
211
  let safePath;
212
212
  try {
213
- safePath = (0, security_cjs_1.requireSafePath)(filePath, root, 'quick-batch --file', { allowAbsolute: true });
213
+ safePath = (0, security_cjs_1.requireSafePath)(filePath, root, 'quick-batch --file', security_cjs_1.PathAcceptance.AbsoluteInsideRoot);
214
214
  }
215
215
  catch (err) {
216
216
  return { ok: false, reason: err instanceof Error ? err.message : String(err) };
@@ -35,6 +35,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
35
35
  const node_path_1 = __importDefault(require("node:path"));
36
36
  const node_fs_1 = __importDefault(require("node:fs"));
37
37
  const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
38
+ const security_cjs_1 = require("./security.cjs");
38
39
  // eslint-disable-next-line @typescript-eslint/no-require-imports
39
40
  const io = require("./io.cjs");
40
41
  // eslint-disable-next-line @typescript-eslint/no-require-imports
@@ -174,8 +175,11 @@ function resolvePhaseDirForArg(cwd, phaseArg) {
174
175
  */
175
176
  function resolveConfinedPath(cwd, relFile) {
176
177
  const root = node_path_1.default.resolve(cwd);
177
- const resolved = node_path_1.default.resolve(root, relFile);
178
- if (resolved !== root && !resolved.startsWith(root + node_path_1.default.sep))
178
+ // ADR-4650 decision 6: lexical family — resolving the symlink here would
179
+ // undo the refuse-don't-resolve posture documented above; `lstatSync` below
180
+ // is the gate that actually refuses a symlink.
181
+ const resolved = (0, security_cjs_1.tryWithinRootLexical)(relFile, root);
182
+ if (resolved === null)
179
183
  return null;
180
184
  try {
181
185
  if (!node_fs_1.default.lstatSync(resolved).isFile())
@@ -321,6 +325,32 @@ function loadWindowsOrDegrade(cwd, windowsOverride) {
321
325
  }
322
326
  return { ok: true, windows, ledger };
323
327
  }
328
+ /**
329
+ * #3780: lazy (module-load cost, see file header) require of the ledger's
330
+ * serialization seam — the same `.planning/.WINDOWS.lock` the windows cmd*
331
+ * writers hold, so this router's own read-compute-write cycles on
332
+ * WINDOWS.md cannot lose updates against them. Required from the REAL
333
+ * compiled module, never through the injectable `windowsOverride` seam:
334
+ * the lock is infrastructure, not a parser stand-in.
335
+ */
336
+ function withLedgerLock(cwd, fn) {
337
+ let lockMod;
338
+ try {
339
+ /* eslint-disable @typescript-eslint/no-require-imports */
340
+ lockMod = require('./broken-windows.cjs');
341
+ /* eslint-enable @typescript-eslint/no-require-imports */
342
+ }
343
+ catch {
344
+ // Ledger module unavailable (the #1953 degrade world — see the row-86
345
+ // notesLedgerUnavailableWithoutBrokenWindows contract): no lock-holding
346
+ // writer can exist either, because every WINDOWS.md writer requires this
347
+ // same module. Run the body unlocked and let loadWindowsOrDegrade
348
+ // produce the canonical degrade note — wrapping that world in lock
349
+ // ceremony would only rewrite the note the degrade contract pins.
350
+ return fn();
351
+ }
352
+ return lockMod.withLedgerLock(cwd, fn);
353
+ }
324
354
  /**
325
355
  * Strict-mode window append (step 9 of `evaluate`). Degrades to
326
356
  * `{ recorded: false, note }` per `loadWindowsOrDegrade` — never an error,
@@ -329,6 +359,23 @@ function loadWindowsOrDegrade(cwd, windowsOverride) {
329
359
  * file/line) and does not append a second one.
330
360
  */
331
361
  function recordStrictWindow(cwd, padded, target, windowsOverride) {
362
+ // #3780: hold the same cross-process ledger lock the windows cmd* writers
363
+ // hold — this site's read-compute-write on WINDOWS.md is otherwise the
364
+ // same lost-update race: a concurrent `gsd_run windows append` (or another
365
+ // evaluator) could silently overwrite this entry, or be overwritten by
366
+ // it. The lock comes from the real ledger module, not the injectable
367
+ // `windowsOverride` seam — it is infrastructure, not a parser stand-in.
368
+ // The wrapper keeps the #1953-defect-2 degrade contract: the lock's typed
369
+ // refusal degrades to `{ recorded: false, note }` like every other
370
+ // failure, it never throws out of this function.
371
+ try {
372
+ return withLedgerLock(cwd, () => recordStrictWindowLocked(cwd, padded, target, windowsOverride));
373
+ }
374
+ catch (e) {
375
+ return { recorded: false, note: `failed to record broken-windows entry: ${e instanceof Error ? e.message : String(e)}` };
376
+ }
377
+ }
378
+ function recordStrictWindowLocked(cwd, padded, target, windowsOverride) {
332
379
  const loaded = loadWindowsOrDegrade(cwd, windowsOverride);
333
380
  if (!loaded.ok)
334
381
  return { recorded: false, note: loaded.note };
@@ -357,6 +404,18 @@ function recordStrictWindow(cwd, padded, target, windowsOverride) {
357
404
  * `accept`/`decline` never tell a user "it failed" without saying why.
358
405
  */
359
406
  function resolveLedgerWindow(cwd, padded, file, line, kind, reasonText, windowsOverride) {
407
+ // #3780: same serialization as recordStrictWindow — a concurrent ledger
408
+ // writer holding a stale snapshot would silently revert this resolve (or
409
+ // lose its own write to this one). Same degrade contract: the lock's
410
+ // typed refusal degrades, never throws.
411
+ try {
412
+ return withLedgerLock(cwd, () => resolveLedgerWindowLocked(cwd, padded, file, line, kind, reasonText, windowsOverride));
413
+ }
414
+ catch (e) {
415
+ return { resolved: false, note: `failed to resolve broken-windows entry: ${e instanceof Error ? e.message : String(e)}` };
416
+ }
417
+ }
418
+ function resolveLedgerWindowLocked(cwd, padded, file, line, kind, reasonText, windowsOverride) {
360
419
  const loaded = loadWindowsOrDegrade(cwd, windowsOverride);
361
420
  if (!loaded.ok)
362
421
  return { resolved: false, note: loaded.note };
@@ -15,6 +15,10 @@ const node_os_1 = __importDefault(require("node:os"));
15
15
  const node_path_1 = __importDefault(require("node:path"));
16
16
  const node_crypto_1 = __importDefault(require("node:crypto"));
17
17
  const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
18
+ // ADR-4650 decision 6: lexical family — the key is validated before
19
+ // `fs.mkdirSync` creates the store dir, so the candidate legitimately does
20
+ // not exist yet at check time.
21
+ const security_cjs_1 = require("./security.cjs");
18
22
  // ---------------------------------------------------------------------------
19
23
  // Constants
20
24
  // ---------------------------------------------------------------------------
@@ -94,15 +98,12 @@ function putResearch(cwd, key, payload, { clock = Date, homeDir = node_os_1.defa
94
98
  const fetched_at = new Date(clock.now()).toISOString();
95
99
  const entry = { content, source, provider, confidence, fetched_at, ttl, kind };
96
100
  const dir = resolveStorePath(cwd, source, { homeDir });
97
- // Belt-and-suspenders: ensure the resolved file path stays inside the store dir.
98
- const resolvedDir = node_path_1.default.resolve(dir);
99
- const filePath = node_path_1.default.join(dir, `${key}.json`);
100
- const resolvedFile = node_path_1.default.resolve(filePath);
101
- if (!resolvedFile.startsWith(resolvedDir + node_path_1.default.sep)) {
101
+ const containedFile = (0, security_cjs_1.tryWithinRootLexical)(`${key}.json`, dir);
102
+ if (containedFile === null || containedFile === node_path_1.default.resolve(dir)) {
102
103
  throw new Error('invalid research key');
103
104
  }
104
105
  node_fs_1.default.mkdirSync(dir, { recursive: true });
105
- (0, shell_command_projection_cjs_1.platformWriteSync)(filePath, JSON.stringify(entry));
106
+ (0, shell_command_projection_cjs_1.platformWriteSync)(containedFile, JSON.stringify(entry));
106
107
  return entry;
107
108
  }
108
109
  // ---------------------------------------------------------------------------
@@ -120,16 +121,14 @@ function getResearch(cwd, key, { clock = Date, homeDir = node_os_1.default.homed
120
121
  const tierDirs = [userDir, projectDir];
121
122
  const candidates = [];
122
123
  for (const dir of tierDirs) {
123
- const resolvedDir = node_path_1.default.resolve(dir);
124
- const filePath = node_path_1.default.join(dir, `${key}.json`);
125
- // Belt-and-suspenders: ensure path stays inside tier dir
126
- if (!node_path_1.default.resolve(filePath).startsWith(resolvedDir + node_path_1.default.sep))
124
+ const containedFile = (0, security_cjs_1.tryWithinRootLexical)(`${key}.json`, dir);
125
+ if (containedFile === null || containedFile === node_path_1.default.resolve(dir))
127
126
  continue;
128
- if (!node_fs_1.default.existsSync(filePath))
127
+ if (!node_fs_1.default.existsSync(containedFile))
129
128
  continue;
130
129
  let entry;
131
130
  try {
132
- entry = JSON.parse(node_fs_1.default.readFileSync(filePath, 'utf8'));
131
+ entry = JSON.parse(node_fs_1.default.readFileSync(containedFile, 'utf8'));
133
132
  }
134
133
  catch {
135
134
  // Corrupt file in this tier — skip it
@@ -64,7 +64,7 @@ exports.checkReviewerDocsParity = checkReviewerDocsParity;
64
64
  * `args` is an argv TEMPLATE, not a prefix. The injected pieces — model, effort, output file,
65
65
  * argv-borne prompt — do not all go in the same place, and no positional rule expresses that:
66
66
  * `codex` injects the model in the MIDDLE (after the `exec --ephemeral` subcommand) and the output
67
- * file later still, while `gemini` injects the model first and five lanes end with a bare `-` that
67
+ * file later still, while `kimi-code` injects the model first and five lanes end with a bare `-` that
68
68
  * must stay last. Splicing by position silently produced
69
69
  * `codex --model M -o F exec --ephemeral …`, which is not a valid codex invocation.
70
70
  *
@@ -94,36 +94,16 @@ const SPAWN_STDIN_STDOUT = {
94
94
  outputChannel: 'stdout',
95
95
  };
96
96
  /**
97
- * The twelve declared lanes, in `write_reviews` order.
97
+ * The eleven declared lanes, in `write_reviews` order.
98
+ *
99
+ * The `gemini` lane was retired by #4709: Google sunset Gemini CLI on 2026-06-18 (the same
100
+ * sunset that removed the gemini RUNTIME in #1928/1.8.0), so the lane spawned a binary that no
101
+ * longer serves the free/Pro/Ultra tiers that are GSD's audience.
98
102
  *
99
103
  * `kimi-code` joined in Phase 5b (#2799, closes #2718) — ADR-2782's phase table lands it here
100
104
  * rather than in 5a precisely so it arrives together with the iteration that can invoke it.
101
105
  */
102
106
  exports.REVIEWER_LANES = Object.freeze([
103
- {
104
- slug: 'gemini',
105
- flags: ['--gemini'],
106
- transport: 'spawn',
107
- probe: { kind: 'command-exists', binary: 'gemini' },
108
- invoke: {
109
- binary: 'gemini',
110
- args: ['{{model}}', '-p', '-'],
111
- ...SPAWN_STDIN_STDOUT,
112
- modelArg: '-m',
113
- effortChannel: 'none',
114
- },
115
- timeoutFloorMs: 900_000,
116
- timeoutConfigKey: 'review.timeouts.gemini',
117
- emptyOutput: 'stub-with-stderr',
118
- reviewsSection: 'Gemini',
119
- evidenceClass: 'source-grounded',
120
- requiresBinaries: [],
121
- promptBudgetKey: 'review.max_prompt_tokens_per_reviewer.gemini',
122
- modelConfigKey: 'review.models.gemini',
123
- effortConfigKey: null,
124
- defaultEffort: null,
125
- handler: null,
126
- },
127
107
  {
128
108
  // 1_200_000 rather than the 900_000 floor: headless Claude measured ~525 s
129
109
  // on a large plan set (review.md:304).
@@ -139,8 +119,8 @@ exports.REVIEWER_LANES = Object.freeze([
139
119
  effortChannel: 'argv',
140
120
  // #2483: without these the claude leg is the only reviewer that additionally inherits the
141
121
  // invoking user's global CLAUDE.md, the project CLAUDE.md, and Claude Code auto-memory —
142
- // a context asymmetry against the independent-review premise (gemini sees only the
143
- // assembled prompt; codex runs --ephemeral). Both flags, not just the first: CLAUDE.md
122
+ // a context asymmetry against the independent-review premise (codex sees only the
123
+ // assembled prompt and runs --ephemeral). Both flags, not just the first: CLAUDE.md
144
124
  // loading and auto-memory are independently-toggled mechanisms, and an environment
145
125
  // exporting CLAUDE_CODE_DISABLE_AUTO_MEMORY=0 forces auto-memory back ON — the explicit
146
126
  // pair is robust against that. Applies when /gsd:review runs from a non-Claude-Code host;
@@ -796,7 +776,7 @@ const NON_LANE_SIGNATURE_FLAGS = new Set(['--all']);
796
776
  /**
797
777
  * Is `flag` documented in `text` under one of the two structural shapes docs actually use?
798
778
  *
799
- * Backticked is the `COMMANDS.md` table-cell shape; bracketed (`[--gemini]`) is the
779
+ * Backticked is the `COMMANDS.md` table-cell shape; bracketed (`[--codex]`) is the
800
780
  * `FEATURES.md` signature shape. Requiring one of those two delimiters — rather than a bare
801
781
  * substring — is what keeps prose and fenced examples from satisfying the gate, and it bounds the
802
782
  * token for free: a backticked `--claude` demands its closing backtick, so a backticked
@@ -889,7 +869,7 @@ const BRACKETED_FLAG_RE = /\[(--[a-z0-9][a-z0-9-]*)\]/g;
889
869
  * cell 3. A file-scoped check is therefore satisfied by the forwarding row alone, so deleting a
890
870
  * lane's actual table row — the exact #2781 regression — passes. Keying on cell 1 separates the
891
871
  * two: `| `--agy` / `--antigravity` | … |` is one lane row declaring two flags, while
892
- * `| Reviewer flags | No | … `--gemini`, `--claude` … |` is not a lane row at all.
872
+ * `| Reviewer flags | No | … `--codex`, `--claude` … |` is not a lane row at all.
893
873
  */
894
874
  function flagsInFirstTableCell(lines, declared) {
895
875
  const found = new Set();
@@ -31,6 +31,8 @@ exports.resolveTimeoutMs = resolveTimeoutMs;
31
31
  exports.nativeTimeoutToken = nativeTimeoutToken;
32
32
  exports.isEmptyReview = isEmptyReview;
33
33
  exports.fileRefPrompt = fileRefPrompt;
34
+ exports.artifactPaths = artifactPaths;
35
+ exports.resolveLaneBudget = resolveLaneBudget;
34
36
  exports.resolveLanePlan = resolveLanePlan;
35
37
  const review_lane_descriptor_cjs_1 = require("./review-lane-descriptor.cjs");
36
38
  /* ------------------------------------------------------------------ *
@@ -236,6 +238,27 @@ function artifactPaths(runDir, slug) {
236
238
  errPath: `${base}/gsd-review-${slug}.err`,
237
239
  };
238
240
  }
241
+ /**
242
+ * Per-lane prompt budget (#2797 semantics, preserved exactly).
243
+ *
244
+ * `-1` is the UNSET sentinel and falls back to the central `review.max_prompt_tokens`, because
245
+ * `0` is a legitimate value meaning "do not trim this lane". Treating 0 as unset would silently
246
+ * switch a user who deliberately disabled trimming onto the global budget.
247
+ *
248
+ * Single source of truth: `gsd-core/bin/gsd-tools.cjs`'s `review-lane plan`/`invoke` and
249
+ * `src/reviewer-step-dispatch.cts`'s `dispatchReviewerLanes` both resolve a lane's budget through
250
+ * this function rather than each carrying their own copy (#4209 R3 — two verbatim copies drift).
251
+ */
252
+ function resolveLaneBudget(lane, configGet) {
253
+ if (!lane.promptBudgetKey)
254
+ return null;
255
+ const per = configGet(lane.promptBudgetKey);
256
+ const isNum = (v) => typeof v === 'number' && Number.isFinite(v);
257
+ if (isNum(per) && per !== -1)
258
+ return per;
259
+ const global = configGet('review.max_prompt_tokens');
260
+ return isNum(global) ? global : null;
261
+ }
239
262
  /* ------------------------------------------------------------------ *
240
263
  * Resolution
241
264
  * ------------------------------------------------------------------ */
@@ -20,7 +20,7 @@
20
20
  * `reviewer` bodies in the capability registry, not a hand-maintained tail.
21
21
  * A capability of EITHER `role: "runtime"` (the six dual-purpose hosts —
22
22
  * antigravity/claude/codex/cursor/opencode/qwen) or the lane-only
23
- * `role: "reviewer"` (gemini/coderabbit/ollama/lm_studio/llama_cpp) may carry
23
+ * `role: "reviewer"` (coderabbit/ollama/lm_studio/llama_cpp) may carry
24
24
  * a `reviewer` body, and it is the body's `reviewer.slug` — NOT the capability
25
25
  * id — that becomes the roster entry: the two differ for `lm-studio` (id) /
26
26
  * `lm_studio` (slug) and `llama-cpp` (id) / `llama_cpp` (slug), ADR-2782's
@@ -229,7 +229,7 @@ function resolveReviewerSelection(input) {
229
229
  // ADR-2782 D4: absent-safe governs DISCOVERY, never explicit selection.
230
230
  // Not finding a lane nobody asked for is normal; failing to run a lane
231
231
  // somebody asked for is an error. Every miss used to be an `info`, so a
232
- // PARTIAL miss (`--gemini --qwen` with qwen absent) ran the review with a
232
+ // PARTIAL miss (`--codex --qwen` with qwen absent) ran the review with a
233
233
  // thinner reviewer set while present_results reported success — "a cross-AI
234
234
  // review that silently drops a lane is blind in one eye" (review.md).
235
235
  // A total miss already errored, but only as a side effect of the selected