@bhargavvc/sdd-cc 1.35.0 → 1.42.4

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 (1376) hide show
  1. package/README.ja-JP.md +54 -52
  2. package/README.ko-KR.md +47 -45
  3. package/README.md +86 -733
  4. package/README.pt-BR.md +14 -12
  5. package/README.zh-CN.md +31 -29
  6. package/agents/sdd-ai-researcher.md +2 -2
  7. package/agents/sdd-code-fixer.md +169 -17
  8. package/agents/sdd-code-reviewer.md +40 -8
  9. package/agents/sdd-codebase-mapper.md +89 -6
  10. package/agents/sdd-debug-session-manager.md +314 -0
  11. package/agents/sdd-debugger.md +147 -80
  12. package/agents/sdd-doc-classifier.md +168 -0
  13. package/agents/sdd-doc-synthesizer.md +204 -0
  14. package/agents/sdd-doc-verifier.md +20 -4
  15. package/agents/sdd-doc-writer.md +22 -9
  16. package/agents/sdd-domain-researcher.md +2 -2
  17. package/agents/sdd-eval-auditor.md +30 -3
  18. package/agents/sdd-eval-planner.md +2 -2
  19. package/agents/sdd-executor.md +203 -43
  20. package/agents/sdd-framework-selector.md +1 -1
  21. package/agents/sdd-integration-checker.md +30 -3
  22. package/agents/sdd-intel-updater.md +51 -23
  23. package/agents/sdd-nyquist-auditor.md +31 -4
  24. package/agents/sdd-pattern-mapper.md +335 -0
  25. package/agents/sdd-phase-researcher.md +195 -32
  26. package/agents/sdd-plan-checker.md +135 -24
  27. package/agents/sdd-planner.md +190 -205
  28. package/agents/sdd-project-researcher.md +7 -7
  29. package/agents/sdd-research-synthesizer.md +6 -6
  30. package/agents/sdd-roadmapper.md +19 -10
  31. package/agents/sdd-security-auditor.md +33 -6
  32. package/agents/sdd-ui-auditor.md +23 -7
  33. package/agents/sdd-ui-checker.md +16 -7
  34. package/agents/sdd-ui-researcher.md +8 -8
  35. package/agents/sdd-verifier.md +124 -27
  36. package/bin/install.js +5016 -372
  37. package/bin/sdd-sdk.js +37 -0
  38. package/commands/sdd/add-tests.md +5 -4
  39. package/commands/sdd/ai-integration-phase.md +4 -3
  40. package/commands/sdd/audit-fix.md +2 -1
  41. package/commands/sdd/audit-milestone.md +3 -2
  42. package/commands/sdd/autonomous.md +3 -3
  43. package/commands/sdd/capture.md +62 -0
  44. package/commands/sdd/cleanup.md +2 -1
  45. package/commands/sdd/code-review.md +8 -4
  46. package/commands/sdd/commit.md +39 -0
  47. package/commands/sdd/complete-milestone.md +15 -8
  48. package/commands/sdd/config.md +58 -0
  49. package/commands/sdd/debug.md +21 -155
  50. package/commands/sdd/discuss-phase.md +18 -11
  51. package/commands/sdd/docs-update.md +3 -2
  52. package/commands/sdd/eval-review.md +4 -3
  53. package/commands/sdd/execute-phase.md +5 -4
  54. package/commands/sdd/explore.md +3 -3
  55. package/commands/sdd/extract-learnings.md +23 -0
  56. package/commands/sdd/fast.md +4 -3
  57. package/commands/sdd/forensics.md +3 -2
  58. package/commands/sdd/graphify.md +199 -0
  59. package/commands/sdd/health.md +12 -3
  60. package/commands/sdd/help.md +1 -1
  61. package/commands/sdd/import.md +10 -5
  62. package/commands/sdd/inbox.md +39 -0
  63. package/commands/sdd/ingest-docs.md +42 -0
  64. package/commands/sdd/manager.md +8 -3
  65. package/commands/sdd/map-codebase.md +18 -6
  66. package/commands/sdd/milestone-summary.md +1 -1
  67. package/commands/sdd/mvp-phase.md +45 -0
  68. package/commands/sdd/new-milestone.md +4 -3
  69. package/commands/sdd/new-project.md +4 -3
  70. package/commands/sdd/ns-context.md +23 -0
  71. package/commands/sdd/ns-ideate.md +24 -0
  72. package/commands/sdd/ns-manage.md +29 -0
  73. package/commands/sdd/ns-project.md +22 -0
  74. package/commands/sdd/ns-review.md +26 -0
  75. package/commands/sdd/ns-workflow.md +28 -0
  76. package/commands/sdd/pause-work.md +6 -1
  77. package/commands/sdd/phase.md +56 -0
  78. package/commands/sdd/plan-phase.md +15 -5
  79. package/commands/sdd/plan-review-convergence.md +59 -0
  80. package/commands/sdd/pr-branch.md +2 -1
  81. package/commands/sdd/profile-user.md +1 -1
  82. package/commands/sdd/progress.md +27 -5
  83. package/commands/sdd/quick.md +128 -3
  84. package/commands/sdd/resume-work.md +2 -12
  85. package/commands/sdd/review-backlog.md +3 -2
  86. package/commands/sdd/review.md +3 -2
  87. package/commands/sdd/secure-phase.md +3 -2
  88. package/commands/sdd/settings.md +2 -9
  89. package/commands/sdd/ship.md +2 -1
  90. package/commands/sdd/sketch.md +60 -0
  91. package/commands/sdd/spec-phase.md +63 -0
  92. package/commands/sdd/spike.md +57 -0
  93. package/commands/sdd/stats.md +2 -1
  94. package/commands/sdd/surface.md +129 -0
  95. package/commands/sdd/thread.md +8 -111
  96. package/commands/sdd/ui-phase.md +3 -2
  97. package/commands/sdd/ui-review.md +3 -2
  98. package/commands/sdd/ultraplan-phase.md +34 -0
  99. package/commands/sdd/undo.md +2 -1
  100. package/commands/sdd/update.md +21 -10
  101. package/commands/sdd/validate-phase.md +3 -2
  102. package/commands/sdd/verify-work.md +5 -4
  103. package/commands/sdd/workspace.md +52 -0
  104. package/commands/sdd/workstreams.md +12 -11
  105. package/hooks/dist/sdd-check-update-worker.js +116 -0
  106. package/hooks/dist/sdd-check-update.js +13 -88
  107. package/hooks/dist/sdd-context-monitor.js +28 -1
  108. package/hooks/dist/sdd-phase-boundary.sh +23 -3
  109. package/hooks/dist/sdd-read-guard.js +21 -2
  110. package/hooks/dist/sdd-read-injection-scanner.js +152 -0
  111. package/hooks/dist/sdd-session-state.sh +38 -12
  112. package/hooks/dist/sdd-statusline.js +324 -28
  113. package/hooks/dist/sdd-update-banner.js +134 -0
  114. package/hooks/dist/sdd-validate-commit.sh +15 -5
  115. package/hooks/dist/sdd-workflow-guard.js +2 -2
  116. package/hooks/lib/git-cmd.js +150 -0
  117. package/hooks/sdd-check-update-worker.js +116 -0
  118. package/hooks/sdd-check-update.js +13 -88
  119. package/hooks/sdd-context-monitor.js +28 -1
  120. package/hooks/sdd-phase-boundary.sh +23 -3
  121. package/hooks/sdd-read-guard.js +21 -2
  122. package/hooks/sdd-read-injection-scanner.js +152 -0
  123. package/hooks/sdd-session-state.sh +38 -12
  124. package/hooks/sdd-statusline.js +324 -28
  125. package/hooks/sdd-update-banner.js +134 -0
  126. package/hooks/sdd-validate-commit.sh +15 -5
  127. package/hooks/sdd-workflow-guard.js +2 -2
  128. package/package.json +32 -7
  129. package/scripts/audit-workflow-script-paths.cjs +73 -0
  130. package/scripts/build-hooks.js +98 -4
  131. package/scripts/changeset/cli.cjs +269 -0
  132. package/scripts/changeset/github-release-notes.cjs +198 -0
  133. package/scripts/changeset/lint.cjs +110 -0
  134. package/scripts/changeset/new.cjs +137 -0
  135. package/scripts/changeset/parse.cjs +60 -0
  136. package/scripts/changeset/render.cjs +34 -0
  137. package/scripts/changeset/serialize.cjs +74 -0
  138. package/scripts/command-contract-helpers.cjs +61 -0
  139. package/scripts/diff-touches-shipped-paths.cjs +147 -0
  140. package/scripts/fix-slash-commands.cjs +106 -0
  141. package/scripts/gen-inventory-manifest.cjs +109 -0
  142. package/scripts/lint-command-contract.cjs +108 -0
  143. package/scripts/lint-descriptions.cjs +83 -0
  144. package/scripts/lint-no-source-grep-extras.cjs +81 -0
  145. package/scripts/lint-no-source-grep.cjs +174 -0
  146. package/scripts/lint-shell-command-projection-drift.cjs +57 -0
  147. package/scripts/lint-skill-deps.cjs +180 -0
  148. package/scripts/pr-template-policy.cjs +169 -0
  149. package/scripts/prompt-injection-scan.sh +2 -0
  150. package/scripts/rebrand-gsd-to-sdd.sh +4 -3
  151. package/scripts/strip-prose-atrefs.cjs +106 -0
  152. package/scripts/verify-tarball-sdk-dist.sh +69 -0
  153. package/sdd/bin/check-latest-version.cjs +104 -0
  154. package/sdd/bin/lib/active-workstream-store.cjs +85 -0
  155. package/sdd/bin/lib/adr-parser.cjs +394 -0
  156. package/sdd/bin/lib/artifacts.cjs +53 -0
  157. package/sdd/bin/lib/audit.cjs +755 -0
  158. package/sdd/bin/lib/cjs-command-router-adapter.cjs +39 -0
  159. package/sdd/bin/lib/clusters.cjs +136 -0
  160. package/sdd/bin/lib/command-aliases.generated.cjs +838 -0
  161. package/sdd/bin/lib/commands.cjs +108 -98
  162. package/sdd/bin/lib/config-schema.cjs +135 -0
  163. package/sdd/bin/lib/config.cjs +253 -68
  164. package/sdd/bin/lib/context-utilization.cjs +47 -0
  165. package/sdd/bin/lib/core.cjs +997 -607
  166. package/sdd/bin/lib/decisions.cjs +48 -0
  167. package/sdd/bin/lib/docs.cjs +36 -33
  168. package/sdd/bin/lib/drift.cjs +379 -0
  169. package/sdd/bin/lib/fallow-runner.cjs +109 -0
  170. package/sdd/bin/lib/frontmatter.cjs +19 -11
  171. package/sdd/bin/lib/gap-checker.cjs +197 -0
  172. package/sdd/bin/lib/graphify.cjs +577 -0
  173. package/sdd/bin/lib/init-command-router.cjs +70 -0
  174. package/sdd/bin/lib/init.cjs +603 -102
  175. package/sdd/bin/lib/install-profiles.cjs +572 -0
  176. package/sdd/bin/lib/installer-migration-authoring.cjs +117 -0
  177. package/sdd/bin/lib/installer-migration-report.cjs +328 -0
  178. package/sdd/bin/lib/installer-migrations/000-first-time-baseline.cjs +220 -0
  179. package/sdd/bin/lib/installer-migrations/001-legacy-orphan-files.cjs +41 -0
  180. package/sdd/bin/lib/installer-migrations/002-codex-legacy-hooks-json.cjs +80 -0
  181. package/sdd/bin/lib/installer-migrations.cjs +703 -0
  182. package/sdd/bin/lib/intel.cjs +35 -52
  183. package/sdd/bin/lib/learnings.cjs +2 -1
  184. package/sdd/bin/lib/milestone.cjs +313 -283
  185. package/sdd/bin/lib/model-catalog.cjs +136 -0
  186. package/sdd/bin/lib/model-profiles.cjs +25 -70
  187. package/sdd/bin/lib/phase-command-router.cjs +96 -0
  188. package/sdd/bin/lib/phase.cjs +556 -102
  189. package/sdd/bin/lib/phases-command-router.cjs +39 -0
  190. package/sdd/bin/lib/plan-scan.cjs +138 -0
  191. package/sdd/bin/lib/planning-workspace.cjs +361 -0
  192. package/sdd/bin/lib/profile-output.cjs +109 -43
  193. package/sdd/bin/lib/profile-pipeline.cjs +1 -1
  194. package/sdd/bin/lib/review-reviewer-selection.cjs +125 -0
  195. package/sdd/bin/lib/roadmap-command-router.cjs +23 -0
  196. package/sdd/bin/lib/roadmap.cjs +278 -17
  197. package/sdd/bin/lib/runtime-homes.cjs +178 -0
  198. package/sdd/bin/lib/sdd2-import.cjs +3 -3
  199. package/sdd/bin/lib/secrets.cjs +33 -0
  200. package/sdd/bin/lib/security.cjs +8 -7
  201. package/sdd/bin/lib/shell-command-projection.cjs +548 -0
  202. package/sdd/bin/lib/state-command-router.cjs +100 -0
  203. package/sdd/bin/lib/state-document.cjs +12 -0
  204. package/sdd/bin/lib/state-document.generated.cjs +127 -0
  205. package/sdd/bin/lib/state.cjs +720 -218
  206. package/sdd/bin/lib/surface.cjs +398 -0
  207. package/sdd/bin/lib/template.cjs +4 -2
  208. package/sdd/bin/lib/uat.cjs +9 -2
  209. package/sdd/bin/lib/validate-command-router.cjs +55 -0
  210. package/sdd/bin/lib/verify-command-router.cjs +34 -0
  211. package/sdd/bin/lib/verify.cjs +464 -137
  212. package/sdd/bin/lib/workstream-inventory.cjs +159 -0
  213. package/sdd/bin/lib/workstream-name-policy.cjs +33 -0
  214. package/sdd/bin/lib/workstream.cjs +73 -195
  215. package/sdd/bin/lib/worktree-safety.cjs +563 -0
  216. package/sdd/bin/sdd-tools.cjs +386 -252
  217. package/sdd/bin/verify-reapply-patches.cjs +247 -0
  218. package/sdd/contexts/review.md +1 -0
  219. package/sdd/references/artifact-types.md +18 -0
  220. package/sdd/references/autonomous-smart-discuss.md +277 -0
  221. package/sdd/references/checkpoints.md +36 -0
  222. package/sdd/references/context-budget.md +85 -49
  223. package/sdd/references/continuation-format.md +26 -22
  224. package/sdd/references/debugger-philosophy.md +76 -0
  225. package/sdd/references/decimal-phase-calculation.md +5 -5
  226. package/sdd/references/doc-conflict-engine.md +91 -0
  227. package/sdd/references/domain-probes.md +1 -1
  228. package/sdd/references/execute-mvp-tdd.md +81 -0
  229. package/sdd/references/executor-examples.md +110 -0
  230. package/sdd/references/gate-prompts.md +2 -2
  231. package/sdd/references/git-integration.md +10 -7
  232. package/sdd/references/git-planning-commit.md +6 -4
  233. package/sdd/references/mandatory-initial-read.md +2 -0
  234. package/sdd/references/model-profiles.md +106 -6
  235. package/sdd/references/mvp-concepts.md +49 -0
  236. package/sdd/references/phase-argument-parsing.md +3 -3
  237. package/sdd/references/planner-antipatterns.md +89 -0
  238. package/sdd/references/planner-chunked.md +49 -0
  239. package/sdd/references/planner-human-verify-mode.md +57 -0
  240. package/sdd/references/planner-mvp-mode.md +53 -0
  241. package/sdd/references/planner-revision.md +1 -1
  242. package/sdd/references/planner-source-audit.md +73 -0
  243. package/sdd/references/planning-config.md +30 -13
  244. package/sdd/references/project-skills-discovery.md +19 -0
  245. package/sdd/references/scout-codebase.md +51 -0
  246. package/sdd/references/skeleton-template.md +48 -0
  247. package/sdd/references/sketch-interactivity.md +41 -0
  248. package/sdd/references/sketch-theme-system.md +94 -0
  249. package/sdd/references/sketch-tooling.md +45 -0
  250. package/sdd/references/sketch-variant-patterns.md +81 -0
  251. package/sdd/references/spidr-splitting.md +69 -0
  252. package/sdd/references/tdd.md +67 -0
  253. package/sdd/references/thinking-partner.md +1 -1
  254. package/sdd/references/universal-anti-patterns.md +4 -4
  255. package/sdd/references/user-story-template.md +58 -0
  256. package/sdd/references/verification-overrides.md +3 -3
  257. package/sdd/references/verify-mvp-mode.md +85 -0
  258. package/sdd/references/workstream-flag.md +11 -11
  259. package/sdd/references/worktree-path-safety.md +89 -0
  260. package/sdd/templates/AI-SPEC.md +1 -1
  261. package/sdd/templates/DEBUG.md +8 -3
  262. package/sdd/templates/README.md +77 -0
  263. package/sdd/templates/UAT.md +4 -4
  264. package/sdd/templates/VALIDATION.md +1 -1
  265. package/sdd/templates/claude-md.md +5 -5
  266. package/sdd/templates/config.json +16 -2
  267. package/sdd/templates/debug-subagent-prompt.md +1 -1
  268. package/sdd/templates/dev-preferences.md +1 -1
  269. package/sdd/templates/discovery.md +2 -2
  270. package/sdd/templates/phase-prompt.md +1 -1
  271. package/sdd/templates/planner-subagent-prompt.md +3 -3
  272. package/sdd/templates/project.md +1 -1
  273. package/sdd/templates/research.md +41 -1
  274. package/sdd/templates/spec.md +307 -0
  275. package/sdd/templates/state.md +9 -1
  276. package/sdd/workflows/add-backlog.md +90 -0
  277. package/sdd/workflows/add-phase.md +7 -7
  278. package/sdd/workflows/add-tests.md +12 -12
  279. package/sdd/workflows/add-todo.md +4 -4
  280. package/sdd/workflows/ai-integration-phase.md +26 -16
  281. package/sdd/workflows/analyze-dependencies.md +3 -3
  282. package/sdd/workflows/audit-fix.md +23 -3
  283. package/sdd/workflows/audit-milestone.md +37 -20
  284. package/sdd/workflows/audit-uat.md +3 -3
  285. package/sdd/workflows/autonomous.md +31 -301
  286. package/sdd/workflows/check-todos.md +6 -6
  287. package/sdd/workflows/cleanup.md +1 -1
  288. package/sdd/workflows/code-review-fix.md +20 -16
  289. package/sdd/workflows/code-review.md +114 -16
  290. package/sdd/workflows/commit.md +166 -0
  291. package/sdd/workflows/complete-milestone.md +68 -15
  292. package/sdd/workflows/debug.md +231 -0
  293. package/sdd/workflows/diagnose-issues.md +8 -6
  294. package/sdd/workflows/discovery-phase.md +3 -3
  295. package/sdd/workflows/discuss-phase/modes/advisor.md +175 -0
  296. package/sdd/workflows/discuss-phase/modes/all.md +28 -0
  297. package/sdd/workflows/discuss-phase/modes/analyze.md +44 -0
  298. package/sdd/workflows/discuss-phase/modes/auto.md +56 -0
  299. package/sdd/workflows/discuss-phase/modes/batch.md +52 -0
  300. package/sdd/workflows/discuss-phase/modes/chain.md +97 -0
  301. package/sdd/workflows/discuss-phase/modes/default.md +141 -0
  302. package/sdd/workflows/discuss-phase/modes/power.md +44 -0
  303. package/sdd/workflows/discuss-phase/modes/text.md +55 -0
  304. package/sdd/workflows/discuss-phase/templates/checkpoint.json +18 -0
  305. package/sdd/workflows/discuss-phase/templates/context.md +136 -0
  306. package/sdd/workflows/discuss-phase/templates/discussion-log.md +50 -0
  307. package/sdd/workflows/discuss-phase-assumptions.md +24 -21
  308. package/sdd/workflows/discuss-phase-power.md +3 -3
  309. package/sdd/workflows/discuss-phase.md +203 -905
  310. package/sdd/workflows/do.md +25 -21
  311. package/sdd/workflows/docs-update.md +23 -17
  312. package/sdd/workflows/edit-phase.md +294 -0
  313. package/sdd/workflows/eval-review.md +7 -7
  314. package/sdd/workflows/execute-phase/steps/codebase-drift-gate.md +81 -0
  315. package/sdd/workflows/execute-phase/steps/per-plan-worktree-gate.md +94 -0
  316. package/sdd/workflows/execute-phase/steps/post-merge-gate.md +116 -0
  317. package/sdd/workflows/execute-phase.md +650 -252
  318. package/sdd/workflows/execute-plan.md +75 -35
  319. package/sdd/workflows/explore.md +7 -3
  320. package/sdd/workflows/extract-learnings.md +242 -0
  321. package/sdd/workflows/fast.md +13 -12
  322. package/sdd/workflows/forensics.md +19 -6
  323. package/sdd/workflows/graduation.md +195 -0
  324. package/sdd/workflows/health.md +49 -7
  325. package/sdd/workflows/help.md +340 -149
  326. package/sdd/workflows/import.md +20 -43
  327. package/sdd/workflows/inbox.md +5 -5
  328. package/sdd/workflows/ingest-docs.md +339 -0
  329. package/sdd/workflows/insert-phase.md +33 -12
  330. package/sdd/workflows/list-phase-assumptions.md +2 -2
  331. package/sdd/workflows/list-workspaces.md +2 -2
  332. package/sdd/workflows/manager.md +38 -11
  333. package/sdd/workflows/map-codebase.md +87 -23
  334. package/sdd/workflows/milestone-summary.md +8 -8
  335. package/sdd/workflows/mvp-phase.md +221 -0
  336. package/sdd/workflows/new-milestone.md +163 -23
  337. package/sdd/workflows/new-project.md +254 -53
  338. package/sdd/workflows/new-workspace.md +8 -8
  339. package/sdd/workflows/next.md +85 -18
  340. package/sdd/workflows/note.md +2 -2
  341. package/sdd/workflows/pause-work.md +13 -9
  342. package/sdd/workflows/plan-milestone-gaps.md +18 -11
  343. package/sdd/workflows/plan-phase.md +767 -94
  344. package/sdd/workflows/plan-review-convergence.md +329 -0
  345. package/sdd/workflows/plant-seed.md +146 -89
  346. package/sdd/workflows/pr-branch.md +1 -1
  347. package/sdd/workflows/profile-user.md +15 -15
  348. package/sdd/workflows/progress.md +198 -56
  349. package/sdd/workflows/quick.md +318 -54
  350. package/{commands/sdd → sdd/workflows}/reapply-patches.md +102 -23
  351. package/sdd/workflows/remove-phase.md +10 -10
  352. package/sdd/workflows/remove-workspace.md +21 -6
  353. package/sdd/workflows/resume-project.md +26 -23
  354. package/sdd/workflows/review.md +151 -20
  355. package/sdd/workflows/scan.md +5 -3
  356. package/sdd/workflows/secure-phase.md +26 -13
  357. package/sdd/workflows/settings-advanced.md +579 -0
  358. package/sdd/workflows/settings-integrations.md +281 -0
  359. package/sdd/workflows/settings.md +202 -23
  360. package/sdd/workflows/ship.md +131 -16
  361. package/sdd/workflows/sketch-wrap-up.md +285 -0
  362. package/sdd/workflows/sketch.md +360 -0
  363. package/sdd/workflows/spec-phase.md +262 -0
  364. package/sdd/workflows/spike-wrap-up.md +306 -0
  365. package/sdd/workflows/spike.md +452 -0
  366. package/sdd/workflows/stats.md +21 -2
  367. package/sdd/workflows/sync-skills.md +182 -0
  368. package/sdd/workflows/thread.md +221 -0
  369. package/sdd/workflows/transition.md +52 -30
  370. package/sdd/workflows/ui-phase.md +37 -20
  371. package/sdd/workflows/ui-review.md +12 -10
  372. package/sdd/workflows/ultraplan-phase.md +198 -0
  373. package/sdd/workflows/undo.md +9 -9
  374. package/sdd/workflows/update.md +187 -17
  375. package/sdd/workflows/validate-phase.md +12 -10
  376. package/sdd/workflows/verify-phase.md +112 -27
  377. package/sdd/workflows/verify-work.md +97 -28
  378. package/sdk/dist/cli-transport.d.ts +19 -0
  379. package/sdk/dist/cli-transport.d.ts.map +1 -0
  380. package/sdk/dist/cli-transport.js +104 -0
  381. package/sdk/dist/cli-transport.js.map +1 -0
  382. package/sdk/dist/cli.d.ts +46 -0
  383. package/sdk/dist/cli.d.ts.map +1 -0
  384. package/sdk/dist/cli.js +511 -0
  385. package/sdk/dist/cli.js.map +1 -0
  386. package/sdk/dist/config.d.ts +84 -0
  387. package/sdk/dist/config.d.ts.map +1 -0
  388. package/sdk/dist/config.js +135 -0
  389. package/sdk/dist/config.js.map +1 -0
  390. package/sdk/dist/context-engine.d.ts +49 -0
  391. package/sdk/dist/context-engine.d.ts.map +1 -0
  392. package/sdk/dist/context-engine.js +142 -0
  393. package/sdk/dist/context-engine.js.map +1 -0
  394. package/sdk/dist/context-truncation.d.ts +33 -0
  395. package/sdk/dist/context-truncation.d.ts.map +1 -0
  396. package/sdk/dist/context-truncation.js +197 -0
  397. package/sdk/dist/context-truncation.js.map +1 -0
  398. package/sdk/dist/errors.d.ts +46 -0
  399. package/sdk/dist/errors.d.ts.map +1 -0
  400. package/sdk/dist/errors.js +64 -0
  401. package/sdk/dist/errors.js.map +1 -0
  402. package/sdk/dist/event-stream.d.ts +53 -0
  403. package/sdk/dist/event-stream.d.ts.map +1 -0
  404. package/sdk/dist/event-stream.js +321 -0
  405. package/sdk/dist/event-stream.js.map +1 -0
  406. package/sdk/dist/golden/capture.d.ts +15 -0
  407. package/sdk/dist/golden/capture.d.ts.map +1 -0
  408. package/sdk/dist/golden/capture.js +67 -0
  409. package/sdk/dist/golden/capture.js.map +1 -0
  410. package/sdk/dist/golden/golden-integration-covered.d.ts +6 -0
  411. package/sdk/dist/golden/golden-integration-covered.d.ts.map +1 -0
  412. package/sdk/dist/golden/golden-integration-covered.js +30 -0
  413. package/sdk/dist/golden/golden-integration-covered.js.map +1 -0
  414. package/sdk/dist/golden/golden-mutation-covered.d.ts +7 -0
  415. package/sdk/dist/golden/golden-mutation-covered.d.ts.map +1 -0
  416. package/sdk/dist/golden/golden-mutation-covered.js +17 -0
  417. package/sdk/dist/golden/golden-mutation-covered.js.map +1 -0
  418. package/sdk/dist/golden/golden-policy.d.ts +10 -0
  419. package/sdk/dist/golden/golden-policy.d.ts.map +1 -0
  420. package/sdk/dist/golden/golden-policy.js +98 -0
  421. package/sdk/dist/golden/golden-policy.js.map +1 -0
  422. package/sdk/dist/golden/init-golden-normalize.d.ts +8 -0
  423. package/sdk/dist/golden/init-golden-normalize.d.ts.map +1 -0
  424. package/sdk/dist/golden/init-golden-normalize.js +14 -0
  425. package/sdk/dist/golden/init-golden-normalize.js.map +1 -0
  426. package/sdk/dist/golden/read-only-golden-rows.d.ts +20 -0
  427. package/sdk/dist/golden/read-only-golden-rows.d.ts.map +1 -0
  428. package/sdk/dist/golden/read-only-golden-rows.js +67 -0
  429. package/sdk/dist/golden/read-only-golden-rows.js.map +1 -0
  430. package/sdk/dist/golden/registry-canonical-commands.d.ts +6 -0
  431. package/sdk/dist/golden/registry-canonical-commands.d.ts.map +1 -0
  432. package/sdk/dist/golden/registry-canonical-commands.js +30 -0
  433. package/sdk/dist/golden/registry-canonical-commands.js.map +1 -0
  434. package/sdk/dist/index.d.ts +125 -0
  435. package/sdk/dist/index.d.ts.map +1 -0
  436. package/sdk/dist/index.js +298 -0
  437. package/sdk/dist/index.js.map +1 -0
  438. package/sdk/dist/init-runner.d.ts +90 -0
  439. package/sdk/dist/init-runner.d.ts.map +1 -0
  440. package/sdk/dist/init-runner.js +613 -0
  441. package/sdk/dist/init-runner.js.map +1 -0
  442. package/sdk/dist/logger.d.ts +50 -0
  443. package/sdk/dist/logger.d.ts.map +1 -0
  444. package/sdk/dist/logger.js +70 -0
  445. package/sdk/dist/logger.js.map +1 -0
  446. package/sdk/dist/model-catalog.d.ts +31 -0
  447. package/sdk/dist/model-catalog.d.ts.map +1 -0
  448. package/sdk/dist/model-catalog.js +31 -0
  449. package/sdk/dist/model-catalog.js.map +1 -0
  450. package/sdk/dist/phase-prompt.d.ts +72 -0
  451. package/sdk/dist/phase-prompt.d.ts.map +1 -0
  452. package/sdk/dist/phase-prompt.js +213 -0
  453. package/sdk/dist/phase-prompt.js.map +1 -0
  454. package/sdk/dist/phase-runner.d.ts +145 -0
  455. package/sdk/dist/phase-runner.d.ts.map +1 -0
  456. package/sdk/dist/phase-runner.js +1206 -0
  457. package/sdk/dist/phase-runner.js.map +1 -0
  458. package/sdk/dist/plan-parser.d.ts +55 -0
  459. package/sdk/dist/plan-parser.d.ts.map +1 -0
  460. package/sdk/dist/plan-parser.js +389 -0
  461. package/sdk/dist/plan-parser.js.map +1 -0
  462. package/sdk/dist/planning-journal.d.ts +64 -0
  463. package/sdk/dist/planning-journal.d.ts.map +1 -0
  464. package/sdk/dist/planning-journal.js +88 -0
  465. package/sdk/dist/planning-journal.js.map +1 -0
  466. package/sdk/dist/planning-runtime.d.ts +67 -0
  467. package/sdk/dist/planning-runtime.d.ts.map +1 -0
  468. package/sdk/dist/planning-runtime.js +58 -0
  469. package/sdk/dist/planning-runtime.js.map +1 -0
  470. package/sdk/dist/prompt-builder.d.ts +44 -0
  471. package/sdk/dist/prompt-builder.d.ts.map +1 -0
  472. package/sdk/dist/prompt-builder.js +180 -0
  473. package/sdk/dist/prompt-builder.js.map +1 -0
  474. package/sdk/dist/prompt-sanitizer.d.ts +35 -0
  475. package/sdk/dist/prompt-sanitizer.d.ts.map +1 -0
  476. package/sdk/dist/prompt-sanitizer.js +101 -0
  477. package/sdk/dist/prompt-sanitizer.js.map +1 -0
  478. package/sdk/dist/query/active-workstream-store.d.ts +7 -0
  479. package/sdk/dist/query/active-workstream-store.d.ts.map +1 -0
  480. package/sdk/dist/query/active-workstream-store.js +56 -0
  481. package/sdk/dist/query/active-workstream-store.js.map +1 -0
  482. package/sdk/dist/query/agent-failure-classifier.d.ts +38 -0
  483. package/sdk/dist/query/agent-failure-classifier.d.ts.map +1 -0
  484. package/sdk/dist/query/agent-failure-classifier.js +83 -0
  485. package/sdk/dist/query/agent-failure-classifier.js.map +1 -0
  486. package/sdk/dist/query/audit-open.d.ts +46 -0
  487. package/sdk/dist/query/audit-open.d.ts.map +1 -0
  488. package/sdk/dist/query/audit-open.js +662 -0
  489. package/sdk/dist/query/audit-open.js.map +1 -0
  490. package/sdk/dist/query/check-auto-mode.d.ts +13 -0
  491. package/sdk/dist/query/check-auto-mode.d.ts.map +1 -0
  492. package/sdk/dist/query/check-auto-mode.js +40 -0
  493. package/sdk/dist/query/check-auto-mode.js.map +1 -0
  494. package/sdk/dist/query/check-completion.d.ts +10 -0
  495. package/sdk/dist/query/check-completion.d.ts.map +1 -0
  496. package/sdk/dist/query/check-completion.js +157 -0
  497. package/sdk/dist/query/check-completion.js.map +1 -0
  498. package/sdk/dist/query/check-decision-coverage.d.ts +33 -0
  499. package/sdk/dist/query/check-decision-coverage.d.ts.map +1 -0
  500. package/sdk/dist/query/check-decision-coverage.js +472 -0
  501. package/sdk/dist/query/check-decision-coverage.js.map +1 -0
  502. package/sdk/dist/query/check-gates.d.ts +10 -0
  503. package/sdk/dist/query/check-gates.d.ts.map +1 -0
  504. package/sdk/dist/query/check-gates.js +89 -0
  505. package/sdk/dist/query/check-gates.js.map +1 -0
  506. package/sdk/dist/query/check-ship-ready.d.ts +10 -0
  507. package/sdk/dist/query/check-ship-ready.d.ts.map +1 -0
  508. package/sdk/dist/query/check-ship-ready.js +93 -0
  509. package/sdk/dist/query/check-ship-ready.js.map +1 -0
  510. package/sdk/dist/query/check-verification-status.d.ts +10 -0
  511. package/sdk/dist/query/check-verification-status.d.ts.map +1 -0
  512. package/sdk/dist/query/check-verification-status.js +142 -0
  513. package/sdk/dist/query/check-verification-status.js.map +1 -0
  514. package/sdk/dist/query/command-aliases.generated.d.ts +31 -0
  515. package/sdk/dist/query/command-aliases.generated.d.ts.map +1 -0
  516. package/sdk/dist/query/command-aliases.generated.js +135 -0
  517. package/sdk/dist/query/command-aliases.generated.js.map +1 -0
  518. package/sdk/dist/query/command-catalog.d.ts +9 -0
  519. package/sdk/dist/query/command-catalog.d.ts.map +1 -0
  520. package/sdk/dist/query/command-catalog.js +17 -0
  521. package/sdk/dist/query/command-catalog.js.map +1 -0
  522. package/sdk/dist/query/command-definition.d.ts +19 -0
  523. package/sdk/dist/query/command-definition.d.ts.map +1 -0
  524. package/sdk/dist/query/command-definition.js +44 -0
  525. package/sdk/dist/query/command-definition.js.map +1 -0
  526. package/sdk/dist/query/command-family-handlers.d.ts +3 -0
  527. package/sdk/dist/query/command-family-handlers.d.ts.map +1 -0
  528. package/sdk/dist/query/command-family-handlers.js +94 -0
  529. package/sdk/dist/query/command-family-handlers.js.map +1 -0
  530. package/sdk/dist/query/command-manifest.d.ts +2 -0
  531. package/sdk/dist/query/command-manifest.d.ts.map +1 -0
  532. package/sdk/dist/query/command-manifest.init.d.ts +6 -0
  533. package/sdk/dist/query/command-manifest.init.d.ts.map +1 -0
  534. package/sdk/dist/query/command-manifest.init.js +23 -0
  535. package/sdk/dist/query/command-manifest.init.js.map +1 -0
  536. package/sdk/dist/query/command-manifest.js +17 -0
  537. package/sdk/dist/query/command-manifest.js.map +1 -0
  538. package/sdk/dist/query/command-manifest.non-family.d.ts +9 -0
  539. package/sdk/dist/query/command-manifest.non-family.d.ts.map +1 -0
  540. package/sdk/dist/query/command-manifest.non-family.js +59 -0
  541. package/sdk/dist/query/command-manifest.non-family.js.map +1 -0
  542. package/sdk/dist/query/command-manifest.phase.d.ts +6 -0
  543. package/sdk/dist/query/command-manifest.phase.d.ts.map +1 -0
  544. package/sdk/dist/query/command-manifest.phase.js +15 -0
  545. package/sdk/dist/query/command-manifest.phase.js.map +1 -0
  546. package/sdk/dist/query/command-manifest.phases.d.ts +7 -0
  547. package/sdk/dist/query/command-manifest.phases.d.ts.map +1 -0
  548. package/sdk/dist/query/command-manifest.phases.js +10 -0
  549. package/sdk/dist/query/command-manifest.phases.js.map +1 -0
  550. package/sdk/dist/query/command-manifest.roadmap.d.ts +6 -0
  551. package/sdk/dist/query/command-manifest.roadmap.d.ts.map +1 -0
  552. package/sdk/dist/query/command-manifest.roadmap.js +10 -0
  553. package/sdk/dist/query/command-manifest.roadmap.js.map +1 -0
  554. package/sdk/dist/query/command-manifest.state.d.ts +9 -0
  555. package/sdk/dist/query/command-manifest.state.d.ts.map +1 -0
  556. package/sdk/dist/query/command-manifest.state.js +30 -0
  557. package/sdk/dist/query/command-manifest.state.js.map +1 -0
  558. package/sdk/dist/query/command-manifest.types.d.ts +12 -0
  559. package/sdk/dist/query/command-manifest.types.d.ts.map +1 -0
  560. package/sdk/dist/query/command-manifest.types.js +2 -0
  561. package/sdk/dist/query/command-manifest.types.js.map +1 -0
  562. package/sdk/dist/query/command-manifest.validate.d.ts +6 -0
  563. package/sdk/dist/query/command-manifest.validate.d.ts.map +1 -0
  564. package/sdk/dist/query/command-manifest.validate.js +10 -0
  565. package/sdk/dist/query/command-manifest.validate.js.map +1 -0
  566. package/sdk/dist/query/command-manifest.verify.d.ts +6 -0
  567. package/sdk/dist/query/command-manifest.verify.d.ts.map +1 -0
  568. package/sdk/dist/query/command-manifest.verify.js +14 -0
  569. package/sdk/dist/query/command-manifest.verify.js.map +1 -0
  570. package/sdk/dist/query/command-static-catalog-domain.d.ts +3 -0
  571. package/sdk/dist/query/command-static-catalog-domain.d.ts.map +1 -0
  572. package/sdk/dist/query/command-static-catalog-domain.js +116 -0
  573. package/sdk/dist/query/command-static-catalog-domain.js.map +1 -0
  574. package/sdk/dist/query/command-static-catalog-foundation.d.ts +7 -0
  575. package/sdk/dist/query/command-static-catalog-foundation.d.ts.map +1 -0
  576. package/sdk/dist/query/command-static-catalog-foundation.js +98 -0
  577. package/sdk/dist/query/command-static-catalog-foundation.js.map +1 -0
  578. package/sdk/dist/query/command-topology.d.ts +32 -0
  579. package/sdk/dist/query/command-topology.d.ts.map +1 -0
  580. package/sdk/dist/query/command-topology.js +66 -0
  581. package/sdk/dist/query/command-topology.js.map +1 -0
  582. package/sdk/dist/query/commands-list.d.ts +14 -0
  583. package/sdk/dist/query/commands-list.d.ts.map +1 -0
  584. package/sdk/dist/query/commands-list.js +18 -0
  585. package/sdk/dist/query/commands-list.js.map +1 -0
  586. package/sdk/dist/query/commit.d.ts +79 -0
  587. package/sdk/dist/query/commit.d.ts.map +1 -0
  588. package/sdk/dist/query/commit.js +340 -0
  589. package/sdk/dist/query/commit.js.map +1 -0
  590. package/sdk/dist/query/config-gates.d.ts +12 -0
  591. package/sdk/dist/query/config-gates.d.ts.map +1 -0
  592. package/sdk/dist/query/config-gates.js +66 -0
  593. package/sdk/dist/query/config-gates.js.map +1 -0
  594. package/sdk/dist/query/config-mutation.d.ts +86 -0
  595. package/sdk/dist/query/config-mutation.d.ts.map +1 -0
  596. package/sdk/dist/query/config-mutation.js +518 -0
  597. package/sdk/dist/query/config-mutation.js.map +1 -0
  598. package/sdk/dist/query/config-query.d.ts +57 -0
  599. package/sdk/dist/query/config-query.d.ts.map +1 -0
  600. package/sdk/dist/query/config-query.js +208 -0
  601. package/sdk/dist/query/config-query.js.map +1 -0
  602. package/sdk/dist/query/config-schema.d.ts +36 -0
  603. package/sdk/dist/query/config-schema.d.ts.map +1 -0
  604. package/sdk/dist/query/config-schema.js +147 -0
  605. package/sdk/dist/query/config-schema.js.map +1 -0
  606. package/sdk/dist/query/decisions.d.ts +58 -0
  607. package/sdk/dist/query/decisions.d.ts.map +1 -0
  608. package/sdk/dist/query/decisions.js +161 -0
  609. package/sdk/dist/query/decisions.js.map +1 -0
  610. package/sdk/dist/query/detect-custom-files.d.ts +11 -0
  611. package/sdk/dist/query/detect-custom-files.d.ts.map +1 -0
  612. package/sdk/dist/query/detect-custom-files.js +89 -0
  613. package/sdk/dist/query/detect-custom-files.js.map +1 -0
  614. package/sdk/dist/query/detect-phase-type.d.ts +9 -0
  615. package/sdk/dist/query/detect-phase-type.d.ts.map +1 -0
  616. package/sdk/dist/query/detect-phase-type.js +124 -0
  617. package/sdk/dist/query/detect-phase-type.js.map +1 -0
  618. package/sdk/dist/query/docs-init.d.ts +26 -0
  619. package/sdk/dist/query/docs-init.d.ts.map +1 -0
  620. package/sdk/dist/query/docs-init.js +231 -0
  621. package/sdk/dist/query/docs-init.js.map +1 -0
  622. package/sdk/dist/query/fallow-audit.d.ts +44 -0
  623. package/sdk/dist/query/fallow-audit.d.ts.map +1 -0
  624. package/sdk/dist/query/fallow-audit.js +44 -0
  625. package/sdk/dist/query/fallow-audit.js.map +1 -0
  626. package/sdk/dist/query/frontmatter-mutation.d.ts +77 -0
  627. package/sdk/dist/query/frontmatter-mutation.d.ts.map +1 -0
  628. package/sdk/dist/query/frontmatter-mutation.js +317 -0
  629. package/sdk/dist/query/frontmatter-mutation.js.map +1 -0
  630. package/sdk/dist/query/frontmatter.d.ts +93 -0
  631. package/sdk/dist/query/frontmatter.d.ts.map +1 -0
  632. package/sdk/dist/query/frontmatter.js +365 -0
  633. package/sdk/dist/query/frontmatter.js.map +1 -0
  634. package/sdk/dist/query/helpers.d.ts +191 -0
  635. package/sdk/dist/query/helpers.d.ts.map +1 -0
  636. package/sdk/dist/query/helpers.js +613 -0
  637. package/sdk/dist/query/helpers.js.map +1 -0
  638. package/sdk/dist/query/index.d.ts +8 -0
  639. package/sdk/dist/query/index.d.ts.map +1 -0
  640. package/sdk/dist/query/index.js +6 -0
  641. package/sdk/dist/query/index.js.map +1 -0
  642. package/sdk/dist/query/init-complex.d.ts +47 -0
  643. package/sdk/dist/query/init-complex.d.ts.map +1 -0
  644. package/sdk/dist/query/init-complex.js +718 -0
  645. package/sdk/dist/query/init-complex.js.map +1 -0
  646. package/sdk/dist/query/init.d.ts +106 -0
  647. package/sdk/dist/query/init.d.ts.map +1 -0
  648. package/sdk/dist/query/init.js +1159 -0
  649. package/sdk/dist/query/init.js.map +1 -0
  650. package/sdk/dist/query/intel.d.ts +43 -0
  651. package/sdk/dist/query/intel.d.ts.map +1 -0
  652. package/sdk/dist/query/intel.js +416 -0
  653. package/sdk/dist/query/intel.js.map +1 -0
  654. package/sdk/dist/query/mutation-event-decorator.d.ts +5 -0
  655. package/sdk/dist/query/mutation-event-decorator.d.ts.map +1 -0
  656. package/sdk/dist/query/mutation-event-decorator.js +28 -0
  657. package/sdk/dist/query/mutation-event-decorator.js.map +1 -0
  658. package/sdk/dist/query/mutation-event-mapper.d.ts +4 -0
  659. package/sdk/dist/query/mutation-event-mapper.d.ts.map +1 -0
  660. package/sdk/dist/query/mutation-event-mapper.js +70 -0
  661. package/sdk/dist/query/mutation-event-mapper.js.map +1 -0
  662. package/sdk/dist/query/mvp.d.ts +113 -0
  663. package/sdk/dist/query/mvp.d.ts.map +1 -0
  664. package/sdk/dist/query/mvp.js +225 -0
  665. package/sdk/dist/query/mvp.js.map +1 -0
  666. package/sdk/dist/query/phase-filesystem-adapter.d.ts +4 -0
  667. package/sdk/dist/query/phase-filesystem-adapter.d.ts.map +1 -0
  668. package/sdk/dist/query/phase-filesystem-adapter.js +33 -0
  669. package/sdk/dist/query/phase-filesystem-adapter.js.map +1 -0
  670. package/sdk/dist/query/phase-lifecycle-policy.d.ts +34 -0
  671. package/sdk/dist/query/phase-lifecycle-policy.d.ts.map +1 -0
  672. package/sdk/dist/query/phase-lifecycle-policy.js +138 -0
  673. package/sdk/dist/query/phase-lifecycle-policy.js.map +1 -0
  674. package/sdk/dist/query/phase-lifecycle.d.ts +116 -0
  675. package/sdk/dist/query/phase-lifecycle.d.ts.map +1 -0
  676. package/sdk/dist/query/phase-lifecycle.js +1486 -0
  677. package/sdk/dist/query/phase-lifecycle.js.map +1 -0
  678. package/sdk/dist/query/phase-list-queries.d.ts +18 -0
  679. package/sdk/dist/query/phase-list-queries.d.ts.map +1 -0
  680. package/sdk/dist/query/phase-list-queries.js +129 -0
  681. package/sdk/dist/query/phase-list-queries.js.map +1 -0
  682. package/sdk/dist/query/phase-ready.d.ts +9 -0
  683. package/sdk/dist/query/phase-ready.d.ts.map +1 -0
  684. package/sdk/dist/query/phase-ready.js +132 -0
  685. package/sdk/dist/query/phase-ready.js.map +1 -0
  686. package/sdk/dist/query/phase-roadmap-mutation.d.ts +13 -0
  687. package/sdk/dist/query/phase-roadmap-mutation.d.ts.map +1 -0
  688. package/sdk/dist/query/phase-roadmap-mutation.js +65 -0
  689. package/sdk/dist/query/phase-roadmap-mutation.js.map +1 -0
  690. package/sdk/dist/query/phase.d.ts +48 -0
  691. package/sdk/dist/query/phase.d.ts.map +1 -0
  692. package/sdk/dist/query/phase.js +451 -0
  693. package/sdk/dist/query/phase.js.map +1 -0
  694. package/sdk/dist/query/pipeline.d.ts +53 -0
  695. package/sdk/dist/query/pipeline.d.ts.map +1 -0
  696. package/sdk/dist/query/pipeline.js +198 -0
  697. package/sdk/dist/query/pipeline.js.map +1 -0
  698. package/sdk/dist/query/plan-scan.d.ts +14 -0
  699. package/sdk/dist/query/plan-scan.d.ts.map +1 -0
  700. package/sdk/dist/query/plan-scan.js +70 -0
  701. package/sdk/dist/query/plan-scan.js.map +1 -0
  702. package/sdk/dist/query/plan-task-structure.d.ts +9 -0
  703. package/sdk/dist/query/plan-task-structure.d.ts.map +1 -0
  704. package/sdk/dist/query/plan-task-structure.js +59 -0
  705. package/sdk/dist/query/plan-task-structure.js.map +1 -0
  706. package/sdk/dist/query/profile-extract-messages.d.ts +40 -0
  707. package/sdk/dist/query/profile-extract-messages.d.ts.map +1 -0
  708. package/sdk/dist/query/profile-extract-messages.js +195 -0
  709. package/sdk/dist/query/profile-extract-messages.js.map +1 -0
  710. package/sdk/dist/query/profile-output.d.ts +11 -0
  711. package/sdk/dist/query/profile-output.d.ts.map +1 -0
  712. package/sdk/dist/query/profile-output.js +873 -0
  713. package/sdk/dist/query/profile-output.js.map +1 -0
  714. package/sdk/dist/query/profile-questionnaire-data.d.ts +21 -0
  715. package/sdk/dist/query/profile-questionnaire-data.d.ts.map +1 -0
  716. package/sdk/dist/query/profile-questionnaire-data.js +171 -0
  717. package/sdk/dist/query/profile-questionnaire-data.js.map +1 -0
  718. package/sdk/dist/query/profile-sample.d.ts +22 -0
  719. package/sdk/dist/query/profile-sample.d.ts.map +1 -0
  720. package/sdk/dist/query/profile-sample.js +136 -0
  721. package/sdk/dist/query/profile-sample.js.map +1 -0
  722. package/sdk/dist/query/profile-scan-sessions.d.ts +49 -0
  723. package/sdk/dist/query/profile-scan-sessions.d.ts.map +1 -0
  724. package/sdk/dist/query/profile-scan-sessions.js +137 -0
  725. package/sdk/dist/query/profile-scan-sessions.js.map +1 -0
  726. package/sdk/dist/query/profile.d.ts +61 -0
  727. package/sdk/dist/query/profile.d.ts.map +1 -0
  728. package/sdk/dist/query/profile.js +307 -0
  729. package/sdk/dist/query/profile.js.map +1 -0
  730. package/sdk/dist/query/progress.d.ts +77 -0
  731. package/sdk/dist/query/progress.d.ts.map +1 -0
  732. package/sdk/dist/query/progress.js +481 -0
  733. package/sdk/dist/query/progress.js.map +1 -0
  734. package/sdk/dist/query/query-cli-adapter.d.ts +8 -0
  735. package/sdk/dist/query/query-cli-adapter.d.ts.map +1 -0
  736. package/sdk/dist/query/query-cli-adapter.js +32 -0
  737. package/sdk/dist/query/query-cli-adapter.js.map +1 -0
  738. package/sdk/dist/query/query-cli-output.d.ts +9 -0
  739. package/sdk/dist/query/query-cli-output.d.ts.map +1 -0
  740. package/sdk/dist/query/query-cli-output.js +28 -0
  741. package/sdk/dist/query/query-cli-output.js.map +1 -0
  742. package/sdk/dist/query/query-command-diagnosis.d.ts +6 -0
  743. package/sdk/dist/query/query-command-diagnosis.d.ts.map +1 -0
  744. package/sdk/dist/query/query-command-diagnosis.js +6 -0
  745. package/sdk/dist/query/query-command-diagnosis.js.map +1 -0
  746. package/sdk/dist/query/query-command-resolution-strategy.d.ts +29 -0
  747. package/sdk/dist/query/query-command-resolution-strategy.d.ts.map +1 -0
  748. package/sdk/dist/query/query-command-resolution-strategy.js +103 -0
  749. package/sdk/dist/query/query-command-resolution-strategy.js.map +1 -0
  750. package/sdk/dist/query/query-command-semantics.d.ts +7 -0
  751. package/sdk/dist/query/query-command-semantics.d.ts.map +1 -0
  752. package/sdk/dist/query/query-command-semantics.js +7 -0
  753. package/sdk/dist/query/query-command-semantics.js.map +1 -0
  754. package/sdk/dist/query/query-dispatch-contract.d.ts +21 -0
  755. package/sdk/dist/query/query-dispatch-contract.d.ts.map +1 -0
  756. package/sdk/dist/query/query-dispatch-contract.js +2 -0
  757. package/sdk/dist/query/query-dispatch-contract.js.map +1 -0
  758. package/sdk/dist/query/query-dispatch-error-mapper.d.ts +6 -0
  759. package/sdk/dist/query/query-dispatch-error-mapper.d.ts.map +1 -0
  760. package/sdk/dist/query/query-dispatch-error-mapper.js +6 -0
  761. package/sdk/dist/query/query-dispatch-error-mapper.js.map +1 -0
  762. package/sdk/dist/query/query-dispatch-formatting.d.ts +6 -0
  763. package/sdk/dist/query/query-dispatch-formatting.d.ts.map +1 -0
  764. package/sdk/dist/query/query-dispatch-formatting.js +6 -0
  765. package/sdk/dist/query/query-dispatch-formatting.js.map +1 -0
  766. package/sdk/dist/query/query-dispatch-input-validation.d.ts +6 -0
  767. package/sdk/dist/query/query-dispatch-input-validation.d.ts.map +1 -0
  768. package/sdk/dist/query/query-dispatch-input-validation.js +6 -0
  769. package/sdk/dist/query/query-dispatch-input-validation.js.map +1 -0
  770. package/sdk/dist/query/query-dispatch-observability.d.ts +2 -0
  771. package/sdk/dist/query/query-dispatch-observability.d.ts.map +1 -0
  772. package/sdk/dist/query/query-dispatch-observability.js +7 -0
  773. package/sdk/dist/query/query-dispatch-observability.js.map +1 -0
  774. package/sdk/dist/query/query-dispatch-plan.d.ts +6 -0
  775. package/sdk/dist/query/query-dispatch-plan.d.ts.map +1 -0
  776. package/sdk/dist/query/query-dispatch-plan.js +6 -0
  777. package/sdk/dist/query/query-dispatch-plan.js.map +1 -0
  778. package/sdk/dist/query/query-dispatch-result-builder.d.ts +6 -0
  779. package/sdk/dist/query/query-dispatch-result-builder.d.ts.map +1 -0
  780. package/sdk/dist/query/query-dispatch-result-builder.js +6 -0
  781. package/sdk/dist/query/query-dispatch-result-builder.js.map +1 -0
  782. package/sdk/dist/query/query-dispatch.d.ts +48 -0
  783. package/sdk/dist/query/query-dispatch.d.ts.map +1 -0
  784. package/sdk/dist/query/query-dispatch.js +175 -0
  785. package/sdk/dist/query/query-dispatch.js.map +1 -0
  786. package/sdk/dist/query/query-error-details-schema.d.ts +19 -0
  787. package/sdk/dist/query/query-error-details-schema.d.ts.map +1 -0
  788. package/sdk/dist/query/query-error-details-schema.js +10 -0
  789. package/sdk/dist/query/query-error-details-schema.js.map +1 -0
  790. package/sdk/dist/query/query-error-taxonomy.d.ts +38 -0
  791. package/sdk/dist/query/query-error-taxonomy.d.ts.map +1 -0
  792. package/sdk/dist/query/query-error-taxonomy.js +74 -0
  793. package/sdk/dist/query/query-error-taxonomy.js.map +1 -0
  794. package/sdk/dist/query/query-fallback-bridge-adapter.d.ts +14 -0
  795. package/sdk/dist/query/query-fallback-bridge-adapter.d.ts.map +1 -0
  796. package/sdk/dist/query/query-fallback-bridge-adapter.js +33 -0
  797. package/sdk/dist/query/query-fallback-bridge-adapter.js.map +1 -0
  798. package/sdk/dist/query/query-fallback-executor.d.ts +11 -0
  799. package/sdk/dist/query/query-fallback-executor.d.ts.map +1 -0
  800. package/sdk/dist/query/query-fallback-executor.js +31 -0
  801. package/sdk/dist/query/query-fallback-executor.js.map +1 -0
  802. package/sdk/dist/query/query-fallback-output-classifier.d.ts +6 -0
  803. package/sdk/dist/query/query-fallback-output-classifier.d.ts.map +1 -0
  804. package/sdk/dist/query/query-fallback-output-classifier.js +27 -0
  805. package/sdk/dist/query/query-fallback-output-classifier.js.map +1 -0
  806. package/sdk/dist/query/query-fallback-policy.d.ts +6 -0
  807. package/sdk/dist/query/query-fallback-policy.d.ts.map +1 -0
  808. package/sdk/dist/query/query-fallback-policy.js +7 -0
  809. package/sdk/dist/query/query-fallback-policy.js.map +1 -0
  810. package/sdk/dist/query/query-native-dispatch-adapter.d.ts +7 -0
  811. package/sdk/dist/query/query-native-dispatch-adapter.d.ts.map +1 -0
  812. package/sdk/dist/query/query-native-dispatch-adapter.js +6 -0
  813. package/sdk/dist/query/query-native-dispatch-adapter.js.map +1 -0
  814. package/sdk/dist/query/query-policy-capability.d.ts +10 -0
  815. package/sdk/dist/query/query-policy-capability.d.ts.map +1 -0
  816. package/sdk/dist/query/query-policy-capability.js +17 -0
  817. package/sdk/dist/query/query-policy-capability.js.map +1 -0
  818. package/sdk/dist/query/query-runtime-context.d.ts +19 -0
  819. package/sdk/dist/query/query-runtime-context.d.ts.map +1 -0
  820. package/sdk/dist/query/query-runtime-context.js +31 -0
  821. package/sdk/dist/query/query-runtime-context.js.map +1 -0
  822. package/sdk/dist/query/query-unknown-command-hints.d.ts +2 -0
  823. package/sdk/dist/query/query-unknown-command-hints.d.ts.map +1 -0
  824. package/sdk/dist/query/query-unknown-command-hints.js +6 -0
  825. package/sdk/dist/query/query-unknown-command-hints.js.map +1 -0
  826. package/sdk/dist/query/registry-assembly-descriptor.d.ts +12 -0
  827. package/sdk/dist/query/registry-assembly-descriptor.d.ts.map +1 -0
  828. package/sdk/dist/query/registry-assembly-descriptor.js +61 -0
  829. package/sdk/dist/query/registry-assembly-descriptor.js.map +1 -0
  830. package/sdk/dist/query/registry-assembly-invariants.d.ts +30 -0
  831. package/sdk/dist/query/registry-assembly-invariants.d.ts.map +1 -0
  832. package/sdk/dist/query/registry-assembly-invariants.js +77 -0
  833. package/sdk/dist/query/registry-assembly-invariants.js.map +1 -0
  834. package/sdk/dist/query/registry-assembly.d.ts +10 -0
  835. package/sdk/dist/query/registry-assembly.d.ts.map +1 -0
  836. package/sdk/dist/query/registry-assembly.js +53 -0
  837. package/sdk/dist/query/registry-assembly.js.map +1 -0
  838. package/sdk/dist/query/registry.d.ts +90 -0
  839. package/sdk/dist/query/registry.d.ts.map +1 -0
  840. package/sdk/dist/query/registry.js +129 -0
  841. package/sdk/dist/query/registry.js.map +1 -0
  842. package/sdk/dist/query/requirements-extract-from-plans.d.ts +9 -0
  843. package/sdk/dist/query/requirements-extract-from-plans.d.ts.map +1 -0
  844. package/sdk/dist/query/requirements-extract-from-plans.js +76 -0
  845. package/sdk/dist/query/requirements-extract-from-plans.js.map +1 -0
  846. package/sdk/dist/query/roadmap-update-plan-progress.d.ts +11 -0
  847. package/sdk/dist/query/roadmap-update-plan-progress.d.ts.map +1 -0
  848. package/sdk/dist/query/roadmap-update-plan-progress.js +124 -0
  849. package/sdk/dist/query/roadmap-update-plan-progress.js.map +1 -0
  850. package/sdk/dist/query/roadmap.d.ts +137 -0
  851. package/sdk/dist/query/roadmap.d.ts.map +1 -0
  852. package/sdk/dist/query/roadmap.js +753 -0
  853. package/sdk/dist/query/roadmap.js.map +1 -0
  854. package/sdk/dist/query/route-next-action.d.ts +9 -0
  855. package/sdk/dist/query/route-next-action.d.ts.map +1 -0
  856. package/sdk/dist/query/route-next-action.js +318 -0
  857. package/sdk/dist/query/route-next-action.js.map +1 -0
  858. package/sdk/dist/query/schema-detect.d.ts +21 -0
  859. package/sdk/dist/query/schema-detect.d.ts.map +1 -0
  860. package/sdk/dist/query/schema-detect.js +146 -0
  861. package/sdk/dist/query/schema-detect.js.map +1 -0
  862. package/sdk/dist/query/secrets.d.ts +27 -0
  863. package/sdk/dist/query/secrets.d.ts.map +1 -0
  864. package/sdk/dist/query/secrets.js +42 -0
  865. package/sdk/dist/query/secrets.js.map +1 -0
  866. package/sdk/dist/query/skill-manifest.d.ts +50 -0
  867. package/sdk/dist/query/skill-manifest.d.ts.map +1 -0
  868. package/sdk/dist/query/skill-manifest.js +171 -0
  869. package/sdk/dist/query/skill-manifest.js.map +1 -0
  870. package/sdk/dist/query/skills.d.ts +27 -0
  871. package/sdk/dist/query/skills.d.ts.map +1 -0
  872. package/sdk/dist/query/skills.js +137 -0
  873. package/sdk/dist/query/skills.js.map +1 -0
  874. package/sdk/dist/query/state-document.d.ts +14 -0
  875. package/sdk/dist/query/state-document.d.ts.map +1 -0
  876. package/sdk/dist/query/state-document.js +110 -0
  877. package/sdk/dist/query/state-document.js.map +1 -0
  878. package/sdk/dist/query/state-mutation.d.ts +224 -0
  879. package/sdk/dist/query/state-mutation.d.ts.map +1 -0
  880. package/sdk/dist/query/state-mutation.js +1539 -0
  881. package/sdk/dist/query/state-mutation.js.map +1 -0
  882. package/sdk/dist/query/state-project-load.d.ts +23 -0
  883. package/sdk/dist/query/state-project-load.d.ts.map +1 -0
  884. package/sdk/dist/query/state-project-load.js +75 -0
  885. package/sdk/dist/query/state-project-load.js.map +1 -0
  886. package/sdk/dist/query/state.d.ts +78 -0
  887. package/sdk/dist/query/state.d.ts.map +1 -0
  888. package/sdk/dist/query/state.js +430 -0
  889. package/sdk/dist/query/state.js.map +1 -0
  890. package/sdk/dist/query/summary.d.ts +18 -0
  891. package/sdk/dist/query/summary.d.ts.map +1 -0
  892. package/sdk/dist/query/summary.js +249 -0
  893. package/sdk/dist/query/summary.js.map +1 -0
  894. package/sdk/dist/query/template.d.ts +46 -0
  895. package/sdk/dist/query/template.d.ts.map +1 -0
  896. package/sdk/dist/query/template.js +210 -0
  897. package/sdk/dist/query/template.js.map +1 -0
  898. package/sdk/dist/query/uat.d.ts +34 -0
  899. package/sdk/dist/query/uat.d.ts.map +1 -0
  900. package/sdk/dist/query/uat.js +339 -0
  901. package/sdk/dist/query/uat.js.map +1 -0
  902. package/sdk/dist/query/utils.d.ts +59 -0
  903. package/sdk/dist/query/utils.d.ts.map +1 -0
  904. package/sdk/dist/query/utils.js +74 -0
  905. package/sdk/dist/query/utils.js.map +1 -0
  906. package/sdk/dist/query/validate.d.ts +67 -0
  907. package/sdk/dist/query/validate.d.ts.map +1 -0
  908. package/sdk/dist/query/validate.js +908 -0
  909. package/sdk/dist/query/validate.js.map +1 -0
  910. package/sdk/dist/query/verify.d.ts +110 -0
  911. package/sdk/dist/query/verify.d.ts.map +1 -0
  912. package/sdk/dist/query/verify.js +631 -0
  913. package/sdk/dist/query/verify.js.map +1 -0
  914. package/sdk/dist/query/websearch.d.ts +24 -0
  915. package/sdk/dist/query/websearch.d.ts.map +1 -0
  916. package/sdk/dist/query/websearch.js +68 -0
  917. package/sdk/dist/query/websearch.js.map +1 -0
  918. package/sdk/dist/query/workspace.d.ts +62 -0
  919. package/sdk/dist/query/workspace.d.ts.map +1 -0
  920. package/sdk/dist/query/workspace.js +104 -0
  921. package/sdk/dist/query/workspace.js.map +1 -0
  922. package/sdk/dist/query/workstream-inventory.d.ts +52 -0
  923. package/sdk/dist/query/workstream-inventory.d.ts.map +1 -0
  924. package/sdk/dist/query/workstream-inventory.js +141 -0
  925. package/sdk/dist/query/workstream-inventory.js.map +1 -0
  926. package/sdk/dist/query/workstream.d.ts +35 -0
  927. package/sdk/dist/query/workstream.d.ts.map +1 -0
  928. package/sdk/dist/query/workstream.js +298 -0
  929. package/sdk/dist/query/workstream.js.map +1 -0
  930. package/sdk/dist/query/worktree.d.ts +3 -0
  931. package/sdk/dist/query/worktree.d.ts.map +1 -0
  932. package/sdk/dist/query/worktree.js +36 -0
  933. package/sdk/dist/query/worktree.js.map +1 -0
  934. package/sdk/dist/query-command-executor.d.ts +22 -0
  935. package/sdk/dist/query-command-executor.d.ts.map +1 -0
  936. package/sdk/dist/query-command-executor.js +22 -0
  937. package/sdk/dist/query-command-executor.js.map +1 -0
  938. package/sdk/dist/query-execution-policy.d.ts +24 -0
  939. package/sdk/dist/query-execution-policy.d.ts.map +1 -0
  940. package/sdk/dist/query-execution-policy.js +27 -0
  941. package/sdk/dist/query-execution-policy.js.map +1 -0
  942. package/sdk/dist/query-failure-classification.d.ts +9 -0
  943. package/sdk/dist/query-failure-classification.d.ts.map +1 -0
  944. package/sdk/dist/query-failure-classification.js +32 -0
  945. package/sdk/dist/query-failure-classification.js.map +1 -0
  946. package/sdk/dist/query-hotpath-methods.d.ts +19 -0
  947. package/sdk/dist/query-hotpath-methods.d.ts.map +1 -0
  948. package/sdk/dist/query-hotpath-methods.js +34 -0
  949. package/sdk/dist/query-hotpath-methods.js.map +1 -0
  950. package/sdk/dist/query-native-direct-adapter.d.ts +20 -0
  951. package/sdk/dist/query-native-direct-adapter.d.ts.map +1 -0
  952. package/sdk/dist/query-native-direct-adapter.js +52 -0
  953. package/sdk/dist/query-native-direct-adapter.js.map +1 -0
  954. package/sdk/dist/query-native-hotpath-adapter.d.ts +15 -0
  955. package/sdk/dist/query-native-hotpath-adapter.d.ts.map +1 -0
  956. package/sdk/dist/query-native-hotpath-adapter.js +32 -0
  957. package/sdk/dist/query-native-hotpath-adapter.js.map +1 -0
  958. package/sdk/dist/query-raw-output-projection.d.ts +6 -0
  959. package/sdk/dist/query-raw-output-projection.d.ts.map +1 -0
  960. package/sdk/dist/query-raw-output-projection.js +67 -0
  961. package/sdk/dist/query-raw-output-projection.js.map +1 -0
  962. package/sdk/dist/query-runtime-bridge.d.ts +61 -0
  963. package/sdk/dist/query-runtime-bridge.d.ts.map +1 -0
  964. package/sdk/dist/query-runtime-bridge.js +144 -0
  965. package/sdk/dist/query-runtime-bridge.js.map +1 -0
  966. package/sdk/dist/query-sdd-tools-path.d.ts +2 -0
  967. package/sdk/dist/query-sdd-tools-path.d.ts.map +1 -0
  968. package/sdk/dist/query-sdd-tools-path.js +2 -0
  969. package/sdk/dist/query-sdd-tools-path.js.map +1 -0
  970. package/sdk/dist/query-sdd-tools-runtime.d.ts +20 -0
  971. package/sdk/dist/query-sdd-tools-runtime.d.ts.map +1 -0
  972. package/sdk/dist/query-sdd-tools-runtime.js +47 -0
  973. package/sdk/dist/query-sdd-tools-runtime.js.map +1 -0
  974. package/sdk/dist/query-subprocess-adapter.d.ts +18 -0
  975. package/sdk/dist/query-subprocess-adapter.d.ts.map +1 -0
  976. package/sdk/dist/query-subprocess-adapter.js +92 -0
  977. package/sdk/dist/query-subprocess-adapter.js.map +1 -0
  978. package/sdk/dist/query-tools-error-factory.d.ts +16 -0
  979. package/sdk/dist/query-tools-error-factory.d.ts.map +1 -0
  980. package/sdk/dist/query-tools-error-factory.js +33 -0
  981. package/sdk/dist/query-tools-error-factory.js.map +1 -0
  982. package/sdk/dist/research-gate.d.ts +24 -0
  983. package/sdk/dist/research-gate.d.ts.map +1 -0
  984. package/sdk/dist/research-gate.js +70 -0
  985. package/sdk/dist/research-gate.js.map +1 -0
  986. package/sdk/dist/runtime-gate.d.ts +14 -0
  987. package/sdk/dist/runtime-gate.d.ts.map +1 -0
  988. package/sdk/dist/runtime-gate.js +48 -0
  989. package/sdk/dist/runtime-gate.js.map +1 -0
  990. package/sdk/dist/sdd-tools-error.d.ts +23 -0
  991. package/sdk/dist/sdd-tools-error.d.ts.map +1 -0
  992. package/sdk/dist/sdd-tools-error.js +29 -0
  993. package/sdk/dist/sdd-tools-error.js.map +1 -0
  994. package/sdk/dist/sdd-tools.d.ts +97 -0
  995. package/sdk/dist/sdd-tools.d.ts.map +1 -0
  996. package/sdk/dist/sdd-tools.js +168 -0
  997. package/sdk/dist/sdd-tools.js.map +1 -0
  998. package/sdk/dist/sdd-transport-policy.d.ts +10 -0
  999. package/sdk/dist/sdd-transport-policy.d.ts.map +1 -0
  1000. package/sdk/dist/sdd-transport-policy.js +32 -0
  1001. package/sdk/dist/sdd-transport-policy.js.map +1 -0
  1002. package/sdk/dist/sdd-transport.d.ts +39 -0
  1003. package/sdk/dist/sdd-transport.d.ts.map +1 -0
  1004. package/sdk/dist/sdd-transport.js +78 -0
  1005. package/sdk/dist/sdd-transport.js.map +1 -0
  1006. package/sdk/dist/sdk-package-compatibility.d.ts +38 -0
  1007. package/sdk/dist/sdk-package-compatibility.d.ts.map +1 -0
  1008. package/sdk/dist/sdk-package-compatibility.js +90 -0
  1009. package/sdk/dist/sdk-package-compatibility.js.map +1 -0
  1010. package/sdk/dist/session-runner.d.ts +40 -0
  1011. package/sdk/dist/session-runner.d.ts.map +1 -0
  1012. package/sdk/dist/session-runner.js +274 -0
  1013. package/sdk/dist/session-runner.js.map +1 -0
  1014. package/sdk/dist/tool-scoping.d.ts +31 -0
  1015. package/sdk/dist/tool-scoping.d.ts.map +1 -0
  1016. package/sdk/dist/tool-scoping.js +54 -0
  1017. package/sdk/dist/tool-scoping.js.map +1 -0
  1018. package/sdk/dist/types.d.ts +794 -0
  1019. package/sdk/dist/types.d.ts.map +1 -0
  1020. package/sdk/dist/types.js +77 -0
  1021. package/sdk/dist/types.js.map +1 -0
  1022. package/sdk/dist/workstream-name-policy.d.ts +13 -0
  1023. package/sdk/dist/workstream-name-policy.d.ts.map +1 -0
  1024. package/sdk/dist/workstream-name-policy.js +24 -0
  1025. package/sdk/dist/workstream-name-policy.js.map +1 -0
  1026. package/sdk/dist/workstream-utils.d.ts +15 -0
  1027. package/sdk/dist/workstream-utils.d.ts.map +1 -0
  1028. package/sdk/dist/workstream-utils.js +21 -0
  1029. package/sdk/dist/workstream-utils.js.map +1 -0
  1030. package/sdk/dist/ws-transport.d.ts +32 -0
  1031. package/sdk/dist/ws-transport.d.ts.map +1 -0
  1032. package/sdk/dist/ws-transport.js +84 -0
  1033. package/sdk/dist/ws-transport.js.map +1 -0
  1034. package/sdk/package-lock.json +2502 -0
  1035. package/sdk/package.json +57 -0
  1036. package/sdk/prompts/templates/project.md +186 -0
  1037. package/sdk/prompts/templates/requirements.md +231 -0
  1038. package/sdk/prompts/templates/research-project/ARCHITECTURE.md +204 -0
  1039. package/sdk/prompts/templates/research-project/FEATURES.md +147 -0
  1040. package/sdk/prompts/templates/research-project/PITFALLS.md +200 -0
  1041. package/sdk/prompts/templates/research-project/STACK.md +120 -0
  1042. package/sdk/prompts/templates/research-project/SUMMARY.md +170 -0
  1043. package/sdk/prompts/templates/roadmap.md +202 -0
  1044. package/sdk/prompts/templates/state.md +175 -0
  1045. package/sdk/shared/model-catalog.json +122 -0
  1046. package/sdk/src/assembled-prompts.test.ts +349 -0
  1047. package/sdk/src/bug-3591-sddtools-runtime-workstream.test.ts +179 -0
  1048. package/sdk/src/cli-transport.test.ts +388 -0
  1049. package/sdk/src/cli-transport.ts +130 -0
  1050. package/sdk/src/cli.test.ts +426 -0
  1051. package/sdk/src/cli.ts +589 -0
  1052. package/sdk/src/config.test.ts +271 -0
  1053. package/sdk/src/config.ts +218 -0
  1054. package/sdk/src/context-engine.test.ts +295 -0
  1055. package/sdk/src/context-engine.ts +170 -0
  1056. package/sdk/src/context-truncation.test.ts +163 -0
  1057. package/sdk/src/context-truncation.ts +233 -0
  1058. package/sdk/src/e2e.integration.test.ts +181 -0
  1059. package/sdk/src/errors.ts +72 -0
  1060. package/sdk/src/event-stream.test.ts +661 -0
  1061. package/sdk/src/event-stream.ts +441 -0
  1062. package/sdk/src/golden/capture.ts +95 -0
  1063. package/sdk/src/golden/fixtures/generate-slug.golden.json +1 -0
  1064. package/sdk/src/golden/fixtures/profile-sample-sessions/demo-project/sample.jsonl +3 -0
  1065. package/sdk/src/golden/fixtures/summary-extract-sample.md +26 -0
  1066. package/sdk/src/golden/fixtures/uat-render-checkpoint-sample.md +15 -0
  1067. package/sdk/src/golden/golden-integration-covered.ts +30 -0
  1068. package/sdk/src/golden/golden-mutation-covered.ts +17 -0
  1069. package/sdk/src/golden/golden-policy.test.ts +8 -0
  1070. package/sdk/src/golden/golden-policy.ts +120 -0
  1071. package/sdk/src/golden/golden.integration.test.ts +677 -0
  1072. package/sdk/src/golden/init-golden-normalize.ts +15 -0
  1073. package/sdk/src/golden/read-only-golden-rows.ts +77 -0
  1074. package/sdk/src/golden/read-only-parity.integration.test.ts +133 -0
  1075. package/sdk/src/golden/registry-canonical-commands.ts +31 -0
  1076. package/sdk/src/index.ts +352 -0
  1077. package/sdk/src/init-e2e.integration.test.ts +138 -0
  1078. package/sdk/src/init-runner.test.ts +740 -0
  1079. package/sdk/src/init-runner.ts +734 -0
  1080. package/sdk/src/lifecycle-e2e.integration.test.ts +258 -0
  1081. package/sdk/src/logger.test.ts +149 -0
  1082. package/sdk/src/logger.ts +113 -0
  1083. package/sdk/src/milestone-runner.test.ts +421 -0
  1084. package/sdk/src/model-catalog.ts +70 -0
  1085. package/sdk/src/phase-prompt.test.ts +535 -0
  1086. package/sdk/src/phase-prompt.ts +259 -0
  1087. package/sdk/src/phase-runner-types.test.ts +421 -0
  1088. package/sdk/src/phase-runner.integration.test.ts +377 -0
  1089. package/sdk/src/phase-runner.test.ts +2720 -0
  1090. package/sdk/src/phase-runner.ts +1442 -0
  1091. package/sdk/src/plan-parser.test.ts +579 -0
  1092. package/sdk/src/plan-parser.ts +431 -0
  1093. package/sdk/src/planning-journal.test.ts +70 -0
  1094. package/sdk/src/planning-journal.ts +153 -0
  1095. package/sdk/src/planning-runtime.test.ts +29 -0
  1096. package/sdk/src/planning-runtime.ts +100 -0
  1097. package/sdk/src/prompt-builder.test.ts +318 -0
  1098. package/sdk/src/prompt-builder.ts +218 -0
  1099. package/sdk/src/prompt-sanitizer.test.ts +260 -0
  1100. package/sdk/src/prompt-sanitizer.ts +116 -0
  1101. package/sdk/src/query/QUERY-HANDLERS.md +349 -0
  1102. package/sdk/src/query/active-workstream-store.ts +50 -0
  1103. package/sdk/src/query/agent-failure-classifier.test.ts +157 -0
  1104. package/sdk/src/query/agent-failure-classifier.ts +105 -0
  1105. package/sdk/src/query/audit-open.ts +722 -0
  1106. package/sdk/src/query/check-auto-mode.test.ts +77 -0
  1107. package/sdk/src/query/check-auto-mode.ts +49 -0
  1108. package/sdk/src/query/check-completion.test.ts +113 -0
  1109. package/sdk/src/query/check-completion.ts +182 -0
  1110. package/sdk/src/query/check-decision-coverage.test.ts +519 -0
  1111. package/sdk/src/query/check-decision-coverage.ts +554 -0
  1112. package/sdk/src/query/check-gates.test.ts +103 -0
  1113. package/sdk/src/query/check-gates.ts +112 -0
  1114. package/sdk/src/query/check-ship-ready.test.ts +111 -0
  1115. package/sdk/src/query/check-ship-ready.ts +104 -0
  1116. package/sdk/src/query/check-verification-status.test.ts +143 -0
  1117. package/sdk/src/query/check-verification-status.ts +160 -0
  1118. package/sdk/src/query/command-aliases.generated.ts +156 -0
  1119. package/sdk/src/query/command-catalog.ts +31 -0
  1120. package/sdk/src/query/command-definition.test.ts +47 -0
  1121. package/sdk/src/query/command-definition.ts +70 -0
  1122. package/sdk/src/query/command-family-handlers.ts +117 -0
  1123. package/sdk/src/query/command-manifest.init.ts +24 -0
  1124. package/sdk/src/query/command-manifest.non-family.ts +85 -0
  1125. package/sdk/src/query/command-manifest.phase.ts +16 -0
  1126. package/sdk/src/query/command-manifest.phases.ts +11 -0
  1127. package/sdk/src/query/command-manifest.roadmap.ts +11 -0
  1128. package/sdk/src/query/command-manifest.state.ts +31 -0
  1129. package/sdk/src/query/command-manifest.ts +17 -0
  1130. package/sdk/src/query/command-manifest.types.ts +13 -0
  1131. package/sdk/src/query/command-manifest.validate.ts +11 -0
  1132. package/sdk/src/query/command-manifest.verify.ts +15 -0
  1133. package/sdk/src/query/command-resolution.test.ts +70 -0
  1134. package/sdk/src/query/command-seam-coverage.test.ts +118 -0
  1135. package/sdk/src/query/command-static-catalog-domain.ts +117 -0
  1136. package/sdk/src/query/command-static-catalog-foundation.ts +103 -0
  1137. package/sdk/src/query/command-topology.test.ts +28 -0
  1138. package/sdk/src/query/command-topology.ts +114 -0
  1139. package/sdk/src/query/commands-list.test.ts +36 -0
  1140. package/sdk/src/query/commands-list.ts +19 -0
  1141. package/sdk/src/query/commit.test.ts +485 -0
  1142. package/sdk/src/query/commit.ts +383 -0
  1143. package/sdk/src/query/config-gates.test.ts +89 -0
  1144. package/sdk/src/query/config-gates.ts +69 -0
  1145. package/sdk/src/query/config-mutation.test.ts +598 -0
  1146. package/sdk/src/query/config-mutation.ts +575 -0
  1147. package/sdk/src/query/config-query.test.ts +367 -0
  1148. package/sdk/src/query/config-query.ts +244 -0
  1149. package/sdk/src/query/config-schema.ts +159 -0
  1150. package/sdk/src/query/decisions.test.ts +215 -0
  1151. package/sdk/src/query/decisions.ts +192 -0
  1152. package/sdk/src/query/decomposed-handlers.test.ts +431 -0
  1153. package/sdk/src/query/detect-custom-files.test.ts +115 -0
  1154. package/sdk/src/query/detect-custom-files.ts +96 -0
  1155. package/sdk/src/query/detect-phase-type.test.ts +105 -0
  1156. package/sdk/src/query/detect-phase-type.ts +141 -0
  1157. package/sdk/src/query/docs-init.ts +258 -0
  1158. package/sdk/src/query/fallow-audit.ts +88 -0
  1159. package/sdk/src/query/frontmatter-array.test.ts +14 -0
  1160. package/sdk/src/query/frontmatter-mutation.test.ts +259 -0
  1161. package/sdk/src/query/frontmatter-mutation.ts +343 -0
  1162. package/sdk/src/query/frontmatter.test.ts +326 -0
  1163. package/sdk/src/query/frontmatter.ts +395 -0
  1164. package/sdk/src/query/helpers.test.ts +615 -0
  1165. package/sdk/src/query/helpers.ts +646 -0
  1166. package/sdk/src/query/index-thin-seam.test.ts +16 -0
  1167. package/sdk/src/query/index.ts +9 -0
  1168. package/sdk/src/query/init-complex.test.ts +616 -0
  1169. package/sdk/src/query/init-complex.ts +799 -0
  1170. package/sdk/src/query/init-progress-precedence.test.ts +177 -0
  1171. package/sdk/src/query/init-workstream-milestone-op.test.ts +321 -0
  1172. package/sdk/src/query/init.test.ts +792 -0
  1173. package/sdk/src/query/init.ts +1262 -0
  1174. package/sdk/src/query/intel.test.ts +90 -0
  1175. package/sdk/src/query/intel.ts +404 -0
  1176. package/sdk/src/query/mutation-event-decorator.test.ts +45 -0
  1177. package/sdk/src/query/mutation-event-decorator.ts +37 -0
  1178. package/sdk/src/query/mutation-event-mapper.test.ts +33 -0
  1179. package/sdk/src/query/mutation-event-mapper.ts +102 -0
  1180. package/sdk/src/query/mvp.test.ts +335 -0
  1181. package/sdk/src/query/mvp.ts +292 -0
  1182. package/sdk/src/query/normalize-query-command.test.ts +102 -0
  1183. package/sdk/src/query/phase-filesystem-adapter.ts +35 -0
  1184. package/sdk/src/query/phase-lifecycle-policy.ts +171 -0
  1185. package/sdk/src/query/phase-lifecycle.test.ts +1750 -0
  1186. package/sdk/src/query/phase-lifecycle.ts +1833 -0
  1187. package/sdk/src/query/phase-list-queries.test.ts +88 -0
  1188. package/sdk/src/query/phase-list-queries.ts +152 -0
  1189. package/sdk/src/query/phase-ready.test.ts +65 -0
  1190. package/sdk/src/query/phase-ready.ts +159 -0
  1191. package/sdk/src/query/phase-roadmap-mutation.ts +77 -0
  1192. package/sdk/src/query/phase.test.ts +651 -0
  1193. package/sdk/src/query/phase.ts +550 -0
  1194. package/sdk/src/query/pipeline.test.ts +169 -0
  1195. package/sdk/src/query/pipeline.ts +243 -0
  1196. package/sdk/src/query/plan-scan.test.ts +35 -0
  1197. package/sdk/src/query/plan-scan.ts +82 -0
  1198. package/sdk/src/query/plan-task-structure.test.ts +65 -0
  1199. package/sdk/src/query/plan-task-structure.ts +63 -0
  1200. package/sdk/src/query/policy-convergence.test.ts +28 -0
  1201. package/sdk/src/query/profile-extract-messages.ts +247 -0
  1202. package/sdk/src/query/profile-output.ts +929 -0
  1203. package/sdk/src/query/profile-questionnaire-data.ts +181 -0
  1204. package/sdk/src/query/profile-sample.ts +184 -0
  1205. package/sdk/src/query/profile-scan-sessions.ts +174 -0
  1206. package/sdk/src/query/profile.test.ts +136 -0
  1207. package/sdk/src/query/profile.ts +337 -0
  1208. package/sdk/src/query/progress.test.ts +156 -0
  1209. package/sdk/src/query/progress.ts +566 -0
  1210. package/sdk/src/query/query-cli-adapter.test.ts +79 -0
  1211. package/sdk/src/query/query-cli-adapter.ts +39 -0
  1212. package/sdk/src/query/query-cli-output.test.ts +33 -0
  1213. package/sdk/src/query/query-cli-output.ts +35 -0
  1214. package/sdk/src/query/query-command-diagnosis.test.ts +22 -0
  1215. package/sdk/src/query/query-command-diagnosis.ts +5 -0
  1216. package/sdk/src/query/query-command-resolution-strategy.test.ts +34 -0
  1217. package/sdk/src/query/query-command-resolution-strategy.ts +121 -0
  1218. package/sdk/src/query/query-command-semantics.test.ts +22 -0
  1219. package/sdk/src/query/query-command-semantics.ts +22 -0
  1220. package/sdk/src/query/query-dispatch-contract.ts +30 -0
  1221. package/sdk/src/query/query-dispatch-error-mapper.test.ts +62 -0
  1222. package/sdk/src/query/query-dispatch-error-mapper.ts +5 -0
  1223. package/sdk/src/query/query-dispatch-formatting.test.ts +28 -0
  1224. package/sdk/src/query/query-dispatch-formatting.ts +5 -0
  1225. package/sdk/src/query/query-dispatch-input-validation.test.ts +23 -0
  1226. package/sdk/src/query/query-dispatch-input-validation.ts +5 -0
  1227. package/sdk/src/query/query-dispatch-observability.test.ts +10 -0
  1228. package/sdk/src/query/query-dispatch-observability.ts +6 -0
  1229. package/sdk/src/query/query-dispatch-plan.test.ts +25 -0
  1230. package/sdk/src/query/query-dispatch-plan.ts +5 -0
  1231. package/sdk/src/query/query-dispatch-result-builder.test.ts +16 -0
  1232. package/sdk/src/query/query-dispatch-result-builder.ts +5 -0
  1233. package/sdk/src/query/query-dispatch.test.ts +399 -0
  1234. package/sdk/src/query/query-dispatch.ts +243 -0
  1235. package/sdk/src/query/query-error-details-schema.ts +29 -0
  1236. package/sdk/src/query/query-error-taxonomy.test.ts +39 -0
  1237. package/sdk/src/query/query-error-taxonomy.ts +117 -0
  1238. package/sdk/src/query/query-fallback-bridge-adapter.test.ts +32 -0
  1239. package/sdk/src/query/query-fallback-bridge-adapter.ts +54 -0
  1240. package/sdk/src/query/query-fallback-executor.test.ts +82 -0
  1241. package/sdk/src/query/query-fallback-executor.ts +44 -0
  1242. package/sdk/src/query/query-fallback-output-classifier.test.ts +36 -0
  1243. package/sdk/src/query/query-fallback-output-classifier.ts +31 -0
  1244. package/sdk/src/query/query-fallback-policy.test.ts +13 -0
  1245. package/sdk/src/query/query-fallback-policy.ts +11 -0
  1246. package/sdk/src/query/query-native-dispatch-adapter.ts +16 -0
  1247. package/sdk/src/query/query-policy-capability.test.ts +10 -0
  1248. package/sdk/src/query/query-policy-capability.ts +26 -0
  1249. package/sdk/src/query/query-policy-snapshot.test.ts +9 -0
  1250. package/sdk/src/query/query-registry-capability.test.ts +14 -0
  1251. package/sdk/src/query/query-runtime-context.ts +44 -0
  1252. package/sdk/src/query/query-unknown-command-hints.test.ts +9 -0
  1253. package/sdk/src/query/query-unknown-command-hints.ts +5 -0
  1254. package/sdk/src/query/registry-assembly-descriptor.ts +87 -0
  1255. package/sdk/src/query/registry-assembly-invariants.ts +127 -0
  1256. package/sdk/src/query/registry-assembly.test.ts +138 -0
  1257. package/sdk/src/query/registry-assembly.ts +78 -0
  1258. package/sdk/src/query/registry.test.ts +208 -0
  1259. package/sdk/src/query/registry.ts +142 -0
  1260. package/sdk/src/query/requirements-extract-from-plans.test.ts +58 -0
  1261. package/sdk/src/query/requirements-extract-from-plans.ts +86 -0
  1262. package/sdk/src/query/roadmap-update-plan-progress.test.ts +233 -0
  1263. package/sdk/src/query/roadmap-update-plan-progress.ts +159 -0
  1264. package/sdk/src/query/roadmap.test.ts +1181 -0
  1265. package/sdk/src/query/roadmap.ts +894 -0
  1266. package/sdk/src/query/route-next-action.test.ts +61 -0
  1267. package/sdk/src/query/route-next-action.ts +345 -0
  1268. package/sdk/src/query/schema-detect.ts +189 -0
  1269. package/sdk/src/query/secrets.test.ts +66 -0
  1270. package/sdk/src/query/secrets.ts +43 -0
  1271. package/sdk/src/query/skill-manifest.test.ts +62 -0
  1272. package/sdk/src/query/skill-manifest.ts +216 -0
  1273. package/sdk/src/query/skills.test.ts +234 -0
  1274. package/sdk/src/query/skills.ts +143 -0
  1275. package/sdk/src/query/state-document.test.ts +197 -0
  1276. package/sdk/src/query/state-document.ts +129 -0
  1277. package/sdk/src/query/state-mutation.test.ts +1198 -0
  1278. package/sdk/src/query/state-mutation.ts +1718 -0
  1279. package/sdk/src/query/state-project-load.ts +80 -0
  1280. package/sdk/src/query/state.test.ts +616 -0
  1281. package/sdk/src/query/state.ts +463 -0
  1282. package/sdk/src/query/sub-repos-root.integration.test.ts +79 -0
  1283. package/sdk/src/query/summary.test.ts +95 -0
  1284. package/sdk/src/query/summary.ts +296 -0
  1285. package/sdk/src/query/template.test.ts +180 -0
  1286. package/sdk/src/query/template.ts +242 -0
  1287. package/sdk/src/query/uat.test.ts +77 -0
  1288. package/sdk/src/query/uat.ts +365 -0
  1289. package/sdk/src/query/utils.test.ts +82 -0
  1290. package/sdk/src/query/utils.ts +106 -0
  1291. package/sdk/src/query/validate.test.ts +831 -0
  1292. package/sdk/src/query/validate.ts +952 -0
  1293. package/sdk/src/query/verify.test.ts +414 -0
  1294. package/sdk/src/query/verify.ts +692 -0
  1295. package/sdk/src/query/websearch.test.ts +31 -0
  1296. package/sdk/src/query/websearch.ts +82 -0
  1297. package/sdk/src/query/workspace.test.ts +120 -0
  1298. package/sdk/src/query/workspace.ts +145 -0
  1299. package/sdk/src/query/workstream-inventory.ts +195 -0
  1300. package/sdk/src/query/workstream.test.ts +153 -0
  1301. package/sdk/src/query/workstream.ts +324 -0
  1302. package/sdk/src/query/worktree.ts +39 -0
  1303. package/sdk/src/query-command-executor.ts +31 -0
  1304. package/sdk/src/query-execution-policy.test.ts +52 -0
  1305. package/sdk/src/query-execution-policy.ts +46 -0
  1306. package/sdk/src/query-failure-classification.test.ts +23 -0
  1307. package/sdk/src/query-failure-classification.ts +42 -0
  1308. package/sdk/src/query-hotpath-methods.ts +48 -0
  1309. package/sdk/src/query-native-direct-adapter.test.ts +35 -0
  1310. package/sdk/src/query-native-direct-adapter.ts +70 -0
  1311. package/sdk/src/query-native-hotpath-adapter.test.ts +43 -0
  1312. package/sdk/src/query-native-hotpath-adapter.ts +45 -0
  1313. package/sdk/src/query-raw-output-projection.test.ts +39 -0
  1314. package/sdk/src/query-raw-output-projection.ts +74 -0
  1315. package/sdk/src/query-runtime-bridge.test.ts +150 -0
  1316. package/sdk/src/query-runtime-bridge.ts +215 -0
  1317. package/sdk/src/query-runtime-seam-coverage.test.ts +20 -0
  1318. package/sdk/src/query-sdd-tools-path.ts +1 -0
  1319. package/sdk/src/query-sdd-tools-runtime.ts +89 -0
  1320. package/sdk/src/query-subprocess-adapter.test.ts +84 -0
  1321. package/sdk/src/query-subprocess-adapter.ts +146 -0
  1322. package/sdk/src/query-tools-error-factory.test.ts +35 -0
  1323. package/sdk/src/query-tools-error-factory.ts +76 -0
  1324. package/sdk/src/research-gate.test.ts +190 -0
  1325. package/sdk/src/research-gate.ts +94 -0
  1326. package/sdk/src/runtime-bridge-options.test.ts +33 -0
  1327. package/sdk/src/runtime-gate.test.ts +84 -0
  1328. package/sdk/src/runtime-gate.ts +52 -0
  1329. package/sdk/src/sdd-tools-error.test.ts +21 -0
  1330. package/sdk/src/sdd-tools-error.ts +65 -0
  1331. package/sdk/src/sdd-tools.test.ts +472 -0
  1332. package/sdk/src/sdd-tools.ts +237 -0
  1333. package/sdk/src/sdd-transport-policy.test.ts +34 -0
  1334. package/sdk/src/sdd-transport-policy.ts +48 -0
  1335. package/sdk/src/sdd-transport.test.ts +292 -0
  1336. package/sdk/src/sdd-transport.ts +117 -0
  1337. package/sdk/src/sdk-package-compatibility.test.ts +97 -0
  1338. package/sdk/src/sdk-package-compatibility.ts +141 -0
  1339. package/sdk/src/session-runner.test.ts +164 -0
  1340. package/sdk/src/session-runner.ts +327 -0
  1341. package/sdk/src/tool-scoping.test.ts +160 -0
  1342. package/sdk/src/tool-scoping.ts +61 -0
  1343. package/sdk/src/types.ts +927 -0
  1344. package/sdk/src/workflow-agent-skills-consistency.test.ts +98 -0
  1345. package/sdk/src/workstream-name-policy.ts +24 -0
  1346. package/sdk/src/workstream-utils.ts +21 -0
  1347. package/sdk/src/ws-flag.test.ts +285 -0
  1348. package/sdk/src/ws-transport.test.ts +161 -0
  1349. package/sdk/src/ws-transport.ts +93 -0
  1350. package/sdk/tsconfig.json +20 -0
  1351. package/commands/sdd/add-backlog.md +0 -76
  1352. package/commands/sdd/add-phase.md +0 -43
  1353. package/commands/sdd/add-todo.md +0 -47
  1354. package/commands/sdd/analyze-dependencies.md +0 -34
  1355. package/commands/sdd/check-todos.md +0 -45
  1356. package/commands/sdd/code-review-fix.md +0 -52
  1357. package/commands/sdd/do.md +0 -30
  1358. package/commands/sdd/from-sdd2.md +0 -45
  1359. package/commands/sdd/insert-phase.md +0 -32
  1360. package/commands/sdd/intel.md +0 -179
  1361. package/commands/sdd/join-discord.md +0 -19
  1362. package/commands/sdd/list-phase-assumptions.md +0 -46
  1363. package/commands/sdd/list-workspaces.md +0 -19
  1364. package/commands/sdd/new-workspace.md +0 -44
  1365. package/commands/sdd/next.md +0 -26
  1366. package/commands/sdd/note.md +0 -34
  1367. package/commands/sdd/plan-milestone-gaps.md +0 -34
  1368. package/commands/sdd/plant-seed.md +0 -28
  1369. package/commands/sdd/remove-phase.md +0 -31
  1370. package/commands/sdd/remove-workspace.md +0 -26
  1371. package/commands/sdd/research-phase.md +0 -195
  1372. package/commands/sdd/scan.md +0 -26
  1373. package/commands/sdd/session-report.md +0 -19
  1374. package/commands/sdd/set-profile.md +0 -12
  1375. package/scripts/sync-upstream.sh +0 -56
  1376. package/sdd/workflows/research-phase.md +0 -82
