@opengsd/gsd-core 1.15.0 → 1.17.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 -2
- package/.opencode/plugins/gsd-core.js +336 -6
- package/.opencode/plugins/gsd-statusline/tui.tsx +55 -0
- package/GEMINI.md +1 -1
- package/agents/gsd-code-fixer.compact.md +1 -1
- package/agents/gsd-code-fixer.md +1 -1
- package/agents/gsd-code-reviewer.compact.md +5 -3
- package/agents/gsd-code-reviewer.md +8 -6
- package/agents/gsd-debug-session-manager.compact.md +7 -1
- package/agents/gsd-debug-session-manager.md +7 -1
- package/agents/gsd-debugger.md +2 -2
- package/agents/gsd-eval-auditor.compact.md +1 -1
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +4 -4
- package/agents/gsd-intel-updater.compact.md +1 -1
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.md +2 -2
- package/agents/gsd-phase-researcher.md +1 -1
- package/agents/gsd-plan-checker.md +7 -2
- package/agents/gsd-planner.md +3 -3
- package/agents/gsd-project-researcher.compact.md +1 -1
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.compact.md +1 -1
- package/agents/gsd-research-synthesizer.md +1 -1
- package/agents/gsd-ui-auditor.compact.md +21 -30
- package/agents/gsd-ui-auditor.md +42 -51
- package/agents/gsd-ui-researcher.compact.md +1 -1
- package/agents/gsd-ui-researcher.md +1 -1
- package/agents/gsd-verifier.md +31 -9
- package/bin/gsd-mcp-server.js +3 -1
- package/bin/install.js +487 -290
- package/commands/gsd/add-tests.md +6 -1
- package/commands/gsd/ai-integration-phase.md +6 -1
- package/commands/gsd/audit-fix.md +5 -0
- package/commands/gsd/audit-milestone.md +6 -1
- package/commands/gsd/autonomous.md +5 -0
- package/commands/gsd/capture.md +8 -4
- package/commands/gsd/code-review.md +7 -2
- package/commands/gsd/complete-milestone.md +4 -0
- package/commands/gsd/config.md +7 -3
- package/commands/gsd/debug.md +11 -7
- package/commands/gsd/discuss-phase.md +7 -3
- package/commands/gsd/docs-update.md +12 -7
- package/commands/gsd/eval-review.md +6 -1
- package/commands/gsd/execute-phase.md +12 -7
- package/commands/gsd/extract-learnings.md +5 -0
- package/commands/gsd/fast.md +4 -0
- package/commands/gsd/forensics.md +5 -1
- package/commands/gsd/graphify.md +10 -6
- package/commands/gsd/health.md +5 -0
- package/commands/gsd/help.md +7 -2
- package/commands/gsd/import.md +7 -3
- package/commands/gsd/inbox.md +5 -0
- package/commands/gsd/ingest-docs.md +5 -1
- package/commands/gsd/manager.md +6 -1
- package/commands/gsd/map-codebase.md +7 -3
- package/commands/gsd/mempalace-capture.md +5 -1
- package/commands/gsd/mempalace-recall.md +5 -1
- package/commands/gsd/milestone-summary.md +5 -1
- package/commands/gsd/mvp-phase.md +8 -3
- package/commands/gsd/new-milestone.md +6 -1
- package/commands/gsd/new-project.md +5 -0
- package/commands/gsd/next.md +6 -1
- package/commands/gsd/ns-context.md +4 -0
- package/commands/gsd/ns-ideate.md +4 -0
- package/commands/gsd/ns-manage.md +4 -0
- package/commands/gsd/ns-project.md +4 -0
- package/commands/gsd/ns-review.md +4 -0
- package/commands/gsd/ns-workflow.md +4 -0
- package/commands/gsd/onboard.md +6 -1
- package/commands/gsd/pause-work.md +5 -1
- package/commands/gsd/phase.md +8 -4
- package/commands/gsd/plan-phase.md +6 -1
- package/commands/gsd/plan-review-convergence.md +5 -1
- package/commands/gsd/pr-branch.md +4 -0
- package/commands/gsd/profile-user.md +5 -1
- package/commands/gsd/progress.md +6 -1
- package/commands/gsd/quick-batch.md +20 -8
- package/commands/gsd/quick.md +12 -7
- package/commands/gsd/review.md +5 -1
- package/commands/gsd/secure-phase.md +6 -1
- package/commands/gsd/ship.md +5 -0
- package/commands/gsd/sketch.md +7 -2
- package/commands/gsd/spec-phase.md +5 -1
- package/commands/gsd/spike.md +8 -3
- package/commands/gsd/surface.md +5 -1
- package/commands/gsd/thread.md +4 -0
- package/commands/gsd/ui-phase.md +6 -1
- package/commands/gsd/ui-review.md +6 -1
- package/commands/gsd/ultraplan-phase.md +5 -1
- package/commands/gsd/undo.md +5 -1
- package/commands/gsd/update.md +6 -2
- package/commands/gsd/validate-phase.md +6 -1
- package/commands/gsd/verify-work.md +6 -1
- package/commands/gsd/workspace.md +7 -3
- package/gsd-core/bin/gsd-tools.cjs +159 -58
- package/gsd-core/bin/lib/active-workstream-store.cjs +15 -0
- package/gsd-core/bin/lib/adr-parser.cjs +37 -5
- package/gsd-core/bin/lib/agent-install-check.cjs +4 -1
- package/gsd-core/bin/lib/audit.cjs +78 -44
- package/gsd-core/bin/lib/broken-windows.cjs +13 -13
- package/gsd-core/bin/lib/capability-activation.cjs +9 -4
- package/gsd-core/bin/lib/capability-registry.cjs +249 -117
- package/gsd-core/bin/lib/capability-validator.cjs +18 -1
- package/gsd-core/bin/lib/capability-writer.cjs +2 -1
- package/gsd-core/bin/lib/check-auto-mode.cjs +35 -0
- package/gsd-core/bin/lib/check-command-router.cjs +164 -1712
- package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +13 -2
- package/gsd-core/bin/lib/cli-exit.cjs +12 -0
- package/gsd-core/bin/lib/codex-agent-toml.cjs +11 -8
- package/gsd-core/bin/lib/command-aliases.cjs +7 -0
- package/gsd-core/bin/lib/command-routing-hub.cjs +48 -1
- package/gsd-core/bin/lib/commands.cjs +201 -178
- package/gsd-core/bin/lib/complexity-trigger.cjs +8 -7
- package/gsd-core/bin/lib/config.cjs +43 -12
- package/gsd-core/bin/lib/core-utils.cjs +6 -1
- package/gsd-core/bin/lib/coverage.cjs +4 -8
- package/gsd-core/bin/lib/decision-coverage-support.cjs +259 -0
- package/gsd-core/bin/lib/drift.cjs +177 -42
- package/gsd-core/bin/lib/frontmatter-fence.cjs +90 -0
- package/gsd-core/bin/lib/frontmatter-splice.cjs +494 -0
- package/gsd-core/bin/lib/frontmatter.cjs +413 -234
- package/gsd-core/bin/lib/gap-checker.cjs +72 -29
- package/gsd-core/bin/lib/gate-api-coverage-verify-pre.cjs +381 -0
- package/gsd-core/bin/lib/gate-args.cjs +53 -0
- package/gsd-core/bin/lib/gate-codebase-drift.cjs +285 -0
- package/gsd-core/bin/lib/gate-config.cjs +46 -0
- package/gsd-core/bin/lib/gate-context-drift.cjs +142 -0
- package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +169 -0
- package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +126 -0
- package/gsd-core/bin/lib/gate-evaluation-scope.cjs +555 -0
- package/gsd-core/bin/lib/gate-evidence.cjs +138 -0
- package/gsd-core/bin/lib/gate-exit.cjs +27 -0
- package/gsd-core/bin/lib/gate-gap-analysis-plan-post.cjs +61 -0
- package/gsd-core/bin/lib/gate-phase-context.cjs +170 -0
- package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +1 -1
- package/gsd-core/bin/lib/gate-predicate.cjs +165 -0
- package/gsd-core/bin/lib/gate-prohibition-enforcement.cjs +94 -0
- package/gsd-core/bin/lib/gate-schema-drift.cjs +165 -0
- package/gsd-core/bin/lib/gate-tdd-red-evidence.cjs +100 -0
- package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +182 -0
- package/gsd-core/bin/lib/gate-ui-plan.cjs +86 -0
- package/gsd-core/bin/lib/gate-ui-safety.cjs +81 -0
- package/gsd-core/bin/lib/gate-verdict.cjs +64 -0
- package/gsd-core/bin/lib/gate-verify-command-paths.cjs +78 -0
- package/gsd-core/bin/lib/gate-verify-failure-directions.cjs +41 -0
- package/gsd-core/bin/lib/graphify.cjs +3 -2
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +43 -47
- package/gsd-core/bin/lib/health-diagnostic.cjs +45 -8
- package/gsd-core/bin/lib/init.cjs +194 -108
- package/gsd-core/bin/lib/install-engine.cjs +30 -35
- package/gsd-core/bin/lib/install-profiles.cjs +7 -4
- package/gsd-core/bin/lib/install-shadow-report.cjs +12 -0
- package/gsd-core/bin/lib/installer-migrations/011-opencode-mcp-no-prompts.cjs +99 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +54 -1
- package/gsd-core/bin/lib/io.cjs +122 -3
- package/gsd-core/bin/lib/jsonc-edit.cjs +418 -0
- package/gsd-core/bin/lib/loop-host-contract.cjs +2 -1
- package/gsd-core/bin/lib/loop-resolver.cjs +95 -0
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +75 -1
- package/gsd-core/bin/lib/mcp-server.cjs +5 -1
- package/gsd-core/bin/lib/milestone.cjs +19 -1
- package/gsd-core/bin/lib/model-resolver.cjs +18 -18
- package/gsd-core/bin/lib/observability/event.cjs +1 -1
- package/gsd-core/bin/lib/observability/logger.cjs +46 -1
- package/gsd-core/bin/lib/opencode-mcp-entry.cjs +39 -0
- package/gsd-core/bin/lib/opencode-version.cjs +486 -0
- package/gsd-core/bin/lib/pattern.cjs +10 -0
- package/gsd-core/bin/lib/phase-command-router.cjs +11 -4
- package/gsd-core/bin/lib/phase-estimation.cjs +5 -4
- package/gsd-core/bin/lib/phase-id.cjs +1 -1
- package/gsd-core/bin/lib/phase-lifecycle.cjs +9 -2
- package/gsd-core/bin/lib/phase-status.cjs +360 -0
- package/gsd-core/bin/lib/phase.cjs +301 -80
- package/gsd-core/bin/lib/plan-document.cjs +93 -19
- package/gsd-core/bin/lib/plan-drift-guard.cjs +5 -0
- package/gsd-core/bin/lib/planning-document.cjs +273 -40
- package/gsd-core/bin/lib/planning-inspect.cjs +42 -8
- package/gsd-core/bin/lib/planning-snapshot.cjs +18 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +76 -53
- package/gsd-core/bin/lib/pristine-baseline.cjs +10 -0
- package/gsd-core/bin/lib/profile-output.cjs +6 -3
- package/gsd-core/bin/lib/prohibition-enforcement.cjs +0 -55
- package/gsd-core/bin/lib/quick-batch-command-router.cjs +35 -9
- package/gsd-core/bin/lib/quick-batch-dispatch.cjs +13 -9
- package/gsd-core/bin/lib/real-home-guard.cjs +9 -1
- package/gsd-core/bin/lib/report-parser.cjs +269 -0
- package/gsd-core/bin/lib/roadmap-command-router.cjs +13 -15
- package/gsd-core/bin/lib/roadmap-parser.cjs +82 -15
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +127 -65
- package/gsd-core/bin/lib/roadmap.cjs +169 -72
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +186 -161
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +2 -1
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +57 -1
- package/gsd-core/bin/lib/runtime-homes.cjs +13 -10
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +365 -594
- package/gsd-core/bin/lib/runtime-name-policy.cjs +142 -27
- package/gsd-core/bin/lib/runtime-slash.cjs +60 -30
- package/gsd-core/bin/lib/shell-command-projection.cjs +37 -2
- package/gsd-core/bin/lib/smart-entry.cjs +111 -56
- package/gsd-core/bin/lib/stale-bake-guard.cjs +32 -48
- package/gsd-core/bin/lib/state-contract.cjs +15 -18
- package/gsd-core/bin/lib/state-document.cjs +100 -22
- package/gsd-core/bin/lib/state-transition.cjs +67 -9
- package/gsd-core/bin/lib/state.cjs +668 -171
- package/gsd-core/bin/lib/surface.cjs +2 -1
- package/gsd-core/bin/lib/tdd-red-evidence.cjs +48 -152
- package/gsd-core/bin/lib/uat-predicate.cjs +313 -35
- package/gsd-core/bin/lib/uat.cjs +424 -7
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +94 -58
- package/gsd-core/bin/lib/update-context.cjs +18 -1
- package/gsd-core/bin/lib/vendor/README.md +31 -9
- package/gsd-core/bin/lib/vendor/saxes.cjs +1934 -0
- package/gsd-core/bin/lib/vendor/saxes.cjs.LICENSE.txt +92 -0
- package/gsd-core/bin/lib/vendor/tap-parser.cjs +8927 -0
- package/gsd-core/bin/lib/vendor/tap-parser.cjs.LICENSE.txt +152 -0
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +1265 -324
- package/gsd-core/bin/lib/verify-command-router.cjs +18 -7
- package/gsd-core/bin/lib/verify.cjs +286 -567
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +14 -6
- package/gsd-core/bin/lib/workstream-inventory.cjs +31 -21
- package/gsd-core/bin/lib/workstream-name-policy.cjs +31 -1
- package/gsd-core/bin/lib/workstream.cjs +11 -2
- package/gsd-core/bin/shared/config-defaults.manifest.json +5 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +4 -0
- package/gsd-core/references/autonomous-smart-discuss.md +2 -1
- package/gsd-core/references/autonomous-ui-design-contract.md +3 -3
- package/gsd-core/references/execute-mvp-tdd.md +5 -10
- package/gsd-core/references/execute-phase-between-wave-reset.md +3 -0
- package/gsd-core/references/execute-phase-response-language.md +1 -1
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/loop-hook-dispatch.md +7 -1
- package/gsd-core/references/offer-next.md +1 -1
- package/gsd-core/references/planning-config.md +1 -1
- package/gsd-core/references/spidr-splitting.md +1 -1
- package/gsd-core/references/tdd.md +10 -4
- package/gsd-core/references/verifier-phase-gates.md +5 -2
- package/gsd-core/references/verify-mvp-mode.md +2 -2
- package/gsd-core/references/workstream-flag.md +33 -3
- package/gsd-core/templates/README.md +1 -1
- package/gsd-core/templates/UAT.md +17 -1
- package/gsd-core/templates/config.json +2 -11
- package/gsd-core/templates/verification-report.md +1 -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 +8 -7
- package/gsd-core/workflows/add-tests.md +3 -2
- package/gsd-core/workflows/add-todo.md +4 -3
- package/gsd-core/workflows/ai-integration-phase.md +3 -2
- package/gsd-core/workflows/audit-fix.md +1 -1
- package/gsd-core/workflows/audit-milestone.md +4 -3
- package/gsd-core/workflows/audit-uat.md +1 -1
- package/gsd-core/workflows/autonomous.md +28 -18
- package/gsd-core/workflows/check-todos.md +6 -5
- package/gsd-core/workflows/cleanup.md +1 -1
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +20 -13
- package/gsd-core/workflows/code-review-fix.md +5 -4
- package/gsd-core/workflows/code-review.md +100 -91
- package/gsd-core/workflows/complete-milestone/detail/elaboration.md +4 -3
- package/gsd-core/workflows/complete-milestone.md +12 -7
- package/gsd-core/workflows/debug.md +30 -5
- package/gsd-core/workflows/diagnose-issues.md +3 -2
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
- package/gsd-core/workflows/discuss-phase.md +4 -3
- package/gsd-core/workflows/do.md +1 -1
- package/gsd-core/workflows/docs-update.md +4 -3
- package/gsd-core/workflows/edit-phase.md +4 -3
- package/gsd-core/workflows/eval-review.md +5 -3
- package/gsd-core/workflows/execute-phase/detail/elaboration.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +4 -2
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +15 -4
- package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +10 -7
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +3 -1
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/protected-branch.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/regression-gate.md +2 -0
- package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +187 -0
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +2 -3
- package/gsd-core/workflows/execute-phase.md +81 -171
- package/gsd-core/workflows/execute-plan.md +13 -19
- package/gsd-core/workflows/explore.md +2 -2
- package/gsd-core/workflows/extract-learnings.md +3 -2
- package/gsd-core/workflows/fast.md +1 -1
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +1 -1
- package/gsd-core/workflows/health.md +2 -1
- package/gsd-core/workflows/import.md +3 -2
- package/gsd-core/workflows/inbox.md +1 -1
- package/gsd-core/workflows/ingest-docs.md +1 -1
- package/gsd-core/workflows/insert-phase.md +4 -3
- package/gsd-core/workflows/list-seeds.md +1 -1
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +5 -3
- package/gsd-core/workflows/map-codebase.md +4 -3
- package/gsd-core/workflows/milestone-summary.md +3 -2
- package/gsd-core/workflows/mvp-phase.md +14 -14
- package/gsd-core/workflows/new-milestone.md +10 -10
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
- package/gsd-core/workflows/new-project.md +1 -1
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +1 -1
- package/gsd-core/workflows/pause-work.md +2 -2
- package/gsd-core/workflows/plan-phase/detail/elaboration.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/closed-phase-gate.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +1 -1
- package/gsd-core/workflows/plan-phase.md +27 -18
- package/gsd-core/workflows/plan-review-convergence.md +1 -1
- package/gsd-core/workflows/plant-seed.md +1 -1
- package/gsd-core/workflows/pr-branch.md +1 -1
- package/gsd-core/workflows/profile-user.md +1 -1
- package/gsd-core/workflows/progress.md +19 -49
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +4 -2
- package/gsd-core/workflows/quick/steps/quick-verification.md +4 -4
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +30 -11
- package/gsd-core/workflows/quick-batch/steps/batch-init.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/completion.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/merge-wave.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/planner-wave.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/research-phase.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/resume-mode.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/verification-wave.md +9 -3
- package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +1 -1
- package/gsd-core/workflows/quick-batch.md +15 -10
- package/gsd-core/workflows/quick.md +42 -31
- package/gsd-core/workflows/remove-phase.md +3 -2
- package/gsd-core/workflows/remove-workspace.md +1 -1
- package/gsd-core/workflows/resume-project.md +17 -12
- package/gsd-core/workflows/review.md +3 -2
- package/gsd-core/workflows/scan.md +3 -2
- package/gsd-core/workflows/secure-phase.md +11 -12
- package/gsd-core/workflows/settings-advanced.md +1 -1
- package/gsd-core/workflows/settings-integrations.md +1 -1
- package/gsd-core/workflows/settings.md +1 -1
- package/gsd-core/workflows/ship.md +12 -12
- package/gsd-core/workflows/sketch-wrap-up.md +1 -1
- package/gsd-core/workflows/sketch.md +1 -1
- package/gsd-core/workflows/smart-entry.md +1 -1
- package/gsd-core/workflows/spec-phase.md +1 -1
- package/gsd-core/workflows/spike-wrap-up.md +1 -1
- package/gsd-core/workflows/spike.md +1 -1
- package/gsd-core/workflows/stats.md +1 -1
- package/gsd-core/workflows/sync-skills.md +1 -1
- package/gsd-core/workflows/thread.md +2 -2
- package/gsd-core/workflows/transition.md +13 -23
- package/gsd-core/workflows/ui-phase.md +5 -4
- package/gsd-core/workflows/ui-review.md +4 -3
- package/gsd-core/workflows/ultraplan-phase.md +3 -2
- package/gsd-core/workflows/undo.md +1 -1
- package/gsd-core/workflows/validate-phase.md +10 -12
- package/gsd-core/workflows/verify-work/detail/elaboration.md +43 -3
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +1 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +5 -3
- package/gsd-core/workflows/verify-work.md +68 -59
- package/hooks/dist/gsd-agent-isolation-guard.js +8 -0
- package/hooks/dist/gsd-check-update-worker.js +8 -0
- package/hooks/dist/gsd-check-update.js +34 -20
- package/hooks/dist/gsd-context-monitor.js +45 -13
- package/hooks/dist/gsd-cursor-subagent-start.js +8 -0
- package/hooks/dist/gsd-secret-read-guard.js +263 -16
- package/hooks/dist/gsd-statusline.js +336 -29
- package/hooks/dist/gsd-update-banner.js +8 -0
- package/hooks/dist/gsd-windsurf-pre-write.js +11 -2
- package/hooks/dist/gsd-workflow-guard.js +5 -4
- package/hooks/dist/gsd-worktree-path-guard.js +6 -2
- package/hooks/dist/lib/cli-exit.js +12 -0
- package/hooks/dist/lib/git-probe.js +17 -1
- package/hooks/dist/lib/isolation-sentinel.js +2 -2
- package/hooks/gsd-agent-isolation-guard.js +8 -0
- package/hooks/gsd-check-update-worker.js +8 -0
- package/hooks/gsd-check-update.js +34 -20
- package/hooks/gsd-context-monitor.js +45 -13
- package/hooks/gsd-cursor-subagent-start.js +8 -0
- package/hooks/gsd-secret-read-guard.js +263 -16
- package/hooks/gsd-statusline.js +336 -29
- package/hooks/gsd-update-banner.js +8 -0
- package/hooks/gsd-windsurf-pre-write.js +11 -2
- package/hooks/gsd-workflow-guard.js +5 -4
- package/hooks/gsd-worktree-path-guard.js +6 -2
- package/hooks/hooks.json +5 -5
- package/hooks/lib/cli-exit.js +12 -0
- package/hooks/lib/git-probe.js +17 -1
- package/hooks/lib/isolation-sentinel.js +2 -2
- package/package.json +21 -4
- package/scripts/changeset/parse.cjs +52 -4
- package/scripts/ci-timeout-report.cjs +770 -4
- package/scripts/command-contract-helpers.cjs +12 -8
- package/scripts/docs-guard-registry.cjs +6 -0
- package/scripts/gen-capability-registry.cjs +7 -1
- package/scripts/gen-features.cjs +13 -8
- package/scripts/gen-hooks-cli-exit.cjs +12 -28
- package/scripts/gen-loop-host-contract.cjs +14 -2
- package/scripts/gen-platform-conformance-tier.cjs +187 -1
- package/scripts/gen-plugin-skills.cjs +87 -1
- package/scripts/gen-research-agents.cjs +24 -31
- package/scripts/gen-scripts-cli-exit.cjs +30 -3
- package/scripts/gen-test-timings.cjs +32 -7
- package/scripts/lib/cli-exit.cjs +12 -0
- package/scripts/lib/macos-conformance-tier.generated.cjs +24 -2
- package/scripts/lib/ndjson-reporter.cjs +28 -3
- package/scripts/lib/platform-conformance-tier.generated.cjs +44 -5
- package/scripts/lib/registration-ledger-preload.cjs +155 -0
- package/scripts/lib/vendor-bundle.cjs +59 -0
- package/scripts/lib/vendor-licenses/saxes-6.0.0.txt +64 -0
- package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +1 -1
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
- package/scripts/lint-completion-predicate-drift.cjs +18 -19
- package/scripts/lint-descriptions.cjs +7 -3
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +10 -0
- package/scripts/lint-eslint-glob-coverage.allowlist.json +20 -0
- package/scripts/lint-frontmatter-fence-drift.cjs +313 -0
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +122 -16
- package/scripts/lint-phase-enumeration-drift.cjs +12 -8
- package/scripts/lint-phase-id-drift.cjs +29 -0
- package/scripts/lint-planning-document-positive-control.cjs +329 -0
- package/scripts/lint-response-language-coverage.cjs +3 -0
- package/scripts/lint-skill-deps.cjs +7 -3
- package/scripts/lint-test-file-count.allowlist.json +11 -1
- package/scripts/lint-test-file-count.cjs +34 -1
- package/scripts/lint-vendored-deps.cjs +41 -5
- package/scripts/lint-workflow-shellcheck-baseline.json +10 -10
- package/scripts/mutation-matrix.cjs +53 -6
- package/scripts/release-tarball-smoke.cjs +14 -7
- package/scripts/require-issue-link-policy.cjs +6 -2
- package/scripts/sync-runtime-launcher.cjs +184 -2
- package/scripts/verify-npm-publish.cjs +76 -20
- package/skills/gsd-add-tests/SKILL.md +6 -1
- package/skills/gsd-ai-integration-phase/SKILL.md +6 -1
- package/skills/gsd-audit-fix/SKILL.md +5 -0
- package/skills/gsd-audit-milestone/SKILL.md +6 -1
- package/skills/gsd-autonomous/SKILL.md +5 -0
- package/skills/gsd-capture/SKILL.md +8 -4
- package/skills/gsd-code-review/SKILL.md +7 -2
- package/skills/gsd-complete-milestone/SKILL.md +4 -0
- package/skills/gsd-config/SKILL.md +8 -4
- package/skills/gsd-debug/SKILL.md +11 -7
- package/skills/gsd-discuss-phase/SKILL.md +7 -3
- package/skills/gsd-docs-update/SKILL.md +12 -7
- package/skills/gsd-eval-review/SKILL.md +6 -1
- package/skills/gsd-execute-phase/SKILL.md +12 -7
- package/skills/gsd-extract-learnings/SKILL.md +5 -0
- package/skills/gsd-fast/SKILL.md +4 -0
- package/skills/gsd-forensics/SKILL.md +5 -1
- package/skills/gsd-graphify/SKILL.md +10 -6
- package/skills/gsd-health/SKILL.md +5 -0
- package/skills/gsd-help/SKILL.md +7 -2
- package/skills/gsd-import/SKILL.md +7 -3
- package/skills/gsd-inbox/SKILL.md +5 -0
- package/skills/gsd-ingest-docs/SKILL.md +5 -1
- package/skills/gsd-manager/SKILL.md +6 -1
- package/skills/gsd-map-codebase/SKILL.md +7 -3
- package/skills/gsd-mempalace-capture/SKILL.md +5 -1
- package/skills/gsd-mempalace-recall/SKILL.md +5 -1
- package/skills/gsd-milestone-summary/SKILL.md +5 -1
- package/skills/gsd-mvp-phase/SKILL.md +8 -3
- package/skills/gsd-new-milestone/SKILL.md +6 -1
- package/skills/gsd-new-project/SKILL.md +5 -0
- package/skills/gsd-next/SKILL.md +6 -1
- package/skills/gsd-ns-context/SKILL.md +4 -0
- package/skills/gsd-ns-ideate/SKILL.md +4 -0
- package/skills/gsd-ns-manage/SKILL.md +4 -0
- package/skills/gsd-ns-project/SKILL.md +4 -0
- package/skills/gsd-ns-review/SKILL.md +4 -0
- package/skills/gsd-ns-workflow/SKILL.md +4 -0
- package/skills/gsd-onboard/SKILL.md +6 -1
- package/skills/gsd-pause-work/SKILL.md +5 -1
- package/skills/gsd-phase/SKILL.md +8 -4
- package/skills/gsd-plan-phase/SKILL.md +6 -1
- package/skills/gsd-plan-review-convergence/SKILL.md +5 -1
- package/skills/gsd-pr-branch/SKILL.md +4 -0
- package/skills/gsd-profile-user/SKILL.md +5 -1
- package/skills/gsd-progress/SKILL.md +6 -1
- package/skills/gsd-quick/SKILL.md +16 -10
- package/skills/gsd-quick-batch/SKILL.md +20 -8
- package/skills/gsd-review/SKILL.md +5 -1
- package/skills/gsd-review-backlog/SKILL.md +3 -2
- package/skills/gsd-secure-phase/SKILL.md +6 -1
- package/skills/gsd-ship/SKILL.md +5 -0
- package/skills/gsd-sketch/SKILL.md +7 -2
- package/skills/gsd-spec-phase/SKILL.md +5 -1
- package/skills/gsd-spike/SKILL.md +8 -3
- package/skills/gsd-surface/SKILL.md +5 -1
- package/skills/gsd-thread/SKILL.md +4 -0
- package/skills/gsd-ui-phase/SKILL.md +6 -1
- package/skills/gsd-ui-review/SKILL.md +6 -1
- package/skills/gsd-ultraplan-phase/SKILL.md +5 -1
- package/skills/gsd-undo/SKILL.md +5 -1
- package/skills/gsd-update/SKILL.md +6 -2
- package/skills/gsd-validate-phase/SKILL.md +6 -1
- package/skills/gsd-verify-work/SKILL.md +6 -1
- package/skills/gsd-workspace/SKILL.md +7 -3
- package/skills/gsd-workstreams/SKILL.md +6 -6
- package/vscode/package.json +1 -1
- package/gsd-core/workflows/execute-phase/steps/stale-reverification.md +0 -24
|
@@ -46,14 +46,19 @@ const planDocument = require("./plan-document.cjs");
|
|
|
46
46
|
const state_document_cjs_1 = require("./state-document.cjs");
|
|
47
47
|
const runtime_slash_cjs_1 = require("./runtime-slash.cjs");
|
|
48
48
|
const host_runtime_detection_cjs_1 = require("./host-runtime-detection.cjs");
|
|
49
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports -- commands.cjs is an export= CommonJS module
|
|
50
|
-
const commandsMod = require("./commands.cjs");
|
|
51
49
|
const security_cjs_1 = require("./security.cjs");
|
|
52
50
|
const runtime_homes_cjs_1 = require("./runtime-homes.cjs");
|
|
53
51
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- frontmatter.cjs is an export= CommonJS module
|
|
54
52
|
const frontmatterMod = require("./frontmatter.cjs");
|
|
55
53
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- verification.cjs is an export= CommonJS module
|
|
56
54
|
const verificationMod = require("./verification.cjs");
|
|
55
|
+
// #5060: Phase Status Module — the single owner of "what state is phase P
|
|
56
|
+
// in?" (ADR-5057 §1/§2). Replaces this file's own determinePhaseStatus/
|
|
57
|
+
// projectCompletionStatus derivations, and cmdInitMilestoneOp's
|
|
58
|
+
// summary-count-only completion check (the former listPhaseSummaryFiles
|
|
59
|
+
// helper, since removed). listPhasePlanFiles (below) is unrelated — it backs
|
|
60
|
+
// only the STATE.md disk-plan-count validation, not a completion verdict.
|
|
61
|
+
const phase_status_cjs_1 = require("./phase-status.cjs");
|
|
57
62
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- uat-predicate.cjs is an export= CommonJS module
|
|
58
63
|
const uatPredicateMod = require("./uat-predicate.cjs");
|
|
59
64
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- agent-install-check.cjs is an export= CommonJS module
|
|
@@ -91,10 +96,9 @@ const { getRoadmapPhaseInternal, getMilestoneInfo, stripShippedMilestones, extra
|
|
|
91
96
|
const { pathExistsInternal, generateSlugInternal, toPosixPath } = coreUtils;
|
|
92
97
|
const { comparePhaseNum, normalizePhaseName, stripProjectCodePrefix, PHASE_NUMBER_TOKEN_SOURCE, PHASE_DEP_REF_SOURCE, isForeignPrefixedPhaseQuery, isSentinelPhaseId, extractPhaseToken, scopeToPhase, renderPhaseBranchName, parsePhaseId, renderPhaseId, phaseHeadingPrefixSrcFor, PHASE_HEADING_BASELINE, buildPhaseHeadingScanRegex, } = phaseId;
|
|
93
98
|
const { pruneOrphanedWorktrees } = worktreeSafety;
|
|
94
|
-
const { planningPaths, planningDir, planningRoot, todosDir, listAvailableWorkstreams, peekActiveWorkstream, resolveEnvWorkstream, diagnoseUnresolvedActiveWorkstream, describeUnresolvedWorkstreamReason, findContextMdIn, resolvePhaseIdConvention, } = planningWorkspace;
|
|
95
|
-
const {
|
|
96
|
-
const {
|
|
97
|
-
const { isPhaseComplete, resolveVerificationFile, resolveUatFile } = verificationMod;
|
|
99
|
+
const { planningPaths, planningDir, planningRoot, todosDir, listAvailableWorkstreams, peekActiveWorkstream, resolveEnvWorkstream, diagnoseUnresolvedActiveWorkstream, describeUnresolvedWorkstreamReason, findContextMdIn, resolvePhaseIdConvention, worktreesOptedOut, } = planningWorkspace;
|
|
100
|
+
const { extractFrontmatter, frontmatterBlock } = frontmatterMod;
|
|
101
|
+
const { isPhaseComplete, resolveVerificationFile, resolveUatFile, VERIFICATION_STATUS, VerificationStatusError } = verificationMod;
|
|
98
102
|
const { evaluateUatPassed } = uatPredicateMod;
|
|
99
103
|
const { resolveLoopHooks } = loopResolverMod;
|
|
100
104
|
const { loadRegistry } = capabilityLoaderMod;
|
|
@@ -153,6 +157,24 @@ function slugifyPhaseName(phaseName) {
|
|
|
153
157
|
// the same reported phase_slug.
|
|
154
158
|
return phaseName ? coreUtils.generateSlugInternal(phaseName, null) : null;
|
|
155
159
|
}
|
|
160
|
+
/**
|
|
161
|
+
* #4854: the one place that decides which name an `init` verb emits as
|
|
162
|
+
* `phase_name`. When a phase directory exists, `searchPhaseInDir` derives
|
|
163
|
+
* `phaseInfo.phase_name` from the directory-name remainder — already slugified
|
|
164
|
+
* (`phase.add` writes `${num}-${slug}` dirs), so it comes out byte-identical to
|
|
165
|
+
* `phase_slug`. The ROADMAP carries the curated display name
|
|
166
|
+
* (`### Phase N: <Name>`), so it wins; the disk-derived name is the fallback
|
|
167
|
+
* for a phase the ROADMAP does not describe, then `null`. #3171 fixed this
|
|
168
|
+
* inline for `init execute-phase` only; plan-phase (whose `phase_name` reaches
|
|
169
|
+
* STATE.md through `state planned-phase --name`), verify-work, code-review,
|
|
170
|
+
* discuss-phase-assumptions and phase-op read the raw disk value. `phase_slug`
|
|
171
|
+
* is deliberately not routed through here — it stays disk-derived.
|
|
172
|
+
*/
|
|
173
|
+
function resolvePhaseDisplayName(phaseInfo, roadmapPhase) {
|
|
174
|
+
return roadmapPhase?.['phase_name']
|
|
175
|
+
|| phaseInfo?.['phase_name']
|
|
176
|
+
|| null;
|
|
177
|
+
}
|
|
156
178
|
/**
|
|
157
179
|
* #2994 (review finding, DEFECT.GENERATIVE-FIX): shared archived/not-found
|
|
158
180
|
* fallback applied identically by `cmdInitExecutePhase`, `cmdInitPlanPhase`,
|
|
@@ -160,10 +182,11 @@ function slugifyPhaseName(phaseName) {
|
|
|
160
182
|
* `cmdInitDiscussPhaseAssumptions` — 6 call sites previously reproducing the
|
|
161
183
|
* exact same two-branch control flow verbatim (only the synthetic
|
|
162
184
|
* replacement object's field set differs per caller, supplied here via
|
|
163
|
-
* `buildFallback`). `cmdInitPhaseOp`
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
185
|
+
* `buildFallback`). `cmdInitPhaseOp` does not use this helper (its own fallback
|
|
186
|
+
* object differs by one field, `has_reviews` absent, so it is not a
|
|
187
|
+
* byte-identical copy), but since #4854 it resolves `roadmapPhase` once up
|
|
188
|
+
* front like the others, so `resolvePhaseDisplayName` sees it in the ordinary
|
|
189
|
+
* case too.
|
|
167
190
|
*
|
|
168
191
|
* Behavior-preserving by construction: every original call site either (a)
|
|
169
192
|
* unconditionally computed `roadmapPhase` once up front and then applied
|
|
@@ -186,20 +209,10 @@ function applyRoadmapFallback(phaseInfo, roadmapPhase, buildFallback) {
|
|
|
186
209
|
}
|
|
187
210
|
return phaseInfo;
|
|
188
211
|
}
|
|
189
|
-
function listPhaseSummaryFiles(phaseDir) {
|
|
190
|
-
return scanPhasePlans(phaseDir)['summaryFiles'];
|
|
191
|
-
}
|
|
192
212
|
function listPhasePlanFiles(phaseDir) {
|
|
193
213
|
return scanPhasePlans(phaseDir)['planFiles'];
|
|
194
214
|
}
|
|
195
|
-
function
|
|
196
|
-
if (phaseComplete)
|
|
197
|
-
return 'complete';
|
|
198
|
-
if (implementationComplete)
|
|
199
|
-
return 'executed';
|
|
200
|
-
return 'incomplete';
|
|
201
|
-
}
|
|
202
|
-
function buildPhaseCompletionProjection(cwd, phaseNumber, phaseDir, planCount, summaryCount, slashRuntime) {
|
|
215
|
+
function buildPhaseCompletionProjection(cwd, phaseNumber, phaseDir, planCount, summaryCount, slashRuntime, convention) {
|
|
203
216
|
// ADR-3180 §7.4 (issue #3186) / DO-NOT-MIGRATE exemption
|
|
204
217
|
// (scripts/lint-completion-predicate-drift.cjs FUNCTION_SCOPED_EXEMPTIONS,
|
|
205
218
|
// declared deviation): `implementation_complete` answers "are the plans
|
|
@@ -219,20 +232,35 @@ function buildPhaseCompletionProjection(cwd, phaseNumber, phaseDir, planCount, s
|
|
|
219
232
|
// #2617: the router still owns both the message content and the runtime
|
|
220
233
|
// projection; init passes the phase number it already knows (its phaseDir
|
|
221
234
|
// is unresolved in some branches, where the router could not derive one).
|
|
222
|
-
const completionResult = isPhaseComplete(phaseFullDir, { runtime: slashRuntime, phaseNumber });
|
|
235
|
+
const completionResult = isPhaseComplete(phaseFullDir, { runtime: slashRuntime, phaseNumber, convention });
|
|
236
|
+
// #5118: the owner carried an out-of-set report status in its result
|
|
237
|
+
// (`statusError`, `verification.status: null`); an init bundle is never
|
|
238
|
+
// assembled over a report the owner refused — the carried error is raised
|
|
239
|
+
// here and every `init *` surface built on this projection fails with the
|
|
240
|
+
// error's own reason (the CLI entry seam), printing nothing.
|
|
241
|
+
if (completionResult.value.statusError)
|
|
242
|
+
throw completionResult.value.statusError;
|
|
223
243
|
const verificationStatus = completionResult.value.verification;
|
|
224
244
|
const projectedVerificationStatus = verificationStatus.status;
|
|
225
245
|
const projectedVerificationAction = verificationStatus.next_action;
|
|
226
|
-
const verificationPassed = projectedVerificationStatus ===
|
|
246
|
+
const verificationPassed = projectedVerificationStatus === VERIFICATION_STATUS.PASSED;
|
|
227
247
|
const phaseComplete = completionResult.value.complete;
|
|
228
248
|
return {
|
|
229
249
|
implementation_complete: implementationComplete,
|
|
230
250
|
verification_status: projectedVerificationStatus,
|
|
231
251
|
verification_passed: verificationPassed,
|
|
232
252
|
phase_complete: phaseComplete,
|
|
233
|
-
|
|
253
|
+
// #5060: Phase Status Module — the single owner of "what state is phase P
|
|
254
|
+
// in?" (ADR-5057 §1/§2).
|
|
255
|
+
completion_status: (0, phase_status_cjs_1.toCompletionStatus)((0, phase_status_cjs_1.phaseStatusFromFacts)({
|
|
256
|
+
planCount,
|
|
257
|
+
summaryCount,
|
|
258
|
+
complete: phaseComplete,
|
|
259
|
+
verificationStatus: projectedVerificationStatus,
|
|
260
|
+
})),
|
|
234
261
|
verification_next_action: projectedVerificationAction,
|
|
235
262
|
verification_next_command: verificationStatus.next_command,
|
|
263
|
+
verification_route: verificationStatus.route,
|
|
236
264
|
// #3057 B3: readVerificationStatus's result carries this flag when its
|
|
237
265
|
// internal staleness check could not run to completion.
|
|
238
266
|
verification_stale_check_indeterminate: 'staleCheckIndeterminate' in verificationStatus
|
|
@@ -479,7 +507,8 @@ function detectHasPriorPhases(cwd, phaseInfo) {
|
|
|
479
507
|
* `false` — strict `=== true`, never coerced, mirrors `detectHasPriorPhases`'s
|
|
480
508
|
* degrade-to-false discipline. `keyPath` is always a fixed literal supplied
|
|
481
509
|
* by this module, never attacker/user input, so a plain bracket traversal
|
|
482
|
-
* carries no prototype hazard here.
|
|
510
|
+
* carries no prototype hazard here. Only for keys whose default is OFF — a
|
|
511
|
+
* default-ON key read here silently inverts its unset value (#4977).
|
|
483
512
|
*/
|
|
484
513
|
function readConfigJsonBoolean(cwd, keyPath) {
|
|
485
514
|
try {
|
|
@@ -727,7 +756,13 @@ function buildSectionManifestField(cwd, phaseInfo, options, workflow, overrides
|
|
|
727
756
|
flags,
|
|
728
757
|
phaseNumber,
|
|
729
758
|
hasPriorPhases: detectHasPriorPhases(cwd, phaseInfo),
|
|
730
|
-
|
|
759
|
+
// #4977: `workflow.use_worktrees` defaults ON, so this fact must come from
|
|
760
|
+
// the #3972 owner `query dispatch-isolation` and the isolation guard
|
|
761
|
+
// already share — not `readConfigJsonBoolean`, whose absent ⇒ false
|
|
762
|
+
// polarity (right for the opt-in keys around it) excluded the quick
|
|
763
|
+
// pre-dispatch plan commit while the executor was still dispatched
|
|
764
|
+
// isolated. The ladder also brings root→workstream inheritance along.
|
|
765
|
+
worktreesEnabled: !worktreesOptedOut(cwd),
|
|
731
766
|
phaseMvpMode: detectPhaseMvpMode(cwd, phaseNumber),
|
|
732
767
|
needsCodebaseMap: overrides.needsCodebaseMap,
|
|
733
768
|
chunkedMode,
|
|
@@ -908,7 +943,7 @@ function cmdInitExecutePhase(cwd, phase, raw, options = {}) {
|
|
|
908
943
|
// the human-curated display name (`### Phase N: <Name>`); prefer it,
|
|
909
944
|
// matching the no-disk fallback above. phase_slug stays disk-derived — it
|
|
910
945
|
// correctly feeds branch-name construction below and is unchanged here.
|
|
911
|
-
phase_name: (roadmapPhase
|
|
946
|
+
phase_name: resolvePhaseDisplayName(phaseInfo, roadmapPhase),
|
|
912
947
|
phase_slug: phaseInfo?.['phase_slug'] || null,
|
|
913
948
|
phase_req_ids,
|
|
914
949
|
plans: phaseInfo?.['plans'] || [],
|
|
@@ -1027,7 +1062,7 @@ function cmdInitPlanPhase(cwd, phase, raw, options = {}) {
|
|
|
1027
1062
|
const phase_req_ids = reqExtracted && reqExtracted !== 'TBD' ? reqExtracted : null;
|
|
1028
1063
|
const phaseDirPlan = phaseInfo?.['directory'] || null;
|
|
1029
1064
|
const phaseNumberPlan = phaseInfo?.['phase_number'] || null;
|
|
1030
|
-
const phaseNamePlan = phaseInfo
|
|
1065
|
+
const phaseNamePlan = resolvePhaseDisplayName(phaseInfo, roadmapPhase);
|
|
1031
1066
|
const rawProjectCodePlan = config.project_code || '';
|
|
1032
1067
|
let expectedPhaseDirPlan = null;
|
|
1033
1068
|
if (!phaseDirPlan && phaseNumberPlan && phaseNamePlan) {
|
|
@@ -1075,8 +1110,10 @@ function cmdInitPlanPhase(cwd, phase, raw, options = {}) {
|
|
|
1075
1110
|
phase_slug: phaseInfo?.['phase_slug'] || null,
|
|
1076
1111
|
padded_phase: phaseNumberPlan ? normalizePhaseName(phaseNumberPlan) : null,
|
|
1077
1112
|
phase_req_ids,
|
|
1113
|
+
// #5060: Phase Status Module — the single owner of "what state is phase P
|
|
1114
|
+
// in?" (ADR-5057 §1/§2).
|
|
1078
1115
|
phase_status: phaseDirPlan
|
|
1079
|
-
?
|
|
1116
|
+
? (0, phase_status_cjs_1.toDisplayLabel)((0, phase_status_cjs_1.phaseStatus)(node_path_1.default.join(cwd, phaseDirPlan), { convention: resolvePhaseIdConvention(cwd) }).value.status, { pendingWord: 'Pending' })
|
|
1080
1117
|
: 'Pending',
|
|
1081
1118
|
has_research: phaseInfo?.['has_research'] || false,
|
|
1082
1119
|
has_context: phaseInfo?.['has_context'] || false,
|
|
@@ -1273,12 +1310,15 @@ function buildInitCompletenessFields(cwd) {
|
|
|
1273
1310
|
}
|
|
1274
1311
|
function cmdInitNewProject(cwd, raw, options = {}) {
|
|
1275
1312
|
const config = loadConfig(cwd);
|
|
1276
|
-
|
|
1277
|
-
|
|
1313
|
+
// #4976: probe the GSD-owned store the config loader resolves
|
|
1314
|
+
// (`GSD_HOME || homedir()`), so these flags agree with config-new-project's
|
|
1315
|
+
// key probes in the same /gsd-new-project run.
|
|
1316
|
+
const gsdHome = process.env['GSD_HOME'] || node_os_1.default.homedir();
|
|
1317
|
+
const braveKeyFile = node_path_1.default.join(gsdHome, '.gsd', 'brave_api_key');
|
|
1278
1318
|
const hasBraveSearch = !!(process.env['BRAVE_API_KEY'] || node_fs_1.default.existsSync(braveKeyFile));
|
|
1279
|
-
const firecrawlKeyFile = node_path_1.default.join(
|
|
1319
|
+
const firecrawlKeyFile = node_path_1.default.join(gsdHome, '.gsd', 'firecrawl_api_key');
|
|
1280
1320
|
const hasFirecrawl = !!(process.env['FIRECRAWL_API_KEY'] || node_fs_1.default.existsSync(firecrawlKeyFile));
|
|
1281
|
-
const exaKeyFile = node_path_1.default.join(
|
|
1321
|
+
const exaKeyFile = node_path_1.default.join(gsdHome, '.gsd', 'exa_api_key');
|
|
1282
1322
|
const hasExaSearch = !!(process.env['EXA_API_KEY'] || node_fs_1.default.existsSync(exaKeyFile));
|
|
1283
1323
|
const hasCode = hasCodeFilesInternal(cwd);
|
|
1284
1324
|
const hasPackageFile = hasPackageFileInternal(cwd);
|
|
@@ -1638,9 +1678,21 @@ function cmdInitVerifyWork(cwd, phase, raw) {
|
|
|
1638
1678
|
};
|
|
1639
1679
|
});
|
|
1640
1680
|
const phaseDir = phaseInfo?.['directory'] || null;
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1681
|
+
// #5060: Phase Status Module — matched counts from the §7.5 owner
|
|
1682
|
+
// (scanPhasePlans via phaseStatus), not phaseInfo's raw plans/summaries
|
|
1683
|
+
// arrays, so this projection's counts agree with buildPhaseCompletionProjection's
|
|
1684
|
+
// own isPhaseComplete call below (see the convention thread there).
|
|
1685
|
+
const verifyWorkConvention = resolvePhaseIdConvention(cwd);
|
|
1686
|
+
const verifyWorkPs = phaseDir
|
|
1687
|
+
? (0, phase_status_cjs_1.phaseStatus)(node_path_1.default.join(cwd, phaseDir), { convention: verifyWorkConvention })
|
|
1688
|
+
: null;
|
|
1689
|
+
const planCount = verifyWorkPs
|
|
1690
|
+
? verifyWorkPs.value.planCount
|
|
1691
|
+
: phaseInfo?.['plans']?.length || 0;
|
|
1692
|
+
const summaryCount = verifyWorkPs
|
|
1693
|
+
? verifyWorkPs.value.summaryCount
|
|
1694
|
+
: phaseInfo?.['summaries']?.length || 0;
|
|
1695
|
+
const completion = buildPhaseCompletionProjection(cwd, phaseInfo?.['phase_number'] || phase, phaseDir, planCount, summaryCount, _slashRuntime, verifyWorkConvention);
|
|
1644
1696
|
const uatReport = phaseDir
|
|
1645
1697
|
? evaluateUatPassed(node_path_1.default.join(cwd, phaseDir), {
|
|
1646
1698
|
policy: { requireVerification: true },
|
|
@@ -1656,7 +1708,7 @@ function cmdInitVerifyWork(cwd, phase, raw) {
|
|
|
1656
1708
|
// itself stays relative — evaluateUatPassed above still joins it against cwd.
|
|
1657
1709
|
phase_dir: phaseDir ? toPosixPath(node_path_1.default.join(cwd, phaseDir)) : null,
|
|
1658
1710
|
phase_number: phaseInfo?.['phase_number'] || null,
|
|
1659
|
-
phase_name: phaseInfo
|
|
1711
|
+
phase_name: resolvePhaseDisplayName(phaseInfo, roadmapPhase),
|
|
1660
1712
|
// #2376: verify-work.md's plan_gap_closure step reads these instead of
|
|
1661
1713
|
// hardcoding '.planning/STATE.md' / '.planning/ROADMAP.md' literals.
|
|
1662
1714
|
state_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'STATE.md')),
|
|
@@ -1728,7 +1780,7 @@ function cmdInitCodeReview(cwd, phase, raw, options = {}) {
|
|
|
1728
1780
|
});
|
|
1729
1781
|
const phaseDir = phaseInfo?.['directory'] || null;
|
|
1730
1782
|
const phaseNumber = phaseInfo?.['phase_number'] || null;
|
|
1731
|
-
const phaseName = phaseInfo
|
|
1783
|
+
const phaseName = resolvePhaseDisplayName(phaseInfo, roadmapPhase);
|
|
1732
1784
|
const fallow = detectFallowConfig(cwd);
|
|
1733
1785
|
const result = {
|
|
1734
1786
|
commit_docs: config.commit_docs,
|
|
@@ -1857,7 +1909,7 @@ function cmdInitDiscussPhaseAssumptions(cwd, phase, raw, options = {}) {
|
|
|
1857
1909
|
});
|
|
1858
1910
|
const phaseDir = phaseInfo?.['directory'] || null;
|
|
1859
1911
|
const phaseNumber = phaseInfo?.['phase_number'] || null;
|
|
1860
|
-
const phaseName = phaseInfo
|
|
1912
|
+
const phaseName = resolvePhaseDisplayName(phaseInfo, roadmapPhase);
|
|
1861
1913
|
// #2994: mirrors discuss-phase-assumptions.md's own auto_advance step
|
|
1862
1914
|
// resolver — `--auto` flag OR the consolidated `check auto-mode --pick
|
|
1863
1915
|
// active` fact (workflow._auto_chain_active OR workflow.auto_advance).
|
|
@@ -1909,8 +1961,10 @@ function cmdInitPhaseOp(cwd, phase, raw) {
|
|
|
1909
1961
|
output(withProjectRoot(cwd, result), raw);
|
|
1910
1962
|
return;
|
|
1911
1963
|
}
|
|
1964
|
+
// #4854: resolved once, up front (a pure read — guardedGetRoadmapPhase has no side effects),
|
|
1965
|
+
// so the ordinary case (phase dir on disk, not archived) also sees the ROADMAP display name.
|
|
1966
|
+
const roadmapPhase = guardedGetRoadmapPhase(cwd, phase, config.project_code);
|
|
1912
1967
|
if (phaseInfo?.['archived']) {
|
|
1913
|
-
const roadmapPhase = guardedGetRoadmapPhase(cwd, phase, config.project_code);
|
|
1914
1968
|
if (roadmapPhase?.['found']) {
|
|
1915
1969
|
const phaseName = roadmapPhase['phase_name'];
|
|
1916
1970
|
phaseInfo = {
|
|
@@ -1933,7 +1987,6 @@ function cmdInitPhaseOp(cwd, phase, raw) {
|
|
|
1933
1987
|
}
|
|
1934
1988
|
}
|
|
1935
1989
|
if (!phaseInfo) {
|
|
1936
|
-
const roadmapPhase = guardedGetRoadmapPhase(cwd, phase, config.project_code);
|
|
1937
1990
|
if (roadmapPhase?.['found']) {
|
|
1938
1991
|
const phaseName = roadmapPhase['phase_name'];
|
|
1939
1992
|
phaseInfo = {
|
|
@@ -1957,7 +2010,7 @@ function cmdInitPhaseOp(cwd, phase, raw) {
|
|
|
1957
2010
|
}
|
|
1958
2011
|
const phaseDir = phaseInfo?.['directory'] || null;
|
|
1959
2012
|
const phaseNumber = phaseInfo?.['phase_number'] || null;
|
|
1960
|
-
const phaseName = phaseInfo
|
|
2013
|
+
const phaseName = resolvePhaseDisplayName(phaseInfo, roadmapPhase);
|
|
1961
2014
|
const rawProjectCode = config.project_code || '';
|
|
1962
2015
|
let expectedPhaseDir = null;
|
|
1963
2016
|
if (!phaseDir && phaseNumber && phaseName) {
|
|
@@ -2314,6 +2367,12 @@ function cmdInitTodos(cwd, area, raw) {
|
|
|
2314
2367
|
function cmdInitMilestoneOp(cwd, raw) {
|
|
2315
2368
|
const config = loadConfig(cwd);
|
|
2316
2369
|
const milestone = milestoneRecord(cwd);
|
|
2370
|
+
// #5060: Phase Status Module — the single owner of "what state is phase P
|
|
2371
|
+
// in?" (ADR-5057 §1/§2). A phase counts as completed only when the ladder
|
|
2372
|
+
// itself says COMPLETE, not "has any *-SUMMARY.md" (a counts-only verdict
|
|
2373
|
+
// that bypasses isPhaseComplete and disagrees with every other completion
|
|
2374
|
+
// consumer on a stale `passed` report).
|
|
2375
|
+
const milestoneOpConvention = resolvePhaseIdConvention(cwd);
|
|
2317
2376
|
let phaseCount = 0;
|
|
2318
2377
|
let completedPhases = 0;
|
|
2319
2378
|
const phasesDir = node_path_1.default.join(planningDir(cwd), 'phases');
|
|
@@ -2325,7 +2384,7 @@ function cmdInitMilestoneOp(cwd, raw) {
|
|
|
2325
2384
|
// #1729: `(?:\s*\([^)\n]{0,200}\))?` tolerates a pre-colon ( ) tag, owned by
|
|
2326
2385
|
// buildPhaseHeadingScanRegex (phase-id.cts) so this scan also recognizes
|
|
2327
2386
|
// bracket-convention headings instead of hand-rolling a literal `Phase\s+`.
|
|
2328
|
-
const { regex: phasePattern, phaseNumGroup } = buildPhaseHeadingScanRegex(PHASE_HEADING_BASELINE.ANY_BRACKET,
|
|
2387
|
+
const { regex: phasePattern, phaseNumGroup } = buildPhaseHeadingScanRegex(PHASE_HEADING_BASELINE.ANY_BRACKET, milestoneOpConvention);
|
|
2329
2388
|
let m;
|
|
2330
2389
|
while ((m = phasePattern.exec(currentSection)) !== null) {
|
|
2331
2390
|
// #3185: canonical sentinel predicate (SENTINEL_RANGES [0,999]) — this was a local 999-only literal that admitted Phase 0.
|
|
@@ -2366,8 +2425,8 @@ function cmdInitMilestoneOp(cwd, raw) {
|
|
|
2366
2425
|
if (!dirName)
|
|
2367
2426
|
continue;
|
|
2368
2427
|
try {
|
|
2369
|
-
const
|
|
2370
|
-
if (
|
|
2428
|
+
const isComplete = (0, phase_status_cjs_1.phaseStatus)(node_path_1.default.join(phasesDir, dirName), { convention: milestoneOpConvention }).value.status === phase_status_cjs_1.PHASE_STATUS.COMPLETE;
|
|
2429
|
+
if (isComplete)
|
|
2371
2430
|
completedPhases++;
|
|
2372
2431
|
}
|
|
2373
2432
|
catch {
|
|
@@ -2386,8 +2445,8 @@ function cmdInitMilestoneOp(cwd, raw) {
|
|
|
2386
2445
|
phaseCount = dirs.length;
|
|
2387
2446
|
for (const dir of dirs) {
|
|
2388
2447
|
try {
|
|
2389
|
-
const
|
|
2390
|
-
if (
|
|
2448
|
+
const isComplete = (0, phase_status_cjs_1.phaseStatus)(node_path_1.default.join(phasesDir, dir), { convention: milestoneOpConvention }).value.status === phase_status_cjs_1.PHASE_STATUS.COMPLETE;
|
|
2449
|
+
if (isComplete)
|
|
2391
2450
|
completedPhases++;
|
|
2392
2451
|
}
|
|
2393
2452
|
catch {
|
|
@@ -2493,11 +2552,23 @@ function cmdInitManager(cwd, raw) {
|
|
|
2493
2552
|
// getMilestonePhaseFilter window check (which also never excluded
|
|
2494
2553
|
// sentinels, unlike the owner).
|
|
2495
2554
|
const _checkboxStates = new Map();
|
|
2496
|
-
|
|
2555
|
+
// #4982: anchored (`^`, `m`) so the phase label must be the FIRST thing
|
|
2556
|
+
// after the checkbox (tolerating only an optional `**` bold marker) —
|
|
2557
|
+
// the prior unanchored `\s*.*` let the greedy `.*` bind to the LAST
|
|
2558
|
+
// "Phase N" mentioned anywhere in the line's prose instead of the line's
|
|
2559
|
+
// own phase. First-match-wins (`if (!_checkboxStates.has(...))` below)
|
|
2560
|
+
// additionally guards against a later anchored line (e.g. a per-plan
|
|
2561
|
+
// sub-entry self-titled "Phase N ...") overwriting an already-recorded
|
|
2562
|
+
// phase's own (first) checkbox — anchoring alone does not fully close
|
|
2563
|
+
// that "last-match-wins" composition defect.
|
|
2564
|
+
const _cbPattern = new RegExp(`^[ \\t]*-[ \\t]*\\[(x| )\\][ \\t]*(?:\\*\\*)?${phaseHeadingPrefix}(${PHASE_NUMBER_TOKEN_SOURCE})[:\\s]`, 'gim');
|
|
2497
2565
|
let _cbMatch;
|
|
2498
2566
|
while ((_cbMatch = _cbPattern.exec(content)) !== null) {
|
|
2499
2567
|
const phaseGroup = capturesBracketId ? 3 : 2;
|
|
2500
|
-
|
|
2568
|
+
const _cbKey = _cbMatch[phaseGroup];
|
|
2569
|
+
if (!_checkboxStates.has(_cbKey)) {
|
|
2570
|
+
_checkboxStates.set(_cbKey, _cbMatch[1].toLowerCase() === 'x');
|
|
2571
|
+
}
|
|
2501
2572
|
}
|
|
2502
2573
|
// #1729: `(?:\s*\([^)\n]{0,200}\))?` tolerates a pre-colon ( ) tag (literal mirror of OPTIONAL_PHASE_TAG_SOURCE).
|
|
2503
2574
|
const phasePattern = new RegExp(`#{2,4}\\s*${phaseHeadingPrefix}(${PHASE_NUMBER_TOKEN_SOURCE})(?:\\s*\\([^)\\n]{0,200}\\))?\\s*:\\s*([^\\n]+)`, 'gi');
|
|
@@ -2529,7 +2600,7 @@ function cmdInitManager(cwd, raw) {
|
|
|
2529
2600
|
const goal = roadmapParser.extractPhaseFieldMultiline(section, 'Goal');
|
|
2530
2601
|
const dependsMatch = section.match(/\*\*Depends on(?::\*\*|\*\*:)\s*([^\n]+)/i);
|
|
2531
2602
|
const depends_on = dependsMatch ? dependsMatch[1].trim() : null;
|
|
2532
|
-
let diskStatus =
|
|
2603
|
+
let diskStatus = phase_status_cjs_1.DISK_STATUS.NO_DIRECTORY;
|
|
2533
2604
|
let planCount = 0;
|
|
2534
2605
|
let summaryCount = 0;
|
|
2535
2606
|
let hasContext = false;
|
|
@@ -2539,7 +2610,7 @@ function cmdInitManager(cwd, raw) {
|
|
|
2539
2610
|
// #4014 (epic #3473 B4-unreadable): default COMPLETE — no directory at
|
|
2540
2611
|
// all (dirMatch not found) is a genuine, not-unreadable answer.
|
|
2541
2612
|
let contextScope = SCOPE.COMPLETE;
|
|
2542
|
-
let completion = buildPhaseCompletionProjection(cwd, phaseNum, null, planCount, summaryCount, _slashRuntime);
|
|
2613
|
+
let completion = buildPhaseCompletionProjection(cwd, phaseNum, null, planCount, summaryCount, _slashRuntime, phaseIdConvention);
|
|
2543
2614
|
try {
|
|
2544
2615
|
// #4801: resolve through the canonical locator instead of a private
|
|
2545
2616
|
// current-milestone-only scan. findPhaseInternal searches the live
|
|
@@ -2570,8 +2641,11 @@ function cmdInitManager(cwd, raw) {
|
|
|
2570
2641
|
// only, the failure control-flow is untouched.
|
|
2571
2642
|
contextScope = findContextMdIn(fullDir).scope;
|
|
2572
2643
|
const phaseFiles = node_fs_1.default.readdirSync(fullDir);
|
|
2573
|
-
|
|
2574
|
-
|
|
2644
|
+
// #5060: Phase Status Module — the single owner of "what state is
|
|
2645
|
+
// phase P in?" (ADR-5057 §1/§2).
|
|
2646
|
+
const ps = (0, phase_status_cjs_1.phaseStatus)(fullDir, { convention: phaseIdConvention });
|
|
2647
|
+
planCount = ps.value.planCount;
|
|
2648
|
+
summaryCount = ps.value.summaryCount;
|
|
2575
2649
|
// #3511-class: scope the raw listing to THIS phase's own artifacts
|
|
2576
2650
|
// before the hasContext/hasResearch predicates run, so a stray
|
|
2577
2651
|
// cross-phase `-CONTEXT.md`/`-RESEARCH.md` sitting in this directory
|
|
@@ -2579,21 +2653,8 @@ function cmdInitManager(cwd, raw) {
|
|
|
2579
2653
|
const scopedFiles = scopeToPhase(phaseFiles, dirMatch);
|
|
2580
2654
|
hasContext = findContextMdIn(scopedFiles) !== null;
|
|
2581
2655
|
hasResearch = scopedFiles.some((f) => f.endsWith('-RESEARCH.md') || f === 'RESEARCH.md');
|
|
2582
|
-
completion = buildPhaseCompletionProjection(cwd, phaseNum, phaseDirRel, planCount, summaryCount, _slashRuntime);
|
|
2583
|
-
|
|
2584
|
-
diskStatus = 'complete';
|
|
2585
|
-
else if (completion.implementation_complete)
|
|
2586
|
-
diskStatus = 'executed';
|
|
2587
|
-
else if (summaryCount > 0)
|
|
2588
|
-
diskStatus = 'partial';
|
|
2589
|
-
else if (planCount > 0)
|
|
2590
|
-
diskStatus = 'planned';
|
|
2591
|
-
else if (hasResearch)
|
|
2592
|
-
diskStatus = 'researched';
|
|
2593
|
-
else if (hasContext)
|
|
2594
|
-
diskStatus = 'discussed';
|
|
2595
|
-
else
|
|
2596
|
-
diskStatus = 'empty';
|
|
2656
|
+
completion = buildPhaseCompletionProjection(cwd, phaseNum, phaseDirRel, planCount, summaryCount, _slashRuntime, phaseIdConvention);
|
|
2657
|
+
diskStatus = (0, phase_status_cjs_1.toDiskStatus)(ps.value.status, { hasResearch, hasContext });
|
|
2597
2658
|
const nowMs = clock_cjs_1.realClock.now();
|
|
2598
2659
|
let newestMtime = 0;
|
|
2599
2660
|
for (const f of phaseFiles) {
|
|
@@ -2751,7 +2812,7 @@ function cmdInitManager(cwd, raw) {
|
|
|
2751
2812
|
}
|
|
2752
2813
|
for (const phase of phases) {
|
|
2753
2814
|
phase['is_next_to_discuss'] =
|
|
2754
|
-
(phase['disk_status'] ===
|
|
2815
|
+
(phase['disk_status'] === phase_status_cjs_1.DISK_STATUS.EMPTY || phase['disk_status'] === phase_status_cjs_1.DISK_STATUS.NO_DIRECTORY) &&
|
|
2755
2816
|
phase['deps_satisfied'];
|
|
2756
2817
|
}
|
|
2757
2818
|
let waitingSignal = null;
|
|
@@ -2773,12 +2834,12 @@ function cmdInitManager(cwd, raw) {
|
|
|
2773
2834
|
}
|
|
2774
2835
|
const recommendedActions = [];
|
|
2775
2836
|
for (const phase of phases) {
|
|
2776
|
-
if (phase['disk_status'] ===
|
|
2837
|
+
if (phase['disk_status'] === phase_status_cjs_1.DISK_STATUS.COMPLETE)
|
|
2777
2838
|
continue;
|
|
2778
2839
|
// #3185: canonical sentinel predicate (SENTINEL_RANGES [0,999]) — this was a local 999-only literal that admitted Phase 0.
|
|
2779
2840
|
if (isSentinelPhaseId(phase['number']))
|
|
2780
2841
|
continue;
|
|
2781
|
-
if (phase['disk_status'] ===
|
|
2842
|
+
if (phase['disk_status'] === phase_status_cjs_1.DISK_STATUS.EXECUTED) {
|
|
2782
2843
|
recommendedActions.push({
|
|
2783
2844
|
phase: phase['number'],
|
|
2784
2845
|
phase_name: phase['name'],
|
|
@@ -2787,7 +2848,7 @@ function cmdInitManager(cwd, raw) {
|
|
|
2787
2848
|
command: phase['verification_next_command'],
|
|
2788
2849
|
});
|
|
2789
2850
|
}
|
|
2790
|
-
else if (phase['disk_status'] ===
|
|
2851
|
+
else if (phase['disk_status'] === phase_status_cjs_1.DISK_STATUS.PLANNED && phase['deps_satisfied']) {
|
|
2791
2852
|
recommendedActions.push({
|
|
2792
2853
|
phase: phase['number'],
|
|
2793
2854
|
phase_name: phase['name'],
|
|
@@ -2796,8 +2857,8 @@ function cmdInitManager(cwd, raw) {
|
|
|
2796
2857
|
command: `${(0, runtime_slash_cjs_1.formatGsdSlash)('execute-phase', _slashRuntime)} ${phase['number']}`,
|
|
2797
2858
|
});
|
|
2798
2859
|
}
|
|
2799
|
-
else if (phase['disk_status'] ===
|
|
2800
|
-
phase['disk_status'] ===
|
|
2860
|
+
else if (phase['disk_status'] === phase_status_cjs_1.DISK_STATUS.DISCUSSED ||
|
|
2861
|
+
phase['disk_status'] === phase_status_cjs_1.DISK_STATUS.RESEARCHED) {
|
|
2801
2862
|
recommendedActions.push({
|
|
2802
2863
|
phase: phase['number'],
|
|
2803
2864
|
phase_name: phase['name'],
|
|
@@ -2806,7 +2867,7 @@ function cmdInitManager(cwd, raw) {
|
|
|
2806
2867
|
command: `${(0, runtime_slash_cjs_1.formatGsdSlash)('plan-phase', _slashRuntime)} ${phase['number']}`,
|
|
2807
2868
|
});
|
|
2808
2869
|
}
|
|
2809
|
-
else if ((phase['disk_status'] ===
|
|
2870
|
+
else if ((phase['disk_status'] === phase_status_cjs_1.DISK_STATUS.EMPTY || phase['disk_status'] === phase_status_cjs_1.DISK_STATUS.NO_DIRECTORY) &&
|
|
2810
2871
|
phase['is_next_to_discuss']) {
|
|
2811
2872
|
recommendedActions.push({
|
|
2812
2873
|
phase: phase['number'],
|
|
@@ -2817,10 +2878,10 @@ function cmdInitManager(cwd, raw) {
|
|
|
2817
2878
|
});
|
|
2818
2879
|
}
|
|
2819
2880
|
}
|
|
2820
|
-
const activeExecuting = phases.filter((p) => p['disk_status'] ===
|
|
2821
|
-
(p['disk_status'] ===
|
|
2881
|
+
const activeExecuting = phases.filter((p) => p['disk_status'] === phase_status_cjs_1.DISK_STATUS.PARTIAL ||
|
|
2882
|
+
(p['disk_status'] === phase_status_cjs_1.DISK_STATUS.PLANNED && p['is_active']));
|
|
2822
2883
|
const activePlanning = phases.filter((p) => p['is_active'] &&
|
|
2823
|
-
(p['disk_status'] ===
|
|
2884
|
+
(p['disk_status'] === phase_status_cjs_1.DISK_STATUS.DISCUSSED || p['disk_status'] === phase_status_cjs_1.DISK_STATUS.RESEARCHED));
|
|
2824
2885
|
const filteredActions = recommendedActions.filter((action) => {
|
|
2825
2886
|
if (action['action'] === 'execute' && activeExecuting.length > 0) {
|
|
2826
2887
|
return activeExecuting.every((active) => !hasDepRelationship(action['phase'], active['number']));
|
|
@@ -2863,7 +2924,7 @@ function cmdInitManager(cwd, raw) {
|
|
|
2863
2924
|
phases,
|
|
2864
2925
|
phase_count: phases.length,
|
|
2865
2926
|
completed_count: completedCount,
|
|
2866
|
-
in_progress_count: phases.filter((p) => [
|
|
2927
|
+
in_progress_count: phases.filter((p) => [phase_status_cjs_1.DISK_STATUS.EXECUTED, phase_status_cjs_1.DISK_STATUS.PARTIAL, phase_status_cjs_1.DISK_STATUS.PLANNED, phase_status_cjs_1.DISK_STATUS.DISCUSSED, phase_status_cjs_1.DISK_STATUS.RESEARCHED].includes(p['disk_status'])).length,
|
|
2867
2928
|
recommended_actions: filteredActions,
|
|
2868
2929
|
waiting_signal: waitingSignal,
|
|
2869
2930
|
all_complete: completedCount === nonBacklogPhases.length && nonBacklogPhases.length > 0,
|
|
@@ -3213,10 +3274,34 @@ function cmdInitProgress(cwd, raw, options = {}) {
|
|
|
3213
3274
|
// uncounted LABEL_ONLY consumer to init.cts's pinned
|
|
3214
3275
|
// tests/adr-612-bracket-heading-selection.test.cjs census.
|
|
3215
3276
|
// phase-id-owner: deliberately unmigrated (#4984 revert) — see comment above.
|
|
3216
|
-
|
|
3277
|
+
// #4982: anchored (`^`, `m`) — the phase label must be the FIRST thing
|
|
3278
|
+
// after the checkbox (tolerating only an optional `**` bold marker) — so
|
|
3279
|
+
// the greedy `.*` this replaces can no longer bind a line's checkbox to
|
|
3280
|
+
// the LAST "Phase N" mentioned anywhere in that line's prose. This value
|
|
3281
|
+
// feeds `roadmap_complete` AND directly gates next_phase/current_phase
|
|
3282
|
+
// selection below, so getting the wrong phase here is load-bearing, not
|
|
3283
|
+
// metadata-only (contrast the `_cbPattern` site in cmdInitManager).
|
|
3284
|
+
// First-match-wins (`if (!roadmapCheckboxStates.has(...))`) additionally
|
|
3285
|
+
// guards against a later anchored line (e.g. a per-plan sub-entry
|
|
3286
|
+
// self-titled "Phase N ...") overwriting an already-recorded phase's own
|
|
3287
|
+
// (first) checkbox — anchoring alone does not fully close that
|
|
3288
|
+
// "last-match-wins" composition defect.
|
|
3289
|
+
// `(?:\[[^\]\n]{0,200}\]\s*)?` tolerates an optional leading bracket tag
|
|
3290
|
+
// (literal mirror of BASE_ANY_BRACKET_HEADING_PREFIX_SRC, phase-id.cts)
|
|
3291
|
+
// BEFORE the literal "Phase" word — decoration tolerance only, no capture
|
|
3292
|
+
// group, no convention gating. Without it the anchor fix above regresses
|
|
3293
|
+
// a checklist line combining a bracket tag with literal "Phase N" wording
|
|
3294
|
+
// (e.g. `**[GSD.02] Phase 3: ...**`), which the old unanchored `.*`
|
|
3295
|
+
// matched (by absorbing the bracket text). This does NOT migrate the site
|
|
3296
|
+
// onto phaseHeadingPrefixSrcFor / the bracket convention — that stays
|
|
3297
|
+
// out of scope per the comment above (#4984 revert, pinned census).
|
|
3298
|
+
const cbPattern = new RegExp(`^[ \\t]*-[ \\t]*\\[(x| )\\][ \\t]*(?:\\*\\*)?(?:\\[[^\\]\\n]{0,200}\\]\\s*)?Phase\\s+(${PHASE_NUMBER_TOKEN_SOURCE})[:\\s]`, 'gim');
|
|
3217
3299
|
let cbm;
|
|
3218
3300
|
while ((cbm = cbPattern.exec(roadmapContent)) !== null) {
|
|
3219
|
-
|
|
3301
|
+
const cbKey = cbm[2];
|
|
3302
|
+
if (!roadmapCheckboxStates.has(cbKey)) {
|
|
3303
|
+
roadmapCheckboxStates.set(cbKey, cbm[1].toLowerCase() === 'x');
|
|
3304
|
+
}
|
|
3220
3305
|
}
|
|
3221
3306
|
}
|
|
3222
3307
|
catch {
|
|
@@ -3238,8 +3323,9 @@ function cmdInitProgress(cwd, raw, options = {}) {
|
|
|
3238
3323
|
seenPhaseNums.add(phaseNumber.replace(/^0+/, '') || '0');
|
|
3239
3324
|
const phasePath = node_path_1.default.join(phasesDir, dir);
|
|
3240
3325
|
const phaseFiles = node_fs_1.default.readdirSync(phasePath);
|
|
3241
|
-
|
|
3242
|
-
|
|
3326
|
+
// #5060: Phase Status Module — the single owner of "what state is
|
|
3327
|
+
// phase P in?" (ADR-5057 §1/§2).
|
|
3328
|
+
const ps = (0, phase_status_cjs_1.phaseStatus)(phasePath, { convention: resolvePhaseIdConvention(cwd) });
|
|
3243
3329
|
// #3511-class: scope the raw listing to THIS phase's own artifacts
|
|
3244
3330
|
// before the hasResearch predicate runs, so a stray cross-phase
|
|
3245
3331
|
// `-RESEARCH.md` sitting in this directory cannot win this phase's
|
|
@@ -3247,16 +3333,8 @@ function cmdInitProgress(cwd, raw, options = {}) {
|
|
|
3247
3333
|
const scopedPhaseFiles = scopeToPhase(phaseFiles, dir);
|
|
3248
3334
|
const hasResearch = scopedPhaseFiles.some((f) => f.endsWith('-RESEARCH.md') || f === 'RESEARCH.md');
|
|
3249
3335
|
const phaseDirRel = toPosixPath(node_path_1.default.relative(cwd, node_path_1.default.join(planningDir(cwd), 'phases', dir)));
|
|
3250
|
-
const completion = buildPhaseCompletionProjection(cwd, phaseNumber, phaseDirRel,
|
|
3251
|
-
const status =
|
|
3252
|
-
? 'complete'
|
|
3253
|
-
: completion.implementation_complete
|
|
3254
|
-
? 'executed'
|
|
3255
|
-
: plans.length > 0
|
|
3256
|
-
? 'in_progress'
|
|
3257
|
-
: hasResearch
|
|
3258
|
-
? 'researched'
|
|
3259
|
-
: 'pending';
|
|
3336
|
+
const completion = buildPhaseCompletionProjection(cwd, phaseNumber, phaseDirRel, ps.value.planCount, ps.value.summaryCount, _slashRuntime, resolvePhaseIdConvention(cwd));
|
|
3337
|
+
const status = (0, phase_status_cjs_1.toProgressStatus)(ps.value.status, { hasResearch });
|
|
3260
3338
|
const phaseInfo = {
|
|
3261
3339
|
number: phaseNumber,
|
|
3262
3340
|
name: phaseName,
|
|
@@ -3265,30 +3343,37 @@ function cmdInitProgress(cwd, raw, options = {}) {
|
|
|
3265
3343
|
// above still joins it against cwd.
|
|
3266
3344
|
directory: toPosixPath(node_path_1.default.join(cwd, phaseDirRel)),
|
|
3267
3345
|
status,
|
|
3268
|
-
plan_count:
|
|
3269
|
-
summary_count:
|
|
3346
|
+
plan_count: ps.value.planCount,
|
|
3347
|
+
summary_count: ps.value.summaryCount,
|
|
3270
3348
|
has_research: hasResearch,
|
|
3271
3349
|
...completion,
|
|
3272
3350
|
};
|
|
3273
3351
|
phases.push(phaseInfo);
|
|
3274
|
-
if (!currentPhase && (status ===
|
|
3352
|
+
if (!currentPhase && (status === phase_status_cjs_1.PROGRESS_STATUS.EXECUTED || status === phase_status_cjs_1.PROGRESS_STATUS.IN_PROGRESS || status === phase_status_cjs_1.PROGRESS_STATUS.RESEARCHED)) {
|
|
3275
3353
|
currentPhase = phaseInfo;
|
|
3276
3354
|
}
|
|
3277
|
-
if (!nextPhase && status ===
|
|
3355
|
+
if (!nextPhase && status === phase_status_cjs_1.PROGRESS_STATUS.PENDING) {
|
|
3278
3356
|
nextPhase = phaseInfo;
|
|
3279
3357
|
}
|
|
3280
3358
|
}
|
|
3281
3359
|
}
|
|
3282
|
-
catch {
|
|
3283
|
-
|
|
3360
|
+
catch (err) {
|
|
3361
|
+
// #5118: the owner's out-of-set report error is not a scan failure to
|
|
3362
|
+
// degrade over — the bundle is never assembled over a refused report.
|
|
3363
|
+
if (err instanceof VerificationStatusError)
|
|
3364
|
+
throw err;
|
|
3365
|
+
/* otherwise intentionally empty */
|
|
3284
3366
|
}
|
|
3285
3367
|
for (const [num, name] of roadmapPhaseNames) {
|
|
3286
3368
|
const stripped = num.replace(/^0+/, '') || '0';
|
|
3287
3369
|
if (!seenPhaseNums.has(stripped)) {
|
|
3288
3370
|
const checkboxComplete = roadmapCheckboxStates.get(num) === true ||
|
|
3289
3371
|
roadmapCheckboxStates.get(stripped) === true;
|
|
3290
|
-
const completion = buildPhaseCompletionProjection(cwd, num, null, 0, 0, _slashRuntime);
|
|
3291
|
-
|
|
3372
|
+
const completion = buildPhaseCompletionProjection(cwd, num, null, 0, 0, _slashRuntime, resolvePhaseIdConvention(cwd));
|
|
3373
|
+
// #5060: this synthetic row has no phase directory at all — the
|
|
3374
|
+
// roadmap heading exists but no `seenPhaseNums` disk match was found —
|
|
3375
|
+
// so it is the ladder's own NOT_STARTED word, not a derived guess.
|
|
3376
|
+
const status = phase_status_cjs_1.PROGRESS_STATUS.NOT_STARTED;
|
|
3292
3377
|
const phaseInfo = {
|
|
3293
3378
|
number: num,
|
|
3294
3379
|
// #3883 (ADR-3473 §8.3): delegate to the canonical slug formula
|
|
@@ -3325,7 +3410,7 @@ function cmdInitProgress(cwd, raw, options = {}) {
|
|
|
3325
3410
|
{
|
|
3326
3411
|
const frontier = phases.find((p) => {
|
|
3327
3412
|
const st = p['status'];
|
|
3328
|
-
return (st ===
|
|
3413
|
+
return (st === phase_status_cjs_1.PROGRESS_STATUS.PENDING || st === phase_status_cjs_1.PROGRESS_STATUS.NOT_STARTED) && p['roadmap_complete'] !== true;
|
|
3329
3414
|
});
|
|
3330
3415
|
if (frontier)
|
|
3331
3416
|
nextPhase = frontier;
|
|
@@ -3362,8 +3447,8 @@ function cmdInitProgress(cwd, raw, options = {}) {
|
|
|
3362
3447
|
milestone_name: milestone['name'] ?? null,
|
|
3363
3448
|
phases,
|
|
3364
3449
|
phase_count: phases.length,
|
|
3365
|
-
completed_count: phases.filter((p) => p['status'] ===
|
|
3366
|
-
in_progress_count: phases.filter((p) => [
|
|
3450
|
+
completed_count: phases.filter((p) => p['status'] === phase_status_cjs_1.PROGRESS_STATUS.COMPLETE).length,
|
|
3451
|
+
in_progress_count: phases.filter((p) => [phase_status_cjs_1.PROGRESS_STATUS.EXECUTED, phase_status_cjs_1.PROGRESS_STATUS.IN_PROGRESS].includes(p['status'])).length,
|
|
3367
3452
|
current_phase: currentPhase,
|
|
3368
3453
|
next_phase: nextPhase,
|
|
3369
3454
|
paused_at: pausedAt,
|
|
@@ -3955,10 +4040,11 @@ function buildSkillManifest(cwd, skillsDir = null) {
|
|
|
3955
4040
|
seenNamesInRoot.add(name);
|
|
3956
4041
|
const description = frontmatter['description'] || '';
|
|
3957
4042
|
const triggers = [];
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
4043
|
+
// TRIGGER lines are read from the body after the block `extractFrontmatter` read (the
|
|
4044
|
+
// one fence owner), so a `---` inside a frontmatter value cannot start the body early.
|
|
4045
|
+
const block = frontmatterBlock(content);
|
|
4046
|
+
if (block) {
|
|
4047
|
+
const triggerLines = block.rest.match(/^TRIGGER\s+when:\s*(.+)$/gmi);
|
|
3962
4048
|
if (triggerLines) {
|
|
3963
4049
|
for (const line of triggerLines) {
|
|
3964
4050
|
const m = line.match(/^TRIGGER\s+when:\s*(.+)$/i);
|