@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
@@ -21,6 +21,8 @@ const gate_phase_context_cjs_1 = require("./gate-phase-context.cjs");
21
21
  const gate_evaluation_scope_cjs_1 = require("./gate-evaluation-scope.cjs");
22
22
  const runtime_slash_cjs_1 = require("./runtime-slash.cjs");
23
23
  const ui_safety_gate_cjs_1 = require("./ui-safety-gate.cjs");
24
+ const ui_frontend_evidence_cjs_1 = require("./ui-frontend-evidence.cjs");
25
+ const gate_evidence_cjs_1 = require("./gate-evidence.cjs");
24
26
  const UI_FILE_EXTENSIONS_RE = /\.(tsx|jsx|css|scss|sass|less|vue|svelte|html)$/i;
25
27
  const UI_PATH_PATTERNS_RE = /\/(components|pages|views|screens|layouts|ui|frontend)\//i;
26
28
  /**
@@ -32,7 +34,10 @@ const UI_PATH_PATTERNS_RE = /\/(components|pages|views|screens|layouts|ui|fronte
32
34
  * git call is bounded by the resolver's seam; an unreadable scope is reported, not "clean").
33
35
  * (d) Phase directory → `*-UI-SPEC.md`.
34
36
  *
35
- * `block = frontend && hasUiFiles && !hasUiSpec`.
37
+ * (c') Static frontend evidence (`readStaticFrontendEvidence`, the definition `computeUiPlanGate` uses),
38
+ * probed only for a frontend phase that changed UI files (#5646).
39
+ *
40
+ * `block = frontend && hasUiFiles && hasFrontendEvidence && !hasUiSpec`.
36
41
  */
