@opengsd/gsd-core 1.17.0 → 1.19.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 (369) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +2 -1
  3. package/.opencode/plugins/gsd-core.js +2 -3
  4. package/agents/gsd-advisor-researcher.compact.md +1 -1
  5. package/agents/gsd-advisor-researcher.md +1 -1
  6. package/agents/gsd-assumptions-analyzer.compact.md +1 -1
  7. package/agents/gsd-assumptions-analyzer.md +1 -1
  8. package/agents/gsd-code-fixer.compact.md +3 -3
  9. package/agents/gsd-code-fixer.md +5 -4
  10. package/agents/gsd-code-reviewer.compact.md +1 -1
  11. package/agents/gsd-code-reviewer.md +1 -1
  12. package/agents/gsd-codebase-mapper.compact.md +1 -1
  13. package/agents/gsd-codebase-mapper.md +1 -1
  14. package/agents/gsd-debugger.md +1 -1
  15. package/agents/gsd-doc-verifier.compact.md +4 -4
  16. package/agents/gsd-doc-verifier.md +4 -3
  17. package/agents/gsd-doc-writer.compact.md +23 -5
  18. package/agents/gsd-doc-writer.md +19 -6
  19. package/agents/gsd-eval-auditor.compact.md +1 -1
  20. package/agents/gsd-eval-auditor.md +1 -1
  21. package/agents/gsd-executor.md +7 -3
  22. package/agents/gsd-integration-checker.compact.md +1 -1
  23. package/agents/gsd-integration-checker.md +1 -1
  24. package/agents/gsd-nyquist-auditor.compact.md +1 -1
  25. package/agents/gsd-nyquist-auditor.md +1 -1
  26. package/agents/gsd-phase-researcher.md +1 -1
  27. package/agents/gsd-plan-checker.md +2 -1
  28. package/agents/gsd-planner.md +5 -4
  29. package/agents/gsd-project-researcher.compact.md +1 -1
  30. package/agents/gsd-project-researcher.md +1 -1
  31. package/agents/gsd-research-synthesizer.compact.md +5 -5
  32. package/agents/gsd-research-synthesizer.md +5 -5
  33. package/agents/gsd-roadmapper.compact.md +1 -1
  34. package/agents/gsd-roadmapper.md +1 -1
  35. package/agents/gsd-security-auditor.compact.md +1 -1
  36. package/agents/gsd-security-auditor.md +1 -1
  37. package/agents/gsd-ui-auditor.compact.md +1 -1
  38. package/agents/gsd-ui-auditor.md +1 -1
  39. package/agents/gsd-ui-checker.compact.md +1 -1
  40. package/agents/gsd-ui-checker.md +1 -1
  41. package/agents/gsd-ui-researcher.compact.md +13 -1
  42. package/agents/gsd-ui-researcher.md +28 -1
  43. package/agents/gsd-verifier.md +2 -2
  44. package/bin/install.js +460 -105
  45. package/commands/gsd/code-review.md +8 -0
  46. package/commands/gsd/pause-work.md +1 -1
  47. package/gsd-core/bin/gsd-tools.cjs +124 -18
  48. package/gsd-core/bin/lib/agent-install-check.cjs +29 -3
  49. package/gsd-core/bin/lib/args-terminator.cjs +114 -0
  50. package/gsd-core/bin/lib/broken-windows.cjs +59 -1
  51. package/gsd-core/bin/lib/capability-ledger.cjs +25 -0
  52. package/gsd-core/bin/lib/capability-lock.cjs +41 -8
  53. package/gsd-core/bin/lib/capability-registry.cjs +162 -74
  54. package/gsd-core/bin/lib/capability-source.cjs +3 -1
  55. package/gsd-core/bin/lib/capability-state.cjs +20 -11
  56. package/gsd-core/bin/lib/capability-validator.cjs +23 -4
  57. package/gsd-core/bin/lib/commands.cjs +5 -1
  58. package/gsd-core/bin/lib/config-loader.cjs +13 -3
  59. package/gsd-core/bin/lib/config.cjs +256 -58
  60. package/gsd-core/bin/lib/core-utils.cjs +34 -0
  61. package/gsd-core/bin/lib/decision-coverage-support.cjs +93 -0
  62. package/gsd-core/bin/lib/gate-context-drift.cjs +8 -3
  63. package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +21 -1
  64. package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +19 -1
  65. package/gsd-core/bin/lib/gate-evaluation-scope.cjs +134 -13
  66. package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +23 -3
  67. package/gsd-core/bin/lib/gate-predicate.cjs +8 -12
  68. package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +114 -18
  69. package/gsd-core/bin/lib/gate-ui-safety.cjs +23 -5
  70. package/gsd-core/bin/lib/git-info-exclude.cjs +57 -0
  71. package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +18 -3
  72. package/gsd-core/bin/lib/health-diagnostic-types.cjs +4 -0
  73. package/gsd-core/bin/lib/health-diagnostic.cjs +52 -1
  74. package/gsd-core/bin/lib/host-integration.cjs +13 -6
  75. package/gsd-core/bin/lib/init.cjs +76 -5
  76. package/gsd-core/bin/lib/install-effort-resolver.cjs +2 -2
  77. package/gsd-core/bin/lib/install-engine.cjs +246 -32
  78. package/gsd-core/bin/lib/install-model-override-resolver.cjs +4 -3
  79. package/gsd-core/bin/lib/install-profiles.cjs +14 -7
  80. package/gsd-core/bin/lib/installer-migration-report.cjs +2 -0
  81. package/gsd-core/bin/lib/markdown-line-diff.cjs +147 -0
  82. package/gsd-core/bin/lib/markdown-sectionizer.cjs +113 -0
  83. package/gsd-core/bin/lib/milestone-lock.cjs +8 -1
  84. package/gsd-core/bin/lib/milestone-release-map.cjs +244 -0
  85. package/gsd-core/bin/lib/milestone-release-tags.cjs +440 -0
  86. package/gsd-core/bin/lib/milestone.cjs +43 -1
  87. package/gsd-core/bin/lib/model-catalog.cjs +8 -0
  88. package/gsd-core/bin/lib/normalize-test-command.cjs +67 -0
  89. package/gsd-core/bin/lib/phase-id.cjs +21 -4
  90. package/gsd-core/bin/lib/phase-lifecycle.cjs +37 -4
  91. package/gsd-core/bin/lib/phase.cjs +235 -37
  92. package/gsd-core/bin/lib/planning-snapshot.cjs +3 -1
  93. package/gsd-core/bin/lib/planning-workspace.cjs +18 -0
  94. package/gsd-core/bin/lib/pristine-baseline.cjs +11 -3
  95. package/gsd-core/bin/lib/read-only-git-env.cjs +58 -0
  96. package/gsd-core/bin/lib/report-parser.cjs +57 -1
  97. package/gsd-core/bin/lib/review-lane-descriptor.cjs +35 -2
  98. package/gsd-core/bin/lib/review-lane-invocation.cjs +40 -0
  99. package/gsd-core/bin/lib/review-lane-runner.cjs +33 -4
  100. package/gsd-core/bin/lib/review-reviewer-selection.cjs +20 -1
  101. package/gsd-core/bin/lib/roadmap-parser.cjs +12 -0
  102. package/gsd-core/bin/lib/roadmap-upgrade.cjs +39 -2
  103. package/gsd-core/bin/lib/roadmap.cjs +89 -30
  104. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +428 -16
  105. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +8 -4
  106. package/gsd-core/bin/lib/runtime-homes.cjs +18 -0
  107. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +60 -16
  108. package/gsd-core/bin/lib/shell-command-projection.cjs +123 -16
  109. package/gsd-core/bin/lib/smart-entry.cjs +37 -16
  110. package/gsd-core/bin/lib/state-contract.cjs +29 -9
  111. package/gsd-core/bin/lib/state-document.cjs +47 -5
  112. package/gsd-core/bin/lib/state-transition.cjs +150 -34
  113. package/gsd-core/bin/lib/state.cjs +140 -88
  114. package/gsd-core/bin/lib/surface.cjs +9 -0
  115. package/gsd-core/bin/lib/task-command-router.cjs +7 -28
  116. package/gsd-core/bin/lib/task-content-resolution.cjs +46 -1
  117. package/gsd-core/bin/lib/tdd-red-evidence.cjs +5 -0
  118. package/gsd-core/bin/lib/tdd-test-files.cjs +42 -0
  119. package/gsd-core/bin/lib/verification.cjs +96 -9
  120. package/gsd-core/bin/lib/verify.cjs +38 -1
  121. package/gsd-core/bin/lib/worktree-safety.cjs +22 -1
  122. package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
  123. package/gsd-core/bin/shared/config-schema.manifest.json +1 -0
  124. package/gsd-core/references/agent-contracts.md +1 -1
  125. package/gsd-core/references/agent-skills-bootstrap.md +26 -7
  126. package/gsd-core/references/git-integration.md +14 -3
  127. package/gsd-core/references/loop-hook-dispatch.md +13 -6
  128. package/gsd-core/references/planner-reversibility.md +18 -4
  129. package/gsd-core/references/planner-verify-command-grounding.md +18 -0
  130. package/gsd-core/references/planning-config.md +2 -0
  131. package/gsd-core/references/tdd.md +5 -4
  132. package/gsd-core/references/verifier-phase-gates.md +8 -1
  133. package/gsd-core/templates/DEBUG.md +16 -0
  134. package/gsd-core/templates/config.json +2 -1
  135. package/gsd-core/templates/verification-report.md +1 -1
  136. package/gsd-core/workflows/add-backlog.md +10 -2
  137. package/gsd-core/workflows/add-phase.md +5 -1
  138. package/gsd-core/workflows/add-tests.md +5 -1
  139. package/gsd-core/workflows/add-todo.md +5 -1
  140. package/gsd-core/workflows/ai-integration-phase.md +5 -1
  141. package/gsd-core/workflows/audit-fix.md +2 -1
  142. package/gsd-core/workflows/audit-milestone.md +21 -9
  143. package/gsd-core/workflows/autonomous/templates/minimal-context.md +41 -0
  144. package/gsd-core/workflows/autonomous.md +52 -64
  145. package/gsd-core/workflows/check-todos.md +5 -1
  146. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +10 -1
  147. package/gsd-core/workflows/code-review-fix.md +5 -1
  148. package/gsd-core/workflows/code-review.md +66 -8
  149. package/gsd-core/workflows/complete-milestone/detail/elaboration.md +5 -1
  150. package/gsd-core/workflows/complete-milestone/steps/project-md-evolution-review.md +145 -0
  151. package/gsd-core/workflows/complete-milestone/steps/release-map.md +80 -0
  152. package/gsd-core/workflows/complete-milestone.md +64 -157
  153. package/gsd-core/workflows/debug.md +5 -1
  154. package/gsd-core/workflows/diagnose-issues.md +34 -6
  155. package/gsd-core/workflows/discuss-phase/modes/chain.md +5 -1
  156. package/gsd-core/workflows/discuss-phase/modes/power.md +1 -1
  157. package/gsd-core/workflows/discuss-phase-assumptions.md +44 -5
  158. package/gsd-core/workflows/discuss-phase-power.md +19 -2
  159. package/gsd-core/workflows/discuss-phase.md +11 -11
  160. package/gsd-core/workflows/docs-update/detail/elaboration.md +7 -6
  161. package/gsd-core/workflows/docs-update.md +27 -5
  162. package/gsd-core/workflows/edit-phase.md +5 -1
  163. package/gsd-core/workflows/eval-review.md +11 -3
  164. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +5 -1
  165. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +13 -7
  166. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +19 -8
  167. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +21 -3
  168. package/gsd-core/workflows/execute-phase/steps/regression-gate.md +18 -1
  169. package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +7 -3
  170. package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +11 -2
  171. package/gsd-core/workflows/execute-phase.md +46 -11
  172. package/gsd-core/workflows/execute-plan.md +8 -4
  173. package/gsd-core/workflows/extract-learnings.md +6 -2
  174. package/gsd-core/workflows/forensics.md +5 -1
  175. package/gsd-core/workflows/health.md +2 -1
  176. package/gsd-core/workflows/import.md +6 -2
  177. package/gsd-core/workflows/insert-phase.md +5 -1
  178. package/gsd-core/workflows/manager.md +10 -2
  179. package/gsd-core/workflows/map-codebase.md +5 -1
  180. package/gsd-core/workflows/milestone-summary.md +10 -2
  181. package/gsd-core/workflows/new-milestone.md +13 -5
  182. package/gsd-core/workflows/new-project.md +9 -5
  183. package/gsd-core/workflows/next.md +8 -4
  184. package/gsd-core/workflows/pause-work.md +3 -3
  185. package/gsd-core/workflows/plan-phase/steps/auto-advance-check.md +70 -0
  186. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +7 -3
  187. package/gsd-core/workflows/plan-phase/steps/closed-phase-gate.md +6 -2
  188. package/gsd-core/workflows/plan-phase.md +54 -86
  189. package/gsd-core/workflows/plan-review-convergence.md +17 -5
  190. package/gsd-core/workflows/plant-seed.md +8 -4
  191. package/gsd-core/workflows/progress.md +6 -2
  192. package/gsd-core/workflows/quick/steps/plan-checker-loop.md +1 -1
  193. package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +8 -1
  194. package/gsd-core/workflows/quick-batch/steps/plan-checker-loop.md +2 -1
  195. package/gsd-core/workflows/quick-batch.md +5 -1
  196. package/gsd-core/workflows/quick.md +23 -8
  197. package/gsd-core/workflows/remove-phase.md +5 -1
  198. package/gsd-core/workflows/resume-project.md +5 -1
  199. package/gsd-core/workflows/review.md +22 -15
  200. package/gsd-core/workflows/scan.md +5 -1
  201. package/gsd-core/workflows/section-manifest.json +5 -0
  202. package/gsd-core/workflows/secure-phase.md +6 -2
  203. package/gsd-core/workflows/settings.md +4 -3
  204. package/gsd-core/workflows/ship.md +16 -14
  205. package/gsd-core/workflows/spec-phase.md +3 -6
  206. package/gsd-core/workflows/thread.md +10 -2
  207. package/gsd-core/workflows/transition.md +5 -1
  208. package/gsd-core/workflows/ui-phase.md +5 -1
  209. package/gsd-core/workflows/ui-review.md +6 -2
  210. package/gsd-core/workflows/ultraplan-phase.md +5 -1
  211. package/gsd-core/workflows/update.md +5 -1
  212. package/gsd-core/workflows/validate-phase.md +6 -2
  213. package/gsd-core/workflows/verify-work/detail/elaboration.md +1 -1
  214. package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +5 -1
  215. package/gsd-core/workflows/verify-work.md +15 -6
  216. package/hooks/dist/gsd-agent-isolation-guard.js +14 -2
  217. package/hooks/dist/gsd-cursor-subagent-start.js +8 -3
  218. package/hooks/dist/gsd-path-export.js +95 -0
  219. package/hooks/dist/gsd-secret-read-guard.js +244 -53
  220. package/hooks/dist/gsd-statusline.js +35 -2
  221. package/hooks/dist/gsd-validate-commit.sh +27 -5
  222. package/hooks/dist/gsd-windsurf-pre-write.js +28 -1
  223. package/hooks/dist/gsd-workflow-guard.js +1 -1
  224. package/hooks/dist/gsd-worktree-path-guard.js +28 -1
  225. package/hooks/dist/lib/isolation-sentinel.js +44 -0
  226. package/hooks/dist/managed-hooks-registry.cjs +1 -0
  227. package/hooks/gsd-agent-isolation-guard.js +14 -2
  228. package/hooks/gsd-cursor-subagent-start.js +8 -3
  229. package/hooks/gsd-path-export.js +95 -0
  230. package/hooks/gsd-secret-read-guard.js +244 -53
  231. package/hooks/gsd-statusline.js +35 -2
  232. package/hooks/gsd-validate-commit.sh +27 -5
  233. package/hooks/gsd-windsurf-pre-write.js +28 -1
  234. package/hooks/gsd-workflow-guard.js +1 -1
  235. package/hooks/gsd-worktree-path-guard.js +28 -1
  236. package/hooks/hooks.json +1 -0
  237. package/hooks/lib/isolation-sentinel.js +44 -0
  238. package/hooks/managed-hooks-registry.cjs +1 -0
  239. package/package.json +13 -6
  240. package/pi/gsd.cjs +1047 -10
  241. package/pi/package-agents/gsd-advisor-researcher.md +113 -0
  242. package/pi/package-agents/gsd-ai-researcher.md +111 -0
  243. package/pi/package-agents/gsd-assumptions-analyzer.md +110 -0
  244. package/pi/package-agents/gsd-code-fixer.md +769 -0
  245. package/pi/package-agents/gsd-code-reviewer.md +402 -0
  246. package/pi/package-agents/gsd-codebase-mapper.md +850 -0
  247. package/pi/package-agents/gsd-debug-session-manager.md +416 -0
  248. package/pi/package-agents/gsd-debugger.md +1274 -0
  249. package/pi/package-agents/gsd-doc-classifier.md +269 -0
  250. package/pi/package-agents/gsd-doc-synthesizer.md +259 -0
  251. package/pi/package-agents/gsd-doc-verifier.md +212 -0
  252. package/pi/package-agents/gsd-doc-writer.md +626 -0
  253. package/pi/package-agents/gsd-dom-verifier.md +164 -0
  254. package/pi/package-agents/gsd-domain-researcher.md +144 -0
  255. package/pi/package-agents/gsd-eval-auditor.md +185 -0
  256. package/pi/package-agents/gsd-eval-planner.md +149 -0
  257. package/pi/package-agents/gsd-executor.md +894 -0
  258. package/pi/package-agents/gsd-framework-selector.md +159 -0
  259. package/pi/package-agents/gsd-integration-checker.md +476 -0
  260. package/pi/package-agents/gsd-intel-updater.md +338 -0
  261. package/pi/package-agents/gsd-mempalace-curator.md +49 -0
  262. package/pi/package-agents/gsd-nyquist-auditor.md +200 -0
  263. package/pi/package-agents/gsd-pattern-mapper.md +340 -0
  264. package/pi/package-agents/gsd-phase-researcher.md +897 -0
  265. package/pi/package-agents/gsd-plan-checker.md +1077 -0
  266. package/pi/package-agents/gsd-planner.md +1003 -0
  267. package/pi/package-agents/gsd-project-researcher.md +611 -0
  268. package/pi/package-agents/gsd-research-synthesizer.md +259 -0
  269. package/pi/package-agents/gsd-roadmapper.md +779 -0
  270. package/pi/package-agents/gsd-security-auditor.md +171 -0
  271. package/pi/package-agents/gsd-ui-auditor.md +581 -0
  272. package/pi/package-agents/gsd-ui-checker.md +417 -0
  273. package/pi/package-agents/gsd-ui-researcher.md +469 -0
  274. package/pi/package-agents/gsd-user-profiler.md +174 -0
  275. package/pi/package-agents/gsd-verifier.md +963 -0
  276. package/pi/package-agents/manifest.json +39 -0
  277. package/pi/package-skills/gsd-add-tests/SKILL.md +39 -0
  278. package/pi/package-skills/gsd-ai-integration-phase/SKILL.md +36 -0
  279. package/pi/package-skills/gsd-audit-fix/SKILL.md +34 -0
  280. package/pi/package-skills/gsd-audit-milestone/SKILL.md +40 -0
  281. package/pi/package-skills/gsd-audit-uat/SKILL.md +26 -0
  282. package/pi/package-skills/gsd-autonomous/SKILL.md +52 -0
  283. package/pi/package-skills/gsd-capture/SKILL.md +68 -0
  284. package/pi/package-skills/gsd-cleanup/SKILL.md +25 -0
  285. package/pi/package-skills/gsd-code-review/SKILL.md +71 -0
  286. package/pi/package-skills/gsd-complete-milestone/SKILL.md +147 -0
  287. package/pi/package-skills/gsd-config/SKILL.md +60 -0
  288. package/pi/package-skills/gsd-debug/SKILL.md +64 -0
  289. package/pi/package-skills/gsd-discuss-phase/SKILL.md +74 -0
  290. package/pi/package-skills/gsd-docs-update/SKILL.md +50 -0
  291. package/pi/package-skills/gsd-eval-review/SKILL.md +35 -0
  292. package/pi/package-skills/gsd-execute-phase/SKILL.md +62 -0
  293. package/pi/package-skills/gsd-explore/SKILL.md +26 -0
  294. package/pi/package-skills/gsd-extract-learnings/SKILL.md +25 -0
  295. package/pi/package-skills/gsd-fast/SKILL.md +33 -0
  296. package/pi/package-skills/gsd-forensics/SKILL.md +59 -0
  297. package/pi/package-skills/gsd-graphify/SKILL.md +210 -0
  298. package/pi/package-skills/gsd-health/SKILL.md +36 -0
  299. package/pi/package-skills/gsd-help/SKILL.md +37 -0
  300. package/pi/package-skills/gsd-import/SKILL.md +46 -0
  301. package/pi/package-skills/gsd-inbox/SKILL.md +42 -0
  302. package/pi/package-skills/gsd-ingest-docs/SKILL.md +43 -0
  303. package/pi/package-skills/gsd-manager/SKILL.md +46 -0
  304. package/pi/package-skills/gsd-map-codebase/SKILL.md +85 -0
  305. package/pi/package-skills/gsd-mempalace-capture/SKILL.md +111 -0
  306. package/pi/package-skills/gsd-mempalace-recall/SKILL.md +111 -0
  307. package/pi/package-skills/gsd-milestone-summary/SKILL.md +54 -0
  308. package/pi/package-skills/gsd-mvp-phase/SKILL.md +45 -0
  309. package/pi/package-skills/gsd-new-milestone/SKILL.md +49 -0
  310. package/pi/package-skills/gsd-new-project/SKILL.md +49 -0
  311. package/pi/package-skills/gsd-next/SKILL.md +34 -0
  312. package/pi/package-skills/gsd-ns-context/SKILL.md +31 -0
  313. package/pi/package-skills/gsd-ns-ideate/SKILL.md +30 -0
  314. package/pi/package-skills/gsd-ns-manage/SKILL.md +42 -0
  315. package/pi/package-skills/gsd-ns-project/SKILL.md +34 -0
  316. package/pi/package-skills/gsd-ns-review/SKILL.md +35 -0
  317. package/pi/package-skills/gsd-ns-workflow/SKILL.md +44 -0
  318. package/pi/package-skills/gsd-onboard/SKILL.md +46 -0
  319. package/pi/package-skills/gsd-pause-work/SKILL.md +48 -0
  320. package/pi/package-skills/gsd-phase/SKILL.md +61 -0
  321. package/pi/package-skills/gsd-plan-phase/SKILL.md +62 -0
  322. package/pi/package-skills/gsd-plan-review-convergence/SKILL.md +63 -0
  323. package/pi/package-skills/gsd-pr-branch/SKILL.md +31 -0
  324. package/pi/package-skills/gsd-profile-user/SKILL.md +48 -0
  325. package/pi/package-skills/gsd-progress/SKILL.md +51 -0
  326. package/pi/package-skills/gsd-quick/SKILL.md +179 -0
  327. package/pi/package-skills/gsd-quick-batch/SKILL.md +114 -0
  328. package/pi/package-skills/gsd-resume-work/SKILL.md +31 -0
  329. package/pi/package-skills/gsd-review/SKILL.md +50 -0
  330. package/pi/package-skills/gsd-review-backlog/SKILL.md +65 -0
  331. package/pi/package-skills/gsd-secure-phase/SKILL.md +37 -0
  332. package/pi/package-skills/gsd-settings/SKILL.md +30 -0
  333. package/pi/package-skills/gsd-ship/SKILL.md +27 -0
  334. package/pi/package-skills/gsd-sketch/SKILL.md +56 -0
  335. package/pi/package-skills/gsd-spec-phase/SKILL.md +63 -0
  336. package/pi/package-skills/gsd-spike/SKILL.md +53 -0
  337. package/pi/package-skills/gsd-stats/SKILL.md +22 -0
  338. package/pi/package-skills/gsd-surface/SKILL.md +177 -0
  339. package/pi/package-skills/gsd-thread/SKILL.md +29 -0
  340. package/pi/package-skills/gsd-ui-phase/SKILL.md +35 -0
  341. package/pi/package-skills/gsd-ui-review/SKILL.md +35 -0
  342. package/pi/package-skills/gsd-ultraplan-phase/SKILL.md +38 -0
  343. package/pi/package-skills/gsd-undo/SKILL.md +38 -0
  344. package/pi/package-skills/gsd-update/SKILL.md +51 -0
  345. package/pi/package-skills/gsd-validate-phase/SKILL.md +37 -0
  346. package/pi/package-skills/gsd-verify-work/SKILL.md +41 -0
  347. package/pi/package-skills/gsd-workspace/SKILL.md +57 -0
  348. package/pi/package-skills/gsd-workstreams/SKILL.md +73 -0
  349. package/scripts/audit-workflow-script-paths.cjs +1 -1
  350. package/scripts/build-hooks.js +4 -0
  351. package/scripts/command-contract-helpers.cjs +1 -1
  352. package/scripts/diagnose-windows-spawn-watcher.cjs +317 -0
  353. package/scripts/docs-guard-registry.cjs +22 -7
  354. package/scripts/gen-health-docs.cjs +13 -1
  355. package/scripts/gen-pi-package-skills.cjs +217 -0
  356. package/scripts/lib/macos-conformance-tier.generated.cjs +19 -0
  357. package/scripts/lib/platform-conformance-tier.generated.cjs +41 -0
  358. package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +3 -3
  359. package/scripts/lint-phase-arg-assignment.cjs +2 -2
  360. package/scripts/lint-retired-runtime-name.cjs +5 -0
  361. package/scripts/lint-workflow-shellcheck-baseline.json +16 -16
  362. package/scripts/npm-audit-baseline.cjs +41 -7
  363. package/scripts/release-tarball-smoke.cjs +1 -0
  364. package/scripts/reviewed-or-maintainer-policy.cjs +181 -0
  365. package/scripts/select-docs-guards.cjs +1 -1
  366. package/scripts/self-test-report-policy.cjs +350 -0
  367. package/skills/gsd-code-review/SKILL.md +8 -0
  368. package/skills/gsd-pause-work/SKILL.md +1 -1
  369. package/vscode/package.json +1 -1
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ /**
3
+ * read-only-git-env.cts — the single owner of the read-only git env block
4
+ * (#5048). CONTEXT.md / OS Shell Projection seam.
5
+ *
6
+ * By default `git status` refreshes the index and takes an *optional*
7
+ * `.git/index.lock` to write the refreshed copy back. That is a write the caller
8
+ * never asked for, and it turns a pure read into a contender for the lock a
9
+ * real `git add` / `git commit` needs — so a read-only statusline render can
10
+ * make a concurrent commit fail with
11
+ * `Unable to create '.git/index.lock': File exists`. `GIT_OPTIONAL_LOCKS=0`
12
+ * tells git to skip only those *optional* index operations. Nothing a read
13
+ * needs is lost: `git status` reads the index, it just doesn't need to rewrite
14
+ * it.
15
+ *
16
+ * ## Why this module exists
17
+ *
18
+ * The block used to be hand-written at every seam that spawns git for a read.
19
+ * Six copies of `{ ...process.env, GIT_OPTIONAL_LOCKS: '0' }` is six places to
20
+ * forget when a seam is added, and a probe that checks each seam for the literal
21
+ * value passes even when a seam stopped consulting the owner. One owner makes
22
+ * the drift structural instead: the parity test patches THIS function to a
23
+ * sentinel and asserts every seam's spawn carries the sentinel, so a seam that
24
+ * hand-writes the variable again fails red rather than passing quietly.
25
+ * (tests/git-optional-locks-parity.test.cjs, "#5048 every seam reads the shared
26
+ * owner".)
27
+ *
28
+ * ## Why the hook scripts require the built artifact
29
+ *
30
+ * `hooks/*.js` are staged as standalone files at install time, so they reach
31
+ * compiled `src/` modules through `../gsd-core/bin/lib/*.cjs` rather than a
32
+ * sibling hooks/-tree file — the same rule hooks/lib/git-cmd.js follows for
33
+ * token-scanner. They call `readOnlyGitEnv()` per spawn rather than snapshotting
34
+ * the result at module load, so a later `process.env` mutation is visible and the
35
+ * two behave identically.
36
+ */
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ exports.readOnlyGitEnv = readOnlyGitEnv;
39
+ /**
40
+ * Build the env for a read-only git spawn.
41
+ *
42
+ * @param base Environment to spread, `process.env` by default. Callers that
43
+ * layer extra git variables on top (GIT_TERMINAL_PROMPT, a caller's own
44
+ * overrides) pass them in `base`; callers that must let a caller-supplied
45
+ * override win spread the result and apply their own keys afterwards.
46
+ * @returns A fresh object each call — never the cached `process.env`.
47
+ */
48
+ function readOnlyGitEnv(base = process.env) {
49
+ const env = {};
50
+ for (const [key, value] of Object.entries(base)) {
51
+ // process.env carries undefined-valued keys on some platforms; spawn()
52
+ // rejects a non-string value rather than ignoring it.
53
+ if (value !== undefined)
54
+ env[key] = value;
55
+ }
56
+ env.GIT_OPTIONAL_LOCKS = '0';
57
+ return env;
58
+ }
@@ -6,7 +6,7 @@ exports.parseTestReport = parseTestReport;
6
6
  const tap_parser_cjs_1 = require("./vendor/tap-parser.cjs");
