@opengsd/gsd-core 1.18.0 → 1.20.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 (308) 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-code-fixer.compact.md +7 -7
  5. package/agents/gsd-code-fixer.md +13 -7
  6. package/agents/gsd-code-reviewer.compact.md +49 -8
  7. package/agents/gsd-code-reviewer.md +53 -14
  8. package/agents/gsd-executor.md +8 -4
  9. package/agents/gsd-verifier.md +1 -1
  10. package/bin/install.js +422 -103
  11. package/commands/gsd/update.md +5 -2
  12. package/gsd-core/bin/gsd-tools.cjs +179 -30
  13. package/gsd-core/bin/lib/agent-install-check.cjs +29 -3
  14. package/gsd-core/bin/lib/args-terminator.cjs +114 -0
  15. package/gsd-core/bin/lib/broken-windows.cjs +59 -1
  16. package/gsd-core/bin/lib/capability-lifecycle.cjs +1 -12
  17. package/gsd-core/bin/lib/capability-lock.cjs +13 -2
  18. package/gsd-core/bin/lib/capability-registry.cjs +376 -103
  19. package/gsd-core/bin/lib/capability-state.cjs +14 -8
  20. package/gsd-core/bin/lib/capability-validator.cjs +32 -0
  21. package/gsd-core/bin/lib/commands.cjs +27 -17
  22. package/gsd-core/bin/lib/config-loader.cjs +13 -3
  23. package/gsd-core/bin/lib/config.cjs +256 -58
  24. package/gsd-core/bin/lib/core-utils.cjs +45 -0
  25. package/gsd-core/bin/lib/decision-coverage-support.cjs +74 -0
  26. package/gsd-core/bin/lib/frontmatter.cjs +21 -3
  27. package/gsd-core/bin/lib/gate-api-coverage-verify-pre.cjs +2 -2
  28. package/gsd-core/bin/lib/gate-context-drift.cjs +9 -4
  29. package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +6 -1
  30. package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +6 -1
  31. package/gsd-core/bin/lib/gate-evaluation-scope.cjs +134 -13
  32. package/gsd-core/bin/lib/gate-phase-context.cjs +7 -8
  33. package/gsd-core/bin/lib/gate-schema-drift.cjs +1 -1
  34. package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +63 -22
  35. package/gsd-core/bin/lib/gate-ui-safety.cjs +23 -5
  36. package/gsd-core/bin/lib/git-info-exclude.cjs +52 -0
  37. package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +31 -12
  38. package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +9 -7
  39. package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +3 -3
  40. package/gsd-core/bin/lib/health-diagnostic-types.cjs +4 -0
  41. package/gsd-core/bin/lib/health-diagnostic.cjs +52 -1
  42. package/gsd-core/bin/lib/host-integration.cjs +13 -6
  43. package/gsd-core/bin/lib/init.cjs +245 -68
  44. package/gsd-core/bin/lib/install-engine.cjs +246 -32
  45. package/gsd-core/bin/lib/install-profiles.cjs +9 -4
  46. package/gsd-core/bin/lib/installer-migration-report.cjs +2 -0
  47. package/gsd-core/bin/lib/io.cjs +6 -0
  48. package/gsd-core/bin/lib/markdown-line-diff.cjs +147 -0
  49. package/gsd-core/bin/lib/markdown-sectionizer.cjs +147 -1
  50. package/gsd-core/bin/lib/markdown-table.cjs +23 -0
  51. package/gsd-core/bin/lib/mcp-server.cjs +8 -5
  52. package/gsd-core/bin/lib/milestone-lock.cjs +8 -1
  53. package/gsd-core/bin/lib/milestone-release-map.cjs +244 -0
  54. package/gsd-core/bin/lib/milestone-release-tags.cjs +440 -0
  55. package/gsd-core/bin/lib/milestone.cjs +61 -51
  56. package/gsd-core/bin/lib/model-catalog.cjs +8 -0
  57. package/gsd-core/bin/lib/normalize-test-command.cjs +67 -0
  58. package/gsd-core/bin/lib/phase-entry-grammar.cjs +119 -0
  59. package/gsd-core/bin/lib/phase-id-display.cjs +2 -0
  60. package/gsd-core/bin/lib/phase-id.cjs +629 -38
  61. package/gsd-core/bin/lib/phase-lifecycle.cjs +12 -44
  62. package/gsd-core/bin/lib/phase-locator.cjs +328 -19
  63. package/gsd-core/bin/lib/phase.cjs +3066 -653
  64. package/gsd-core/bin/lib/planning-document.cjs +26 -5
  65. package/gsd-core/bin/lib/planning-inspect.cjs +27 -35
  66. package/gsd-core/bin/lib/planning-snapshot.cjs +15 -8
  67. package/gsd-core/bin/lib/planning-workspace.cjs +21 -3
  68. package/gsd-core/bin/lib/pristine-baseline.cjs +11 -3
  69. package/gsd-core/bin/lib/read-only-git-env.cjs +79 -0
  70. package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +2 -2
  71. package/gsd-core/bin/lib/review-lane-descriptor.cjs +57 -2
  72. package/gsd-core/bin/lib/review-lane-invocation.cjs +125 -18
  73. package/gsd-core/bin/lib/review-lane-runner.cjs +33 -4
  74. package/gsd-core/bin/lib/reviewer-step-dispatch.cjs +11 -9
  75. package/gsd-core/bin/lib/roadmap-parser.cjs +735 -137
  76. package/gsd-core/bin/lib/roadmap-progress.cjs +136 -0
  77. package/gsd-core/bin/lib/roadmap-upgrade.cjs +47 -7
  78. package/gsd-core/bin/lib/roadmap.cjs +383 -123
  79. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +381 -14
  80. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +8 -4
  81. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +60 -16
  82. package/gsd-core/bin/lib/shell-command-projection.cjs +151 -19
  83. package/gsd-core/bin/lib/smart-entry.cjs +35 -11
  84. package/gsd-core/bin/lib/state-contract.cjs +39 -15
  85. package/gsd-core/bin/lib/state-document.cjs +344 -27
  86. package/gsd-core/bin/lib/state-transition.cjs +156 -32
  87. package/gsd-core/bin/lib/state.cjs +527 -186
  88. package/gsd-core/bin/lib/surface.cjs +9 -0
  89. package/gsd-core/bin/lib/task-command-router.cjs +5 -25
  90. package/gsd-core/bin/lib/task-content-resolution.cjs +46 -1
  91. package/gsd-core/bin/lib/template.cjs +2 -2
  92. package/gsd-core/bin/lib/validate.cjs +3 -2
  93. package/gsd-core/bin/lib/vendor/re2js.cjs +863 -577
  94. package/gsd-core/bin/lib/vendor/re2js.d.cts +284 -219
  95. package/gsd-core/bin/lib/verification.cjs +96 -9
  96. package/gsd-core/bin/lib/verify.cjs +4 -2
  97. package/gsd-core/bin/lib/workstream-inventory.cjs +26 -20
  98. package/gsd-core/bin/lib/worktree-safety.cjs +22 -1
  99. package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
  100. package/gsd-core/bin/shared/config-schema.manifest.json +1 -0
  101. package/gsd-core/bin/verify-reapply-patches.cjs +411 -10
  102. package/gsd-core/references/cicd-review-patterns.md +45 -0
  103. package/gsd-core/references/git-integration.md +11 -0
  104. package/gsd-core/references/loop-hook-dispatch.md +13 -6
  105. package/gsd-core/references/necessity-review.md +48 -0
  106. package/gsd-core/references/planning-config.md +2 -0
  107. package/gsd-core/references/tdd.md +2 -2
  108. package/gsd-core/templates/DEBUG.md +16 -0
  109. package/gsd-core/templates/config.json +2 -1
  110. package/gsd-core/templates/verification-report.md +1 -1
  111. package/gsd-core/workflows/audit-fix.md +2 -1
  112. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +10 -1
  113. package/gsd-core/workflows/code-review-fix.md +46 -5
  114. package/gsd-core/workflows/code-review.md +64 -7
  115. package/gsd-core/workflows/complete-milestone/steps/project-md-evolution-review.md +145 -0
  116. package/gsd-core/workflows/complete-milestone/steps/release-map.md +80 -0
  117. package/gsd-core/workflows/complete-milestone.md +37 -150
  118. package/gsd-core/workflows/diagnose-issues.md +29 -5
  119. package/gsd-core/workflows/discuss-phase/modes/power.md +1 -1
  120. package/gsd-core/workflows/discuss-phase-assumptions.md +33 -2
  121. package/gsd-core/workflows/discuss-phase-power.md +19 -2
  122. package/gsd-core/workflows/discuss-phase.md +6 -10
  123. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +13 -7
  124. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +7 -2
  125. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -1
  126. package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +2 -2
  127. package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +11 -2
  128. package/gsd-core/workflows/execute-phase.md +10 -6
  129. package/gsd-core/workflows/execute-plan.md +1 -1
  130. package/gsd-core/workflows/health.md +2 -1
  131. package/gsd-core/workflows/import.md +1 -1
  132. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +2 -2
  133. package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +13 -9
  134. package/gsd-core/workflows/plan-phase.md +14 -14
  135. package/gsd-core/workflows/pr-branch.md +2 -0
  136. package/gsd-core/workflows/quick/steps/plan-checker-loop.md +1 -1
  137. package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +8 -1
  138. package/gsd-core/workflows/quick-batch/steps/plan-checker-loop.md +2 -1
  139. package/gsd-core/workflows/quick.md +1 -1
  140. package/gsd-core/workflows/reapply-patches.md +104 -0
  141. package/gsd-core/workflows/review.md +70 -154
  142. package/gsd-core/workflows/section-manifest.json +5 -0
  143. package/gsd-core/workflows/secure-phase.md +1 -1
  144. package/gsd-core/workflows/settings-advanced.md +57 -9
  145. package/gsd-core/workflows/settings.md +1 -0
  146. package/gsd-core/workflows/ship.md +15 -4
  147. package/gsd-core/workflows/spec-phase.md +3 -6
  148. package/gsd-core/workflows/verify-work.md +4 -3
  149. package/hooks/dist/gsd-agent-isolation-guard.js +11 -1
  150. package/hooks/dist/gsd-cursor-subagent-start.js +6 -2
  151. package/hooks/dist/gsd-graphify-update.sh +6 -0
  152. package/hooks/dist/gsd-path-export.js +95 -0
  153. package/hooks/dist/gsd-secret-read-guard.js +172 -39
  154. package/hooks/dist/gsd-statusline.js +37 -3
  155. package/hooks/dist/gsd-windsurf-pre-write.js +29 -2
  156. package/hooks/dist/gsd-workflow-guard.js +3 -2
  157. package/hooks/dist/gsd-worktree-path-guard.js +29 -2
  158. package/hooks/dist/lib/git-probe.js +16 -0
  159. package/hooks/dist/lib/isolation-sentinel.js +44 -0
  160. package/hooks/dist/managed-hooks-registry.cjs +1 -0
  161. package/hooks/gsd-agent-isolation-guard.js +11 -1
  162. package/hooks/gsd-cursor-subagent-start.js +6 -2
  163. package/hooks/gsd-graphify-update.sh +6 -0
  164. package/hooks/gsd-path-export.js +95 -0
  165. package/hooks/gsd-secret-read-guard.js +172 -39
  166. package/hooks/gsd-statusline.js +37 -3
  167. package/hooks/gsd-windsurf-pre-write.js +29 -2
  168. package/hooks/gsd-workflow-guard.js +3 -2
  169. package/hooks/gsd-worktree-path-guard.js +29 -2
  170. package/hooks/hooks.json +1 -0
  171. package/hooks/lib/git-probe.js +16 -0
  172. package/hooks/lib/isolation-sentinel.js +44 -0
  173. package/hooks/managed-hooks-registry.cjs +1 -0
  174. package/package.json +15 -8
  175. package/pi/gsd.cjs +1047 -10
  176. package/pi/package-agents/gsd-advisor-researcher.md +113 -0
  177. package/pi/package-agents/gsd-ai-researcher.md +111 -0
  178. package/pi/package-agents/gsd-assumptions-analyzer.md +110 -0
  179. package/pi/package-agents/gsd-code-fixer.md +774 -0
  180. package/pi/package-agents/gsd-code-reviewer.md +441 -0
  181. package/pi/package-agents/gsd-codebase-mapper.md +850 -0
  182. package/pi/package-agents/gsd-debug-session-manager.md +416 -0
  183. package/pi/package-agents/gsd-debugger.md +1274 -0
  184. package/pi/package-agents/gsd-doc-classifier.md +269 -0
  185. package/pi/package-agents/gsd-doc-synthesizer.md +259 -0
  186. package/pi/package-agents/gsd-doc-verifier.md +212 -0
  187. package/pi/package-agents/gsd-doc-writer.md +626 -0
  188. package/pi/package-agents/gsd-dom-verifier.md +164 -0
  189. package/pi/package-agents/gsd-domain-researcher.md +144 -0
  190. package/pi/package-agents/gsd-eval-auditor.md +185 -0
  191. package/pi/package-agents/gsd-eval-planner.md +149 -0
  192. package/pi/package-agents/gsd-executor.md +898 -0
  193. package/pi/package-agents/gsd-framework-selector.md +159 -0
  194. package/pi/package-agents/gsd-integration-checker.md +476 -0
  195. package/pi/package-agents/gsd-intel-updater.md +338 -0
  196. package/pi/package-agents/gsd-mempalace-curator.md +49 -0
  197. package/pi/package-agents/gsd-nyquist-auditor.md +200 -0
  198. package/pi/package-agents/gsd-pattern-mapper.md +340 -0
  199. package/pi/package-agents/gsd-phase-researcher.md +897 -0
  200. package/pi/package-agents/gsd-plan-checker.md +1077 -0
  201. package/pi/package-agents/gsd-planner.md +1003 -0
  202. package/pi/package-agents/gsd-project-researcher.md +611 -0
  203. package/pi/package-agents/gsd-research-synthesizer.md +259 -0
  204. package/pi/package-agents/gsd-roadmapper.md +779 -0
  205. package/pi/package-agents/gsd-security-auditor.md +171 -0
  206. package/pi/package-agents/gsd-ui-auditor.md +581 -0
  207. package/pi/package-agents/gsd-ui-checker.md +417 -0
  208. package/pi/package-agents/gsd-ui-researcher.md +469 -0
  209. package/pi/package-agents/gsd-user-profiler.md +174 -0
  210. package/pi/package-agents/gsd-verifier.md +963 -0
  211. package/pi/package-agents/manifest.json +39 -0
  212. package/pi/package-skills/gsd-add-tests/SKILL.md +39 -0
  213. package/pi/package-skills/gsd-ai-integration-phase/SKILL.md +36 -0
  214. package/pi/package-skills/gsd-audit-fix/SKILL.md +34 -0
  215. package/pi/package-skills/gsd-audit-milestone/SKILL.md +40 -0
  216. package/pi/package-skills/gsd-audit-uat/SKILL.md +26 -0
  217. package/pi/package-skills/gsd-autonomous/SKILL.md +52 -0
  218. package/pi/package-skills/gsd-capture/SKILL.md +68 -0
  219. package/pi/package-skills/gsd-cleanup/SKILL.md +25 -0
  220. package/pi/package-skills/gsd-code-review/SKILL.md +71 -0
  221. package/pi/package-skills/gsd-complete-milestone/SKILL.md +147 -0
  222. package/pi/package-skills/gsd-config/SKILL.md +60 -0
  223. package/pi/package-skills/gsd-debug/SKILL.md +64 -0
  224. package/pi/package-skills/gsd-discuss-phase/SKILL.md +74 -0
  225. package/pi/package-skills/gsd-docs-update/SKILL.md +50 -0
  226. package/pi/package-skills/gsd-eval-review/SKILL.md +35 -0
  227. package/pi/package-skills/gsd-execute-phase/SKILL.md +62 -0
  228. package/pi/package-skills/gsd-explore/SKILL.md +26 -0
  229. package/pi/package-skills/gsd-extract-learnings/SKILL.md +25 -0
  230. package/pi/package-skills/gsd-fast/SKILL.md +33 -0
  231. package/pi/package-skills/gsd-forensics/SKILL.md +59 -0
  232. package/pi/package-skills/gsd-graphify/SKILL.md +210 -0
  233. package/pi/package-skills/gsd-health/SKILL.md +36 -0
  234. package/pi/package-skills/gsd-help/SKILL.md +37 -0
  235. package/pi/package-skills/gsd-import/SKILL.md +46 -0
  236. package/pi/package-skills/gsd-inbox/SKILL.md +42 -0
  237. package/pi/package-skills/gsd-ingest-docs/SKILL.md +43 -0
  238. package/pi/package-skills/gsd-manager/SKILL.md +46 -0
  239. package/pi/package-skills/gsd-map-codebase/SKILL.md +85 -0
  240. package/pi/package-skills/gsd-mempalace-capture/SKILL.md +111 -0
  241. package/pi/package-skills/gsd-mempalace-recall/SKILL.md +111 -0
  242. package/pi/package-skills/gsd-milestone-summary/SKILL.md +54 -0
  243. package/pi/package-skills/gsd-mvp-phase/SKILL.md +45 -0
  244. package/pi/package-skills/gsd-new-milestone/SKILL.md +49 -0
  245. package/pi/package-skills/gsd-new-project/SKILL.md +49 -0
  246. package/pi/package-skills/gsd-next/SKILL.md +34 -0
  247. package/pi/package-skills/gsd-ns-context/SKILL.md +31 -0
  248. package/pi/package-skills/gsd-ns-ideate/SKILL.md +30 -0
  249. package/pi/package-skills/gsd-ns-manage/SKILL.md +42 -0
  250. package/pi/package-skills/gsd-ns-project/SKILL.md +34 -0
  251. package/pi/package-skills/gsd-ns-review/SKILL.md +35 -0
  252. package/pi/package-skills/gsd-ns-workflow/SKILL.md +44 -0
  253. package/pi/package-skills/gsd-onboard/SKILL.md +46 -0
  254. package/pi/package-skills/gsd-pause-work/SKILL.md +48 -0
  255. package/pi/package-skills/gsd-phase/SKILL.md +61 -0
  256. package/pi/package-skills/gsd-plan-phase/SKILL.md +62 -0
  257. package/pi/package-skills/gsd-plan-review-convergence/SKILL.md +63 -0
  258. package/pi/package-skills/gsd-pr-branch/SKILL.md +31 -0
  259. package/pi/package-skills/gsd-profile-user/SKILL.md +48 -0
  260. package/pi/package-skills/gsd-progress/SKILL.md +51 -0
  261. package/pi/package-skills/gsd-quick/SKILL.md +179 -0
  262. package/pi/package-skills/gsd-quick-batch/SKILL.md +114 -0
  263. package/pi/package-skills/gsd-resume-work/SKILL.md +31 -0
  264. package/pi/package-skills/gsd-review/SKILL.md +50 -0
  265. package/pi/package-skills/gsd-review-backlog/SKILL.md +65 -0
  266. package/pi/package-skills/gsd-secure-phase/SKILL.md +37 -0
  267. package/pi/package-skills/gsd-settings/SKILL.md +30 -0
  268. package/pi/package-skills/gsd-ship/SKILL.md +27 -0
  269. package/pi/package-skills/gsd-sketch/SKILL.md +56 -0
  270. package/pi/package-skills/gsd-spec-phase/SKILL.md +63 -0
  271. package/pi/package-skills/gsd-spike/SKILL.md +53 -0
  272. package/pi/package-skills/gsd-stats/SKILL.md +22 -0
  273. package/pi/package-skills/gsd-surface/SKILL.md +177 -0
  274. package/pi/package-skills/gsd-thread/SKILL.md +29 -0
  275. package/pi/package-skills/gsd-ui-phase/SKILL.md +35 -0
  276. package/pi/package-skills/gsd-ui-review/SKILL.md +35 -0
  277. package/pi/package-skills/gsd-ultraplan-phase/SKILL.md +38 -0
  278. package/pi/package-skills/gsd-undo/SKILL.md +38 -0
  279. package/pi/package-skills/gsd-update/SKILL.md +54 -0
  280. package/pi/package-skills/gsd-validate-phase/SKILL.md +37 -0
  281. package/pi/package-skills/gsd-verify-work/SKILL.md +41 -0
  282. package/pi/package-skills/gsd-workspace/SKILL.md +57 -0
  283. package/pi/package-skills/gsd-workstreams/SKILL.md +73 -0
  284. package/scripts/build-hooks.js +4 -0
  285. package/scripts/ci-next-health.cjs +246 -23
  286. package/scripts/command-contract-helpers.cjs +1 -1
  287. package/scripts/docs-guard-registry.cjs +22 -7
  288. package/scripts/gen-features.cjs +14 -2
  289. package/scripts/gen-health-docs.cjs +13 -1
  290. package/scripts/gen-pi-package-skills.cjs +217 -0
  291. package/scripts/lib/drift-scan.cjs +27 -0
  292. package/scripts/lib/macos-conformance-tier.generated.cjs +17 -1
  293. package/scripts/lib/platform-conformance-tier.generated.cjs +37 -1
  294. package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +3 -3
  295. package/scripts/lint-phase-enumeration-drift.cjs +8 -4
  296. package/scripts/lint-retired-runtime-name.cjs +5 -0
  297. package/scripts/lint-roadmap-progress-drift.cjs +421 -0
  298. package/scripts/mutation-matrix.cjs +23 -1
  299. package/scripts/npm-audit-baseline.cjs +41 -7
  300. package/scripts/reviewed-or-maintainer-policy.cjs +181 -0
  301. package/scripts/select-docs-guards.cjs +1 -1
  302. package/scripts/self-test-report-policy.cjs +350 -0
  303. package/scripts/sync-next-version.cjs +38 -6
  304. package/skills/gsd-update/SKILL.md +5 -2
  305. package/vscode/package.json +1 -1
  306. package/scripts/diagnose-validate-commit-in-tier.cjs +0 -270
  307. package/scripts/diagnose-validate-commit-phases.cjs +0 -348
  308. package/scripts/xtrace-phase-timing.cjs +0 -205
