@bhargavvc/sdd-cc 1.30.1 → 1.42.3
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.
- package/README.ja-JP.md +165 -129
- package/README.ko-KR.md +161 -123
- package/README.md +103 -679
- package/README.pt-BR.md +92 -52
- package/README.zh-CN.md +145 -103
- package/agents/sdd-advisor-researcher.md +23 -0
- package/agents/sdd-ai-researcher.md +133 -0
- package/agents/sdd-code-fixer.md +668 -0
- package/agents/sdd-code-reviewer.md +387 -0
- package/agents/sdd-codebase-mapper.md +86 -3
- package/agents/sdd-debug-session-manager.md +314 -0
- package/agents/sdd-debugger.md +157 -78
- package/agents/sdd-doc-classifier.md +168 -0
- package/agents/sdd-doc-synthesizer.md +204 -0
- package/agents/sdd-doc-verifier.md +217 -0
- package/agents/sdd-doc-writer.md +615 -0
- package/agents/sdd-domain-researcher.md +153 -0
- package/agents/sdd-eval-auditor.md +191 -0
- package/agents/sdd-eval-planner.md +154 -0
- package/agents/sdd-executor.md +283 -40
- package/agents/sdd-framework-selector.md +160 -0
- package/agents/sdd-integration-checker.md +30 -3
- package/agents/sdd-intel-updater.md +342 -0
- package/agents/sdd-nyquist-auditor.md +31 -4
- package/agents/sdd-pattern-mapper.md +335 -0
- package/agents/sdd-phase-researcher.md +254 -24
- package/agents/sdd-plan-checker.md +223 -18
- package/agents/sdd-planner.md +286 -362
- package/agents/sdd-project-researcher.md +28 -5
- package/agents/sdd-research-synthesizer.md +4 -4
- package/agents/sdd-roadmapper.md +14 -5
- package/agents/sdd-security-auditor.md +155 -0
- package/agents/sdd-ui-auditor.md +60 -4
- package/agents/sdd-ui-checker.md +11 -2
- package/agents/sdd-ui-researcher.md +27 -4
- package/agents/sdd-user-profiler.md +2 -2
- package/agents/sdd-verifier.md +258 -41
- package/bin/install.js +6862 -618
- package/bin/sdd-sdk.js +37 -0
- package/commands/sdd/add-tests.md +3 -2
- package/commands/sdd/ai-integration-phase.md +37 -0
- package/commands/sdd/audit-fix.md +34 -0
- package/commands/sdd/audit-milestone.md +3 -2
- package/commands/sdd/autonomous.md +10 -5
- package/commands/sdd/capture.md +62 -0
- package/commands/sdd/cleanup.md +7 -1
- package/commands/sdd/code-review.md +59 -0
- package/commands/sdd/complete-milestone.md +11 -4
- package/commands/sdd/config.md +58 -0
- package/commands/sdd/debug.md +23 -144
- package/commands/sdd/discuss-phase.md +22 -10
- package/commands/sdd/docs-update.md +49 -0
- package/commands/sdd/eval-review.md +33 -0
- package/commands/sdd/execute-phase.md +9 -4
- package/commands/sdd/explore.md +27 -0
- package/commands/sdd/extract-learnings.md +23 -0
- package/commands/sdd/fast.md +2 -1
- package/commands/sdd/forensics.md +3 -2
- package/commands/sdd/graphify.md +199 -0
- package/commands/sdd/health.md +12 -3
- package/commands/sdd/help.md +3 -1
- package/commands/sdd/import.md +41 -0
- package/commands/sdd/inbox.md +39 -0
- package/commands/sdd/ingest-docs.md +42 -0
- package/commands/sdd/manager.md +9 -3
- package/commands/sdd/map-codebase.md +15 -3
- package/commands/sdd/milestone-summary.md +1 -1
- package/commands/sdd/mvp-phase.md +45 -0
- package/commands/sdd/new-milestone.md +3 -2
- package/commands/sdd/new-project.md +7 -2
- package/commands/sdd/ns-context.md +23 -0
- package/commands/sdd/ns-ideate.md +24 -0
- package/commands/sdd/ns-manage.md +29 -0
- package/commands/sdd/ns-project.md +22 -0
- package/commands/sdd/ns-review.md +26 -0
- package/commands/sdd/ns-workflow.md +28 -0
- package/commands/sdd/pause-work.md +6 -1
- package/commands/sdd/phase.md +56 -0
- package/commands/sdd/plan-phase.md +19 -4
- package/commands/sdd/plan-review-convergence.md +59 -0
- package/commands/sdd/pr-branch.md +2 -1
- package/commands/sdd/profile-user.md +2 -2
- package/commands/sdd/progress.md +27 -5
- package/commands/sdd/quick.md +132 -5
- package/commands/sdd/resume-work.md +2 -12
- package/commands/sdd/review-backlog.md +4 -2
- package/commands/sdd/review.md +7 -3
- package/commands/sdd/secure-phase.md +36 -0
- package/commands/sdd/settings.md +2 -9
- package/commands/sdd/ship.md +1 -0
- package/commands/sdd/sketch.md +60 -0
- package/commands/sdd/spec-phase.md +63 -0
- package/commands/sdd/spike.md +57 -0
- package/commands/sdd/stats.md +2 -1
- package/commands/sdd/surface.md +129 -0
- package/commands/sdd/thread.md +8 -111
- package/commands/sdd/ui-phase.md +3 -2
- package/commands/sdd/ui-review.md +3 -2
- package/commands/sdd/ultraplan-phase.md +34 -0
- package/commands/sdd/undo.md +35 -0
- package/commands/sdd/update.md +21 -10
- package/commands/sdd/validate-phase.md +3 -2
- package/commands/sdd/verify-work.md +4 -3
- package/commands/sdd/workspace.md +52 -0
- package/commands/sdd/workstreams.md +15 -8
- package/hooks/dist/sdd-check-update-worker.js +116 -0
- package/hooks/dist/sdd-check-update.js +19 -69
- package/hooks/dist/sdd-context-monitor.js +43 -7
- package/hooks/dist/sdd-phase-boundary.sh +47 -0
- package/hooks/dist/sdd-prompt-guard.js +1 -0
- package/hooks/dist/sdd-read-guard.js +101 -0
- package/hooks/dist/sdd-read-injection-scanner.js +152 -0
- package/hooks/dist/sdd-session-state.sh +59 -0
- package/hooks/dist/sdd-statusline.js +439 -21
- package/hooks/dist/sdd-update-banner.js +134 -0
- package/hooks/dist/sdd-validate-commit.sh +57 -0
- package/hooks/dist/sdd-workflow-guard.js +2 -2
- package/hooks/lib/git-cmd.js +150 -0
- package/hooks/sdd-check-update-worker.js +116 -0
- package/hooks/sdd-check-update.js +64 -0
- package/hooks/sdd-context-monitor.js +192 -0
- package/hooks/sdd-phase-boundary.sh +47 -0
- package/hooks/sdd-prompt-guard.js +97 -0
- package/hooks/sdd-read-guard.js +101 -0
- package/hooks/sdd-read-injection-scanner.js +152 -0
- package/hooks/sdd-session-state.sh +59 -0
- package/hooks/sdd-statusline.js +537 -0
- package/hooks/sdd-update-banner.js +134 -0
- package/hooks/sdd-validate-commit.sh +57 -0
- package/hooks/sdd-workflow-guard.js +94 -0
- package/package.json +34 -9
- package/scripts/audit-workflow-script-paths.cjs +73 -0
- package/scripts/build-hooks.js +114 -9
- package/scripts/changeset/cli.cjs +269 -0
- package/scripts/changeset/github-release-notes.cjs +198 -0
- package/scripts/changeset/lint.cjs +110 -0
- package/scripts/changeset/new.cjs +137 -0
- package/scripts/changeset/parse.cjs +60 -0
- package/scripts/changeset/render.cjs +34 -0
- package/scripts/changeset/serialize.cjs +74 -0
- package/scripts/command-contract-helpers.cjs +61 -0
- package/scripts/diff-touches-shipped-paths.cjs +147 -0
- package/scripts/fix-slash-commands.cjs +106 -0
- package/scripts/gen-inventory-manifest.cjs +109 -0
- package/scripts/lint-command-contract.cjs +108 -0
- package/scripts/lint-descriptions.cjs +83 -0
- package/scripts/lint-no-source-grep-extras.cjs +81 -0
- package/scripts/lint-no-source-grep.cjs +174 -0
- package/scripts/lint-shell-command-projection-drift.cjs +57 -0
- package/scripts/lint-skill-deps.cjs +180 -0
- package/scripts/pr-template-policy.cjs +169 -0
- package/scripts/prompt-injection-scan.sh +3 -0
- package/scripts/rebrand-gsd-to-sdd.sh +222 -220
- package/scripts/run-tests.cjs +5 -1
- package/scripts/strip-prose-atrefs.cjs +106 -0
- package/scripts/verify-tarball-sdk-dist.sh +69 -0
- package/sdd/bin/check-latest-version.cjs +104 -0
- package/sdd/bin/lib/active-workstream-store.cjs +85 -0
- package/sdd/bin/lib/adr-parser.cjs +394 -0
- package/sdd/bin/lib/artifacts.cjs +53 -0
- package/sdd/bin/lib/audit.cjs +755 -0
- package/sdd/bin/lib/cjs-command-router-adapter.cjs +39 -0
- package/sdd/bin/lib/clusters.cjs +135 -0
- package/sdd/bin/lib/command-aliases.generated.cjs +838 -0
- package/sdd/bin/lib/commands.cjs +179 -107
- package/sdd/bin/lib/config-schema.cjs +135 -0
- package/sdd/bin/lib/config.cjs +313 -86
- package/sdd/bin/lib/context-utilization.cjs +47 -0
- package/sdd/bin/lib/core.cjs +1146 -391
- package/sdd/bin/lib/decisions.cjs +48 -0
- package/sdd/bin/lib/docs.cjs +270 -0
- package/sdd/bin/lib/drift.cjs +379 -0
- package/sdd/bin/lib/fallow-runner.cjs +109 -0
- package/sdd/bin/lib/frontmatter.cjs +389 -336
- package/sdd/bin/lib/gap-checker.cjs +197 -0
- package/sdd/bin/lib/graphify.cjs +577 -0
- package/sdd/bin/lib/init-command-router.cjs +70 -0
- package/sdd/bin/lib/init.cjs +692 -97
- package/sdd/bin/lib/install-profiles.cjs +572 -0
- package/sdd/bin/lib/installer-migration-authoring.cjs +117 -0
- package/sdd/bin/lib/installer-migration-report.cjs +328 -0
- package/sdd/bin/lib/installer-migrations/000-first-time-baseline.cjs +220 -0
- package/sdd/bin/lib/installer-migrations/001-legacy-orphan-files.cjs +41 -0
- package/sdd/bin/lib/installer-migrations/002-codex-legacy-hooks-json.cjs +80 -0
- package/sdd/bin/lib/installer-migrations.cjs +703 -0
- package/sdd/bin/lib/intel.cjs +643 -0
- package/sdd/bin/lib/learnings.cjs +379 -0
- package/sdd/bin/lib/milestone.cjs +313 -252
- package/sdd/bin/lib/model-catalog.cjs +136 -0
- package/sdd/bin/lib/model-profiles.cjs +25 -68
- package/sdd/bin/lib/phase-command-router.cjs +96 -0
- package/sdd/bin/lib/phase.cjs +868 -335
- package/sdd/bin/lib/phases-command-router.cjs +39 -0
- package/sdd/bin/lib/plan-scan.cjs +138 -0
- package/sdd/bin/lib/planning-workspace.cjs +361 -0
- package/sdd/bin/lib/profile-output.cjs +197 -35
- package/sdd/bin/lib/profile-pipeline.cjs +1 -1
- package/sdd/bin/lib/review-reviewer-selection.cjs +125 -0
- package/sdd/bin/lib/roadmap-command-router.cjs +23 -0
- package/sdd/bin/lib/roadmap.cjs +416 -124
- package/sdd/bin/lib/runtime-homes.cjs +178 -0
- package/sdd/bin/lib/schema-detect.cjs +238 -0
- package/sdd/bin/lib/sdd2-import.cjs +511 -0
- package/sdd/bin/lib/secrets.cjs +33 -0
- package/sdd/bin/lib/security.cjs +131 -9
- package/sdd/bin/lib/shell-command-projection.cjs +548 -0
- package/sdd/bin/lib/state-command-router.cjs +100 -0
- package/sdd/bin/lib/state-document.cjs +12 -0
- package/sdd/bin/lib/state-document.generated.cjs +127 -0
- package/sdd/bin/lib/state.cjs +1253 -367
- package/sdd/bin/lib/surface.cjs +398 -0
- package/sdd/bin/lib/template.cjs +11 -5
- package/sdd/bin/lib/uat.cjs +9 -2
- package/sdd/bin/lib/validate-command-router.cjs +55 -0
- package/sdd/bin/lib/verify-command-router.cjs +34 -0
- package/sdd/bin/lib/verify.cjs +648 -140
- package/sdd/bin/lib/workstream-inventory.cjs +159 -0
- package/sdd/bin/lib/workstream-name-policy.cjs +33 -0
- package/sdd/bin/lib/workstream.cjs +78 -196
- package/sdd/bin/lib/worktree-safety.cjs +563 -0
- package/sdd/bin/sdd-tools.cjs +528 -222
- package/sdd/bin/verify-reapply-patches.cjs +247 -0
- package/sdd/contexts/dev.md +21 -0
- package/sdd/contexts/research.md +22 -0
- package/sdd/contexts/review.md +23 -0
- package/sdd/references/agent-contracts.md +79 -0
- package/sdd/references/ai-evals.md +156 -0
- package/sdd/references/ai-frameworks.md +186 -0
- package/sdd/references/artifact-types.md +131 -0
- package/sdd/references/autonomous-smart-discuss.md +277 -0
- package/sdd/references/checkpoints.md +36 -0
- package/sdd/references/common-bug-patterns.md +114 -0
- package/sdd/references/context-budget.md +85 -0
- package/sdd/references/continuation-format.md +30 -26
- package/sdd/references/debugger-philosophy.md +76 -0
- package/sdd/references/decimal-phase-calculation.md +5 -5
- package/sdd/references/doc-conflict-engine.md +91 -0
- package/sdd/references/domain-probes.md +125 -0
- package/sdd/references/execute-mvp-tdd.md +81 -0
- package/sdd/references/executor-examples.md +110 -0
- package/sdd/references/few-shot-examples/plan-checker.md +73 -0
- package/sdd/references/few-shot-examples/verifier.md +109 -0
- package/sdd/references/gate-prompts.md +100 -0
- package/sdd/references/gates.md +70 -0
- package/sdd/references/git-integration.md +9 -6
- package/sdd/references/git-planning-commit.md +6 -4
- package/sdd/references/ios-scaffold.md +123 -0
- package/sdd/references/mandatory-initial-read.md +2 -0
- package/sdd/references/model-profile-resolution.md +2 -0
- package/sdd/references/model-profiles.md +128 -22
- package/sdd/references/mvp-concepts.md +49 -0
- package/sdd/references/phase-argument-parsing.md +3 -3
- package/sdd/references/planner-antipatterns.md +89 -0
- package/sdd/references/planner-chunked.md +49 -0
- package/sdd/references/planner-gap-closure.md +62 -0
- package/sdd/references/planner-human-verify-mode.md +57 -0
- package/sdd/references/planner-mvp-mode.md +53 -0
- package/sdd/references/planner-reviews.md +39 -0
- package/sdd/references/planner-revision.md +87 -0
- package/sdd/references/planner-source-audit.md +73 -0
- package/sdd/references/planning-config.md +276 -7
- package/sdd/references/project-skills-discovery.md +19 -0
- package/sdd/references/revision-loop.md +97 -0
- package/sdd/references/scout-codebase.md +51 -0
- package/sdd/references/skeleton-template.md +48 -0
- package/sdd/references/sketch-interactivity.md +41 -0
- package/sdd/references/sketch-theme-system.md +94 -0
- package/sdd/references/sketch-tooling.md +45 -0
- package/sdd/references/sketch-variant-patterns.md +81 -0
- package/sdd/references/spidr-splitting.md +69 -0
- package/sdd/references/tdd.md +67 -0
- package/sdd/references/thinking-models-debug.md +44 -0
- package/sdd/references/thinking-models-execution.md +50 -0
- package/sdd/references/thinking-models-planning.md +62 -0
- package/sdd/references/thinking-models-research.md +50 -0
- package/sdd/references/thinking-models-verification.md +55 -0
- package/sdd/references/thinking-partner.md +96 -0
- package/sdd/references/ui-brand.md +4 -4
- package/sdd/references/universal-anti-patterns.md +63 -0
- package/sdd/references/user-story-template.md +58 -0
- package/sdd/references/verification-overrides.md +227 -0
- package/sdd/references/verify-mvp-mode.md +85 -0
- package/sdd/references/workstream-flag.md +63 -10
- package/sdd/references/worktree-path-safety.md +89 -0
- package/sdd/templates/AI-SPEC.md +246 -0
- package/sdd/templates/DEBUG.md +7 -2
- package/sdd/templates/README.md +77 -0
- package/sdd/templates/SECURITY.md +61 -0
- package/sdd/templates/VALIDATION.md +3 -3
- package/sdd/templates/claude-md.md +27 -4
- package/sdd/templates/config.json +20 -2
- package/sdd/templates/discovery.md +2 -2
- package/sdd/templates/research.md +40 -0
- package/sdd/templates/spec.md +307 -0
- package/sdd/templates/state.md +10 -2
- package/sdd/workflows/add-backlog.md +90 -0
- package/sdd/workflows/add-phase.md +12 -12
- package/sdd/workflows/add-tests.md +6 -3
- package/sdd/workflows/add-todo.md +8 -6
- package/sdd/workflows/ai-integration-phase.md +294 -0
- package/sdd/workflows/analyze-dependencies.md +96 -0
- package/sdd/workflows/audit-fix.md +177 -0
- package/sdd/workflows/audit-milestone.md +35 -18
- package/sdd/workflows/audit-uat.md +1 -1
- package/sdd/workflows/autonomous.md +202 -304
- package/sdd/workflows/check-todos.md +12 -10
- package/sdd/workflows/cleanup.md +3 -1
- package/sdd/workflows/code-review-fix.md +501 -0
- package/sdd/workflows/code-review.md +613 -0
- package/sdd/workflows/complete-milestone.md +115 -28
- package/sdd/workflows/debug.md +231 -0
- package/sdd/workflows/diagnose-issues.md +14 -5
- package/sdd/workflows/discovery-phase.md +3 -1
- package/sdd/workflows/discuss-phase/modes/advisor.md +175 -0
- package/sdd/workflows/discuss-phase/modes/all.md +28 -0
- package/sdd/workflows/discuss-phase/modes/analyze.md +44 -0
- package/sdd/workflows/discuss-phase/modes/auto.md +56 -0
- package/sdd/workflows/discuss-phase/modes/batch.md +52 -0
- package/sdd/workflows/discuss-phase/modes/chain.md +97 -0
- package/sdd/workflows/discuss-phase/modes/default.md +141 -0
- package/sdd/workflows/discuss-phase/modes/power.md +44 -0
- package/sdd/workflows/discuss-phase/modes/text.md +55 -0
- package/sdd/workflows/discuss-phase/templates/checkpoint.json +18 -0
- package/sdd/workflows/discuss-phase/templates/context.md +136 -0
- package/sdd/workflows/discuss-phase/templates/discussion-log.md +50 -0
- package/sdd/workflows/discuss-phase-assumptions.md +41 -20
- package/sdd/workflows/discuss-phase-power.md +291 -0
- package/sdd/workflows/discuss-phase.md +242 -792
- package/sdd/workflows/do.md +13 -7
- package/sdd/workflows/docs-update.md +1161 -0
- package/sdd/workflows/edit-phase.md +294 -0
- package/sdd/workflows/eval-review.md +155 -0
- package/sdd/workflows/execute-phase/steps/codebase-drift-gate.md +81 -0
- package/sdd/workflows/execute-phase/steps/per-plan-worktree-gate.md +94 -0
- package/sdd/workflows/execute-phase/steps/post-merge-gate.md +116 -0
- package/sdd/workflows/execute-phase.md +1062 -108
- package/sdd/workflows/execute-plan.md +118 -107
- package/sdd/workflows/explore.md +143 -0
- package/sdd/workflows/extract-learnings.md +242 -0
- package/sdd/workflows/forensics.md +17 -4
- package/sdd/workflows/graduation.md +195 -0
- package/sdd/workflows/health.md +45 -3
- package/sdd/workflows/help.md +265 -88
- package/sdd/workflows/import.md +253 -0
- package/sdd/workflows/inbox.md +387 -0
- package/sdd/workflows/ingest-docs.md +339 -0
- package/sdd/workflows/insert-phase.md +37 -16
- package/sdd/workflows/list-phase-assumptions.md +2 -2
- package/sdd/workflows/list-workspaces.md +3 -3
- package/sdd/workflows/manager.md +62 -32
- package/sdd/workflows/map-codebase.md +90 -24
- package/sdd/workflows/milestone-summary.md +6 -6
- package/sdd/workflows/mvp-phase.md +221 -0
- package/sdd/workflows/new-milestone.md +168 -20
- package/sdd/workflows/new-project.md +273 -47
- package/sdd/workflows/new-workspace.md +8 -6
- package/sdd/workflows/next.md +127 -4
- package/sdd/workflows/note.md +7 -5
- package/sdd/workflows/pause-work.md +79 -12
- package/sdd/workflows/plan-milestone-gaps.md +14 -7
- package/sdd/workflows/plan-phase.md +987 -62
- package/sdd/workflows/plan-review-convergence.md +329 -0
- package/sdd/workflows/plant-seed.md +145 -85
- package/sdd/workflows/pr-branch.md +41 -13
- package/sdd/workflows/profile-user.md +20 -18
- package/sdd/workflows/progress.md +186 -44
- package/sdd/workflows/quick.md +470 -58
- package/sdd/workflows/reapply-patches.md +390 -0
- package/sdd/workflows/remove-phase.md +12 -12
- package/sdd/workflows/remove-workspace.md +24 -7
- package/sdd/workflows/resume-project.md +18 -15
- package/sdd/workflows/review.md +242 -11
- package/sdd/workflows/scan.md +104 -0
- package/sdd/workflows/secure-phase.md +179 -0
- package/sdd/workflows/session-report.md +2 -2
- package/sdd/workflows/settings-advanced.md +579 -0
- package/sdd/workflows/settings-integrations.md +281 -0
- package/sdd/workflows/settings.md +221 -16
- package/sdd/workflows/ship.md +140 -13
- package/sdd/workflows/sketch-wrap-up.md +285 -0
- package/sdd/workflows/sketch.md +360 -0
- package/sdd/workflows/spec-phase.md +262 -0
- package/sdd/workflows/spike-wrap-up.md +306 -0
- package/sdd/workflows/spike.md +452 -0
- package/sdd/workflows/stats.md +20 -1
- package/sdd/workflows/sync-skills.md +182 -0
- package/sdd/workflows/thread.md +221 -0
- package/sdd/workflows/transition.md +44 -22
- package/sdd/workflows/ui-phase.md +39 -14
- package/sdd/workflows/ui-review.md +33 -6
- package/sdd/workflows/ultraplan-phase.md +198 -0
- package/sdd/workflows/undo.md +314 -0
- package/sdd/workflows/update.md +350 -29
- package/sdd/workflows/validate-phase.md +10 -6
- package/sdd/workflows/verify-phase.md +307 -18
- package/sdd/workflows/verify-work.md +153 -10
- package/sdk/dist/cli-transport.d.ts +19 -0
- package/sdk/dist/cli-transport.d.ts.map +1 -0
- package/sdk/dist/cli-transport.js +104 -0
- package/sdk/dist/cli-transport.js.map +1 -0
- package/sdk/dist/cli.d.ts +46 -0
- package/sdk/dist/cli.d.ts.map +1 -0
- package/sdk/dist/cli.js +511 -0
- package/sdk/dist/cli.js.map +1 -0
- package/sdk/dist/config.d.ts +84 -0
- package/sdk/dist/config.d.ts.map +1 -0
- package/sdk/dist/config.js +135 -0
- package/sdk/dist/config.js.map +1 -0
- package/sdk/dist/context-engine.d.ts +49 -0
- package/sdk/dist/context-engine.d.ts.map +1 -0
- package/sdk/dist/context-engine.js +142 -0
- package/sdk/dist/context-engine.js.map +1 -0
- package/sdk/dist/context-truncation.d.ts +33 -0
- package/sdk/dist/context-truncation.d.ts.map +1 -0
- package/sdk/dist/context-truncation.js +197 -0
- package/sdk/dist/context-truncation.js.map +1 -0
- package/sdk/dist/errors.d.ts +46 -0
- package/sdk/dist/errors.d.ts.map +1 -0
- package/sdk/dist/errors.js +64 -0
- package/sdk/dist/errors.js.map +1 -0
- package/sdk/dist/event-stream.d.ts +53 -0
- package/sdk/dist/event-stream.d.ts.map +1 -0
- package/sdk/dist/event-stream.js +321 -0
- package/sdk/dist/event-stream.js.map +1 -0
- package/sdk/dist/golden/capture.d.ts +15 -0
- package/sdk/dist/golden/capture.d.ts.map +1 -0
- package/sdk/dist/golden/capture.js +67 -0
- package/sdk/dist/golden/capture.js.map +1 -0
- package/sdk/dist/golden/golden-integration-covered.d.ts +6 -0
- package/sdk/dist/golden/golden-integration-covered.d.ts.map +1 -0
- package/sdk/dist/golden/golden-integration-covered.js +30 -0
- package/sdk/dist/golden/golden-integration-covered.js.map +1 -0
- package/sdk/dist/golden/golden-mutation-covered.d.ts +7 -0
- package/sdk/dist/golden/golden-mutation-covered.d.ts.map +1 -0
- package/sdk/dist/golden/golden-mutation-covered.js +17 -0
- package/sdk/dist/golden/golden-mutation-covered.js.map +1 -0
- package/sdk/dist/golden/golden-policy.d.ts +10 -0
- package/sdk/dist/golden/golden-policy.d.ts.map +1 -0
- package/sdk/dist/golden/golden-policy.js +98 -0
- package/sdk/dist/golden/golden-policy.js.map +1 -0
- package/sdk/dist/golden/init-golden-normalize.d.ts +8 -0
- package/sdk/dist/golden/init-golden-normalize.d.ts.map +1 -0
- package/sdk/dist/golden/init-golden-normalize.js +14 -0
- package/sdk/dist/golden/init-golden-normalize.js.map +1 -0
- package/sdk/dist/golden/read-only-golden-rows.d.ts +20 -0
- package/sdk/dist/golden/read-only-golden-rows.d.ts.map +1 -0
- package/sdk/dist/golden/read-only-golden-rows.js +67 -0
- package/sdk/dist/golden/read-only-golden-rows.js.map +1 -0
- package/sdk/dist/golden/registry-canonical-commands.d.ts +6 -0
- package/sdk/dist/golden/registry-canonical-commands.d.ts.map +1 -0
- package/sdk/dist/golden/registry-canonical-commands.js +30 -0
- package/sdk/dist/golden/registry-canonical-commands.js.map +1 -0
- package/sdk/dist/index.d.ts +125 -0
- package/sdk/dist/index.d.ts.map +1 -0
- package/sdk/dist/index.js +298 -0
- package/sdk/dist/index.js.map +1 -0
- package/sdk/dist/init-runner.d.ts +90 -0
- package/sdk/dist/init-runner.d.ts.map +1 -0
- package/sdk/dist/init-runner.js +613 -0
- package/sdk/dist/init-runner.js.map +1 -0
- package/sdk/dist/logger.d.ts +50 -0
- package/sdk/dist/logger.d.ts.map +1 -0
- package/sdk/dist/logger.js +70 -0
- package/sdk/dist/logger.js.map +1 -0
- package/sdk/dist/model-catalog.d.ts +31 -0
- package/sdk/dist/model-catalog.d.ts.map +1 -0
- package/sdk/dist/model-catalog.js +31 -0
- package/sdk/dist/model-catalog.js.map +1 -0
- package/sdk/dist/phase-prompt.d.ts +72 -0
- package/sdk/dist/phase-prompt.d.ts.map +1 -0
- package/sdk/dist/phase-prompt.js +213 -0
- package/sdk/dist/phase-prompt.js.map +1 -0
- package/sdk/dist/phase-runner.d.ts +145 -0
- package/sdk/dist/phase-runner.d.ts.map +1 -0
- package/sdk/dist/phase-runner.js +1206 -0
- package/sdk/dist/phase-runner.js.map +1 -0
- package/sdk/dist/plan-parser.d.ts +55 -0
- package/sdk/dist/plan-parser.d.ts.map +1 -0
- package/sdk/dist/plan-parser.js +389 -0
- package/sdk/dist/plan-parser.js.map +1 -0
- package/sdk/dist/planning-journal.d.ts +64 -0
- package/sdk/dist/planning-journal.d.ts.map +1 -0
- package/sdk/dist/planning-journal.js +88 -0
- package/sdk/dist/planning-journal.js.map +1 -0
- package/sdk/dist/planning-runtime.d.ts +67 -0
- package/sdk/dist/planning-runtime.d.ts.map +1 -0
- package/sdk/dist/planning-runtime.js +58 -0
- package/sdk/dist/planning-runtime.js.map +1 -0
- package/sdk/dist/prompt-builder.d.ts +44 -0
- package/sdk/dist/prompt-builder.d.ts.map +1 -0
- package/sdk/dist/prompt-builder.js +180 -0
- package/sdk/dist/prompt-builder.js.map +1 -0
- package/sdk/dist/prompt-sanitizer.d.ts +35 -0
- package/sdk/dist/prompt-sanitizer.d.ts.map +1 -0
- package/sdk/dist/prompt-sanitizer.js +101 -0
- package/sdk/dist/prompt-sanitizer.js.map +1 -0
- package/sdk/dist/query/active-workstream-store.d.ts +7 -0
- package/sdk/dist/query/active-workstream-store.d.ts.map +1 -0
- package/sdk/dist/query/active-workstream-store.js +56 -0
- package/sdk/dist/query/active-workstream-store.js.map +1 -0
- package/sdk/dist/query/agent-failure-classifier.d.ts +38 -0
- package/sdk/dist/query/agent-failure-classifier.d.ts.map +1 -0
- package/sdk/dist/query/agent-failure-classifier.js +83 -0
- package/sdk/dist/query/agent-failure-classifier.js.map +1 -0
- package/sdk/dist/query/audit-open.d.ts +46 -0
- package/sdk/dist/query/audit-open.d.ts.map +1 -0
- package/sdk/dist/query/audit-open.js +662 -0
- package/sdk/dist/query/audit-open.js.map +1 -0
- package/sdk/dist/query/check-auto-mode.d.ts +13 -0
- package/sdk/dist/query/check-auto-mode.d.ts.map +1 -0
- package/sdk/dist/query/check-auto-mode.js +40 -0
- package/sdk/dist/query/check-auto-mode.js.map +1 -0
- package/sdk/dist/query/check-completion.d.ts +10 -0
- package/sdk/dist/query/check-completion.d.ts.map +1 -0
- package/sdk/dist/query/check-completion.js +157 -0
- package/sdk/dist/query/check-completion.js.map +1 -0
- package/sdk/dist/query/check-decision-coverage.d.ts +33 -0
- package/sdk/dist/query/check-decision-coverage.d.ts.map +1 -0
- package/sdk/dist/query/check-decision-coverage.js +472 -0
- package/sdk/dist/query/check-decision-coverage.js.map +1 -0
- package/sdk/dist/query/check-gates.d.ts +10 -0
- package/sdk/dist/query/check-gates.d.ts.map +1 -0
- package/sdk/dist/query/check-gates.js +89 -0
- package/sdk/dist/query/check-gates.js.map +1 -0
- package/sdk/dist/query/check-ship-ready.d.ts +10 -0
- package/sdk/dist/query/check-ship-ready.d.ts.map +1 -0
- package/sdk/dist/query/check-ship-ready.js +93 -0
- package/sdk/dist/query/check-ship-ready.js.map +1 -0
- package/sdk/dist/query/check-verification-status.d.ts +10 -0
- package/sdk/dist/query/check-verification-status.d.ts.map +1 -0
- package/sdk/dist/query/check-verification-status.js +142 -0
- package/sdk/dist/query/check-verification-status.js.map +1 -0
- package/sdk/dist/query/command-aliases.generated.d.ts +31 -0
- package/sdk/dist/query/command-aliases.generated.d.ts.map +1 -0
- package/sdk/dist/query/command-aliases.generated.js +135 -0
- package/sdk/dist/query/command-aliases.generated.js.map +1 -0
- package/sdk/dist/query/command-catalog.d.ts +9 -0
- package/sdk/dist/query/command-catalog.d.ts.map +1 -0
- package/sdk/dist/query/command-catalog.js +17 -0
- package/sdk/dist/query/command-catalog.js.map +1 -0
- package/sdk/dist/query/command-definition.d.ts +19 -0
- package/sdk/dist/query/command-definition.d.ts.map +1 -0
- package/sdk/dist/query/command-definition.js +44 -0
- package/sdk/dist/query/command-definition.js.map +1 -0
- package/sdk/dist/query/command-family-handlers.d.ts +3 -0
- package/sdk/dist/query/command-family-handlers.d.ts.map +1 -0
- package/sdk/dist/query/command-family-handlers.js +94 -0
- package/sdk/dist/query/command-family-handlers.js.map +1 -0
- package/sdk/dist/query/command-manifest.d.ts +2 -0
- package/sdk/dist/query/command-manifest.d.ts.map +1 -0
- package/sdk/dist/query/command-manifest.init.d.ts +6 -0
- package/sdk/dist/query/command-manifest.init.d.ts.map +1 -0
- package/sdk/dist/query/command-manifest.init.js +23 -0
- package/sdk/dist/query/command-manifest.init.js.map +1 -0
- package/sdk/dist/query/command-manifest.js +17 -0
- package/sdk/dist/query/command-manifest.js.map +1 -0
- package/sdk/dist/query/command-manifest.non-family.d.ts +9 -0
- package/sdk/dist/query/command-manifest.non-family.d.ts.map +1 -0
- package/sdk/dist/query/command-manifest.non-family.js +59 -0
- package/sdk/dist/query/command-manifest.non-family.js.map +1 -0
- package/sdk/dist/query/command-manifest.phase.d.ts +6 -0
- package/sdk/dist/query/command-manifest.phase.d.ts.map +1 -0
- package/sdk/dist/query/command-manifest.phase.js +15 -0
- package/sdk/dist/query/command-manifest.phase.js.map +1 -0
- package/sdk/dist/query/command-manifest.phases.d.ts +7 -0
- package/sdk/dist/query/command-manifest.phases.d.ts.map +1 -0
- package/sdk/dist/query/command-manifest.phases.js +10 -0
- package/sdk/dist/query/command-manifest.phases.js.map +1 -0
- package/sdk/dist/query/command-manifest.roadmap.d.ts +6 -0
- package/sdk/dist/query/command-manifest.roadmap.d.ts.map +1 -0
- package/sdk/dist/query/command-manifest.roadmap.js +10 -0
- package/sdk/dist/query/command-manifest.roadmap.js.map +1 -0
- package/sdk/dist/query/command-manifest.state.d.ts +9 -0
- package/sdk/dist/query/command-manifest.state.d.ts.map +1 -0
- package/sdk/dist/query/command-manifest.state.js +30 -0
- package/sdk/dist/query/command-manifest.state.js.map +1 -0
- package/sdk/dist/query/command-manifest.types.d.ts +12 -0
- package/sdk/dist/query/command-manifest.types.d.ts.map +1 -0
- package/sdk/dist/query/command-manifest.types.js +2 -0
- package/sdk/dist/query/command-manifest.types.js.map +1 -0
- package/sdk/dist/query/command-manifest.validate.d.ts +6 -0
- package/sdk/dist/query/command-manifest.validate.d.ts.map +1 -0
- package/sdk/dist/query/command-manifest.validate.js +10 -0
- package/sdk/dist/query/command-manifest.validate.js.map +1 -0
- package/sdk/dist/query/command-manifest.verify.d.ts +6 -0
- package/sdk/dist/query/command-manifest.verify.d.ts.map +1 -0
- package/sdk/dist/query/command-manifest.verify.js +14 -0
- package/sdk/dist/query/command-manifest.verify.js.map +1 -0
- package/sdk/dist/query/command-static-catalog-domain.d.ts +3 -0
- package/sdk/dist/query/command-static-catalog-domain.d.ts.map +1 -0
- package/sdk/dist/query/command-static-catalog-domain.js +116 -0
- package/sdk/dist/query/command-static-catalog-domain.js.map +1 -0
- package/sdk/dist/query/command-static-catalog-foundation.d.ts +7 -0
- package/sdk/dist/query/command-static-catalog-foundation.d.ts.map +1 -0
- package/sdk/dist/query/command-static-catalog-foundation.js +98 -0
- package/sdk/dist/query/command-static-catalog-foundation.js.map +1 -0
- package/sdk/dist/query/command-topology.d.ts +32 -0
- package/sdk/dist/query/command-topology.d.ts.map +1 -0
- package/sdk/dist/query/command-topology.js +66 -0
- package/sdk/dist/query/command-topology.js.map +1 -0
- package/sdk/dist/query/commands-list.d.ts +14 -0
- package/sdk/dist/query/commands-list.d.ts.map +1 -0
- package/sdk/dist/query/commands-list.js +18 -0
- package/sdk/dist/query/commands-list.js.map +1 -0
- package/sdk/dist/query/commit.d.ts +79 -0
- package/sdk/dist/query/commit.d.ts.map +1 -0
- package/sdk/dist/query/commit.js +340 -0
- package/sdk/dist/query/commit.js.map +1 -0
- package/sdk/dist/query/config-gates.d.ts +12 -0
- package/sdk/dist/query/config-gates.d.ts.map +1 -0
- package/sdk/dist/query/config-gates.js +66 -0
- package/sdk/dist/query/config-gates.js.map +1 -0
- package/sdk/dist/query/config-mutation.d.ts +86 -0
- package/sdk/dist/query/config-mutation.d.ts.map +1 -0
- package/sdk/dist/query/config-mutation.js +518 -0
- package/sdk/dist/query/config-mutation.js.map +1 -0
- package/sdk/dist/query/config-query.d.ts +57 -0
- package/sdk/dist/query/config-query.d.ts.map +1 -0
- package/sdk/dist/query/config-query.js +208 -0
- package/sdk/dist/query/config-query.js.map +1 -0
- package/sdk/dist/query/config-schema.d.ts +36 -0
- package/sdk/dist/query/config-schema.d.ts.map +1 -0
- package/sdk/dist/query/config-schema.js +147 -0
- package/sdk/dist/query/config-schema.js.map +1 -0
- package/sdk/dist/query/decisions.d.ts +58 -0
- package/sdk/dist/query/decisions.d.ts.map +1 -0
- package/sdk/dist/query/decisions.js +161 -0
- package/sdk/dist/query/decisions.js.map +1 -0
- package/sdk/dist/query/detect-custom-files.d.ts +11 -0
- package/sdk/dist/query/detect-custom-files.d.ts.map +1 -0
- package/sdk/dist/query/detect-custom-files.js +89 -0
- package/sdk/dist/query/detect-custom-files.js.map +1 -0
- package/sdk/dist/query/detect-phase-type.d.ts +9 -0
- package/sdk/dist/query/detect-phase-type.d.ts.map +1 -0
- package/sdk/dist/query/detect-phase-type.js +124 -0
- package/sdk/dist/query/detect-phase-type.js.map +1 -0
- package/sdk/dist/query/docs-init.d.ts +26 -0
- package/sdk/dist/query/docs-init.d.ts.map +1 -0
- package/sdk/dist/query/docs-init.js +231 -0
- package/sdk/dist/query/docs-init.js.map +1 -0
- package/sdk/dist/query/fallow-audit.d.ts +44 -0
- package/sdk/dist/query/fallow-audit.d.ts.map +1 -0
- package/sdk/dist/query/fallow-audit.js +44 -0
- package/sdk/dist/query/fallow-audit.js.map +1 -0
- package/sdk/dist/query/frontmatter-mutation.d.ts +77 -0
- package/sdk/dist/query/frontmatter-mutation.d.ts.map +1 -0
- package/sdk/dist/query/frontmatter-mutation.js +317 -0
- package/sdk/dist/query/frontmatter-mutation.js.map +1 -0
- package/sdk/dist/query/frontmatter.d.ts +93 -0
- package/sdk/dist/query/frontmatter.d.ts.map +1 -0
- package/sdk/dist/query/frontmatter.js +365 -0
- package/sdk/dist/query/frontmatter.js.map +1 -0
- package/sdk/dist/query/helpers.d.ts +191 -0
- package/sdk/dist/query/helpers.d.ts.map +1 -0
- package/sdk/dist/query/helpers.js +613 -0
- package/sdk/dist/query/helpers.js.map +1 -0
- package/sdk/dist/query/index.d.ts +8 -0
- package/sdk/dist/query/index.d.ts.map +1 -0
- package/sdk/dist/query/index.js +6 -0
- package/sdk/dist/query/index.js.map +1 -0
- package/sdk/dist/query/init-complex.d.ts +47 -0
- package/sdk/dist/query/init-complex.d.ts.map +1 -0
- package/sdk/dist/query/init-complex.js +718 -0
- package/sdk/dist/query/init-complex.js.map +1 -0
- package/sdk/dist/query/init.d.ts +106 -0
- package/sdk/dist/query/init.d.ts.map +1 -0
- package/sdk/dist/query/init.js +1159 -0
- package/sdk/dist/query/init.js.map +1 -0
- package/sdk/dist/query/intel.d.ts +43 -0
- package/sdk/dist/query/intel.d.ts.map +1 -0
- package/sdk/dist/query/intel.js +416 -0
- package/sdk/dist/query/intel.js.map +1 -0
- package/sdk/dist/query/mutation-event-decorator.d.ts +5 -0
- package/sdk/dist/query/mutation-event-decorator.d.ts.map +1 -0
- package/sdk/dist/query/mutation-event-decorator.js +28 -0
- package/sdk/dist/query/mutation-event-decorator.js.map +1 -0
- package/sdk/dist/query/mutation-event-mapper.d.ts +4 -0
- package/sdk/dist/query/mutation-event-mapper.d.ts.map +1 -0
- package/sdk/dist/query/mutation-event-mapper.js +70 -0
- package/sdk/dist/query/mutation-event-mapper.js.map +1 -0
- package/sdk/dist/query/mvp.d.ts +113 -0
- package/sdk/dist/query/mvp.d.ts.map +1 -0
- package/sdk/dist/query/mvp.js +225 -0
- package/sdk/dist/query/mvp.js.map +1 -0
- package/sdk/dist/query/phase-filesystem-adapter.d.ts +4 -0
- package/sdk/dist/query/phase-filesystem-adapter.d.ts.map +1 -0
- package/sdk/dist/query/phase-filesystem-adapter.js +33 -0
- package/sdk/dist/query/phase-filesystem-adapter.js.map +1 -0
- package/sdk/dist/query/phase-lifecycle-policy.d.ts +34 -0
- package/sdk/dist/query/phase-lifecycle-policy.d.ts.map +1 -0
- package/sdk/dist/query/phase-lifecycle-policy.js +138 -0
- package/sdk/dist/query/phase-lifecycle-policy.js.map +1 -0
- package/sdk/dist/query/phase-lifecycle.d.ts +116 -0
- package/sdk/dist/query/phase-lifecycle.d.ts.map +1 -0
- package/sdk/dist/query/phase-lifecycle.js +1486 -0
- package/sdk/dist/query/phase-lifecycle.js.map +1 -0
- package/sdk/dist/query/phase-list-queries.d.ts +18 -0
- package/sdk/dist/query/phase-list-queries.d.ts.map +1 -0
- package/sdk/dist/query/phase-list-queries.js +129 -0
- package/sdk/dist/query/phase-list-queries.js.map +1 -0
- package/sdk/dist/query/phase-ready.d.ts +9 -0
- package/sdk/dist/query/phase-ready.d.ts.map +1 -0
- package/sdk/dist/query/phase-ready.js +132 -0
- package/sdk/dist/query/phase-ready.js.map +1 -0
- package/sdk/dist/query/phase-roadmap-mutation.d.ts +13 -0
- package/sdk/dist/query/phase-roadmap-mutation.d.ts.map +1 -0
- package/sdk/dist/query/phase-roadmap-mutation.js +65 -0
- package/sdk/dist/query/phase-roadmap-mutation.js.map +1 -0
- package/sdk/dist/query/phase.d.ts +48 -0
- package/sdk/dist/query/phase.d.ts.map +1 -0
- package/sdk/dist/query/phase.js +451 -0
- package/sdk/dist/query/phase.js.map +1 -0
- package/sdk/dist/query/pipeline.d.ts +53 -0
- package/sdk/dist/query/pipeline.d.ts.map +1 -0
- package/sdk/dist/query/pipeline.js +198 -0
- package/sdk/dist/query/pipeline.js.map +1 -0
- package/sdk/dist/query/plan-scan.d.ts +14 -0
- package/sdk/dist/query/plan-scan.d.ts.map +1 -0
- package/sdk/dist/query/plan-scan.js +70 -0
- package/sdk/dist/query/plan-scan.js.map +1 -0
- package/sdk/dist/query/plan-task-structure.d.ts +9 -0
- package/sdk/dist/query/plan-task-structure.d.ts.map +1 -0
- package/sdk/dist/query/plan-task-structure.js +59 -0
- package/sdk/dist/query/plan-task-structure.js.map +1 -0
- package/sdk/dist/query/profile-extract-messages.d.ts +40 -0
- package/sdk/dist/query/profile-extract-messages.d.ts.map +1 -0
- package/sdk/dist/query/profile-extract-messages.js +195 -0
- package/sdk/dist/query/profile-extract-messages.js.map +1 -0
- package/sdk/dist/query/profile-output.d.ts +11 -0
- package/sdk/dist/query/profile-output.d.ts.map +1 -0
- package/sdk/dist/query/profile-output.js +873 -0
- package/sdk/dist/query/profile-output.js.map +1 -0
- package/sdk/dist/query/profile-questionnaire-data.d.ts +21 -0
- package/sdk/dist/query/profile-questionnaire-data.d.ts.map +1 -0
- package/sdk/dist/query/profile-questionnaire-data.js +171 -0
- package/sdk/dist/query/profile-questionnaire-data.js.map +1 -0
- package/sdk/dist/query/profile-sample.d.ts +22 -0
- package/sdk/dist/query/profile-sample.d.ts.map +1 -0
- package/sdk/dist/query/profile-sample.js +136 -0
- package/sdk/dist/query/profile-sample.js.map +1 -0
- package/sdk/dist/query/profile-scan-sessions.d.ts +49 -0
- package/sdk/dist/query/profile-scan-sessions.d.ts.map +1 -0
- package/sdk/dist/query/profile-scan-sessions.js +137 -0
- package/sdk/dist/query/profile-scan-sessions.js.map +1 -0
- package/sdk/dist/query/profile.d.ts +61 -0
- package/sdk/dist/query/profile.d.ts.map +1 -0
- package/sdk/dist/query/profile.js +307 -0
- package/sdk/dist/query/profile.js.map +1 -0
- package/sdk/dist/query/progress.d.ts +77 -0
- package/sdk/dist/query/progress.d.ts.map +1 -0
- package/sdk/dist/query/progress.js +481 -0
- package/sdk/dist/query/progress.js.map +1 -0
- package/sdk/dist/query/query-cli-adapter.d.ts +8 -0
- package/sdk/dist/query/query-cli-adapter.d.ts.map +1 -0
- package/sdk/dist/query/query-cli-adapter.js +32 -0
- package/sdk/dist/query/query-cli-adapter.js.map +1 -0
- package/sdk/dist/query/query-cli-output.d.ts +9 -0
- package/sdk/dist/query/query-cli-output.d.ts.map +1 -0
- package/sdk/dist/query/query-cli-output.js +28 -0
- package/sdk/dist/query/query-cli-output.js.map +1 -0
- package/sdk/dist/query/query-command-diagnosis.d.ts +6 -0
- package/sdk/dist/query/query-command-diagnosis.d.ts.map +1 -0
- package/sdk/dist/query/query-command-diagnosis.js +6 -0
- package/sdk/dist/query/query-command-diagnosis.js.map +1 -0
- package/sdk/dist/query/query-command-resolution-strategy.d.ts +29 -0
- package/sdk/dist/query/query-command-resolution-strategy.d.ts.map +1 -0
- package/sdk/dist/query/query-command-resolution-strategy.js +103 -0
- package/sdk/dist/query/query-command-resolution-strategy.js.map +1 -0
- package/sdk/dist/query/query-command-semantics.d.ts +7 -0
- package/sdk/dist/query/query-command-semantics.d.ts.map +1 -0
- package/sdk/dist/query/query-command-semantics.js +7 -0
- package/sdk/dist/query/query-command-semantics.js.map +1 -0
- package/sdk/dist/query/query-dispatch-contract.d.ts +21 -0
- package/sdk/dist/query/query-dispatch-contract.d.ts.map +1 -0
- package/sdk/dist/query/query-dispatch-contract.js +2 -0
- package/sdk/dist/query/query-dispatch-contract.js.map +1 -0
- package/sdk/dist/query/query-dispatch-error-mapper.d.ts +6 -0
- package/sdk/dist/query/query-dispatch-error-mapper.d.ts.map +1 -0
- package/sdk/dist/query/query-dispatch-error-mapper.js +6 -0
- package/sdk/dist/query/query-dispatch-error-mapper.js.map +1 -0
- package/sdk/dist/query/query-dispatch-formatting.d.ts +6 -0
- package/sdk/dist/query/query-dispatch-formatting.d.ts.map +1 -0
- package/sdk/dist/query/query-dispatch-formatting.js +6 -0
- package/sdk/dist/query/query-dispatch-formatting.js.map +1 -0
- package/sdk/dist/query/query-dispatch-input-validation.d.ts +6 -0
- package/sdk/dist/query/query-dispatch-input-validation.d.ts.map +1 -0
- package/sdk/dist/query/query-dispatch-input-validation.js +6 -0
- package/sdk/dist/query/query-dispatch-input-validation.js.map +1 -0
- package/sdk/dist/query/query-dispatch-observability.d.ts +2 -0
- package/sdk/dist/query/query-dispatch-observability.d.ts.map +1 -0
- package/sdk/dist/query/query-dispatch-observability.js +7 -0
- package/sdk/dist/query/query-dispatch-observability.js.map +1 -0
- package/sdk/dist/query/query-dispatch-plan.d.ts +6 -0
- package/sdk/dist/query/query-dispatch-plan.d.ts.map +1 -0
- package/sdk/dist/query/query-dispatch-plan.js +6 -0
- package/sdk/dist/query/query-dispatch-plan.js.map +1 -0
- package/sdk/dist/query/query-dispatch-result-builder.d.ts +6 -0
- package/sdk/dist/query/query-dispatch-result-builder.d.ts.map +1 -0
- package/sdk/dist/query/query-dispatch-result-builder.js +6 -0
- package/sdk/dist/query/query-dispatch-result-builder.js.map +1 -0
- package/sdk/dist/query/query-dispatch.d.ts +48 -0
- package/sdk/dist/query/query-dispatch.d.ts.map +1 -0
- package/sdk/dist/query/query-dispatch.js +175 -0
- package/sdk/dist/query/query-dispatch.js.map +1 -0
- package/sdk/dist/query/query-error-details-schema.d.ts +19 -0
- package/sdk/dist/query/query-error-details-schema.d.ts.map +1 -0
- package/sdk/dist/query/query-error-details-schema.js +10 -0
- package/sdk/dist/query/query-error-details-schema.js.map +1 -0
- package/sdk/dist/query/query-error-taxonomy.d.ts +38 -0
- package/sdk/dist/query/query-error-taxonomy.d.ts.map +1 -0
- package/sdk/dist/query/query-error-taxonomy.js +74 -0
- package/sdk/dist/query/query-error-taxonomy.js.map +1 -0
- package/sdk/dist/query/query-fallback-bridge-adapter.d.ts +14 -0
- package/sdk/dist/query/query-fallback-bridge-adapter.d.ts.map +1 -0
- package/sdk/dist/query/query-fallback-bridge-adapter.js +33 -0
- package/sdk/dist/query/query-fallback-bridge-adapter.js.map +1 -0
- package/sdk/dist/query/query-fallback-executor.d.ts +11 -0
- package/sdk/dist/query/query-fallback-executor.d.ts.map +1 -0
- package/sdk/dist/query/query-fallback-executor.js +31 -0
- package/sdk/dist/query/query-fallback-executor.js.map +1 -0
- package/sdk/dist/query/query-fallback-output-classifier.d.ts +6 -0
- package/sdk/dist/query/query-fallback-output-classifier.d.ts.map +1 -0
- package/sdk/dist/query/query-fallback-output-classifier.js +27 -0
- package/sdk/dist/query/query-fallback-output-classifier.js.map +1 -0
- package/sdk/dist/query/query-fallback-policy.d.ts +6 -0
- package/sdk/dist/query/query-fallback-policy.d.ts.map +1 -0
- package/sdk/dist/query/query-fallback-policy.js +7 -0
- package/sdk/dist/query/query-fallback-policy.js.map +1 -0
- package/sdk/dist/query/query-native-dispatch-adapter.d.ts +7 -0
- package/sdk/dist/query/query-native-dispatch-adapter.d.ts.map +1 -0
- package/sdk/dist/query/query-native-dispatch-adapter.js +6 -0
- package/sdk/dist/query/query-native-dispatch-adapter.js.map +1 -0
- package/sdk/dist/query/query-policy-capability.d.ts +10 -0
- package/sdk/dist/query/query-policy-capability.d.ts.map +1 -0
- package/sdk/dist/query/query-policy-capability.js +17 -0
- package/sdk/dist/query/query-policy-capability.js.map +1 -0
- package/sdk/dist/query/query-runtime-context.d.ts +19 -0
- package/sdk/dist/query/query-runtime-context.d.ts.map +1 -0
- package/sdk/dist/query/query-runtime-context.js +31 -0
- package/sdk/dist/query/query-runtime-context.js.map +1 -0
- package/sdk/dist/query/query-unknown-command-hints.d.ts +2 -0
- package/sdk/dist/query/query-unknown-command-hints.d.ts.map +1 -0
- package/sdk/dist/query/query-unknown-command-hints.js +6 -0
- package/sdk/dist/query/query-unknown-command-hints.js.map +1 -0
- package/sdk/dist/query/registry-assembly-descriptor.d.ts +12 -0
- package/sdk/dist/query/registry-assembly-descriptor.d.ts.map +1 -0
- package/sdk/dist/query/registry-assembly-descriptor.js +61 -0
- package/sdk/dist/query/registry-assembly-descriptor.js.map +1 -0
- package/sdk/dist/query/registry-assembly-invariants.d.ts +30 -0
- package/sdk/dist/query/registry-assembly-invariants.d.ts.map +1 -0
- package/sdk/dist/query/registry-assembly-invariants.js +77 -0
- package/sdk/dist/query/registry-assembly-invariants.js.map +1 -0
- package/sdk/dist/query/registry-assembly.d.ts +10 -0
- package/sdk/dist/query/registry-assembly.d.ts.map +1 -0
- package/sdk/dist/query/registry-assembly.js +53 -0
- package/sdk/dist/query/registry-assembly.js.map +1 -0
- package/sdk/dist/query/registry.d.ts +90 -0
- package/sdk/dist/query/registry.d.ts.map +1 -0
- package/sdk/dist/query/registry.js +129 -0
- package/sdk/dist/query/registry.js.map +1 -0
- package/sdk/dist/query/requirements-extract-from-plans.d.ts +9 -0
- package/sdk/dist/query/requirements-extract-from-plans.d.ts.map +1 -0
- package/sdk/dist/query/requirements-extract-from-plans.js +76 -0
- package/sdk/dist/query/requirements-extract-from-plans.js.map +1 -0
- package/sdk/dist/query/roadmap-update-plan-progress.d.ts +11 -0
- package/sdk/dist/query/roadmap-update-plan-progress.d.ts.map +1 -0
- package/sdk/dist/query/roadmap-update-plan-progress.js +124 -0
- package/sdk/dist/query/roadmap-update-plan-progress.js.map +1 -0
- package/sdk/dist/query/roadmap.d.ts +137 -0
- package/sdk/dist/query/roadmap.d.ts.map +1 -0
- package/sdk/dist/query/roadmap.js +753 -0
- package/sdk/dist/query/roadmap.js.map +1 -0
- package/sdk/dist/query/route-next-action.d.ts +9 -0
- package/sdk/dist/query/route-next-action.d.ts.map +1 -0
- package/sdk/dist/query/route-next-action.js +318 -0
- package/sdk/dist/query/route-next-action.js.map +1 -0
- package/sdk/dist/query/schema-detect.d.ts +21 -0
- package/sdk/dist/query/schema-detect.d.ts.map +1 -0
- package/sdk/dist/query/schema-detect.js +146 -0
- package/sdk/dist/query/schema-detect.js.map +1 -0
- package/sdk/dist/query/secrets.d.ts +27 -0
- package/sdk/dist/query/secrets.d.ts.map +1 -0
- package/sdk/dist/query/secrets.js +42 -0
- package/sdk/dist/query/secrets.js.map +1 -0
- package/sdk/dist/query/skill-manifest.d.ts +50 -0
- package/sdk/dist/query/skill-manifest.d.ts.map +1 -0
- package/sdk/dist/query/skill-manifest.js +171 -0
- package/sdk/dist/query/skill-manifest.js.map +1 -0
- package/sdk/dist/query/skills.d.ts +27 -0
- package/sdk/dist/query/skills.d.ts.map +1 -0
- package/sdk/dist/query/skills.js +137 -0
- package/sdk/dist/query/skills.js.map +1 -0
- package/sdk/dist/query/state-document.d.ts +14 -0
- package/sdk/dist/query/state-document.d.ts.map +1 -0
- package/sdk/dist/query/state-document.js +110 -0
- package/sdk/dist/query/state-document.js.map +1 -0
- package/sdk/dist/query/state-mutation.d.ts +224 -0
- package/sdk/dist/query/state-mutation.d.ts.map +1 -0
- package/sdk/dist/query/state-mutation.js +1539 -0
- package/sdk/dist/query/state-mutation.js.map +1 -0
- package/sdk/dist/query/state-project-load.d.ts +23 -0
- package/sdk/dist/query/state-project-load.d.ts.map +1 -0
- package/sdk/dist/query/state-project-load.js +75 -0
- package/sdk/dist/query/state-project-load.js.map +1 -0
- package/sdk/dist/query/state.d.ts +78 -0
- package/sdk/dist/query/state.d.ts.map +1 -0
- package/sdk/dist/query/state.js +430 -0
- package/sdk/dist/query/state.js.map +1 -0
- package/sdk/dist/query/summary.d.ts +18 -0
- package/sdk/dist/query/summary.d.ts.map +1 -0
- package/sdk/dist/query/summary.js +249 -0
- package/sdk/dist/query/summary.js.map +1 -0
- package/sdk/dist/query/template.d.ts +46 -0
- package/sdk/dist/query/template.d.ts.map +1 -0
- package/sdk/dist/query/template.js +210 -0
- package/sdk/dist/query/template.js.map +1 -0
- package/sdk/dist/query/uat.d.ts +34 -0
- package/sdk/dist/query/uat.d.ts.map +1 -0
- package/sdk/dist/query/uat.js +339 -0
- package/sdk/dist/query/uat.js.map +1 -0
- package/sdk/dist/query/utils.d.ts +59 -0
- package/sdk/dist/query/utils.d.ts.map +1 -0
- package/sdk/dist/query/utils.js +74 -0
- package/sdk/dist/query/utils.js.map +1 -0
- package/sdk/dist/query/validate.d.ts +67 -0
- package/sdk/dist/query/validate.d.ts.map +1 -0
- package/sdk/dist/query/validate.js +908 -0
- package/sdk/dist/query/validate.js.map +1 -0
- package/sdk/dist/query/verify.d.ts +110 -0
- package/sdk/dist/query/verify.d.ts.map +1 -0
- package/sdk/dist/query/verify.js +631 -0
- package/sdk/dist/query/verify.js.map +1 -0
- package/sdk/dist/query/websearch.d.ts +24 -0
- package/sdk/dist/query/websearch.d.ts.map +1 -0
- package/sdk/dist/query/websearch.js +68 -0
- package/sdk/dist/query/websearch.js.map +1 -0
- package/sdk/dist/query/workspace.d.ts +62 -0
- package/sdk/dist/query/workspace.d.ts.map +1 -0
- package/sdk/dist/query/workspace.js +104 -0
- package/sdk/dist/query/workspace.js.map +1 -0
- package/sdk/dist/query/workstream-inventory.d.ts +52 -0
- package/sdk/dist/query/workstream-inventory.d.ts.map +1 -0
- package/sdk/dist/query/workstream-inventory.js +141 -0
- package/sdk/dist/query/workstream-inventory.js.map +1 -0
- package/sdk/dist/query/workstream.d.ts +35 -0
- package/sdk/dist/query/workstream.d.ts.map +1 -0
- package/sdk/dist/query/workstream.js +298 -0
- package/sdk/dist/query/workstream.js.map +1 -0
- package/sdk/dist/query/worktree.d.ts +3 -0
- package/sdk/dist/query/worktree.d.ts.map +1 -0
- package/sdk/dist/query/worktree.js +36 -0
- package/sdk/dist/query/worktree.js.map +1 -0
- package/sdk/dist/query-command-executor.d.ts +22 -0
- package/sdk/dist/query-command-executor.d.ts.map +1 -0
- package/sdk/dist/query-command-executor.js +22 -0
- package/sdk/dist/query-command-executor.js.map +1 -0
- package/sdk/dist/query-execution-policy.d.ts +24 -0
- package/sdk/dist/query-execution-policy.d.ts.map +1 -0
- package/sdk/dist/query-execution-policy.js +27 -0
- package/sdk/dist/query-execution-policy.js.map +1 -0
- package/sdk/dist/query-failure-classification.d.ts +9 -0
- package/sdk/dist/query-failure-classification.d.ts.map +1 -0
- package/sdk/dist/query-failure-classification.js +32 -0
- package/sdk/dist/query-failure-classification.js.map +1 -0
- package/sdk/dist/query-hotpath-methods.d.ts +19 -0
- package/sdk/dist/query-hotpath-methods.d.ts.map +1 -0
- package/sdk/dist/query-hotpath-methods.js +34 -0
- package/sdk/dist/query-hotpath-methods.js.map +1 -0
- package/sdk/dist/query-native-direct-adapter.d.ts +20 -0
- package/sdk/dist/query-native-direct-adapter.d.ts.map +1 -0
- package/sdk/dist/query-native-direct-adapter.js +52 -0
- package/sdk/dist/query-native-direct-adapter.js.map +1 -0
- package/sdk/dist/query-native-hotpath-adapter.d.ts +15 -0
- package/sdk/dist/query-native-hotpath-adapter.d.ts.map +1 -0
- package/sdk/dist/query-native-hotpath-adapter.js +32 -0
- package/sdk/dist/query-native-hotpath-adapter.js.map +1 -0
- package/sdk/dist/query-raw-output-projection.d.ts +6 -0
- package/sdk/dist/query-raw-output-projection.d.ts.map +1 -0
- package/sdk/dist/query-raw-output-projection.js +67 -0
- package/sdk/dist/query-raw-output-projection.js.map +1 -0
- package/sdk/dist/query-runtime-bridge.d.ts +61 -0
- package/sdk/dist/query-runtime-bridge.d.ts.map +1 -0
- package/sdk/dist/query-runtime-bridge.js +144 -0
- package/sdk/dist/query-runtime-bridge.js.map +1 -0
- package/sdk/dist/query-sdd-tools-path.d.ts +2 -0
- package/sdk/dist/query-sdd-tools-path.d.ts.map +1 -0
- package/sdk/dist/query-sdd-tools-path.js +2 -0
- package/sdk/dist/query-sdd-tools-path.js.map +1 -0
- package/sdk/dist/query-sdd-tools-runtime.d.ts +20 -0
- package/sdk/dist/query-sdd-tools-runtime.d.ts.map +1 -0
- package/sdk/dist/query-sdd-tools-runtime.js +47 -0
- package/sdk/dist/query-sdd-tools-runtime.js.map +1 -0
- package/sdk/dist/query-subprocess-adapter.d.ts +18 -0
- package/sdk/dist/query-subprocess-adapter.d.ts.map +1 -0
- package/sdk/dist/query-subprocess-adapter.js +92 -0
- package/sdk/dist/query-subprocess-adapter.js.map +1 -0
- package/sdk/dist/query-tools-error-factory.d.ts +16 -0
- package/sdk/dist/query-tools-error-factory.d.ts.map +1 -0
- package/sdk/dist/query-tools-error-factory.js +33 -0
- package/sdk/dist/query-tools-error-factory.js.map +1 -0
- package/sdk/dist/research-gate.d.ts +24 -0
- package/sdk/dist/research-gate.d.ts.map +1 -0
- package/sdk/dist/research-gate.js +70 -0
- package/sdk/dist/research-gate.js.map +1 -0
- package/sdk/dist/runtime-gate.d.ts +14 -0
- package/sdk/dist/runtime-gate.d.ts.map +1 -0
- package/sdk/dist/runtime-gate.js +48 -0
- package/sdk/dist/runtime-gate.js.map +1 -0
- package/sdk/dist/sdd-tools-error.d.ts +23 -0
- package/sdk/dist/sdd-tools-error.d.ts.map +1 -0
- package/sdk/dist/sdd-tools-error.js +29 -0
- package/sdk/dist/sdd-tools-error.js.map +1 -0
- package/sdk/dist/sdd-tools.d.ts +97 -0
- package/sdk/dist/sdd-tools.d.ts.map +1 -0
- package/sdk/dist/sdd-tools.js +168 -0
- package/sdk/dist/sdd-tools.js.map +1 -0
- package/sdk/dist/sdd-transport-policy.d.ts +10 -0
- package/sdk/dist/sdd-transport-policy.d.ts.map +1 -0
- package/sdk/dist/sdd-transport-policy.js +32 -0
- package/sdk/dist/sdd-transport-policy.js.map +1 -0
- package/sdk/dist/sdd-transport.d.ts +39 -0
- package/sdk/dist/sdd-transport.d.ts.map +1 -0
- package/sdk/dist/sdd-transport.js +78 -0
- package/sdk/dist/sdd-transport.js.map +1 -0
- package/sdk/dist/sdk-package-compatibility.d.ts +38 -0
- package/sdk/dist/sdk-package-compatibility.d.ts.map +1 -0
- package/sdk/dist/sdk-package-compatibility.js +90 -0
- package/sdk/dist/sdk-package-compatibility.js.map +1 -0
- package/sdk/dist/session-runner.d.ts +40 -0
- package/sdk/dist/session-runner.d.ts.map +1 -0
- package/sdk/dist/session-runner.js +274 -0
- package/sdk/dist/session-runner.js.map +1 -0
- package/sdk/dist/tool-scoping.d.ts +31 -0
- package/sdk/dist/tool-scoping.d.ts.map +1 -0
- package/sdk/dist/tool-scoping.js +54 -0
- package/sdk/dist/tool-scoping.js.map +1 -0
- package/sdk/dist/types.d.ts +794 -0
- package/sdk/dist/types.d.ts.map +1 -0
- package/sdk/dist/types.js +77 -0
- package/sdk/dist/types.js.map +1 -0
- package/sdk/dist/workstream-name-policy.d.ts +13 -0
- package/sdk/dist/workstream-name-policy.d.ts.map +1 -0
- package/sdk/dist/workstream-name-policy.js +24 -0
- package/sdk/dist/workstream-name-policy.js.map +1 -0
- package/sdk/dist/workstream-utils.d.ts +15 -0
- package/sdk/dist/workstream-utils.d.ts.map +1 -0
- package/sdk/dist/workstream-utils.js +21 -0
- package/sdk/dist/workstream-utils.js.map +1 -0
- package/sdk/dist/ws-transport.d.ts +32 -0
- package/sdk/dist/ws-transport.d.ts.map +1 -0
- package/sdk/dist/ws-transport.js +84 -0
- package/sdk/dist/ws-transport.js.map +1 -0
- package/sdk/package-lock.json +2502 -0
- package/sdk/package.json +57 -0
- package/sdk/prompts/templates/project.md +186 -0
- package/sdk/prompts/templates/requirements.md +231 -0
- package/sdk/prompts/templates/research-project/ARCHITECTURE.md +204 -0
- package/sdk/prompts/templates/research-project/FEATURES.md +147 -0
- package/sdk/prompts/templates/research-project/PITFALLS.md +200 -0
- package/sdk/prompts/templates/research-project/STACK.md +120 -0
- package/sdk/prompts/templates/research-project/SUMMARY.md +170 -0
- package/sdk/prompts/templates/roadmap.md +202 -0
- package/sdk/prompts/templates/state.md +175 -0
- package/sdk/shared/model-catalog.json +122 -0
- package/sdk/src/assembled-prompts.test.ts +349 -0
- package/sdk/src/bug-3591-sddtools-runtime-workstream.test.ts +179 -0
- package/sdk/src/cli-transport.test.ts +388 -0
- package/sdk/src/cli-transport.ts +130 -0
- package/sdk/src/cli.test.ts +426 -0
- package/sdk/src/cli.ts +589 -0
- package/sdk/src/config.test.ts +271 -0
- package/sdk/src/config.ts +218 -0
- package/sdk/src/context-engine.test.ts +295 -0
- package/sdk/src/context-engine.ts +170 -0
- package/sdk/src/context-truncation.test.ts +163 -0
- package/sdk/src/context-truncation.ts +233 -0
- package/sdk/src/e2e.integration.test.ts +181 -0
- package/sdk/src/errors.ts +72 -0
- package/sdk/src/event-stream.test.ts +661 -0
- package/sdk/src/event-stream.ts +441 -0
- package/sdk/src/golden/capture.ts +95 -0
- package/sdk/src/golden/fixtures/generate-slug.golden.json +1 -0
- package/sdk/src/golden/fixtures/profile-sample-sessions/demo-project/sample.jsonl +3 -0
- package/sdk/src/golden/fixtures/summary-extract-sample.md +26 -0
- package/sdk/src/golden/fixtures/uat-render-checkpoint-sample.md +15 -0
- package/sdk/src/golden/golden-integration-covered.ts +30 -0
- package/sdk/src/golden/golden-mutation-covered.ts +17 -0
- package/sdk/src/golden/golden-policy.test.ts +8 -0
- package/sdk/src/golden/golden-policy.ts +120 -0
- package/sdk/src/golden/golden.integration.test.ts +677 -0
- package/sdk/src/golden/init-golden-normalize.ts +15 -0
- package/sdk/src/golden/read-only-golden-rows.ts +77 -0
- package/sdk/src/golden/read-only-parity.integration.test.ts +133 -0
- package/sdk/src/golden/registry-canonical-commands.ts +31 -0
- package/sdk/src/index.ts +352 -0
- package/sdk/src/init-e2e.integration.test.ts +138 -0
- package/sdk/src/init-runner.test.ts +740 -0
- package/sdk/src/init-runner.ts +734 -0
- package/sdk/src/lifecycle-e2e.integration.test.ts +258 -0
- package/sdk/src/logger.test.ts +149 -0
- package/sdk/src/logger.ts +113 -0
- package/sdk/src/milestone-runner.test.ts +421 -0
- package/sdk/src/model-catalog.ts +70 -0
- package/sdk/src/phase-prompt.test.ts +535 -0
- package/sdk/src/phase-prompt.ts +259 -0
- package/sdk/src/phase-runner-types.test.ts +421 -0
- package/sdk/src/phase-runner.integration.test.ts +377 -0
- package/sdk/src/phase-runner.test.ts +2720 -0
- package/sdk/src/phase-runner.ts +1442 -0
- package/sdk/src/plan-parser.test.ts +579 -0
- package/sdk/src/plan-parser.ts +431 -0
- package/sdk/src/planning-journal.test.ts +70 -0
- package/sdk/src/planning-journal.ts +153 -0
- package/sdk/src/planning-runtime.test.ts +29 -0
- package/sdk/src/planning-runtime.ts +100 -0
- package/sdk/src/prompt-builder.test.ts +318 -0
- package/sdk/src/prompt-builder.ts +218 -0
- package/sdk/src/prompt-sanitizer.test.ts +260 -0
- package/sdk/src/prompt-sanitizer.ts +116 -0
- package/sdk/src/query/QUERY-HANDLERS.md +349 -0
- package/sdk/src/query/active-workstream-store.ts +50 -0
- package/sdk/src/query/agent-failure-classifier.test.ts +157 -0
- package/sdk/src/query/agent-failure-classifier.ts +105 -0
- package/sdk/src/query/audit-open.ts +722 -0
- package/sdk/src/query/check-auto-mode.test.ts +77 -0
- package/sdk/src/query/check-auto-mode.ts +49 -0
- package/sdk/src/query/check-completion.test.ts +113 -0
- package/sdk/src/query/check-completion.ts +182 -0
- package/sdk/src/query/check-decision-coverage.test.ts +519 -0
- package/sdk/src/query/check-decision-coverage.ts +554 -0
- package/sdk/src/query/check-gates.test.ts +103 -0
- package/sdk/src/query/check-gates.ts +112 -0
- package/sdk/src/query/check-ship-ready.test.ts +111 -0
- package/sdk/src/query/check-ship-ready.ts +104 -0
- package/sdk/src/query/check-verification-status.test.ts +143 -0
- package/sdk/src/query/check-verification-status.ts +160 -0
- package/sdk/src/query/command-aliases.generated.ts +156 -0
- package/sdk/src/query/command-catalog.ts +31 -0
- package/sdk/src/query/command-definition.test.ts +47 -0
- package/sdk/src/query/command-definition.ts +70 -0
- package/sdk/src/query/command-family-handlers.ts +117 -0
- package/sdk/src/query/command-manifest.init.ts +24 -0
- package/sdk/src/query/command-manifest.non-family.ts +85 -0
- package/sdk/src/query/command-manifest.phase.ts +16 -0
- package/sdk/src/query/command-manifest.phases.ts +11 -0
- package/sdk/src/query/command-manifest.roadmap.ts +11 -0
- package/sdk/src/query/command-manifest.state.ts +31 -0
- package/sdk/src/query/command-manifest.ts +17 -0
- package/sdk/src/query/command-manifest.types.ts +13 -0
- package/sdk/src/query/command-manifest.validate.ts +11 -0
- package/sdk/src/query/command-manifest.verify.ts +15 -0
- package/sdk/src/query/command-resolution.test.ts +70 -0
- package/sdk/src/query/command-seam-coverage.test.ts +118 -0
- package/sdk/src/query/command-static-catalog-domain.ts +117 -0
- package/sdk/src/query/command-static-catalog-foundation.ts +103 -0
- package/sdk/src/query/command-topology.test.ts +28 -0
- package/sdk/src/query/command-topology.ts +114 -0
- package/sdk/src/query/commands-list.test.ts +36 -0
- package/sdk/src/query/commands-list.ts +19 -0
- package/sdk/src/query/commit.test.ts +485 -0
- package/sdk/src/query/commit.ts +383 -0
- package/sdk/src/query/config-gates.test.ts +89 -0
- package/sdk/src/query/config-gates.ts +69 -0
- package/sdk/src/query/config-mutation.test.ts +598 -0
- package/sdk/src/query/config-mutation.ts +575 -0
- package/sdk/src/query/config-query.test.ts +367 -0
- package/sdk/src/query/config-query.ts +244 -0
- package/sdk/src/query/config-schema.ts +159 -0
- package/sdk/src/query/decisions.test.ts +215 -0
- package/sdk/src/query/decisions.ts +192 -0
- package/sdk/src/query/decomposed-handlers.test.ts +431 -0
- package/sdk/src/query/detect-custom-files.test.ts +115 -0
- package/sdk/src/query/detect-custom-files.ts +96 -0
- package/sdk/src/query/detect-phase-type.test.ts +105 -0
- package/sdk/src/query/detect-phase-type.ts +141 -0
- package/sdk/src/query/docs-init.ts +258 -0
- package/sdk/src/query/fallow-audit.ts +88 -0
- package/sdk/src/query/frontmatter-array.test.ts +14 -0
- package/sdk/src/query/frontmatter-mutation.test.ts +259 -0
- package/sdk/src/query/frontmatter-mutation.ts +343 -0
- package/sdk/src/query/frontmatter.test.ts +326 -0
- package/sdk/src/query/frontmatter.ts +395 -0
- package/sdk/src/query/helpers.test.ts +615 -0
- package/sdk/src/query/helpers.ts +646 -0
- package/sdk/src/query/index-thin-seam.test.ts +16 -0
- package/sdk/src/query/index.ts +9 -0
- package/sdk/src/query/init-complex.test.ts +616 -0
- package/sdk/src/query/init-complex.ts +799 -0
- package/sdk/src/query/init-progress-precedence.test.ts +177 -0
- package/sdk/src/query/init-workstream-milestone-op.test.ts +321 -0
- package/sdk/src/query/init.test.ts +792 -0
- package/sdk/src/query/init.ts +1262 -0
- package/sdk/src/query/intel.test.ts +90 -0
- package/sdk/src/query/intel.ts +404 -0
- package/sdk/src/query/mutation-event-decorator.test.ts +45 -0
- package/sdk/src/query/mutation-event-decorator.ts +37 -0
- package/sdk/src/query/mutation-event-mapper.test.ts +33 -0
- package/sdk/src/query/mutation-event-mapper.ts +102 -0
- package/sdk/src/query/mvp.test.ts +335 -0
- package/sdk/src/query/mvp.ts +292 -0
- package/sdk/src/query/normalize-query-command.test.ts +102 -0
- package/sdk/src/query/phase-filesystem-adapter.ts +35 -0
- package/sdk/src/query/phase-lifecycle-policy.ts +171 -0
- package/sdk/src/query/phase-lifecycle.test.ts +1750 -0
- package/sdk/src/query/phase-lifecycle.ts +1833 -0
- package/sdk/src/query/phase-list-queries.test.ts +88 -0
- package/sdk/src/query/phase-list-queries.ts +152 -0
- package/sdk/src/query/phase-ready.test.ts +65 -0
- package/sdk/src/query/phase-ready.ts +159 -0
- package/sdk/src/query/phase-roadmap-mutation.ts +77 -0
- package/sdk/src/query/phase.test.ts +651 -0
- package/sdk/src/query/phase.ts +550 -0
- package/sdk/src/query/pipeline.test.ts +169 -0
- package/sdk/src/query/pipeline.ts +243 -0
- package/sdk/src/query/plan-scan.test.ts +35 -0
- package/sdk/src/query/plan-scan.ts +82 -0
- package/sdk/src/query/plan-task-structure.test.ts +65 -0
- package/sdk/src/query/plan-task-structure.ts +63 -0
- package/sdk/src/query/policy-convergence.test.ts +28 -0
- package/sdk/src/query/profile-extract-messages.ts +247 -0
- package/sdk/src/query/profile-output.ts +929 -0
- package/sdk/src/query/profile-questionnaire-data.ts +181 -0
- package/sdk/src/query/profile-sample.ts +184 -0
- package/sdk/src/query/profile-scan-sessions.ts +174 -0
- package/sdk/src/query/profile.test.ts +136 -0
- package/sdk/src/query/profile.ts +337 -0
- package/sdk/src/query/progress.test.ts +156 -0
- package/sdk/src/query/progress.ts +566 -0
- package/sdk/src/query/query-cli-adapter.test.ts +79 -0
- package/sdk/src/query/query-cli-adapter.ts +39 -0
- package/sdk/src/query/query-cli-output.test.ts +33 -0
- package/sdk/src/query/query-cli-output.ts +35 -0
- package/sdk/src/query/query-command-diagnosis.test.ts +22 -0
- package/sdk/src/query/query-command-diagnosis.ts +5 -0
- package/sdk/src/query/query-command-resolution-strategy.test.ts +34 -0
- package/sdk/src/query/query-command-resolution-strategy.ts +121 -0
- package/sdk/src/query/query-command-semantics.test.ts +22 -0
- package/sdk/src/query/query-command-semantics.ts +22 -0
- package/sdk/src/query/query-dispatch-contract.ts +30 -0
- package/sdk/src/query/query-dispatch-error-mapper.test.ts +62 -0
- package/sdk/src/query/query-dispatch-error-mapper.ts +5 -0
- package/sdk/src/query/query-dispatch-formatting.test.ts +28 -0
- package/sdk/src/query/query-dispatch-formatting.ts +5 -0
- package/sdk/src/query/query-dispatch-input-validation.test.ts +23 -0
- package/sdk/src/query/query-dispatch-input-validation.ts +5 -0
- package/sdk/src/query/query-dispatch-observability.test.ts +10 -0
- package/sdk/src/query/query-dispatch-observability.ts +6 -0
- package/sdk/src/query/query-dispatch-plan.test.ts +25 -0
- package/sdk/src/query/query-dispatch-plan.ts +5 -0
- package/sdk/src/query/query-dispatch-result-builder.test.ts +16 -0
- package/sdk/src/query/query-dispatch-result-builder.ts +5 -0
- package/sdk/src/query/query-dispatch.test.ts +399 -0
- package/sdk/src/query/query-dispatch.ts +243 -0
- package/sdk/src/query/query-error-details-schema.ts +29 -0
- package/sdk/src/query/query-error-taxonomy.test.ts +39 -0
- package/sdk/src/query/query-error-taxonomy.ts +117 -0
- package/sdk/src/query/query-fallback-bridge-adapter.test.ts +32 -0
- package/sdk/src/query/query-fallback-bridge-adapter.ts +54 -0
- package/sdk/src/query/query-fallback-executor.test.ts +82 -0
- package/sdk/src/query/query-fallback-executor.ts +44 -0
- package/sdk/src/query/query-fallback-output-classifier.test.ts +36 -0
- package/sdk/src/query/query-fallback-output-classifier.ts +31 -0
- package/sdk/src/query/query-fallback-policy.test.ts +13 -0
- package/sdk/src/query/query-fallback-policy.ts +11 -0
- package/sdk/src/query/query-native-dispatch-adapter.ts +16 -0
- package/sdk/src/query/query-policy-capability.test.ts +10 -0
- package/sdk/src/query/query-policy-capability.ts +26 -0
- package/sdk/src/query/query-policy-snapshot.test.ts +9 -0
- package/sdk/src/query/query-registry-capability.test.ts +14 -0
- package/sdk/src/query/query-runtime-context.ts +44 -0
- package/sdk/src/query/query-unknown-command-hints.test.ts +9 -0
- package/sdk/src/query/query-unknown-command-hints.ts +5 -0
- package/sdk/src/query/registry-assembly-descriptor.ts +87 -0
- package/sdk/src/query/registry-assembly-invariants.ts +127 -0
- package/sdk/src/query/registry-assembly.test.ts +138 -0
- package/sdk/src/query/registry-assembly.ts +78 -0
- package/sdk/src/query/registry.test.ts +208 -0
- package/sdk/src/query/registry.ts +142 -0
- package/sdk/src/query/requirements-extract-from-plans.test.ts +58 -0
- package/sdk/src/query/requirements-extract-from-plans.ts +86 -0
- package/sdk/src/query/roadmap-update-plan-progress.test.ts +233 -0
- package/sdk/src/query/roadmap-update-plan-progress.ts +159 -0
- package/sdk/src/query/roadmap.test.ts +1181 -0
- package/sdk/src/query/roadmap.ts +894 -0
- package/sdk/src/query/route-next-action.test.ts +61 -0
- package/sdk/src/query/route-next-action.ts +345 -0
- package/sdk/src/query/schema-detect.ts +189 -0
- package/sdk/src/query/secrets.test.ts +66 -0
- package/sdk/src/query/secrets.ts +43 -0
- package/sdk/src/query/skill-manifest.test.ts +62 -0
- package/sdk/src/query/skill-manifest.ts +216 -0
- package/sdk/src/query/skills.test.ts +234 -0
- package/sdk/src/query/skills.ts +143 -0
- package/sdk/src/query/state-document.test.ts +197 -0
- package/sdk/src/query/state-document.ts +129 -0
- package/sdk/src/query/state-mutation.test.ts +1198 -0
- package/sdk/src/query/state-mutation.ts +1718 -0
- package/sdk/src/query/state-project-load.ts +80 -0
- package/sdk/src/query/state.test.ts +616 -0
- package/sdk/src/query/state.ts +463 -0
- package/sdk/src/query/sub-repos-root.integration.test.ts +79 -0
- package/sdk/src/query/summary.test.ts +95 -0
- package/sdk/src/query/summary.ts +296 -0
- package/sdk/src/query/template.test.ts +180 -0
- package/sdk/src/query/template.ts +242 -0
- package/sdk/src/query/uat.test.ts +77 -0
- package/sdk/src/query/uat.ts +365 -0
- package/sdk/src/query/utils.test.ts +82 -0
- package/sdk/src/query/utils.ts +106 -0
- package/sdk/src/query/validate.test.ts +831 -0
- package/sdk/src/query/validate.ts +952 -0
- package/sdk/src/query/verify.test.ts +414 -0
- package/sdk/src/query/verify.ts +692 -0
- package/sdk/src/query/websearch.test.ts +31 -0
- package/sdk/src/query/websearch.ts +82 -0
- package/sdk/src/query/workspace.test.ts +120 -0
- package/sdk/src/query/workspace.ts +145 -0
- package/sdk/src/query/workstream-inventory.ts +195 -0
- package/sdk/src/query/workstream.test.ts +153 -0
- package/sdk/src/query/workstream.ts +324 -0
- package/sdk/src/query/worktree.ts +39 -0
- package/sdk/src/query-command-executor.ts +31 -0
- package/sdk/src/query-execution-policy.test.ts +52 -0
- package/sdk/src/query-execution-policy.ts +46 -0
- package/sdk/src/query-failure-classification.test.ts +23 -0
- package/sdk/src/query-failure-classification.ts +42 -0
- package/sdk/src/query-hotpath-methods.ts +48 -0
- package/sdk/src/query-native-direct-adapter.test.ts +35 -0
- package/sdk/src/query-native-direct-adapter.ts +70 -0
- package/sdk/src/query-native-hotpath-adapter.test.ts +43 -0
- package/sdk/src/query-native-hotpath-adapter.ts +45 -0
- package/sdk/src/query-raw-output-projection.test.ts +39 -0
- package/sdk/src/query-raw-output-projection.ts +74 -0
- package/sdk/src/query-runtime-bridge.test.ts +150 -0
- package/sdk/src/query-runtime-bridge.ts +215 -0
- package/sdk/src/query-runtime-seam-coverage.test.ts +20 -0
- package/sdk/src/query-sdd-tools-path.ts +1 -0
- package/sdk/src/query-sdd-tools-runtime.ts +89 -0
- package/sdk/src/query-subprocess-adapter.test.ts +84 -0
- package/sdk/src/query-subprocess-adapter.ts +146 -0
- package/sdk/src/query-tools-error-factory.test.ts +35 -0
- package/sdk/src/query-tools-error-factory.ts +76 -0
- package/sdk/src/research-gate.test.ts +190 -0
- package/sdk/src/research-gate.ts +94 -0
- package/sdk/src/runtime-bridge-options.test.ts +33 -0
- package/sdk/src/runtime-gate.test.ts +84 -0
- package/sdk/src/runtime-gate.ts +52 -0
- package/sdk/src/sdd-tools-error.test.ts +21 -0
- package/sdk/src/sdd-tools-error.ts +65 -0
- package/sdk/src/sdd-tools.test.ts +472 -0
- package/sdk/src/sdd-tools.ts +237 -0
- package/sdk/src/sdd-transport-policy.test.ts +34 -0
- package/sdk/src/sdd-transport-policy.ts +48 -0
- package/sdk/src/sdd-transport.test.ts +292 -0
- package/sdk/src/sdd-transport.ts +117 -0
- package/sdk/src/sdk-package-compatibility.test.ts +97 -0
- package/sdk/src/sdk-package-compatibility.ts +141 -0
- package/sdk/src/session-runner.test.ts +164 -0
- package/sdk/src/session-runner.ts +327 -0
- package/sdk/src/tool-scoping.test.ts +160 -0
- package/sdk/src/tool-scoping.ts +61 -0
- package/sdk/src/types.ts +927 -0
- package/sdk/src/workflow-agent-skills-consistency.test.ts +98 -0
- package/sdk/src/workstream-name-policy.ts +24 -0
- package/sdk/src/workstream-utils.ts +21 -0
- package/sdk/src/ws-flag.test.ts +285 -0
- package/sdk/src/ws-transport.test.ts +161 -0
- package/sdk/src/ws-transport.ts +93 -0
- package/sdk/tsconfig.json +20 -0
- package/commands/sdd/add-backlog.md +0 -76
- package/commands/sdd/add-phase.md +0 -43
- package/commands/sdd/add-todo.md +0 -47
- package/commands/sdd/check-todos.md +0 -45
- package/commands/sdd/do.md +0 -30
- package/commands/sdd/insert-phase.md +0 -32
- package/commands/sdd/join-discord.md +0 -18
- package/commands/sdd/list-phase-assumptions.md +0 -46
- package/commands/sdd/list-workspaces.md +0 -19
- package/commands/sdd/new-workspace.md +0 -44
- package/commands/sdd/next.md +0 -24
- package/commands/sdd/note.md +0 -34
- package/commands/sdd/plan-milestone-gaps.md +0 -34
- package/commands/sdd/plant-seed.md +0 -28
- package/commands/sdd/reapply-patches.md +0 -123
- package/commands/sdd/remove-phase.md +0 -31
- package/commands/sdd/remove-workspace.md +0 -26
- package/commands/sdd/research-phase.md +0 -195
- package/commands/sdd/session-report.md +0 -19
- package/commands/sdd/set-profile.md +0 -12
- package/scripts/sync-upstream.sh +0 -56
- package/sdd/commands/sdd/workstreams.md +0 -63
- package/sdd/workflows/research-phase.md +0 -82
package/sdd/bin/lib/phase.cjs
CHANGED
|
@@ -4,9 +4,63 @@
|
|
|
4
4
|
|
|
5
5
|
const fs = require('fs');
|
|
6
6
|
const path = require('path');
|
|
7
|
-
const { escapeRegex, loadConfig, normalizePhaseName, comparePhaseNum, findPhaseInternal, getArchivedPhaseDirs, generateSlugInternal, getMilestonePhaseFilter, stripShippedMilestones, extractCurrentMilestone, replaceInCurrentMilestone, toPosixPath,
|
|
7
|
+
const { escapeRegex, loadConfig, normalizePhaseName, phaseMarkdownRegexSource, comparePhaseNum, findPhaseInternal, getArchivedPhaseDirs, generateSlugInternal, getMilestonePhaseFilter, stripShippedMilestones, extractCurrentMilestone, replaceInCurrentMilestone, toPosixPath, output, error, readSubdirectories, phaseTokenMatches, ERROR_REASON } = require('./core.cjs');
|
|
8
|
+
const { platformWriteSync, platformReadSync, platformEnsureDir } = require('./shell-command-projection.cjs');
|
|
9
|
+
const { planningDir, withPlanningLock } = require('./planning-workspace.cjs');
|
|
8
10
|
const { extractFrontmatter } = require('./frontmatter.cjs');
|
|
9
|
-
const { writeStateMd, stateExtractField, stateReplaceField, stateReplaceFieldWithFallback } = require('./state.cjs');
|
|
11
|
+
const { writeStateMd, readModifyWriteStateMd, stateExtractField, stateReplaceField, stateReplaceFieldWithFallback, updatePerformanceMetricsSection } = require('./state.cjs');
|
|
12
|
+
|
|
13
|
+
// #2893 — strict canonical filter: `{padded_phase}-{NN}-PLAN.md` or `PLAN.md`.
|
|
14
|
+
// Documented in agents/sdd-planner.md (write_phase_prompt step). The wider
|
|
15
|
+
// "looks like a plan but isn't canonical" probe below is used to surface a
|
|
16
|
+
// loud warning instead of silently returning zero plans.
|
|
17
|
+
const isCanonicalPlanFile = (f) => f.endsWith('-PLAN.md') || f === 'PLAN.md';
|
|
18
|
+
|
|
19
|
+
// Any .md file with PLAN anywhere in the basename — the diagnostic net for
|
|
20
|
+
// catching agent deviations like `01-PLAN-01-foundation.md` (#2893).
|
|
21
|
+
// Excludes derivative files (`-PLAN-OUTLINE.md`, `*.pre-bounce.md`, etc.) that
|
|
22
|
+
// the planner legitimately produces alongside canonical plans.
|
|
23
|
+
const PLAN_OUTLINE_RE = /-PLAN-OUTLINE\.md$/i;
|
|
24
|
+
const PLAN_PRE_BOUNCE_RE = /-PLAN.*\.pre-bounce\.md$/i;
|
|
25
|
+
const looksLikePlanFile = (f) =>
|
|
26
|
+
/\.md$/i.test(f)
|
|
27
|
+
&& /PLAN/i.test(f)
|
|
28
|
+
&& !PLAN_OUTLINE_RE.test(f)
|
|
29
|
+
&& !PLAN_PRE_BOUNCE_RE.test(f);
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Detect plan-shaped files that the canonical filter would reject. Returns
|
|
33
|
+
* a warning string when offenders exist, else null. Centralised so every
|
|
34
|
+
* read site (phase-plan-index, phases list --type plans, find-phase) emits
|
|
35
|
+
* the same message.
|
|
36
|
+
*
|
|
37
|
+
* @param {string[]} dirFiles — readdirSync output for one phase directory
|
|
38
|
+
* @param {string[]} matchedFiles — what the canonical filter accepted
|
|
39
|
+
* @returns {string|null}
|
|
40
|
+
*/
|
|
41
|
+
function describeNonCanonicalPlans(dirFiles, matchedFiles) {
|
|
42
|
+
const matched = new Set(matchedFiles);
|
|
43
|
+
const offenders = dirFiles.filter((f) => looksLikePlanFile(f) && !matched.has(f));
|
|
44
|
+
if (offenders.length === 0) return null;
|
|
45
|
+
return (
|
|
46
|
+
`Found ${offenders.length} plan-shaped file(s) in this phase that don't match the canonical ` +
|
|
47
|
+
`naming convention "{padded_phase}-{NN}-PLAN.md" (or bare "PLAN.md") and were skipped: ` +
|
|
48
|
+
offenders.map((f) => `"${f}"`).join(', ') +
|
|
49
|
+
`. Rename to the canonical form (e.g. "01-01-PLAN.md") so the executor can detect them. ` +
|
|
50
|
+
`See agents/sdd-planner.md write_phase_prompt step for the full contract.`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function extractCanonicalPlanId(filename) {
|
|
55
|
+
const base = filename.replace(/-PLAN\.md$/i, '').replace(/-SUMMARY\.md$/i, '').replace(/\.md$/i, '');
|
|
56
|
+
const parts = base.split('-').filter(Boolean);
|
|
57
|
+
const tokenRe = /^\d+[A-Z]?(?:\.\d+)*$/i;
|
|
58
|
+
const phaseIdx = parts.findIndex(p => tokenRe.test(p));
|
|
59
|
+
if (phaseIdx >= 0 && phaseIdx + 1 < parts.length && tokenRe.test(parts[phaseIdx + 1])) {
|
|
60
|
+
return `${parts[phaseIdx]}-${parts[phaseIdx + 1]}`;
|
|
61
|
+
}
|
|
62
|
+
return base;
|
|
63
|
+
}
|
|
10
64
|
|
|
11
65
|
function cmdPhasesList(cwd, options, raw) {
|
|
12
66
|
const phasesDir = path.join(planningDir(cwd), 'phases');
|
|
@@ -41,7 +95,7 @@ function cmdPhasesList(cwd, options, raw) {
|
|
|
41
95
|
// If filtering by phase number
|
|
42
96
|
if (phase) {
|
|
43
97
|
const normalized = normalizePhaseName(phase);
|
|
44
|
-
const match = dirs.find(d => d
|
|
98
|
+
const match = dirs.find(d => phaseTokenMatches(d, normalized));
|
|
45
99
|
if (!match) {
|
|
46
100
|
output({ files: [], count: 0, phase_dir: null, error: 'Phase not found' }, raw, '');
|
|
47
101
|
return;
|
|
@@ -52,13 +106,18 @@ function cmdPhasesList(cwd, options, raw) {
|
|
|
52
106
|
// If listing files of a specific type
|
|
53
107
|
if (type) {
|
|
54
108
|
const files = [];
|
|
109
|
+
const warnings = [];
|
|
55
110
|
for (const dir of dirs) {
|
|
56
111
|
const dirPath = path.join(phasesDir, dir);
|
|
57
112
|
const dirFiles = fs.readdirSync(dirPath);
|
|
58
113
|
|
|
59
114
|
let filtered;
|
|
60
115
|
if (type === 'plans') {
|
|
61
|
-
filtered = dirFiles.filter(
|
|
116
|
+
filtered = dirFiles.filter(isCanonicalPlanFile);
|
|
117
|
+
// #2893 — surface plan-shaped files the canonical filter rejected
|
|
118
|
+
// so callers (executor init, etc.) don't silently see zero plans.
|
|
119
|
+
const w = describeNonCanonicalPlans(dirFiles, filtered);
|
|
120
|
+
if (w) warnings.push(`${dir}: ${w}`);
|
|
62
121
|
} else if (type === 'summaries') {
|
|
63
122
|
filtered = dirFiles.filter(f => f.endsWith('-SUMMARY.md') || f === 'SUMMARY.md');
|
|
64
123
|
} else {
|
|
@@ -73,6 +132,7 @@ function cmdPhasesList(cwd, options, raw) {
|
|
|
73
132
|
count: files.length,
|
|
74
133
|
phase_dir: phase ? dirs[0].replace(/^\d+(?:\.\d+)*-?/, '') : null,
|
|
75
134
|
};
|
|
135
|
+
if (warnings.length) result.warning = warnings.join(' | ');
|
|
76
136
|
output(result, raw, files.join('\n'));
|
|
77
137
|
return;
|
|
78
138
|
}
|
|
@@ -88,50 +148,51 @@ function cmdPhaseNextDecimal(cwd, basePhase, raw) {
|
|
|
88
148
|
const phasesDir = path.join(planningDir(cwd), 'phases');
|
|
89
149
|
const normalized = normalizePhaseName(basePhase);
|
|
90
150
|
|
|
91
|
-
// Check if phases directory exists
|
|
92
|
-
if (!fs.existsSync(phasesDir)) {
|
|
93
|
-
output(
|
|
94
|
-
{
|
|
95
|
-
found: false,
|
|
96
|
-
base_phase: normalized,
|
|
97
|
-
next: `${normalized}.1`,
|
|
98
|
-
existing: [],
|
|
99
|
-
},
|
|
100
|
-
raw,
|
|
101
|
-
`${normalized}.1`
|
|
102
|
-
);
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
151
|
try {
|
|
107
|
-
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
// Check if base phase exists
|
|
111
|
-
const baseExists = dirs.some(d => d.startsWith(normalized + '-') || d === normalized);
|
|
152
|
+
let baseExists = false;
|
|
153
|
+
const decimalSet = new Set();
|
|
112
154
|
|
|
113
|
-
//
|
|
114
|
-
|
|
115
|
-
|
|
155
|
+
// Scan directory names for existing decimal phases
|
|
156
|
+
if (fs.existsSync(phasesDir)) {
|
|
157
|
+
const entries = fs.readdirSync(phasesDir, { withFileTypes: true });
|
|
158
|
+
const dirs = entries.filter(e => e.isDirectory()).map(e => e.name);
|
|
159
|
+
baseExists = dirs.some(d => phaseTokenMatches(d, normalized));
|
|
116
160
|
|
|
117
|
-
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
161
|
+
const dirPattern = new RegExp(`^(?:[A-Z]{1,6}-)?${escapeRegex(normalized)}\\.(\\d+)`);
|
|
162
|
+
for (const dir of dirs) {
|
|
163
|
+
const match = dir.match(dirPattern);
|
|
164
|
+
if (match) decimalSet.add(parseInt(match[1], 10));
|
|
121
165
|
}
|
|
122
166
|
}
|
|
123
167
|
|
|
124
|
-
//
|
|
125
|
-
|
|
168
|
+
// Also scan ROADMAP.md for phase entries that may not have directories yet
|
|
169
|
+
const roadmapPath = path.join(planningDir(cwd), 'ROADMAP.md');
|
|
170
|
+
if (fs.existsSync(roadmapPath)) {
|
|
171
|
+
try {
|
|
172
|
+
const roadmapContent = fs.readFileSync(roadmapPath, 'utf-8');
|
|
173
|
+
// #3537: padding-tolerant on both sides — `0*${escapeRegex(...)}`
|
|
174
|
+
// tolerated extra padding but not missing.
|
|
175
|
+
const phasePattern = new RegExp(
|
|
176
|
+
`#{2,4}\\s*Phase\\s+${phaseMarkdownRegexSource(normalized)}\\.(\\d+)\\s*:`, 'gi'
|
|
177
|
+
);
|
|
178
|
+
let pm;
|
|
179
|
+
while ((pm = phasePattern.exec(roadmapContent)) !== null) {
|
|
180
|
+
decimalSet.add(parseInt(pm[1], 10));
|
|
181
|
+
}
|
|
182
|
+
} catch { /* ROADMAP.md read failure is non-fatal */ }
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Build sorted list of existing decimals
|
|
186
|
+
const existingDecimals = Array.from(decimalSet)
|
|
187
|
+
.sort((a, b) => a - b)
|
|
188
|
+
.map(n => `${normalized}.${n}`);
|
|
126
189
|
|
|
127
190
|
// Calculate next decimal
|
|
128
191
|
let nextDecimal;
|
|
129
|
-
if (
|
|
192
|
+
if (decimalSet.size === 0) {
|
|
130
193
|
nextDecimal = `${normalized}.1`;
|
|
131
194
|
} else {
|
|
132
|
-
|
|
133
|
-
const lastNum = parseInt(lastDecimal.split('.')[1], 10);
|
|
134
|
-
nextDecimal = `${normalized}.${lastNum + 1}`;
|
|
195
|
+
nextDecimal = `${normalized}.${Math.max(...decimalSet) + 1}`;
|
|
135
196
|
}
|
|
136
197
|
|
|
137
198
|
output(
|
|
@@ -149,48 +210,128 @@ function cmdPhaseNextDecimal(cwd, basePhase, raw) {
|
|
|
149
210
|
}
|
|
150
211
|
}
|
|
151
212
|
|
|
213
|
+
function getRoadmapModeForPhase(cwd, phaseNum) {
|
|
214
|
+
const roadmapPath = path.join(planningDir(cwd), 'ROADMAP.md');
|
|
215
|
+
if (!fs.existsSync(roadmapPath)) return null;
|
|
216
|
+
|
|
217
|
+
const rawContent = fs.readFileSync(roadmapPath, 'utf-8');
|
|
218
|
+
const milestoneContent = extractCurrentMilestone(rawContent, cwd);
|
|
219
|
+
const fullContent = stripShippedMilestones(rawContent);
|
|
220
|
+
const escapedPhase = phaseMarkdownRegexSource(phaseNum);
|
|
221
|
+
const phaseHeader = new RegExp(`#{2,4}\\s*Phase\\s+${escapedPhase}\\s*:`, 'i');
|
|
222
|
+
|
|
223
|
+
for (const content of [milestoneContent, fullContent]) {
|
|
224
|
+
const headerMatch = content.match(phaseHeader);
|
|
225
|
+
if (!headerMatch || headerMatch.index === undefined) continue;
|
|
226
|
+
|
|
227
|
+
const sectionStart = headerMatch.index;
|
|
228
|
+
const rest = content.slice(sectionStart);
|
|
229
|
+
const nextHeader = rest.slice(headerMatch[0].length).match(/\n#{2,4}\s+Phase\s+\S/i);
|
|
230
|
+
const sectionEnd = nextHeader ? sectionStart + headerMatch[0].length + nextHeader.index : content.length;
|
|
231
|
+
const section = content.slice(sectionStart, sectionEnd);
|
|
232
|
+
const modeMatch = section.match(/\*\*Mode(?::\*\*|\*\*:)\s*([^\n]+)/i);
|
|
233
|
+
if (modeMatch) return modeMatch[1].trim().toLowerCase();
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function cmdPhaseMvpMode(cwd, args, raw) {
|
|
240
|
+
const phaseNum = args[0];
|
|
241
|
+
if (!phaseNum) {
|
|
242
|
+
error('Usage: phase.mvp-mode <phase-number> [--cli-flag]', ERROR_REASON.USAGE);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const cliFlagPresent = args.includes('--cli-flag');
|
|
246
|
+
const roadmapMode = getRoadmapModeForPhase(cwd, phaseNum);
|
|
247
|
+
const config = loadConfig(cwd);
|
|
248
|
+
const configMvpMode = Boolean(config.mvp_mode);
|
|
249
|
+
|
|
250
|
+
let active = false;
|
|
251
|
+
let source = 'none';
|
|
252
|
+
if (cliFlagPresent) {
|
|
253
|
+
active = true;
|
|
254
|
+
source = 'cli_flag';
|
|
255
|
+
} else if (roadmapMode === 'mvp') {
|
|
256
|
+
active = true;
|
|
257
|
+
source = 'roadmap';
|
|
258
|
+
} else if (configMvpMode) {
|
|
259
|
+
active = true;
|
|
260
|
+
source = 'config';
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
output({
|
|
264
|
+
active,
|
|
265
|
+
source,
|
|
266
|
+
roadmap_mode: roadmapMode,
|
|
267
|
+
config_mvp_mode: configMvpMode,
|
|
268
|
+
cli_flag_present: cliFlagPresent,
|
|
269
|
+
}, raw);
|
|
270
|
+
}
|
|
271
|
+
|
|
152
272
|
function cmdFindPhase(cwd, phase, raw) {
|
|
153
273
|
if (!phase) {
|
|
154
274
|
error('phase identifier required');
|
|
155
275
|
}
|
|
156
276
|
|
|
157
|
-
const
|
|
277
|
+
const planBase = planningDir(cwd);
|
|
158
278
|
const normalized = normalizePhaseName(phase);
|
|
279
|
+
const notFound = { found: false, directory: null, phase_number: null, phase_name: null, plans: [], summaries: [], searched_directories: [] };
|
|
159
280
|
|
|
160
|
-
|
|
161
|
-
|
|
281
|
+
// Build candidate search dirs: flat layout first, then milestone-archive layout.
|
|
282
|
+
const searchDirs = [];
|
|
283
|
+
const flatPhasesDir = path.join(planBase, 'phases');
|
|
284
|
+
if (fs.existsSync(flatPhasesDir)) searchDirs.push(flatPhasesDir);
|
|
162
285
|
try {
|
|
163
|
-
const
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
return;
|
|
286
|
+
const milestonesDir = path.join(planBase, 'milestones');
|
|
287
|
+
const entries = fs.readdirSync(milestonesDir, { withFileTypes: true })
|
|
288
|
+
.filter(e => e.isDirectory() && /^v\d+.*-phases$/.test(e.name))
|
|
289
|
+
.sort((a, b) => a.name.localeCompare(b.name, undefined, { numeric: true }));
|
|
290
|
+
for (const e of entries) {
|
|
291
|
+
searchDirs.push(path.join(milestonesDir, e.name));
|
|
170
292
|
}
|
|
293
|
+
} catch { /* no milestones dir */ }
|
|
171
294
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
const phaseName = dirMatch && dirMatch[2] ? dirMatch[2] : null;
|
|
295
|
+
notFound.searched_directories = searchDirs.map((searchDir) =>
|
|
296
|
+
toPosixPath(path.join(path.relative(cwd, planBase), path.relative(planBase, searchDir))));
|
|
175
297
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
298
|
+
for (const searchDir of searchDirs) {
|
|
299
|
+
try {
|
|
300
|
+
const entries = fs.readdirSync(searchDir, { withFileTypes: true });
|
|
301
|
+
const dirs = entries.filter(e => e.isDirectory()).map(e => e.name).sort((a, b) => comparePhaseNum(a, b));
|
|
180
302
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
directory: toPosixPath(path.join(path.relative(cwd, planningDir(cwd)), 'phases', match)),
|
|
184
|
-
phase_number: phaseNumber,
|
|
185
|
-
phase_name: phaseName,
|
|
186
|
-
plans,
|
|
187
|
-
summaries,
|
|
188
|
-
};
|
|
303
|
+
const match = dirs.find(d => phaseTokenMatches(d, normalized));
|
|
304
|
+
if (!match) continue;
|
|
189
305
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
306
|
+
// Extract phase number — supports project-code-prefixed (CK-01-name), numeric (01-name), and custom IDs
|
|
307
|
+
const dirMatch = match.match(/^(?:[A-Z]{1,6}-)(\d+[A-Z]?(?:\.\d+)*)-?(.*)/i)
|
|
308
|
+
|| match.match(/^(\d+[A-Z]?(?:\.\d+)*)-?(.*)/i);
|
|
309
|
+
const phaseNumber = dirMatch ? dirMatch[1] : normalized;
|
|
310
|
+
const phaseName = dirMatch && dirMatch[2] ? dirMatch[2] : null;
|
|
311
|
+
|
|
312
|
+
const phaseDir = path.join(searchDir, match);
|
|
313
|
+
const phaseFiles = fs.readdirSync(phaseDir);
|
|
314
|
+
const plans = phaseFiles.filter(isCanonicalPlanFile).sort();
|
|
315
|
+
const summaries = phaseFiles.filter(f => f.endsWith('-SUMMARY.md') || f === 'SUMMARY.md').sort();
|
|
316
|
+
// #2893 — same diagnostic as phase-plan-index for consistency.
|
|
317
|
+
const planNamingWarning = describeNonCanonicalPlans(phaseFiles, plans);
|
|
318
|
+
|
|
319
|
+
const result = {
|
|
320
|
+
found: true,
|
|
321
|
+
directory: toPosixPath(path.join(path.relative(cwd, planBase), path.relative(planBase, searchDir), match)),
|
|
322
|
+
phase_number: phaseNumber,
|
|
323
|
+
phase_name: phaseName,
|
|
324
|
+
plans,
|
|
325
|
+
summaries,
|
|
326
|
+
};
|
|
327
|
+
if (planNamingWarning) result.warning = planNamingWarning;
|
|
328
|
+
|
|
329
|
+
output(result, raw, result.directory);
|
|
330
|
+
return;
|
|
331
|
+
} catch { continue; }
|
|
193
332
|
}
|
|
333
|
+
|
|
334
|
+
output(notFound, raw, '');
|
|
194
335
|
}
|
|
195
336
|
|
|
196
337
|
function extractObjective(content) {
|
|
@@ -212,7 +353,7 @@ function cmdPhasePlanIndex(cwd, phase, raw) {
|
|
|
212
353
|
try {
|
|
213
354
|
const entries = fs.readdirSync(phasesDir, { withFileTypes: true });
|
|
214
355
|
const dirs = entries.filter(e => e.isDirectory()).map(e => e.name).sort((a, b) => comparePhaseNum(a, b));
|
|
215
|
-
const match = dirs.find(d => d
|
|
356
|
+
const match = dirs.find(d => phaseTokenMatches(d, normalized));
|
|
216
357
|
if (match) {
|
|
217
358
|
phaseDir = path.join(phasesDir, match);
|
|
218
359
|
phaseDirName = match;
|
|
@@ -228,18 +369,24 @@ function cmdPhasePlanIndex(cwd, phase, raw) {
|
|
|
228
369
|
|
|
229
370
|
// Get all files in phase directory
|
|
230
371
|
const phaseFiles = fs.readdirSync(phaseDir);
|
|
231
|
-
const planFiles = phaseFiles.filter(
|
|
372
|
+
const planFiles = phaseFiles.filter(isCanonicalPlanFile).sort();
|
|
232
373
|
const summaryFiles = phaseFiles.filter(f => f.endsWith('-SUMMARY.md') || f === 'SUMMARY.md');
|
|
374
|
+
// #2893 — surface plan-shaped files the canonical filter rejected so a
|
|
375
|
+
// misnamed plan never silently produces plan_count: 0 at executor init.
|
|
376
|
+
const planNamingWarning = describeNonCanonicalPlans(phaseFiles, planFiles);
|
|
233
377
|
|
|
234
378
|
// Build set of plan IDs with summaries
|
|
235
379
|
const completedPlanIds = new Set(
|
|
236
|
-
summaryFiles.
|
|
380
|
+
summaryFiles.flatMap(s => {
|
|
381
|
+
const exact = s.replace('-SUMMARY.md', '').replace('SUMMARY.md', '');
|
|
382
|
+
const canonical = extractCanonicalPlanId(s);
|
|
383
|
+
return canonical === exact ? [exact] : [exact, canonical];
|
|
384
|
+
})
|
|
237
385
|
);
|
|
238
386
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
const
|
|
242
|
-
let hasCheckpoints = false;
|
|
387
|
+
// ── Pass 1: parse each plan file ─────────────────────────────────────────
|
|
388
|
+
|
|
389
|
+
const rawPlans = [];
|
|
243
390
|
|
|
244
391
|
for (const planFile of planFiles) {
|
|
245
392
|
const planId = planFile.replace('-PLAN.md', '').replace('PLAN.md', '');
|
|
@@ -252,8 +399,20 @@ function cmdPhasePlanIndex(cwd, phase, raw) {
|
|
|
252
399
|
const mdTasks = content.match(/##\s*Task\s*\d+/gi) || [];
|
|
253
400
|
const taskCount = xmlTasks.length || mdTasks.length;
|
|
254
401
|
|
|
255
|
-
// Parse wave as integer
|
|
256
|
-
|
|
402
|
+
// Parse wave as integer — use nullish handling so wave: 0 is preserved.
|
|
403
|
+
// parseInt returns NaN for missing/non-numeric values; fall back to null
|
|
404
|
+
// (meaning "no declared wave") so downstream can apply the topo default.
|
|
405
|
+
const parsedWave = parseInt(fm.wave, 10);
|
|
406
|
+
const declaredWave = Number.isNaN(parsedWave) ? null : parsedWave;
|
|
407
|
+
|
|
408
|
+
// Parse depends_on — normalise to string[]
|
|
409
|
+
let dependsOn = [];
|
|
410
|
+
const fmDeps = fm['depends_on'];
|
|
411
|
+
if (Array.isArray(fmDeps)) {
|
|
412
|
+
dependsOn = fmDeps.map(String);
|
|
413
|
+
} else if (typeof fmDeps === 'string' && fmDeps.trim() !== '') {
|
|
414
|
+
dependsOn = [fmDeps];
|
|
415
|
+
}
|
|
257
416
|
|
|
258
417
|
// Parse autonomous (default true if not specified)
|
|
259
418
|
let autonomous = true;
|
|
@@ -261,10 +420,6 @@ function cmdPhasePlanIndex(cwd, phase, raw) {
|
|
|
261
420
|
autonomous = fm.autonomous === 'true' || fm.autonomous === true;
|
|
262
421
|
}
|
|
263
422
|
|
|
264
|
-
if (!autonomous) {
|
|
265
|
-
hasCheckpoints = true;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
423
|
// Parse files_modified (underscore is canonical; also accept hyphenated for compat)
|
|
269
424
|
let filesModified = [];
|
|
270
425
|
const fmFiles = fm['files_modified'] || fm['files-modified'];
|
|
@@ -272,29 +427,130 @@ function cmdPhasePlanIndex(cwd, phase, raw) {
|
|
|
272
427
|
filesModified = Array.isArray(fmFiles) ? fmFiles : [fmFiles];
|
|
273
428
|
}
|
|
274
429
|
|
|
275
|
-
const hasSummary = completedPlanIds.has(planId);
|
|
276
|
-
if (!hasSummary) {
|
|
277
|
-
incomplete.push(planId);
|
|
278
|
-
}
|
|
430
|
+
const hasSummary = completedPlanIds.has(planId) || completedPlanIds.has(extractCanonicalPlanId(planFile));
|
|
279
431
|
|
|
280
|
-
|
|
432
|
+
rawPlans.push({
|
|
281
433
|
id: planId,
|
|
282
|
-
|
|
434
|
+
declaredWave,
|
|
435
|
+
dependsOn,
|
|
283
436
|
autonomous,
|
|
284
437
|
objective: extractObjective(content) || fm.objective || null,
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
438
|
+
filesModified,
|
|
439
|
+
taskCount,
|
|
440
|
+
hasSummary,
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// ── Pass 2: topological level assignment via depends_on DAG ──────────────
|
|
445
|
+
|
|
446
|
+
// Build a map from plan ID → raw plan for fast lookup.
|
|
447
|
+
// Deps that reference plans outside this phase are treated as external and ignored.
|
|
448
|
+
const planMap = new Map(rawPlans.map(p => [p.id, p]));
|
|
449
|
+
// Secondary index: canonical prefix → full plan ID, so depends_on: ['03-01'] resolves
|
|
450
|
+
// to '03-01-auth-hardening-PLAN.md'-derived ID '03-01-auth-hardening' (k015).
|
|
451
|
+
const canonicalToId = new Map(rawPlans.map(p => [extractCanonicalPlanId(p.id), p.id]));
|
|
452
|
+
|
|
453
|
+
// Kahn's algorithm — compute in-degree and adjacency for in-phase deps only.
|
|
454
|
+
const level = new Map();
|
|
455
|
+
const inDeg = new Map();
|
|
456
|
+
const adj = new Map();
|
|
457
|
+
|
|
458
|
+
for (const p of rawPlans) {
|
|
459
|
+
if (!inDeg.has(p.id)) inDeg.set(p.id, 0);
|
|
460
|
+
if (!adj.has(p.id)) adj.set(p.id, []);
|
|
461
|
+
for (const dep of p.dependsOn) {
|
|
462
|
+
// Accept both full-stem ('03-01-auth-hardening') and canonical-prefix ('03-01') forms.
|
|
463
|
+
const resolvedDep = planMap.has(dep) ? dep : canonicalToId.get(dep);
|
|
464
|
+
if (!resolvedDep) continue; // external dep — ignore
|
|
465
|
+
if (!adj.has(resolvedDep)) adj.set(resolvedDep, []);
|
|
466
|
+
adj.get(resolvedDep).push(p.id);
|
|
467
|
+
inDeg.set(p.id, (inDeg.get(p.id) ?? 0) + 1);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// Start with nodes that have no in-phase dependencies.
|
|
472
|
+
const queue = [];
|
|
473
|
+
for (const p of rawPlans) {
|
|
474
|
+
if ((inDeg.get(p.id) ?? 0) === 0) {
|
|
475
|
+
queue.push(p.id);
|
|
476
|
+
level.set(p.id, 0);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
let visited = 0;
|
|
481
|
+
while (queue.length > 0) {
|
|
482
|
+
const cur = queue.shift();
|
|
483
|
+
visited++;
|
|
484
|
+
const curLevel = level.get(cur);
|
|
485
|
+
for (const dep of (adj.get(cur) ?? [])) {
|
|
486
|
+
const newLevel = curLevel + 1;
|
|
487
|
+
if (newLevel > (level.get(dep) ?? -1)) {
|
|
488
|
+
level.set(dep, newLevel);
|
|
489
|
+
}
|
|
490
|
+
inDeg.set(dep, inDeg.get(dep) - 1);
|
|
491
|
+
if (inDeg.get(dep) === 0) {
|
|
492
|
+
queue.push(dep);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// Cycle detection — any node not visited has a cycle.
|
|
498
|
+
if (visited < rawPlans.length) {
|
|
499
|
+
const cycleNodes = rawPlans.filter(p => !level.has(p.id)).map(p => p.id);
|
|
500
|
+
error(`depends_on cycle detected in phase ${normalized} — cycle involves: ${cycleNodes.join(', ')}`);
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// ── Pass 3: determine lowest bucket key and build output ─────────────────
|
|
505
|
+
|
|
506
|
+
// If any plan has declared wave: 0, the lowest level maps to "0"; otherwise "1".
|
|
507
|
+
const anyWaveZero = rawPlans.some(p => p.declaredWave === 0);
|
|
508
|
+
const levelOffset = anyWaveZero ? 0 : 1;
|
|
509
|
+
|
|
510
|
+
const plans = [];
|
|
511
|
+
const waves = {};
|
|
512
|
+
const incomplete = [];
|
|
513
|
+
let hasCheckpoints = false;
|
|
514
|
+
const warnings = [];
|
|
515
|
+
|
|
516
|
+
for (const raw of rawPlans) {
|
|
517
|
+
if (!raw.autonomous) {
|
|
518
|
+
hasCheckpoints = true;
|
|
519
|
+
}
|
|
520
|
+
if (!raw.hasSummary) {
|
|
521
|
+
incomplete.push(raw.id);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// Computed wave = topological level + offset (so lowest level → 0 or 1).
|
|
525
|
+
const computedWave = (level.get(raw.id) ?? 0) + levelOffset;
|
|
526
|
+
|
|
527
|
+
// The effective wave used for bucketing is always the computed topo level.
|
|
528
|
+
// If the plan declared a wave that disagrees, emit a non-fatal warning.
|
|
529
|
+
const effectiveWave = computedWave;
|
|
530
|
+
if (raw.declaredWave !== null && raw.declaredWave !== computedWave) {
|
|
531
|
+
warnings.push(
|
|
532
|
+
`Plan ${raw.id}: declared wave: ${raw.declaredWave} but depends_on DAG places it in wave ${computedWave}`,
|
|
533
|
+
);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
const plan = {
|
|
537
|
+
id: raw.id,
|
|
538
|
+
wave: effectiveWave,
|
|
539
|
+
depends_on: raw.dependsOn,
|
|
540
|
+
autonomous: raw.autonomous,
|
|
541
|
+
objective: raw.objective,
|
|
542
|
+
files_modified: raw.filesModified,
|
|
543
|
+
task_count: raw.taskCount,
|
|
544
|
+
has_summary: raw.hasSummary,
|
|
288
545
|
};
|
|
289
546
|
|
|
290
547
|
plans.push(plan);
|
|
291
548
|
|
|
292
|
-
|
|
293
|
-
const waveKey = String(wave);
|
|
549
|
+
const waveKey = String(effectiveWave);
|
|
294
550
|
if (!waves[waveKey]) {
|
|
295
551
|
waves[waveKey] = [];
|
|
296
552
|
}
|
|
297
|
-
waves[waveKey].push(
|
|
553
|
+
waves[waveKey].push(raw.id);
|
|
298
554
|
}
|
|
299
555
|
|
|
300
556
|
const result = {
|
|
@@ -304,6 +560,8 @@ function cmdPhasePlanIndex(cwd, phase, raw) {
|
|
|
304
560
|
incomplete,
|
|
305
561
|
has_checkpoints: hasCheckpoints,
|
|
306
562
|
};
|
|
563
|
+
if (planNamingWarning) result.warning = planNamingWarning;
|
|
564
|
+
if (warnings.length > 0) result.warnings = warnings;
|
|
307
565
|
|
|
308
566
|
output(result, raw);
|
|
309
567
|
}
|
|
@@ -319,53 +577,81 @@ function cmdPhaseAdd(cwd, description, raw, customId) {
|
|
|
319
577
|
error('ROADMAP.md not found');
|
|
320
578
|
}
|
|
321
579
|
|
|
322
|
-
const rawContent = fs.readFileSync(roadmapPath, 'utf-8');
|
|
323
|
-
const content = extractCurrentMilestone(rawContent, cwd);
|
|
324
580
|
const slug = generateSlugInternal(description);
|
|
325
581
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
// Custom phase naming: use provided ID or generate from description
|
|
331
|
-
newPhaseId = customId || slug.toUpperCase().replace(/-/g, '-');
|
|
332
|
-
if (!newPhaseId) error('--id required when phase_naming is "custom"');
|
|
333
|
-
dirName = `${newPhaseId}-${slug}`;
|
|
334
|
-
} else {
|
|
335
|
-
// Sequential mode: find highest integer phase number (in current milestone only)
|
|
336
|
-
const phasePattern = /#{2,4}\s*Phase\s+(\d+)[A-Z]?(?:\.\d+)*:/gi;
|
|
337
|
-
let maxPhase = 0;
|
|
338
|
-
let m;
|
|
339
|
-
while ((m = phasePattern.exec(content)) !== null) {
|
|
340
|
-
const num = parseInt(m[1], 10);
|
|
341
|
-
if (num > maxPhase) maxPhase = num;
|
|
342
|
-
}
|
|
582
|
+
// Wrap entire read-modify-write in lock to prevent concurrent corruption
|
|
583
|
+
const { newPhaseId, dirName } = withPlanningLock(cwd, () => {
|
|
584
|
+
const rawContent = fs.readFileSync(roadmapPath, 'utf-8');
|
|
585
|
+
const content = extractCurrentMilestone(rawContent, cwd);
|
|
343
586
|
|
|
344
|
-
|
|
345
|
-
const
|
|
346
|
-
|
|
347
|
-
|
|
587
|
+
// Optional project code prefix (e.g., 'CK' → 'CK-01-foundation')
|
|
588
|
+
const projectCode = config.project_code || '';
|
|
589
|
+
const prefix = projectCode ? `${projectCode}-` : '';
|
|
590
|
+
|
|
591
|
+
let _newPhaseId;
|
|
592
|
+
let _dirName;
|
|
593
|
+
|
|
594
|
+
if (customId || config.phase_naming === 'custom') {
|
|
595
|
+
// Custom phase naming: use provided ID or generate from description
|
|
596
|
+
_newPhaseId = customId || slug.toUpperCase().replace(/-/g, '-');
|
|
597
|
+
if (!_newPhaseId) error('--id required when phase_naming is "custom"');
|
|
598
|
+
_dirName = `${prefix}${_newPhaseId}-${slug}`;
|
|
599
|
+
} else {
|
|
600
|
+
// Sequential mode: find highest integer phase number from two sources:
|
|
601
|
+
// 1. ROADMAP.md (current milestone only)
|
|
602
|
+
// 2. .planning/phases/ on disk (orphan directories not tracked in roadmap)
|
|
603
|
+
// Skip 999.x backlog phases — they live outside the active sequence
|
|
604
|
+
const phasePattern = /#{2,4}\s*Phase\s+(\d+)[A-Z]?(?:\.\d+)*:/gi;
|
|
605
|
+
let maxPhase = 0;
|
|
606
|
+
let m;
|
|
607
|
+
while ((m = phasePattern.exec(content)) !== null) {
|
|
608
|
+
const num = parseInt(m[1], 10);
|
|
609
|
+
if (num >= 999) continue; // backlog phases use 999.x numbering
|
|
610
|
+
if (num > maxPhase) maxPhase = num;
|
|
611
|
+
}
|
|
348
612
|
|
|
349
|
-
|
|
613
|
+
// Also scan .planning/phases/ for orphan directories not tracked in ROADMAP.
|
|
614
|
+
// Directory names follow: [PREFIX-]NN-slug (e.g. 03-api or CK-05-old-feature).
|
|
615
|
+
// Strip the optional project_code prefix before extracting the leading integer.
|
|
616
|
+
const phasesOnDisk = path.join(planningDir(cwd), 'phases');
|
|
617
|
+
if (fs.existsSync(phasesOnDisk)) {
|
|
618
|
+
const dirNumPattern = /^(?:[A-Z][A-Z0-9]*-)?(\d+)-/;
|
|
619
|
+
for (const entry of fs.readdirSync(phasesOnDisk)) {
|
|
620
|
+
const match = entry.match(dirNumPattern);
|
|
621
|
+
if (!match) continue;
|
|
622
|
+
const num = parseInt(match[1], 10);
|
|
623
|
+
if (num >= 999) continue; // skip backlog orphans
|
|
624
|
+
if (num > maxPhase) maxPhase = num;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
350
627
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
628
|
+
_newPhaseId = maxPhase + 1;
|
|
629
|
+
const paddedNum = String(_newPhaseId).padStart(2, '0');
|
|
630
|
+
_dirName = `${prefix}${paddedNum}-${slug}`;
|
|
631
|
+
}
|
|
354
632
|
|
|
355
|
-
|
|
356
|
-
const dependsOn = config.phase_naming === 'custom' ? '' : `\n**Depends on:** Phase ${typeof newPhaseId === 'number' ? newPhaseId - 1 : 'TBD'}`;
|
|
357
|
-
const phaseEntry = `\n### Phase ${newPhaseId}: ${description}\n\n**Goal:** [To be planned]\n**Requirements**: TBD${dependsOn}\n**Plans:** 0 plans\n\nPlans:\n- [ ] TBD (run /sdd:plan-phase ${newPhaseId} to break down)\n`;
|
|
633
|
+
const dirPath = path.join(planningDir(cwd), 'phases', _dirName);
|
|
358
634
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
if (lastSeparator > 0) {
|
|
363
|
-
updatedContent = rawContent.slice(0, lastSeparator) + phaseEntry + rawContent.slice(lastSeparator);
|
|
364
|
-
} else {
|
|
365
|
-
updatedContent = rawContent + phaseEntry;
|
|
366
|
-
}
|
|
635
|
+
// Create directory with .gitkeep so git tracks empty folders
|
|
636
|
+
platformEnsureDir(dirPath);
|
|
637
|
+
platformWriteSync(path.join(dirPath, '.gitkeep'), '');
|
|
367
638
|
|
|
368
|
-
|
|
639
|
+
// Build phase entry
|
|
640
|
+
const dependsOn = config.phase_naming === 'custom' ? '' : `\n**Depends on:** Phase ${typeof _newPhaseId === 'number' ? _newPhaseId - 1 : 'TBD'}`;
|
|
641
|
+
const phaseEntry = `\n### Phase ${_newPhaseId}: ${description}\n\n**Goal:** [To be planned]\n**Requirements**: TBD${dependsOn}\n**Plans:** 0 plans\n\nPlans:\n- [ ] TBD (run /sdd:plan-phase ${_newPhaseId} to break down)\n`;
|
|
642
|
+
|
|
643
|
+
// Find insertion point: before last "---" or at end
|
|
644
|
+
let updatedContent;
|
|
645
|
+
const lastSeparator = rawContent.lastIndexOf('\n---');
|
|
646
|
+
if (lastSeparator > 0) {
|
|
647
|
+
updatedContent = rawContent.slice(0, lastSeparator) + phaseEntry + rawContent.slice(lastSeparator);
|
|
648
|
+
} else {
|
|
649
|
+
updatedContent = rawContent + phaseEntry;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
platformWriteSync(roadmapPath, updatedContent);
|
|
653
|
+
return { newPhaseId: _newPhaseId, dirName: _dirName };
|
|
654
|
+
});
|
|
369
655
|
|
|
370
656
|
const result = {
|
|
371
657
|
phase_number: typeof newPhaseId === 'number' ? newPhaseId : String(newPhaseId),
|
|
@@ -379,6 +665,76 @@ function cmdPhaseAdd(cwd, description, raw, customId) {
|
|
|
379
665
|
output(result, raw, result.padded);
|
|
380
666
|
}
|
|
381
667
|
|
|
668
|
+
function cmdPhaseAddBatch(cwd, descriptions, raw) {
|
|
669
|
+
if (!Array.isArray(descriptions) || descriptions.length === 0) {
|
|
670
|
+
error('descriptions array required for phase add-batch');
|
|
671
|
+
}
|
|
672
|
+
const config = loadConfig(cwd);
|
|
673
|
+
const roadmapPath = path.join(planningDir(cwd), 'ROADMAP.md');
|
|
674
|
+
if (!fs.existsSync(roadmapPath)) { error('ROADMAP.md not found'); }
|
|
675
|
+
const projectCode = config.project_code || '';
|
|
676
|
+
const prefix = projectCode ? `${projectCode}-` : '';
|
|
677
|
+
|
|
678
|
+
const results = withPlanningLock(cwd, () => {
|
|
679
|
+
let rawContent = fs.readFileSync(roadmapPath, 'utf-8');
|
|
680
|
+
const content = extractCurrentMilestone(rawContent, cwd);
|
|
681
|
+
let maxPhase = 0;
|
|
682
|
+
if (config.phase_naming !== 'custom') {
|
|
683
|
+
const phasePattern = /#{2,4}\s*Phase\s+(\d+)[A-Z]?(?:\.\d+)*:/gi;
|
|
684
|
+
let m;
|
|
685
|
+
while ((m = phasePattern.exec(content)) !== null) {
|
|
686
|
+
const num = parseInt(m[1], 10);
|
|
687
|
+
if (num >= 999) continue;
|
|
688
|
+
if (num > maxPhase) maxPhase = num;
|
|
689
|
+
}
|
|
690
|
+
const phasesOnDisk = path.join(planningDir(cwd), 'phases');
|
|
691
|
+
if (fs.existsSync(phasesOnDisk)) {
|
|
692
|
+
const dirNumPattern = /^(?:[A-Z][A-Z0-9]*-)?(\d+)-/;
|
|
693
|
+
for (const entry of fs.readdirSync(phasesOnDisk)) {
|
|
694
|
+
const match = entry.match(dirNumPattern);
|
|
695
|
+
if (!match) continue;
|
|
696
|
+
const num = parseInt(match[1], 10);
|
|
697
|
+
if (num >= 999) continue;
|
|
698
|
+
if (num > maxPhase) maxPhase = num;
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
const added = [];
|
|
703
|
+
for (const description of descriptions) {
|
|
704
|
+
const slug = generateSlugInternal(description);
|
|
705
|
+
let newPhaseId, dirName;
|
|
706
|
+
if (config.phase_naming === 'custom') {
|
|
707
|
+
newPhaseId = slug.toUpperCase().replace(/-/g, '-');
|
|
708
|
+
dirName = `${prefix}${newPhaseId}-${slug}`;
|
|
709
|
+
} else {
|
|
710
|
+
maxPhase += 1;
|
|
711
|
+
newPhaseId = maxPhase;
|
|
712
|
+
dirName = `${prefix}${String(newPhaseId).padStart(2, '0')}-${slug}`;
|
|
713
|
+
}
|
|
714
|
+
const dirPath = path.join(planningDir(cwd), 'phases', dirName);
|
|
715
|
+
platformEnsureDir(dirPath);
|
|
716
|
+
platformWriteSync(path.join(dirPath, '.gitkeep'), '');
|
|
717
|
+
const dependsOn = config.phase_naming === 'custom' ? '' : `\n**Depends on:** Phase ${typeof newPhaseId === 'number' ? newPhaseId - 1 : 'TBD'}`;
|
|
718
|
+
const phaseEntry = `\n### Phase ${newPhaseId}: ${description}\n\n**Goal:** [To be planned]\n**Requirements**: TBD${dependsOn}\n**Plans:** 0 plans\n\nPlans:\n- [ ] TBD (run /sdd:plan-phase ${newPhaseId} to break down)\n`;
|
|
719
|
+
const lastSeparator = rawContent.lastIndexOf('\n---');
|
|
720
|
+
rawContent = lastSeparator > 0
|
|
721
|
+
? rawContent.slice(0, lastSeparator) + phaseEntry + rawContent.slice(lastSeparator)
|
|
722
|
+
: rawContent + phaseEntry;
|
|
723
|
+
added.push({
|
|
724
|
+
phase_number: typeof newPhaseId === 'number' ? newPhaseId : String(newPhaseId),
|
|
725
|
+
padded: typeof newPhaseId === 'number' ? String(newPhaseId).padStart(2, '0') : String(newPhaseId),
|
|
726
|
+
name: description,
|
|
727
|
+
slug,
|
|
728
|
+
directory: toPosixPath(path.join(path.relative(cwd, planningDir(cwd)), 'phases', dirName)),
|
|
729
|
+
naming_mode: config.phase_naming,
|
|
730
|
+
});
|
|
731
|
+
}
|
|
732
|
+
platformWriteSync(roadmapPath, rawContent);
|
|
733
|
+
return added;
|
|
734
|
+
});
|
|
735
|
+
output({ phases: results, count: results.length }, raw);
|
|
736
|
+
}
|
|
737
|
+
|
|
382
738
|
function cmdPhaseInsert(cwd, afterPhase, description, raw) {
|
|
383
739
|
if (!afterPhase || !description) {
|
|
384
740
|
error('after-phase and description required for phase insert');
|
|
@@ -389,66 +745,91 @@ function cmdPhaseInsert(cwd, afterPhase, description, raw) {
|
|
|
389
745
|
error('ROADMAP.md not found');
|
|
390
746
|
}
|
|
391
747
|
|
|
392
|
-
const rawContent = fs.readFileSync(roadmapPath, 'utf-8');
|
|
393
|
-
const content = extractCurrentMilestone(rawContent, cwd);
|
|
394
748
|
const slug = generateSlugInternal(description);
|
|
395
749
|
|
|
396
|
-
//
|
|
397
|
-
const
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
const decimalPattern = new RegExp(`^${normalizedBase}\\.(\\d+)`);
|
|
414
|
-
for (const dir of dirs) {
|
|
415
|
-
const dm = dir.match(decimalPattern);
|
|
416
|
-
if (dm) existingDecimals.push(parseInt(dm[1], 10));
|
|
750
|
+
// Wrap entire read-modify-write in lock to prevent concurrent corruption
|
|
751
|
+
const { decimalPhase, dirName } = withPlanningLock(cwd, () => {
|
|
752
|
+
const rawContent = fs.readFileSync(roadmapPath, 'utf-8');
|
|
753
|
+
const content = extractCurrentMilestone(rawContent, cwd);
|
|
754
|
+
|
|
755
|
+
// Normalize input then route through canonical padding-tolerant fragment
|
|
756
|
+
// (#3537). The prior hand-rolled `0*${unpadded}` worked for the integer
|
|
757
|
+
// base but duplicated logic — funnel it through the shared helper.
|
|
758
|
+
const normalizedAfter = normalizePhaseName(afterPhase);
|
|
759
|
+
const afterPhaseEscaped = phaseMarkdownRegexSource(normalizedAfter);
|
|
760
|
+
const targetPattern = new RegExp(`#{2,4}\\s*Phase\\s+${afterPhaseEscaped}:`, 'i');
|
|
761
|
+
if (!targetPattern.test(content)) {
|
|
762
|
+
const checklistPattern = new RegExp(`-\\s*\\[[ x]\\]\\s*\\*\\*Phase\\s+${afterPhaseEscaped}:`, 'i');
|
|
763
|
+
if (checklistPattern.test(content)) {
|
|
764
|
+
error(`Phase ${afterPhase} exists in roadmap summary but is missing a detail section (### Phase ${afterPhase}: ...).`);
|
|
765
|
+
}
|
|
766
|
+
error(`Phase ${afterPhase} not found in ROADMAP.md`);
|
|
417
767
|
}
|
|
418
|
-
} catch { /* intentionally empty */ }
|
|
419
768
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
769
|
+
// Calculate next decimal by scanning both directories AND ROADMAP.md entries
|
|
770
|
+
const phasesDir = path.join(planningDir(cwd), 'phases');
|
|
771
|
+
const normalizedBase = normalizePhaseName(afterPhase);
|
|
772
|
+
const decimalSet = new Set();
|
|
424
773
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
774
|
+
try {
|
|
775
|
+
const entries = fs.readdirSync(phasesDir, { withFileTypes: true });
|
|
776
|
+
const dirs = entries.filter(e => e.isDirectory()).map(e => e.name);
|
|
777
|
+
const decimalPattern = new RegExp(`^(?:[A-Z]{1,6}-)?${escapeRegex(normalizedBase)}\\.(\\d+)`);
|
|
778
|
+
for (const dir of dirs) {
|
|
779
|
+
const dm = dir.match(decimalPattern);
|
|
780
|
+
if (dm) decimalSet.add(parseInt(dm[1], 10));
|
|
781
|
+
}
|
|
782
|
+
} catch { /* intentionally empty */ }
|
|
428
783
|
|
|
429
|
-
|
|
430
|
-
|
|
784
|
+
// Also scan ROADMAP.md content (already loaded) for decimal entries.
|
|
785
|
+
// #3537: padding-tolerant fragment so un-padded `Phase 2.7:` is found
|
|
786
|
+
// when caller passes the padded base `02`.
|
|
787
|
+
const rmPhasePattern = new RegExp(
|
|
788
|
+
`#{2,4}\\s*Phase\\s+${phaseMarkdownRegexSource(normalizedBase)}\\.(\\d+)\\s*:`, 'gi'
|
|
789
|
+
);
|
|
790
|
+
let rmMatch;
|
|
791
|
+
while ((rmMatch = rmPhasePattern.exec(rawContent)) !== null) {
|
|
792
|
+
decimalSet.add(parseInt(rmMatch[1], 10));
|
|
793
|
+
}
|
|
431
794
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
795
|
+
const nextDecimal = decimalSet.size === 0 ? 1 : Math.max(...decimalSet) + 1;
|
|
796
|
+
const _decimalPhase = `${normalizedBase}.${nextDecimal}`;
|
|
797
|
+
// Optional project code prefix
|
|
798
|
+
const insertConfig = loadConfig(cwd);
|
|
799
|
+
const projectCode = insertConfig.project_code || '';
|
|
800
|
+
const pfx = projectCode ? `${projectCode}-` : '';
|
|
801
|
+
const _dirName = `${pfx}${_decimalPhase}-${slug}`;
|
|
802
|
+
const dirPath = path.join(planningDir(cwd), 'phases', _dirName);
|
|
803
|
+
|
|
804
|
+
// Create directory with .gitkeep so git tracks empty folders
|
|
805
|
+
platformEnsureDir(dirPath);
|
|
806
|
+
platformWriteSync(path.join(dirPath, '.gitkeep'), '');
|
|
807
|
+
|
|
808
|
+
// Build phase entry
|
|
809
|
+
const phaseEntry = `\n### Phase ${_decimalPhase}: ${description} (INSERTED)\n\n**Goal:** [Urgent work - to be planned]\n**Requirements**: TBD\n**Depends on:** Phase ${afterPhase}\n**Plans:** 0 plans\n\nPlans:\n- [ ] TBD (run /sdd:plan-phase ${_decimalPhase} to break down)\n`;
|
|
810
|
+
|
|
811
|
+
// Insert after the target phase section
|
|
812
|
+
const headerPattern = new RegExp(`(#{2,4}\\s*Phase\\s+${afterPhaseEscaped}:[^\\n]*\\n)`, 'i');
|
|
813
|
+
const headerMatch = rawContent.match(headerPattern);
|
|
814
|
+
if (!headerMatch) {
|
|
815
|
+
error(`Could not find Phase ${afterPhase} header`);
|
|
816
|
+
}
|
|
438
817
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
818
|
+
const headerIdx = rawContent.indexOf(headerMatch[0]);
|
|
819
|
+
const afterHeader = rawContent.slice(headerIdx + headerMatch[0].length);
|
|
820
|
+
const nextPhaseMatch = afterHeader.match(/\n#{2,4}\s+Phase\s+\d/i);
|
|
442
821
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
822
|
+
let insertIdx;
|
|
823
|
+
if (nextPhaseMatch) {
|
|
824
|
+
insertIdx = headerIdx + headerMatch[0].length + nextPhaseMatch.index;
|
|
825
|
+
} else {
|
|
826
|
+
insertIdx = rawContent.length;
|
|
827
|
+
}
|
|
449
828
|
|
|
450
|
-
|
|
451
|
-
|
|
829
|
+
const updatedContent = rawContent.slice(0, insertIdx) + phaseEntry + rawContent.slice(insertIdx);
|
|
830
|
+
platformWriteSync(roadmapPath, updatedContent);
|
|
831
|
+
return { decimalPhase: _decimalPhase, dirName: _dirName };
|
|
832
|
+
});
|
|
452
833
|
|
|
453
834
|
const result = {
|
|
454
835
|
phase_number: decimalPhase,
|
|
@@ -468,10 +849,12 @@ function cmdPhaseInsert(cwd, afterPhase, description, raw) {
|
|
|
468
849
|
*/
|
|
469
850
|
function renameDecimalPhases(phasesDir, baseInt, removedDecimal) {
|
|
470
851
|
const renamedDirs = [], renamedFiles = [];
|
|
471
|
-
|
|
852
|
+
// Capture the zero-padded prefix (e.g. "06" from "06.3-slug") so the renamed
|
|
853
|
+
// directory preserves the original padding format.
|
|
854
|
+
const decPattern = new RegExp(`^(0*${baseInt})\\.(\\d+)-(.+)$`);
|
|
472
855
|
const dirs = readSubdirectories(phasesDir, true);
|
|
473
856
|
const toRename = dirs
|
|
474
|
-
.map(dir => { const m = dir.match(decPattern); return m ? { dir, oldDecimal: parseInt(m[
|
|
857
|
+
.map(dir => { const m = dir.match(decPattern); return m ? { dir, prefix: m[1], oldDecimal: parseInt(m[2], 10), slug: m[3] } : null; })
|
|
475
858
|
.filter(item => item && item.oldDecimal > removedDecimal)
|
|
476
859
|
.sort((a, b) => b.oldDecimal - a.oldDecimal); // descending to avoid conflicts
|
|
477
860
|
|
|
@@ -479,7 +862,7 @@ function renameDecimalPhases(phasesDir, baseInt, removedDecimal) {
|
|
|
479
862
|
const newDecimal = item.oldDecimal - 1;
|
|
480
863
|
const oldPhaseId = `${baseInt}.${item.oldDecimal}`;
|
|
481
864
|
const newPhaseId = `${baseInt}.${newDecimal}`;
|
|
482
|
-
const newDirName = `${
|
|
865
|
+
const newDirName = `${item.prefix}.${newDecimal}-${item.slug}`;
|
|
483
866
|
fs.renameSync(path.join(phasesDir, item.dir), path.join(phasesDir, newDirName));
|
|
484
867
|
renamedDirs.push({ from: item.dir, to: newDirName });
|
|
485
868
|
for (const f of fs.readdirSync(path.join(phasesDir, newDirName))) {
|
|
@@ -506,7 +889,7 @@ function renameIntegerPhases(phasesDir, removedInt) {
|
|
|
506
889
|
const m = dir.match(/^(\d+)([A-Z])?(?:\.(\d+))?-(.+)$/i);
|
|
507
890
|
if (!m) return null;
|
|
508
891
|
const dirInt = parseInt(m[1], 10);
|
|
509
|
-
return dirInt > removedInt ? { dir, oldInt: dirInt, letter: m[2] ? m[2].toUpperCase() : '', decimal: m[3] ? parseInt(m[3], 10) : null, slug: m[4] } : null;
|
|
892
|
+
return (dirInt > removedInt && dirInt < 999) ? { dir, oldInt: dirInt, letter: m[2] ? m[2].toUpperCase() : '', decimal: m[3] ? parseInt(m[3], 10) : null, slug: m[4] } : null;
|
|
510
893
|
})
|
|
511
894
|
.filter(Boolean)
|
|
512
895
|
.sort((a, b) => a.oldInt !== b.oldInt ? b.oldInt - a.oldInt : (b.decimal || 0) - (a.decimal || 0));
|
|
@@ -533,32 +916,94 @@ function renameIntegerPhases(phasesDir, removedInt) {
|
|
|
533
916
|
return { renamedDirs, renamedFiles };
|
|
534
917
|
}
|
|
535
918
|
|
|
919
|
+
function decrementRoadmapPhaseNumber(raw, removedInt) {
|
|
920
|
+
const num = parseInt(raw, 10);
|
|
921
|
+
if (!Number.isInteger(num) || num <= removedInt || num >= 999) return raw;
|
|
922
|
+
return String(num - 1);
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
function decrementRoadmapPhaseToken(raw, removedInt) {
|
|
926
|
+
const match = String(raw).match(/^(\d+)(\.\d+)?$/);
|
|
927
|
+
if (!match) return raw;
|
|
928
|
+
const num = parseInt(match[1], 10);
|
|
929
|
+
if (!Number.isInteger(num) || num <= removedInt || num >= 999) return raw;
|
|
930
|
+
return `${num - 1}${match[2] || ''}`;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
function decrementRoadmapPaddedPhaseNumber(raw, removedInt) {
|
|
934
|
+
const num = parseInt(raw, 10);
|
|
935
|
+
if (!Number.isInteger(num) || num <= removedInt || num >= 999) return raw;
|
|
936
|
+
return String(num - 1).padStart(raw.length, '0');
|
|
937
|
+
}
|
|
938
|
+
|
|
536
939
|
/**
|
|
537
940
|
* Remove a phase section from ROADMAP.md and renumber all subsequent integer phases.
|
|
538
941
|
*/
|
|
539
|
-
function updateRoadmapAfterPhaseRemoval(roadmapPath, targetPhase, isDecimal, removedInt) {
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
942
|
+
function updateRoadmapAfterPhaseRemoval(roadmapPath, targetPhase, isDecimal, removedInt, cwd) {
|
|
943
|
+
// Wrap entire read-modify-write in lock to prevent concurrent corruption
|
|
944
|
+
withPlanningLock(cwd, () => {
|
|
945
|
+
let content = fs.readFileSync(roadmapPath, 'utf-8');
|
|
946
|
+
const escaped = escapeRegex(targetPhase);
|
|
947
|
+
|
|
948
|
+
// #3601: the end-of-section lookahead is depth-aware. It captures the
|
|
949
|
+
// hash count of the header being removed and stops only at a subsequent
|
|
950
|
+
// header of the SAME depth, whether integer or decimal. This preserves
|
|
951
|
+
// two existing contracts:
|
|
952
|
+
//
|
|
953
|
+
// (#3601 case) Remove `### Phase 2:` and stop at `### Phase 2.1:` —
|
|
954
|
+
// `Phase 2.1` is a peer-level decimal phase (depth 3) and must be
|
|
955
|
+
// preserved.
|
|
956
|
+
//
|
|
957
|
+
// (#3355 case) Remove `### Phase 27:` and continue past
|
|
958
|
+
// `#### Phase 27.1:` (depth 4 — a child of Phase 27) until the next
|
|
959
|
+
// depth-3 header. The child decimal is part of the integer phase
|
|
960
|
+
// being removed.
|
|
961
|
+
//
|
|
962
|
+
// The `(?!#)` negative lookahead after the backreference prevents the
|
|
963
|
+
// depth-3 match from being satisfied by a depth-4+ header that starts
|
|
964
|
+
// with the same three hashes.
|
|
965
|
+
content = content.replace(new RegExp(`\\n?(?<h>#{2,4})\\s*Phase\\s+${escaped}\\s*:[\\s\\S]*?(?=\\n\\k<h>(?!#)\\s+Phase\\s+[^\\n:]+\\s*:|$)`, 'i'), '');
|
|
966
|
+
content = content.replace(new RegExp(`\\n?-\\s*\\[[ x]\\]\\s*.*Phase\\s+${escaped}[:\\s][^\\n]*`, 'gi'), '');
|
|
967
|
+
content = content.replace(new RegExp(`\\n?\\|\\s*${escaped}\\.?\\s[^|]*\\|[^\\n]*`, 'gi'), '');
|
|
968
|
+
|
|
969
|
+
if (!isDecimal) {
|
|
970
|
+
content = content.replace(
|
|
971
|
+
/(#{2,4}\s*Phase\s+)(\d+(?:\.\d+)?)(\s*:)/gi,
|
|
972
|
+
(_match, prefix, num, suffix) => `${prefix}${decrementRoadmapPhaseToken(num, removedInt)}${suffix}`
|
|
973
|
+
);
|
|
974
|
+
content = content.replace(
|
|
975
|
+
/(-\s*\[[ x]\]\s*.*?Phase\s+)(\d+)(\s*:|\s+)/gi,
|
|
976
|
+
(_match, prefix, num, suffix) => `${prefix}${decrementRoadmapPhaseNumber(num, removedInt)}${suffix}`
|
|
977
|
+
);
|
|
978
|
+
content = content.replace(
|
|
979
|
+
/(\|\s*)(\d+)(\.\s)/g,
|
|
980
|
+
(_match, prefix, num, suffix) => `${prefix}${decrementRoadmapPhaseNumber(num, removedInt)}${suffix}`
|
|
981
|
+
);
|
|
982
|
+
// #3602: extend the suffix lookahead so slugged plan filenames like
|
|
983
|
+
// `07-01-cherry-pick-foundation-PLAN.md` match too. The previous
|
|
984
|
+
// pattern only allowed a compact `-(PLAN|SUMMARY).md` immediately
|
|
985
|
+
// after the plan number (or no suffix at all); a slug between the
|
|
986
|
+
// number and the `-PLAN.md` / `-SUMMARY.md` suffix made the
|
|
987
|
+
// lookahead fail and left the stale `07-01-` prefix in ROADMAP
|
|
988
|
+
// text while the on-disk file was already renamed to `06-01-…`.
|
|
989
|
+
// The slug segment `(?:-[A-Za-z][A-Za-z0-9-]*)*` allows any number
|
|
990
|
+
// of kebab-case tokens before the canonical PLAN/SUMMARY suffix.
|
|
991
|
+
content = content.replace(
|
|
992
|
+
/(?<![0-9-])(\d{2})-(\d{2})(?=(?:(?:-[A-Za-z][A-Za-z0-9-]*)*-(?:PLAN|SUMMARY)\.md)|(?![0-9-]))/g,
|
|
993
|
+
(_match, phaseNum, planNum) => `${decrementRoadmapPaddedPhaseNumber(phaseNum, removedInt)}-${planNum}`
|
|
994
|
+
);
|
|
995
|
+
content = content.replace(
|
|
996
|
+
/(\*\*Depends on\*\*\s*:\s*Phase\s+)(\d+(?:\.\d+)?)\b/gi,
|
|
997
|
+
(_match, prefix, num) => `${prefix}${decrementRoadmapPhaseToken(num, removedInt)}`
|
|
998
|
+
);
|
|
999
|
+
content = content.replace(
|
|
1000
|
+
/(Depends on:\*\*\s*Phase\s+)(\d+(?:\.\d+)?)\b/gi,
|
|
1001
|
+
(_match, prefix, num) => `${prefix}${decrementRoadmapPhaseToken(num, removedInt)}`
|
|
1002
|
+
);
|
|
558
1003
|
}
|
|
559
|
-
}
|
|
560
1004
|
|
|
561
|
-
|
|
1005
|
+
platformWriteSync(roadmapPath, content);
|
|
1006
|
+
});
|
|
562
1007
|
}
|
|
563
1008
|
|
|
564
1009
|
function cmdPhaseRemove(cwd, targetPhase, options, raw) {
|
|
@@ -575,7 +1020,7 @@ function cmdPhaseRemove(cwd, targetPhase, options, raw) {
|
|
|
575
1020
|
|
|
576
1021
|
// Find target directory
|
|
577
1022
|
const targetDir = readSubdirectories(phasesDir, true)
|
|
578
|
-
.find(d =>
|
|
1023
|
+
.find(d => phaseTokenMatches(d, normalized)) || null;
|
|
579
1024
|
|
|
580
1025
|
// Guard against removing executed work
|
|
581
1026
|
if (targetDir && !force) {
|
|
@@ -592,28 +1037,29 @@ function cmdPhaseRemove(cwd, targetPhase, options, raw) {
|
|
|
592
1037
|
let renamedDirs = [], renamedFiles = [];
|
|
593
1038
|
try {
|
|
594
1039
|
const renamed = isDecimal
|
|
595
|
-
? renameDecimalPhases(phasesDir, normalized.split('.')[0], parseInt(normalized.split('.')[1], 10))
|
|
1040
|
+
? renameDecimalPhases(phasesDir, parseInt(normalized.split('.')[0], 10), parseInt(normalized.split('.')[1], 10))
|
|
596
1041
|
: renameIntegerPhases(phasesDir, parseInt(normalized, 10));
|
|
597
1042
|
renamedDirs = renamed.renamedDirs;
|
|
598
1043
|
renamedFiles = renamed.renamedFiles;
|
|
599
1044
|
} catch { /* intentionally empty */ }
|
|
600
1045
|
|
|
601
1046
|
// Update ROADMAP.md
|
|
602
|
-
updateRoadmapAfterPhaseRemoval(roadmapPath, targetPhase, isDecimal, parseInt(normalized, 10));
|
|
1047
|
+
updateRoadmapAfterPhaseRemoval(roadmapPath, targetPhase, isDecimal, parseInt(normalized, 10), cwd);
|
|
603
1048
|
|
|
604
|
-
// Update STATE.md phase count
|
|
1049
|
+
// Update STATE.md phase count atomically (#P4.4)
|
|
605
1050
|
const statePath = path.join(planningDir(cwd), 'STATE.md');
|
|
606
1051
|
if (fs.existsSync(statePath)) {
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
1052
|
+
readModifyWriteStateMd(statePath, (stateContent) => {
|
|
1053
|
+
const totalRaw = stateExtractField(stateContent, 'Total Phases');
|
|
1054
|
+
if (totalRaw) {
|
|
1055
|
+
stateContent = stateReplaceField(stateContent, 'Total Phases', String(parseInt(totalRaw, 10) - 1)) || stateContent;
|
|
1056
|
+
}
|
|
1057
|
+
const ofMatch = stateContent.match(/(\bof\s+)(\d+)(\s*(?:\(|phases?))/i);
|
|
1058
|
+
if (ofMatch) {
|
|
1059
|
+
stateContent = stateContent.replace(/(\bof\s+)(\d+)(\s*(?:\(|phases?))/i, `$1${parseInt(ofMatch[2], 10) - 1}$3`);
|
|
1060
|
+
}
|
|
1061
|
+
return stateContent;
|
|
1062
|
+
}, cwd);
|
|
617
1063
|
}
|
|
618
1064
|
|
|
619
1065
|
output({
|
|
@@ -668,84 +1114,147 @@ function cmdPhaseComplete(cwd, phaseNum, raw) {
|
|
|
668
1114
|
}
|
|
669
1115
|
} catch {}
|
|
670
1116
|
|
|
671
|
-
// Update ROADMAP.md
|
|
1117
|
+
// Update ROADMAP.md and REQUIREMENTS.md atomically under lock
|
|
672
1118
|
if (fs.existsSync(roadmapPath)) {
|
|
673
|
-
|
|
1119
|
+
withPlanningLock(cwd, () => {
|
|
1120
|
+
let roadmapContent = fs.readFileSync(roadmapPath, 'utf-8');
|
|
1121
|
+
|
|
1122
|
+
// Checkbox: - [ ] Phase N: → - [x] Phase N: (...completed DATE)
|
|
1123
|
+
// #3537: padding-tolerant fragment so the caller-resolved padded id
|
|
1124
|
+
// matches un-padded ROADMAP prose.
|
|
1125
|
+
const phaseEscaped = phaseMarkdownRegexSource(phaseNum);
|
|
1126
|
+
const checkboxPattern = new RegExp(
|
|
1127
|
+
`(-\\s*\\[)[ ](\\]\\s*.*Phase\\s+${phaseEscaped}[:\\s][^\\n]*)`,
|
|
1128
|
+
'i'
|
|
1129
|
+
);
|
|
1130
|
+
roadmapContent = roadmapContent.replace(checkboxPattern, `$1x$2 (completed ${today})`);
|
|
674
1131
|
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
1132
|
+
// Progress table: update Status to Complete, add date (handles 4 or 5 column tables)
|
|
1133
|
+
const tableRowPattern = new RegExp(
|
|
1134
|
+
`^(\\|\\s*${phaseEscaped}\\.?\\s[^|]*(?:\\|[^\\n]*))$`,
|
|
1135
|
+
'im'
|
|
1136
|
+
);
|
|
1137
|
+
roadmapContent = roadmapContent.replace(tableRowPattern, (fullRow) => {
|
|
1138
|
+
const cells = fullRow.split('|').slice(1, -1);
|
|
1139
|
+
if (cells.length === 5) {
|
|
1140
|
+
// 5-col: Phase | Milestone | Plans | Status | Completed
|
|
1141
|
+
cells[2] = ` ${summaryCount}/${planCount} `;
|
|
1142
|
+
cells[3] = ' Complete ';
|
|
1143
|
+
cells[4] = ` ${today} `;
|
|
1144
|
+
} else if (cells.length === 4) {
|
|
1145
|
+
// 4-col: Phase | Plans | Status | Completed
|
|
1146
|
+
cells[1] = ` ${summaryCount}/${planCount} `;
|
|
1147
|
+
cells[2] = ' Complete ';
|
|
1148
|
+
cells[3] = ` ${today} `;
|
|
1149
|
+
}
|
|
1150
|
+
return '|' + cells.join('|') + '|';
|
|
1151
|
+
});
|
|
1152
|
+
|
|
1153
|
+
// Update plan count in phase section.
|
|
1154
|
+
// Use direct .replace() rather than replaceInCurrentMilestone() so this
|
|
1155
|
+
// works when the current milestone section is itself inside a <details>
|
|
1156
|
+
// block (the standard /sdd:new-project layout). replaceInCurrentMilestone
|
|
1157
|
+
// scopes to content after the last </details>, which misses content inside
|
|
1158
|
+
// the current milestone's own <details> wrapper (#2005).
|
|
1159
|
+
// The phase-scoped heading pattern is specific enough to avoid matching
|
|
1160
|
+
// archived phases (which belong to different milestones).
|
|
1161
|
+
const planCountPattern = new RegExp(
|
|
1162
|
+
`(#{2,4}\\s*Phase\\s+${phaseEscaped}[\\s\\S]*?\\*\\*Plans:\\*\\*\\s*)[^\\n]+`,
|
|
1163
|
+
'i'
|
|
1164
|
+
);
|
|
1165
|
+
roadmapContent = roadmapContent.replace(
|
|
1166
|
+
planCountPattern,
|
|
1167
|
+
`$1${summaryCount}/${planCount} plans complete`
|
|
1168
|
+
);
|
|
681
1169
|
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
cells[4] = ` ${today} `;
|
|
694
|
-
} else if (cells.length === 4) {
|
|
695
|
-
// 4-col: Phase | Plans | Status | Completed
|
|
696
|
-
cells[2] = ' Complete ';
|
|
697
|
-
cells[3] = ` ${today} `;
|
|
1170
|
+
// Mark completed plan checkboxes (safety net for missed per-plan updates)
|
|
1171
|
+
// Handles both plain IDs ("- [ ] 01-01-PLAN.md") and bold-wrapped IDs ("- [ ] **01-01**")
|
|
1172
|
+
for (const summaryFile of phaseInfo.summaries) {
|
|
1173
|
+
const planId = summaryFile.replace('-SUMMARY.md', '').replace('SUMMARY.md', '');
|
|
1174
|
+
if (!planId) continue;
|
|
1175
|
+
const planEscaped = escapeRegex(planId);
|
|
1176
|
+
const planCheckboxPattern = new RegExp(
|
|
1177
|
+
`(-\\s*\\[) (\\]\\s*(?:\\*\\*)?${planEscaped}(?:\\*\\*)?)`,
|
|
1178
|
+
'i'
|
|
1179
|
+
);
|
|
1180
|
+
roadmapContent = roadmapContent.replace(planCheckboxPattern, '$1x$2');
|
|
698
1181
|
}
|
|
699
|
-
return '|' + cells.join('|') + '|';
|
|
700
|
-
});
|
|
701
1182
|
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
'
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
1183
|
+
platformWriteSync(roadmapPath, roadmapContent);
|
|
1184
|
+
|
|
1185
|
+
// Update REQUIREMENTS.md traceability for this phase's requirements
|
|
1186
|
+
const reqPath = path.join(planningDir(cwd), 'REQUIREMENTS.md');
|
|
1187
|
+
if (fs.existsSync(reqPath)) {
|
|
1188
|
+
// Extract the current phase section from roadmap (scoped to avoid cross-phase matching).
|
|
1189
|
+
// #3537: padding-tolerant fragment so an un-padded `Phase 2.7:` heading
|
|
1190
|
+
// is found when caller resolved to padded `02.7`.
|
|
1191
|
+
const phaseEsc = phaseMarkdownRegexSource(phaseNum);
|
|
1192
|
+
const currentMilestoneRoadmap = extractCurrentMilestone(roadmapContent, cwd);
|
|
1193
|
+
const phaseSectionMatch = currentMilestoneRoadmap.match(
|
|
1194
|
+
new RegExp(`(#{2,4}\\s*Phase\\s+${phaseEsc}[:\\s][\\s\\S]*?)(?=#{2,4}\\s*Phase\\s+|$)`, 'i')
|
|
1195
|
+
);
|
|
1196
|
+
|
|
1197
|
+
const sectionText = phaseSectionMatch ? phaseSectionMatch[1] : '';
|
|
1198
|
+
// Accept all bold/colon variants (#2769) — the previous pattern only
|
|
1199
|
+
// matched **Requirements:** (colon inside bold) and silently skipped
|
|
1200
|
+
// **Requirements**: (colon outside), preventing the matching REQ-IDs
|
|
1201
|
+
// from being ticked off in REQUIREMENTS.md on phase completion.
|
|
1202
|
+
const reqMatch = sectionText.match(/\*\*Requirements:?\*\*[^\S\n]*:?[^\S\n]*([^\n]+)/i);
|
|
711
1203
|
|
|
712
|
-
|
|
1204
|
+
let reqContent = fs.readFileSync(reqPath, 'utf-8');
|
|
713
1205
|
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
1206
|
+
if (reqMatch) {
|
|
1207
|
+
const reqIds = reqMatch[1].replace(/[\[\]]/g, '').split(/[,\s]+/).map(r => r.trim()).filter(Boolean);
|
|
1208
|
+
|
|
1209
|
+
for (const reqId of reqIds) {
|
|
1210
|
+
const reqEscaped = escapeRegex(reqId);
|
|
1211
|
+
// Update checkbox: - [ ] **REQ-ID** → - [x] **REQ-ID**
|
|
1212
|
+
reqContent = reqContent.replace(
|
|
1213
|
+
new RegExp(`(-\\s*\\[)[ ](\\]\\s*\\*\\*${reqEscaped}\\*\\*)`, 'gi'),
|
|
1214
|
+
'$1x$2'
|
|
1215
|
+
);
|
|
1216
|
+
// Update traceability table: | REQ-ID | Phase N | Pending/In Progress | → | REQ-ID | Phase N | Complete |
|
|
1217
|
+
reqContent = reqContent.replace(
|
|
1218
|
+
new RegExp(`(\\|\\s*${reqEscaped}\\s*\\|[^|]+\\|)\\s*(?:Pending|In Progress)\\s*(\\|)`, 'gi'),
|
|
1219
|
+
'$1 Complete $2'
|
|
1220
|
+
);
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
723
1223
|
|
|
724
|
-
|
|
725
|
-
|
|
1224
|
+
// Scan body for all **REQ-ID** patterns, warn about any missing from the Traceability table.
|
|
1225
|
+
// Always runs regardless of whether the roadmap has a Requirements: line.
|
|
1226
|
+
const bodyReqIds = [];
|
|
1227
|
+
const bodyReqPattern = /\*\*([A-Z][A-Z0-9]*-\d+)\*\*/g;
|
|
1228
|
+
let bodyMatch;
|
|
1229
|
+
while ((bodyMatch = bodyReqPattern.exec(reqContent)) !== null) {
|
|
1230
|
+
const id = bodyMatch[1];
|
|
1231
|
+
if (!bodyReqIds.includes(id)) bodyReqIds.push(id);
|
|
1232
|
+
}
|
|
726
1233
|
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
1234
|
+
// Collect REQ-IDs present in the Traceability section only, to avoid
|
|
1235
|
+
// picking up IDs from other tables in the document.
|
|
1236
|
+
const traceabilityHeadingMatch = reqContent.match(/^#{1,6}\s+Traceability\b/im);
|
|
1237
|
+
const traceabilitySection = traceabilityHeadingMatch
|
|
1238
|
+
? reqContent.slice(traceabilityHeadingMatch.index)
|
|
1239
|
+
: '';
|
|
1240
|
+
const tableReqIds = new Set();
|
|
1241
|
+
const tableRowPattern = /^\|\s*([A-Z][A-Z0-9]*-\d+)\s*\|/gm;
|
|
1242
|
+
let tableMatch;
|
|
1243
|
+
while ((tableMatch = tableRowPattern.exec(traceabilitySection)) !== null) {
|
|
1244
|
+
tableReqIds.add(tableMatch[1]);
|
|
1245
|
+
}
|
|
730
1246
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
new RegExp(`(-\\s*\\[)[ ](\\]\\s*\\*\\*${reqEscaped}\\*\\*)`, 'gi'),
|
|
736
|
-
'$1x$2'
|
|
737
|
-
);
|
|
738
|
-
// Update traceability table: | REQ-ID | Phase N | Pending/In Progress | → | REQ-ID | Phase N | Complete |
|
|
739
|
-
reqContent = reqContent.replace(
|
|
740
|
-
new RegExp(`(\\|\\s*${reqEscaped}\\s*\\|[^|]+\\|)\\s*(?:Pending|In Progress)\\s*(\\|)`, 'gi'),
|
|
741
|
-
'$1 Complete $2'
|
|
1247
|
+
const unregistered = bodyReqIds.filter(id => !tableReqIds.has(id));
|
|
1248
|
+
if (unregistered.length > 0) {
|
|
1249
|
+
warnings.push(
|
|
1250
|
+
`REQUIREMENTS.md: ${unregistered.length} REQ-ID(s) found in body but missing from Traceability table: ${unregistered.join(', ')} — add them manually to keep traceability in sync`
|
|
742
1251
|
);
|
|
743
1252
|
}
|
|
744
1253
|
|
|
745
|
-
|
|
1254
|
+
platformWriteSync(reqPath, reqContent);
|
|
746
1255
|
requirementsUpdated = true;
|
|
747
1256
|
}
|
|
748
|
-
}
|
|
1257
|
+
});
|
|
749
1258
|
}
|
|
750
1259
|
|
|
751
1260
|
// Find next phase — check both filesystem AND roadmap
|
|
@@ -763,9 +1272,11 @@ function cmdPhaseComplete(cwd, phaseNum, raw) {
|
|
|
763
1272
|
.sort((a, b) => comparePhaseNum(a, b));
|
|
764
1273
|
|
|
765
1274
|
// Find the next phase directory after current
|
|
1275
|
+
// Skip backlog phases (999.x) — they are parked ideas, not sequential work (#2129)
|
|
766
1276
|
for (const dir of dirs) {
|
|
767
1277
|
const dm = dir.match(/^(\d+[A-Z]?(?:\.\d+)*)-?(.*)/i);
|
|
768
1278
|
if (dm) {
|
|
1279
|
+
if (/^999(?:\.|$)/.test(dm[1])) continue;
|
|
769
1280
|
if (comparePhaseNum(dm[1], phaseNum) > 0) {
|
|
770
1281
|
nextPhaseNum = dm[1];
|
|
771
1282
|
nextPhaseName = dm[2] || null;
|
|
@@ -794,69 +1305,88 @@ function cmdPhaseComplete(cwd, phaseNum, raw) {
|
|
|
794
1305
|
} catch { /* intentionally empty */ }
|
|
795
1306
|
}
|
|
796
1307
|
|
|
797
|
-
// Update STATE.md —
|
|
1308
|
+
// Update STATE.md atomically — hold lock across read-modify-write (#P4.4).
|
|
1309
|
+
// Previously read outside the lock; a crash between the ROADMAP update
|
|
1310
|
+
// (locked above) and this write left ROADMAP/STATE inconsistent.
|
|
798
1311
|
if (fs.existsSync(statePath)) {
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
1312
|
+
readModifyWriteStateMd(statePath, (stateContent) => {
|
|
1313
|
+
// Update Current Phase — preserve "X of Y (Name)" compound format
|
|
1314
|
+
const phaseValue = nextPhaseNum || phaseNum;
|
|
1315
|
+
const existingPhaseField = stateExtractField(stateContent, 'Current Phase')
|
|
1316
|
+
|| stateExtractField(stateContent, 'Phase');
|
|
1317
|
+
let newPhaseValue = String(phaseValue);
|
|
1318
|
+
if (existingPhaseField) {
|
|
1319
|
+
const totalMatch = existingPhaseField.match(/of\s+(\d+)/);
|
|
1320
|
+
const nameMatch = existingPhaseField.match(/\(([^)]+)\)/);
|
|
1321
|
+
if (totalMatch) {
|
|
1322
|
+
const total = totalMatch[1];
|
|
1323
|
+
const nameStr = nextPhaseName ? ` (${nextPhaseName.replace(/-/g, ' ')})` : (nameMatch ? ` (${nameMatch[1]})` : '');
|
|
1324
|
+
newPhaseValue = `${phaseValue} of ${total}${nameStr}`;
|
|
1325
|
+
}
|
|
813
1326
|
}
|
|
814
|
-
|
|
815
|
-
stateContent = stateReplaceFieldWithFallback(stateContent, 'Current Phase', 'Phase', newPhaseValue);
|
|
816
|
-
|
|
817
|
-
// Update Current Phase Name
|
|
818
|
-
if (nextPhaseName) {
|
|
819
|
-
stateContent = stateReplaceFieldWithFallback(stateContent, 'Current Phase Name', null, nextPhaseName.replace(/-/g, ' '));
|
|
820
|
-
}
|
|
821
|
-
|
|
822
|
-
// Update Status
|
|
823
|
-
stateContent = stateReplaceFieldWithFallback(stateContent, 'Status', null,
|
|
824
|
-
isLastPhase ? 'Milestone complete' : 'Ready to plan');
|
|
1327
|
+
stateContent = stateReplaceFieldWithFallback(stateContent, 'Current Phase', 'Phase', newPhaseValue);
|
|
825
1328
|
|
|
826
|
-
|
|
827
|
-
|
|
1329
|
+
// Update Current Phase Name
|
|
1330
|
+
if (nextPhaseName) {
|
|
1331
|
+
stateContent = stateReplaceFieldWithFallback(stateContent, 'Current Phase Name', null, nextPhaseName.replace(/-/g, ' '));
|
|
1332
|
+
}
|
|
828
1333
|
|
|
829
|
-
|
|
830
|
-
|
|
1334
|
+
// Update Status
|
|
1335
|
+
stateContent = stateReplaceFieldWithFallback(stateContent, 'Status', null,
|
|
1336
|
+
isLastPhase ? 'Milestone complete' : 'Ready to plan');
|
|
1337
|
+
|
|
1338
|
+
// Update Current Plan
|
|
1339
|
+
stateContent = stateReplaceFieldWithFallback(stateContent, 'Current Plan', 'Plan', 'Not started');
|
|
1340
|
+
|
|
1341
|
+
// Update Last Activity
|
|
1342
|
+
stateContent = stateReplaceFieldWithFallback(stateContent, 'Last Activity', 'Last activity', today);
|
|
1343
|
+
|
|
1344
|
+
// Update Last Activity Description
|
|
1345
|
+
stateContent = stateReplaceFieldWithFallback(stateContent, 'Last Activity Description', null,
|
|
1346
|
+
`Phase ${phaseNum} complete${nextPhaseNum ? `, transitioned to Phase ${nextPhaseNum}` : ''}`);
|
|
1347
|
+
|
|
1348
|
+
// Increment Completed Phases counter (#956)
|
|
1349
|
+
const completedRaw = stateExtractField(stateContent, 'Completed Phases');
|
|
1350
|
+
if (completedRaw) {
|
|
1351
|
+
const newCompleted = parseInt(completedRaw, 10) + 1;
|
|
1352
|
+
stateContent = stateReplaceField(stateContent, 'Completed Phases', String(newCompleted)) || stateContent;
|
|
1353
|
+
|
|
1354
|
+
// Recalculate percent based on completed / total (#956)
|
|
1355
|
+
const totalRaw = stateExtractField(stateContent, 'Total Phases');
|
|
1356
|
+
if (totalRaw) {
|
|
1357
|
+
const totalPhases = parseInt(totalRaw, 10);
|
|
1358
|
+
if (totalPhases > 0) {
|
|
1359
|
+
const newPercent = Math.round((newCompleted / totalPhases) * 100);
|
|
1360
|
+
stateContent = stateReplaceField(stateContent, 'Progress', `${newPercent}%`) || stateContent;
|
|
1361
|
+
stateContent = stateContent.replace(
|
|
1362
|
+
/(percent:\s*)\d+/,
|
|
1363
|
+
`$1${newPercent}`
|
|
1364
|
+
);
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
831
1368
|
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
`Phase ${phaseNum} complete${nextPhaseNum ? `, transitioned to Phase ${nextPhaseNum}` : ''}`);
|
|
1369
|
+
// Gate 4: Update Performance Metrics section (#1627)
|
|
1370
|
+
stateContent = updatePerformanceMetricsSection(stateContent, cwd, phaseNum, planCount, summaryCount);
|
|
835
1371
|
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
const newCompleted = parseInt(completedRaw, 10) + 1;
|
|
840
|
-
stateContent = stateReplaceField(stateContent, 'Completed Phases', String(newCompleted)) || stateContent;
|
|
1372
|
+
return stateContent;
|
|
1373
|
+
}, cwd);
|
|
1374
|
+
}
|
|
841
1375
|
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
);
|
|
854
|
-
}
|
|
1376
|
+
// Auto-prune STATE.md on phase boundary when configured (#2087)
|
|
1377
|
+
let autoPruned = false;
|
|
1378
|
+
try {
|
|
1379
|
+
const configPath = path.join(planningDir(cwd), 'config.json');
|
|
1380
|
+
if (fs.existsSync(configPath)) {
|
|
1381
|
+
const rawConfig = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
1382
|
+
const autoPruneEnabled = rawConfig.workflow && rawConfig.workflow.auto_prune_state === true;
|
|
1383
|
+
if (autoPruneEnabled && fs.existsSync(statePath)) {
|
|
1384
|
+
const { cmdStatePrune } = require('./state.cjs');
|
|
1385
|
+
cmdStatePrune(cwd, { keepRecent: '3', dryRun: false, silent: true }, true);
|
|
1386
|
+
autoPruned = true;
|
|
855
1387
|
}
|
|
856
1388
|
}
|
|
857
|
-
|
|
858
|
-
writeStateMd(statePath, stateContent, cwd);
|
|
859
|
-
}
|
|
1389
|
+
} catch { /* intentionally empty — auto-prune is best-effort */ }
|
|
860
1390
|
|
|
861
1391
|
const result = {
|
|
862
1392
|
completed_phase: phaseNum,
|
|
@@ -869,6 +1399,7 @@ function cmdPhaseComplete(cwd, phaseNum, raw) {
|
|
|
869
1399
|
roadmap_updated: fs.existsSync(roadmapPath),
|
|
870
1400
|
state_updated: fs.existsSync(statePath),
|
|
871
1401
|
requirements_updated: requirementsUpdated,
|
|
1402
|
+
auto_pruned: autoPruned,
|
|
872
1403
|
warnings,
|
|
873
1404
|
has_warnings: warnings.length > 0,
|
|
874
1405
|
};
|
|
@@ -882,6 +1413,8 @@ module.exports = {
|
|
|
882
1413
|
cmdFindPhase,
|
|
883
1414
|
cmdPhasePlanIndex,
|
|
884
1415
|
cmdPhaseAdd,
|
|
1416
|
+
cmdPhaseAddBatch,
|
|
1417
|
+
cmdPhaseMvpMode,
|
|
885
1418
|
cmdPhaseInsert,
|
|
886
1419
|
cmdPhaseRemove,
|
|
887
1420
|
cmdPhaseComplete,
|