37
42
  function computeUiSafetyGate(projectDir, phase) {
38
43
  // (a) phase section text (same two-pass lookup as computeUiPlanGate)
@@ -43,14 +48,27 @@ function computeUiSafetyGate(projectDir, phase) {
43
48
  // (c) any UI files in the phase's own commits? (deleted paths count: a removed component is a UI change)
44
49
  const scope = (0, gate_evaluation_scope_cjs_1.resolveEvaluationScope)(projectDir, { kind: 'phase', phase });
45
50
  const hasUiFiles = scope.changedFiles.some((f) => f.trim() && (UI_FILE_EXTENSIONS_RE.test(f) || UI_PATH_PATTERNS_RE.test(f)));
51
+ // (c') #5646 — static structural corroboration, the same evidence `computeUiPlanGate` requires (#3312):
52
+ // `hasUiFiles` is a weak signal (an `.html` fixture, or any file under a `ui/` directory in any
53
+ // language), so on its own it halted projects with no frontend that the plan gate had cleared. Only
54
+ // probed when it could change the answer. `unreadable` (#5170) is a manifest or tree the probe could
55
+ // not look at: absence of evidence is then not established, and the verdict says so (below).
56
+ const frontendEvidence = frontend && hasUiFiles ? (0, ui_frontend_evidence_cjs_1.readStaticFrontendEvidence)(projectDir) : (0, gate_evidence_cjs_1.evidenceNone)();
57
+ const hasFrontendEvidence = frontendEvidence.kind === 'found';
46
58
  // (d) phase directory and *-UI-SPEC.md
47
59
  // `none` is "no spec"; `unreadable` is "could not look" (#5170) and is carried to the verdict.
48
60
  const uiSpec = (0, gate_phase_context_cjs_1.locateUiSpec)(projectDir, phase);
49
61
  const hasUiSpec = uiSpec.kind === 'found';
50
- const readError = roadmapReadError ?? (uiSpec.kind === 'unreadable' ? uiSpec.reason : undefined);
51
- // block only when: this is a frontend phase AND UI files were changed AND no UI-SPEC exists
52
- const block = frontend && hasUiFiles && !hasUiSpec;
53
- const result = { frontend, hasUiFiles, hasUiSpec, block };
62
+ // Unreadable frontend evidence only matters when it could flip the verdict: with a UI-SPEC present the
63
+ // gate does not block whatever the tree holds.
64
+ const frontendReadError = frontendEvidence.kind === 'unreadable' && !hasUiSpec
65
+ ? `static frontend evidence could not be read (${frontendEvidence.reason})`
66
+ : undefined;
67
+ const readError = roadmapReadError ?? (uiSpec.kind === 'unreadable' ? uiSpec.reason : undefined) ?? frontendReadError;
68
+ // block only when: this is a frontend phase AND UI files were changed AND the project has static
69
+ // frontend evidence AND no UI-SPEC exists
70
+ const block = frontend && hasUiFiles && hasFrontendEvidence && !hasUiSpec;
71
+ const result = { frontend, hasUiFiles, hasFrontendEvidence, hasUiSpec, block };
54
72
  if (block) {
55
73
  result.message = `UI files changed in this wave but no UI-SPEC.md exists for Phase ${phase}. ` +
56
74
  `Run ${(0, runtime_slash_cjs_1.runtimeCommand)(projectDir, `ui-phase ${phase}`)} to generate the design contract before continuing.`;
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ /**
3
+ * Keep a machine-local file out of `git status` without touching any tracked
4
+ * file: append an anchored entry to the enclosing repo's `info/exclude` (#5551).
5
+ *
6
+ * Used for files GSD writes under `.planning/` that are per-machine state, not
7
+ * project content (the milestone claim). A copy that is already tracked is left
8
+ * alone — an exclude entry never untracks, and migrating it is the user's call.
9
+ *
10
+ * Best-effort by contract: never throws. Ignoring is optional, so no failure
11
+ * here (no git, read-only `.git`, odd path) may perturb the caller.
12
+ */
13
+ var __importDefault = (this && this.__importDefault) || function (mod) {
14
+ return (mod && mod.__esModule) ? mod : { "default": mod };
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.excludeFromGit = excludeFromGit;
18
+ const node_fs_1 = __importDefault(require("node:fs"));
19
+ const node_path_1 = __importDefault(require("node:path"));
20
+ const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
21
+ const text_lines_cjs_1 = require("./text-lines.cjs");
22
+ /** Escape gitignore metacharacters so a directory or file name matches literally. */
23
+ function escapeGitignore(s) {
24
+ return s.replace(/[\\*?[]/g, '\\$&');
25
+ }
26
+ /**
27
+ * Exclude `<dir>/<filename>` from git via the repo-local `info/exclude`.
28
+ * `dir` must already exist (it is the spawn cwd).
29
+ */
30
+ function excludeFromGit(dir, filename) {
31
+ try {
32
+ // gitignore cannot express a newline in a pattern, and git's line output could not be split.
33
+ if (/[\r\n]/.test(dir))
34
+ return;
35
+ // cwd must pick the repo: drop inherited repository-location variables (e.g. inside a git hook).
36
+ const env = { GIT_DIR: undefined, GIT_WORK_TREE: undefined, GIT_INDEX_FILE: undefined, GIT_COMMON_DIR: undefined };
37
+ // The prefix goes last: stdout is trimmed, and a non-empty prefix ends in `/`, so only an
38
+ // empty prefix (dir is the git root) loses its line; a leading space survives.
39
+ const revParse = (0, shell_command_projection_cjs_1.execGit)(['rev-parse', '--git-path', 'info/exclude', '--show-prefix'], {
40
+ cwd: dir,
41
+ env: env,
42
+ });
43
+ const [excludeRel, prefix = ''] = (0, text_lines_cjs_1.splitLines)(String(revParse.stdout));
44
+ if (revParse.exitCode !== 0 || !excludeRel)
45
+ return;
46
+ const exclude = node_path_1.default.resolve(dir, excludeRel);
47
+ const entry = `/${escapeGitignore(prefix)}${escapeGitignore(filename)}`;
48
+ const existing = node_fs_1.default.existsSync(exclude) ? node_fs_1.default.readFileSync(exclude, 'utf8') : '';
49
+ if ((0, text_lines_cjs_1.splitLines)(existing).includes(entry))
50
+ return;
51
+ node_fs_1.default.mkdirSync(node_path_1.default.dirname(exclude), { recursive: true });
52
+ node_fs_1.default.appendFileSync(exclude, (existing && !existing.endsWith('\n') ? '\n' : '') + entry + '\n');
53
+ }
54
+ catch {
55
+ // advisory: see the module header.
56
+ }
57
+ }
@@ -42,7 +42,7 @@
42
42
  */
43
43
  // eslint-disable-next-line @typescript-eslint/no-require-imports
44
44
  const healthDiagnosticMod = require("../health-diagnostic-types.cjs");
45
- const { SEVERITY, adviseRemedy } = healthDiagnosticMod;
45
+ const { SEVERITY, REMEDY_ACTION, REMEDY_RISK, adviseRemedy } = healthDiagnosticMod;
46
46
  // eslint-disable-next-line @typescript-eslint/no-require-imports
47
47
  const validateMod = require("../validate.cjs");
48
48
  // #612: `isPhaseDirName` is the convention-SELECTED shape test wrapping
@@ -57,6 +57,9 @@ const phaseIdMod = require("../phase-id.cjs");
57
57
  const { extractPhaseToken, normalizePhaseName, comparePhaseNum } = phaseIdMod;
58
58
  // #5060: the Phase Status Module owns the status-label ladder.
59
59
  const phase_status_cjs_1 = require("../phase-status.cjs");
60
+ // #5291: W030 asks whether a raw report status has a known repair. The lookup is
61
+ // a pure read of a frozen table, so `check` stays free of ambient I/O (§8.1 rule 1).
62
+ const verification_cjs_1 = require("../verification.cjs");
60
63
  // ─── W005 — phase directory doesn't follow NN-name format (verify.cts:1893-1902) ─
61
64
  function checkW005(snapshot) {
62
65
  const diagnostics = [];
@@ -174,11 +177,21 @@ function checkW030(snapshot) {
174
177
  const invalid = phase.verificationStatusError;
175
178
  if (!invalid)
176
179
  continue;
180
+ // #5291: a KNOWN legacy status is repairable (rewritten to its closed-set
181
+ // equivalent, original kept in `legacy_status`); any other value has no
182
+ // mapping and keeps the advise-only remedy — it stays refused.
183
+ const target = (0, verification_cjs_1.legacyStatusRepairTarget)(invalid.rawStatus);
177
184
  diagnostics.push({
178
185
  code: 'W030',
179
186
  severity: SEVERITY.WARNING,
180
187
  message: `Phase ${phase.dir}: ${invalid.message}`,
181
- remedy: adviseRemedy('Set the report frontmatter `status` to one of passed | gaps_found | human_needed, or delete the report and re-run the phase verification'),
188
+ remedy: target === null
189
+ ? adviseRemedy('Set the report frontmatter `status` to one of passed | gaps_found | human_needed, or delete the report and re-run the phase verification')
190
+ : {
191
+ action: REMEDY_ACTION.REPAIR_VERIFICATION_STATUS,
192
+ risk: REMEDY_RISK.NONE,
193
+ args: { file: invalid.file, from: invalid.rawStatus, to: target },
194
+ },
182
195
  });
183
196
  }
184
197
  return diagnostics;
@@ -217,7 +230,9 @@ const RULES = [
217
230
  code: 'W030',
218
231
  severity: SEVERITY.WARNING,
219
232
  description: 'Phase verification report status is outside the closed set',
220
- repairable: false,
233
+ // #5291: repairable per finding — a KNOWN legacy status (`pass_with_caveats`)
234
+ // is rewritten by `--repair`; any other value stays advise-only.
235
+ repairable: true,
221
236
  check: checkW030,
222
237
  },
223
238
  ];
@@ -38,6 +38,10 @@ const REMEDY_ACTION = Object.freeze({
38
38
  ADD_NYQUIST_KEY: 'addNyquistKey',
39
39
  ADD_AI_INTEGRATION_PHASE_KEY: 'addAiIntegrationPhaseKey',
40
40
  BACKFILL_MILESTONES: 'backfillMilestones',
41
+ // #5291: rewrite a KNOWN legacy verification `status` (W030) to its closed-set
42
+ // equivalent, keeping the original in `legacy_status`. Per-finding: only
43
+ // emitted when the raw value has a mapping; every other W030 stays ADVISE.
44
+ REPAIR_VERIFICATION_STATUS: 'repairVerificationStatus',
41
45
  // §8.3 rule 5 — every non-repairable finding's `fix` string becomes an
42
46
  // ADVISE payload; ADVISE never acts, only describes.
43
47
  ADVISE: 'advise',
@@ -118,6 +118,9 @@ const { getMilestoneInfo } = roadmapParserMod;
118
118
  const stateMod = require("./state.cjs");
119
119
  const { writeStateMd, assertVerificationReportsReadable } = stateMod;
120
120
  // eslint-disable-next-line @typescript-eslint/no-require-imports
121
+ const verificationMod = require("./verification.cjs");
122
+ const { repairLegacyVerificationStatus } = verificationMod;
123
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
121
124
  const frontmatter = require("./frontmatter.cjs");
122
125
  const { extractFrontmatter } = frontmatter;
123
126
  // eslint-disable-next-line @typescript-eslint/no-require-imports
@@ -252,9 +255,27 @@ function computeMissingMilestoneVersions(milestonesArchiveDir, milestonesPath) {
252
255
  * shape, collapsed to one seam here since every case now shares one
253
256
  * caller).
254
257
  */
255
- function runRepairAction(cwd, action, paths) {
258
+ function runRepairAction(cwd, action, paths, args = {}) {
256
259
  const { rootBase, configPath, statePath, milestonesPath, milestonesArchiveDir } = paths;
257
260
  switch (action) {
261
+ case REMEDY_ACTION.REPAIR_VERIFICATION_STATUS: {
262
+ // #5291: the report path comes from the finding's own remedy args, not
263
+ // from user input; `repairLegacyVerificationStatus` re-verifies that it is
264
+ // a report contained in its phase directory before it writes a byte.
265
+ const file = typeof args['file'] === 'string' ? args['file'] : '';
266
+ if (file === '')
267
+ return { success: false, error: 'no report path on the finding' };
268
+ const repaired = repairLegacyVerificationStatus(file);
269
+ if (!repaired.ok)
270
+ return { success: false, error: repaired.reason };
271
+ return {
272
+ success: true,
273
+ path: node_path_1.default.relative(cwd, file).split(node_path_1.default.sep).join('/'),
274
+ detail: repaired.legacyStatusKept
275
+ ? `status ${repaired.from} -> ${repaired.to}; the report's existing legacy_status was left as it was`
276
+ : `status ${repaired.from} -> ${repaired.to}; original kept as legacy_status`,
277
+ };
278
+ }
258
279
  case REMEDY_ACTION.CREATE_CONFIG:
259
280
  case REMEDY_ACTION.RESET_CONFIG: {
260
281
  (0, shell_command_projection_cjs_1.platformWriteSync)(configPath, JSON.stringify(defaultConfigPayload(), null, 2));
@@ -390,6 +411,34 @@ function applyRepairs(cwd, diagnostics, repair, backfill) {
390
411
  const refused = [];
391
412
  const details = [];
392
413
  const paths = repairPaths(cwd);
414
+ // #5291: a legacy-status repair is the CURE for the refusal the pre-check
415
+ // below enforces, so it runs first (a report edit is its only write and it
416
+ // validates its own target); the pre-check then sees the repaired reports.
417
+ const statusRepairs = new Set();
418
+ if (repair) {
419
+ for (const diagnostic of diagnostics) {
420
+ const { remedy, code } = diagnostic;
421
+ if (remedy.action !== REMEDY_ACTION.REPAIR_VERIFICATION_STATUS || remedy.risk === REMEDY_RISK.DESTRUCTIVE)
422
+ continue;
423
+ statusRepairs.add(diagnostic);
424
+ try {
425
+ const outcome = runRepairAction(cwd, remedy.action, paths, remedy.args);
426
+ details.push({
427
+ code,
428
+ action: remedy.action,
429
+ success: outcome.success,
430
+ ...(outcome.path ? { path: outcome.path } : {}),
431
+ ...(outcome.detail ? { detail: outcome.detail } : {}),
432
+ ...(outcome.error ? { error: outcome.error } : {}),
433
+ });
434
+ if (outcome.success)
435
+ applied.push(code);
436
+ }
437
+ catch (err) {
438
+ details.push({ code, action: remedy.action, success: false, error: err instanceof Error ? err.message : String(err) });
439
+ }
440
+ }
441
+ }
393
442
  // #5118 (no write before the error): a requested REGENERATE_STATE rewrites
394
443
  // STATE.md from every phase's report and throws on one whose `status` is
395
444
  // outside the closed set — but other repairs in the SAME run (config,
@@ -411,6 +460,8 @@ function applyRepairs(cwd, diagnostics, repair, backfill) {
411
460
  const { remedy, code } = diagnostic;
412
461
  if (remedy.action === REMEDY_ACTION.ADVISE)
413
462
  continue;
463
+ if (statusRepairs.has(diagnostic))
464
+ continue;
414
465
  const requested = remedy.action === REMEDY_ACTION.BACKFILL_MILESTONES ? repair || backfill : repair;
415
466
  if (!requested)
416
467
  continue;
@@ -620,7 +620,7 @@ function hookEventSurfaceFor(hookEvents) {
620
620
  // event subset (imperative hosts' extension API). They are not the same thing.
621
621
  //
622
622
  // Values are documentation-sourced (ADR-1239 §research): OpenCode ~25 plugin
623
- // events (session/tool/file/permission); pi ~30 fine-grained extension events;
623
+ // events (session/tool/file/permission); pi 41 fine-grained extension events (pi 1.3.0);
624
624
  // 'none' = the host exposes no extension surface and the engine owns the bus
625
625
  // (VS Code). Declarative hosts (no plugin API) do not set `extensionEvents`.
626
626
  // OpenCode's plugin event surface (ADR-1239 §research; ~25 documented events,
@@ -655,11 +655,13 @@ const EXTENSION_EVENT_SURFACES = Object.freeze({
655
655
  'pre_gateway_dispatch', 'pre_approval_request',
656
656
  'transform_tool_result',
657
657
  ]),
658
- // #2102 Stage 2 — pi's real ExtensionAPI event vocabulary (~30 fine-grained
659
- // extension events; documentation-sourced, ADR-1239 §research). Replaces the
660
- // placeholder single-event ['tool_call'] surface — the Stage 1 value only
661
- // covered the one event pi/gsd.cjs happened to bind at the time, not the
662
- // full declared surface.
658
+ // pi's real ExtensionAPI event vocabulary: the 41 `on(event: "...")` overloads
659
+ // declared by pi 1.3.0 (@earendil-works/pi-coding-agent
660
+ // dist/core/extensions/types.d.ts, sourceCommit 71023aec15, #5557). #2102
661
+ // Stage 2 declared the first 30 from pi.dev prose; the last 11 on the final
662
+ // row group were added when the host's own declarations were read. The
663
+ // pi.dev extensions page lists a lossy subset (it omits session_before_compact,
664
+ // which pi/gsd.cjs binds), so the type declarations are the source of truth.
663
665
  pi: Object.freeze([
664
666
  'session_start', 'project_trust', 'resources_discover', 'input',
665
667
  'before_agent_start', 'agent_start', 'message_start', 'message_update',
@@ -669,6 +671,11 @@ const EXTENSION_EVENT_SURFACES = Object.freeze({
669
671
  'session_before_switch', 'session_shutdown', 'session_before_fork',
670
672
  'session_info_changed', 'session_before_compact', 'session_compact',
671
673
  'session_before_tree', 'session_tree', 'thinking_level_select', 'model_select',
674
+ // Added in pi 1.3.0 (#5557):
675
+ 'agent_before_settle', 'agent_settled', 'before_provider_headers',
676
+ 'cache_warming_decision', 'context_with_system', 'mcp_servers_change',
677
+ 'provider_stream_event', 'session_compact_failed', 'ui_prompt_end',
678
+ 'ui_prompt_start', 'user_bash',
672
679
  ]),
673
680
  none: Object.freeze([]),
674
681
  });
@@ -20,6 +20,8 @@ const markdown_sectionizer_cjs_1 = require("./markdown-sectionizer.cjs");
20
20
  const io = require("./io.cjs");
21
21
  // eslint-disable-next-line @typescript-eslint/no-require-imports -- config-loader.cjs is an export= CommonJS module
22
22
  const configLoader = require("./config-loader.cjs");
23
+ // eslint-disable-next-line @typescript-eslint/no-require-imports -- capability-ledger.cjs is an export= CommonJS module
24
+ const capabilityLedger = require("./capability-ledger.cjs");
23
25
  const project_root_cjs_1 = require("./project-root.cjs");
24
26
  // eslint-disable-next-line @typescript-eslint/no-require-imports -- model-resolver.cjs is an export= CommonJS module
25
27
  const modelResolver = require("./model-resolver.cjs");
@@ -96,7 +98,7 @@ const { getRoadmapPhaseInternal, getMilestoneInfo, stripShippedMilestones, extra
96
98
  const { pathExistsInternal, generateSlugInternal, toPosixPath } = coreUtils;
97
99
  const { comparePhaseNum, normalizePhaseName, stripProjectCodePrefix, PHASE_NUMBER_TOKEN_SOURCE, PHASE_DEP_REF_SOURCE, isForeignPrefixedPhaseQuery, isSentinelPhaseId, extractPhaseToken, scopeToPhase, renderPhaseBranchName, parsePhaseId, renderPhaseId, phaseHeadingPrefixSrcFor, PHASE_HEADING_BASELINE, buildPhaseHeadingScanRegex, } = phaseId;
98
100
  const { pruneOrphanedWorktrees } = worktreeSafety;
99
- const { planningPaths, planningDir, planningRoot, todosDir, listAvailableWorkstreams, peekActiveWorkstream, resolveEnvWorkstream, diagnoseUnresolvedActiveWorkstream, describeUnresolvedWorkstreamReason, findContextMdIn, resolvePhaseIdConvention, worktreesOptedOut, } = planningWorkspace;
101
+ const { planningPaths, planningDir, planningRoot, todosDir, listAvailableWorkstreams, peekActiveWorkstream, resolveEnvWorkstream, diagnoseUnresolvedActiveWorkstream, describeUnresolvedWorkstreamReason, findContextMdIn, findPhaseSpecIn, resolvePhaseIdConvention, worktreesOptedOut, } = planningWorkspace;
100
102
  const { extractFrontmatter, frontmatterBlock } = frontmatterMod;
101
103
  const { isPhaseComplete, resolveVerificationFile, resolveUatFile, VERIFICATION_STATUS, VerificationStatusError } = verificationMod;
102
104
  const { evaluateUatPassed } = uatPredicateMod;
@@ -175,6 +177,28 @@ function resolvePhaseDisplayName(phaseInfo, roadmapPhase) {
175
177
  || phaseInfo?.['phase_name']
176
178
  || null;
177
179
  }
180
+ /**
181
+ * #5629: the phase SPEC as init facts, for every init payload a SPEC-consuming workflow parses
182
+ * (discuss-phase via `phase-op`, discuss-phase-assumptions, plan-phase). `has_spec` is always present;
183
+ * `spec_path` (absolute, posix) only when a plain `NN-SPEC.md` exists. One predicate (`findPhaseSpecIn`, shared
184
+ * with the context-drift gate) decides, so a UI-SPEC or AI-SPEC is never mistaken for the requirements lock and
185
+ * no workflow globs for it. A phase with no directory yet, or one that cannot be read, has no SPEC.
186
+ */
187
+ function phaseSpecFacts(phaseDirAbs) {
188
+ if (!phaseDirAbs)
189
+ return { has_spec: false };
190
+ let files;
191
+ try {
192
+ files = node_fs_1.default.readdirSync(phaseDirAbs);
193
+ }
194
+ catch {
195
+ return { has_spec: false };
196
+ }
197
+ // Scoped to THIS phase's own artifacts first (#3511), like the sibling artifact lookups: a misfiled
198
+ // `02-SPEC.md` in phase 03's directory must not win (the context-drift gate scopes the same way).
199
+ const spec = findPhaseSpecIn(scopeToPhase(files, node_path_1.default.basename(phaseDirAbs)));
200
+ return spec ? { has_spec: true, spec_path: toPosixPath(node_path_1.default.join(phaseDirAbs, spec)) } : { has_spec: false };
201
+ }
178
202
  /**
179
203
  * #2994 (review finding, DEFECT.GENERATIVE-FIX): shared archived/not-found
180
204
  * fallback applied identically by `cmdInitExecutePhase`, `cmdInitPlanPhase`,
@@ -598,6 +622,28 @@ function detectFallowConfig(cwd) {
598
622
  function detectGitCreateTag(cwd) {
599
623
  return readConfigJsonValue(cwd, ['git', 'create_tag']) !== false;
600
624
  }
625
+ /**
626
+ * `git.repo_tagging` ground truth (#5706, epic #3628): the milestone tagging
627
+ * mode exposed to `complete-milestone.md`. Only the documented `per_repo`
628
+ * opts in; an absent key or any other stored value reads as the default
629
+ * `single` (today's behavior), matching `loadConfig`'s resolution.
630
+ */
631
+ function detectRepoTagging(cwd) {
632
+ return readConfigJsonValue(cwd, ['git', 'repo_tagging']) === 'per_repo' ? 'per_repo' : 'single';
633
+ }
634
+ /**
635
+ * The configured `planning.sub_repos` (#5706): an array of non-empty repo
636
+ * names, possibly empty. A legacy top-level `sub_repos` is honored when the
637
+ * nested key is absent, the same flat-then-nested order `loadConfig` applies.
638
+ * Non-string members are dropped; any degraded read yields `[]`.
639
+ */
640
+ function detectSubRepos(cwd) {
641
+ const nested = readConfigJsonValue(cwd, ['planning', 'sub_repos']);
642
+ const raw = nested !== undefined ? nested : readConfigJsonValue(cwd, ['sub_repos']);
643
+ if (!Array.isArray(raw))
644
+ return [];
645
+ return raw.filter((name) => typeof name === 'string' && name.trim() !== '');
646
+ }
601
647
  /**
602
648
  * `state:phase-mvp-mode` ground truth (design doc §Behavior table: ROADMAP.md
603
649
  * `**Mode:** mvp` for the CURRENT phase). Bounded, non-throwing — an absent
@@ -1137,6 +1183,8 @@ function cmdInitPlanPhase(cwd, phase, raw, options = {}) {
1137
1183
  state_path: node_fs_1.default.existsSync(statePath) ? toPosixPath(statePath) : null,
1138
1184
  roadmap_path: node_fs_1.default.existsSync(roadmapPath) ? toPosixPath(roadmapPath) : null,
1139
1185
  requirements_path: node_fs_1.default.existsSync(requirementsPath) ? toPosixPath(requirementsPath) : null,
1186
+ // #5629: the phase SPEC (plan-phase lifts its Edge Coverage from it; no workflow globs for it).
1187
+ ...phaseSpecFacts(phaseInfo?.['directory'] ? node_path_1.default.join(cwd, phaseInfo['directory']) : null),
1140
1188
  patterns_path: null,
1141
1189
  };
1142
1190
  if (phaseInfo?.['directory']) {
@@ -1932,6 +1980,8 @@ function cmdInitDiscussPhaseAssumptions(cwd, phase, raw, options = {}) {
1932
1980
  plan_count: phaseInfo?.['plans']?.length || 0,
1933
1981
  roadmap_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
1934
1982
  planning_exists: node_fs_1.default.existsSync(planningDir(cwd)),
1983
+ // #5629: the phase SPEC, so assumptions mode honours it like the default flow does.
1984
+ ...phaseSpecFacts(phaseDir ? node_path_1.default.join(cwd, phaseDir) : null),
1935
1985
  };
1936
1986
  // #2994 (Phase 6.3): additive, optional field — degrades to null, never throws.
1937
1987
  const sectionManifestOptions = {
@@ -2063,6 +2113,8 @@ function cmdInitPhaseOp(cwd, phase, raw) {
2063
2113
  state_path: node_fs_1.default.existsSync(statePath) ? toPosixPath(statePath) : null,
2064
2114
  roadmap_path: node_fs_1.default.existsSync(roadmapPath) ? toPosixPath(roadmapPath) : null,
2065
2115
  requirements_path: node_fs_1.default.existsSync(requirementsPath) ? toPosixPath(requirementsPath) : null,
2116
+ // #5629: the phase SPEC (discuss-phase reads it from here; no workflow globs for it).
2117
+ ...phaseSpecFacts(phaseDir ? node_path_1.default.join(cwd, phaseDir) : null),
2066
2118
  };
2067
2119
  if (phaseInfo?.['directory']) {
2068
2120
  const phaseDirFull = node_path_1.default.join(cwd, phaseInfo['directory']);
@@ -3014,9 +3066,23 @@ function cmdInitCompleteMilestone(cwd, raw, options = {}) {
3014
3066
  milestones_path: node_fs_1.default.existsSync(milestonesPath) ? toPosixPath(milestonesPath) : null,
3015
3067
  project_path: node_fs_1.default.existsSync(projectPath) ? toPosixPath(projectPath) : null,
3016
3068
  requirements_path: node_fs_1.default.existsSync(requirementsPath) ? toPosixPath(requirementsPath) : null,
3069
+ // #5706 (epic #3628): the repositories configured for this project and the
3070
+ // milestone tagging mode, so the workflow reads both from one init call.
3071
+ sub_repos: detectSubRepos(cwd),
3072
+ repo_tagging: detectRepoTagging(cwd),
3017
3073
  };
3074
+ // #5195: `state:flat-mode` gates the PROJECT.md evolution review. PROJECT.md
3075
+ // is shared across workstreams (the `projectPath` comment above), so a
3076
+ // workstream's milestone close must not rewrite or stage it — the same
3077
+ // decision `cmdInitNewMilestone` applies to its Part A (#2308), resolved from
3078
+ // the same authority (`GSD_WORKSTREAM` env, else the stored pointer) so the
3079
+ // gate cannot disagree with the workstream-scoped paths returned above.
3080
+ // Read-only peek: no self-heal side effect from building a report field (#3579).
3081
+ const workstreamActive = !!(resolveEnvWorkstream() ?? peekActiveWorkstream(cwd));
3018
3082
  result['section_manifest'] = buildSectionManifestField(cwd, null, options, 'complete-milestone', {
3019
3083
  gitCreateTag,
3084
+ workstreamActive,
3085
+ flatMode: !workstreamActive,
3020
3086
  });
3021
3087
  output(withProjectRoot(cwd, result), raw);
3022
3088
  }
@@ -3773,7 +3839,7 @@ function buildAgentSkillsBlock(config, agentType, projectRoot, diagnostics) {
3773
3839
  }).join('\n');
3774
3840
  return `<agent_skills>\nRead these user-configured skills:\n${lines}\n</agent_skills>`;
3775
3841
  }
3776
- function cmdAgentSkills(cwd, agentType, raw, jsonMode) {
3842
+ function cmdAgentSkills(cwd, agentType, raw, jsonMode, skillsOnly = false) {
3777
3843
  if (!agentType) {
3778
3844
  output('', raw, '');
3779
3845
  return;
@@ -3804,8 +3870,13 @@ function cmdAgentSkills(cwd, agentType, raw, jsonMode) {
3804
3870
  // (a real exit code) instead of a prose config-get gate. Compact is tried
3805
3871
  // first when requested; a missing compact sibling falls back to canonical
3806
3872
  // with the fallback disclosed in the payload itself, never a silent switch.
3873
+ //
3874
+ // #5122: `skillsOnly` (the CLI's `--skills-only`) is the agent's own
3875
+ // self-load. It wants configured skills and nothing else, so it skips the
3876
+ // fallback on every runtime — otherwise a non-Claude agent reads its own
3877
+ // persona back into itself as if it were a skills block.
3807
3878
  let agentPayloadVariant = null;
3808
- if (!block) {
3879
+ if (!block && !skillsOnly) {
3809
3880
  const runtime = (config && config['runtime']) || process.env['GSD_RUNTIME'] || 'claude';
3810
3881
  if (runtime !== 'claude') {
3811
3882
  const agentCheck = checkAgentsInstalled(runtime, projectRoot);
@@ -4071,7 +4142,7 @@ function buildSkillManifest(cwd, skillsDir = null) {
4071
4142
  if (!entry.isDirectory())
4072
4143
  continue;
4073
4144
  const skillMdPath = node_path_1.default.join(rootPath, entry.name, 'SKILL.md');
4074
- const content = (0, shell_command_projection_cjs_1.platformReadSync)(skillMdPath);
4145
+ const content = capabilityLedger.readSkillFile(skillMdPath);
4075
4146
  if (content !== null) {
4076
4147
  if (pushSkillEntry(`${entry.name}/SKILL.md`, content, skillMdPath))
4077
4148
  skillCount++;
@@ -4096,7 +4167,7 @@ function buildSkillManifest(cwd, skillsDir = null) {
4096
4167
  if (!nested.isDirectory())
4097
4168
  continue;
4098
4169
  const nestedSkillMd = node_path_1.default.join(nestedSkillsDir, nested.name, 'SKILL.md');
4099
- const nestedContent = (0, shell_command_projection_cjs_1.platformReadSync)(nestedSkillMd);
4170
+ const nestedContent = capabilityLedger.readSkillFile(nestedSkillMd);
4100
4171
  if (nestedContent === null)
4101
4172
  continue;
4102
4173
  // Use forward-slash separator explicitly so manifest paths are posix-style
@@ -35,7 +35,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
35
35
  */
36
36
  const node_fs_1 = __importDefault(require("node:fs"));
37
37
  const node_path_1 = __importDefault(require("node:path"));
38
- const node_os_1 = __importDefault(require("node:os"));
38
+ const runtime_homes_cjs_1 = require("./runtime-homes.cjs");
39
39
  // eslint-disable-next-line @typescript-eslint/no-require-imports -- install-fs-adapter.cjs is an export= CommonJS module
40
40
  const installFsAdapter = require("./install-fs-adapter.cjs");
41
41
  const { installFs } = installFsAdapter;
@@ -154,7 +154,7 @@ function _findAncestorGsdConfigPath(targetDir) {
154
154
  * @param targetDir Runtime install root (walks up to find .planning/).
155
155
  */
156
156
  function readGsdEffectiveEffortConfig(targetDir = null) {
157
- const homeDefaults = _readGsdConfigFile(node_path_1.default.join(node_os_1.default.homedir(), '.gsd', 'defaults.json'), '~/.gsd/defaults.json');
157
+ const homeDefaults = _readGsdConfigFile(node_path_1.default.join((0, runtime_homes_cjs_1.resolveGsdHome)(), '.gsd', 'defaults.json'), '~/.gsd/defaults.json');
158
158
  let projectConfig = null;
159
159
  if (targetDir) {
160
160
  const candidate = _findAncestorGsdConfigPath(targetDir);