@opengsd/gsd-core 1.10.0 → 1.12.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/agents/gsd-code-fixer.md +1 -1
- package/agents/gsd-debug-session-manager.md +12 -1
- package/agents/gsd-debugger.md +1 -1
- package/agents/gsd-doc-synthesizer.md +2 -4
- package/agents/gsd-dom-verifier.md +169 -0
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +22 -14
- package/agents/gsd-framework-selector.md +1 -3
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.md +5 -3
- package/agents/gsd-pattern-mapper.md +11 -0
- package/agents/gsd-phase-researcher.md +23 -2
- package/agents/gsd-plan-checker.md +50 -53
- package/agents/gsd-planner.md +50 -50
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.md +2 -2
- package/agents/gsd-roadmapper.md +15 -11
- package/agents/gsd-ui-checker.md +63 -4
- package/agents/gsd-ui-researcher.md +41 -3
- package/agents/gsd-user-profiler.md +3 -0
- package/agents/gsd-verifier.md +13 -4
- package/bin/install.js +1448 -1103
- package/commands/gsd/code-review.md +1 -1
- package/commands/gsd/discuss-phase.md +1 -1
- package/commands/gsd/execute-phase.md +1 -1
- package/commands/gsd/import.md +1 -1
- package/commands/gsd/map-codebase.md +1 -1
- package/commands/gsd/mempalace-capture.md +1 -1
- package/commands/gsd/mempalace-recall.md +1 -1
- package/commands/gsd/new-milestone.md +1 -1
- package/commands/gsd/quick.md +9 -5
- package/commands/gsd/review-backlog.md +2 -1
- package/commands/gsd/verify-work.md +1 -1
- package/gsd-core/bin/gsd-tools.cjs +1035 -138
- package/gsd-core/bin/lib/active-workstream-store.cjs +146 -22
- package/gsd-core/bin/lib/adr-parser.cjs +13 -7
- package/gsd-core/bin/lib/agent-install-check.cjs +392 -32
- package/gsd-core/bin/lib/api-coverage.cjs +33 -14
- package/gsd-core/bin/lib/artifacts.cjs +5 -0
- package/gsd-core/bin/lib/assumption-delta.cjs +32 -15
- package/gsd-core/bin/lib/audit-command-router.cjs +9 -2
- package/gsd-core/bin/lib/audit.cjs +1026 -268
- package/gsd-core/bin/lib/broken-windows.cjs +306 -28
- package/gsd-core/bin/lib/capability-consent.cjs +149 -15
- package/gsd-core/bin/lib/capability-lifecycle.cjs +45 -0
- package/gsd-core/bin/lib/capability-lock.cjs +10 -4
- package/gsd-core/bin/lib/capability-registry.cjs +845 -130
- package/gsd-core/bin/lib/capability-source.cjs +92 -0
- package/gsd-core/bin/lib/capability-state.cjs +18 -3
- package/gsd-core/bin/lib/capability-trust.cjs +444 -25
- package/gsd-core/bin/lib/capability-validator.cjs +700 -40
- package/gsd-core/bin/lib/capability-writer.cjs +3 -2
- package/gsd-core/bin/lib/check-command-router.cjs +216 -42
- package/gsd-core/bin/lib/claude-orchestration.cjs +56 -3
- package/gsd-core/bin/lib/cli-exit.cjs +496 -10
- package/gsd-core/bin/lib/code-review-depth.cjs +288 -0
- package/gsd-core/bin/lib/codex-agent-toml.cjs +735 -0
- package/gsd-core/bin/lib/command-aliases.cjs +22 -0
- package/gsd-core/bin/lib/command-arg-projection.cjs +144 -14
- package/gsd-core/bin/lib/command-roster.cjs +44 -1
- package/gsd-core/bin/lib/command-routing-hub.cjs +31 -2
- package/gsd-core/bin/lib/commands.cjs +1172 -108
- package/gsd-core/bin/lib/commonjs-marker.cjs +12 -6
- package/gsd-core/bin/lib/complexity-trigger.cjs +1192 -0
- package/gsd-core/bin/lib/config-loader.cjs +187 -23
- package/gsd-core/bin/lib/config.cjs +102 -3
- package/gsd-core/bin/lib/configuration.cjs +129 -37
- package/gsd-core/bin/lib/core-utils.cjs +208 -33
- package/gsd-core/bin/lib/decisions.cjs +23 -0
- package/gsd-core/bin/lib/edge-probe.cjs +9 -1
- package/gsd-core/bin/lib/estimate-cli.cjs +55 -11
- package/gsd-core/bin/lib/exit-code-registry.cjs +98 -0
- package/gsd-core/bin/lib/fallow-runner.cjs +20 -44
- package/gsd-core/bin/lib/frontmatter.cjs +899 -229
- package/gsd-core/bin/lib/gap-checker.cjs +95 -10
- package/gsd-core/bin/lib/git-base-branch.cjs +276 -39
- package/gsd-core/bin/lib/gsd2-import.cjs +10 -1
- package/gsd-core/bin/lib/health-diagnostic-rules/agent-install.cjs +101 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/config-validation.cjs +348 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +149 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/install-surface-shadowing.cjs +98 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/milestone-archive-hygiene.cjs +100 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +222 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +268 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/root-existence.cjs +161 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +303 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +187 -0
- package/gsd-core/bin/lib/health-diagnostic-types.cjs +68 -0
- package/gsd-core/bin/lib/health-diagnostic.cjs +451 -0
- package/gsd-core/bin/lib/host-integration.cjs +39 -6
- package/gsd-core/bin/lib/host-runtime-detection.cjs +134 -0
- package/gsd-core/bin/lib/init-command-router.cjs +118 -21
- package/gsd-core/bin/lib/init.cjs +439 -168
- package/gsd-core/bin/lib/install-effort-resolver.cjs +73 -30
- package/gsd-core/bin/lib/install-engine.cjs +811 -259
- package/gsd-core/bin/lib/install-fs-adapter.cjs +262 -0
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +235 -0
- package/gsd-core/bin/lib/install-profiles.cjs +212 -61
- package/gsd-core/bin/lib/install-scope.cjs +270 -0
- package/gsd-core/bin/lib/install-shadow-report.cjs +385 -0
- package/gsd-core/bin/lib/installed-surface-resolver.cjs +381 -0
- package/gsd-core/bin/lib/installer-migration-report.cjs +3 -0
- package/gsd-core/bin/lib/installer-migrations/010-antigravity-retire-confighome-artifacts.cjs +169 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +148 -38
- package/gsd-core/bin/lib/intel.cjs +101 -26
- package/gsd-core/bin/lib/io.cjs +170 -15
- package/gsd-core/bin/lib/learnings.cjs +85 -14
- package/gsd-core/bin/lib/legacy-cleanup.cjs +8 -2
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +2 -1
- package/gsd-core/bin/lib/markdown-table.cjs +183 -22
- package/gsd-core/bin/lib/milestone-lock.cjs +248 -0
- package/gsd-core/bin/lib/milestone.cjs +842 -73
- package/gsd-core/bin/lib/model-catalog.cjs +232 -16
- package/gsd-core/bin/lib/model-resolver.cjs +193 -68
- package/gsd-core/bin/lib/normalize-test-command.cjs +1 -1
- package/gsd-core/bin/lib/onboard-projection.cjs +5 -1
- package/gsd-core/bin/lib/pattern.cjs +122 -0
- package/gsd-core/bin/lib/phase-estimation.cjs +18 -9
- package/gsd-core/bin/lib/phase-id.cjs +514 -40
- package/gsd-core/bin/lib/phase-lifecycle.cjs +52 -19
- package/gsd-core/bin/lib/phase-locator.cjs +262 -34
- package/gsd-core/bin/lib/phase.cjs +1038 -214
- package/gsd-core/bin/lib/plan-dependency-graph.cjs +72 -1
- package/gsd-core/bin/lib/plan-document.cjs +263 -0
- package/gsd-core/bin/lib/plan-drift-guard.cjs +120 -0
- package/gsd-core/bin/lib/plan-scan.cjs +98 -3
- package/gsd-core/bin/lib/planning-command-router.cjs +61 -0
- package/gsd-core/bin/lib/planning-inspect.cjs +1168 -0
- package/gsd-core/bin/lib/planning-scope.cjs +31 -0
- package/gsd-core/bin/lib/planning-snapshot.cjs +894 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +112 -6
- package/gsd-core/bin/lib/probe-core.cjs +5 -2
- package/gsd-core/bin/lib/profile-output.cjs +1 -1
- package/gsd-core/bin/lib/profile-pipeline-command-router.cjs +50 -7
- package/gsd-core/bin/lib/profile-pipeline.cjs +6 -3
- package/gsd-core/bin/lib/real-home-guard.cjs +419 -0
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +766 -0
- package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +11 -6
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +22 -13
- package/gsd-core/bin/lib/review-lane-invocation.cjs +30 -0
- package/gsd-core/bin/lib/review-lane-runner.cjs +421 -66
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +13 -18
- package/gsd-core/bin/lib/roadmap-command-router.cjs +59 -11
- package/gsd-core/bin/lib/roadmap-parser.cjs +1006 -184
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +37 -10
- package/gsd-core/bin/lib/roadmap.cjs +442 -96
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +702 -52
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +14 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +459 -55
- package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +3 -2
- package/gsd-core/bin/lib/runtime-homes.cjs +69 -3
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +402 -58
- package/gsd-core/bin/lib/runtime-identity.cjs +234 -0
- package/gsd-core/bin/lib/runtime-name-policy.cjs +3 -1
- package/gsd-core/bin/lib/runtime-slash.cjs +96 -8
- package/gsd-core/bin/lib/security.cjs +104 -5
- package/gsd-core/bin/lib/shell-command-projection.cjs +342 -7
- package/gsd-core/bin/lib/smart-entry.cjs +133 -23
- package/gsd-core/bin/lib/spec-section.cjs +12 -7
- package/gsd-core/bin/lib/state-command-router.cjs +52 -19
- package/gsd-core/bin/lib/state-contract.cjs +359 -0
- package/gsd-core/bin/lib/state-document.cjs +338 -8
- package/gsd-core/bin/lib/state-md-schema.cjs +221 -0
- package/gsd-core/bin/lib/state-transition.cjs +846 -176
- package/gsd-core/bin/lib/state.cjs +2589 -369
- package/gsd-core/bin/lib/surface.cjs +33 -11
- package/gsd-core/bin/lib/task-command-router.cjs +111 -1
- package/gsd-core/bin/lib/task-content-resolution.cjs +368 -0
- package/gsd-core/bin/lib/teams-status.cjs +4 -1
- package/gsd-core/bin/lib/text-lines.cjs +80 -0
- package/gsd-core/bin/lib/token-scanner.cjs +76 -0
- package/gsd-core/bin/lib/uat-predicate.cjs +67 -23
- package/gsd-core/bin/lib/uat.cjs +1761 -167
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +9 -1
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +157 -0
- package/gsd-core/bin/lib/ui-safety-gate.cjs +51 -12
- package/gsd-core/bin/lib/unusable-input.cjs +37 -0
- package/gsd-core/bin/lib/update-context.cjs +8 -2
- package/gsd-core/bin/lib/user-artifact-staging.cjs +705 -0
- package/gsd-core/bin/lib/validate-command-router.cjs +2 -2
- package/gsd-core/bin/lib/validate.cjs +20 -6
- package/gsd-core/bin/lib/vendor/README.md +75 -0
- package/gsd-core/bin/lib/vendor/js-yaml.cjs +3014 -0
- package/gsd-core/bin/lib/vendor/re2js.cjs +6480 -0
- package/gsd-core/bin/lib/vendor/re2js.d.cts +938 -0
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +272 -9
- package/gsd-core/bin/lib/verify-command-grounding.cjs +846 -0
- package/gsd-core/bin/lib/verify.cjs +453 -918
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +53 -32
- package/gsd-core/bin/lib/workstream-inventory.cjs +63 -10
- package/gsd-core/bin/lib/workstream-name-policy.cjs +25 -4
- package/gsd-core/bin/lib/workstream.cjs +2 -2
- package/gsd-core/bin/lib/worktree-base-ref.cjs +66 -12
- package/gsd-core/bin/lib/worktree-safety.cjs +341 -18
- package/gsd-core/bin/shared/config-defaults.manifest.json +8 -1
- package/gsd-core/bin/shared/config-schema.manifest.json +12 -1
- package/gsd-core/bin/shared/exit-codes.json +8 -0
- package/gsd-core/bin/shared/exit-codes.sh +20 -0
- package/gsd-core/bin/shared/model-catalog.json +8 -1
- package/gsd-core/references/agent-contracts.md +44 -26
- package/gsd-core/references/api-coverage.md +24 -2
- package/gsd-core/references/autonomous-smart-discuss.md +3 -3
- package/gsd-core/references/checkpoints.md +39 -21
- package/gsd-core/references/context-budget.md +1 -1
- package/gsd-core/references/decimal-phase-calculation.md +5 -5
- package/gsd-core/references/dispatch-isolation-gate.md +138 -0
- package/gsd-core/references/doc-conflict-engine.md +1 -1
- package/gsd-core/references/edge-probe.md +8 -0
- package/gsd-core/references/execute-mvp-tdd.md +4 -6
- package/gsd-core/references/execute-phase-between-wave-reset.md +15 -14
- package/gsd-core/references/execute-phase-context-guard.md +1 -1
- package/gsd-core/references/execute-phase-response-language.md +1 -1
- package/gsd-core/references/execute-phase-wave-guard.md +17 -11
- package/gsd-core/references/failing-direction.md +78 -0
- package/gsd-core/references/gate-prompts.md +1 -1
- package/gsd-core/references/git-integration.md +5 -5
- package/gsd-core/references/git-planning-commit.md +5 -4
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/loop-hook-dispatch.md +61 -2
- package/gsd-core/references/model-profiles.md +12 -4
- package/gsd-core/references/mvp-concepts.md +9 -9
- package/gsd-core/references/nyquist-compliance.md +74 -0
- package/gsd-core/references/offer-next.md +3 -5
- package/gsd-core/references/phase-argument-parsing.md +3 -3
- package/gsd-core/references/planner-failing-direction.md +53 -0
- package/gsd-core/references/planner-guidance.md +3 -9
- package/gsd-core/references/planner-human-verify-mode.md +15 -1
- package/gsd-core/references/planner-preconditions.md +1 -1
- package/gsd-core/references/planner-reviews.md +1 -1
- package/gsd-core/references/planner-revision.md +1 -1
- package/gsd-core/references/planner-verify-command-grounding.md +17 -0
- package/gsd-core/references/planning-config.md +44 -13
- package/gsd-core/references/reviewer-instances.md +31 -0
- package/gsd-core/references/revision-loop.md +1 -1
- package/gsd-core/references/runtime-aware-dispatch.md +1 -1
- package/gsd-core/references/specless-probe-fallback.md +1 -1
- package/gsd-core/references/tdd.md +1 -3
- package/gsd-core/references/ui-brand.md +65 -21
- package/gsd-core/references/ui-consideration-probe.md +1 -1
- package/gsd-core/references/universal-anti-patterns.md +5 -5
- package/gsd-core/references/verifier-phase-gates.md +192 -0
- package/gsd-core/references/verify-command-path-resolvability.md +42 -0
- package/gsd-core/references/verify-mvp-mode.md +2 -2
- package/gsd-core/references/workstream-flag.md +33 -17
- package/gsd-core/templates/README.md +1 -1
- package/gsd-core/templates/SECURITY.md +3 -3
- package/gsd-core/templates/UI-SPEC.md +25 -3
- package/gsd-core/templates/VALIDATION.md +3 -3
- package/gsd-core/templates/discussion-log.md +1 -1
- package/gsd-core/templates/phase-prompt.md +5 -4
- package/gsd-core/templates/state.md +11 -4
- package/gsd-core/templates/verification-report.md +9 -1
- package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
- package/gsd-core/workflows/add-backlog.md +1 -1
- package/gsd-core/workflows/add-phase.md +3 -3
- package/gsd-core/workflows/add-tests.md +3 -8
- package/gsd-core/workflows/add-todo.md +1 -1
- package/gsd-core/workflows/ai-integration-phase.md +13 -20
- package/gsd-core/workflows/audit-fix.md +12 -3
- package/gsd-core/workflows/audit-milestone.md +9 -9
- package/gsd-core/workflows/audit-uat.md +17 -2
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +2 -2
- package/gsd-core/workflows/autonomous.md +11 -27
- package/gsd-core/workflows/check-todos.md +1 -1
- package/gsd-core/workflows/cleanup.md +64 -5
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +14 -4
- package/gsd-core/workflows/code-review-fix.md +38 -11
- package/gsd-core/workflows/code-review.md +159 -52
- package/gsd-core/workflows/complete-milestone.md +151 -23
- package/gsd-core/workflows/debug.md +12 -8
- package/gsd-core/workflows/diagnose-issues.md +47 -15
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +5 -8
- package/gsd-core/workflows/discuss-phase/modes/default.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/text.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +1 -3
- package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
- package/gsd-core/workflows/discuss-phase.md +1 -1
- package/gsd-core/workflows/do.md +3 -6
- package/gsd-core/workflows/docs-update.md +5 -4
- package/gsd-core/workflows/edit-phase.md +27 -2
- package/gsd-core/workflows/eval-review.md +7 -14
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +142 -15
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +77 -0
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +24 -4
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/protected-branch.md +21 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +39 -0
- package/gsd-core/workflows/execute-phase.md +72 -100
- package/gsd-core/workflows/execute-plan.md +52 -15
- package/gsd-core/workflows/explore.md +131 -4
- package/gsd-core/workflows/extract-learnings.md +1 -1
- package/gsd-core/workflows/fast.md +10 -2
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +5 -5
- package/gsd-core/workflows/health.md +76 -10
- package/gsd-core/workflows/import.md +18 -15
- package/gsd-core/workflows/inbox.md +4 -5
- package/gsd-core/workflows/ingest-docs.md +49 -16
- package/gsd-core/workflows/insert-phase.md +5 -5
- package/gsd-core/workflows/list-seeds.md +5 -3
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +12 -23
- package/gsd-core/workflows/map-codebase.md +1 -1
- package/gsd-core/workflows/milestone-summary.md +1 -1
- package/gsd-core/workflows/mvp-phase.md +8 -5
- package/gsd-core/workflows/new-milestone.md +22 -29
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
- package/gsd-core/workflows/new-project.md +26 -40
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +14 -2
- package/gsd-core/workflows/pause-work.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +2 -4
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +3 -3
- package/gsd-core/workflows/plan-phase.md +162 -59
- package/gsd-core/workflows/plan-review-convergence.md +96 -11
- package/gsd-core/workflows/plant-seed.md +2 -2
- package/gsd-core/workflows/pr-branch.md +187 -51
- package/gsd-core/workflows/profile-user.md +16 -14
- package/gsd-core/workflows/progress.md +61 -18
- package/gsd-core/workflows/quick/steps/discussion-phase.md +1 -3
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +5 -7
- package/gsd-core/workflows/quick/steps/quick-verification.md +28 -9
- package/gsd-core/workflows/quick/steps/research-phase.md +4 -6
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +3 -3
- package/gsd-core/workflows/quick.md +55 -44
- package/gsd-core/workflows/remove-phase.md +4 -4
- package/gsd-core/workflows/remove-workspace.md +2 -2
- package/gsd-core/workflows/resume-project.md +8 -12
- package/gsd-core/workflows/review.md +219 -20
- package/gsd-core/workflows/scan.md +1 -1
- package/gsd-core/workflows/secure-phase.md +3 -3
- package/gsd-core/workflows/session-report.md +2 -1
- package/gsd-core/workflows/settings-advanced.md +7 -9
- package/gsd-core/workflows/settings-integrations.md +64 -31
- package/gsd-core/workflows/settings.md +69 -7
- package/gsd-core/workflows/ship.md +116 -50
- package/gsd-core/workflows/sketch-wrap-up.md +11 -17
- package/gsd-core/workflows/sketch.md +12 -18
- package/gsd-core/workflows/smart-entry.md +3 -5
- package/gsd-core/workflows/spec-phase.md +53 -13
- package/gsd-core/workflows/spike-wrap-up.md +7 -11
- package/gsd-core/workflows/spike.md +20 -31
- package/gsd-core/workflows/stats.md +2 -2
- package/gsd-core/workflows/sync-skills.md +64 -9
- package/gsd-core/workflows/thread.md +11 -7
- package/gsd-core/workflows/transition.md +49 -14
- package/gsd-core/workflows/ui-phase.md +15 -21
- package/gsd-core/workflows/ui-review.md +8 -12
- package/gsd-core/workflows/ultraplan-phase.md +5 -13
- package/gsd-core/workflows/undo.md +8 -16
- package/gsd-core/workflows/update.md +7 -11
- package/gsd-core/workflows/validate-phase.md +3 -3
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +25 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
- package/gsd-core/workflows/verify-work.md +66 -25
- package/hooks/dist/gsd-agent-isolation-guard.js +158 -30
- package/hooks/dist/gsd-check-update-worker.js +56 -13
- package/hooks/dist/gsd-check-update.js +19 -1
- package/hooks/dist/gsd-config-reload.js +18 -12
- package/hooks/dist/gsd-context-monitor.js +19 -10
- package/hooks/dist/gsd-cursor-post-tool.js +3 -1
- package/hooks/dist/gsd-cursor-pre-tool.js +2 -3
- package/hooks/dist/gsd-cursor-session-start.js +2 -1
- package/hooks/dist/gsd-cursor-stop.js +2 -1
- package/hooks/dist/gsd-cursor-subagent-start.js +83 -3
- package/hooks/dist/gsd-cursor-subagent-stop.js +6 -3
- package/hooks/dist/gsd-ensure-canonical-path.js +2 -1
- package/hooks/dist/gsd-graphify-update.sh +22 -18
- package/hooks/dist/gsd-node-runner.sh +76 -0
- package/hooks/dist/gsd-phase-boundary.sh +1 -0
- package/hooks/dist/gsd-prompt-guard.js +37 -27
- package/hooks/dist/gsd-read-guard.js +16 -7
- package/hooks/dist/gsd-read-injection-scanner.js +55 -32
- package/hooks/dist/gsd-session-state.sh +1 -0
- package/hooks/dist/gsd-statusline.js +231 -24
- package/hooks/dist/gsd-update-banner.js +22 -1
- package/hooks/dist/gsd-validate-commit.sh +80 -6
- package/hooks/dist/gsd-windsurf-pre-command.js +16 -11
- package/hooks/dist/gsd-windsurf-pre-write.js +22 -13
- package/hooks/dist/gsd-workflow-guard.js +162 -46
- package/hooks/dist/gsd-worktree-path-guard.js +36 -21
- package/hooks/dist/gsd-write-guard.js +35 -25
- package/hooks/dist/lib/cli-exit.js +560 -0
- package/hooks/dist/lib/exit-code-registry.js +98 -0
- package/hooks/dist/lib/git-cmd.js +92 -59
- package/hooks/dist/lib/git-probe.js +84 -0
- package/hooks/dist/lib/hook-exit.js +81 -0
- package/hooks/dist/lib/injection-patterns.js +45 -0
- package/hooks/dist/lib/isolation-deny-reason.js +39 -0
- package/hooks/dist/lib/isolation-sentinel.js +9 -0
- package/hooks/dist/managed-hooks-registry.cjs +3 -0
- package/hooks/gsd-agent-isolation-guard.js +158 -30
- package/hooks/gsd-check-update-worker.js +56 -13
- package/hooks/gsd-check-update.js +19 -1
- package/hooks/gsd-config-reload.js +18 -12
- package/hooks/gsd-context-monitor.js +19 -10
- package/hooks/gsd-cursor-post-tool.js +3 -1
- package/hooks/gsd-cursor-pre-tool.js +2 -3
- package/hooks/gsd-cursor-session-start.js +2 -1
- package/hooks/gsd-cursor-stop.js +2 -1
- package/hooks/gsd-cursor-subagent-start.js +83 -3
- package/hooks/gsd-cursor-subagent-stop.js +6 -3
- package/hooks/gsd-ensure-canonical-path.js +2 -1
- package/hooks/gsd-graphify-update.sh +22 -18
- package/hooks/gsd-node-runner.sh +76 -0
- package/hooks/gsd-phase-boundary.sh +1 -0
- package/hooks/gsd-prompt-guard.js +37 -27
- package/hooks/gsd-read-guard.js +16 -7
- package/hooks/gsd-read-injection-scanner.js +55 -32
- package/hooks/gsd-session-state.sh +1 -0
- package/hooks/gsd-statusline.js +231 -24
- package/hooks/gsd-update-banner.js +22 -1
- package/hooks/gsd-validate-commit.sh +80 -6
- package/hooks/gsd-windsurf-pre-command.js +16 -11
- package/hooks/gsd-windsurf-pre-write.js +22 -13
- package/hooks/gsd-workflow-guard.js +162 -46
- package/hooks/gsd-worktree-path-guard.js +36 -21
- package/hooks/gsd-write-guard.js +35 -25
- package/hooks/lib/cli-exit.js +560 -0
- package/hooks/lib/exit-code-registry.js +98 -0
- package/hooks/lib/git-cmd.js +92 -59
- package/hooks/lib/git-probe.js +84 -0
- package/hooks/lib/hook-exit.js +81 -0
- package/hooks/lib/injection-patterns.js +45 -0
- package/hooks/lib/isolation-deny-reason.js +39 -0
- package/hooks/lib/isolation-sentinel.js +9 -0
- package/hooks/managed-hooks-registry.cjs +3 -0
- package/package.json +28 -11
- package/pi/gsd.cjs +19 -5
- package/scripts/base64-scan.sh +74 -12
- package/scripts/baselines/planning-prompt-drift-baseline.json +4 -0
- package/scripts/baselines/planning-snapshot-bypass-baseline.json +12 -0
- package/scripts/baselines/unreachable-guard-drift-baseline.json +4 -0
- package/scripts/build-hooks.js +5 -0
- package/scripts/changeset/lint.cjs +60 -5
- package/scripts/check-alias-drift.cjs +7 -43
- package/scripts/check-contract-drift.cjs +297 -0
- package/scripts/check-glossary-refs.cjs +77 -15
- package/scripts/check-mutation-score-ratchet.cjs +156 -0
- package/scripts/ci-check-job-near-cap.cjs +49 -0
- package/scripts/ci-pr-mergeability.cjs +262 -0
- package/scripts/ci-test-scope.cjs +64 -14
- package/scripts/ci-timeout-report.cjs +230 -0
- package/scripts/command-contract-helpers.cjs +903 -1
- package/scripts/docs-guard-registry.cjs +396 -0
- package/scripts/gen-adr-index.cjs +728 -38
- package/scripts/gen-capability-registry.cjs +11 -21
- package/scripts/gen-context-index.cjs +2 -11
- package/scripts/gen-exit-code-docs.cjs +318 -0
- package/scripts/gen-exit-code-registry.cjs +891 -0
- package/scripts/gen-features.cjs +836 -0
- package/scripts/gen-health-docs.cjs +390 -0
- package/scripts/gen-hooks-cli-exit.cjs +239 -0
- package/scripts/gen-install-tree-fixtures.cjs +2 -2
- package/scripts/gen-inventory-manifest.cjs +50 -4
- package/scripts/gen-loop-host-contract.cjs +138 -25
- package/scripts/gen-registry.cjs +3 -14
- package/scripts/gen-scripts-cli-exit.cjs +185 -0
- package/scripts/gen-state-md-docs.cjs +727 -0
- package/scripts/{test-failure-reasons.cjs → gsd-test-gate-reasons.cjs} +6 -0
- package/scripts/lib/alias-drift-families.cjs +46 -0
- package/scripts/lib/ci-job-timing.cjs +72 -0
- package/scripts/lib/cli-exit.cjs +546 -44
- package/scripts/lib/drift-scan.cjs +308 -0
- package/scripts/lib/exit-code-registry.cjs +98 -0
- package/scripts/lib/ndjson-reporter.cjs +119 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +1 -26
- package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +4 -0
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +3 -0
- package/scripts/lint-canary-version-leak.cjs +73 -0
- package/scripts/lint-command-contract.cjs +96 -13
- package/scripts/lint-completion-predicate-drift.cjs +933 -0
- package/scripts/lint-completion-ratio-drift.cjs +214 -0
- package/scripts/lint-default-flip-documentation.cjs +193 -0
- package/scripts/lint-docs-guard-registration.cjs +495 -0
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +193 -0
- package/scripts/lint-eslint-glob-coverage.allowlist.json +38 -0
- package/scripts/lint-eslint-glob-coverage.cjs +340 -0
- package/scripts/{lint-fix-has-regression-test.cjs → lint-fix-has-regression-tests.cjs} +12 -6
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +237 -0
- package/scripts/lint-health-diagnostic-rule-table.cjs +461 -0
- package/scripts/lint-hooks-runtime-build-seam.cjs +262 -0
- package/scripts/lint-milestone-window-drift.cjs +468 -0
- package/scripts/lint-mutation-test-derivation-drift.cjs +86 -0
- package/scripts/lint-phase-enumeration-drift.cjs +492 -0
- package/scripts/lint-plan-count-drift.cjs +318 -0
- package/scripts/lint-planning-artifact-writer-drift.cjs +398 -0
- package/scripts/lint-planning-prompt-drift.cjs +471 -0
- package/scripts/lint-planning-snapshot-bypass-drift.cjs +544 -0
- package/scripts/lint-regression-test-names.cjs +15 -13
- package/scripts/lint-removed-but-needed.cjs +488 -0
- package/scripts/lint-seam-enforcement.cjs +182 -0
- package/scripts/lint-slug-derivation-drift.cjs +921 -0
- package/scripts/lint-source-test-name-collision.cjs +241 -0
- package/scripts/lint-state-field-drift.cjs +805 -0
- package/scripts/lint-state-write-path-drift.cjs +950 -0
- package/scripts/lint-test-file-count.allowlist.json +137 -8
- package/scripts/lint-test-file-count.cjs +25 -3
- package/scripts/lint-unreachable-guard-drift.cjs +830 -0
- package/scripts/lint-vendored-deps.cjs +297 -0
- package/scripts/mutation-matrix.cjs +599 -50
- package/scripts/pr-changed-files.cjs +63 -0
- package/scripts/pr-template-policy.cjs +14 -4
- package/scripts/prompt-injection-scan.sh +100 -14
- package/scripts/require-issue-link-policy.cjs +192 -0
- package/scripts/secret-scan.sh +75 -13
- package/scripts/select-docs-guards.cjs +56 -0
- package/scripts/sync-runtime-launcher.cjs +24 -7
- package/skills/gsd-autonomous/SKILL.md +0 -1
- package/skills/gsd-code-review/SKILL.md +1 -1
- package/skills/gsd-discuss-phase/SKILL.md +1 -1
- package/skills/gsd-execute-phase/SKILL.md +1 -2
- package/skills/gsd-import/SKILL.md +1 -1
- package/skills/gsd-map-codebase/SKILL.md +1 -1
- package/skills/gsd-mempalace-capture/SKILL.md +1 -1
- package/skills/gsd-mempalace-recall/SKILL.md +1 -1
- package/skills/gsd-new-milestone/SKILL.md +1 -1
- package/skills/gsd-next/SKILL.md +0 -1
- package/skills/gsd-plan-phase/SKILL.md +0 -1
- package/skills/gsd-progress/SKILL.md +0 -1
- package/skills/gsd-quick/SKILL.md +9 -5
- package/skills/gsd-review-backlog/SKILL.md +2 -1
- package/skills/gsd-stats/SKILL.md +0 -1
- package/skills/gsd-verify-work/SKILL.md +1 -1
- package/vscode/package.json +1 -1
- package/bin/lib/ui-safety-gate.cjs +0 -107
- package/gsd-core/workflows/discovery-phase.md +0 -298
- package/gsd-core/workflows/plan-milestone-gaps.md +0 -281
- package/gsd-core/workflows/verify-phase.md +0 -574
- package/scripts/affected-tests-lib.cjs +0 -554
- package/scripts/lint-allow-test-rule-refs.cjs +0 -162
- package/scripts/lint-emitted-drift-ack.cjs +0 -344
- package/scripts/run-affected-tests.cjs +0 -7
- package/scripts/run-tests.cjs +0 -1051
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* State Contract Module — `.planning/state.json` schema v1 (#3227).
|
|
4
|
+
*
|
|
5
|
+
* A **best-effort publisher** invoked at 11 step-boundary commands
|
|
6
|
+
* (`state.*`, `phase.*`, `milestone.complete`). It composes existing
|
|
7
|
+
* canonical owners; it introduces no second answer to any question GSD
|
|
8
|
+
* already answers:
|
|
9
|
+
* - `planning-workspace.cjs`'s `planningPaths` for every `.planning/` path
|
|
10
|
+
* (workstream-aware — never re-derived here).
|
|
11
|
+
* - `phase-lifecycle.cjs`'s `locateProgressTable` (this issue's Edit 1) for
|
|
12
|
+
* "where is the Progress table" — the SAME table
|
|
13
|
+
* `deriveProgressFromRoadmap` counts from, so `phases[]` and
|
|
14
|
+
* `deriveProgressFromRoadmap`'s `totalPhases` can never disagree about
|
|
15
|
+
* which rows are data rows.
|
|
16
|
+
* - `phase-id.cjs`'s `isSentinelPhaseId` / `parsePhaseFromProse` for
|
|
17
|
+
* sentinel exclusion and STATE.md phase-token parsing.
|
|
18
|
+
* - `roadmap-parser.cjs`'s `getMilestoneInfo` for milestone identity.
|
|
19
|
+
* - `markdown-sectionizer.cjs`'s `collectSection` for the `## Phases`
|
|
20
|
+
* checkbox fallback.
|
|
21
|
+
* - `state-document.cjs`'s `stateFieldValue` + `frontmatter.cjs`'s
|
|
22
|
+
* `extractFrontmatter`/`stripFrontmatter` for STATE.md's `current_phase`.
|
|
23
|
+
* - `shell-command-projection.cjs`'s `platformReadSync`/`platformWriteSync`
|
|
24
|
+
* — the CLAUDE.md-designated single OS-facing I/O seam. `platformWriteSync`
|
|
25
|
+
* is ALREADY atomic (sibling tmp + `retryRenameSync`, Windows transient-
|
|
26
|
+
* lock retry, EXDEV fallback) — this module adds no sixth atomic-write
|
|
27
|
+
* helper (the repo already carries five).
|
|
28
|
+
* - `smart-entry.cjs`'s `classifyProject` for `next` — this is what makes
|
|
29
|
+
* "`next` equals smart-entry's recommended action" true BY CONSTRUCTION
|
|
30
|
+
* rather than by a second copy of the routing table.
|
|
31
|
+
*
|
|
32
|
+
* WHY NOT `PlanningSnapshot` / `buildPlanningInspect`. `PlanningSnapshot` is
|
|
33
|
+
* an explicitly-additive INTERNAL diagnostic shape (ADR-3180 §8.1) still
|
|
34
|
+
* growing across phases; freezing it as an external contract is the exact
|
|
35
|
+
* Hyrum's-Law break `planning.inspect` (`src/planning-inspect.cts`) already
|
|
36
|
+
* refused for the same reason (#2790). `state.json` declares its OWN flat,
|
|
37
|
+
* minimal, six-key schema instead — see PUBLIC SURFACE below.
|
|
38
|
+
*
|
|
39
|
+
* NOT built (Gall's Law / Zawinski's Law — see `.gsd/phase/feat-3227-state-
|
|
40
|
+
* contract/40-design.md`): a `--watch` mode, a reader API inside gsd-core, a
|
|
41
|
+
* diff/event stream, a config toggle, milestone-scoping of `phases[]`. This
|
|
42
|
+
* module answers "where is this project right now" and nothing else — a
|
|
43
|
+
* request for document *contents* belongs to `planning.inspect`.
|
|
44
|
+
*
|
|
45
|
+
* REQUIRE-CYCLE HAZARD (the single most important implementation
|
|
46
|
+
* constraint). `src/state.cts` imports THIS module, and `src/smart-entry.cts`
|
|
47
|
+
* imports `state.cjs` and destructures `readStateHeadFreshness` off it at
|
|
48
|
+
* MODULE LOAD time. A top-level `import smartEntry = require('./smart-entry.cjs')`
|
|
49
|
+
* here would therefore close the cycle
|
|
50
|
+
* `state.cjs -> state-contract.cjs -> smart-entry.cjs -> state.cjs`, binding
|
|
51
|
+
* `readStateHeadFreshness` to `undefined` inside `smart-entry.cjs` and
|
|
52
|
+
* throwing at its first call. Every owner below is required LAZILY, inside
|
|
53
|
+
* the function body, via a small cached loader — never at module top level —
|
|
54
|
+
* which also keeps this module's (and its owners') load cost off every
|
|
55
|
+
* command that imports `state.cjs` but never reaches a publish boundary.
|
|
56
|
+
* Someone will be tempted to "tidy" the lazy requires into top-level ones;
|
|
57
|
+
* doing so reopens the cycle.
|
|
58
|
+
*
|
|
59
|
+
* `withPlanningLock` is deliberately NOT taken around the write (Rejected §3
|
|
60
|
+
* of the design doc): it is not re-entrant, several phase commands already
|
|
61
|
+
* hold it when they would call this publisher, and `platformWriteSync`'s
|
|
62
|
+
* tmp+rename already makes each publish all-or-nothing without it.
|
|
63
|
+
*
|
|
64
|
+
* ADR-457 build-at-publish: source in src/state-contract.cts, compiled to
|
|
65
|
+
* gsd-core/bin/lib/state-contract.cjs (gitignored).
|
|
66
|
+
*/
|
|
67
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
68
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
69
|
+
};
|
|
70
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
71
|
+
exports.PUBLISH_REASON = exports.PHASE_STATUS = exports.PHASE_KEY_ORDER = exports.CONTRACT_KEY_ORDER = exports.STATE_CONTRACT_FLAVOR = exports.STATE_CONTRACT_VERSION = void 0;
|
|
72
|
+
exports.buildStateContract = buildStateContract;
|
|
73
|
+
exports.publishStateContract = publishStateContract;
|
|
74
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
75
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
76
|
+
// ─── Public wire vocabulary ────────────────────────────────────────────────
|
|
77
|
+
exports.STATE_CONTRACT_VERSION = '1.0.0';
|
|
78
|
+
exports.STATE_CONTRACT_FLAVOR = 'core';
|
|
79
|
+
/** Key order of the emitted contract object — an observable, pinned by test. */
|
|
80
|
+
exports.CONTRACT_KEY_ORDER = Object.freeze(['contract', 'flavor', 'milestone', 'phases', 'next', 'updated_at']);
|
|
81
|
+
/** Key order of each emitted phase object — an observable, pinned by test. */
|
|
82
|
+
exports.PHASE_KEY_ORDER = Object.freeze(['number', 'name', 'status']);
|
|
83
|
+
/** Frozen three-value phase status vocabulary. Conservative in what we send (Postel's Law). */
|
|
84
|
+
exports.PHASE_STATUS = Object.freeze({
|
|
85
|
+
COMPLETE: 'complete',
|
|
86
|
+
IN_PROGRESS: 'in_progress',
|
|
87
|
+
PENDING: 'pending',
|
|
88
|
+
});
|
|
89
|
+
/** Frozen `publishStateContract` result reasons. */
|
|
90
|
+
exports.PUBLISH_REASON = Object.freeze({
|
|
91
|
+
PUBLISHED: 'published',
|
|
92
|
+
NO_PLANNING_DIR: 'no_planning_dir',
|
|
93
|
+
WRITE_FAILED: 'write_failed',
|
|
94
|
+
});
|
|
95
|
+
let _owners = null;
|
|
96
|
+
/**
|
|
97
|
+
* Lazily require every owner this module composes. MUST stay lazy — see the
|
|
98
|
+
* "REQUIRE-CYCLE HAZARD" module-doc comment above. Cached after first call so
|
|
99
|
+
* repeat invocations within one process (multiple publishes in one command,
|
|
100
|
+
* or across the several boundary commands in a test run) pay the require
|
|
101
|
+
* cost once.
|
|
102
|
+
*/
|
|
103
|
+
function owners() {
|
|
104
|
+
if (_owners)
|
|
105
|
+
return _owners;
|
|
106
|
+
/* eslint-disable @typescript-eslint/no-require-imports */
|
|
107
|
+
const planningWorkspaceMod = require('./planning-workspace.cjs');
|
|
108
|
+
const shellCommandProjectionMod = require('./shell-command-projection.cjs');
|
|
109
|
+
const phaseLifecycleMod = require('./phase-lifecycle.cjs');
|
|
110
|
+
const phaseIdMod = require('./phase-id.cjs');
|
|
111
|
+
const roadmapParserMod = require('./roadmap-parser.cjs');
|
|
112
|
+
const markdownSectionizerMod = require('./markdown-sectionizer.cjs');
|
|
113
|
+
const stateDocumentMod = require('./state-document.cjs');
|
|
114
|
+
const frontmatterMod = require('./frontmatter.cjs');
|
|
115
|
+
const smartEntryMod = require('./smart-entry.cjs');
|
|
116
|
+
/* eslint-enable @typescript-eslint/no-require-imports */
|
|
117
|
+
_owners = {
|
|
118
|
+
planningPaths: planningWorkspaceMod.planningPaths,
|
|
119
|
+
platformReadSync: shellCommandProjectionMod.platformReadSync,
|
|
120
|
+
platformWriteSync: shellCommandProjectionMod.platformWriteSync,
|
|
121
|
+
locateProgressTable: phaseLifecycleMod.locateProgressTable,
|
|
122
|
+
isSentinelPhaseId: phaseIdMod.isSentinelPhaseId,
|
|
123
|
+
parsePhaseFromProse: phaseIdMod.parsePhaseFromProse,
|
|
124
|
+
getMilestoneInfo: roadmapParserMod.getMilestoneInfo,
|
|
125
|
+
collectSection: markdownSectionizerMod.collectSection,
|
|
126
|
+
stateFieldValue: stateDocumentMod.stateFieldValue,
|
|
127
|
+
extractFrontmatter: frontmatterMod.extractFrontmatter,
|
|
128
|
+
stripFrontmatter: frontmatterMod.stripFrontmatter,
|
|
129
|
+
classifyProject: smartEntryMod.classifyProject,
|
|
130
|
+
};
|
|
131
|
+
return _owners;
|
|
132
|
+
}
|
|
133
|
+
// ─── milestone ──────────────────────────────────────────────────────────────
|
|
134
|
+
function buildMilestone(cwd) {
|
|
135
|
+
try {
|
|
136
|
+
const { value } = owners().getMilestoneInfo(cwd);
|
|
137
|
+
if (!value)
|
|
138
|
+
return null;
|
|
139
|
+
// U+2014 EM DASH, spaced on both sides. Never fabricate a name — version
|
|
140
|
+
// alone when no name-bearing evidence resolved (design row 21).
|
|
141
|
+
return value.name && value.name.length > 0 ? `${value.version} — ${value.name}` : value.version;
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// ─── phases: Progress-table (primary) enumerator ───────────────────────────
|
|
148
|
+
const PHASE_CELL_RE = /^(\d+(?:\.\d+)*)\s*[.:)–—-]?\s*(.*)$/;
|
|
149
|
+
function statusFromProgressCell(raw) {
|
|
150
|
+
const normalized = (raw ?? '').trim().toLowerCase().replace(/\s+/g, ' ');
|
|
151
|
+
if (normalized === 'complete')
|
|
152
|
+
return exports.PHASE_STATUS.COMPLETE;
|
|
153
|
+
if (normalized === 'in progress')
|
|
154
|
+
return exports.PHASE_STATUS.IN_PROGRESS;
|
|
155
|
+
// Everything else — 'not started', 'deferred' (design row 12, lossy by
|
|
156
|
+
// design), '', and any unrecognized word — folds to pending. An
|
|
157
|
+
// unrecognized status must never reach the wire as a 4th value.
|
|
158
|
+
return exports.PHASE_STATUS.PENDING;
|
|
159
|
+
}
|
|
160
|
+
function phasesFromProgressTable(table) {
|
|
161
|
+
const { isSentinelPhaseId } = owners();
|
|
162
|
+
const phases = [];
|
|
163
|
+
for (const row of table.rows) {
|
|
164
|
+
const cell = (row['Phase'] ?? '').trim();
|
|
165
|
+
if (!/^\d/.test(cell))
|
|
166
|
+
continue; // stray note row, no leading digit
|
|
167
|
+
if (isSentinelPhaseId(cell))
|
|
168
|
+
continue; // phase 0 / 999.x sentinels
|
|
169
|
+
const m = PHASE_CELL_RE.exec(cell);
|
|
170
|
+
const number = m ? m[1] : cell;
|
|
171
|
+
const name = m && m[2].trim().length > 0 ? m[2].trim() : null;
|
|
172
|
+
phases.push({ number, name, status: statusFromProgressCell(row['Status']) });
|
|
173
|
+
}
|
|
174
|
+
return phases;
|
|
175
|
+
}
|
|
176
|
+
// ─── phases: `## Phases` checkbox fallback ─────────────────────────────────
|
|
177
|
+
// `- [x] **Phase 1: Foundation**` / `- [ ] **Phase 2.1: Hardening**`.
|
|
178
|
+
const PHASE_BULLET_RE = /^[ \t]*[-*][ \t]+\[([ xX])\][ \t]+\*\*Phase[ \t]+(\d+(?:\.\d+)*)[ \t]*:?[ \t]*([^*\n]*)\*\*/gm;
|
|
179
|
+
/**
|
|
180
|
+
* STATE.md's current phase, via the same frontmatter-then-body chain
|
|
181
|
+
* `cmdStateCompletePhase` uses (`stateFieldValue` owns the #1760 fallback
|
|
182
|
+
* ladder). Any failure anywhere in the chain yields `null` — treat current
|
|
183
|
+
* phase as unknown so every unchecked bullet is PENDING rather than
|
|
184
|
+
* IN_PROGRESS by a guess.
|
|
185
|
+
*/
|
|
186
|
+
function currentPhaseFromState(statePath) {
|
|
187
|
+
const { platformReadSync, extractFrontmatter, stripFrontmatter, stateFieldValue, parsePhaseFromProse } = owners();
|
|
188
|
+
try {
|
|
189
|
+
const raw = platformReadSync(statePath);
|
|
190
|
+
if (raw === null)
|
|
191
|
+
return null;
|
|
192
|
+
const fm = extractFrontmatter(raw, statePath);
|
|
193
|
+
const body = stripFrontmatter(raw);
|
|
194
|
+
const { value } = stateFieldValue(fm, body, 'current_phase', 'Current Phase');
|
|
195
|
+
if (!value)
|
|
196
|
+
return null;
|
|
197
|
+
return parsePhaseFromProse(value).phase;
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Fallback enumerator when the ROADMAP carries no Progress table.
|
|
205
|
+
*
|
|
206
|
+
* Scoping to `## Phases` is load-bearing negative space (design "Not-
|
|
207
|
+
* corruption" section): it is what keeps `- [x] 01-01: a plan` (a PLAN
|
|
208
|
+
* bullet under `## Phase Details`) and `- ✅ **v1.0 MVP** - Phases 1-4`
|
|
209
|
+
* (a MILESTONE bullet under `## Milestones`) from being read as phases. The
|
|
210
|
+
* `**Phase N` anchor inside `PHASE_BULLET_RE` is the second layer of that
|
|
211
|
+
* defence — a plan bullet's text never starts with `**Phase`.
|
|
212
|
+
*/
|
|
213
|
+
function phasesFromChecklist(roadmapContent, cwd, statePath) {
|
|
214
|
+
const { collectSection, isSentinelPhaseId } = owners();
|
|
215
|
+
const section = collectSection(roadmapContent, (h) => /^phases$/i.test(h.text.trim()));
|
|
216
|
+
if (!section)
|
|
217
|
+
return [];
|
|
218
|
+
const currentPhase = currentPhaseFromState(statePath);
|
|
219
|
+
const phases = [];
|
|
220
|
+
let match;
|
|
221
|
+
const pattern = new RegExp(PHASE_BULLET_RE.source, PHASE_BULLET_RE.flags);
|
|
222
|
+
while ((match = pattern.exec(section.body)) !== null) {
|
|
223
|
+
const checked = match[1] === 'x' || match[1] === 'X';
|
|
224
|
+
const number = match[2];
|
|
225
|
+
if (isSentinelPhaseId(number))
|
|
226
|
+
continue;
|
|
227
|
+
const name = match[3].replace(/\r$/, '').trim();
|
|
228
|
+
const status = checked
|
|
229
|
+
? exports.PHASE_STATUS.COMPLETE
|
|
230
|
+
: (currentPhase !== null && number === currentPhase ? exports.PHASE_STATUS.IN_PROGRESS : exports.PHASE_STATUS.PENDING);
|
|
231
|
+
phases.push({ number, name: name.length > 0 ? name : null, status });
|
|
232
|
+
}
|
|
233
|
+
return phases;
|
|
234
|
+
}
|
|
235
|
+
function buildPhases(cwd, paths) {
|
|
236
|
+
const { platformReadSync, locateProgressTable } = owners();
|
|
237
|
+
try {
|
|
238
|
+
let content = platformReadSync(paths.roadmap);
|
|
239
|
+
if (content === null)
|
|
240
|
+
return [];
|
|
241
|
+
if (content.charCodeAt(0) === 0xfeff)
|
|
242
|
+
content = content.slice(1); // strip leading BOM
|
|
243
|
+
const table = locateProgressTable(content);
|
|
244
|
+
if (table)
|
|
245
|
+
return phasesFromProgressTable(table);
|
|
246
|
+
return phasesFromChecklist(content, cwd, paths.state);
|
|
247
|
+
}
|
|
248
|
+
catch {
|
|
249
|
+
return [];
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
// ─── next ───────────────────────────────────────────────────────────────────
|
|
253
|
+
function buildNext(cwd, deps) {
|
|
254
|
+
try {
|
|
255
|
+
const classify = deps?.classify ?? owners().classifyProject;
|
|
256
|
+
const result = classify(cwd);
|
|
257
|
+
const action = result.actions.find((a) => a.id === result.recommended);
|
|
258
|
+
if (!action)
|
|
259
|
+
return null;
|
|
260
|
+
return { command: action.command, label: action.label, reason: result.summary };
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
// ─── Entry points ───────────────────────────────────────────────────────────
|
|
267
|
+
/**
|
|
268
|
+
* Build the state-contract snapshot. PURE — writes nothing. Every stage is
|
|
269
|
+
* independently try/caught (milestone, phases, next) so one bad document
|
|
270
|
+
* cannot lose the others; `updated_at` and the frozen `contract`/`flavor`
|
|
271
|
+
* keys always resolve.
|
|
272
|
+
*/
|
|
273
|
+
function buildStateContract(cwd, deps) {
|
|
274
|
+
const nowFn = deps?.now ?? Date.now;
|
|
275
|
+
const updated_at = new Date(nowFn()).toISOString();
|
|
276
|
+
// #2245 shape: `planningPaths` -> `planningDir` throws a plain Error for an
|
|
277
|
+
// invalid GSD_WORKSTREAM/GSD_PROJECT segment. This call must not be hoisted
|
|
278
|
+
// outside a try, or that throw escapes uncaught and breaks the invariant
|
|
279
|
+
// this function is documented as upholding (see `getMilestoneInfo`'s
|
|
280
|
+
// equivalent guard comment in src/roadmap-parser.cts for the same shape).
|
|
281
|
+
let paths;
|
|
282
|
+
try {
|
|
283
|
+
paths = owners().planningPaths(cwd);
|
|
284
|
+
}
|
|
285
|
+
catch {
|
|
286
|
+
paths = null;
|
|
287
|
+
}
|
|
288
|
+
if (!paths) {
|
|
289
|
+
return {
|
|
290
|
+
contract: exports.STATE_CONTRACT_VERSION,
|
|
291
|
+
flavor: exports.STATE_CONTRACT_FLAVOR,
|
|
292
|
+
milestone: null,
|
|
293
|
+
phases: [],
|
|
294
|
+
next: null,
|
|
295
|
+
updated_at,
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
const milestone = buildMilestone(cwd);
|
|
299
|
+
const phases = buildPhases(cwd, paths);
|
|
300
|
+
const next = buildNext(cwd, deps);
|
|
301
|
+
return {
|
|
302
|
+
contract: exports.STATE_CONTRACT_VERSION,
|
|
303
|
+
flavor: exports.STATE_CONTRACT_FLAVOR,
|
|
304
|
+
milestone,
|
|
305
|
+
phases,
|
|
306
|
+
next,
|
|
307
|
+
updated_at,
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Publish the state-contract snapshot to `<planning>/state.json`. NEVER
|
|
312
|
+
* throws — for any input, ever (acceptance criterion 3: the parent boundary
|
|
313
|
+
* command's exit code and stdout must be unchanged whatever happens here).
|
|
314
|
+
*
|
|
315
|
+
* No `.planning/` directory at all: writes nothing, creates nothing. This
|
|
316
|
+
* guard is essential — `platformWriteSync` does `mkdirSync(dirname,
|
|
317
|
+
* {recursive:true})`, so without it the publisher would conjure a
|
|
318
|
+
* `.planning/` tree inside a non-GSD directory.
|
|
319
|
+
*
|
|
320
|
+
* `withPlanningLock` is deliberately NOT taken here — see the module-doc
|
|
321
|
+
* "REQUIRE-CYCLE HAZARD" section's sibling note: it is not re-entrant and
|
|
322
|
+
* several phase commands already hold it when they call this publisher, so
|
|
323
|
+
* acquiring it here would throw in exactly the situation this function must
|
|
324
|
+
* never perturb. `platformWriteSync`'s sibling-tmp + rename already makes
|
|
325
|
+
* each publish all-or-nothing without it.
|
|
326
|
+
*/
|
|
327
|
+
function publishStateContract(cwd, deps) {
|
|
328
|
+
try {
|
|
329
|
+
const { planningPaths, platformWriteSync } = owners();
|
|
330
|
+
// Resolve the planning root BEFORE anything else. A resolution failure
|
|
331
|
+
// (invalid GSD_WORKSTREAM/GSD_PROJECT segment — the #2245 shape) means no
|
|
332
|
+
// write was ever attempted, so it must map to `no_planning_dir`, not
|
|
333
|
+
// `write_failed` — that reason is reserved for an attempted-and-failed
|
|
334
|
+
// write, and reporting it here would send a caller looking at disk
|
|
335
|
+
// permissions for a problem that isn't there.
|
|
336
|
+
let paths;
|
|
337
|
+
try {
|
|
338
|
+
paths = planningPaths(cwd);
|
|
339
|
+
}
|
|
340
|
+
catch {
|
|
341
|
+
return { published: false, reason: exports.PUBLISH_REASON.NO_PLANNING_DIR };
|
|
342
|
+
}
|
|
343
|
+
if (!node_fs_1.default.existsSync(paths.planning)) {
|
|
344
|
+
return { published: false, reason: exports.PUBLISH_REASON.NO_PLANNING_DIR };
|
|
345
|
+
}
|
|
346
|
+
const snapshot = buildStateContract(cwd, deps);
|
|
347
|
+
const statePath = node_path_1.default.join(paths.planning, 'state.json');
|
|
348
|
+
try {
|
|
349
|
+
platformWriteSync(statePath, JSON.stringify(snapshot, null, 2) + '\n');
|
|
350
|
+
}
|
|
351
|
+
catch {
|
|
352
|
+
return { published: false, reason: exports.PUBLISH_REASON.WRITE_FAILED };
|
|
353
|
+
}
|
|
354
|
+
return { published: true, reason: exports.PUBLISH_REASON.PUBLISHED };
|
|
355
|
+
}
|
|
356
|
+
catch {
|
|
357
|
+
return { published: false, reason: exports.PUBLISH_REASON.WRITE_FAILED };
|
|
358
|
+
}
|
|
359
|
+
}
|