@opengsd/get-shit-done-redux 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.ja-JP.md +870 -0
- package/README.ko-KR.md +861 -0
- package/README.md +300 -0
- package/README.pt-BR.md +492 -0
- package/README.zh-CN.md +842 -0
- package/agents/gsd-advisor-researcher.md +127 -0
- package/agents/gsd-ai-researcher.md +133 -0
- package/agents/gsd-assumptions-analyzer.md +105 -0
- package/agents/gsd-code-fixer.md +668 -0
- package/agents/gsd-code-reviewer.md +387 -0
- package/agents/gsd-codebase-mapper.md +853 -0
- package/agents/gsd-debug-session-manager.md +314 -0
- package/agents/gsd-debugger.md +1452 -0
- package/agents/gsd-doc-classifier.md +168 -0
- package/agents/gsd-doc-synthesizer.md +204 -0
- package/agents/gsd-doc-verifier.md +217 -0
- package/agents/gsd-doc-writer.md +615 -0
- package/agents/gsd-domain-researcher.md +153 -0
- package/agents/gsd-eval-auditor.md +191 -0
- package/agents/gsd-eval-planner.md +154 -0
- package/agents/gsd-executor.md +774 -0
- package/agents/gsd-framework-selector.md +160 -0
- package/agents/gsd-integration-checker.md +470 -0
- package/agents/gsd-intel-updater.md +342 -0
- package/agents/gsd-nyquist-auditor.md +203 -0
- package/agents/gsd-pattern-mapper.md +335 -0
- package/agents/gsd-phase-researcher.md +928 -0
- package/agents/gsd-plan-checker.md +978 -0
- package/agents/gsd-planner.md +1278 -0
- package/agents/gsd-project-researcher.md +677 -0
- package/agents/gsd-research-synthesizer.md +247 -0
- package/agents/gsd-roadmapper.md +688 -0
- package/agents/gsd-security-auditor.md +155 -0
- package/agents/gsd-ui-auditor.md +495 -0
- package/agents/gsd-ui-checker.md +309 -0
- package/agents/gsd-ui-researcher.md +380 -0
- package/agents/gsd-user-profiler.md +171 -0
- package/agents/gsd-verifier.md +917 -0
- package/bin/gsd-sdk.js +37 -0
- package/bin/install.js +11468 -0
- package/bin/lib/ui-safety-gate.cjs +107 -0
- package/commands/gsd/add-tests.md +42 -0
- package/commands/gsd/ai-integration-phase.md +37 -0
- package/commands/gsd/audit-fix.md +34 -0
- package/commands/gsd/audit-milestone.md +37 -0
- package/commands/gsd/audit-uat.md +24 -0
- package/commands/gsd/autonomous.md +46 -0
- package/commands/gsd/capture.md +62 -0
- package/commands/gsd/cleanup.md +24 -0
- package/commands/gsd/code-review.md +59 -0
- package/commands/gsd/complete-milestone.md +143 -0
- package/commands/gsd/config.md +58 -0
- package/commands/gsd/debug.md +52 -0
- package/commands/gsd/discuss-phase.md +76 -0
- package/commands/gsd/docs-update.md +49 -0
- package/commands/gsd/eval-review.md +33 -0
- package/commands/gsd/execute-phase.md +64 -0
- package/commands/gsd/explore.md +27 -0
- package/commands/gsd/extract-learnings.md +23 -0
- package/commands/gsd/fast.md +31 -0
- package/commands/gsd/forensics.md +57 -0
- package/commands/gsd/graphify.md +199 -0
- package/commands/gsd/health.md +31 -0
- package/commands/gsd/help.md +28 -0
- package/commands/gsd/import.md +41 -0
- package/commands/gsd/inbox.md +39 -0
- package/commands/gsd/ingest-docs.md +42 -0
- package/commands/gsd/manager.md +45 -0
- package/commands/gsd/map-codebase.md +83 -0
- package/commands/gsd/milestone-summary.md +51 -0
- package/commands/gsd/mvp-phase.md +45 -0
- package/commands/gsd/new-milestone.md +45 -0
- package/commands/gsd/new-project.md +47 -0
- package/commands/gsd/ns-context.md +23 -0
- package/commands/gsd/ns-ideate.md +24 -0
- package/commands/gsd/ns-manage.md +29 -0
- package/commands/gsd/ns-project.md +22 -0
- package/commands/gsd/ns-review.md +26 -0
- package/commands/gsd/ns-workflow.md +28 -0
- package/commands/gsd/pause-work.md +43 -0
- package/commands/gsd/phase.md +56 -0
- package/commands/gsd/plan-phase.md +62 -0
- package/commands/gsd/plan-review-convergence.md +59 -0
- package/commands/gsd/pr-branch.md +26 -0
- package/commands/gsd/profile-user.md +46 -0
- package/commands/gsd/progress.md +46 -0
- package/commands/gsd/quick.md +174 -0
- package/commands/gsd/resume-work.md +30 -0
- package/commands/gsd/review-backlog.md +63 -0
- package/commands/gsd/review.md +41 -0
- package/commands/gsd/secure-phase.md +36 -0
- package/commands/gsd/settings.md +29 -0
- package/commands/gsd/ship.md +24 -0
- package/commands/gsd/sketch.md +60 -0
- package/commands/gsd/spec-phase.md +63 -0
- package/commands/gsd/spike.md +57 -0
- package/commands/gsd/stats.md +19 -0
- package/commands/gsd/surface.md +155 -0
- package/commands/gsd/thread.md +24 -0
- package/commands/gsd/ui-phase.md +35 -0
- package/commands/gsd/ui-review.md +33 -0
- package/commands/gsd/ultraplan-phase.md +34 -0
- package/commands/gsd/undo.md +35 -0
- package/commands/gsd/update.md +48 -0
- package/commands/gsd/validate-phase.md +36 -0
- package/commands/gsd/verify-work.md +39 -0
- package/commands/gsd/workspace.md +52 -0
- package/commands/gsd/workstreams.md +70 -0
- package/get-shit-done/bin/check-latest-version.cjs +104 -0
- package/get-shit-done/bin/gsd-tools.cjs +1630 -0
- package/get-shit-done/bin/lib/active-workstream-store.cjs +85 -0
- package/get-shit-done/bin/lib/adr-parser.cjs +394 -0
- package/get-shit-done/bin/lib/artifacts.cjs +53 -0
- package/get-shit-done/bin/lib/audit.cjs +755 -0
- package/get-shit-done/bin/lib/cjs-command-router-adapter.cjs +39 -0
- package/get-shit-done/bin/lib/cjs-sdk-bridge.cjs +136 -0
- package/get-shit-done/bin/lib/clusters.cjs +135 -0
- package/get-shit-done/bin/lib/code-review-flags.cjs +74 -0
- package/get-shit-done/bin/lib/command-aliases.generated.cjs +824 -0
- package/get-shit-done/bin/lib/command-routing-hub.cjs +239 -0
- package/get-shit-done/bin/lib/commands.cjs +1035 -0
- package/get-shit-done/bin/lib/config-schema.cjs +31 -0
- package/get-shit-done/bin/lib/config.cjs +704 -0
- package/get-shit-done/bin/lib/configuration.generated.cjs +253 -0
- package/get-shit-done/bin/lib/context-utilization.cjs +47 -0
- package/get-shit-done/bin/lib/core.cjs +1922 -0
- package/get-shit-done/bin/lib/decisions.cjs +19 -0
- package/get-shit-done/bin/lib/decisions.generated.cjs +121 -0
- package/get-shit-done/bin/lib/docs.cjs +270 -0
- package/get-shit-done/bin/lib/drift.cjs +388 -0
- package/get-shit-done/bin/lib/fallow-runner.cjs +109 -0
- package/get-shit-done/bin/lib/frontmatter.cjs +389 -0
- package/get-shit-done/bin/lib/gap-checker.cjs +205 -0
- package/get-shit-done/bin/lib/graphify.cjs +592 -0
- package/get-shit-done/bin/lib/gsd2-import.cjs +514 -0
- package/get-shit-done/bin/lib/init-command-router.cjs +174 -0
- package/get-shit-done/bin/lib/init.cjs +2096 -0
- package/get-shit-done/bin/lib/install-profiles.cjs +603 -0
- package/get-shit-done/bin/lib/installer-migration-authoring.cjs +117 -0
- package/get-shit-done/bin/lib/installer-migration-report.cjs +354 -0
- package/get-shit-done/bin/lib/installer-migrations/000-first-time-baseline.cjs +220 -0
- package/get-shit-done/bin/lib/installer-migrations/001-legacy-orphan-files.cjs +41 -0
- package/get-shit-done/bin/lib/installer-migrations/002-codex-legacy-hooks-json.cjs +80 -0
- package/get-shit-done/bin/lib/installer-migrations.cjs +776 -0
- package/get-shit-done/bin/lib/intel.cjs +643 -0
- package/get-shit-done/bin/lib/learnings.cjs +379 -0
- package/get-shit-done/bin/lib/milestone.cjs +314 -0
- package/get-shit-done/bin/lib/model-catalog.cjs +136 -0
- package/get-shit-done/bin/lib/model-profiles.cjs +25 -0
- package/get-shit-done/bin/lib/phase-command-router.cjs +226 -0
- package/get-shit-done/bin/lib/phase.cjs +1490 -0
- package/get-shit-done/bin/lib/phases-command-router.cjs +97 -0
- package/get-shit-done/bin/lib/plan-scan.cjs +26 -0
- package/get-shit-done/bin/lib/plan-scan.generated.cjs +97 -0
- package/get-shit-done/bin/lib/planning-workspace.cjs +415 -0
- package/get-shit-done/bin/lib/profile-output.cjs +1130 -0
- package/get-shit-done/bin/lib/profile-pipeline.cjs +539 -0
- package/get-shit-done/bin/lib/project-root.generated.cjs +117 -0
- package/get-shit-done/bin/lib/prompt-budget.cjs +399 -0
- package/get-shit-done/bin/lib/review-reviewer-selection.cjs +125 -0
- package/get-shit-done/bin/lib/roadmap-command-router.cjs +99 -0
- package/get-shit-done/bin/lib/roadmap.cjs +642 -0
- package/get-shit-done/bin/lib/runtime-artifact-layout.cjs +301 -0
- package/get-shit-done/bin/lib/runtime-homes.cjs +185 -0
- package/get-shit-done/bin/lib/runtime-slash.cjs +109 -0
- package/get-shit-done/bin/lib/schema-detect.cjs +21 -0
- package/get-shit-done/bin/lib/schema-detect.generated.cjs +170 -0
- package/get-shit-done/bin/lib/secrets.cjs +20 -0
- package/get-shit-done/bin/lib/secrets.generated.cjs +37 -0
- package/get-shit-done/bin/lib/security.cjs +504 -0
- package/get-shit-done/bin/lib/shell-command-projection.cjs +552 -0
- package/get-shit-done/bin/lib/state-command-router.cjs +346 -0
- package/get-shit-done/bin/lib/state-document.cjs +12 -0
- package/get-shit-done/bin/lib/state-document.generated.cjs +127 -0
- package/get-shit-done/bin/lib/state.cjs +1940 -0
- package/get-shit-done/bin/lib/surface.cjs +430 -0
- package/get-shit-done/bin/lib/template.cjs +228 -0
- package/get-shit-done/bin/lib/uat.cjs +289 -0
- package/get-shit-done/bin/lib/validate-command-router.cjs +129 -0
- package/get-shit-done/bin/lib/verify-command-router.cjs +122 -0
- package/get-shit-done/bin/lib/verify.cjs +1458 -0
- package/get-shit-done/bin/lib/workstream-inventory-builder.generated.cjs +79 -0
- package/get-shit-done/bin/lib/workstream-inventory.cjs +132 -0
- package/get-shit-done/bin/lib/workstream-name-policy.cjs +19 -0
- package/get-shit-done/bin/lib/workstream-name-policy.generated.cjs +61 -0
- package/get-shit-done/bin/lib/workstream.cjs +374 -0
- package/get-shit-done/bin/lib/worktree-safety.cjs +985 -0
- package/get-shit-done/bin/verify-reapply-patches.cjs +336 -0
- package/get-shit-done/contexts/dev.md +21 -0
- package/get-shit-done/contexts/research.md +22 -0
- package/get-shit-done/contexts/review.md +23 -0
- package/get-shit-done/references/agent-contracts.md +79 -0
- package/get-shit-done/references/ai-evals.md +156 -0
- package/get-shit-done/references/ai-frameworks.md +186 -0
- package/get-shit-done/references/artifact-types.md +131 -0
- package/get-shit-done/references/autonomous-smart-discuss.md +277 -0
- package/get-shit-done/references/checkpoints.md +814 -0
- package/get-shit-done/references/common-bug-patterns.md +114 -0
- package/get-shit-done/references/context-budget.md +85 -0
- package/get-shit-done/references/continuation-format.md +253 -0
- package/get-shit-done/references/debugger-philosophy.md +76 -0
- package/get-shit-done/references/decimal-phase-calculation.md +64 -0
- package/get-shit-done/references/doc-conflict-engine.md +91 -0
- package/get-shit-done/references/domain-probes.md +125 -0
- package/get-shit-done/references/execute-mvp-tdd.md +81 -0
- package/get-shit-done/references/executor-examples.md +110 -0
- package/get-shit-done/references/few-shot-examples/plan-checker.md +73 -0
- package/get-shit-done/references/few-shot-examples/verifier.md +109 -0
- package/get-shit-done/references/gate-prompts.md +100 -0
- package/get-shit-done/references/gates.md +70 -0
- package/get-shit-done/references/git-integration.md +298 -0
- package/get-shit-done/references/git-planning-commit.md +40 -0
- package/get-shit-done/references/ios-scaffold.md +123 -0
- package/get-shit-done/references/mandatory-initial-read.md +2 -0
- package/get-shit-done/references/model-profile-resolution.md +38 -0
- package/get-shit-done/references/model-profiles.md +245 -0
- package/get-shit-done/references/mvp-concepts.md +49 -0
- package/get-shit-done/references/phase-argument-parsing.md +61 -0
- package/get-shit-done/references/planner-antipatterns.md +89 -0
- package/get-shit-done/references/planner-chunked.md +49 -0
- package/get-shit-done/references/planner-gap-closure.md +62 -0
- package/get-shit-done/references/planner-graphify-auto-update.md +67 -0
- package/get-shit-done/references/planner-human-verify-mode.md +57 -0
- package/get-shit-done/references/planner-mvp-mode.md +53 -0
- package/get-shit-done/references/planner-reviews.md +39 -0
- package/get-shit-done/references/planner-revision.md +87 -0
- package/get-shit-done/references/planner-source-audit.md +73 -0
- package/get-shit-done/references/planning-config.md +471 -0
- package/get-shit-done/references/project-skills-discovery.md +19 -0
- package/get-shit-done/references/questioning.md +162 -0
- package/get-shit-done/references/revision-loop.md +97 -0
- package/get-shit-done/references/scout-codebase.md +51 -0
- package/get-shit-done/references/skeleton-template.md +48 -0
- package/get-shit-done/references/sketch-interactivity.md +41 -0
- package/get-shit-done/references/sketch-theme-system.md +94 -0
- package/get-shit-done/references/sketch-tooling.md +45 -0
- package/get-shit-done/references/sketch-variant-patterns.md +81 -0
- package/get-shit-done/references/spidr-splitting.md +69 -0
- package/get-shit-done/references/tdd.md +330 -0
- package/get-shit-done/references/thinking-models-debug.md +44 -0
- package/get-shit-done/references/thinking-models-execution.md +50 -0
- package/get-shit-done/references/thinking-models-planning.md +62 -0
- package/get-shit-done/references/thinking-models-research.md +50 -0
- package/get-shit-done/references/thinking-models-verification.md +55 -0
- package/get-shit-done/references/thinking-partner.md +96 -0
- package/get-shit-done/references/ui-brand.md +160 -0
- package/get-shit-done/references/universal-anti-patterns.md +63 -0
- package/get-shit-done/references/user-profiling.md +681 -0
- package/get-shit-done/references/user-story-template.md +58 -0
- package/get-shit-done/references/verification-overrides.md +227 -0
- package/get-shit-done/references/verification-patterns.md +612 -0
- package/get-shit-done/references/verify-mvp-mode.md +85 -0
- package/get-shit-done/references/workstream-flag.md +111 -0
- package/get-shit-done/references/worktree-path-safety.md +89 -0
- package/get-shit-done/templates/AI-SPEC.md +246 -0
- package/get-shit-done/templates/DEBUG.md +169 -0
- package/get-shit-done/templates/README.md +77 -0
- package/get-shit-done/templates/SECURITY.md +61 -0
- package/get-shit-done/templates/UAT.md +265 -0
- package/get-shit-done/templates/UI-SPEC.md +100 -0
- package/get-shit-done/templates/VALIDATION.md +76 -0
- package/get-shit-done/templates/claude-md.md +145 -0
- package/get-shit-done/templates/codebase/architecture.md +255 -0
- package/get-shit-done/templates/codebase/concerns.md +310 -0
- package/get-shit-done/templates/codebase/conventions.md +307 -0
- package/get-shit-done/templates/codebase/integrations.md +280 -0
- package/get-shit-done/templates/codebase/stack.md +186 -0
- package/get-shit-done/templates/codebase/structure.md +285 -0
- package/get-shit-done/templates/codebase/testing.md +480 -0
- package/get-shit-done/templates/config.json +62 -0
- package/get-shit-done/templates/context.md +352 -0
- package/get-shit-done/templates/continue-here.md +78 -0
- package/get-shit-done/templates/copilot-instructions.md +7 -0
- package/get-shit-done/templates/debug-subagent-prompt.md +91 -0
- package/get-shit-done/templates/dev-preferences.md +21 -0
- package/get-shit-done/templates/discovery.md +146 -0
- package/get-shit-done/templates/discussion-log.md +63 -0
- package/get-shit-done/templates/milestone-archive.md +123 -0
- package/get-shit-done/templates/milestone.md +115 -0
- package/get-shit-done/templates/phase-prompt.md +610 -0
- package/get-shit-done/templates/planner-subagent-prompt.md +117 -0
- package/get-shit-done/templates/project.md +186 -0
- package/get-shit-done/templates/requirements.md +231 -0
- package/get-shit-done/templates/research-project/ARCHITECTURE.md +204 -0
- package/get-shit-done/templates/research-project/FEATURES.md +147 -0
- package/get-shit-done/templates/research-project/PITFALLS.md +200 -0
- package/get-shit-done/templates/research-project/STACK.md +120 -0
- package/get-shit-done/templates/research-project/SUMMARY.md +170 -0
- package/get-shit-done/templates/research.md +592 -0
- package/get-shit-done/templates/retrospective.md +54 -0
- package/get-shit-done/templates/roadmap.md +202 -0
- package/get-shit-done/templates/spec.md +307 -0
- package/get-shit-done/templates/state.md +184 -0
- package/get-shit-done/templates/summary-complex.md +59 -0
- package/get-shit-done/templates/summary-minimal.md +41 -0
- package/get-shit-done/templates/summary-standard.md +48 -0
- package/get-shit-done/templates/summary.md +248 -0
- package/get-shit-done/templates/user-profile.md +146 -0
- package/get-shit-done/templates/user-setup.md +311 -0
- package/get-shit-done/templates/verification-report.md +322 -0
- package/get-shit-done/workflows/add-backlog.md +101 -0
- package/get-shit-done/workflows/add-phase.md +123 -0
- package/get-shit-done/workflows/add-tests.md +365 -0
- package/get-shit-done/workflows/add-todo.md +171 -0
- package/get-shit-done/workflows/ai-integration-phase.md +305 -0
- package/get-shit-done/workflows/analyze-dependencies.md +96 -0
- package/get-shit-done/workflows/audit-fix.md +188 -0
- package/get-shit-done/workflows/audit-milestone.md +368 -0
- package/get-shit-done/workflows/audit-uat.md +120 -0
- package/get-shit-done/workflows/autonomous.md +805 -0
- package/get-shit-done/workflows/check-todos.md +190 -0
- package/get-shit-done/workflows/cleanup.md +165 -0
- package/get-shit-done/workflows/code-review-fix.md +512 -0
- package/get-shit-done/workflows/code-review.md +666 -0
- package/get-shit-done/workflows/complete-milestone.md +865 -0
- package/get-shit-done/workflows/debug.md +242 -0
- package/get-shit-done/workflows/diagnose-issues.md +251 -0
- package/get-shit-done/workflows/discovery-phase.md +291 -0
- package/get-shit-done/workflows/discuss-phase/modes/advisor.md +175 -0
- package/get-shit-done/workflows/discuss-phase/modes/all.md +28 -0
- package/get-shit-done/workflows/discuss-phase/modes/analyze.md +44 -0
- package/get-shit-done/workflows/discuss-phase/modes/auto.md +56 -0
- package/get-shit-done/workflows/discuss-phase/modes/batch.md +52 -0
- package/get-shit-done/workflows/discuss-phase/modes/chain.md +97 -0
- package/get-shit-done/workflows/discuss-phase/modes/default.md +141 -0
- package/get-shit-done/workflows/discuss-phase/modes/power.md +44 -0
- package/get-shit-done/workflows/discuss-phase/modes/text.md +55 -0
- package/get-shit-done/workflows/discuss-phase/templates/checkpoint.json +18 -0
- package/get-shit-done/workflows/discuss-phase/templates/context.md +136 -0
- package/get-shit-done/workflows/discuss-phase/templates/discussion-log.md +50 -0
- package/get-shit-done/workflows/discuss-phase-assumptions.md +685 -0
- package/get-shit-done/workflows/discuss-phase-power.md +291 -0
- package/get-shit-done/workflows/discuss-phase.md +499 -0
- package/get-shit-done/workflows/do.md +122 -0
- package/get-shit-done/workflows/docs-update.md +1172 -0
- package/get-shit-done/workflows/edit-phase.md +305 -0
- package/get-shit-done/workflows/eval-review.md +166 -0
- package/get-shit-done/workflows/execute-phase/steps/codebase-drift-gate.md +81 -0
- package/get-shit-done/workflows/execute-phase/steps/per-plan-worktree-gate.md +94 -0
- package/get-shit-done/workflows/execute-phase/steps/post-merge-gate.md +116 -0
- package/get-shit-done/workflows/execute-phase.md +1717 -0
- package/get-shit-done/workflows/execute-plan.md +536 -0
- package/get-shit-done/workflows/explore.md +154 -0
- package/get-shit-done/workflows/extract-learnings.md +253 -0
- package/get-shit-done/workflows/fast.md +124 -0
- package/get-shit-done/workflows/forensics.md +289 -0
- package/get-shit-done/workflows/graduation.md +206 -0
- package/get-shit-done/workflows/health.md +234 -0
- package/get-shit-done/workflows/help/modes/brief.md +22 -0
- package/get-shit-done/workflows/help/modes/default.md +50 -0
- package/get-shit-done/workflows/help/modes/full.md +784 -0
- package/get-shit-done/workflows/help/modes/topic.md +74 -0
- package/get-shit-done/workflows/help.md +24 -0
- package/get-shit-done/workflows/import.md +264 -0
- package/get-shit-done/workflows/inbox.md +387 -0
- package/get-shit-done/workflows/ingest-docs.md +339 -0
- package/get-shit-done/workflows/insert-phase.md +162 -0
- package/get-shit-done/workflows/list-phase-assumptions.md +178 -0
- package/get-shit-done/workflows/list-workspaces.md +67 -0
- package/get-shit-done/workflows/manager.md +403 -0
- package/get-shit-done/workflows/map-codebase.md +454 -0
- package/get-shit-done/workflows/milestone-summary.md +234 -0
- package/get-shit-done/workflows/mvp-phase.md +232 -0
- package/get-shit-done/workflows/new-milestone.md +645 -0
- package/get-shit-done/workflows/new-project.md +1487 -0
- package/get-shit-done/workflows/new-workspace.md +250 -0
- package/get-shit-done/workflows/next.md +231 -0
- package/get-shit-done/workflows/node-repair.md +92 -0
- package/get-shit-done/workflows/note.md +158 -0
- package/get-shit-done/workflows/pause-work.md +254 -0
- package/get-shit-done/workflows/plan-milestone-gaps.md +291 -0
- package/get-shit-done/workflows/plan-phase.md +1800 -0
- package/get-shit-done/workflows/plan-review-convergence.md +340 -0
- package/get-shit-done/workflows/plant-seed.md +240 -0
- package/get-shit-done/workflows/pr-branch.md +157 -0
- package/get-shit-done/workflows/profile-user.md +463 -0
- package/get-shit-done/workflows/progress.md +660 -0
- package/get-shit-done/workflows/quick.md +1049 -0
- package/get-shit-done/workflows/reapply-patches.md +426 -0
- package/get-shit-done/workflows/remove-phase.md +166 -0
- package/get-shit-done/workflows/remove-workspace.md +118 -0
- package/get-shit-done/workflows/resume-project.md +342 -0
- package/get-shit-done/workflows/review.md +633 -0
- package/get-shit-done/workflows/scan.md +115 -0
- package/get-shit-done/workflows/secure-phase.md +190 -0
- package/get-shit-done/workflows/session-report.md +146 -0
- package/get-shit-done/workflows/settings-advanced.md +590 -0
- package/get-shit-done/workflows/settings-integrations.md +292 -0
- package/get-shit-done/workflows/settings.md +545 -0
- package/get-shit-done/workflows/ship.md +366 -0
- package/get-shit-done/workflows/sketch-wrap-up.md +296 -0
- package/get-shit-done/workflows/sketch.md +371 -0
- package/get-shit-done/workflows/spec-phase.md +262 -0
- package/get-shit-done/workflows/spike-wrap-up.md +317 -0
- package/get-shit-done/workflows/spike.md +463 -0
- package/get-shit-done/workflows/stats.md +90 -0
- package/get-shit-done/workflows/sync-skills.md +182 -0
- package/get-shit-done/workflows/thread.md +232 -0
- package/get-shit-done/workflows/transition.md +704 -0
- package/get-shit-done/workflows/ui-phase.md +338 -0
- package/get-shit-done/workflows/ui-review.md +203 -0
- package/get-shit-done/workflows/ultraplan-phase.md +209 -0
- package/get-shit-done/workflows/undo.md +314 -0
- package/get-shit-done/workflows/update.md +664 -0
- package/get-shit-done/workflows/validate-phase.md +189 -0
- package/get-shit-done/workflows/verify-phase.md +554 -0
- package/get-shit-done/workflows/verify-work.md +791 -0
- package/hooks/dist/gsd-check-update-worker.js +117 -0
- package/hooks/dist/gsd-check-update.js +64 -0
- package/hooks/dist/gsd-context-monitor.js +192 -0
- package/hooks/dist/gsd-graphify-update.sh +158 -0
- package/hooks/dist/gsd-phase-boundary.sh +47 -0
- package/hooks/dist/gsd-prompt-guard.js +97 -0
- package/hooks/dist/gsd-read-guard.js +101 -0
- package/hooks/dist/gsd-read-injection-scanner.js +152 -0
- package/hooks/dist/gsd-session-state.sh +59 -0
- package/hooks/dist/gsd-statusline.js +537 -0
- package/hooks/dist/gsd-update-banner.js +134 -0
- package/hooks/dist/gsd-validate-commit.sh +57 -0
- package/hooks/dist/gsd-workflow-guard.js +94 -0
- package/hooks/dist/lib/git-cmd.js +150 -0
- package/hooks/dist/lib/gsd-graphify-rebuild.sh +65 -0
- package/hooks/gsd-check-update-worker.js +117 -0
- package/hooks/gsd-check-update.js +64 -0
- package/hooks/gsd-context-monitor.js +192 -0
- package/hooks/gsd-graphify-update.sh +158 -0
- package/hooks/gsd-phase-boundary.sh +47 -0
- package/hooks/gsd-prompt-guard.js +97 -0
- package/hooks/gsd-read-guard.js +101 -0
- package/hooks/gsd-read-injection-scanner.js +152 -0
- package/hooks/gsd-session-state.sh +59 -0
- package/hooks/gsd-statusline.js +537 -0
- package/hooks/gsd-update-banner.js +134 -0
- package/hooks/gsd-validate-commit.sh +57 -0
- package/hooks/gsd-workflow-guard.js +94 -0
- package/hooks/lib/git-cmd.js +150 -0
- package/hooks/lib/gsd-graphify-rebuild.sh +65 -0
- package/package.json +98 -0
- package/scripts/audit-workflow-script-paths.cjs +73 -0
- package/scripts/base64-scan.sh +262 -0
- package/scripts/build-hooks.js +227 -0
- package/scripts/changeset/cli.cjs +408 -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 +114 -0
- package/scripts/changeset/render.cjs +34 -0
- package/scripts/changeset/serialize.cjs +130 -0
- package/scripts/command-contract-helpers.cjs +64 -0
- package/scripts/diff-touches-shipped-paths.cjs +147 -0
- package/scripts/fix-slash-commands.cjs +147 -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-docs-required.cjs +222 -0
- package/scripts/lint-no-source-grep-extras.cjs +81 -0
- package/scripts/lint-no-source-grep.cjs +174 -0
- package/scripts/lint-pr-check-project-dir.cjs +98 -0
- package/scripts/lint-shared-module-handsync.cjs +331 -0
- package/scripts/lint-shell-command-projection-drift.cjs +57 -0
- package/scripts/lint-skill-deps.cjs +180 -0
- package/scripts/lint-test-file-count.allowlist.json +35 -0
- package/scripts/lint-test-file-count.cjs +190 -0
- package/scripts/pr-template-policy.cjs +268 -0
- package/scripts/prompt-injection-scan.sh +203 -0
- package/scripts/release-tarball-smoke.cjs +677 -0
- package/scripts/run-tests.cjs +178 -0
- package/scripts/secret-scan.sh +229 -0
- package/scripts/shared-module-handsync-allowlist.json +145 -0
- package/scripts/strip-prose-atrefs.cjs +106 -0
- package/scripts/sync-rulesets.sh +34 -0
- package/scripts/verify-tarball-sdk-dist.sh +69 -0
- 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 +108 -0
- package/sdk/dist/config.d.ts.map +1 -0
- package/sdk/dist/config.js +116 -0
- package/sdk/dist/config.js.map +1 -0
- package/sdk/dist/configuration/index.d.ts +85 -0
- package/sdk/dist/configuration/index.d.ts.map +1 -0
- package/sdk/dist/configuration/index.js +257 -0
- package/sdk/dist/configuration/index.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/gsd-tools-error.d.ts +23 -0
- package/sdk/dist/gsd-tools-error.d.ts.map +1 -0
- package/sdk/dist/gsd-tools-error.js +29 -0
- package/sdk/dist/gsd-tools-error.js.map +1 -0
- package/sdk/dist/gsd-tools.d.ts +97 -0
- package/sdk/dist/gsd-tools.d.ts.map +1 -0
- package/sdk/dist/gsd-tools.js +168 -0
- package/sdk/dist/gsd-tools.js.map +1 -0
- package/sdk/dist/gsd-transport-policy.d.ts +10 -0
- package/sdk/dist/gsd-transport-policy.d.ts.map +1 -0
- package/sdk/dist/gsd-transport-policy.js +32 -0
- package/sdk/dist/gsd-transport-policy.js.map +1 -0
- package/sdk/dist/gsd-transport.d.ts +39 -0
- package/sdk/dist/gsd-transport.d.ts.map +1 -0
- package/sdk/dist/gsd-transport.js +78 -0
- package/sdk/dist/gsd-transport.js.map +1 -0
- package/sdk/dist/index.d.ts +127 -0
- package/sdk/dist/index.d.ts.map +1 -0
- package/sdk/dist/index.js +300 -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/project-root/index.d.ts +46 -0
- package/sdk/dist/project-root/index.d.ts.map +1 -0
- package/sdk/dist/project-root/index.js +138 -0
- package/sdk/dist/project-root/index.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 +17 -0
- package/sdk/dist/query/check-ship-ready.d.ts.map +1 -0
- package/sdk/dist/query/check-ship-ready.js +121 -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 +133 -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 +101 -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 +60 -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 +16 -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 +16 -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 +110 -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 +106 -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 +179 -0
- package/sdk/dist/query/commit.d.ts.map +1 -0
- package/sdk/dist/query/commit.js +632 -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 +602 -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 +277 -0
- package/sdk/dist/query/config-query.js.map +1 -0
- package/sdk/dist/query/config-schema.d.ts +19 -0
- package/sdk/dist/query/config-schema.d.ts.map +1 -0
- package/sdk/dist/query/config-schema.js +26 -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 +165 -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 +299 -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 +364 -0
- package/sdk/dist/query/frontmatter.js.map +1 -0
- package/sdk/dist/query/helpers.d.ts +194 -0
- package/sdk/dist/query/helpers.d.ts.map +1 -0
- package/sdk/dist/query/helpers.js +540 -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 +735 -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 +1228 -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 +1823 -0
- package/sdk/dist/query/phase-lifecycle.js.map +1 -0
- package/sdk/dist/query/phase-list-queries.d.ts +20 -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 +25 -0
- package/sdk/dist/query/phase-roadmap-mutation.d.ts.map +1 -0
- package/sdk/dist/query/phase-roadmap-mutation.js +76 -0
- package/sdk/dist/query/phase-roadmap-mutation.js.map +1 -0
- package/sdk/dist/query/phase-uat-passed.d.ts +46 -0
- package/sdk/dist/query/phase-uat-passed.d.ts.map +1 -0
- package/sdk/dist/query/phase-uat-passed.js +238 -0
- package/sdk/dist/query/phase-uat-passed.js.map +1 -0
- package/sdk/dist/query/phase.d.ts +104 -0
- package/sdk/dist/query/phase.d.ts.map +1 -0
- package/sdk/dist/query/phase.js +617 -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/prompt-budget.d.ts +14 -0
- package/sdk/dist/query/prompt-budget.d.ts.map +1 -0
- package/sdk/dist/query/prompt-budget.js +417 -0
- package/sdk/dist/query/prompt-budget.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-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.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 +160 -0
- package/sdk/dist/query/roadmap.d.ts.map +1 -0
- package/sdk/dist/query/roadmap.js +982 -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 +1635 -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 +443 -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 +42 -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 +1001 -0
- package/sdk/dist/query/validate.js.map +1 -0
- package/sdk/dist/query/verify.d.ts +98 -0
- package/sdk/dist/query/verify.d.ts.map +1 -0
- package/sdk/dist/query/verify.js +593 -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 +24 -0
- package/sdk/dist/query/workstream-inventory.d.ts.map +1 -0
- package/sdk/dist/query/workstream-inventory.js +120 -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 +9 -0
- package/sdk/dist/query/worktree.d.ts.map +1 -0
- package/sdk/dist/query/worktree.js +79 -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-gsd-tools-path.d.ts +2 -0
- package/sdk/dist/query-gsd-tools-path.d.ts.map +1 -0
- package/sdk/dist/query-gsd-tools-path.js +2 -0
- package/sdk/dist/query-gsd-tools-path.js.map +1 -0
- package/sdk/dist/query-gsd-tools-runtime.d.ts +20 -0
- package/sdk/dist/query-gsd-tools-runtime.d.ts.map +1 -0
- package/sdk/dist/query-gsd-tools-runtime.js +47 -0
- package/sdk/dist/query-gsd-tools-runtime.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 +86 -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-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-bridge-sync/index.d.ts +96 -0
- package/sdk/dist/runtime-bridge-sync/index.d.ts.map +1 -0
- package/sdk/dist/runtime-bridge-sync/index.js +109 -0
- package/sdk/dist/runtime-bridge-sync/index.js.map +1 -0
- package/sdk/dist/runtime-bridge-sync/worker.d.ts +2 -0
- package/sdk/dist/runtime-bridge-sync/worker.d.ts.map +1 -0
- package/sdk/dist/runtime-bridge-sync/worker.js +180 -0
- package/sdk/dist/runtime-bridge-sync/worker.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/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-inventory/builder.d.ts +88 -0
- package/sdk/dist/workstream-inventory/builder.d.ts.map +1 -0
- package/sdk/dist/workstream-inventory/builder.js +84 -0
- package/sdk/dist/workstream-inventory/builder.js.map +1 -0
- package/sdk/dist/workstream-name-policy.d.ts +37 -0
- package/sdk/dist/workstream-name-policy.d.ts.map +1 -0
- package/sdk/dist/workstream-name-policy.js +53 -0
- package/sdk/dist/workstream-name-policy.js.map +1 -0
- package/sdk/dist/workstream-utils.d.ts +23 -0
- package/sdk/dist/workstream-utils.d.ts.map +1 -0
- package/sdk/dist/workstream-utils.js +34 -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 +2530 -0
- package/sdk/package.json +77 -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/config-defaults.manifest.json +75 -0
- package/sdk/shared/config-schema.manifest.json +151 -0
- package/sdk/shared/model-catalog.json +122 -0
- package/sdk/src/assembled-prompts.test.ts +349 -0
- package/sdk/src/bug-3589-planning-paths-validation.test.ts +89 -0
- package/sdk/src/bug-3591-gsdtools-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 +277 -0
- package/sdk/src/config.ts +202 -0
- package/sdk/src/configuration/index.test.ts +318 -0
- package/sdk/src/configuration/index.ts +325 -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 +1031 -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/gsd-tools-error.test.ts +21 -0
- package/sdk/src/gsd-tools-error.ts +65 -0
- package/sdk/src/gsd-tools.test.ts +472 -0
- package/sdk/src/gsd-tools.ts +237 -0
- package/sdk/src/gsd-transport-policy.test.ts +34 -0
- package/sdk/src/gsd-transport-policy.ts +48 -0
- package/sdk/src/gsd-transport.test.ts +299 -0
- package/sdk/src/gsd-transport.ts +118 -0
- package/sdk/src/index.ts +366 -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.ts +259 -0
- package/sdk/src/phase-runner.integration.test.ts +377 -0
- package/sdk/src/phase-runner.test.ts +3660 -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/project-root/index.test.ts +186 -0
- package/sdk/src/project-root/index.ts +144 -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 +303 -0
- package/sdk/src/query/check-ship-ready.ts +136 -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 +154 -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 +123 -0
- package/sdk/src/query/command-manifest.init.ts +24 -0
- package/sdk/src/query/command-manifest.non-family.ts +86 -0
- package/sdk/src/query/command-manifest.phase.ts +17 -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 +17 -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 +111 -0
- package/sdk/src/query/command-static-catalog-foundation.ts +111 -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 +717 -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 +705 -0
- package/sdk/src/query/config-query.test.ts +472 -0
- package/sdk/src/query/config-query.ts +314 -0
- package/sdk/src/query/config-schema.ts +35 -0
- package/sdk/src/query/decisions.test.ts +221 -0
- package/sdk/src/query/decisions.ts +196 -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 +328 -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 +566 -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 +788 -0
- package/sdk/src/query/init-complex.ts +815 -0
- package/sdk/src/query/init-workstream-milestone-op.test.ts +321 -0
- package/sdk/src/query/init.test.ts +791 -0
- package/sdk/src/query/init.ts +1335 -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 +1971 -0
- package/sdk/src/query/phase-lifecycle.ts +2210 -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 +82 -0
- package/sdk/src/query/phase-uat-passed.test.ts +593 -0
- package/sdk/src/query/phase-uat-passed.ts +297 -0
- package/sdk/src/query/phase.test.ts +693 -0
- package/sdk/src/query/phase.ts +741 -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/prompt-budget.ts +556 -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.ts +5 -0
- package/sdk/src/query/query-dispatch-formatting.ts +5 -0
- package/sdk/src/query/query-dispatch-observability.ts +6 -0
- package/sdk/src/query/query-dispatch.test.ts +699 -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 +1250 -0
- package/sdk/src/query/roadmap.ts +1131 -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 +1210 -0
- package/sdk/src/query/state-mutation.ts +1814 -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 +476 -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 +924 -0
- package/sdk/src/query/validate.ts +1054 -0
- package/sdk/src/query/verify.test.ts +414 -0
- package/sdk/src/query/verify.ts +656 -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 +143 -0
- package/sdk/src/query/workstream.test.ts +153 -0
- package/sdk/src/query/workstream.ts +324 -0
- package/sdk/src/query/worktree.ts +84 -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-gsd-tools-path.ts +1 -0
- package/sdk/src/query-gsd-tools-runtime.ts +89 -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 +93 -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-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-bridge-sync/index.test.ts +164 -0
- package/sdk/src/runtime-bridge-sync/index.ts +154 -0
- package/sdk/src/runtime-bridge-sync/projectdir-regression.test.ts +150 -0
- package/sdk/src/runtime-bridge-sync/worker.ts +224 -0
- package/sdk/src/runtime-gate.test.ts +84 -0
- package/sdk/src/runtime-gate.ts +52 -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-inventory/builder.test.ts +241 -0
- package/sdk/src/workstream-inventory/builder.ts +170 -0
- package/sdk/src/workstream-name-policy.ts +57 -0
- package/sdk/src/workstream-utils.ts +36 -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
|
@@ -0,0 +1,1635 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* STATE.md mutation handlers — write operations with lockfile atomicity.
|
|
3
|
+
*
|
|
4
|
+
* Ported from get-shit-done/bin/lib/state.cjs.
|
|
5
|
+
* Provides STATE.md mutation commands: update, patch, begin-phase,
|
|
6
|
+
* advance-plan, record-metric, update-progress, add-decision, add-blocker,
|
|
7
|
+
* resolve-blocker, record-session, validate, sync, prune, signal-waiting, signal-resume.
|
|
8
|
+
*
|
|
9
|
+
* All writes go through readModifyWriteStateMd which acquires a lockfile,
|
|
10
|
+
* applies the modifier, syncs frontmatter, normalizes markdown, and writes.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* import { stateUpdate, stateBeginPhase } from './state-mutation.js';
|
|
15
|
+
*
|
|
16
|
+
* await stateUpdate(['Status', 'executing'], '/project');
|
|
17
|
+
* await stateBeginPhase(['11', 'State Mutations', '3'], '/project');
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
import { open, unlink, stat, readFile, writeFile, readdir } from 'node:fs/promises';
|
|
21
|
+
import { constants, unlinkSync, existsSync, mkdirSync, writeFileSync, readdirSync, readFileSync, realpathSync, } from 'node:fs';
|
|
22
|
+
import { isAbsolute, join, relative, resolve } from 'node:path';
|
|
23
|
+
import { GSDError, ErrorClassification } from '../errors.js';
|
|
24
|
+
import { extractFrontmatter, stripFrontmatter } from './frontmatter.js';
|
|
25
|
+
import { reconstructFrontmatter } from './frontmatter-mutation.js';
|
|
26
|
+
import { comparePhaseNum, normalizePhaseName, phaseTokenMatches, planningPaths, normalizeMd, } from './helpers.js';
|
|
27
|
+
import { buildStateFrontmatter, getMilestonePhaseFilter } from './state.js';
|
|
28
|
+
import { scanPhasePlans } from './plan-scan.js';
|
|
29
|
+
import { stateExtractField, stateReplaceField, stateReplaceFieldWithFallback, computeProgressPercent } from './state-document.js';
|
|
30
|
+
const PROGRESS_FRONTMATTER_FIELDS = new Set(['Progress', 'Total Plans in Phase', 'Total Phases']);
|
|
31
|
+
// ─── Process exit lock cleanup (D2 — match CJS state.cjs:16-23) ─────────
|
|
32
|
+
/**
|
|
33
|
+
* Module-level set tracking held locks for process.on('exit') cleanup.
|
|
34
|
+
* Exported for test access only.
|
|
35
|
+
*/
|
|
36
|
+
export const _heldStateLocks = new Set();
|
|
37
|
+
process.on('exit', () => {
|
|
38
|
+
for (const lockPath of _heldStateLocks) {
|
|
39
|
+
try {
|
|
40
|
+
unlinkSync(lockPath);
|
|
41
|
+
}
|
|
42
|
+
catch { /* already gone */ }
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
export { stateReplaceField };
|
|
46
|
+
/**
|
|
47
|
+
* Update fields within the ## Current Position section.
|
|
48
|
+
*
|
|
49
|
+
* Only updates fields that already exist in the section.
|
|
50
|
+
*/
|
|
51
|
+
function updateCurrentPositionFields(content, fields) {
|
|
52
|
+
const posPattern = /(##\s*Current Position\s*\n)([\s\S]*?)(?=\n##|$)/i;
|
|
53
|
+
const posMatch = content.match(posPattern);
|
|
54
|
+
if (!posMatch)
|
|
55
|
+
return content;
|
|
56
|
+
let posBody = posMatch[2];
|
|
57
|
+
if (fields.status && /^Status:/m.test(posBody)) {
|
|
58
|
+
posBody = posBody.replace(/^Status:.*$/m, `Status: ${fields.status}`);
|
|
59
|
+
}
|
|
60
|
+
if (fields.lastActivity && /^Last activity:/im.test(posBody)) {
|
|
61
|
+
posBody = posBody.replace(/^Last activity:.*$/im, `Last activity: ${fields.lastActivity}`);
|
|
62
|
+
}
|
|
63
|
+
if (fields.plan && /^Plan:/m.test(posBody)) {
|
|
64
|
+
posBody = posBody.replace(/^Plan:.*$/m, `Plan: ${fields.plan}`);
|
|
65
|
+
}
|
|
66
|
+
return content.replace(posPattern, () => `${posMatch[1]}${posBody}`);
|
|
67
|
+
}
|
|
68
|
+
/** Port of `readTextArgOrFile` from `state.cjs` — inline text or file path under project root. */
|
|
69
|
+
function readTextArgOrFile(projectDir, value, filePath, label) {
|
|
70
|
+
if (!filePath) {
|
|
71
|
+
return (value ?? '').trim();
|
|
72
|
+
}
|
|
73
|
+
// Resolve symlinks on both the project root and the target path before
|
|
74
|
+
// comparing — matches CJS `validatePath` in security.cjs. On macOS,
|
|
75
|
+
// `os.tmpdir()` returns `/var/folders/...` but the realpath is
|
|
76
|
+
// `/private/var/folders/...`; without realpath normalization, the
|
|
77
|
+
// `relative()` check sees `/private/var/...` vs `/var/...` as different
|
|
78
|
+
// tree roots and rejects safe in-project files. Symlink resolution falls
|
|
79
|
+
// back to logical resolve() when the path doesn't exist yet (e.g., file
|
|
80
|
+
// about to be created).
|
|
81
|
+
function realpathOrResolve(p) {
|
|
82
|
+
try {
|
|
83
|
+
return realpathSync(p);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return resolve(p);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const resolvedBase = realpathOrResolve(resolve(projectDir));
|
|
90
|
+
const targetLogical = isAbsolute(filePath) ? resolve(filePath) : resolve(resolvedBase, filePath);
|
|
91
|
+
const resolvedTarget = realpathOrResolve(targetLogical);
|
|
92
|
+
const rel = relative(resolvedBase, resolvedTarget);
|
|
93
|
+
if (rel.startsWith('..') || isAbsolute(rel)) {
|
|
94
|
+
throw new Error(`${label} path rejected: outside project directory`);
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
return readFileSync(resolvedTarget, 'utf-8').trimEnd();
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
throw new Error(`${label} file not found: ${filePath}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// ─── Lockfile helpers ─────────────────────────────────────────────────────
|
|
104
|
+
/**
|
|
105
|
+
* If the lock file contains a PID, return whether that process is gone (stolen
|
|
106
|
+
* locks after SIGKILL/crash). Null if the file could not be read.
|
|
107
|
+
*/
|
|
108
|
+
async function isLockProcessDead(lockPath) {
|
|
109
|
+
try {
|
|
110
|
+
const raw = await readFile(lockPath, 'utf-8');
|
|
111
|
+
const pid = parseInt(raw.trim(), 10);
|
|
112
|
+
// An empty or unparseable lock file means the writer opened the file with
|
|
113
|
+
// O_EXCL but hasn't finished writing the PID yet (async window between
|
|
114
|
+
// `open` and `writeFile`). Treat this as "unknown / still alive" — do NOT
|
|
115
|
+
// steal the lock, let the normal retry + timeout path handle it.
|
|
116
|
+
if (!Number.isFinite(pid) || pid <= 0)
|
|
117
|
+
return null;
|
|
118
|
+
try {
|
|
119
|
+
process.kill(pid, 0);
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Acquire a lockfile for STATE.md operations.
|
|
132
|
+
*
|
|
133
|
+
* Uses O_CREAT|O_EXCL for atomic creation. Retries up to 10 times with
|
|
134
|
+
* 200ms + jitter delay. Cleans stale locks when the holder PID is dead, or when
|
|
135
|
+
* the lock file is older than 10 seconds (existing heuristic).
|
|
136
|
+
*
|
|
137
|
+
* @param statePath - Path to STATE.md
|
|
138
|
+
* @returns Path to the lockfile
|
|
139
|
+
*/
|
|
140
|
+
export async function acquireStateLock(statePath) {
|
|
141
|
+
const lockPath = statePath + '.lock';
|
|
142
|
+
const maxRetries = 10;
|
|
143
|
+
const retryDelay = 200;
|
|
144
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
145
|
+
try {
|
|
146
|
+
const fd = await open(lockPath, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY);
|
|
147
|
+
await fd.writeFile(String(process.pid));
|
|
148
|
+
await fd.close();
|
|
149
|
+
_heldStateLocks.add(lockPath);
|
|
150
|
+
return lockPath;
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
if (err instanceof Error && err.code === 'EEXIST') {
|
|
154
|
+
try {
|
|
155
|
+
const dead = await isLockProcessDead(lockPath);
|
|
156
|
+
if (dead === true) {
|
|
157
|
+
await unlink(lockPath);
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
const s = await stat(lockPath);
|
|
161
|
+
if (Date.now() - s.mtimeMs > 10000) {
|
|
162
|
+
await unlink(lockPath);
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
catch { /* lock released between check */ }
|
|
167
|
+
if (i === maxRetries - 1) {
|
|
168
|
+
try {
|
|
169
|
+
await unlink(lockPath);
|
|
170
|
+
}
|
|
171
|
+
catch { /* ignore */ }
|
|
172
|
+
return lockPath;
|
|
173
|
+
}
|
|
174
|
+
await new Promise(r => setTimeout(r, retryDelay + Math.floor(Math.random() * 50)));
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
// D3: Graceful degradation on non-EEXIST errors (match CJS state.cjs:889)
|
|
178
|
+
return lockPath;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return lockPath;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Release a lockfile.
|
|
186
|
+
*
|
|
187
|
+
* @param lockPath - Path to the lockfile to release
|
|
188
|
+
*/
|
|
189
|
+
export async function releaseStateLock(lockPath) {
|
|
190
|
+
_heldStateLocks.delete(lockPath);
|
|
191
|
+
try {
|
|
192
|
+
await unlink(lockPath);
|
|
193
|
+
}
|
|
194
|
+
catch { /* already gone */ }
|
|
195
|
+
}
|
|
196
|
+
// ─── Frontmatter sync + write helpers ─────────────────────────────────────
|
|
197
|
+
/**
|
|
198
|
+
* Sync STATE.md content with rebuilt YAML frontmatter.
|
|
199
|
+
*
|
|
200
|
+
* Strips existing frontmatter, rebuilds from body + disk, and splices back.
|
|
201
|
+
* Preserves existing status when body-derived status is 'unknown'.
|
|
202
|
+
*/
|
|
203
|
+
async function syncStateFrontmatter(content, projectDir, workstream, options = {}) {
|
|
204
|
+
const existingFm = extractFrontmatter(content);
|
|
205
|
+
const body = stripFrontmatter(content);
|
|
206
|
+
const derivedFm = await buildStateFrontmatter(body, projectDir, workstream, options);
|
|
207
|
+
// Preserve existing status when body-derived is 'unknown'
|
|
208
|
+
if (derivedFm.status === 'unknown' && existingFm.status && existingFm.status !== 'unknown') {
|
|
209
|
+
derivedFm.status = existingFm.status;
|
|
210
|
+
}
|
|
211
|
+
const yamlStr = reconstructFrontmatter(derivedFm);
|
|
212
|
+
return `---\n${yamlStr}\n---\n\n${body}`;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Atomic read-modify-write for STATE.md.
|
|
216
|
+
*
|
|
217
|
+
* Holds lock across the entire read -> transform -> write cycle.
|
|
218
|
+
*
|
|
219
|
+
* @param projectDir - Project root directory
|
|
220
|
+
* @param modifier - Function to transform STATE.md content
|
|
221
|
+
* @returns The final written content
|
|
222
|
+
*/
|
|
223
|
+
async function readModifyWriteStateMd(projectDir, modifier, workstream, options = {}) {
|
|
224
|
+
const statePath = planningPaths(projectDir, workstream).state;
|
|
225
|
+
const resync = options.resync !== false;
|
|
226
|
+
const lockPath = await acquireStateLock(statePath);
|
|
227
|
+
try {
|
|
228
|
+
let content;
|
|
229
|
+
try {
|
|
230
|
+
content = await readFile(statePath, 'utf-8');
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
content = '';
|
|
234
|
+
}
|
|
235
|
+
// Strip frontmatter before passing to modifier so that regex replacements
|
|
236
|
+
// operate on body fields only (not on YAML frontmatter keys like 'status:').
|
|
237
|
+
// syncStateFrontmatter rebuilds frontmatter from the modified body + disk.
|
|
238
|
+
const preFm = extractFrontmatter(content);
|
|
239
|
+
const body = stripFrontmatter(content);
|
|
240
|
+
const modified = await modifier(body);
|
|
241
|
+
let synced = await syncStateFrontmatter(modified, projectDir, workstream, {
|
|
242
|
+
preserveExistingProgress: options.preserveExistingProgress,
|
|
243
|
+
});
|
|
244
|
+
if (!resync && preFm && preFm.progress) {
|
|
245
|
+
const postFm = extractFrontmatter(synced);
|
|
246
|
+
postFm.progress = preFm.progress;
|
|
247
|
+
const yamlStr = reconstructFrontmatter(postFm);
|
|
248
|
+
synced = `---\n${yamlStr}\n---\n\n${stripFrontmatter(synced)}`;
|
|
249
|
+
}
|
|
250
|
+
const normalized = normalizeMd(synced);
|
|
251
|
+
await writeFile(statePath, normalized, 'utf-8');
|
|
252
|
+
return normalized;
|
|
253
|
+
}
|
|
254
|
+
finally {
|
|
255
|
+
await releaseStateLock(lockPath);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Full-file read-modify-write for STATE.md — matches CJS `readModifyWriteStateMd` in `state.cjs`
|
|
260
|
+
* (modifier receives entire file content including YAML frontmatter).
|
|
261
|
+
* Used by milestone completion and other flows that replace body fields the same way as the CLI.
|
|
262
|
+
*/
|
|
263
|
+
export async function readModifyWriteStateMdFull(projectDir, modifier, workstream) {
|
|
264
|
+
const statePath = planningPaths(projectDir, workstream).state;
|
|
265
|
+
const lockPath = await acquireStateLock(statePath);
|
|
266
|
+
try {
|
|
267
|
+
let content = '';
|
|
268
|
+
try {
|
|
269
|
+
content = await readFile(statePath, 'utf-8');
|
|
270
|
+
}
|
|
271
|
+
catch {
|
|
272
|
+
/* missing */
|
|
273
|
+
}
|
|
274
|
+
const modified = await modifier(content);
|
|
275
|
+
const synced = await syncStateFrontmatter(modified, projectDir, workstream);
|
|
276
|
+
await writeFile(statePath, normalizeMd(synced), 'utf-8');
|
|
277
|
+
}
|
|
278
|
+
finally {
|
|
279
|
+
await releaseStateLock(lockPath);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
// ─── Exported handlers ────────────────────────────────────────────────────
|
|
283
|
+
/**
|
|
284
|
+
* Query handler for state.update command.
|
|
285
|
+
*
|
|
286
|
+
* Replaces a single field in STATE.md.
|
|
287
|
+
*
|
|
288
|
+
* @param args - args[0]: field name, args[1]: new value
|
|
289
|
+
* @param projectDir - Project root directory
|
|
290
|
+
* @returns QueryResult with { updated: true/false }
|
|
291
|
+
*/
|
|
292
|
+
export const stateUpdate = async (args, projectDir, workstream) => {
|
|
293
|
+
const field = args[0];
|
|
294
|
+
const value = args[1];
|
|
295
|
+
if (!field || value === undefined) {
|
|
296
|
+
throw new GSDError('field and value required for state update', ErrorClassification.Validation);
|
|
297
|
+
}
|
|
298
|
+
// Match CJS `cmdStateUpdate` contract: caller receives `{ updated: false,
|
|
299
|
+
// reason: '...' }` when the operation is a no-op so shell-script consumers
|
|
300
|
+
// can JSON.parse output and branch on the reason. Without an explicit
|
|
301
|
+
// STATE.md check up front, readModifyWriteStateMd's auto-create behavior
|
|
302
|
+
// would mask "STATE.md missing" as a successful no-op write.
|
|
303
|
+
const statePath = planningPaths(projectDir, workstream).state;
|
|
304
|
+
try {
|
|
305
|
+
await readFile(statePath, 'utf-8');
|
|
306
|
+
}
|
|
307
|
+
catch {
|
|
308
|
+
return { data: { updated: false, reason: 'STATE.md not found' } };
|
|
309
|
+
}
|
|
310
|
+
let updated = false;
|
|
311
|
+
const shouldResync = PROGRESS_FRONTMATTER_FIELDS.has(field);
|
|
312
|
+
await readModifyWriteStateMd(projectDir, (content) => {
|
|
313
|
+
const result = stateReplaceField(content, field, value);
|
|
314
|
+
if (result) {
|
|
315
|
+
updated = true;
|
|
316
|
+
return result;
|
|
317
|
+
}
|
|
318
|
+
return content;
|
|
319
|
+
}, workstream, {
|
|
320
|
+
resync: shouldResync,
|
|
321
|
+
preserveExistingProgress: !shouldResync,
|
|
322
|
+
});
|
|
323
|
+
if (!updated) {
|
|
324
|
+
return { data: { updated: false, reason: `Field "${field}" not found in STATE.md` } };
|
|
325
|
+
}
|
|
326
|
+
return { data: { updated: true } };
|
|
327
|
+
};
|
|
328
|
+
/**
|
|
329
|
+
* Query handler for state.patch command.
|
|
330
|
+
*
|
|
331
|
+
* Replaces multiple fields atomically in one lock cycle.
|
|
332
|
+
*
|
|
333
|
+
* @param args - Either `--field value` pairs (CLI / gsd-tools) or a single JSON object string (SDK).
|
|
334
|
+
* @param projectDir - Project root directory
|
|
335
|
+
* @returns QueryResult with `{ updated, failed }` matching `cmdStatePatch` in `state.cjs`
|
|
336
|
+
*/
|
|
337
|
+
export const statePatch = async (args, projectDir, workstream) => {
|
|
338
|
+
let patches;
|
|
339
|
+
if (args.length >= 2 && args[0]?.startsWith('--')) {
|
|
340
|
+
patches = {};
|
|
341
|
+
for (let i = 0; i < args.length; i += 2) {
|
|
342
|
+
const key = args[i]?.replace(/^--/, '');
|
|
343
|
+
const value = args[i + 1];
|
|
344
|
+
if (key && value !== undefined)
|
|
345
|
+
patches[key] = value;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
const jsonString = args[0];
|
|
350
|
+
if (!jsonString) {
|
|
351
|
+
throw new GSDError('JSON patches required', ErrorClassification.Validation);
|
|
352
|
+
}
|
|
353
|
+
try {
|
|
354
|
+
patches = JSON.parse(jsonString);
|
|
355
|
+
}
|
|
356
|
+
catch {
|
|
357
|
+
throw new GSDError('Invalid JSON for patches', ErrorClassification.Validation);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
const updated = [];
|
|
361
|
+
const failed = [];
|
|
362
|
+
const shouldResync = Object.keys(patches).some(field => PROGRESS_FRONTMATTER_FIELDS.has(field));
|
|
363
|
+
await readModifyWriteStateMd(projectDir, (content) => {
|
|
364
|
+
for (const [field, value] of Object.entries(patches)) {
|
|
365
|
+
const result = stateReplaceField(content, field, String(value));
|
|
366
|
+
if (result) {
|
|
367
|
+
content = result;
|
|
368
|
+
updated.push(field);
|
|
369
|
+
}
|
|
370
|
+
else {
|
|
371
|
+
failed.push(field);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
return content;
|
|
375
|
+
}, workstream, {
|
|
376
|
+
resync: shouldResync,
|
|
377
|
+
preserveExistingProgress: !shouldResync,
|
|
378
|
+
});
|
|
379
|
+
return { data: { updated, failed } };
|
|
380
|
+
};
|
|
381
|
+
/**
|
|
382
|
+
* Query handler for state.begin-phase command.
|
|
383
|
+
*
|
|
384
|
+
* Sets phase, plan, status, progress, and current focus fields.
|
|
385
|
+
* Rewrites the Current Position section.
|
|
386
|
+
*
|
|
387
|
+
* Accepts gsd-tools-style argv: `--phase N [--name S] [--plans C]` or positional
|
|
388
|
+
* `[phase, name?, planCount?]` (tests and direct handler calls).
|
|
389
|
+
*
|
|
390
|
+
* @param args - Named or positional phase / name / plan count
|
|
391
|
+
* @param projectDir - Project root directory
|
|
392
|
+
* @returns QueryResult with phase metadata and `updated` field names (for raw parity)
|
|
393
|
+
*/
|
|
394
|
+
export const stateBeginPhase = async (args, projectDir, workstream) => {
|
|
395
|
+
const named = parseNamedArgs(args, ['phase', 'name', 'plans']);
|
|
396
|
+
let phaseNumber = named.phase || '';
|
|
397
|
+
let phaseName = named.name || '';
|
|
398
|
+
let plansStr = named.plans;
|
|
399
|
+
const positionalMode = args.length > 0 && !String(args[0]).startsWith('--');
|
|
400
|
+
if (positionalMode) {
|
|
401
|
+
if (!phaseNumber)
|
|
402
|
+
phaseNumber = args[0] ?? '';
|
|
403
|
+
if (!phaseName)
|
|
404
|
+
phaseName = args[1] ?? '';
|
|
405
|
+
if (plansStr === null && args[2] !== undefined && !String(args[2]).startsWith('--')) {
|
|
406
|
+
plansStr = args[2];
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
const plansParsed = plansStr !== null && plansStr !== '' ? parseInt(String(plansStr), 10) : NaN;
|
|
410
|
+
const planNum = Number.isFinite(plansParsed) && !Number.isNaN(plansParsed) && plansParsed > 0
|
|
411
|
+
? plansParsed
|
|
412
|
+
: null;
|
|
413
|
+
if (!phaseNumber) {
|
|
414
|
+
throw new GSDError('phase number required', ErrorClassification.Validation);
|
|
415
|
+
}
|
|
416
|
+
const today = new Date().toISOString().split('T')[0];
|
|
417
|
+
const updated = [];
|
|
418
|
+
await readModifyWriteStateMd(projectDir, (content) => {
|
|
419
|
+
// Update bold/plain fields
|
|
420
|
+
const statusValue = `Executing Phase ${phaseNumber}`;
|
|
421
|
+
let u = stateReplaceField(content, 'Status', statusValue);
|
|
422
|
+
if (u) {
|
|
423
|
+
content = u;
|
|
424
|
+
updated.push('Status');
|
|
425
|
+
}
|
|
426
|
+
u = stateReplaceField(content, 'Last Activity', today);
|
|
427
|
+
if (u) {
|
|
428
|
+
content = u;
|
|
429
|
+
updated.push('Last Activity');
|
|
430
|
+
}
|
|
431
|
+
const activityDesc = `Phase ${phaseNumber} execution started`;
|
|
432
|
+
u = stateReplaceField(content, 'Last Activity Description', activityDesc);
|
|
433
|
+
if (u) {
|
|
434
|
+
content = u;
|
|
435
|
+
updated.push('Last Activity Description');
|
|
436
|
+
}
|
|
437
|
+
u = stateReplaceField(content, 'Current Phase', String(phaseNumber));
|
|
438
|
+
if (u) {
|
|
439
|
+
content = u;
|
|
440
|
+
updated.push('Current Phase');
|
|
441
|
+
}
|
|
442
|
+
if (phaseName) {
|
|
443
|
+
u = stateReplaceField(content, 'Current Phase Name', phaseName);
|
|
444
|
+
if (u) {
|
|
445
|
+
content = u;
|
|
446
|
+
updated.push('Current Phase Name');
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
u = stateReplaceField(content, 'Current Plan', '1');
|
|
450
|
+
if (u) {
|
|
451
|
+
content = u;
|
|
452
|
+
updated.push('Current Plan');
|
|
453
|
+
}
|
|
454
|
+
if (planNum !== null && !Number.isNaN(planNum)) {
|
|
455
|
+
u = stateReplaceField(content, 'Total Plans in Phase', String(planNum));
|
|
456
|
+
if (u) {
|
|
457
|
+
content = u;
|
|
458
|
+
updated.push('Total Plans in Phase');
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
// Update **Current focus:**
|
|
462
|
+
const focusLabel = phaseName ? `Phase ${phaseNumber} — ${phaseName}` : `Phase ${phaseNumber}`;
|
|
463
|
+
const focusPattern = /(\*\*Current focus:\*\*\s*).*/i;
|
|
464
|
+
if (focusPattern.test(content)) {
|
|
465
|
+
content = content.replace(focusPattern, (_match, prefix) => `${prefix}${focusLabel}`);
|
|
466
|
+
updated.push('Current focus');
|
|
467
|
+
}
|
|
468
|
+
// Update ## Current Position section
|
|
469
|
+
const positionPattern = /(##\s*Current Position\s*\n)([\s\S]*?)(?=\n##|$)/i;
|
|
470
|
+
const positionMatch = content.match(positionPattern);
|
|
471
|
+
if (positionMatch) {
|
|
472
|
+
const header = positionMatch[1];
|
|
473
|
+
let posBody = positionMatch[2];
|
|
474
|
+
const newPhase = `Phase: ${phaseNumber}${phaseName ? ` (${phaseName})` : ''} — EXECUTING`;
|
|
475
|
+
if (/^Phase:/m.test(posBody)) {
|
|
476
|
+
posBody = posBody.replace(/^Phase:.*$/m, newPhase);
|
|
477
|
+
}
|
|
478
|
+
else {
|
|
479
|
+
posBody = newPhase + '\n' + posBody;
|
|
480
|
+
}
|
|
481
|
+
const newPlan = `Plan: 1 of ${planNum ?? '?'}`;
|
|
482
|
+
if (/^Plan:/m.test(posBody)) {
|
|
483
|
+
posBody = posBody.replace(/^Plan:.*$/m, newPlan);
|
|
484
|
+
}
|
|
485
|
+
else {
|
|
486
|
+
posBody = posBody.replace(/^(Phase:.*$)/m, `$1\n${newPlan}`);
|
|
487
|
+
}
|
|
488
|
+
const newStatus = `Status: Executing Phase ${phaseNumber}`;
|
|
489
|
+
if (/^Status:/m.test(posBody)) {
|
|
490
|
+
posBody = posBody.replace(/^Status:.*$/m, newStatus);
|
|
491
|
+
}
|
|
492
|
+
const newActivity = `Last activity: ${today} -- Phase ${phaseNumber} execution started`;
|
|
493
|
+
if (/^Last activity:/im.test(posBody)) {
|
|
494
|
+
posBody = posBody.replace(/^Last activity:.*$/im, newActivity);
|
|
495
|
+
}
|
|
496
|
+
content = content.replace(positionPattern, () => `${header}${posBody}`);
|
|
497
|
+
updated.push('Current Position');
|
|
498
|
+
}
|
|
499
|
+
return content;
|
|
500
|
+
}, workstream);
|
|
501
|
+
return {
|
|
502
|
+
data: {
|
|
503
|
+
updated,
|
|
504
|
+
phase: phaseNumber,
|
|
505
|
+
phase_name: phaseName || null,
|
|
506
|
+
plan_count: planNum !== null && !Number.isNaN(planNum) ? planNum : null,
|
|
507
|
+
},
|
|
508
|
+
};
|
|
509
|
+
};
|
|
510
|
+
/**
|
|
511
|
+
* Query handler for state.advance-plan command.
|
|
512
|
+
*
|
|
513
|
+
* Increments plan counter. Detects phase completion when at last plan.
|
|
514
|
+
*
|
|
515
|
+
* @param args - unused
|
|
516
|
+
* @param projectDir - Project root directory
|
|
517
|
+
* @returns QueryResult with { advanced, current_plan, total_plans }
|
|
518
|
+
*/
|
|
519
|
+
export const stateAdvancePlan = async (_args, projectDir, workstream) => {
|
|
520
|
+
const today = new Date().toISOString().split('T')[0];
|
|
521
|
+
let result = { error: 'STATE.md not found' };
|
|
522
|
+
await readModifyWriteStateMd(projectDir, (content) => {
|
|
523
|
+
// Parse current plan info (content already has frontmatter stripped)
|
|
524
|
+
const legacyPlan = stateExtractField(content, 'Current Plan');
|
|
525
|
+
const legacyTotal = stateExtractField(content, 'Total Plans in Phase');
|
|
526
|
+
const planField = stateExtractField(content, 'Plan');
|
|
527
|
+
let currentPlan;
|
|
528
|
+
let totalPlans;
|
|
529
|
+
let useCompoundFormat = false;
|
|
530
|
+
let compoundPlanField = null;
|
|
531
|
+
if (legacyPlan && legacyTotal) {
|
|
532
|
+
currentPlan = parseInt(legacyPlan, 10);
|
|
533
|
+
totalPlans = parseInt(legacyTotal, 10);
|
|
534
|
+
}
|
|
535
|
+
else if (planField) {
|
|
536
|
+
currentPlan = parseInt(planField, 10);
|
|
537
|
+
const ofMatch = planField.match(/of\s+(\d+)/);
|
|
538
|
+
totalPlans = ofMatch ? parseInt(ofMatch[1], 10) : NaN;
|
|
539
|
+
useCompoundFormat = true;
|
|
540
|
+
compoundPlanField = planField;
|
|
541
|
+
}
|
|
542
|
+
else {
|
|
543
|
+
result = { error: 'Cannot parse Current Plan or Total Plans in Phase from STATE.md' };
|
|
544
|
+
return content;
|
|
545
|
+
}
|
|
546
|
+
if (isNaN(currentPlan) || isNaN(totalPlans)) {
|
|
547
|
+
result = { error: 'Cannot parse Current Plan or Total Plans in Phase from STATE.md' };
|
|
548
|
+
return content;
|
|
549
|
+
}
|
|
550
|
+
if (currentPlan >= totalPlans) {
|
|
551
|
+
// Phase complete
|
|
552
|
+
content = stateReplaceFieldWithFallback(content, 'Status', null, 'Phase complete — ready for verification');
|
|
553
|
+
content = stateReplaceFieldWithFallback(content, 'Last Activity', 'Last activity', today);
|
|
554
|
+
content = updateCurrentPositionFields(content, {
|
|
555
|
+
status: 'Phase complete — ready for verification',
|
|
556
|
+
lastActivity: today,
|
|
557
|
+
});
|
|
558
|
+
result = {
|
|
559
|
+
advanced: false,
|
|
560
|
+
reason: 'last_plan',
|
|
561
|
+
current_plan: currentPlan,
|
|
562
|
+
total_plans: totalPlans,
|
|
563
|
+
status: 'ready_for_verification',
|
|
564
|
+
};
|
|
565
|
+
return content;
|
|
566
|
+
}
|
|
567
|
+
// Advance to next plan
|
|
568
|
+
const newPlan = currentPlan + 1;
|
|
569
|
+
let planDisplayValue;
|
|
570
|
+
if (useCompoundFormat && compoundPlanField) {
|
|
571
|
+
planDisplayValue = compoundPlanField.replace(/^\d+/, String(newPlan));
|
|
572
|
+
content = stateReplaceField(content, 'Plan', planDisplayValue) || content;
|
|
573
|
+
}
|
|
574
|
+
else {
|
|
575
|
+
planDisplayValue = `${newPlan} of ${totalPlans}`;
|
|
576
|
+
content = stateReplaceField(content, 'Current Plan', String(newPlan)) || content;
|
|
577
|
+
}
|
|
578
|
+
content = stateReplaceFieldWithFallback(content, 'Status', null, 'Ready to execute');
|
|
579
|
+
content = stateReplaceFieldWithFallback(content, 'Last Activity', 'Last activity', today);
|
|
580
|
+
content = updateCurrentPositionFields(content, {
|
|
581
|
+
status: 'Ready to execute',
|
|
582
|
+
lastActivity: today,
|
|
583
|
+
plan: planDisplayValue,
|
|
584
|
+
});
|
|
585
|
+
result = { advanced: true, previous_plan: currentPlan, current_plan: newPlan, total_plans: totalPlans };
|
|
586
|
+
return content;
|
|
587
|
+
}, workstream);
|
|
588
|
+
return { data: result };
|
|
589
|
+
};
|
|
590
|
+
/**
|
|
591
|
+
* Query handler for state.record-metric command.
|
|
592
|
+
*
|
|
593
|
+
* Appends a row to the Performance Metrics table.
|
|
594
|
+
*
|
|
595
|
+
* @param args - gsd-tools argv: `--phase`, `--plan`, `--duration`, `--tasks`, `--files`
|
|
596
|
+
* @param projectDir - Project root directory
|
|
597
|
+
* @returns QueryResult with { recorded: true/false }
|
|
598
|
+
*/
|
|
599
|
+
export const stateRecordMetric = async (args, projectDir, workstream) => {
|
|
600
|
+
const parsed = parseNamedArgs(args, ['phase', 'plan', 'duration', 'tasks', 'files']);
|
|
601
|
+
const phase = parsed.phase;
|
|
602
|
+
const plan = parsed.plan;
|
|
603
|
+
const duration = parsed.duration;
|
|
604
|
+
const tasks = parsed.tasks || '-';
|
|
605
|
+
const files = parsed.files || '-';
|
|
606
|
+
if (!phase || !plan || !duration) {
|
|
607
|
+
return { data: { error: 'phase, plan, and duration required' } };
|
|
608
|
+
}
|
|
609
|
+
// CJS `cmdStateRecordMetric` contract: error out if STATE.md doesn't exist
|
|
610
|
+
// rather than auto-creating it (which `readModifyWriteStateMd` would do).
|
|
611
|
+
const statePath = planningPaths(projectDir, workstream).state;
|
|
612
|
+
try {
|
|
613
|
+
await readFile(statePath, 'utf-8');
|
|
614
|
+
}
|
|
615
|
+
catch {
|
|
616
|
+
return { data: { error: 'STATE.md not found' } };
|
|
617
|
+
}
|
|
618
|
+
let recorded = false;
|
|
619
|
+
let created = false;
|
|
620
|
+
await readModifyWriteStateMd(projectDir, (content) => {
|
|
621
|
+
const metricsPattern = /(##\s*Performance Metrics[\s\S]*?\n\|[^\n]+\n\|[-|\s]+\n)([\s\S]*?)(?=\n##|\n$|$)/i;
|
|
622
|
+
const metricsMatch = content.match(metricsPattern);
|
|
623
|
+
const newRow = `| Phase ${phase} P${plan} | ${duration} | ${tasks} tasks | ${files} files |`;
|
|
624
|
+
if (metricsMatch) {
|
|
625
|
+
let tableBody = metricsMatch[2].trimEnd();
|
|
626
|
+
if (tableBody.trim() === '' || tableBody.includes('None yet')) {
|
|
627
|
+
tableBody = newRow;
|
|
628
|
+
}
|
|
629
|
+
else {
|
|
630
|
+
tableBody = tableBody + '\n' + newRow;
|
|
631
|
+
}
|
|
632
|
+
content = content.replace(metricsPattern, (_match, header) => `${header}${tableBody}\n`);
|
|
633
|
+
recorded = true;
|
|
634
|
+
}
|
|
635
|
+
else {
|
|
636
|
+
// Section absent — DWIM: auto-create canonical ## Performance Metrics scaffold,
|
|
637
|
+
// then append the row. Matches CJS state.cjs DWIM behavior.
|
|
638
|
+
const scaffold = [
|
|
639
|
+
'',
|
|
640
|
+
'## Performance Metrics',
|
|
641
|
+
'',
|
|
642
|
+
'| Phase | Plan | Duration | Notes |',
|
|
643
|
+
'|-------|------|----------|-------|',
|
|
644
|
+
newRow,
|
|
645
|
+
'',
|
|
646
|
+
].join('\n');
|
|
647
|
+
content = content.trimEnd() + '\n' + scaffold;
|
|
648
|
+
recorded = true;
|
|
649
|
+
created = true;
|
|
650
|
+
}
|
|
651
|
+
return content;
|
|
652
|
+
}, workstream);
|
|
653
|
+
const result = { recorded: true, phase, plan, duration };
|
|
654
|
+
if (created)
|
|
655
|
+
result.created = true;
|
|
656
|
+
return { data: result };
|
|
657
|
+
};
|
|
658
|
+
/**
|
|
659
|
+
* Query handler for state.update-progress command.
|
|
660
|
+
*
|
|
661
|
+
* Scans disk to count completed/total plans and updates progress bar.
|
|
662
|
+
*
|
|
663
|
+
* @param args - unused
|
|
664
|
+
* @param projectDir - Project root directory
|
|
665
|
+
* @returns QueryResult with { updated, percent, completed, total }
|
|
666
|
+
*/
|
|
667
|
+
export const stateUpdateProgress = async (_args, projectDir, workstream) => {
|
|
668
|
+
// CJS `cmdStateUpdateProgress` contract: error out when STATE.md is missing.
|
|
669
|
+
// Without this check the SDK silently returns `{ updated: false }` with no
|
|
670
|
+
// STATE.md-aware reason, masking the missing-file condition.
|
|
671
|
+
const statePath = planningPaths(projectDir, workstream).state;
|
|
672
|
+
try {
|
|
673
|
+
await readFile(statePath, 'utf-8');
|
|
674
|
+
}
|
|
675
|
+
catch {
|
|
676
|
+
return { data: { error: 'STATE.md not found' } };
|
|
677
|
+
}
|
|
678
|
+
const phasesDir = planningPaths(projectDir, workstream).phases;
|
|
679
|
+
let totalPlans = 0;
|
|
680
|
+
let totalSummaries = 0;
|
|
681
|
+
try {
|
|
682
|
+
const isDirInMilestone = await getMilestonePhaseFilter(projectDir, workstream);
|
|
683
|
+
const entries = await readdir(phasesDir, { withFileTypes: true });
|
|
684
|
+
const phaseDirs = entries
|
|
685
|
+
.filter(e => e.isDirectory())
|
|
686
|
+
.map(e => e.name)
|
|
687
|
+
.filter(isDirInMilestone);
|
|
688
|
+
for (const dir of phaseDirs) {
|
|
689
|
+
const files = await readdir(join(phasesDir, dir));
|
|
690
|
+
totalPlans += files.filter(f => /-PLAN\.md$/i.test(f)).length;
|
|
691
|
+
totalSummaries += files.filter(f => /-SUMMARY\.md$/i.test(f)).length;
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
catch { /* phases dir may not exist */ }
|
|
695
|
+
const percent = totalPlans > 0 ? Math.min(100, Math.round(totalSummaries / totalPlans * 100)) : 0;
|
|
696
|
+
const barWidth = 10;
|
|
697
|
+
const filled = Math.round(percent / 100 * barWidth);
|
|
698
|
+
const bar = '\u2588'.repeat(filled) + '\u2591'.repeat(barWidth - filled);
|
|
699
|
+
const progressStr = `[${bar}] ${percent}%`;
|
|
700
|
+
let updated = false;
|
|
701
|
+
await readModifyWriteStateMd(projectDir, (content) => {
|
|
702
|
+
const boldProgressPattern = /(\*\*Progress:\*\*\s*).*/i;
|
|
703
|
+
const plainProgressPattern = /^(Progress:\s*).*/im;
|
|
704
|
+
if (boldProgressPattern.test(content)) {
|
|
705
|
+
updated = true;
|
|
706
|
+
return content.replace(boldProgressPattern, (_match, prefix) => `${prefix}${progressStr}`);
|
|
707
|
+
}
|
|
708
|
+
if (plainProgressPattern.test(content)) {
|
|
709
|
+
updated = true;
|
|
710
|
+
return content.replace(plainProgressPattern, (_match, prefix) => `${prefix}${progressStr}`);
|
|
711
|
+
}
|
|
712
|
+
return content;
|
|
713
|
+
}, workstream);
|
|
714
|
+
if (updated) {
|
|
715
|
+
return { data: { updated: true, percent, completed: totalSummaries, total: totalPlans, bar: progressStr } };
|
|
716
|
+
}
|
|
717
|
+
return { data: { updated: false, reason: 'Progress field not found in STATE.md' } };
|
|
718
|
+
};
|
|
719
|
+
/**
|
|
720
|
+
* Query handler for state.add-decision command.
|
|
721
|
+
*
|
|
722
|
+
* Appends a decision to the Decisions section. Removes placeholder text.
|
|
723
|
+
* argv matches `gsd-tools.cjs`: `--phase`, `--summary`, `--rationale`, etc.
|
|
724
|
+
*/
|
|
725
|
+
export const stateAddDecision = async (args, projectDir, workstream) => {
|
|
726
|
+
const parsed = parseNamedArgs(args, ['phase', 'summary', 'summary-file', 'rationale', 'rationale-file']);
|
|
727
|
+
const phase = parsed.phase;
|
|
728
|
+
let summaryText = null;
|
|
729
|
+
let rationaleText = '';
|
|
730
|
+
try {
|
|
731
|
+
summaryText = readTextArgOrFile(projectDir, parsed.summary ?? null, parsed['summary-file'] ?? null, 'summary');
|
|
732
|
+
rationaleText = readTextArgOrFile(projectDir, parsed.rationale || '', parsed['rationale-file'] ?? null, 'rationale');
|
|
733
|
+
}
|
|
734
|
+
catch (err) {
|
|
735
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
736
|
+
return { data: { added: false, reason: msg } };
|
|
737
|
+
}
|
|
738
|
+
if (!summaryText) {
|
|
739
|
+
return { data: { error: 'summary required' } };
|
|
740
|
+
}
|
|
741
|
+
const entry = `- [Phase ${phase || '?'}]: ${summaryText}${rationaleText ? ` — ${rationaleText}` : ''}`;
|
|
742
|
+
let created = false;
|
|
743
|
+
await readModifyWriteStateMd(projectDir, (content) => {
|
|
744
|
+
const sectionPattern = /(###?\s*(?:Decisions|Decisions Made|Accumulated.*Decisions)\s*\n)([\s\S]*?)(?=\n###?|\n##[^#]|$)/i;
|
|
745
|
+
const match = content.match(sectionPattern);
|
|
746
|
+
if (match) {
|
|
747
|
+
let sectionBody = match[2];
|
|
748
|
+
sectionBody = sectionBody.replace(/None yet\.?\s*\n?/gi, '').replace(/No decisions yet\.?\s*\n?/gi, '');
|
|
749
|
+
sectionBody = sectionBody.trimEnd() + '\n' + entry + '\n';
|
|
750
|
+
return content.replace(sectionPattern, (_match, header) => `${header}${sectionBody}`);
|
|
751
|
+
}
|
|
752
|
+
// Section absent — DWIM (CJS state.cjs:481-492): auto-create the
|
|
753
|
+
// canonical `## Decisions` scaffold and append the entry. Matches the
|
|
754
|
+
// begin-phase / advance-plan DWIM behavior. Without this, callers that
|
|
755
|
+
// never touched the Decisions section see `{added: false}` even though
|
|
756
|
+
// STATE.md is writable. Bug #3286.
|
|
757
|
+
const scaffold = ['', '## Decisions', '', entry, ''].join('\n');
|
|
758
|
+
created = true;
|
|
759
|
+
return content.trimEnd() + '\n' + scaffold;
|
|
760
|
+
}, workstream);
|
|
761
|
+
const result = { added: true, decision: entry };
|
|
762
|
+
if (created)
|
|
763
|
+
result['created'] = true;
|
|
764
|
+
return { data: result };
|
|
765
|
+
};
|
|
766
|
+
/**
|
|
767
|
+
* Query handler for state.add-blocker command.
|
|
768
|
+
* argv: `--text`, `--text-file` (see `gsd-tools.cjs`).
|
|
769
|
+
*/
|
|
770
|
+
export const stateAddBlocker = async (args, projectDir, workstream) => {
|
|
771
|
+
const parsed = parseNamedArgs(args, ['text', 'text-file']);
|
|
772
|
+
let blockerText = null;
|
|
773
|
+
try {
|
|
774
|
+
blockerText = readTextArgOrFile(projectDir, parsed.text ?? null, parsed['text-file'] ?? null, 'blocker');
|
|
775
|
+
}
|
|
776
|
+
catch (err) {
|
|
777
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
778
|
+
return { data: { added: false, reason: msg } };
|
|
779
|
+
}
|
|
780
|
+
if (!blockerText) {
|
|
781
|
+
return { data: { error: 'text required' } };
|
|
782
|
+
}
|
|
783
|
+
const entry = `- ${blockerText}`;
|
|
784
|
+
let created = false;
|
|
785
|
+
await readModifyWriteStateMd(projectDir, (content) => {
|
|
786
|
+
const sectionPattern = /(###?\s*(?:Blockers|Blockers\/Concerns|Concerns)\s*\n)([\s\S]*?)(?=\n###?|\n##[^#]|$)/i;
|
|
787
|
+
const match = content.match(sectionPattern);
|
|
788
|
+
if (match) {
|
|
789
|
+
let sectionBody = match[2];
|
|
790
|
+
sectionBody = sectionBody.replace(/None\.?\s*\n?/gi, '').replace(/None yet\.?\s*\n?/gi, '');
|
|
791
|
+
sectionBody = sectionBody.trimEnd() + '\n' + entry + '\n';
|
|
792
|
+
return content.replace(sectionPattern, (_match, header) => `${header}${sectionBody}`);
|
|
793
|
+
}
|
|
794
|
+
// Section absent — DWIM (CJS state.cjs:532-542): auto-create the
|
|
795
|
+
// canonical `### Blockers` scaffold and append the entry. Bug #3286
|
|
796
|
+
// parity — matches stateAddDecision DWIM above.
|
|
797
|
+
const scaffold = ['', '### Blockers', '', entry, ''].join('\n');
|
|
798
|
+
created = true;
|
|
799
|
+
return content.trimEnd() + '\n' + scaffold;
|
|
800
|
+
}, workstream);
|
|
801
|
+
const result = { added: true, blocker: blockerText };
|
|
802
|
+
if (created)
|
|
803
|
+
result['created'] = true;
|
|
804
|
+
return { data: result };
|
|
805
|
+
};
|
|
806
|
+
/**
|
|
807
|
+
* Query handler for state.resolve-blocker command.
|
|
808
|
+
* argv: `--text` (see `gsd-tools.cjs`).
|
|
809
|
+
*/
|
|
810
|
+
export const stateResolveBlocker = async (args, projectDir, workstream) => {
|
|
811
|
+
const parsed = parseNamedArgs(args, ['text']);
|
|
812
|
+
const searchText = parsed.text;
|
|
813
|
+
if (!searchText) {
|
|
814
|
+
return { data: { error: 'text required' } };
|
|
815
|
+
}
|
|
816
|
+
// CJS `cmdStateResolveBlocker` contract: error out when STATE.md is missing.
|
|
817
|
+
const statePath = planningPaths(projectDir, workstream).state;
|
|
818
|
+
try {
|
|
819
|
+
await readFile(statePath, 'utf-8');
|
|
820
|
+
}
|
|
821
|
+
catch {
|
|
822
|
+
return { data: { error: 'STATE.md not found' } };
|
|
823
|
+
}
|
|
824
|
+
let removedMatchingLine = false;
|
|
825
|
+
let blockersSectionFound = false;
|
|
826
|
+
await readModifyWriteStateMd(projectDir, (content) => {
|
|
827
|
+
const sectionPattern = /(###?\s*(?:Blockers|Blockers\/Concerns|Concerns)\s*\n)([\s\S]*?)(?=\n###?|\n##[^#]|$)/i;
|
|
828
|
+
const match = content.match(sectionPattern);
|
|
829
|
+
if (match) {
|
|
830
|
+
blockersSectionFound = true;
|
|
831
|
+
const sectionBody = match[2];
|
|
832
|
+
const lines = sectionBody.split('\n');
|
|
833
|
+
const filtered = lines.filter(line => {
|
|
834
|
+
if (!line.startsWith('- '))
|
|
835
|
+
return true;
|
|
836
|
+
const matches = line.toLowerCase().includes(searchText.toLowerCase());
|
|
837
|
+
if (matches)
|
|
838
|
+
removedMatchingLine = true;
|
|
839
|
+
return !matches;
|
|
840
|
+
});
|
|
841
|
+
if (!removedMatchingLine) {
|
|
842
|
+
return content;
|
|
843
|
+
}
|
|
844
|
+
let newBody = filtered.join('\n');
|
|
845
|
+
if (!newBody.trim() || !newBody.includes('- ')) {
|
|
846
|
+
newBody = 'None\n';
|
|
847
|
+
}
|
|
848
|
+
content = content.replace(sectionPattern, (_match, header) => `${header}${newBody}`);
|
|
849
|
+
}
|
|
850
|
+
return content;
|
|
851
|
+
}, workstream);
|
|
852
|
+
// CJS `cmdStateResolveBlocker` contract: `resolved: true` whenever the
|
|
853
|
+
// Blockers section was found, even if no line matched. The semantic is
|
|
854
|
+
// "the resolve operation ran against a Blockers section" rather than "a
|
|
855
|
+
// specific line was found and removed". Only `resolved: false` when the
|
|
856
|
+
// Blockers section itself is missing.
|
|
857
|
+
if (blockersSectionFound) {
|
|
858
|
+
return { data: { resolved: true, blocker: searchText } };
|
|
859
|
+
}
|
|
860
|
+
return { data: { resolved: false, reason: 'Blockers section not found in STATE.md' } };
|
|
861
|
+
};
|
|
862
|
+
// ─── state.add-roadmap-evolution ─────────────────────────────────────────
|
|
863
|
+
const VALID_ROADMAP_EVOLUTION_ACTIONS = new Set([
|
|
864
|
+
'inserted', 'removed', 'moved', 'edited', 'added',
|
|
865
|
+
]);
|
|
866
|
+
/**
|
|
867
|
+
* Format a canonical Roadmap Evolution entry line.
|
|
868
|
+
*
|
|
869
|
+
* Shapes match existing workflow templates (`insert-phase.md`, `add-phase.md`):
|
|
870
|
+
* - inserted: `- Phase {phase} inserted after Phase {after}: {note} (URGENT)`
|
|
871
|
+
* - added: `- Phase {phase} added: {note}`
|
|
872
|
+
* - removed: `- Phase {phase} removed: {note}`
|
|
873
|
+
* - moved: `- Phase {phase} moved: {note}`
|
|
874
|
+
* - edited: `- Phase {phase} edited: {note}`
|
|
875
|
+
*/
|
|
876
|
+
function formatRoadmapEvolutionEntry(opts) {
|
|
877
|
+
const { phase, action, note, after, urgent } = opts;
|
|
878
|
+
const trimmedNote = note ? note.trim() : '';
|
|
879
|
+
let line;
|
|
880
|
+
if (action === 'inserted') {
|
|
881
|
+
const afterClause = after ? ` after Phase ${after}` : '';
|
|
882
|
+
line = `- Phase ${phase} inserted${afterClause}`;
|
|
883
|
+
if (trimmedNote)
|
|
884
|
+
line += `: ${trimmedNote}`;
|
|
885
|
+
if (urgent)
|
|
886
|
+
line += ' (URGENT)';
|
|
887
|
+
}
|
|
888
|
+
else {
|
|
889
|
+
// added | removed | moved | edited
|
|
890
|
+
line = `- Phase ${phase} ${action}`;
|
|
891
|
+
if (trimmedNote)
|
|
892
|
+
line += `: ${trimmedNote}`;
|
|
893
|
+
}
|
|
894
|
+
return line;
|
|
895
|
+
}
|
|
896
|
+
/**
|
|
897
|
+
* Query handler for `state.add-roadmap-evolution`.
|
|
898
|
+
*
|
|
899
|
+
* Appends a single entry to the `### Roadmap Evolution` subsection under
|
|
900
|
+
* `## Accumulated Context` in STATE.md. Creates the subsection if missing.
|
|
901
|
+
* Deduplicates on exact line match against existing entries.
|
|
902
|
+
*
|
|
903
|
+
* Canonical replacement for the raw `Edit`/`Write` instructions in
|
|
904
|
+
* `insert-phase.md` / `add-phase.md` step "update_project_state" so that
|
|
905
|
+
* projects with a `protect-files.sh` PreToolUse hook blocking direct
|
|
906
|
+
* STATE.md writes still update the Roadmap Evolution log.
|
|
907
|
+
*
|
|
908
|
+
* argv: `--phase`, `--action` (inserted|removed|moved|edited|added),
|
|
909
|
+
* `--note` (optional), `--after` (optional, for `inserted`),
|
|
910
|
+
* `--urgent` (boolean flag, appends "(URGENT)" when action=inserted).
|
|
911
|
+
*
|
|
912
|
+
* Returns `{ added: true, entry }` on success, or
|
|
913
|
+
* `{ added: false, reason: 'duplicate', entry }` when an identical line
|
|
914
|
+
* already exists.
|
|
915
|
+
*
|
|
916
|
+
* Throws `GSDError` with `ErrorClassification.Validation` when required
|
|
917
|
+
* inputs are missing or `--action` is not in the allowed set.
|
|
918
|
+
*
|
|
919
|
+
* Atomicity: goes through `readModifyWriteStateMd` which holds a lockfile
|
|
920
|
+
* across read -> transform -> write. Matches sibling mutation handlers.
|
|
921
|
+
*/
|
|
922
|
+
export const stateAddRoadmapEvolution = async (args, projectDir, workstream) => {
|
|
923
|
+
const parsed = parseNamedArgs(args, ['phase', 'action', 'note', 'after'], ['urgent']);
|
|
924
|
+
const phase = parsed.phase ?? null;
|
|
925
|
+
const action = parsed.action ?? null;
|
|
926
|
+
const note = parsed.note ?? null;
|
|
927
|
+
const after = parsed.after ?? null;
|
|
928
|
+
const urgent = Boolean(parsed.urgent);
|
|
929
|
+
if (!phase) {
|
|
930
|
+
throw new GSDError('phase required for state.add-roadmap-evolution', ErrorClassification.Validation);
|
|
931
|
+
}
|
|
932
|
+
if (!action) {
|
|
933
|
+
throw new GSDError('action required for state.add-roadmap-evolution', ErrorClassification.Validation);
|
|
934
|
+
}
|
|
935
|
+
if (!VALID_ROADMAP_EVOLUTION_ACTIONS.has(action)) {
|
|
936
|
+
throw new GSDError(`invalid action "${action}" (expected one of: ${Array.from(VALID_ROADMAP_EVOLUTION_ACTIONS).join(', ')})`, ErrorClassification.Validation);
|
|
937
|
+
}
|
|
938
|
+
const entry = formatRoadmapEvolutionEntry({ phase, action, note, after, urgent });
|
|
939
|
+
let added = false;
|
|
940
|
+
let duplicate = false;
|
|
941
|
+
await readModifyWriteStateMd(projectDir, (content) => {
|
|
942
|
+
// Match `### Roadmap Evolution` subsection up to the next heading or EOF.
|
|
943
|
+
const subsectionPattern = /(###\s*Roadmap Evolution\s*\n)([\s\S]*?)(?=\n###?\s|\n##[^#]|$)/i;
|
|
944
|
+
const match = content.match(subsectionPattern);
|
|
945
|
+
if (match) {
|
|
946
|
+
let sectionBody = match[2];
|
|
947
|
+
// Dedupe: exact line match against any existing entry line.
|
|
948
|
+
const existingLines = sectionBody.split('\n').map(l => l.trim());
|
|
949
|
+
if (existingLines.some(l => l === entry.trim())) {
|
|
950
|
+
duplicate = true;
|
|
951
|
+
return content;
|
|
952
|
+
}
|
|
953
|
+
// Strip placeholder "None" / "None yet." lines.
|
|
954
|
+
sectionBody = sectionBody.replace(/^None(?:\s+yet)?\.?\s*$/gim, '');
|
|
955
|
+
sectionBody = sectionBody.trimEnd() + '\n' + entry + '\n';
|
|
956
|
+
content = content.replace(subsectionPattern, (_m, header) => `${header}${sectionBody}`);
|
|
957
|
+
added = true;
|
|
958
|
+
return content;
|
|
959
|
+
}
|
|
960
|
+
// Subsection missing — create it.
|
|
961
|
+
const accumulatedPattern = /(##\s*Accumulated Context\s*\n)/i;
|
|
962
|
+
const newSubsection = `\n### Roadmap Evolution\n\n${entry}\n`;
|
|
963
|
+
if (accumulatedPattern.test(content)) {
|
|
964
|
+
// Insert immediately after the "## Accumulated Context" header.
|
|
965
|
+
content = content.replace(accumulatedPattern, (_m, header) => `${header}${newSubsection}`);
|
|
966
|
+
added = true;
|
|
967
|
+
return content;
|
|
968
|
+
}
|
|
969
|
+
// No Accumulated Context section either — append both at EOF.
|
|
970
|
+
const suffix = `\n## Accumulated Context\n${newSubsection}`;
|
|
971
|
+
content = content.trimEnd() + suffix + '\n';
|
|
972
|
+
added = true;
|
|
973
|
+
return content;
|
|
974
|
+
}, workstream);
|
|
975
|
+
if (duplicate) {
|
|
976
|
+
return { data: { added: false, reason: 'duplicate', entry } };
|
|
977
|
+
}
|
|
978
|
+
if (added) {
|
|
979
|
+
return { data: { added: true, entry } };
|
|
980
|
+
}
|
|
981
|
+
// Unreachable given the logic above, but defensive.
|
|
982
|
+
return { data: { added: false, reason: 'unknown', entry } };
|
|
983
|
+
};
|
|
984
|
+
/**
|
|
985
|
+
* Query handler for state.record-session command.
|
|
986
|
+
* argv: `--stopped-at`, `--resume-file` (see `cmdStateRecordSession` in `state.cjs`).
|
|
987
|
+
*/
|
|
988
|
+
export const stateRecordSession = async (args, projectDir, workstream) => {
|
|
989
|
+
const parsed = parseNamedArgs(args, ['stopped-at', 'resume-file']);
|
|
990
|
+
const stoppedAt = parsed['stopped-at'];
|
|
991
|
+
const resumeFile = (parsed['resume-file'] ?? 'None');
|
|
992
|
+
// CJS `cmdStateRecordSession` contract: error out when STATE.md is missing.
|
|
993
|
+
const statePath = planningPaths(projectDir, workstream).state;
|
|
994
|
+
try {
|
|
995
|
+
await readFile(statePath, 'utf-8');
|
|
996
|
+
}
|
|
997
|
+
catch {
|
|
998
|
+
return { data: { error: 'STATE.md not found' } };
|
|
999
|
+
}
|
|
1000
|
+
const now = new Date().toISOString();
|
|
1001
|
+
const updated = [];
|
|
1002
|
+
await readModifyWriteStateMd(projectDir, (content) => {
|
|
1003
|
+
let result = stateReplaceField(content, 'Last session', now);
|
|
1004
|
+
if (result) {
|
|
1005
|
+
content = result;
|
|
1006
|
+
updated.push('Last session');
|
|
1007
|
+
}
|
|
1008
|
+
result = stateReplaceField(content, 'Last Date', now);
|
|
1009
|
+
if (result) {
|
|
1010
|
+
content = result;
|
|
1011
|
+
updated.push('Last Date');
|
|
1012
|
+
}
|
|
1013
|
+
if (stoppedAt) {
|
|
1014
|
+
result = stateReplaceField(content, 'Stopped At', stoppedAt);
|
|
1015
|
+
if (!result)
|
|
1016
|
+
result = stateReplaceField(content, 'Stopped at', stoppedAt);
|
|
1017
|
+
if (result) {
|
|
1018
|
+
content = result;
|
|
1019
|
+
updated.push('Stopped At');
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
result = stateReplaceField(content, 'Resume File', resumeFile);
|
|
1023
|
+
if (!result)
|
|
1024
|
+
result = stateReplaceField(content, 'Resume file', resumeFile);
|
|
1025
|
+
if (result) {
|
|
1026
|
+
content = result;
|
|
1027
|
+
updated.push('Resume File');
|
|
1028
|
+
}
|
|
1029
|
+
return content;
|
|
1030
|
+
}, workstream);
|
|
1031
|
+
if (updated.length > 0) {
|
|
1032
|
+
return { data: { recorded: true, updated } };
|
|
1033
|
+
}
|
|
1034
|
+
return { data: { recorded: false, reason: 'No session fields found in STATE.md' } };
|
|
1035
|
+
};
|
|
1036
|
+
/**
|
|
1037
|
+
* Query handler for state.planned-phase — port of `cmdStatePlannedPhase` from `state.cjs`.
|
|
1038
|
+
*/
|
|
1039
|
+
export const statePlannedPhase = async (args, projectDir, workstream) => {
|
|
1040
|
+
const parsed = parseNamedArgs(args, ['phase', 'name', 'plans']);
|
|
1041
|
+
const phaseNumber = parsed.phase;
|
|
1042
|
+
const plansRaw = parsed.plans;
|
|
1043
|
+
const parsedPlanCount = plansRaw !== null && plansRaw !== '' ? parseInt(String(plansRaw), 10) : null;
|
|
1044
|
+
const planCount = parsedPlanCount !== null &&
|
|
1045
|
+
!Number.isNaN(parsedPlanCount) &&
|
|
1046
|
+
Number.isFinite(parsedPlanCount) &&
|
|
1047
|
+
parsedPlanCount > 0
|
|
1048
|
+
? parsedPlanCount
|
|
1049
|
+
: null;
|
|
1050
|
+
if (!phaseNumber || String(phaseNumber).trim() === '') {
|
|
1051
|
+
return { data: { error: 'phase required (--phase <n>)' } };
|
|
1052
|
+
}
|
|
1053
|
+
const phaseLabel = String(phaseNumber).trim();
|
|
1054
|
+
const statePath = planningPaths(projectDir, workstream).state;
|
|
1055
|
+
if (!existsSync(statePath)) {
|
|
1056
|
+
return { data: { error: 'STATE.md not found' } };
|
|
1057
|
+
}
|
|
1058
|
+
const today = new Date().toISOString().split('T')[0];
|
|
1059
|
+
const updated = [];
|
|
1060
|
+
await readModifyWriteStateMd(projectDir, (content) => {
|
|
1061
|
+
let result = stateReplaceField(content, 'Status', 'Ready to execute');
|
|
1062
|
+
if (result) {
|
|
1063
|
+
content = result;
|
|
1064
|
+
updated.push('Status');
|
|
1065
|
+
}
|
|
1066
|
+
if (planCount !== null) {
|
|
1067
|
+
result = stateReplaceField(content, 'Total Plans in Phase', String(planCount));
|
|
1068
|
+
if (result) {
|
|
1069
|
+
content = result;
|
|
1070
|
+
updated.push('Total Plans in Phase');
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
result = stateReplaceField(content, 'Last Activity', today);
|
|
1074
|
+
if (result) {
|
|
1075
|
+
content = result;
|
|
1076
|
+
updated.push('Last Activity');
|
|
1077
|
+
}
|
|
1078
|
+
result = stateReplaceField(content, 'Last Activity Description', `Phase ${phaseLabel} planning complete — ${planCount ?? '?'} plans ready`);
|
|
1079
|
+
if (result) {
|
|
1080
|
+
content = result;
|
|
1081
|
+
updated.push('Last Activity Description');
|
|
1082
|
+
}
|
|
1083
|
+
content = updateCurrentPositionFields(content, {
|
|
1084
|
+
status: 'Ready to execute',
|
|
1085
|
+
lastActivity: `${today} -- Phase ${phaseLabel} planning complete`,
|
|
1086
|
+
});
|
|
1087
|
+
return content;
|
|
1088
|
+
}, workstream);
|
|
1089
|
+
return { data: { updated, phase: phaseNumber, plan_count: planCount } };
|
|
1090
|
+
};
|
|
1091
|
+
// ─── stateMilestoneSwitch (bug #2630) ─────────────────────────────────────
|
|
1092
|
+
/**
|
|
1093
|
+
* Query handler for `state.milestone-switch` — resets STATE.md for a new
|
|
1094
|
+
* milestone cycle (bug #2630 regression guard).
|
|
1095
|
+
*
|
|
1096
|
+
* The `/gsd-new-milestone` workflow only rewrote STATE.md's body (Current
|
|
1097
|
+
* Position section). The YAML frontmatter (`milestone`, `milestone_name`,
|
|
1098
|
+
* `status`, `progress.*`) was never touched on a mid-flight switch, so queries
|
|
1099
|
+
* that read frontmatter (`state.json`, `getMilestoneInfo`, every handler that
|
|
1100
|
+
* calls `buildStateFrontmatter`) kept reporting the old milestone and stale
|
|
1101
|
+
* progress counters until the first phase advance forced a resync.
|
|
1102
|
+
*
|
|
1103
|
+
* This handler performs the reset atomically under the STATE.md lock:
|
|
1104
|
+
* - Stomps frontmatter milestone/milestone_name with the caller-supplied
|
|
1105
|
+
* values so `parseMilestoneFromState` reports the new milestone immediately.
|
|
1106
|
+
* - Resets `status` to `'planning'` (workflow is at "Defining requirements").
|
|
1107
|
+
* - Resets `progress` counters to zero (new milestone, nothing executed yet).
|
|
1108
|
+
* - Rewrites the `## Current Position` body to the new-milestone template so
|
|
1109
|
+
* subsequent body-derived field extraction stays consistent with frontmatter.
|
|
1110
|
+
* - Preserves Accumulated Context (decisions, todos, blockers) — symmetric
|
|
1111
|
+
* with `milestone.complete` which also keeps history.
|
|
1112
|
+
*
|
|
1113
|
+
* Args (named, matches gsd-tools style):
|
|
1114
|
+
* - `--version <vX.Y>` (required)
|
|
1115
|
+
* - `--name <milestone name>` (optional; defaults to 'milestone')
|
|
1116
|
+
*
|
|
1117
|
+
* Sibling CJS parity: `cmdInitNewMilestone` in `init.cjs` is read-only (like
|
|
1118
|
+
* the TS `initNewMilestone`). The workflow-level fix is to call
|
|
1119
|
+
* `state.milestone-switch` from `/gsd-new-milestone` Step 5 in place of the
|
|
1120
|
+
* manual body rewrite.
|
|
1121
|
+
*/
|
|
1122
|
+
export const stateMilestoneSwitch = async (args, projectDir, workstream) => {
|
|
1123
|
+
// NOTE: the CLI flag is `--milestone` (not `--version`). gsd-tools reserves
|
|
1124
|
+
// `--version` as a globally-invalid help flag, so the workflow invokes this
|
|
1125
|
+
// handler with `--milestone vX.Y`. The internal variable is still `version`
|
|
1126
|
+
// because the value is a milestone version string.
|
|
1127
|
+
const parsed = parseNamedArgs(args, ['milestone', 'name']);
|
|
1128
|
+
const version = parsed.milestone?.trim();
|
|
1129
|
+
const name = (parsed.name ?? 'milestone').trim() || 'milestone';
|
|
1130
|
+
if (!version) {
|
|
1131
|
+
return { data: { error: 'milestone required (--milestone <vX.Y>)' } };
|
|
1132
|
+
}
|
|
1133
|
+
const today = new Date().toISOString().split('T')[0];
|
|
1134
|
+
const statePath = planningPaths(projectDir, workstream).state;
|
|
1135
|
+
const lockPath = await acquireStateLock(statePath);
|
|
1136
|
+
try {
|
|
1137
|
+
let content = '';
|
|
1138
|
+
try {
|
|
1139
|
+
content = await readFile(statePath, 'utf-8');
|
|
1140
|
+
}
|
|
1141
|
+
catch { /* STATE.md may not exist yet */ }
|
|
1142
|
+
const existingFm = extractFrontmatter(content);
|
|
1143
|
+
const body = stripFrontmatter(content);
|
|
1144
|
+
// Reset Current Position section body so body-derived extraction stays
|
|
1145
|
+
// consistent with the new frontmatter.
|
|
1146
|
+
const positionPattern = /(##\s*Current Position\s*\n)([\s\S]*?)(?=\n##|$)/i;
|
|
1147
|
+
const resetPositionBody = `\nPhase: Not started (defining requirements)\n` +
|
|
1148
|
+
`Plan: —\n` +
|
|
1149
|
+
`Status: Defining requirements\n` +
|
|
1150
|
+
`Last activity: ${today} — Milestone ${version} started\n\n`;
|
|
1151
|
+
let newBody;
|
|
1152
|
+
if (positionPattern.test(body)) {
|
|
1153
|
+
newBody = body.replace(positionPattern, (_m, header) => `${header}${resetPositionBody}`);
|
|
1154
|
+
}
|
|
1155
|
+
else {
|
|
1156
|
+
// Preserve any existing body but prepend a Current Position section.
|
|
1157
|
+
const preface = body.trim().length > 0 ? body : '# Project State\n';
|
|
1158
|
+
newBody = `${preface.trimEnd()}\n\n## Current Position\n${resetPositionBody}`;
|
|
1159
|
+
}
|
|
1160
|
+
// Build fresh frontmatter explicitly — do NOT rely on buildStateFrontmatter
|
|
1161
|
+
// here, because getMilestoneInfo reads the ON-DISK STATE.md and would
|
|
1162
|
+
// return the OLD milestone until we write it first. This is the crux of
|
|
1163
|
+
// bug #2630: any sync-based approach races against the very file it is
|
|
1164
|
+
// about to rewrite.
|
|
1165
|
+
const fm = {
|
|
1166
|
+
gsd_state_version: '1.0',
|
|
1167
|
+
milestone: version,
|
|
1168
|
+
milestone_name: name,
|
|
1169
|
+
status: 'planning',
|
|
1170
|
+
last_updated: new Date().toISOString(),
|
|
1171
|
+
last_activity: today,
|
|
1172
|
+
progress: {
|
|
1173
|
+
total_phases: 0,
|
|
1174
|
+
completed_phases: 0,
|
|
1175
|
+
total_plans: 0,
|
|
1176
|
+
completed_plans: 0,
|
|
1177
|
+
percent: 0,
|
|
1178
|
+
},
|
|
1179
|
+
};
|
|
1180
|
+
// Preserve frontmatter-only fields the caller may still care about
|
|
1181
|
+
// (paused_at cleared deliberately — a new milestone is a fresh start).
|
|
1182
|
+
if (existingFm.gsd_state_version) {
|
|
1183
|
+
fm.gsd_state_version = existingFm.gsd_state_version;
|
|
1184
|
+
}
|
|
1185
|
+
const yamlStr = reconstructFrontmatter(fm);
|
|
1186
|
+
const assembled = `---\n${yamlStr}\n---\n\n${newBody.replace(/^\n+/, '')}`;
|
|
1187
|
+
await writeFile(statePath, normalizeMd(assembled), 'utf-8');
|
|
1188
|
+
return {
|
|
1189
|
+
data: {
|
|
1190
|
+
switched: true,
|
|
1191
|
+
version,
|
|
1192
|
+
name,
|
|
1193
|
+
status: 'planning',
|
|
1194
|
+
},
|
|
1195
|
+
};
|
|
1196
|
+
}
|
|
1197
|
+
finally {
|
|
1198
|
+
await releaseStateLock(lockPath);
|
|
1199
|
+
}
|
|
1200
|
+
};
|
|
1201
|
+
// ─── parseNamedArgs (matches gsd-tools.cjs) ───────────────────────────────
|
|
1202
|
+
function parseNamedArgs(args, valueFlags = [], booleanFlags = []) {
|
|
1203
|
+
const result = {};
|
|
1204
|
+
for (const flag of valueFlags) {
|
|
1205
|
+
const idx = args.indexOf(`--${flag}`);
|
|
1206
|
+
if (idx === -1) {
|
|
1207
|
+
result[flag] = null;
|
|
1208
|
+
continue;
|
|
1209
|
+
}
|
|
1210
|
+
const value = args[idx + 1];
|
|
1211
|
+
if (value === undefined || value.startsWith('--')) {
|
|
1212
|
+
throw new GSDError(`missing value for --${flag}`, ErrorClassification.Validation);
|
|
1213
|
+
}
|
|
1214
|
+
result[flag] = value;
|
|
1215
|
+
}
|
|
1216
|
+
for (const flag of booleanFlags) {
|
|
1217
|
+
result[flag] = args.includes(`--${flag}`);
|
|
1218
|
+
}
|
|
1219
|
+
return result;
|
|
1220
|
+
}
|
|
1221
|
+
// ─── Human gate signals (WAITING.json) ───────────────────────────────────
|
|
1222
|
+
/**
|
|
1223
|
+
* Port of `cmdSignalWaiting` from state.cjs.
|
|
1224
|
+
* Args: `--type`, `--question`, `--options` (pipe-separated), `--phase`.
|
|
1225
|
+
*
|
|
1226
|
+
* Writes `WAITING.json` under both `.gsd/` and `.planning/` so readers that only
|
|
1227
|
+
* watch one location (e.g. init workflows) still observe the signal.
|
|
1228
|
+
*/
|
|
1229
|
+
export const stateSignalWaiting = async (args, projectDir, _workstream) => {
|
|
1230
|
+
const parsed = parseNamedArgs(args, ['type', 'question', 'options', 'phase']);
|
|
1231
|
+
const type = parsed.type || 'decision_point';
|
|
1232
|
+
const question = parsed.question || null;
|
|
1233
|
+
const optionsRaw = parsed.options;
|
|
1234
|
+
const phase = parsed.phase || null;
|
|
1235
|
+
const waitingPaths = [
|
|
1236
|
+
join(projectDir, '.gsd', 'WAITING.json'),
|
|
1237
|
+
join(projectDir, '.planning', 'WAITING.json'),
|
|
1238
|
+
];
|
|
1239
|
+
const signal = {
|
|
1240
|
+
status: 'waiting',
|
|
1241
|
+
type,
|
|
1242
|
+
question,
|
|
1243
|
+
options: optionsRaw ? optionsRaw.split('|').map(o => o.trim()) : [],
|
|
1244
|
+
since: new Date().toISOString(),
|
|
1245
|
+
phase,
|
|
1246
|
+
};
|
|
1247
|
+
try {
|
|
1248
|
+
const payload = JSON.stringify(signal, null, 2);
|
|
1249
|
+
mkdirSync(join(projectDir, '.gsd'), { recursive: true });
|
|
1250
|
+
mkdirSync(join(projectDir, '.planning'), { recursive: true });
|
|
1251
|
+
for (const p of waitingPaths) {
|
|
1252
|
+
writeFileSync(p, payload, 'utf-8');
|
|
1253
|
+
}
|
|
1254
|
+
return { data: { signaled: true, path: waitingPaths[0], paths: waitingPaths } };
|
|
1255
|
+
}
|
|
1256
|
+
catch (e) {
|
|
1257
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
1258
|
+
return { data: { signaled: false, error: msg } };
|
|
1259
|
+
}
|
|
1260
|
+
};
|
|
1261
|
+
/**
|
|
1262
|
+
* Port of `cmdSignalResume` from state.cjs.
|
|
1263
|
+
*/
|
|
1264
|
+
export const stateSignalResume = async (_args, projectDir, _workstream) => {
|
|
1265
|
+
const paths = [
|
|
1266
|
+
join(projectDir, '.gsd', 'WAITING.json'),
|
|
1267
|
+
join(projectDir, '.planning', 'WAITING.json'),
|
|
1268
|
+
];
|
|
1269
|
+
let removed = false;
|
|
1270
|
+
for (const p of paths) {
|
|
1271
|
+
if (existsSync(p)) {
|
|
1272
|
+
try {
|
|
1273
|
+
unlinkSync(p);
|
|
1274
|
+
removed = true;
|
|
1275
|
+
}
|
|
1276
|
+
catch { /* ignore */ }
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
return { data: { resumed: true, removed } };
|
|
1280
|
+
};
|
|
1281
|
+
// ─── stateValidate ───────────────────────────────────────────────────────
|
|
1282
|
+
/**
|
|
1283
|
+
* Port of `cmdStateValidate` from state.cjs.
|
|
1284
|
+
*/
|
|
1285
|
+
export const stateValidate = async (_args, projectDir, workstream) => {
|
|
1286
|
+
const paths = planningPaths(projectDir, workstream);
|
|
1287
|
+
const statePath = paths.state;
|
|
1288
|
+
if (!existsSync(statePath)) {
|
|
1289
|
+
return { data: { error: 'STATE.md not found' } };
|
|
1290
|
+
}
|
|
1291
|
+
const content = await readFile(statePath, 'utf-8');
|
|
1292
|
+
const warnings = [];
|
|
1293
|
+
const drift = {};
|
|
1294
|
+
const status = stateExtractField(content, 'Status') || '';
|
|
1295
|
+
const currentPhase = stateExtractField(content, 'Current Phase');
|
|
1296
|
+
const totalPlansRaw = stateExtractField(content, 'Total Plans in Phase');
|
|
1297
|
+
const totalPlansInPhase = totalPlansRaw ? parseInt(totalPlansRaw, 10) : null;
|
|
1298
|
+
const phasesDir = paths.phases;
|
|
1299
|
+
if (currentPhase && existsSync(phasesDir)) {
|
|
1300
|
+
const normalized = normalizePhaseName(currentPhase.replace(/\s+of\s+\d+.*/, '').trim());
|
|
1301
|
+
try {
|
|
1302
|
+
const entries = readdirSync(phasesDir, { withFileTypes: true });
|
|
1303
|
+
const phaseDir = entries.find(e => e.isDirectory() && phaseTokenMatches(e.name, normalized));
|
|
1304
|
+
if (phaseDir) {
|
|
1305
|
+
const phaseDirPath = join(phasesDir, phaseDir.name);
|
|
1306
|
+
const files = readdirSync(phaseDirPath);
|
|
1307
|
+
// Bug #3257 parity: count nested plans/ subdirectory via scanPhasePlans
|
|
1308
|
+
// so /executing/i status checks below see the full plan count
|
|
1309
|
+
// regardless of whether the planner used the flat or nested layout.
|
|
1310
|
+
const { planCount: diskPlans, summaryCount: diskSummaries } = scanPhasePlans(phaseDirPath);
|
|
1311
|
+
if (totalPlansInPhase !== null && diskPlans !== totalPlansInPhase) {
|
|
1312
|
+
warnings.push(`Plan count mismatch: STATE.md says ${totalPlansInPhase} plans, disk has ${diskPlans}`);
|
|
1313
|
+
drift.plan_count = { state: totalPlansInPhase, disk: diskPlans };
|
|
1314
|
+
}
|
|
1315
|
+
const verificationFiles = files.filter(f => f.includes('VERIFICATION') && f.endsWith('.md'));
|
|
1316
|
+
for (const vf of verificationFiles) {
|
|
1317
|
+
try {
|
|
1318
|
+
const vContent = readFileSync(join(phaseDirPath, vf), 'utf-8');
|
|
1319
|
+
if (/status:\s*passed/i.test(vContent) && /executing/i.test(status)) {
|
|
1320
|
+
warnings.push(`Status drift: STATE.md says "${status}" but ${vf} shows verification passed — phase may be complete`);
|
|
1321
|
+
drift.verification_status = { state_status: status, verification: 'passed' };
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
catch { /* skip */ }
|
|
1325
|
+
}
|
|
1326
|
+
if (diskPlans > 0 && diskSummaries >= diskPlans && /executing/i.test(status)) {
|
|
1327
|
+
if (verificationFiles.length === 0) {
|
|
1328
|
+
warnings.push(`All ${diskPlans} plans have summaries but status is still "${status}" — phase may be ready for verification`);
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
catch { /* skip */ }
|
|
1334
|
+
}
|
|
1335
|
+
const valid = warnings.length === 0;
|
|
1336
|
+
return { data: { valid, warnings, drift } };
|
|
1337
|
+
};
|
|
1338
|
+
// ─── stateSync ─────────────────────────────────────────────────────────────
|
|
1339
|
+
/**
|
|
1340
|
+
* Port of `cmdStateSync` from state.cjs. Supports `--verify` dry-run.
|
|
1341
|
+
*/
|
|
1342
|
+
export const stateSync = async (args, projectDir, workstream) => {
|
|
1343
|
+
const verify = args.includes('--verify');
|
|
1344
|
+
const paths = planningPaths(projectDir, workstream);
|
|
1345
|
+
const statePath = paths.state;
|
|
1346
|
+
if (!existsSync(statePath)) {
|
|
1347
|
+
return { data: { error: 'STATE.md not found' } };
|
|
1348
|
+
}
|
|
1349
|
+
const content = await readFile(statePath, 'utf-8');
|
|
1350
|
+
const changes = [];
|
|
1351
|
+
const today = new Date().toISOString().split('T')[0];
|
|
1352
|
+
const phasesDir = paths.phases;
|
|
1353
|
+
if (!existsSync(phasesDir)) {
|
|
1354
|
+
return { data: { synced: true, changes: [], dry_run: verify } };
|
|
1355
|
+
}
|
|
1356
|
+
let entries;
|
|
1357
|
+
try {
|
|
1358
|
+
entries = readdirSync(phasesDir, { withFileTypes: true })
|
|
1359
|
+
.filter(e => e.isDirectory())
|
|
1360
|
+
.map(e => e.name)
|
|
1361
|
+
.sort((a, b) => comparePhaseNum(a, b));
|
|
1362
|
+
}
|
|
1363
|
+
catch {
|
|
1364
|
+
return { data: { synced: true, changes: [], dry_run: verify } };
|
|
1365
|
+
}
|
|
1366
|
+
let totalDiskPlans = 0;
|
|
1367
|
+
let totalDiskSummaries = 0;
|
|
1368
|
+
let diskCompletedPhases = 0;
|
|
1369
|
+
let highestIncompletePhase = null;
|
|
1370
|
+
let highestIncompletePhaseplanCount = 0;
|
|
1371
|
+
for (const dir of entries) {
|
|
1372
|
+
const dirPath = join(phasesDir, dir);
|
|
1373
|
+
// Bug #3257 parity: scanPhasePlans handles nested plans/ subdirectories
|
|
1374
|
+
// and the extended filename forms (e.g. 5-PLAN-01-setup.md). Without
|
|
1375
|
+
// this, state.sync sees 0 plans for canonical nested layouts and emits
|
|
1376
|
+
// bogus "Total Plans in Phase 0 -> 0" sync updates.
|
|
1377
|
+
const { planCount: plans, summaryCount: summaries, completed } = scanPhasePlans(dirPath);
|
|
1378
|
+
totalDiskPlans += plans;
|
|
1379
|
+
totalDiskSummaries += summaries;
|
|
1380
|
+
if (completed)
|
|
1381
|
+
diskCompletedPhases++;
|
|
1382
|
+
const phaseMatch = dir.match(/^(\d+[A-Z]?(?:\.\d+)*)/i);
|
|
1383
|
+
if (phaseMatch && plans > 0 && summaries < plans) {
|
|
1384
|
+
highestIncompletePhase = dir;
|
|
1385
|
+
highestIncompletePhaseplanCount = plans;
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
// CJS parity: total_phases for the percent calculation is the count of
|
|
1389
|
+
// phase directories in the active milestone (or the actual count on disk
|
|
1390
|
+
// if no milestone filter is configured). Required so the phase-fraction
|
|
1391
|
+
// cap in computeProgressPercent (#3242 Bug B) sees the right denominator.
|
|
1392
|
+
const syncTotalPhases = entries.length;
|
|
1393
|
+
const runModifier = (modified) => {
|
|
1394
|
+
let m = modified;
|
|
1395
|
+
if (highestIncompletePhase) {
|
|
1396
|
+
const currentPlansField = stateExtractField(m, 'Total Plans in Phase');
|
|
1397
|
+
if (currentPlansField && parseInt(currentPlansField, 10) !== highestIncompletePhaseplanCount) {
|
|
1398
|
+
changes.push(`Total Plans in Phase: ${currentPlansField} -> ${highestIncompletePhaseplanCount}`);
|
|
1399
|
+
const result = stateReplaceField(m, 'Total Plans in Phase', String(highestIncompletePhaseplanCount));
|
|
1400
|
+
if (result)
|
|
1401
|
+
m = result;
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
// Use min(plan_fraction, phase_fraction) so ROADMAP-declared-but-
|
|
1405
|
+
// unrealized future phases cap the reported percent (CJS bug #3242 Bug B
|
|
1406
|
+
// parity). Fall back to 0 when computeProgressPercent returns null
|
|
1407
|
+
// (totalDiskPlans === 0 case).
|
|
1408
|
+
const computedPercent = computeProgressPercent(totalDiskSummaries, totalDiskPlans, diskCompletedPhases, syncTotalPhases);
|
|
1409
|
+
const percent = computedPercent !== null ? computedPercent : 0;
|
|
1410
|
+
const currentProgress = stateExtractField(m, 'Progress');
|
|
1411
|
+
if (currentProgress) {
|
|
1412
|
+
const currentPercent = parseInt(currentProgress.replace(/[^\d]/g, ''), 10);
|
|
1413
|
+
if (currentPercent !== percent) {
|
|
1414
|
+
const barWidth = 10;
|
|
1415
|
+
const filled = Math.round(percent / 100 * barWidth);
|
|
1416
|
+
const bar = '\u2588'.repeat(filled) + '\u2591'.repeat(barWidth - filled);
|
|
1417
|
+
const progressStr = `[${bar}] ${percent}%`;
|
|
1418
|
+
changes.push(`Progress: ${currentProgress} -> ${progressStr}`);
|
|
1419
|
+
const result = stateReplaceField(m, 'Progress', progressStr);
|
|
1420
|
+
if (result)
|
|
1421
|
+
m = result;
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
const oldActivity = stateExtractField(m, 'Last Activity');
|
|
1425
|
+
const r = stateReplaceField(m, 'Last Activity', today);
|
|
1426
|
+
if (r) {
|
|
1427
|
+
if (oldActivity !== today) {
|
|
1428
|
+
changes.push(`Last Activity: ${oldActivity} -> ${today}`);
|
|
1429
|
+
}
|
|
1430
|
+
m = r;
|
|
1431
|
+
}
|
|
1432
|
+
return m;
|
|
1433
|
+
};
|
|
1434
|
+
if (verify) {
|
|
1435
|
+
const body = stripFrontmatter(content);
|
|
1436
|
+
runModifier(body);
|
|
1437
|
+
return { data: { synced: false, changes, dry_run: true } };
|
|
1438
|
+
}
|
|
1439
|
+
await readModifyWriteStateMd(projectDir, (body) => runModifier(body), workstream);
|
|
1440
|
+
return { data: { synced: true, changes, dry_run: false } };
|
|
1441
|
+
};
|
|
1442
|
+
// ─── statePrune ────────────────────────────────────────────────────────────
|
|
1443
|
+
/**
|
|
1444
|
+
* Parse phase number from a Performance Metrics table data row.
|
|
1445
|
+
* Supports `stateRecordMetric` rows (`| Phase 3 P1 | ...`) and legacy `| 3 | ...` rows.
|
|
1446
|
+
*/
|
|
1447
|
+
function extractPerformanceMetricsRowPhase(line) {
|
|
1448
|
+
const phaseNamed = line.match(/^\|\s*Phase\s+(\d+)/i);
|
|
1449
|
+
if (phaseNamed)
|
|
1450
|
+
return parseInt(phaseNamed[1], 10);
|
|
1451
|
+
const legacy = line.match(/^\|\s*(\d+)\s*\|/);
|
|
1452
|
+
if (legacy)
|
|
1453
|
+
return parseInt(legacy[1], 10);
|
|
1454
|
+
return null;
|
|
1455
|
+
}
|
|
1456
|
+
/**
|
|
1457
|
+
* Port of inner `prunePass` from state.cjs — mutates content string for sections
|
|
1458
|
+
* older than `cutoff` phase number.
|
|
1459
|
+
*/
|
|
1460
|
+
function prunePass(content, cutoff) {
|
|
1461
|
+
const archivedSections = [];
|
|
1462
|
+
let contentWork = content;
|
|
1463
|
+
const decisionPattern = /(###?\s*(?:Decisions|Decisions Made|Accumulated.*Decisions)\s*\n)([\s\S]*?)(?=\n###?|\n##[^#]|$)/i;
|
|
1464
|
+
const decMatch = contentWork.match(decisionPattern);
|
|
1465
|
+
if (decMatch) {
|
|
1466
|
+
const lines = decMatch[2].split('\n');
|
|
1467
|
+
const keep = [];
|
|
1468
|
+
const archive = [];
|
|
1469
|
+
for (const line of lines) {
|
|
1470
|
+
const pm = line.match(/^\s*-\s*\[Phase\s+(\d+)/i);
|
|
1471
|
+
if (pm && parseInt(pm[1], 10) <= cutoff) {
|
|
1472
|
+
archive.push(line);
|
|
1473
|
+
}
|
|
1474
|
+
else {
|
|
1475
|
+
keep.push(line);
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
if (archive.length > 0) {
|
|
1479
|
+
archivedSections.push({ section: 'Decisions', count: archive.length, lines: archive });
|
|
1480
|
+
contentWork = contentWork.replace(decisionPattern, (_m, header) => `${header}${keep.join('\n')}`);
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
const recentPattern = /(###?\s*Recently Completed\s*\n)([\s\S]*?)(?=\n###?|\n##[^#]|$)/i;
|
|
1484
|
+
const recMatch = contentWork.match(recentPattern);
|
|
1485
|
+
if (recMatch) {
|
|
1486
|
+
const lines = recMatch[2].split('\n');
|
|
1487
|
+
const keep = [];
|
|
1488
|
+
const archive = [];
|
|
1489
|
+
for (const line of lines) {
|
|
1490
|
+
const pm = line.match(/Phase\s+(\d+)/i);
|
|
1491
|
+
if (pm && parseInt(pm[1], 10) <= cutoff) {
|
|
1492
|
+
archive.push(line);
|
|
1493
|
+
}
|
|
1494
|
+
else {
|
|
1495
|
+
keep.push(line);
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
if (archive.length > 0) {
|
|
1499
|
+
archivedSections.push({ section: 'Recently Completed', count: archive.length, lines: archive });
|
|
1500
|
+
contentWork = contentWork.replace(recentPattern, (_m, header) => `${header}${keep.join('\n')}`);
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
const blockersPattern = /(###?\s*(?:Blockers|Blockers\/Concerns|Blockers\s*&\s*Concerns)\s*\n)([\s\S]*?)(?=\n###?|\n##[^#]|$)/i;
|
|
1504
|
+
const blockersMatch = contentWork.match(blockersPattern);
|
|
1505
|
+
if (blockersMatch) {
|
|
1506
|
+
const lines = blockersMatch[2].split('\n');
|
|
1507
|
+
const keep = [];
|
|
1508
|
+
const archive = [];
|
|
1509
|
+
for (const line of lines) {
|
|
1510
|
+
const isResolved = /~~.*~~|\[RESOLVED\]/i.test(line);
|
|
1511
|
+
const pm = line.match(/Phase\s+(\d+)/i);
|
|
1512
|
+
if (isResolved && pm && parseInt(pm[1], 10) <= cutoff) {
|
|
1513
|
+
archive.push(line);
|
|
1514
|
+
}
|
|
1515
|
+
else {
|
|
1516
|
+
keep.push(line);
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
if (archive.length > 0) {
|
|
1520
|
+
archivedSections.push({ section: 'Blockers (resolved)', count: archive.length, lines: archive });
|
|
1521
|
+
contentWork = contentWork.replace(blockersPattern, (_m, header) => `${header}${keep.join('\n')}`);
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
const metricsPattern = /(###?\s*Performance Metrics\s*\n)([\s\S]*?)(?=\n###?|\n##[^#]|$)/i;
|
|
1525
|
+
const metricsMatch = contentWork.match(metricsPattern);
|
|
1526
|
+
if (metricsMatch) {
|
|
1527
|
+
const sectionLines = metricsMatch[2].split('\n');
|
|
1528
|
+
const keep = [];
|
|
1529
|
+
const archive = [];
|
|
1530
|
+
for (const line of sectionLines) {
|
|
1531
|
+
const rowPhase = extractPerformanceMetricsRowPhase(line);
|
|
1532
|
+
if (rowPhase !== null) {
|
|
1533
|
+
if (rowPhase <= cutoff) {
|
|
1534
|
+
archive.push(line);
|
|
1535
|
+
}
|
|
1536
|
+
else {
|
|
1537
|
+
keep.push(line);
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
else {
|
|
1541
|
+
keep.push(line);
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
if (archive.length > 0) {
|
|
1545
|
+
archivedSections.push({ section: 'Performance Metrics', count: archive.length, lines: archive });
|
|
1546
|
+
contentWork = contentWork.replace(metricsPattern, (_m, header) => `${header}${keep.join('\n')}`);
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
return { newContent: contentWork, archivedSections };
|
|
1550
|
+
}
|
|
1551
|
+
/**
|
|
1552
|
+
* Port of `cmdStatePrune` from state.cjs.
|
|
1553
|
+
* Args: `--keep-recent N` (default 3), `--dry-run`, `--silent` (omit extra logging fields — no-op in SDK JSON).
|
|
1554
|
+
*/
|
|
1555
|
+
export const statePrune = async (args, projectDir, workstream) => {
|
|
1556
|
+
const parsed = parseNamedArgs(args, ['keep-recent'], ['dry-run', 'silent']);
|
|
1557
|
+
const parsedKeepRecent = Number.parseInt(String(parsed['keep-recent'] ?? '3'), 10);
|
|
1558
|
+
if (!Number.isInteger(parsedKeepRecent) || parsedKeepRecent < 0) {
|
|
1559
|
+
return { data: { error: 'keep-recent must be a non-negative integer' } };
|
|
1560
|
+
}
|
|
1561
|
+
const keepRecent = parsedKeepRecent;
|
|
1562
|
+
const dryRun = parsed['dry-run'] === true;
|
|
1563
|
+
const paths = planningPaths(projectDir, workstream);
|
|
1564
|
+
const statePath = paths.state;
|
|
1565
|
+
if (!existsSync(statePath)) {
|
|
1566
|
+
return { data: { error: 'STATE.md not found' } };
|
|
1567
|
+
}
|
|
1568
|
+
const fullContent = await readFile(statePath, 'utf-8');
|
|
1569
|
+
// Align with CJS state.cjs:1615 — read Current Phase from the body text first,
|
|
1570
|
+
// fall back to 0 (same as CJS `parseInt(..., 10) || 0`).
|
|
1571
|
+
const currentPhaseRaw = stateExtractField(fullContent, 'Current Phase');
|
|
1572
|
+
const currentPhase = parseInt(String(currentPhaseRaw ?? '').trim(), 10) || 0;
|
|
1573
|
+
const cutoff = currentPhase - keepRecent;
|
|
1574
|
+
if (cutoff <= 0) {
|
|
1575
|
+
return {
|
|
1576
|
+
data: {
|
|
1577
|
+
pruned: false,
|
|
1578
|
+
reason: `Only ${currentPhase} phases — nothing to prune with --keep-recent ${keepRecent}`,
|
|
1579
|
+
},
|
|
1580
|
+
};
|
|
1581
|
+
}
|
|
1582
|
+
const body = stripFrontmatter(fullContent);
|
|
1583
|
+
if (dryRun) {
|
|
1584
|
+
const result = prunePass(body, cutoff);
|
|
1585
|
+
const totalPruned = result.archivedSections.reduce((sum, s) => sum + s.count, 0);
|
|
1586
|
+
return {
|
|
1587
|
+
data: {
|
|
1588
|
+
pruned: false,
|
|
1589
|
+
dry_run: true,
|
|
1590
|
+
cutoff_phase: cutoff,
|
|
1591
|
+
keep_recent: keepRecent,
|
|
1592
|
+
sections: result.archivedSections.map(s => ({
|
|
1593
|
+
section: s.section,
|
|
1594
|
+
entries_would_archive: s.count,
|
|
1595
|
+
})),
|
|
1596
|
+
total_would_archive: totalPruned,
|
|
1597
|
+
note: totalPruned > 0 ? 'Run without --dry-run to actually prune' : 'Nothing to prune',
|
|
1598
|
+
},
|
|
1599
|
+
};
|
|
1600
|
+
}
|
|
1601
|
+
const archived = [];
|
|
1602
|
+
await readModifyWriteStateMd(projectDir, (b) => {
|
|
1603
|
+
const result = prunePass(b, cutoff);
|
|
1604
|
+
archived.push(...result.archivedSections);
|
|
1605
|
+
return result.newContent;
|
|
1606
|
+
}, workstream);
|
|
1607
|
+
const archivePath = join(paths.planning, 'STATE-ARCHIVE.md');
|
|
1608
|
+
const totalPruned = archived.reduce((sum, s) => sum + s.count, 0);
|
|
1609
|
+
if (archived.length > 0) {
|
|
1610
|
+
const timestamp = new Date().toISOString().split('T')[0];
|
|
1611
|
+
let archiveContent = '';
|
|
1612
|
+
if (existsSync(archivePath)) {
|
|
1613
|
+
archiveContent = readFileSync(archivePath, 'utf-8');
|
|
1614
|
+
}
|
|
1615
|
+
else {
|
|
1616
|
+
archiveContent = '# STATE Archive\n\nPruned entries from STATE.md. Recoverable but no longer loaded into agent context.\n\n';
|
|
1617
|
+
}
|
|
1618
|
+
archiveContent += `## Pruned ${timestamp} (phases 1-${cutoff}, kept recent ${keepRecent})\n\n`;
|
|
1619
|
+
for (const section of archived) {
|
|
1620
|
+
archiveContent += `### ${section.section}\n\n${section.lines.join('\n')}\n\n`;
|
|
1621
|
+
}
|
|
1622
|
+
writeFileSync(archivePath, archiveContent, 'utf-8');
|
|
1623
|
+
}
|
|
1624
|
+
return {
|
|
1625
|
+
data: {
|
|
1626
|
+
pruned: totalPruned > 0,
|
|
1627
|
+
cutoff_phase: cutoff,
|
|
1628
|
+
keep_recent: keepRecent,
|
|
1629
|
+
sections: archived.map(s => ({ section: s.section, entries_archived: s.count })),
|
|
1630
|
+
total_archived: totalPruned,
|
|
1631
|
+
archive_file: totalPruned > 0 ? 'STATE-ARCHIVE.md' : null,
|
|
1632
|
+
},
|
|
1633
|
+
};
|
|
1634
|
+
};
|
|
1635
|
+
//# sourceMappingURL=state-mutation.js.map
|