7
7
  const saxes_cjs_1 = require("./vendor/saxes.cjs");
8
8
  exports.ReportFormat = {
9
- Tap: 'tap', Junit: 'junit', SwiftTesting: 'swift-testing', Unittest: 'unittest', Unknown: 'unknown',
9
+ Tap: 'tap', Junit: 'junit', SwiftTesting: 'swift-testing', Unittest: 'unittest', GoTest: 'go-test', Unknown: 'unknown',
10
10
  };
11
11
  exports.TestStatus = { Passed: 'passed', Failed: 'failed', Skipped: 'skipped', Todo: 'todo' };
12
12
  function parseTap(output) {
@@ -247,7 +247,63 @@ function parseUnittest(output) {
247
247
  report.valid = report.issues.length === 0;
248
248
  return report;
249
249
  }
250
+ /**
251
+ * `go test` text output (#5106). Plain console text, so the shape is matched by line:
252
+ * --- FAIL: TestName (0.00s) one per failed test (every test with -v; subtests indented)
253
+ * FAIL\texample.com/pkg\t0.004s one package summary per package, after that package's tests
254
+ * FAIL\texample.com/pkg [build failed] the package did not compile — nothing asserted anything
255
+ * A test's name carries no package, so each test is also known as `<package>.<name>`, attributed to
256
+ * the next package summary line. The same name failing in two packages is ambiguous until qualified.
257
+ * `go test -json` is not text and stays unsupported.
258
+ */
259
+ const GO_TEST_RESULT = /^[ \t]*-{3} (PASS|FAIL|SKIP): (\S+) \(\d+(?:\.\d+)?s\)$/; // -{3}: not a literal fence, see frontmatter-fence-drift
260
+ const GO_PACKAGE_LINE = /^(ok|FAIL|\?)[ \t]+(\S+)[ \t]+(?:\d+(?:\.\d+)?s\b|\(cached\)|\[([a-z ]+)\])/;
261
+ function isGoTestOutput(output) {
262
+ if (/^TAP version \d+/.test(output.trimStart()))
263
+ return false;
264
+ return output.split(/\r?\n/).some((line) => GO_TEST_RESULT.test(line) || GO_PACKAGE_LINE.test(line));
265
+ }
266
+ function parseGoTest(output) {
267
+ const report = { format: exports.ReportFormat.GoTest, valid: true, tests: [], issues: [] };
268
+ let segment = [];
269
+ let packages = 0;
270
+ for (const line of output.split(/\r?\n/)) {
271
+ const result = GO_TEST_RESULT.exec(line);
272
+ if (result) {
273
+ const name = result[2];
274
+ const status = result[1] === 'FAIL' ? exports.TestStatus.Failed : result[1] === 'SKIP' ? exports.TestStatus.Skipped : exports.TestStatus.Passed;
275
+ if (!segment.some((test) => test.name === name && test.status === status)) {
276
+ segment.push({ name, identities: [name], group: null, groupIdentities: [], status });
277
+ }
278
+ continue;
279
+ }
280
+ const pkg = GO_PACKAGE_LINE.exec(line);
281
+ if (!pkg)
282
+ continue;
283
+ packages++;
284
+ const [, outcome, importPath, bracket] = pkg;
285
+ if (outcome === 'FAIL' && (bracket === 'build failed' || bracket === 'setup failed')) {
286
+ report.buildFailed = true;
287
+ report.issues.push(`go test package ${importPath} ${bracket}`);
288
+ }
289
+ else if (outcome === 'ok' && segment.some((test) => test.status === exports.TestStatus.Failed)) {
290
+ report.issues.push(`go test package ${importPath} is ok but its output reports a failed test`);
291
+ }
292
+ for (const test of segment)
293
+ test.identities.push(`${importPath}.${test.name}`);
294
+ report.tests.push(...segment);
295
+ segment = [];
296
+ }
297
+ if (packages === 0)
298
+ report.issues.push('Missing go test package summary');
299
+ if (segment.length > 0)
300
+ report.issues.push('go test results without a following package summary');
301
+ report.valid = report.issues.length === 0;
302
+ return report;
303
+ }
250
304
  const adapters = [
305
+ // Before TAP: a run whose first package is fine begins `ok <TAB>pkg`, which the TAP matcher reads as a point.
306
+ { matches: isGoTestOutput, parse: parseGoTest },
251
307
  { matches: (output) => /^(?:TAP version \d+|(?:not )?ok\b|1\.\.\d+|#)/.test(output.trimStart()), parse: parseTap },
252
308
  { matches: (output) => output.trimStart().startsWith('<'), parse: parseJunit },
253
309
  { matches: (output) => new RegExp(SWIFT_AGGREGATE.source, 'm').test(output), parse: parseSwiftTesting },
@@ -58,6 +58,7 @@ exports.DOCS_PARITY_VIOLATION = exports.LANE_SLUG_RE = exports.PARITY_VIOLATION
58
58
  exports.mergeReviewerLanes = mergeReviewerLanes;
59
59
  exports.checkReviewerLaneParity = checkReviewerLaneParity;
60
60
  exports.checkReviewerDocsParity = checkReviewerDocsParity;
61
+ const text_lines_cjs_1 = require("./text-lines.cjs");
61
62
  /**
62
63
  * Argv placeholders (Phase 5b, #2799).
63
64
  *
@@ -576,6 +577,7 @@ exports.PARITY_VIOLATION = Object.freeze({
576
577
  REGISTRY_LANE_UNDECLARED: 'registry_lane_undeclared',
577
578
  DESCRIPTOR_LANE_NOT_IN_REGISTRY: 'descriptor_lane_not_in_registry',
578
579
  BESPOKE_LEG_PRESENT: 'bespoke_leg_present',
580
+ AVAILABILITY_FALLBACK_MISMATCH: 'availability_fallback_mismatch',
579
581
  DUPLICATE_SLUG: 'duplicate_slug',
580
582
  DUPLICATE_FLAG: 'duplicate_flag',
581
583
  DUPLICATE_SECTION: 'duplicate_section',
@@ -607,6 +609,10 @@ const LEG_MARKER_RE = /<!--\s*reviewer-lane:\s*([a-z0-9_-]+)\s*-->/g;
607
609
  * design principle of this module.
608
610
  */
609
611
  exports.LANE_SLUG_RE = /^[a-z0-9][a-z0-9_-]*$/;
612
+ /** The workflow's availability call: `gsd_run review-lane availability ...` at command position. */
613
+ const AVAILABILITY_CALL_RE = /^\s*gsd_run review-lane availability(?:\s|$)/;
614
+ /** One `<slug>:missing` row in the printf fallback; slug is LANE_SLUG_RE's grammar capped at 32 chars. */
615
+ const AVAILABILITY_FALLBACK_ROW_RE = /(?:'|\\n)([a-z0-9][a-z0-9_-]{0,31}):missing/g;
610
616
  /** Bounds of the step a bespoke leg marker could appear inside. */
611
617
  const INVOKE_STEP_RE = /<step name="invoke_reviewers">([\s\S]*?)<\/step>/;
612
618
  function sliceStep(workflowText, re) {
@@ -627,8 +633,10 @@ function countOccurrences(haystack, re) {
627
633
  }
628
634
  /**
629
635
  * Bidirectional parity across three surfaces: the descriptor, the roster
630
- * (`KNOWN_REVIEWER_SLUGS`), and the generated capability **registry** — plus one anti-parity
631
- * assertion against the workflow.
636
+ * (`KNOWN_REVIEWER_SLUGS`), and the generated capability **registry** — plus two assertions
637
+ * against the workflow: the anti-parity check, and the availability-fallback check (the workflow
638
+ * makes the availability call, has a fallback row per lane, and the fallback slug set equals the
639
+ * openai-http lanes).
632
640
  *
633
641
  * **Re-pointed by Phase 5b (#2799).** Through Phase 5a this function also required a literal
634
642
  * `<!-- reviewer-lane: <slug> -->` per lane inside `invoke_reviewers` and a literal
@@ -671,6 +679,7 @@ function checkReviewerLaneParity(input) {
671
679
  const seenSlug = new Set();
672
680
  const seenFlag = new Set();
673
681
  const seenSection = new Set();
682
+ const httpSlugs = new Set();
674
683
  // The declared parameter type says `ReviewerLane[]`, but this function is a
675
684
  // trust boundary — narrow from `unknown` rather than believing the annotation.
676
685
  const rawLanes = Array.isArray(descriptor) ? descriptor : [];
@@ -689,6 +698,8 @@ function checkReviewerLaneParity(input) {
689
698
  if (seenSlug.has(slug))
690
699
  add(exports.PARITY_VIOLATION.DUPLICATE_SLUG, slug);
691
700
  seenSlug.add(slug);
701
+ if (lane.transport === 'openai-http')
702
+ httpSlugs.add(slug);
692
703
  const flags = Array.isArray(lane.flags) ? lane.flags : [];
693
704
  for (const flag of flags) {
694
705
  if (typeof flag !== 'string')
@@ -740,6 +751,28 @@ function checkReviewerLaneParity(input) {
740
751
  for (const slug of markerSlugs.keys()) {
741
752
  add(exports.PARITY_VIOLATION.BESPOKE_LEG_PRESENT, slug);
742
753
  }
754
+ // --- the availability call's `||` fallback must name exactly the openai-http lanes ---
755
+ //
756
+ // review.md prints these rows only when an older gsd-tools lacks `review-lane availability`, so
757
+ // they are a second hand-kept copy of the roster. Checked only when the call is present.
758
+ // Anchored to the command position so a comment or prose mention cannot shadow the real call;
759
+ // a missing call is itself a violation (otherwise deleting it would silently skip this check).
760
+ const availabilityLine = (0, text_lines_cjs_1.splitLines)(workflowText).find((line) => AVAILABILITY_CALL_RE.test(line));
761
+ if (availabilityLine === undefined) {
762
+ add(exports.PARITY_VIOLATION.AVAILABILITY_FALLBACK_MISMATCH, 'no-call');
763
+ }
764
+ else {
765
+ if (!availabilityLine.includes('review-lane availability ||')) {
766
+ add(exports.PARITY_VIOLATION.AVAILABILITY_FALLBACK_MISMATCH, 'no-fallback');
767
+ }
768
+ const fallback = new Set(Array.from(availabilityLine.matchAll(AVAILABILITY_FALLBACK_ROW_RE), (m) => m[1]));
769
+ for (const slug of fallback)
770
+ if (!httpSlugs.has(slug))
771
+ add(exports.PARITY_VIOLATION.AVAILABILITY_FALLBACK_MISMATCH, slug);
772
+ for (const slug of httpSlugs)
773
+ if (!fallback.has(slug))
774
+ add(exports.PARITY_VIOLATION.AVAILABILITY_FALLBACK_MISMATCH, slug);
775
+ }
743
776
  return { ok: violations.length === 0, violations };
744
777
  }
745
778
  /* ------------------------------------------------------------------ *
@@ -31,6 +31,7 @@ exports.resolveTimeoutMs = resolveTimeoutMs;
31
31
  exports.nativeTimeoutToken = nativeTimeoutToken;
32
32
  exports.isEmptyReview = isEmptyReview;
33
33
  exports.fileRefPrompt = fileRefPrompt;
34
+ exports.applyPromptOverride = applyPromptOverride;
34
35
  exports.artifactPaths = artifactPaths;
35
36
  exports.resolveLaneBudget = resolveLaneBudget;
36
37
  exports.resolveLanePlan = resolveLanePlan;
@@ -229,6 +230,45 @@ function fileRefPrompt(promptPath, repoRoot) {
229
230
  `review request against that absolute root. Output only the resulting markdown review. ` +
230
231
  `Do not edit any files.`);
231
232
  }
233
+ /**
234
+ * Re-point a resolved plan at a different prompt file (`review-lane invoke --prompt-file`, #5049).
235
+ *
236
+ * The override carries a budget-trimmed prompt, so it has to land wherever THIS lane actually
237
+ * reads its prompt, and that differs by channel:
238
+ * - `stdin`: the runner streams the file `plan.stdin` names.
239
+ * - `argv-file-ref`: the prompt PATH is embedded in a sentence in argv (`fileRefPrompt`), already
240
+ * expanded by the time an override can run. Swapping `plan.promptPath` alone changes nothing
241
+ * the CLI reads, which is how the override was dropped silently for cursor, antigravity and
242
+ * kimi-code.
243
+ * - `argv`: the bare path is an argv element.
244
+ * - `openai-http`: the runner reads `plan.promptPath`.
245
+ * Argv elements are matched whole (the file-ref sentence, or the bare path), never by substring,
246
+ * so an unrelated argument that merely contains the path is left alone. `promptPath` moves with
247
+ * argv: the antigravity handler re-derives the sentence it swaps from `plan.promptPath` and would
248
+ * otherwise stop recognising it. A plan that takes no prompt (`none`) is returned unchanged.
249
+ * Pure: returns a new plan and never mutates the one it is given.
250
+ */
251
+ function applyPromptOverride(plan, promptPath, repoRoot) {
252
+ if (plan.transport !== 'spawn')
253
+ return { ...plan, promptPath };
254
+ if (plan.stdin)
255
+ return { ...plan, stdin: promptPath, promptPath };
256
+ const oldRef = fileRefPrompt(plan.promptPath, repoRoot);
257
+ const newRef = fileRefPrompt(promptPath, repoRoot);
258
+ let replaced = false;
259
+ const argv = plan.argv.map((a) => {
260
+ if (a === oldRef) {
261
+ replaced = true;
262
+ return newRef;
263
+ }
264
+ if (a === plan.promptPath) {
265
+ replaced = true;
266
+ return promptPath;
267
+ }
268
+ return a;
269
+ });
270
+ return replaced ? { ...plan, argv, promptPath } : plan;
271
+ }
232
272
  /** Run-dir artifact paths. POSIX-joined: these are workflow-visible strings, not OS paths. */
233
273
  function artifactPaths(runDir, slug) {
234
274
  const base = String(runDir ?? '').replace(/\/+$/, '');
@@ -32,6 +32,7 @@ exports.parseModelBanner = parseModelBanner;
32
32
  exports.parseTranscriptModel = parseTranscriptModel;
33
33
  exports.checkEgressHost = checkEgressHost;
34
34
  exports.probeLane = probeLane;
35
+ exports.probeHttpLanes = probeHttpLanes;
35
36
  exports.writeReviewOrStub = writeReviewOrStub;
36
37
  exports.emptyOutputDiagnosis = emptyOutputDiagnosis;
37
38
  exports.handleOpencodeOutput = handleOpencodeOutput;
@@ -318,14 +319,18 @@ async function probeLane(plan, deps) {
318
319
  // Only a STRING config value names a host. `String(unknown)` would turn an object into the
319
320
  // literal '[object Object]' and probe that as a URL — a nonsense destination reported as
320
321
  // "unreachable" rather than as the misconfiguration it is.
322
+ // For openai-http, `plan.host` is already resolved by `resolveLanePlan` (config → default,
323
+ // unset sentinels like "null" handled) — probe the destination the run would use.
321
324
  const configured = deps.configGet(probe.hostConfigKey);
322
- const base = (0, review_lane_invocation_cjs_1.normalizeHost)((typeof configured === 'string' ? configured : '') ||
323
- (plan.transport === 'openai-http' ? plan.host : ''));
325
+ const base = (0, review_lane_invocation_cjs_1.normalizeHost)((plan.transport === 'openai-http' ? plan.host : '') || (typeof configured === 'string' ? configured : ''));
324
326
  if (!base) {
325
327
  return { available: false, reason: review_lane_invocation_cjs_1.LANE_UNAVAILABLE.HOST_UNREACHABLE, detail: 'no host resolved' };
326
328
  }
327
- const r = await deps.httpJson(`${base}${probe.path}`, { method: 'GET', timeoutMs: probe.timeoutMs });
328
- return r.ok
329
+ // D7: reachable ⇒ available. Any HTTP answer (401 behind an auth proxy, 404, 3xx) proves a
330
+ // server is there; only a transport failure (status 0) does not. Redirects are not followed:
331
+ // a probe must not issue a request to a host the descriptor never named.
332
+ const r = await deps.httpJson(`${base}${probe.path}`, { method: 'GET', timeoutMs: probe.timeoutMs, probe: true });
333
+ return r.status > 0
329
334
  ? { available: true }
330
335
  : {
331
336
  available: false,
@@ -341,6 +346,25 @@ async function probeLane(plan, deps) {
341
346
  };
342
347
  }
343
348
  }
349
+ /**
350
+ * `<slug>:available|missing` rows for the openai-http lanes in `lanes` (all, or those in `selected`).
351
+ * Prerequisite binaries are not folded in: the caller reports `jq` separately. An unresolvable lane
352
+ * reads `missing` and its reason is returned in `warnings` rather than swallowed.
353
+ */
354
+ async function probeHttpLanes(lanes, selected, resolve, deps) {
355
+ // Probes run concurrently (each has its own timeout); Promise.all keeps descriptor order, and
356
+ // warnings are collected from the results afterwards so their order never depends on resolve timing.
357
+ const results = await Promise.all(lanes
358
+ .filter((l) => l.transport === 'openai-http' && (selected.length === 0 || selected.includes(l.slug)))
359
+ .map(async (lane) => {
360
+ const r = resolve(lane);
361
+ const up = r.ok && (await probeLane({ ...r.plan, requiresBinaries: [] }, deps)).available;
362
+ return { row: `${lane.slug}:${up ? 'available' : 'missing'}`, warning: r.ok ? null : `${lane.slug}: ${r.detail}` };
363
+ }));
364
+ const rows = results.map((x) => x.row);
365
+ const warnings = results.flatMap((x) => (x.warning === null ? [] : [x.warning]));
366
+ return { rows, warnings };
367
+ }
344
368
  /* ------------------------------------------------------------------ *
345
369
  * Empty-output policy (#2494 / #2605 / #2794)
346
370
  * ------------------------------------------------------------------ */
@@ -940,6 +964,11 @@ async function runOpenAiCompatible(plan, promptText, deps) {
940
964
  let model = plan.model;
941
965
  if (!model && plan.modelsUrl) {
942
966
  const listed = await deps.httpJson(plan.modelsUrl, { method: 'GET', timeoutMs: 2_000 });
967
+ // A redirect is a lane failure, not "discovery found nothing" (#5433): the host answered with
968
+ // somewhere else to go, so the configured URL is wrong and the completions request would be too.
969
+ if (listed.status >= 300 && listed.status < 400 && listed.error) {
970
+ return { review: '', rawBody: listed.error, model: recordedModel(plan.fallbackModel, exports.MODEL_SOURCE.REQUESTED) };
971
+ }
943
972
  if (listed.ok) {
944
973
  try {
945
974
  const parsed = JSON.parse(listed.body);
@@ -113,6 +113,22 @@ exports.KNOWN_REVIEWER_SLUGS = (() => {
113
113
  return [];
114
114
  }
115
115
  })();
116
+ /**
117
+ * #5359: map a lane flag alias (`agy` for `--agy`) to its canonical slug via the
118
+ * descriptor roster's declared `flags` (same source as `review-lane explicit-from-argv`).
119
+ * Guarded like KNOWN_REVIEWER_SLUGS: a load failure degrades to the plain error.
120
+ */
121
+ function laneSlugForAlias(name, lanes) {
122
+ try {
123
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
124
+ const roster = lanes ?? require('./review-lane-descriptor.cjs').REVIEWER_LANES;
125
+ // `l.slug !== name`: an undetected canonical slug (`--codex` flag) is not an alias.
126
+ return roster.find((l) => l.slug !== name && l.flags.includes(`--${name}`))?.slug;
127
+ }
128
+ catch {
129
+ return undefined;
130
+ }
131
+ }
116
132
  /** Instance names are lowercase slugs that must not shadow a built-in slug. */
117
133
  exports.INSTANCE_NAME_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
118
134
  function normalizeConfiguredDefaultReviewers(rawValue) {
@@ -239,7 +255,10 @@ function resolveReviewerSelection(input) {
239
255
  // Sorted so the error order does not depend on flag order on the command line.
240
256
  const missing = [...explicitFlags].filter((slug) => !detected.has(slug)).sort();
241
257
  for (const slug of missing) {
242
- errors.push(`explicit reviewer '${slug}' is not available on this host`);
258
+ const canonical = laneSlugForAlias(slug, input.lanes);
259
+ errors.push(canonical
260
+ ? `explicit reviewer '${slug}' is a flag alias; pass its canonical slug '${canonical}'`
261
+ : `explicit reviewer '${slug}' is not available on this host`);
243
262
  }
244
263
  // Guarded on the error count as it stood BEFORE this branch, so the
245
264
  // aggregate message fires under exactly the conditions it did previously.
@@ -78,6 +78,17 @@ function isClosedMilestoneHeading(headingText) {
78
78
  function stripShippedMilestones(content) {
79
79
  return (0, markdown_sectionizer_cjs_1.stripTaggedBlocks)(content, 'details');
80
80
  }
81
+ /**
82
+ * #5543: run `edit` over the ROADMAP with every shipped `<details>` block hidden
83
+ * and restored byte-for-byte afterwards. For writers whose active milestone
84
+ * could not be resolved: the first `### Phase N:` in document order must never
85
+ * be the one inside a shipped block. Layout-independent (the active phase may
86
+ * sit before or after a shipped block) and, unlike a "region after the last
87
+ * `</details>`" cut, not fooled by a `</details>` in a fence or inline code.
88
+ */
89
+ function editOutsideShippedBlocks(content, edit) {
90
+ return (0, markdown_sectionizer_cjs_1.editOutsideTaggedBlocks)(content, 'details', edit);
91
+ }
81
92
  /**
82
93
  * #3982: strip only <details> blocks whose <summary> marks a CLOSED milestone
83
94
  * (ARCHIVED/SHIPPED/✅/… without an active marker) — the narrow form of
@@ -2287,6 +2298,7 @@ module.exports = {
2287
2298
  getMilestonePhaseFilter,
2288
2299
  currentMilestoneRawRanges,
2289
2300
  withPhaseSection,
2301
+ editOutsideShippedBlocks,
2290
2302
  computeMilestoneSectionEnd,
2291
2303
  locateMilestoneHeadings,
2292
2304
  listMilestoneHeadings,
@@ -12,7 +12,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  };
13
13
  const node_fs_1 = __importDefault(require("node:fs"));
14
14
  const node_path_1 = __importDefault(require("node:path"));
15
- const node_child_process_1 = require("node:child_process");
16
15
  const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
17
16
  // eslint-disable-next-line @typescript-eslint/no-require-imports
18
17
  const planningWorkspace = require("./planning-workspace.cjs");
@@ -1923,7 +1922,45 @@ function applyMigration(cwd, plan, options = {}) {
1923
1922
  // ── Real run: verify clean working tree ───────────────────────────────────
1924
1923
  let gitStatus;
1925
1924
  try {
1926
- gitStatus = (0, node_child_process_1.execSync)('git status --porcelain', { cwd, encoding: 'utf8', windowsHide: true, timeout: 10_000 });
1925
+ // #5048: this is a read-only spawn, but git still refreshes the index under
1926
+ // it and takes the optional `.git/index.lock` to write the refreshed copy
1927
+ // back — which can lose a race against a real `git add` / `git commit` in
1928
+ // the same repo. Routing through the shared execGit seam (CONTEXT.md, OS
1929
+ // Shell Projection) is what gets GIT_OPTIONAL_LOCKS=0 here; a bare execSync
1930
+ // bypassed the seam and therefore the opt-out, so this call site was the one
1931
+ // read-only `git status` the seam change did not reach. shell-free, so no
1932
+ // argv quoting or PATH-resolution policy is introduced.
1933
+ const statusTimeoutMs = 10_000;
1934
+ const result = (0, shell_command_projection_cjs_1.execGit)(['status', '--porcelain'], { cwd, timeout: statusTimeoutMs });
1935
+ // #5048: execSync carried the cause on the thrown error. execGit reports a
1936
+ // timeout, a spawn/buffer failure or a signal through `timedOut`/`error`/
1937
+ // `signal` with an exit code of `status ?? 1` and often an empty stderr.
1938
+ // Order matters: a maxBuffer overflow returns signal SIGTERM *and*
1939
+ // error.code ENOBUFS — check `error` before `signal` so the real cause is
1940
+ // not reported as "killed by SIGTERM". Only a genuine non-zero exit falls
1941
+ // through. (ENOENT is rewritten by `_spawnResult` to exit 127 + stderr.)
1942
+ if (result.timedOut) {
1943
+ throw new Error(`git status timed out after ${statusTimeoutMs} ms`);
1944
+ }
1945
+ if (result.error) {
1946
+ // The cause is not always a failed spawn: ENOBUFS and EPERM reach this
1947
+ // branch with the process already started (a maxBuffer overflow returns
1948
+ // signal SIGTERM *and* error.code ENOBUFS). So the message stays neutral
1949
+ // about starting and names the code instead of inferring a cause from it.
1950
+ const code = result.error.code;
1951
+ const why = code === 'ENOBUFS' ? 'output exceeded the buffer' : code;
1952
+ const detail = why && !result.error.message.includes(why)
1953
+ ? `${result.error.message} (${why})`
1954
+ : result.error.message;
1955
+ throw new Error(detail);
1956
+ }
1957
+ if (result.signal) {
1958
+ throw new Error(`git status was killed by ${result.signal}`);
1959
+ }
1960
+ if (result.exitCode !== 0) {
1961
+ throw new Error(result.stderr || `git exited ${result.exitCode}`);
1962
+ }
1963
+ gitStatus = result.stdout;
1927
1964
  }
1928
1965
  catch (err) {
1929
1966
  throw new Error(`git status failed: ${err.message}`);