@@ -4,8 +4,24 @@
4
4
 
5
5
  const fs = require('fs');
6
6
  const path = require('path');
7
- const { escapeRegex, loadConfig, getMilestoneInfo, getMilestonePhaseFilter, normalizeMd, planningDir, planningPaths, output, error, atomicWriteFileSync } = require('./core.cjs');
7
+ const { escapeRegex, loadConfig, getMilestoneInfo, getMilestonePhaseFilter, output, error } = require('./core.cjs');
8
+ const { platformWriteSync, platformReadSync, platformEnsureDir } = require('./shell-command-projection.cjs');
9
+ const { planningDir, planningPaths } = require('./planning-workspace.cjs');
8
10
  const { extractFrontmatter, reconstructFrontmatter } = require('./frontmatter.cjs');
11
+ const scanPhasePlans = require('./plan-scan.cjs');
12
+ const {
13
+ computeProgressPercent,
14
+ normalizeProgressNumbers,
15
+ normalizeStateStatus,
16
+ shouldPreserveExistingProgress,
17
+ stateExtractField,
18
+ stateReplaceField,
19
+ } = require('./state-document.cjs');
20
+
21
+ // Cache disk scan results from buildStateFrontmatter per cwd per process (#1967).
22
+ // Avoids re-reading N+1 directories on every state write when the phase structure
23
+ // hasn't changed within the same sdd-tools invocation.
24
+ const _diskScanCache = new Map();
9
25
 
