@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
@@ -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
@@ -54,14 +54,20 @@ const validateMod = require("../validate.cjs");
54
54
  const { isPhaseDirName } = validateMod;
55
55
  // eslint-disable-next-line @typescript-eslint/no-require-imports
56
56
  const phaseIdMod = require("../phase-id.cjs");
57
- const { extractPhaseToken, normalizePhaseName, comparePhaseNum } = phaseIdMod;
57
+ const { extractPhaseToken, normalizePhaseName, phaseKeyFromDir, 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 = [];
66
+ const context = snapshot.directoryContext ?? phaseIdMod.phaseDirectoryContext(snapshot.config.value ?? {}, '', snapshot.roadmapDeclaredPhases.value.map(({ phaseId }) => phaseId));
63
67
  for (const name of snapshot.phaseDirs.value) {
64
- if (!isPhaseDirName(name, snapshot.phaseIdConvention)) {
68
+ const custom = snapshot.phaseIdConvention === 'bracket' ? null : phaseIdMod.customPhaseQuery(name, context);
69
+ const owner = custom && phaseIdMod.customDirectoryOwner(name, custom);
70
+ if (!owner && !isPhaseDirName(name, snapshot.phaseIdConvention)) {
65
71
  diagnostics.push({
66
72
  code: 'W005',
67
73
  severity: SEVERITY.WARNING,
@@ -74,17 +80,18 @@ function checkW005(snapshot) {
74
80
  }
75
81
  // ─── W023 — phase directories collide on normalized key (verify.cts:1904-1950) ─
76
82
  //
77
- // Groups `snapshot.phaseDirs.value` by `normalizePhaseName(extractPhaseToken(name))`
78
- // — the exact same two owners (`phase-id.cjs`) the original `verify.cts:1917-1918`
79
- // call site uses, relocated verbatim rather than reimplemented. Sorted with
80
- // `comparePhaseNum` + a `localeCompare` tiebreak, mirroring
83
+ // Groups directories by the canonical identity owner, preserving recorded
84
+ // custom IDs instead of collapsing their shared token prefixes. Sorted with
85
+ // contextual `comparePhaseNum` + a `localeCompare` tiebreak, mirroring
81
86
  // `verify.cts:1930-1932`'s deterministic-output rationale. See the file-level
82
87
  // comment for the disclosed "described" fidelity reduction.
83
88
  function checkW023(snapshot) {
89
+ const context = snapshot.directoryContext;
84
90
  const groups = new Map();
85
91
  for (const name of snapshot.phaseDirs.value) {
86
- const token = extractPhaseToken(name);
87
- const key = normalizePhaseName(token);
92
+ const key = context?.phaseNaming === 'custom'
93
+ ? phaseKeyFromDir(name, undefined, context)
94
+ : normalizePhaseName(extractPhaseToken(name));
88
95
  const list = groups.get(key);
89
96
  if (list)
90
97
  list.push(name);
@@ -98,7 +105,7 @@ function checkW023(snapshot) {
98
105
  continue;
99
106
  const described = dirs
100
107
  .slice()
101
- .sort((a, b) => comparePhaseNum(a, b) || String(a).localeCompare(String(b)))
108
+ .sort((a, b) => comparePhaseNum(a, b, context) || String(a).localeCompare(String(b)))
102
109
  .map((d) => {
103
110
  const phase = phaseByDir.get(d);
104
111
  const plans = phase ? phase.planCount : 0;
@@ -174,11 +181,21 @@ function checkW030(snapshot) {
174
181
  const invalid = phase.verificationStatusError;
175
182
  if (!invalid)
176
183
  continue;
184
+ // #5291: a KNOWN legacy status is repairable (rewritten to its closed-set
185
+ // equivalent, original kept in `legacy_status`); any other value has no
186
+ // mapping and keeps the advise-only remedy — it stays refused.
187
+ const target = (0, verification_cjs_1.legacyStatusRepairTarget)(invalid.rawStatus);
177
188
  diagnostics.push({
178
189
  code: 'W030',
179
190
  severity: SEVERITY.WARNING,
180
191
  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'),
192
+ remedy: target === null
193
+ ? adviseRemedy('Set the report frontmatter `status` to one of passed | gaps_found | human_needed, or delete the report and re-run the phase verification')
194
+ : {
195
+ action: REMEDY_ACTION.REPAIR_VERIFICATION_STATUS,
196
+ risk: REMEDY_RISK.NONE,
197
+ args: { file: invalid.file, from: invalid.rawStatus, to: target },
198
+ },
182
199
  });
183
200
  }
184
201
  return diagnostics;
@@ -217,7 +234,9 @@ const RULES = [
217
234
  code: 'W030',
218
235
  severity: SEVERITY.WARNING,
219
236
  description: 'Phase verification report status is outside the closed set',
220
- repairable: false,
237
+ // #5291: repairable per finding — a KNOWN legacy status (`pass_with_caveats`)
238
+ // is rewritten by `--repair`; any other value stays advise-only.
239
+ repairable: true,
221
240
  check: checkW030,
222
241
  },
223
242
  ];
@@ -104,7 +104,7 @@ const planningScopeMod = require("../planning-scope.cjs");
104
104
  const { SCOPE } = planningScopeMod;
105
105
  // eslint-disable-next-line @typescript-eslint/no-require-imports
106
106
  const phaseIdMod = require("../phase-id.cjs");
107
- const { matchPhaseDirs, normalizePhaseName, extractPhaseToken, isSentinelPhaseId, isSentinelPhaseDir } = phaseIdMod;
107
+ const { matchPhaseDirs, phaseLookupQuery, extractPhaseToken, isSentinelPhaseId, isSentinelPhaseDir } = phaseIdMod;
108
108
  // eslint-disable-next-line @typescript-eslint/no-require-imports
109
109
  const validateMod = require("../validate.cjs");
110
110
  const { phaseVariants } = validateMod;
@@ -116,7 +116,7 @@ const { phaseVariants } = validateMod;
116
116
  * does the roadmap claim, for W007) call this — one matcher, reused, per the
117
117
  * file-level comment.
118
118
  */
119
- function dirsForPhase(dirs, phaseId, convention) {
119
+ function dirsForPhase(dirs, phaseId, convention, directoryContext) {
120
120
  // #612: `convention` reaches BOTH operands of this pairing or it pairs
121
121
  // nothing. The phases come from a bracket-aware heading scan and the dirs
122
122
  // from a bracket-aware disk scan, so a convention-less selector here leaves
@@ -125,7 +125,7 @@ function dirsForPhase(dirs, phaseId, convention) {
125
125
  // disk" AND every bracket directory reads as unclaimed. `matchPhaseDirs`
126
126
  // forwards it to its primary `phaseTokenMatches`; handed nothing it is
127
127
  // byte-identical, so no legacy repo's pairing changes.
128
- const canonical = matchPhaseDirs(dirs, normalizePhaseName(phaseId), convention).matches;
128
+ const canonical = matchPhaseDirs(dirs, phaseLookupQuery(phaseId, directoryContext), convention, undefined, directoryContext).matches;
129
129
  if (canonical.length > 0)
130
130
  return canonical;
131
131
  // Bug 2 (#3309 W006/W007 migration cluster, found while fixing the
@@ -187,6 +187,7 @@ function checkW006(snapshot) {
187
187
  return [];
188
188
  const dirs = snapshot.allPhaseDirNames.value;
189
189
  const convention = snapshot.phaseIdConvention;
190
+ const directoryContext = snapshot.directoryContext ?? phaseIdMod.phaseDirectoryContext(snapshot.config.value ?? {}, '', snapshot.roadmapDeclaredPhases.value.map(({ phaseId }) => phaseId));
190
191
  const archivedTokens = new Set(snapshot.archivedPhaseTokens.value);
191
192
  // No separate scope guard: `roadmapSentinelPhaseTokens` and
192
193
  // `roadmapDeclaredPhases` are produced by ONE builder call
@@ -219,7 +220,7 @@ function checkW006(snapshot) {
219
220
  // not change its result.
220
221
  if (sentinelTokens.has(phaseId) || isSentinelPhaseId(phaseId))
221
222
  continue;
222
- if (dirsForPhase(dirs, phaseId, convention).length > 0)
223
+ if (dirsForPhase(dirs, phaseId, convention, directoryContext).length > 0)
223
224
  continue;
224
225
  // Bug 1 (#3309 W006/W007 migration cluster): a phase whose ONLY
225
226
  // directory lives under a milestone archive
@@ -247,10 +248,10 @@ function checkW006(snapshot) {
247
248
  // ─── W007 — an on-disk phase directory has no matching ROADMAP entry ──────
248
249
  // (verify.cts:2086-2101)
249
250
  /** Every directory in `dirs` that ANY declared roadmap phase resolves to. */
250
- function computeClaimedDirs(dirs, declaredPhases, convention) {
251
+ function computeClaimedDirs(dirs, declaredPhases, convention, directoryContext) {
251
252
  const claimed = new Set();
252
253
  for (const { phaseId } of declaredPhases) {
253
- for (const dir of dirsForPhase(dirs, phaseId, convention))
254
+ for (const dir of dirsForPhase(dirs, phaseId, convention, directoryContext))
254
255
  claimed.add(dir);
255
256
  }
256
257
  return claimed;
@@ -261,7 +262,8 @@ function checkW007(snapshot) {
261
262
  return [];
262
263
  const dirs = snapshot.allPhaseDirNames.value;
263
264
  const convention = snapshot.phaseIdConvention;
264
- const claimedDirs = computeClaimedDirs(dirs, snapshot.roadmapDeclaredPhases.value, convention);
265
+ const directoryContext = snapshot.directoryContext ?? phaseIdMod.phaseDirectoryContext(snapshot.config.value ?? {}, '', snapshot.roadmapDeclaredPhases.value.map(({ phaseId }) => phaseId));
266
+ const claimedDirs = computeClaimedDirs(dirs, snapshot.roadmapDeclaredPhases.value, convention, directoryContext);
265
267
  const diagnostics = [];
266
268
  for (const dirName of dirs) {
267
269
  // `extractPhaseToken` is the phase-id.cts owner `PHASE_TOKEN_FROM_DIR_RE`
@@ -46,7 +46,7 @@ const healthDiagnosticMod = require("../health-diagnostic-types.cjs");
46
46
  const { SEVERITY, adviseRemedy } = healthDiagnosticMod;
47
47
  // eslint-disable-next-line @typescript-eslint/no-require-imports
48
48
  const phaseIdMod = require("../phase-id.cjs");
49
- const { getMilestoneFromPhaseId, matchPhaseDirs, normalizePhaseName, extractPhaseToken, PHASE_NUMBER_TOKEN_SOURCE } = phaseIdMod;
49
+ const { getMilestoneFromPhaseId, matchPhaseDirs, phaseLookupQuery, extractPhaseToken, PHASE_NUMBER_TOKEN_SOURCE } = phaseIdMod;
50
50
  // eslint-disable-next-line @typescript-eslint/no-require-imports -- the single owner of the persisted status vocabulary
51
51
  const stateDocumentMod = require("../state-document.cjs");
52
52
  const { normalizeStateStatus } = stateDocumentMod;
@@ -332,8 +332,8 @@ const RULE_W026 = {
332
332
  // field's own doc comment on `PlanningSnapshot` for why
333
333
  // `roadmapDeclaredPhases`'s `milestone` attribution is the wrong fit).
334
334
  const unstarted = [];
335
+ const directoryContext = snapshot.directoryContext ?? phaseIdMod.phaseDirectoryContext(snapshot.config.value ?? {}, '', snapshot.currentMilestoneRoadmapPhaseIds.value);
335
336
  for (const phaseId of snapshot.currentMilestoneRoadmapPhaseIds.value) {
336
- const normalized = normalizePhaseName(phaseId);
337
337
  // `allPhaseDirNames` — every directory under `phases/`, UNWINDOWED by
338
338
  // ROADMAP-declaration membership — mirrors the original's own
339
339
  // unwindowed `phaseDirNames2` (`verify.cts:2372-2382`, a direct
@@ -346,7 +346,7 @@ const RULE_W026 = {
346
346
  // moved the read onto the shared selector; the convention rides along,
347
347
  // since the selector's primary match IS the `phaseTokenMatches` call this
348
348
  // line used to make directly.
349
- const hasDirectory = matchPhaseDirs(snapshot.allPhaseDirNames.value, normalized, snapshot.phaseIdConvention).matches.length > 0;
349
+ const hasDirectory = matchPhaseDirs(snapshot.allPhaseDirNames.value, phaseLookupQuery(phaseId, directoryContext), snapshot.phaseIdConvention, undefined, directoryContext).matches.length > 0;
350
350
  if (!hasDirectory)
351
351
  unstarted.push(phaseId);
352
352
  }
@@ -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
  });