@@ -233,14 +233,17 @@ function _resolveCommandsGsdDir() {
233
233
  * Only directories whose names start with gsd- are included so user-created
234
234
  * skills (without the gsd- prefix) are not accidentally pulled in.
235
235
  *
236
- * The requires: field is parsed via the shared parseRequires helper (the same
237
- * parser loadSkillsManifest uses), so the two paths cannot drift.
236
+ * Dependencies use the same parseRequires, parseCallsAgents, and
237
+ * workflowAgentRefs helpers as loadSkillsManifest. Workflow references resolve
238
+ * against this runtime's own gsd-core/workflows tree, including its fragments,
239
+ * so a custom config directory never borrows another installation's agents.
238
240
  *
239
241
  * Returns an empty Map when the skills dir does not exist.
240
242
  */
241
243
  function _loadInstalledSkillsManifest(configDir) {
242
244
  const manifest = new Map();
243
245
  const skillsDir = node_path_1.default.join(configDir, 'skills');
246
+ const workflowsDir = node_path_1.default.join(configDir, 'gsd-core', 'workflows');
244
247
  if (!node_fs_1.default.existsSync(skillsDir))
245
248
  return manifest;
246
249
  let entries;
@@ -282,12 +285,15 @@ function _loadInstalledSkillsManifest(configDir) {
282
285
  // installed-runtime dependency resolution can never silently diverge from
283
286
  // the source-tree path (single source of truth — no duplicated regex).
284
287
  manifest.set(stem, content ? parseRequires(content) : []);
285
- // Mirror loadSkillsManifest's Map shape: it always sets a companion
286
- // `_calls_agents_<stem>` key. Installed SKILL.md bodies carry no
287
- // recoverable agent-call refs, so [] (the no-agents case) keeps the two
288
- // manifest shapes identical and prevents undefined-vs-[] drift for any
289
- // consumer that reads the agent-refs companion key.
290
- manifest.set(`_calls_agents_${stem}`, []);
288
+ // Installed skills delegate to workflows just as source commands do.
289
+ // Preserve their agent closure so surface materialization only prunes
290
+ // agents no retained skill requires (#5356).
291
+ manifest.set(`_calls_agents_${stem}`, [
292
+ ...new Set([
293
+ ...parseCallsAgents(content),
294
+ ...workflowAgentRefs(content, workflowsDir),
295
+ ]),
296
+ ]);
291
297
  }
292
298
  return manifest;
293
299
  }
@@ -856,6 +856,7 @@ const VALID_CONVERTER_NAMES = new Set([
856
856
  'convertClaudeCommandToKimiSkill',
857
857
  'convertClaudeCommandToKimiCodeSkill',
858
858
  'convertClaudeCommandToOpencodeSkill',
859
+ 'convertClaudeCommandToPiSkill',
859
860
  'convertClaudeCommandToTraeSkill',
860
861
  'convertClaudeCommandToWindsurfSkill',
861
862
  'convertClaudeCommandToWindsurfWorkflow',
@@ -879,6 +880,8 @@ const VALID_CONVERTER_NAMES = new Set([
879
880
  // and the kilo/opencode agent converters (shared with those runtimes'
880
881
  // commands-kind entries, options-bag signature `(content, {isAgent, modelOverride})`).
881
882
  'convertClaudeAgentToHermesAgent',
883
+ // #5569 (ADR-5559 §3) — the role file Pi's gsd_dispatch loads.
884
+ 'convertClaudeAgentToPiAgent',
882
885
  'convertClaudeToKiloFrontmatter',
883
886
  'convertClaudeToOpencodeFrontmatter',
884
887
  ]);
@@ -1236,6 +1239,20 @@ function validateArtifactKindEntry(capId, entry, prefix) {
1236
1239
  }
1237
1240
  }
1238
1241
 
1242
+ // excludeSuffixes — optional; filename suffixes the agents staging skips (#5569: Pi omits .compact.md)
1243
+ if (entry.excludeSuffixes !== undefined) {
1244
+ if (!Array.isArray(entry.excludeSuffixes)) {
1245
+ errors.push(ctx + '.excludeSuffixes must be an array of non-empty strings if present');
1246
+ } else {
1247
+ for (let i = 0; i < entry.excludeSuffixes.length; i++) {
1248
+ const s = entry.excludeSuffixes[i];
1249
+ if (typeof s !== 'string' || s.length === 0 || s.includes('/') || s.includes('\\')) {
1250
+ errors.push(ctx + '.excludeSuffixes[' + i + '] must be a non-empty string without path separators');
1251
+ }
1252
+ }
1253
+ }
1254
+ }
1255
+
1239
1256
  // converter — required; must be a string or null (closed ConverterName enum — now enforced in phase 5e)
1240
1257
  if (!Object.prototype.hasOwnProperty.call(entry, 'converter')) {
1241
1258
  errors.push(ctx + '.converter is required (must be a string or null)');
@@ -1857,6 +1874,11 @@ const KNOWN_REVIEWER_FIELDS = new Set([
1857
1874
  // effort", which emits no effort argument at all.
1858
1875
  'effortConfigKey',
1859
1876
  'defaultEffort',
1877
+ // `contextWindowTokens` / `contextWindowConfigKey` added by #4559, same optional/backward-compatible
1878
+ // shape as `promptBudgetKey`: a manifest authored before they existed keeps validating, and an
1879
+ // absent or non-positive window resolves to "no derived prompt cap" at the invocation boundary.
1880
+ 'contextWindowTokens',
1881
+ 'contextWindowConfigKey',
1860
1882
  'handler',
1861
1883
  ]);
1862
1884
 
@@ -2488,6 +2510,16 @@ function validateReviewerBodyFields(cap) {
2488
2510
  );
2489
2511
  }
2490
2512
 
2513
+ // #4559: optional. Absent or null is "no declared window"; a present key must be a dotted
2514
+ // config key string. The window's VALUE is narrowed (never rejected) by `resolveLaneCap`.
2515
+ if (r.contextWindowConfigKey !== undefined && r.contextWindowConfigKey !== null
2516
+ && (typeof r.contextWindowConfigKey !== 'string' || r.contextWindowConfigKey.length === 0)) {
2517
+ errors.push(
2518
+ ctx + ' reviewer.contextWindowConfigKey must be a dotted config key or null ' +
2519
+ '(got: ' + describeValue(r.contextWindowConfigKey) + ')',
2520
+ );
2521
+ }
2522
+
2491
2523
  // ── handler (D6) — closed first-party enum; null is the default ────────────
2492
2524
  if (r.handler !== null && !VALID_LANE_HANDLERS.has(r.handler)) {
2493
2525
  errors.push(
@@ -31,13 +31,13 @@ const coreUtilsMod = require("./core-utils.cjs");
31
31
  const { toPosixPath, generateSlugInternal, extractOneLinerFromBody } = coreUtilsMod;
32
32
  // eslint-disable-next-line @typescript-eslint/no-require-imports
33
33
  const phaseIdMod = require("./phase-id.cjs");
34
- const { normalizePhaseName, comparePhaseNum, extractPhaseToken, PHASE_NUMBER_TOKEN_SOURCE, isSentinelPhaseId, renderPhaseBranchName, parsePhaseId, renderPhaseId, phaseHeadingPrefixSrcFor, PHASE_HEADING_BASELINE, } = phaseIdMod;
34
+ const { customPhaseQuery, customDirectoryOwner, isCustomPhaseId, normalizePhaseName, comparePhaseNum, extractPhaseToken, PHASE_NUMBER_TOKEN_SOURCE, isSentinelPhaseId, renderPhaseBranchName, parsePhaseId, renderPhaseId, phaseHeadingPrefixSrcFor, PHASE_HEADING_BASELINE, } = phaseIdMod;
35
35
  // eslint-disable-next-line @typescript-eslint/no-require-imports
36
36
  const phaseIdDisplayMod = require("./phase-id-display.cjs");
37
37
  const { renderBracketMilestoneDisplay } = phaseIdDisplayMod;
38
38
  // eslint-disable-next-line @typescript-eslint/no-require-imports
39
39
  const phaseLocatorMod = require("./phase-locator.cjs");
40
- const { getArchivedPhaseDirs, findPhaseInternal, listMilestonePhaseDirs } = phaseLocatorMod;
40
+ const { phaseDirectoryOptions, getArchivedPhaseDirs, findPhaseInternal, listMilestonePhaseDirs } = phaseLocatorMod;
41
41
  // eslint-disable-next-line @typescript-eslint/no-require-imports
42
42
  const roadmapParserMod = require("./roadmap-parser.cjs");
43
43
  const { extractCurrentMilestone, stripShippedMilestones: _stripShippedMilestones, getMilestoneInfo, getRoadmapPhaseInternal } = roadmapParserMod;
@@ -1822,7 +1822,7 @@ function cmdCommit(cwd, message, files, raw, amend, noVerify, filesRemoved) {
1822
1822
  // phase — the phase arm must never branch-mutate for it (isSentinelPhaseId
1823
1823
  // is the invariant's single owner, src/phase-id.cts).
1824
1824
  if (phaseNum && !isSentinelPhaseId(phaseNum)) {
1825
- const phaseInfo = findPhaseInternal(cwd, phaseNum);
1825
+ const phaseInfo = findPhaseInternal(cwd, phaseNum, undefined, phaseDirectoryOptions(cwd, config));
1826
1826
  if (phaseInfo) {
1827
1827
  // #4126: shared with init.cts's cmdInitExecutePhase branch_name field
1828
1828
  // via the one canonical renderer (src/phase-id.cts) so an undeliverable
@@ -3053,6 +3053,7 @@ function cmdProgressRender(cwd, format, raw) {
3053
3053
  ? renderBracketMilestoneDisplay(milestone?.version, loadConfig(cwd).project_code)
3054
3054
  : null;
3055
3055
  const milestoneVersion = milestoneDisplay ?? milestone?.version ?? null;
3056
+ const directoryContext = phaseDirectoryOptions(cwd);
3056
3057
  const phases = [];
3057
3058
  let totalPlans = 0;
3058
3059
  let totalSummaries = 0;
@@ -3091,9 +3092,11 @@ function cmdProgressRender(cwd, format, raw) {
3091
3092
  }
3092
3093
  }
3093
3094
  else {
3095
+ const custom = customPhaseQuery(dir, directoryContext);
3096
+ const owner = custom && customDirectoryOwner(dir, custom);
3094
3097
  const dm = dir.match(/^(\d+(?:\.\d+)*)-?(.*)/);
3095
- phaseNum = dm ? dm[1] : dir;
3096
- phaseName = dm && dm[2] ? dm[2].replace(/-/g, ' ') : '';
3098
+ phaseNum = owner ? owner.id : dm ? dm[1] : dir;
3099
+ phaseName = owner ? owner.slug.replace(/-/g, ' ') : dm && dm[2] ? dm[2].replace(/-/g, ' ') : '';
3097
3100
  }
3098
3101
  // #3183/#5060: canonical plan/summary counts and lifecycle status
3099
3102
  // (root+nested, superseded-excluded, canonical pairing) from the
@@ -3212,7 +3215,7 @@ function cmdTodoMatchPhase(cwd, phase, raw) {
3212
3215
  .map(w => w.replace(/[^a-z0-9]/g, ''))
3213
3216
  .filter(w => w.length > 2 && !stopWords.has(w)));
3214
3217
  // Find phase directory to get expected file paths
3215
- const phaseInfoDisk = findPhaseInternal(cwd, phase);
3218
+ const phaseInfoDisk = findPhaseInternal(cwd, phase, undefined, phaseDirectoryOptions(cwd));
3216
3219
  const phasePlans = [];
3217
3220
  if (phaseInfoDisk && phaseInfoDisk['found']) {
3218
3221
  try {
@@ -3394,7 +3397,7 @@ function cmdScaffold(cwd, type, options, raw) {
3394
3397
  const padded = phase ? normalizePhaseName(phase) : '00';
3395
3398
  const today = clock_cjs_1.realClock.localToday();
3396
3399
  // Find phase directory
3397
- const phaseInfo = phase ? findPhaseInternal(cwd, phase) : null;
3400
+ const phaseInfo = phase && type !== 'phase-dir' ? findPhaseInternal(cwd, phase, undefined, phaseDirectoryOptions(cwd)) : null;
3398
3401
  const phaseDir = phaseInfo ? node_path_1.default.join(cwd, phaseInfo['directory']) : null;
3399
3402
  if (phase && !phaseDir && type !== 'phase-dir') {
3400
3403
  error(`Phase ${phase} directory not found`);
@@ -3422,14 +3425,14 @@ function cmdScaffold(cwd, type, options, raw) {
3422
3425
  }
3423
3426
  const slug = generateSlugInternal(name);
3424
3427
  // #3287: apply project_code prefix to stay consistent with phase.add/phase.insert
3425
- const scaffoldConfig = loadConfig(cwd);
3426
- const scaffoldProjectCode = scaffoldConfig['project_code'] || '';
3427
- const scaffoldPrefix = scaffoldProjectCode ? `${scaffoldProjectCode}-` : '';
3428
- const dirName = `${scaffoldPrefix}${padded}-${slug}`;
3429
- const phasesParent = planningPaths(cwd).phases;
3430
- (0, shell_command_projection_cjs_1.platformEnsureDir)(phasesParent);
3431
- const dirPath = node_path_1.default.join(phasesParent, dirName);
3432
- (0, shell_command_projection_cjs_1.platformEnsureDir)(dirPath);
3428
+ const scaffoldConfig = phaseDirectoryOptions(cwd, undefined, '');
3429
+ const roadmapPath = node_path_1.default.join(planningDir(cwd), 'ROADMAP.md');
3430
+ const roadmap = scaffoldConfig.phaseNaming === 'custom' && node_fs_1.default.existsSync(roadmapPath)
3431
+ ? node_fs_1.default.readFileSync(roadmapPath, 'utf8') : '';
3432
+ const [{ dirPath }] = phaseLocatorMod.createPhaseDirectories(cwd, [{
3433
+ id: phase, slug: slug || '',
3434
+ directoryId: scaffoldConfig.phaseNaming === 'custom' && isCustomPhaseId(phase) ? phase : padded,
3435
+ }], { ...scaffoldConfig, roadmap }, false);
3433
3436
  output({ created: true, directory: toPosixPath(node_path_1.default.relative(cwd, dirPath)), path: dirPath }, raw, dirPath);
3434
3437
  return;
3435
3438
  }
@@ -3728,12 +3731,19 @@ function cmdStats(cwd, format, raw) {
3728
3731
  */
3729
3732
  function cmdCheckCommit(cwd, raw) {
3730
3733
  const config = loadConfig(cwd);
3731
- const stagedResult = (0, shell_command_projection_cjs_1.execGit)(['diff', '--cached', '--name-only', '-z'], { cwd });
3734
+ // #5548: execGit scrubs the repo-location vars, but inside the pre-commit hook git sets them
3735
+ // (GIT_DIR/GIT_WORK_TREE of an explicit --git-dir commit, GIT_INDEX_FILE of a `-a` / `<path>`
3736
+ // commit) to name the repo being committed: hand them back or the guard finds no repo and allows.
3737
+ const hookEnv = {};
3738
+ for (const k of shell_command_projection_cjs_1.GIT_LOCATION_ENV_VARS)
3739
+ if (process.env[k] !== undefined)
3740
+ hookEnv[k] = process.env[k];
3741
+ const stagedResult = (0, shell_command_projection_cjs_1.execGit)(['diff', '--cached', '--name-only', '-z'], { cwd, env: hookEnv });
3732
3742
  if (stagedResult.exitCode === 0) {
3733
3743
  const files = stagedResult.stdout.split('\0').filter(Boolean);
3734
3744
  const planningFiles = files.filter(f => f.startsWith('.planning/'));
3735
3745
  if (planningFiles.length > 0) {
3736
- const policy = resolveCommitDocsPolicy(config, detectPhaseNumberFromFiles(planningFiles), () => isGitIgnored(cwd, '.planning'));
3746
+ const policy = resolveCommitDocsPolicy(config, detectPhaseNumberFromFiles(planningFiles), () => isGitIgnored(cwd, '.planning', hookEnv));
3737
3747
  if (!policy.resolved) {
3738
3748
  error(`commit_docs is false but ${planningFiles.length} .planning/ file(s) are staged:\n` +
3739
3749
  planningFiles.map(f => ` ${f}`).join('\n') +
@@ -156,6 +156,15 @@ const CONFIG_DEFAULTS = {
156
156
  planner_stall_detection_enabled: _getNestedConfigDefault('planner', 'stall_detection_enabled'),
157
157
  max_prompt_tokens: _getNestedConfigDefault('review', 'max_prompt_tokens'),
158
158
  };
159
+ /**
160
+ * Resolve `git.repo_tagging` (#5706) from hand-edited configuration. Only the
161
+ * two documented enum members are honored; any other stored value (a number,
162
+ * null, an unknown string, a wrong-case spelling) reads as the default `single`
163
+ * and never throws, so a bad hand edit cannot enable per-repository tagging.
164
+ */
165
+ function resolveRepoTagging(value) {
166
+ return value === 'per_repo' ? 'per_repo' : 'single';
167
+ }
159
168
  /**
160
169
  * Resolve the planner watchdog policy from hand-edited configuration.
161
170
  * Only a real JSON boolean may override the default; strings/numbers/null
@@ -204,16 +213,16 @@ function _deepMergeConfig(base, overlay) {
204
213
  const _warnedUnknownConfigKeys = new Set();
205
214
  // ─── Git utilities ────────────────────────────────────────────────────────────
206
215
  const _gitIgnoredCache = new Map();
207
- function isGitIgnored(cwd, targetPath) {
216
+ function isGitIgnored(cwd, targetPath, env) {
208
217
  // #2206: strip trailing slashes — `git check-ignore` has a quirk where a
209
218
  // CRLF .gitignore with blank lines falsely reports a trailing-slash path
210
219
  // (e.g. `.planning/`) as ignored. Normalizing here protects every call site.
211
220
  const normalized = targetPath.replace(/\/+$/, '');
212
- const key = cwd + '::' + normalized;
221
+ const key = cwd + '::' + normalized + (env ? '::env:' + JSON.stringify(Object.entries(env).sort()) : '');
213
222
  if (_gitIgnoredCache.has(key))
214
223
  return _gitIgnoredCache.get(key);
215
224
  // --no-index checks .gitignore rules regardless of whether the file is tracked.
216
- const result = (0, shell_command_projection_cjs_1.execGit)(['check-ignore', '-q', '--no-index', '--', normalized], { cwd });
225
+ const result = (0, shell_command_projection_cjs_1.execGit)(['check-ignore', '-q', '--no-index', '--', normalized], { cwd, env });
217
226
  const ignored = result.exitCode === 0;
218
227
  _gitIgnoredCache.set(key, ignored);
219
228
  return ignored;
@@ -849,6 +858,7 @@ function loadConfigResolvedInternal(cwd, options = {}) {
849
858
  base_branch: get('base_branch', { section: 'git', field: 'base_branch' }),
850
859
  protected_branches: getNested('git', 'protected_branches'),
851
860
  allow_default_branch_commits: getNested('git', 'allow_default_branch_commits'),
861
+ repo_tagging: resolveRepoTagging(getNested('git', 'repo_tagging')),
852
862
  phase_branch_template: get('phase_branch_template', { section: 'git', field: 'phase_branch_template' }) ?? defaults.phase_branch_template,
853
863
  milestone_branch_template: get('milestone_branch_template', { section: 'git', field: 'milestone_branch_template' }) ?? defaults.milestone_branch_template,
854
864
  quick_branch_template: get('quick_branch_template', { section: 'git', field: 'quick_branch_template' }) ?? defaults.quick_branch_template,