10
26
  /** Shorthand — every state command needs this path */
11
27
  function getStatePath(cwd) {
@@ -22,26 +38,11 @@ process.on('exit', () => {
22
38
  }
23
39
  });
24
40
 
25
- // Shared helper: extract a field value from STATE.md content.
26
- // Supports both **Field:** bold and plain Field: format.
27
- function stateExtractField(content, fieldName) {
28
- const escaped = escapeRegex(fieldName);
29
- const boldPattern = new RegExp(`\\*\\*${escaped}:\\*\\*\\s*(.+)`, 'i');
30
- const boldMatch = content.match(boldPattern);
31
- if (boldMatch) return boldMatch[1].trim();
32
- const plainPattern = new RegExp(`^${escaped}:\\s*(.+)`, 'im');
33
- const plainMatch = content.match(plainPattern);
34
- return plainMatch ? plainMatch[1].trim() : null;
35
- }
36
-
37
41
  function cmdStateLoad(cwd, raw) {
38
42
  const config = loadConfig(cwd);
39
43
  const planDir = planningPaths(cwd).planning;
40
44
 
41
- let stateRaw = '';
42
- try {
43
- stateRaw = fs.readFileSync(path.join(planDir, 'STATE.md'), 'utf-8');
44
- } catch { /* intentionally empty */ }
45
+ const stateRaw = platformReadSync(path.join(planDir, 'STATE.md')) || '';
45
46
 
46
47
  const configExists = fs.existsSync(path.join(planDir, 'config.json'));
47
48
  const roadmapExists = fs.existsSync(path.join(planDir, 'ROADMAP.md'));
@@ -81,8 +82,12 @@ function cmdStateLoad(cwd, raw) {
81
82
 
82
83
  function cmdStateGet(cwd, section, raw) {
83
84
  const statePath = planningPaths(cwd).state;
84
- try {
85
- const content = fs.readFileSync(statePath, 'utf-8');
85
+ const content = platformReadSync(statePath);
86
+ if (content === null) {
87
+ error('STATE.md not found');
88
+ return;
89
+ }
90
+ {
86
91
 
87
92
  if (!section) {
88
93
  output({ content }, raw, content);
@@ -117,8 +122,6 @@ function cmdStateGet(cwd, section, raw) {
117
122
  }
118
123
 
119
124
  output({ error: `Section or field "${section}" not found` }, raw, '');
120
- } catch {
121
- error('STATE.md not found');
122
125
  }
123
126
  }
124
127
 
@@ -156,16 +159,9 @@ function cmdStatePatch(cwd, patches, raw) {
156
159
  // Use atomic read-modify-write to prevent lost updates from concurrent agents
157
160
  readModifyWriteStateMd(statePath, (content) => {
158
161
  for (const [field, value] of Object.entries(patches)) {
159
- const fieldEscaped = escapeRegex(field);
160
- // Try **Field:** bold format first, then plain Field: format
161
- const boldPattern = new RegExp(`(\\*\\*${fieldEscaped}:\\*\\*\\s*)(.*)`, 'i');
162
- const plainPattern = new RegExp(`(^${fieldEscaped}:\\s*)(.*)`, 'im');
163
-
164
- if (boldPattern.test(content)) {
165
- content = content.replace(boldPattern, (_match, prefix) => `${prefix}${value}`);
166
- results.updated.push(field);
167
- } else if (plainPattern.test(content)) {
168
- content = content.replace(plainPattern, (_match, prefix) => `${prefix}${value}`);
162
+ const result = stateReplaceField(content, field, value);
163
+ if (result) {
164
+ content = result;
169
165
  results.updated.push(field);
170
166
  } else {
171
167
  results.failed.push(field);
@@ -195,20 +191,22 @@ function cmdStateUpdate(cwd, field, value) {
195
191
  const statePath = planningPaths(cwd).state;
196
192
  try {
197
193
  let updated = false;
194
+ const shouldResync = ['Progress', 'Total Plans in Phase', 'Total Phases'].includes(field);
195
+ // Preserve curated progress for body-only updates, but allow fields that
196
+ // directly project into progress.* frontmatter to rebuild after mutation.
198
197
  readModifyWriteStateMd(statePath, (content) => {
199
- const fieldEscaped = escapeRegex(field);
200
- // Try **Field:** bold format first, then plain Field: format
201
- const boldPattern = new RegExp(`(\\*\\*${fieldEscaped}:\\*\\*\\s*)(.*)`, 'i');
202
- const plainPattern = new RegExp(`(^${fieldEscaped}:\\s*)(.*)`, 'im');
203
- if (boldPattern.test(content)) {
204
- updated = true;
205
- return content.replace(boldPattern, (_match, prefix) => `${prefix}${value}`);
206
- } else if (plainPattern.test(content)) {
198
+ const body = stripFrontmatter(content);
199
+ const result = stateReplaceField(body, field, value);
200
+ if (result) {
207
201
  updated = true;
208
- return content.replace(plainPattern, (_match, prefix) => `${prefix}${value}`);
202
+ const existingFm = extractFrontmatter(content);
203
+ if (Object.keys(existingFm).length > 0) {
204
+ return `---\n${reconstructFrontmatter(existingFm)}\n---\n\n${result}`;
205
+ }
206
+ return result;
209
207
  }
210
208
  return content;
211
- }, cwd);
209
+ }, cwd, { resync: shouldResync });
212
210
  if (updated) {
213
211
  output({ updated: true });
214
212
  } else {
@@ -220,21 +218,6 @@ function cmdStateUpdate(cwd, field, value) {
220
218
  }
221
219
 
222
220
  // ─── State Progression Engine ────────────────────────────────────────────────
223
- // stateExtractField is defined above (shared helper) — do not duplicate.
224
-
225
- function stateReplaceField(content, fieldName, newValue) {
226
- const escaped = escapeRegex(fieldName);
227
- // Try **Field:** bold format first, then plain Field: format
228
- const boldPattern = new RegExp(`(\\*\\*${escaped}:\\*\\*\\s*)(.*)`, 'i');
229
- if (boldPattern.test(content)) {
230
- return content.replace(boldPattern, (_match, prefix) => `${prefix}${newValue}`);
231
- }
232
- const plainPattern = new RegExp(`(^${escaped}:\\s*)(.*)`, 'im');
233
- if (plainPattern.test(content)) {
234
- return content.replace(plainPattern, (_match, prefix) => `${prefix}${newValue}`);
235
- }
236
- return null;
237
- }
238
221
 
239
222
  /**
240
223
  * Replace a STATE.md field with fallback field name support.
@@ -281,7 +264,7 @@ function updateCurrentPositionFields(content, fields) {
281
264
  posBody = posBody.replace(/^Plan:.*$/m, `Plan: ${fields.plan}`);
282
265
  }
283
266
 
284
- return content.replace(posPattern, `${posMatch[1]}${posBody}`);
267
+ return content.replace(posPattern, () => `${posMatch[1]}${posBody}`);
285
268
  }
286
269
 
287
270
  function cmdStateAdvancePlan(cwd, raw) {
@@ -364,14 +347,16 @@ function cmdStateRecordMetric(cwd, options, raw) {
364
347
  }
365
348
 
366
349
  let recorded = false;
350
+ let created = false;
367
351
  readModifyWriteStateMd(statePath, (content) => {
368
352
  // Find Performance Metrics section and its table
369
353
  const metricsPattern = /(##\s*Performance Metrics[\s\S]*?\n\|[^\n]+\n\|[-|\s]+\n)([\s\S]*?)(?=\n##|\n$|$)/i;
370
354
  const metricsMatch = content.match(metricsPattern);
371
355
 
356
+ const newRow = `| Phase ${phase} P${plan} | ${duration} | ${tasks || '-'} tasks | ${files || '-'} files |`;
357
+
372
358
  if (metricsMatch) {
373
359
  let tableBody = metricsMatch[2].trimEnd();
374
- const newRow = `| Phase ${phase} P${plan} | ${duration} | ${tasks || '-'} tasks | ${files || '-'} files |`;
375
360
 
376
361
  if (tableBody.trim() === '' || tableBody.includes('None yet')) {
377
362
  tableBody = newRow;
@@ -382,14 +367,27 @@ function cmdStateRecordMetric(cwd, options, raw) {
382
367
  recorded = true;
383
368
  return content.replace(metricsPattern, (_match, header) => `${header}${tableBody}\n`);
384
369
  }
385
- return content;
370
+
371
+ // Section absent — DWIM: auto-create canonical ## Performance Metrics scaffold,
372
+ // then append the row. Matches state begin-phase / advance-plan DWIM behavior.
373
+ const scaffold = [
374
+ '',
375
+ '## Performance Metrics',
376
+ '',
377
+ '| Phase | Plan | Duration | Notes |',
378
+ '|-------|------|----------|-------|',
379
+ newRow,
380
+ '',
381
+ ].join('\n');
382
+ recorded = true;
383
+ created = true;
384
+ return content.trimEnd() + '\n' + scaffold;
386
385
  }, cwd);
387
386
 
388
- if (recorded) {
389
- output({ recorded: true, phase, plan, duration }, raw, 'true');
390
- } else {
391
- output({ recorded: false, reason: 'Performance Metrics section not found in STATE.md' }, raw, 'false');
392
- }
387
+ // Auto-create fallback guarantees recorded === true; no else branch needed.
388
+ const result = { recorded: true, phase, plan, duration };
389
+ if (created) result.created = true;
390
+ output(result, raw, 'true');
393
391
  }
394
392
 
395
393
  function cmdStateUpdateProgress(cwd, raw) {
@@ -407,9 +405,9 @@ function cmdStateUpdateProgress(cwd, raw) {
407
405
  .filter(e => e.isDirectory()).map(e => e.name)
408
406
  .filter(isDirInMilestone);
409
407
  for (const dir of phaseDirs) {
410
- const files = fs.readdirSync(path.join(phasesDir, dir));
411
- totalPlans += files.filter(f => f.match(/-PLAN\.md$/i)).length;
412
- totalSummaries += files.filter(f => f.match(/-SUMMARY\.md$/i)).length;
408
+ const { planCount, summaryCount } = scanPhasePlans(path.join(phasesDir, dir));
409
+ totalPlans += planCount;
410
+ totalSummaries += summaryCount;
413
411
  }
414
412
  }
415
413
 
@@ -464,6 +462,7 @@ function cmdStateAddDecision(cwd, options, raw) {
464
462
 
465
463
  const entry = `- [Phase ${phase || '?'}]: ${summaryText}${rationaleText ? ` — ${rationaleText}` : ''}`;
466
464
  let added = false;
465
+ let created = false;
467
466
 
468
467
  readModifyWriteStateMd(statePath, (content) => {
469
468
  // Find Decisions section (various heading patterns)
@@ -478,14 +477,25 @@ function cmdStateAddDecision(cwd, options, raw) {
478
477
  added = true;
479
478
  return content.replace(sectionPattern, (_match, header) => `${header}${sectionBody}`);
480
479
  }
481
- return content;
480
+
481
+ // Section absent — DWIM: auto-create canonical ## Decisions scaffold,
482
+ // then append the entry. Matches state begin-phase / advance-plan DWIM behavior.
483
+ const scaffold = [
484
+ '',
485
+ '## Decisions',
486
+ '',
487
+ entry,
488
+ '',
489
+ ].join('\n');
490
+ added = true;
491
+ created = true;
492
+ return content.trimEnd() + '\n' + scaffold;
482
493
  }, cwd);
483
494
 
484
- if (added) {
485
- output({ added: true, decision: entry }, raw, 'true');
486
- } else {
487
- output({ added: false, reason: 'Decisions section not found in STATE.md' }, raw, 'false');
488
- }
495
+ // Auto-create fallback guarantees added === true; no else branch needed.
496
+ const result = { added: true, decision: entry };
497
+ if (created) result.created = true;
498
+ output(result, raw, 'true');
489
499
  }
490
500
 
491
501
  function cmdStateAddBlocker(cwd, text, raw) {
@@ -505,6 +515,7 @@ function cmdStateAddBlocker(cwd, text, raw) {
505
515
 
506
516
  const entry = `- ${blockerText}`;
507
517
  let added = false;
518
+ let created = false;
508
519
 
509
520
  readModifyWriteStateMd(statePath, (content) => {
510
521
  const sectionPattern = /(###?\s*(?:Blockers|Blockers\/Concerns|Concerns)\s*\n)([\s\S]*?)(?=\n###?|\n##[^#]|$)/i;
@@ -517,14 +528,24 @@ function cmdStateAddBlocker(cwd, text, raw) {
517
528
  added = true;
518
529
  return content.replace(sectionPattern, (_match, header) => `${header}${sectionBody}`);
519
530
  }
520
- return content;
531
+
532
+ // Section absent — DWIM: auto-create canonical ### Blockers scaffold.
533
+ const scaffold = [
534
+ '',
535
+ '### Blockers',
536
+ '',
537
+ entry,
538
+ '',
539
+ ].join('\n');
540
+ added = true;
541
+ created = true;
542
+ return content.trimEnd() + '\n' + scaffold;
521
543
  }, cwd);
522
544
 
523
- if (added) {
524
- output({ added: true, blocker: blockerText }, raw, 'true');
525
- } else {
526
- output({ added: false, reason: 'Blockers section not found in STATE.md' }, raw, 'false');
527
- }
545
+ // Auto-create fallback guarantees added === true; no else branch needed.
546
+ const result = { added: true, blocker: blockerText };
547
+ if (created) result.created = true;
548
+ output(result, raw, 'true');
528
549
  }
529
550
 
530
551
  function cmdStateResolveBlocker(cwd, text, raw) {
@@ -612,17 +633,36 @@ function cmdStateSnapshot(cwd, raw) {
612
633
 
613
634
  const content = fs.readFileSync(statePath, 'utf-8');
614
635
 
615
- // Extract basic fields
616
- const currentPhase = stateExtractField(content, 'Current Phase');
617
- const currentPhaseName = stateExtractField(content, 'Current Phase Name');
618
- const totalPhasesRaw = stateExtractField(content, 'Total Phases');
619
- const currentPlan = stateExtractField(content, 'Current Plan');
620
- const totalPlansRaw = stateExtractField(content, 'Total Plans in Phase');
621
- const status = stateExtractField(content, 'Status');
622
- const progressRaw = stateExtractField(content, 'Progress');
623
- const lastActivity = stateExtractField(content, 'Last Activity');
624
- const lastActivityDesc = stateExtractField(content, 'Last Activity Description');
625
- const pausedAt = stateExtractField(content, 'Paused At');
636
+ // Bug #3265: prefer YAML frontmatter for canonical scalar fields so that a
637
+ // body table cell containing **Status:** Y cannot shadow the authoritative
638
+ // frontmatter value. Mirrors the fix in sdk/src/query/state.ts.
639
+ const fm = extractFrontmatter(content);
640
+ const body = stripFrontmatter(content);
641
+
642
+ // Helper: return frontmatter scalar value when present and non-empty.
643
+ // Accepts strings, numbers, and booleans — coercing non-string primitives to
644
+ // their string representation so callers always receive string | null.
645
+ // Returns null for missing, null/undefined, or empty-after-trim values so
646
+ // the caller falls back to body extraction.
647
+ const fmScalar = (key) => {
648
+ const v = fm[key];
649
+ if (v === null || v === undefined) return null;
650
+ if (typeof v === 'string') return v.trim() || null;
651
+ if (typeof v === 'number' || typeof v === 'boolean') return String(v);
652
+ return null;
653
+ };
654
+
655
+ // Extract basic fields — frontmatter keys take precedence over body
656
+ const currentPhase = fmScalar('current_phase') ?? stateExtractField(body, 'Current Phase');
657
+ const currentPhaseName = fmScalar('current_phase_name') ?? stateExtractField(body, 'Current Phase Name');
658
+ const totalPhasesRaw = fmScalar('total_phases') ?? stateExtractField(body, 'Total Phases');
659
+ const currentPlan = fmScalar('current_plan') ?? stateExtractField(body, 'Current Plan');
660
+ const totalPlansRaw = fmScalar('total_plans_in_phase') ?? stateExtractField(body, 'Total Plans in Phase');
661
+ const status = fmScalar('status') ?? stateExtractField(body, 'Status');
662
+ const progressRaw = fmScalar('progress') ?? stateExtractField(body, 'Progress');
663
+ const lastActivity = fmScalar('last_activity') ?? stateExtractField(body, 'Last Activity');
664
+ const lastActivityDesc = fmScalar('last_activity_desc') ?? stateExtractField(body, 'Last Activity Description');
665
+ const pausedAt = fmScalar('paused_at') ?? stateExtractField(body, 'Paused At');
626
666
 
627
667
  // Parse numeric fields
628
668
  const totalPhases = totalPhasesRaw ? parseInt(totalPhasesRaw, 10) : null;
@@ -631,7 +671,7 @@ function cmdStateSnapshot(cwd, raw) {
631
671
 
632
672
  // Extract decisions table
633
673
  const decisions = [];
634
- const decisionsMatch = content.match(/##\s*Decisions Made[\s\S]*?\n\|[^\n]+\n\|[-|\s]+\n([\s\S]*?)(?=\n##|\n$|$)/i);
674
+ const decisionsMatch = body.match(/##\s*Decisions Made[\s\S]*?\n\|[^\n]+\n\|[-|\s]+\n([\s\S]*?)(?=\n##|\n$|$)/i);
635
675
  if (decisionsMatch) {
636
676
  const tableBody = decisionsMatch[1];
637
677
  const rows = tableBody.trim().split('\n').filter(r => r.includes('|'));
@@ -649,7 +689,7 @@ function cmdStateSnapshot(cwd, raw) {
649
689
 
650
690
  // Extract blockers list
651
691
  const blockers = [];
652
- const blockersMatch = content.match(/##\s*Blockers\s*\n([\s\S]*?)(?=\n##|$)/i);
692
+ const blockersMatch = body.match(/##\s*Blockers\s*\n([\s\S]*?)(?=\n##|$)/i);
653
693
  if (blockersMatch) {
654
694
  const blockersSection = blockersMatch[1];
655
695
  const items = blockersSection.match(/^-\s+(.+)$/gm) || [];
@@ -665,7 +705,7 @@ function cmdStateSnapshot(cwd, raw) {
665
705
  resume_file: null,
666
706
  };
667
707
 
668
- const sessionMatch = content.match(/##\s*Session\s*\n([\s\S]*?)(?=\n##|$)/i);
708
+ const sessionMatch = body.match(/##\s*Session\s*\n([\s\S]*?)(?=\n##|$)/i);
669
709
  if (sessionMatch) {
670
710
  const sessionSection = sessionMatch[1];
671
711
  const lastDateMatch = sessionSection.match(/\*\*Last Date:\*\*\s*(.+)/i)
@@ -715,7 +755,13 @@ function buildStateFrontmatter(bodyContent, cwd) {
715
755
  const status = stateExtractField(bodyContent, 'Status');
716
756
  const progressRaw = stateExtractField(bodyContent, 'Progress');
717
757
  const lastActivity = stateExtractField(bodyContent, 'Last Activity');
718
- const stoppedAt = stateExtractField(bodyContent, 'Stopped At') || stateExtractField(bodyContent, 'Stopped at');
758
+ // Bug #2444: scope Stopped At extraction to the ## Session section so that
759
+ // historical "Stopped at:" prose elsewhere in the body (e.g. in a
760
+ // Session Continuity Archive section) never overwrites the current value.
761
+ // Fall back to full-body search only when no ## Session section exists.
762
+ const sessionSectionMatch = bodyContent.match(/##\s*Session\s*\n([\s\S]*?)(?=\n##|$)/i);
763
+ const sessionBodyScope = sessionSectionMatch ? sessionSectionMatch[1] : bodyContent;
764
+ const stoppedAt = stateExtractField(sessionBodyScope, 'Stopped At') || stateExtractField(sessionBodyScope, 'Stopped at');
719
765
  const pausedAt = stateExtractField(bodyContent, 'Paused At');
720
766
 
721
767
  let milestone = null;
@@ -737,62 +783,79 @@ function buildStateFrontmatter(bodyContent, cwd) {
737
783
  try {
738
784
  const phasesDir = planningPaths(cwd).phases;
739
785
  if (fs.existsSync(phasesDir)) {
740
- const isDirInMilestone = getMilestonePhaseFilter(cwd);
741
- const phaseDirs = fs.readdirSync(phasesDir, { withFileTypes: true })
742
- .filter(e => e.isDirectory()).map(e => e.name)
743
- .filter(isDirInMilestone);
744
- let diskTotalPlans = 0;
745
- let diskTotalSummaries = 0;
746
- let diskCompletedPhases = 0;
747
-
748
- for (const dir of phaseDirs) {
749
- const files = fs.readdirSync(path.join(phasesDir, dir));
750
- const plans = files.filter(f => f.match(/-PLAN\.md$/i)).length;
751
- const summaries = files.filter(f => f.match(/-SUMMARY\.md$/i)).length;
752
- diskTotalPlans += plans;
753
- diskTotalSummaries += summaries;
754
- if (plans > 0 && summaries >= plans) diskCompletedPhases++;
786
+ // Use cached disk scan when available — avoids N+1 readdirSync calls
787
+ // on repeated buildStateFrontmatter invocations within the same process (#1967)
788
+ let cached = _diskScanCache.get(cwd);
789
+ if (!cached) {
790
+ const isDirInMilestone = getMilestonePhaseFilter(cwd);
791
+ const allMatchingDirs = fs.readdirSync(phasesDir, { withFileTypes: true })
792
+ .filter(e => e.isDirectory()).map(e => e.name)
793
+ .filter(isDirInMilestone);
794
+
795
+ // Bug #2445: when stale phase dirs from a prior milestone remain in
796
+ // .planning/phases/ alongside new dirs with the same phase number,
797
+ // de-duplicate by normalized phase number keeping the most recently
798
+ // modified dir. This prevents double-counting (e.g. two "Phase 1" dirs).
799
+ const seenPhaseNums = new Map(); // normalizedNum -> dirName
800
+ for (const dir of allMatchingDirs) {
801
+ const m = dir.match(/^0*(\d+[A-Za-z]?(?:\.\d+)*)/);
802
+ const key = m ? m[1].toLowerCase() : dir;
803
+ if (!seenPhaseNums.has(key)) {
804
+ seenPhaseNums.set(key, dir);
805
+ } else {
806
+ // Keep the dir that is newer on disk (more likely current milestone)
807
+ try {
808
+ const existing = path.join(phasesDir, seenPhaseNums.get(key));
809
+ const candidate = path.join(phasesDir, dir);
810
+ if (fs.statSync(candidate).mtimeMs > fs.statSync(existing).mtimeMs) {
811
+ seenPhaseNums.set(key, dir);
812
+ }
813
+ } catch { /* keep existing on stat error */ }
814
+ }
815
+ }
816
+ const phaseDirs = [...seenPhaseNums.values()];
817
+
818
+ let diskTotalPlans = 0;
819
+ let diskTotalSummaries = 0;
820
+ let diskCompletedPhases = 0;
821
+
822
+ for (const dir of phaseDirs) {
823
+ const phaseDir = path.join(phasesDir, dir);
824
+ const { planCount, summaryCount, completed } = scanPhasePlans(phaseDir);
825
+ diskTotalPlans += planCount;
826
+ diskTotalSummaries += summaryCount;
827
+ if (completed) diskCompletedPhases++;
828
+ }
829
+ cached = {
830
+ totalPhases: isDirInMilestone.phaseCount > 0
831
+ ? Math.max(phaseDirs.length, isDirInMilestone.phaseCount)
832
+ : phaseDirs.length,
833
+ completedPhases: diskCompletedPhases,
834
+ totalPlans: diskTotalPlans,
835
+ completedPlans: diskTotalSummaries,
836
+ };
837
+ _diskScanCache.set(cwd, cached);
755
838
  }
756
- totalPhases = isDirInMilestone.phaseCount > 0
757
- ? Math.max(phaseDirs.length, isDirInMilestone.phaseCount)
758
- : phaseDirs.length;
759
- completedPhases = diskCompletedPhases;
760
- totalPlans = diskTotalPlans;
761
- completedPlans = diskTotalSummaries;
839
+ totalPhases = cached.totalPhases;
840
+ completedPhases = cached.completedPhases;
841
+ totalPlans = cached.totalPlans;
842
+ completedPlans = cached.completedPlans;
762
843
  }
763
844
  } catch { /* intentionally empty */ }
764
845
  }
765
846
 
766
847
  // Derive percent from disk counts when available (ground truth).
767
- // Only falls back to the body Progress: field when no plan files exist on disk
768
- // (phases directory empty or absent), which means disk has no authoritative data.
769
- // This prevents a stale body "0%" from overriding the real 100% completion state.
770
- let progressPercent = null;
771
- if (totalPlans !== null && totalPlans > 0 && completedPlans !== null) {
772
- progressPercent = Math.min(100, Math.round(completedPlans / totalPlans * 100));
773
- } else if (progressRaw) {
848
+ // Uses min(plan_fraction, phase_fraction) via computeProgressPercent so that
849
+ // ROADMAP-declared-but-unrealized future phases cap the reported completion
850
+ // instead of a false 100% from plan-only coverage (#3242 Bug B).
851
+ // Falls back to the body Progress: field only when no plan files exist on disk.
852
+ let progressPercent = computeProgressPercent(completedPlans, totalPlans, completedPhases, totalPhases);
853
+ if (progressPercent === null && progressRaw) {
774
854
  const pctMatch = progressRaw.match(/(\d+)%/);
775
855
  if (pctMatch) progressPercent = parseInt(pctMatch[1], 10);
776
856
  }
777
857
 
778
- // Normalize status to one of: planning, discussing, executing, verifying, paused, completed, unknown
779
- let normalizedStatus = status || 'unknown';
780
- const statusLower = (status || '').toLowerCase();
781
- if (statusLower.includes('paused') || statusLower.includes('stopped') || pausedAt) {
782
- normalizedStatus = 'paused';
783
- } else if (statusLower.includes('executing') || statusLower.includes('in progress')) {
784
- normalizedStatus = 'executing';
785
- } else if (statusLower.includes('planning') || statusLower.includes('ready to plan')) {
786
- normalizedStatus = 'planning';
787
- } else if (statusLower.includes('discussing')) {
788
- normalizedStatus = 'discussing';
789
- } else if (statusLower.includes('verif')) {
790
- normalizedStatus = 'verifying';
791
- } else if (statusLower.includes('complete') || statusLower.includes('done')) {
792
- normalizedStatus = 'completed';
793
- } else if (statusLower.includes('ready to execute')) {
794
- normalizedStatus = 'executing';
795
- }
858
+ const normalizedStatus = normalizeStateStatus(status, pausedAt);
796
859
 
797
860
  const fm = { sdd_state_version: '1.0' };
798
861
 
@@ -904,10 +967,14 @@ function releaseStateLock(lockPath) {
904
967
  * each other's changes (race condition with read-modify-write cycle).
905
968
  */
906
969
  function writeStateMd(statePath, content, cwd) {
970
+ // Invalidate disk scan cache before computing new frontmatter — the write
971
+ // may create new PLAN/SUMMARY files that buildStateFrontmatter must see.
972
+ // Safe for any calling pattern, not just short-lived CLI processes (#1967).
973
+ if (cwd) _diskScanCache.delete(cwd);
907
974
  const synced = syncStateFrontmatter(content, cwd);
908
975
  const lockPath = acquireStateLock(statePath);
909
976
  try {
910
- atomicWriteFileSync(statePath, normalizeMd(synced), 'utf-8');
977
+ platformWriteSync(statePath, synced);
911
978
  } finally {
912
979
  releaseStateLock(lockPath);
913
980
  }
@@ -918,14 +985,44 @@ function writeStateMd(statePath, content, cwd) {
918
985
  * Holds the lock across the entire read -> transform -> write cycle,
919
986
  * preventing the lost-update problem where two agents read the same
920
987
  * content and the second write clobbers the first.
988
+ *
989
+ * @param {string} statePath
990
+ * @param {function} transformFn - (content: string) => string
991
+ * @param {string} cwd
992
+ * @param {{ resync?: boolean }} [options]
993
+ * resync: when true (default) rebuilds the entire frontmatter from disk after
994
+ * the transform. Pass { resync: false } for body-only updates (e.g. state.update
995
+ * on a single field) that must not trample manually-curated cross-milestone
996
+ * progress.* counters in the frontmatter (#3242 Bug A).
997
+ * When resync is false, syncStateFrontmatter still runs to maintain/create the
998
+ * frontmatter block, but any existing progress.* sub-keys are preserved from
999
+ * the pre-transform file rather than being rebuilt from disk.
921
1000
  */
922
- function readModifyWriteStateMd(statePath, transformFn, cwd) {
1001
+ function readModifyWriteStateMd(statePath, transformFn, cwd, options) {
1002
+ const resync = !options || options.resync !== false;
923
1003
  const lockPath = acquireStateLock(statePath);
924
1004
  try {
925
- const content = fs.existsSync(statePath) ? fs.readFileSync(statePath, 'utf-8') : '';
1005
+ const content = platformReadSync(statePath) || '';
1006
+ // Snapshot the existing progress block BEFORE the transform so we can
1007
+ // restore it when resync is false.
1008
+ const preFm = resync ? null : extractFrontmatter(content);
926
1009
  const modified = transformFn(content);
927
- const synced = syncStateFrontmatter(modified, cwd);
928
- atomicWriteFileSync(statePath, normalizeMd(synced), 'utf-8');
1010
+ let synced = syncStateFrontmatter(modified, cwd);
1011
+
1012
+ if (!resync && preFm && preFm.progress) {
1013
+ // Re-apply the curated progress block that syncStateFrontmatter just
1014
+ // overwrote with disk-derived values. Only restore keys that were present
1015
+ // in the snapshot — this preserves any new non-progress frontmatter fields
1016
+ // (e.g., status, current_phase) that syncStateFrontmatter legitimately
1017
+ // derived from the updated body.
1018
+ const postFm = extractFrontmatter(synced);
1019
+ postFm.progress = preFm.progress;
1020
+ const yamlStr = reconstructFrontmatter(postFm);
1021
+ const body = stripFrontmatter(synced);
1022
+ synced = `---\n${yamlStr}\n---\n\n${body}`;
1023
+ }
1024
+
1025
+ platformWriteSync(statePath, synced);
929
1026
  } finally {
930
1027
  releaseStateLock(lockPath);
931
1028
  }
@@ -958,6 +1055,12 @@ function cmdStateJson(cwd, raw) {
958
1055
  if (built.status === 'unknown' && existingFm && existingFm.status && existingFm.status !== 'unknown') {
959
1056
  built.status = existingFm.status;
960
1057
  }
1058
+ // Preserve curated cross-milestone aggregates when local disk scanning sees
1059
+ // only a narrower realized subset (#3242 Bug A). Stale lower counters still
1060
+ // rebuild from disk because they do not exceed the derived scan.
1061
+ if (existingFm && shouldPreserveExistingProgress(existingFm.progress, built.progress)) {
1062
+ built.progress = normalizeProgressNumbers(existingFm.progress);
1063
+ }
961
1064
 
962
1065
  output(built, raw, JSON.stringify(built, null, 2));
963
1066
  }
@@ -979,87 +1082,113 @@ function cmdStateBeginPhase(cwd, phaseNumber, phaseName, planCount, raw) {
979
1082
  const updated = [];
980
1083
 
981
1084
  readModifyWriteStateMd(statePath, (content) => {
1085
+ // Idempotency guard (#3127): if the phase is already mid-flight, do NOT
1086
+ // overwrite execution-progress fields (Current Plan, plan body line,
1087
+ // Last Activity Description). Only update fields that are safe to
1088
+ // refresh on resume (Last Activity date, Status if inconsistent).
1089
+ // A phase is considered mid-flight when Status contains 'Executing Phase N'
1090
+ // for the current phase number.
1091
+ const currentStatus = stateExtractField(content, 'Status') || '';
1092
+ const isAlreadyExecuting = new RegExp(`Executing Phase\\s+${escapeRegex(String(phaseNumber))}\\b`, 'i').test(currentStatus);
1093
+
982
1094
  // Update Status field
983
1095
  const statusValue = `Executing Phase ${phaseNumber}`;
984
1096
  let result = stateReplaceField(content, 'Status', statusValue);
985
1097
  if (result) { content = result; updated.push('Status'); }
986
1098
 
987
- // Update Last Activity
1099
+ // Update Last Activity (safe to update on resume — tracks when execute-phase ran)
988
1100
  result = stateReplaceField(content, 'Last Activity', today);
989
1101
  if (result) { content = result; updated.push('Last Activity'); }
990
1102
 
991
- // Update Last Activity Description if it exists
992
- const activityDesc = `Phase ${phaseNumber} execution started`;
993
- result = stateReplaceField(content, 'Last Activity Description', activityDesc);
994
- if (result) { content = result; updated.push('Last Activity Description'); }
1103
+ if (!isAlreadyExecuting) {
1104
+ // First-time execution: set all progress fields
995
1105
 
996
- // Update Current Phase
997
- result = stateReplaceField(content, 'Current Phase', String(phaseNumber));
998
- if (result) { content = result; updated.push('Current Phase'); }
999
-
1000
- // Update Current Phase Name
1001
- if (phaseName) {
1002
- result = stateReplaceField(content, 'Current Phase Name', phaseName);
1003
- if (result) { content = result; updated.push('Current Phase Name'); }
1004
- }
1106
+ // Update Last Activity Description
1107
+ const activityDesc = `Phase ${phaseNumber} execution started`;
1108
+ result = stateReplaceField(content, 'Last Activity Description', activityDesc);
1109
+ if (result) { content = result; updated.push('Last Activity Description'); }
1005
1110
 
1006
- // Update Current Plan to 1 (starting from the first plan)
1007
- result = stateReplaceField(content, 'Current Plan', '1');
1008
- if (result) { content = result; updated.push('Current Plan'); }
1111
+ // Update Current Phase
1112
+ result = stateReplaceField(content, 'Current Phase', String(phaseNumber));
1113
+ if (result) { content = result; updated.push('Current Phase'); }
1009
1114
 
1010
- // Update Total Plans in Phase
1011
- if (planCount) {
1012
- result = stateReplaceField(content, 'Total Plans in Phase', String(planCount));
1013
- if (result) { content = result; updated.push('Total Plans in Phase'); }
1014
- }
1015
-
1016
- // Update **Current focus:** body text line (#1104)
1017
- const focusLabel = phaseName ? `Phase ${phaseNumber} — ${phaseName}` : `Phase ${phaseNumber}`;
1018
- const focusPattern = /(\*\*Current focus:\*\*\s*).*/i;
1019
- if (focusPattern.test(content)) {
1020
- content = content.replace(focusPattern, (_match, prefix) => `${prefix}${focusLabel}`);
1021
- updated.push('Current focus');
1022
- }
1115
+ // Update Current Phase Name
1116
+ if (phaseName) {
1117
+ result = stateReplaceField(content, 'Current Phase Name', phaseName);
1118
+ if (result) { content = result; updated.push('Current Phase Name'); }
1119
+ }
1023
1120
 
1024
- // Update ## Current Position section (#1104, #1365)
1025
- // Update individual fields within Current Position instead of replacing the
1026
- // entire section, so that Status, Last activity, and Progress are preserved.
1027
- const positionPattern = /(##\s*Current Position\s*\n)([\s\S]*?)(?=\n##|$)/i;
1028
- const positionMatch = content.match(positionPattern);
1029
- if (positionMatch) {
1030
- const header = positionMatch[1];
1031
- let posBody = positionMatch[2];
1121
+ // Update Current Plan to 1 (starting from the first plan)
1122
+ result = stateReplaceField(content, 'Current Plan', '1');
1123
+ if (result) { content = result; updated.push('Current Plan'); }
1032
1124
 
1033
- // Update or insert Phase line
1034
- const newPhase = `Phase: ${phaseNumber}${phaseName ? ` (${phaseName})` : ''} — EXECUTING`;
1035
- if (/^Phase:/m.test(posBody)) {
1036
- posBody = posBody.replace(/^Phase:.*$/m, newPhase);
1037
- } else {
1038
- posBody = newPhase + '\n' + posBody;
1125
+ // Update Total Plans in Phase
1126
+ if (planCount) {
1127
+ result = stateReplaceField(content, 'Total Plans in Phase', String(planCount));
1128
+ if (result) { content = result; updated.push('Total Plans in Phase'); }
1039
1129
  }
1040
1130
 
1041
- // Update or insert Plan line
1042
- const newPlan = `Plan: 1 of ${planCount || '?'}`;
1043
- if (/^Plan:/m.test(posBody)) {
1044
- posBody = posBody.replace(/^Plan:.*$/m, newPlan);
1045
- } else {
1046
- posBody = posBody.replace(/^(Phase:.*$)/m, `$1\n${newPlan}`);
1131
+ // Update **Current focus:** body text line (#1104)
1132
+ const focusLabel = phaseName ? `Phase ${phaseNumber} ${phaseName}` : `Phase ${phaseNumber}`;
1133
+ const focusPattern = /(\*\*Current focus:\*\*\s*).*/i;
1134
+ if (focusPattern.test(content)) {
1135
+ content = content.replace(focusPattern, (_match, prefix) => `${prefix}${focusLabel}`);
1136
+ updated.push('Current focus');
1047
1137
  }
1048
1138
 
1049
- // Update Status line if present
1050
- const newStatus = `Status: Executing Phase ${phaseNumber}`;
1051
- if (/^Status:/m.test(posBody)) {
1052
- posBody = posBody.replace(/^Status:.*$/m, newStatus);
1053
- }
1139
+ // Update ## Current Position section (#1104, #1365)
1140
+ const positionPattern = /(##\s*Current Position\s*\n)([\s\S]*?)(?=\n##|$)/i;
1141
+ const positionMatch = content.match(positionPattern);
1142
+ if (positionMatch) {
1143
+ const header = positionMatch[1];
1144
+ let posBody = positionMatch[2];
1145
+
1146
+ // Update or insert Phase line
1147
+ const newPhase = `Phase: ${phaseNumber}${phaseName ? ` (${phaseName})` : ''} — EXECUTING`;
1148
+ if (/^Phase:/m.test(posBody)) {
1149
+ posBody = posBody.replace(/^Phase:.*$/m, newPhase);
1150
+ } else {
1151
+ posBody = newPhase + '\n' + posBody;
1152
+ }
1054
1153
 
1055
- // Update Last activity line if present
1056
- const newActivity = `Last activity: ${today} -- Phase ${phaseNumber} execution started`;
1057
- if (/^Last activity:/im.test(posBody)) {
1058
- posBody = posBody.replace(/^Last activity:.*$/im, newActivity);
1059
- }
1154
+ // Update or insert Plan line
1155
+ const newPlan = `Plan: 1 of ${planCount || '?'}`;
1156
+ if (/^Plan:/m.test(posBody)) {
1157
+ posBody = posBody.replace(/^Plan:.*$/m, newPlan);
1158
+ } else {
1159
+ posBody = posBody.replace(/^(Phase:.*$)/m, `$1\n${newPlan}`);
1160
+ }
1060
1161
 
1061
- content = content.replace(positionPattern, `${header}${posBody}`);
1062
- updated.push('Current Position');
1162
+ // Update Status line if present
1163
+ const newStatus = `Status: Executing Phase ${phaseNumber}`;
1164
+ if (/^Status:/m.test(posBody)) {
1165
+ posBody = posBody.replace(/^Status:.*$/m, newStatus);
1166
+ }
1167
+
1168
+ // Update Last activity line if present
1169
+ const newActivity = `Last activity: ${today} -- Phase ${phaseNumber} execution started`;
1170
+ if (/^Last activity:/im.test(posBody)) {
1171
+ posBody = posBody.replace(/^Last activity:.*$/im, newActivity);
1172
+ }
1173
+
1174
+ content = content.replace(positionPattern, () => `${header}${posBody}`);
1175
+ updated.push('Current Position');
1176
+ }
1177
+ } else {
1178
+ // Resume path: only update Last activity timestamp in Current Position
1179
+ // (do not touch Plan:, stopped_at, progress.percent, or plan counter)
1180
+ const positionPattern = /(##\s*Current Position\s*\n)([\s\S]*?)(?=\n##|$)/i;
1181
+ const positionMatch = content.match(positionPattern);
1182
+ if (positionMatch) {
1183
+ const header = positionMatch[1];
1184
+ let posBody = positionMatch[2];
1185
+ const resumeActivity = `Last activity: ${today} -- Phase ${phaseNumber} execution resumed (wave continue)`;
1186
+ if (/^Last activity:/im.test(posBody)) {
1187
+ posBody = posBody.replace(/^Last activity:.*$/im, resumeActivity);
1188
+ content = content.replace(positionPattern, () => `${header}${posBody}`);
1189
+ updated.push('Last activity (resume)');
1190
+ }
1191
+ }
1063
1192
  }
1064
1193
 
1065
1194
  return content;
@@ -1088,8 +1217,8 @@ function cmdSignalWaiting(cwd, type, question, options, phase, raw) {
1088
1217
  };
1089
1218
 
1090
1219
  try {
1091
- fs.mkdirSync(sddDir, { recursive: true });
1092
- fs.writeFileSync(waitingPath, JSON.stringify(signal, null, 2), 'utf-8');
1220
+ platformEnsureDir(sddDir);
1221
+ platformWriteSync(waitingPath, JSON.stringify(signal, null, 2));
1093
1222
  output({ signaled: true, path: waitingPath }, raw, 'true');
1094
1223
  } catch (e) {
1095
1224
  output({ signaled: false, error: e.message }, raw, 'false');
@@ -1149,7 +1278,7 @@ function updatePerformanceMetricsSection(content, cwd, phaseNum, planCount, summ
1149
1278
  tableBody = tableBody ? tableBody + '\n' + newRow : newRow;
1150
1279
  }
1151
1280
 
1152
- content = content.replace(byPhaseTablePattern, `$1${tableBody}\n`);
1281
+ content = content.replace(byPhaseTablePattern, (_match, tableHeader) => `${tableHeader}${tableBody}\n`);
1153
1282
  }
1154
1283
 
1155
1284
  return content;
@@ -1201,6 +1330,70 @@ function cmdStatePlannedPhase(cwd, phaseNumber, planCount, raw) {
1201
1330
  output({ updated, phase: phaseNumber, plan_count: planCount }, raw, updated.length > 0 ? 'true' : 'false');
1202
1331
  }
1203
1332
 
1333
+ /**
1334
+ * Bug #2630: reset STATE.md for a new milestone cycle.
1335
+ * Stomps frontmatter milestone/milestone_name/status/progress AND rewrites
1336
+ * the Current Position body. Preserves Accumulated Context.
1337
+ * Symmetric with the SDK `stateMilestoneSwitch` handler.
1338
+ */
1339
+ function cmdStateMilestoneSwitch(cwd, version, name, raw) {
1340
+ if (!version || !String(version).trim()) {
1341
+ output({ error: 'milestone required (--milestone <vX.Y>)' }, raw);
1342
+ return;
1343
+ }
1344
+ const resolvedName = (name && String(name).trim()) || 'milestone';
1345
+ const statePath = planningPaths(cwd).state;
1346
+ const today = new Date().toISOString().split('T')[0];
1347
+
1348
+ const lockPath = acquireStateLock(statePath);
1349
+ try {
1350
+ const content = platformReadSync(statePath) || '';
1351
+ const existingFm = extractFrontmatter(content);
1352
+ const body = stripFrontmatter(content);
1353
+
1354
+ const positionPattern = /(##\s*Current Position\s*\n)([\s\S]*?)(?=\n##|$)/i;
1355
+ const resetPositionBody =
1356
+ `\nPhase: Not started (defining requirements)\n` +
1357
+ `Plan: —\n` +
1358
+ `Status: Defining requirements\n` +
1359
+ `Last activity: ${today} — Milestone ${version} started\n\n`;
1360
+ let newBody;
1361
+ if (positionPattern.test(body)) {
1362
+ newBody = body.replace(positionPattern, (_m, header) => `${header}${resetPositionBody}`);
1363
+ } else {
1364
+ const preface = body.trim().length > 0 ? body : '# Project State\n';
1365
+ newBody = `${preface.trimEnd()}\n\n## Current Position\n${resetPositionBody}`;
1366
+ }
1367
+
1368
+ const fm = {
1369
+ sdd_state_version: existingFm.sdd_state_version || '1.0',
1370
+ milestone: version,
1371
+ milestone_name: resolvedName,
1372
+ status: 'planning',
1373
+ last_updated: new Date().toISOString(),
1374
+ last_activity: today,
1375
+ progress: {
1376
+ total_phases: 0,
1377
+ completed_phases: 0,
1378
+ total_plans: 0,
1379
+ completed_plans: 0,
1380
+ percent: 0,
1381
+ },
1382
+ };
1383
+
1384
+ const yamlStr = reconstructFrontmatter(fm);
1385
+ const assembled = `---\n${yamlStr}\n---\n\n${newBody.replace(/^\n+/, '')}`;
1386
+ platformWriteSync(statePath, assembled);
1387
+ output(
1388
+ { switched: true, version, name: resolvedName, status: 'planning' },
1389
+ raw,
1390
+ 'true',
1391
+ );
1392
+ } finally {
1393
+ releaseStateLock(lockPath);
1394
+ }
1395
+ }
1396
+
1204
1397
  /**
1205
1398
  * Gate 1: Validate STATE.md against filesystem.
1206
1399
  * Returns { valid, warnings, drift } JSON.
@@ -1231,9 +1424,7 @@ function cmdStateValidate(cwd, raw) {
1231
1424
  const phaseDir = entries.find(e => e.isDirectory() && e.name.startsWith(normalized.replace(/^0+/, '').padStart(2, '0')));
1232
1425
  if (phaseDir) {
1233
1426
  const phaseDirPath = path.join(phasesDir, phaseDir.name);
1234
- const files = fs.readdirSync(phaseDirPath);
1235
- const diskPlans = files.filter(f => f.match(/-PLAN\.md$/i)).length;
1236
- const diskSummaries = files.filter(f => f.match(/-SUMMARY\.md$/i)).length;
1427
+ const { planCount: diskPlans, summaryCount: diskSummaries } = scanPhasePlans(phaseDirPath);
1237
1428
 
1238
1429
  // Check plan count mismatch
1239
1430
  if (totalPlansInPhase !== null && diskPlans !== totalPlansInPhase) {
@@ -1242,6 +1433,7 @@ function cmdStateValidate(cwd, raw) {
1242
1433
  }
1243
1434
 
1244
1435
  // Check for VERIFICATION.md
1436
+ const files = fs.readdirSync(phaseDirPath);
1245
1437
  const verificationFiles = files.filter(f => f.includes('VERIFICATION') && f.endsWith('.md'));
1246
1438
  for (const vf of verificationFiles) {
1247
1439
  try {
@@ -1306,6 +1498,7 @@ function cmdStateSync(cwd, options, raw) {
1306
1498
 
1307
1499
  let totalDiskPlans = 0;
1308
1500
  let totalDiskSummaries = 0;
1501
+ let diskCompletedPhases = 0;
1309
1502
  let highestIncompletePhase = null;
1310
1503
  let highestIncompletePhaseNum = null;
1311
1504
  let highestIncompletePhaseplanCount = 0;
@@ -1313,11 +1506,10 @@ function cmdStateSync(cwd, options, raw) {
1313
1506
 
1314
1507
  for (const dir of entries) {
1315
1508
  const dirPath = path.join(phasesDir, dir);
1316
- const files = fs.readdirSync(dirPath);
1317
- const plans = files.filter(f => f.match(/-PLAN\.md$/i)).length;
1318
- const summaries = files.filter(f => f.match(/-SUMMARY\.md$/i)).length;
1509
+ const { planCount: plans, summaryCount: summaries, completed } = scanPhasePlans(dirPath);
1319
1510
  totalDiskPlans += plans;
1320
1511
  totalDiskSummaries += summaries;
1512
+ if (completed) diskCompletedPhases++;
1321
1513
 
1322
1514
  // Track the highest phase with incomplete plans (or any plans)
1323
1515
  const phaseMatch = dir.match(/^(\d+[A-Z]?(?:\.\d+)*)/i);
@@ -1338,6 +1530,18 @@ function cmdStateSync(cwd, options, raw) {
1338
1530
  }
1339
1531
  }
1340
1532
 
1533
+ // Determine total phases from ROADMAP (may be larger than realized disk dirs).
1534
+ // Mirrors the logic in buildStateFrontmatter so both report consistent percents (#3242 Bug B).
1535
+ let syncTotalPhases = null;
1536
+ try {
1537
+ const isDirInMilestone = getMilestonePhaseFilter(cwd);
1538
+ if (isDirInMilestone.phaseCount > 0) {
1539
+ syncTotalPhases = Math.max(entries.length, isDirInMilestone.phaseCount);
1540
+ } else {
1541
+ syncTotalPhases = entries.length;
1542
+ }
1543
+ } catch { /* intentionally empty */ }
1544
+
1341
1545
  // Sync Total Plans in Phase
1342
1546
  if (highestIncompletePhase) {
1343
1547
  const currentPlansField = stateExtractField(modified, 'Total Plans in Phase');
@@ -1348,8 +1552,13 @@ function cmdStateSync(cwd, options, raw) {
1348
1552
  }
1349
1553
  }
1350
1554
 
1351
- // Sync Progress
1352
- const percent = totalDiskPlans > 0 ? Math.min(100, Math.round(totalDiskSummaries / totalDiskPlans * 100)) : 0;
1555
+ // Sync Progress — use shared helper so formula stays in one place (#3242 Bug B).
1556
+ // computeProgressPercent applies min(plan_fraction, phase_fraction) so unrealised
1557
+ // ROADMAP phases cap the reported percent rather than allowing a false 100%.
1558
+ const percent = (() => {
1559
+ const p = computeProgressPercent(totalDiskSummaries, totalDiskPlans, diskCompletedPhases, syncTotalPhases);
1560
+ return p !== null ? p : 0;
1561
+ })();
1353
1562
  const currentProgress = stateExtractField(modified, 'Progress');
1354
1563
  if (currentProgress) {
1355
1564
  const currentPercent = parseInt(currentProgress.replace(/[^\d]/g, ''), 10);
@@ -1386,6 +1595,296 @@ function cmdStateSync(cwd, options, raw) {
1386
1595
  output({ synced: true, changes, dry_run: false }, raw);
1387
1596
  }
1388
1597
 
1598
+ /**
1599
+ * Prune old entries from STATE.md sections that grow unboundedly (#1970).
1600
+ * Moves decisions, recently-completed summaries, and resolved blockers
1601
+ * older than keepRecent phases to STATE-ARCHIVE.md.
1602
+ *
1603
+ * Options:
1604
+ * keepRecent: number of recent phases to retain (default: 3)
1605
+ * dryRun: if true, return what would be pruned without modifying STATE.md
1606
+ */
1607
+ function cmdStatePrune(cwd, options, raw) {
1608
+ const silent = !!options.silent;
1609
+ const emit = silent ? () => {} : (result, r, v) => output(result, r, v);
1610
+ const statePath = planningPaths(cwd).state;
1611
+ if (!fs.existsSync(statePath)) { emit({ error: 'STATE.md not found' }, raw); return; }
1612
+
1613
+ const keepRecent = parseInt(options.keepRecent, 10) || 3;
1614
+ const dryRun = !!options.dryRun;
1615
+ const currentPhaseRaw = stateExtractField(fs.readFileSync(statePath, 'utf-8'), 'Current Phase');
1616
+ const currentPhase = parseInt(currentPhaseRaw, 10) || 0;
1617
+ const cutoff = currentPhase - keepRecent;
1618
+
1619
+ if (cutoff <= 0) {
1620
+ emit({ pruned: false, reason: `Only ${currentPhase} phases — nothing to prune with --keep-recent ${keepRecent}` }, raw, 'false');
1621
+ return;
1622
+ }
1623
+
1624
+ const archivePath = path.join(path.dirname(statePath), 'STATE-ARCHIVE.md');
1625
+ const archived = [];
1626
+
1627
+ // Shared pruning logic applied to both dry-run and real passes.
1628
+ // Returns { newContent, archivedSections }.
1629
+ function prunePass(content) {
1630
+ const sections = [];
1631
+
1632
+ // Prune Decisions section: entries like "- [Phase N]: ..."
1633
+ const decisionPattern = /(###?\s*(?:Decisions|Decisions Made|Accumulated.*Decisions)\s*\n)([\s\S]*?)(?=\n###?|\n##[^#]|$)/i;
1634
+ const decMatch = content.match(decisionPattern);
1635
+ if (decMatch) {
1636
+ const lines = decMatch[2].split('\n');
1637
+ const keep = [];
1638
+ const archive = [];
1639
+ for (const line of lines) {
1640
+ const phaseMatch = line.match(/^\s*-\s*\[Phase\s+(\d+)/i);
1641
+ if (phaseMatch && parseInt(phaseMatch[1], 10) <= cutoff) {
1642
+ archive.push(line);
1643
+ } else {
1644
+ keep.push(line);
1645
+ }
1646
+ }
1647
+ if (archive.length > 0) {
1648
+ sections.push({ section: 'Decisions', count: archive.length, lines: archive });
1649
+ content = content.replace(decisionPattern, (_m, header) => `${header}${keep.join('\n')}`);
1650
+ }
1651
+ }
1652
+
1653
+ // Prune Recently Completed section: entries mentioning phase numbers
1654
+ const recentPattern = /(###?\s*Recently Completed\s*\n)([\s\S]*?)(?=\n###?|\n##[^#]|$)/i;
1655
+ const recMatch = content.match(recentPattern);
1656
+ if (recMatch) {
1657
+ const lines = recMatch[2].split('\n');
1658
+ const keep = [];
1659
+ const archive = [];
1660
+ for (const line of lines) {
1661
+ const phaseMatch = line.match(/Phase\s+(\d+)/i);
1662
+ if (phaseMatch && parseInt(phaseMatch[1], 10) <= cutoff) {
1663
+ archive.push(line);
1664
+ } else {
1665
+ keep.push(line);
1666
+ }
1667
+ }
1668
+ if (archive.length > 0) {
1669
+ sections.push({ section: 'Recently Completed', count: archive.length, lines: archive });
1670
+ content = content.replace(recentPattern, (_m, header) => `${header}${keep.join('\n')}`);
1671
+ }
1672
+ }
1673
+
1674
+ // Prune resolved blockers: lines marked as resolved (strikethrough ~~text~~
1675
+ // or "[RESOLVED]" prefix) with a phase reference older than cutoff
1676
+ const blockersPattern = /(###?\s*(?:Blockers|Blockers\/Concerns|Blockers\s*&\s*Concerns)\s*\n)([\s\S]*?)(?=\n###?|\n##[^#]|$)/i;
1677
+ const blockersMatch = content.match(blockersPattern);
1678
+ if (blockersMatch) {
1679
+ const lines = blockersMatch[2].split('\n');
1680
+ const keep = [];
1681
+ const archive = [];
1682
+ for (const line of lines) {
1683
+ const isResolved = /~~.*~~|\[RESOLVED\]/i.test(line);
1684
+ const phaseMatch = line.match(/Phase\s+(\d+)/i);
1685
+ if (isResolved && phaseMatch && parseInt(phaseMatch[1], 10) <= cutoff) {
1686
+ archive.push(line);
1687
+ } else {
1688
+ keep.push(line);
1689
+ }
1690
+ }
1691
+ if (archive.length > 0) {
1692
+ sections.push({ section: 'Blockers (resolved)', count: archive.length, lines: archive });
1693
+ content = content.replace(blockersPattern, (_m, header) => `${header}${keep.join('\n')}`);
1694
+ }
1695
+ }
1696
+
1697
+ // Prune Performance Metrics table rows: keep only rows for phases > cutoff.
1698
+ // Preserves header rows (| Phase | ... and |---|...) and any prose around the table.
1699
+ const metricsPattern = /(###?\s*Performance Metrics\s*\n)([\s\S]*?)(?=\n###?|\n##[^#]|$)/i;
1700
+ const metricsMatch = content.match(metricsPattern);
1701
+ if (metricsMatch) {
1702
+ const sectionLines = metricsMatch[2].split('\n');
1703
+ const keep = [];
1704
+ const archive = [];
1705
+ for (const line of sectionLines) {
1706
+ // Table data row: starts with | followed by a number (phase)
1707
+ const tableRowMatch = line.match(/^\|\s*(\d+)\s*\|/);
1708
+ if (tableRowMatch) {
1709
+ const rowPhase = parseInt(tableRowMatch[1], 10);
1710
+ if (rowPhase <= cutoff) {
1711
+ archive.push(line);
1712
+ } else {
1713
+ keep.push(line);
1714
+ }
1715
+ } else {
1716
+ // Header row, separator row, or prose — always keep
1717
+ keep.push(line);
1718
+ }
1719
+ }
1720
+ if (archive.length > 0) {
1721
+ sections.push({ section: 'Performance Metrics', count: archive.length, lines: archive });
1722
+ content = content.replace(metricsPattern, (_m, header) => `${header}${keep.join('\n')}`);
1723
+ }
1724
+ }
1725
+
1726
+ return { newContent: content, archivedSections: sections };
1727
+ }
1728
+
1729
+ if (dryRun) {
1730
+ // Dry-run: compute what would be pruned without writing anything
1731
+ const content = fs.readFileSync(statePath, 'utf-8');
1732
+ const result = prunePass(content);
1733
+ const totalPruned = result.archivedSections.reduce((sum, s) => sum + s.count, 0);
1734
+ emit({
1735
+ pruned: false,
1736
+ dry_run: true,
1737
+ cutoff_phase: cutoff,
1738
+ keep_recent: keepRecent,
1739
+ sections: result.archivedSections.map(s => ({ section: s.section, entries_would_archive: s.count })),
1740
+ total_would_archive: totalPruned,
1741
+ note: totalPruned > 0 ? 'Run without --dry-run to actually prune' : 'Nothing to prune',
1742
+ }, raw, totalPruned > 0 ? 'true' : 'false');
1743
+ return;
1744
+ }
1745
+
1746
+ readModifyWriteStateMd(statePath, (content) => {
1747
+ const result = prunePass(content);
1748
+ archived.push(...result.archivedSections);
1749
+ return result.newContent;
1750
+ }, cwd);
1751
+
1752
+ // Write archived entries to STATE-ARCHIVE.md
1753
+ if (archived.length > 0) {
1754
+ const timestamp = new Date().toISOString().split('T')[0];
1755
+ let archiveContent = platformReadSync(archivePath);
1756
+ if (archiveContent === null) {
1757
+ archiveContent = '# STATE Archive\n\nPruned entries from STATE.md. Recoverable but no longer loaded into agent context.\n\n';
1758
+ }
1759
+ archiveContent += `## Pruned ${timestamp} (phases 1-${cutoff}, kept recent ${keepRecent})\n\n`;
1760
+ for (const section of archived) {
1761
+ archiveContent += `### ${section.section}\n\n${section.lines.join('\n')}\n\n`;
1762
+ }
1763
+ platformWriteSync(archivePath, archiveContent);
1764
+ }
1765
+
1766
+ const totalPruned = archived.reduce((sum, s) => sum + s.count, 0);
1767
+ emit({
1768
+ pruned: totalPruned > 0,
1769
+ cutoff_phase: cutoff,
1770
+ keep_recent: keepRecent,
1771
+ sections: archived.map(s => ({ section: s.section, entries_archived: s.count })),
1772
+ total_archived: totalPruned,
1773
+ archive_file: totalPruned > 0 ? 'STATE-ARCHIVE.md' : null,
1774
+ }, raw, totalPruned > 0 ? 'true' : 'false');
1775
+ }
1776
+
1777
+ /**
1778
+ * Mark the current phase as COMPLETE in STATE.md.
1779
+ * Updates Status, Last Activity, and the Current Position section to reflect
1780
+ * that the phase execution is finished and the project is ready for the next phase.
1781
+ * Implements the `sdd state complete-phase` subcommand (issue #2735).
1782
+ */
1783
+ function resolvePhaseIdForCompletePhase(content, overridePhase) {
1784
+ const candidate = overridePhase ||
1785
+ stateExtractField(content, 'Current Phase') ||
1786
+ stateExtractField(content, 'Phase') ||
1787
+ '';
1788
+
1789
+ // Accept canonical phase token only (e.g. 3, 03, 3A, 3.3, 10.2)
1790
+ const phaseMatch = String(candidate).match(/(\d+[A-Z]?(?:\.\d+)*)/i);
1791
+ return phaseMatch ? phaseMatch[1] : null;
1792
+ }
1793
+
1794
+ function cmdStateCompletePhase(cwd, raw, overridePhase) {
1795
+ const statePath = planningPaths(cwd).state;
1796
+ if (!fs.existsSync(statePath)) {
1797
+ output({ error: 'STATE.md not found' }, raw);
1798
+ return;
1799
+ }
1800
+
1801
+ const content = fs.readFileSync(statePath, 'utf-8');
1802
+ const resolvedPhase = resolvePhaseIdForCompletePhase(content, overridePhase);
1803
+ if (!resolvedPhase || /^phase$/i.test(resolvedPhase)) {
1804
+ output({ error: 'Unable to resolve current phase. Pass an explicit phase: state complete-phase --phase <N>' }, raw);
1805
+ return;
1806
+ }
1807
+
1808
+ // Idempotency guard (#3489). If STATE.md's canonical `Current Phase` field
1809
+ // already names a phase distinct from the one we are being asked to mark
1810
+ // complete, the project has advanced past the requested phase (e.g. a
1811
+ // follow-up phase was inserted, or the next phase began). Re-running
1812
+ // `state complete-phase --phase <N>` in that situation previously rolled
1813
+ // STATE.md back to <N>'s moment-of-completion — silently clobbering Status,
1814
+ // Last Activity, Last Activity Description, and the Current Position body.
1815
+ // The handler is now a no-op in that case so re-invocation from downstream
1816
+ // workflows cannot regress the project state.
1817
+ const existingCurrentPhaseRaw = stateExtractField(content, 'Current Phase') || '';
1818
+ const existingCurrentPhaseMatch = String(existingCurrentPhaseRaw).match(/(\d+[A-Z]?(?:\.\d+)*)/i);
1819
+ const existingCurrentPhase = existingCurrentPhaseMatch ? existingCurrentPhaseMatch[1] : null;
1820
+ if (existingCurrentPhase && existingCurrentPhase !== resolvedPhase) {
1821
+ output(
1822
+ { updated: [], phase: resolvedPhase, idempotent: true, note: 'phase already superseded; no-op' },
1823
+ raw,
1824
+ 'false',
1825
+ );
1826
+ return;
1827
+ }
1828
+
1829
+ const today = new Date().toISOString().split('T')[0];
1830
+ const updated = [];
1831
+
1832
+ readModifyWriteStateMd(statePath, (content) => {
1833
+ const currentPhase = resolvedPhase;
1834
+
1835
+ // Update Status field
1836
+ const statusValue = `Phase ${currentPhase} complete`;
1837
+ let result = stateReplaceField(content, 'Status', statusValue);
1838
+ if (result) { content = result; updated.push('Status'); }
1839
+
1840
+ // Update Last Activity date
1841
+ result = stateReplaceField(content, 'Last Activity', today);
1842
+ if (result) { content = result; updated.push('Last Activity'); }
1843
+
1844
+ // Update Last Activity Description
1845
+ const activityDesc = `Phase ${currentPhase} marked complete`;
1846
+ result = stateReplaceField(content, 'Last Activity Description', activityDesc);
1847
+ if (result) { content = result; updated.push('Last Activity Description'); }
1848
+
1849
+ // Update ## Current Position section
1850
+ const positionPattern = /(##\s*Current Position\s*\n)([\s\S]*?)(?=\n##|$)/i;
1851
+ const positionMatch = content.match(positionPattern);
1852
+ if (positionMatch) {
1853
+ const header = positionMatch[1];
1854
+ let posBody = positionMatch[2];
1855
+
1856
+ // Update Phase line to show COMPLETE
1857
+ const newPhase = `Phase: ${currentPhase} — COMPLETE`;
1858
+ if (/^Phase:/m.test(posBody)) {
1859
+ posBody = posBody.replace(/^Phase:.*$/m, newPhase);
1860
+ }
1861
+
1862
+ // Update Status line if present
1863
+ const newStatus = `Status: Phase ${currentPhase} complete`;
1864
+ if (/^Status:/m.test(posBody)) {
1865
+ posBody = posBody.replace(/^Status:.*$/m, newStatus);
1866
+ }
1867
+
1868
+ // Update Last activity line if present
1869
+ const newActivity = `Last activity: ${today} -- Phase ${currentPhase} marked complete`;
1870
+ if (/^Last activity:/im.test(posBody)) {
1871
+ posBody = posBody.replace(/^Last activity:.*$/im, newActivity);
1872
+ }
1873
+
1874
+ content = content.replace(positionPattern, () => `${header}${posBody}`);
1875
+ updated.push('Current Position');
1876
+ }
1877
+
1878
+ return content;
1879
+ }, cwd);
1880
+
1881
+ output(
1882
+ { updated, phase: resolvedPhase },
1883
+ raw,
1884
+ updated.length > 0 ? 'true' : 'false',
1885
+ );
1886
+ }
1887
+
1389
1888
  module.exports = {
1390
1889
  stateExtractField,
1391
1890
  stateReplaceField,
@@ -1408,8 +1907,11 @@ module.exports = {
1408
1907
  cmdStateJson,
1409
1908
  cmdStateBeginPhase,
1410
1909
  cmdStatePlannedPhase,
1910
+ cmdStateCompletePhase,
1411
1911
  cmdStateValidate,
1412
1912
  cmdStateSync,
1913
+ cmdStatePrune,
1914
+ cmdStateMilestoneSwitch,
1413
1915
  cmdSignalWaiting,
1414
1916
  cmdSignalResume,
1415
1917
  };