@opengsd/gsd-core 1.14.0 → 1.16.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/.opencode/plugins/gsd-core.js +85 -5
- package/README.ja-JP.md +3 -3
- package/README.ko-KR.md +3 -3
- package/README.pt-BR.md +3 -3
- package/README.zh-CN.md +3 -3
- package/agents/gsd-code-fixer.compact.md +7 -6
- package/agents/gsd-code-fixer.md +9 -8
- 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 +17 -2
- package/agents/gsd-debug-session-manager.md +17 -2
- package/agents/gsd-debugger.md +3 -3
- package/agents/gsd-eval-auditor.compact.md +1 -1
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +17 -12
- 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 +19 -11
- package/agents/gsd-plan-checker.md +15 -9
- package/agents/gsd-planner.md +15 -11
- 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 +166 -37
- package/agents/gsd-ui-researcher.compact.md +1 -1
- package/agents/gsd-ui-researcher.md +1 -1
- package/agents/gsd-verifier.md +37 -14
- package/bin/install.js +764 -287
- 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 +7 -2
- package/commands/gsd/capture.md +9 -5
- 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 +12 -4
- 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 +11 -7
- package/commands/gsd/pr-branch.md +4 -0
- package/commands/gsd/profile-user.md +5 -1
- package/commands/gsd/progress.md +7 -2
- package/commands/gsd/quick-batch.md +21 -9
- package/commands/gsd/quick.md +12 -7
- package/commands/gsd/review.md +7 -4
- 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 +477 -78
- package/gsd-core/bin/lib/active-workstream-store.cjs +15 -0
- package/gsd-core/bin/lib/adr-parser.cjs +3 -1
- package/gsd-core/bin/lib/agent-install-check.cjs +4 -1
- package/gsd-core/bin/lib/audit.cjs +144 -42
- 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 +197 -222
- package/gsd-core/bin/lib/capability-validator.cjs +16 -1
- package/gsd-core/bin/lib/check-auto-mode.cjs +35 -0
- package/gsd-core/bin/lib/check-command-router.cjs +164 -1625
- 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 +32 -33
- 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 +343 -207
- package/gsd-core/bin/lib/complexity-trigger.cjs +8 -7
- package/gsd-core/bin/lib/config-loader.cjs +65 -4
- package/gsd-core/bin/lib/config.cjs +76 -19
- 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/decisions.cjs +30 -14
- 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 +426 -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 +141 -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 +80 -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 +10 -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/host-runtime-detection.cjs +9 -0
- package/gsd-core/bin/lib/init.cjs +364 -132
- package/gsd-core/bin/lib/install-engine.cjs +30 -33
- package/gsd-core/bin/lib/install-profiles.cjs +7 -4
- package/gsd-core/bin/lib/installer-migrations.cjs +8 -1
- package/gsd-core/bin/lib/io.cjs +122 -3
- 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/milestone.cjs +37 -6
- package/gsd-core/bin/lib/model-resolver.cjs +171 -62
- 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/pattern.cjs +10 -0
- package/gsd-core/bin/lib/phase-command-router.cjs +20 -5
- package/gsd-core/bin/lib/phase-estimation.cjs +5 -4
- package/gsd-core/bin/lib/phase-id-card.cjs +32 -0
- package/gsd-core/bin/lib/phase-id-display.cjs +78 -0
- package/gsd-core/bin/lib/phase-id.cjs +110 -8
- package/gsd-core/bin/lib/phase-lifecycle.cjs +9 -2
- package/gsd-core/bin/lib/phase-locator.cjs +29 -10
- package/gsd-core/bin/lib/phase-status.cjs +360 -0
- package/gsd-core/bin/lib/phase.cjs +489 -88
- package/gsd-core/bin/lib/plan-document.cjs +142 -20
- package/gsd-core/bin/lib/plan-drift-guard.cjs +5 -0
- package/gsd-core/bin/lib/planning-document.cjs +692 -0
- package/gsd-core/bin/lib/planning-inspect.cjs +60 -9
- package/gsd-core/bin/lib/planning-snapshot.cjs +18 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +83 -55
- package/gsd-core/bin/lib/pr-branch-patterns.cjs +57 -0
- package/gsd-core/bin/lib/pristine-baseline.cjs +10 -0
- package/gsd-core/bin/lib/probe-core.cjs +7 -1
- 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/project-root.cjs +41 -2
- package/gsd-core/bin/lib/quick-batch-command-router.cjs +35 -9
- package/gsd-core/bin/lib/quick-batch-dispatch.cjs +11 -8
- 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/review-lane-descriptor.cjs +10 -30
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +2 -2
- package/gsd-core/bin/lib/roadmap-command-router.cjs +25 -19
- package/gsd-core/bin/lib/roadmap-parser.cjs +242 -15
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +1653 -65
- package/gsd-core/bin/lib/roadmap.cjs +405 -88
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +373 -187
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +5 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +57 -1
- package/gsd-core/bin/lib/runtime-homes.cjs +14 -7
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +522 -624
- package/gsd-core/bin/lib/runtime-name-policy.cjs +246 -21
- package/gsd-core/bin/lib/runtime-slash.cjs +47 -30
- package/gsd-core/bin/lib/shell-command-projection.cjs +47 -8
- package/gsd-core/bin/lib/smart-entry.cjs +19 -3
- 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 +39 -2
- package/gsd-core/bin/lib/state.cjs +256 -105
- package/gsd-core/bin/lib/surface.cjs +19 -2
- package/gsd-core/bin/lib/tdd-red-evidence.cjs +48 -79
- package/gsd-core/bin/lib/uat-predicate.cjs +359 -38
- package/gsd-core/bin/lib/uat.cjs +432 -7
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +15 -2
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +167 -40
- package/gsd-core/bin/lib/undo-commit-selection.cjs +131 -0
- 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 +1378 -274
- package/gsd-core/bin/lib/verify-command-grounding.cjs +46 -2
- package/gsd-core/bin/lib/verify-command-router.cjs +18 -7
- package/gsd-core/bin/lib/verify.cjs +357 -531
- 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/lib/worktree-base-ref.cjs +482 -73
- package/gsd-core/bin/lib/worktree-safety.cjs +784 -51
- package/gsd-core/bin/shared/config-defaults.manifest.json +8 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +5 -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/checkpoints.md +5 -3
- package/gsd-core/references/edge-probe-fixtures/01-round-half-even/expected-coverage.json +28 -3
- package/gsd-core/references/edge-probe-fixtures/02-merge-intervals/expected-coverage.json +37 -4
- package/gsd-core/references/edge-probe-fixtures/03-truncate-graphemes/expected-coverage.json +28 -3
- package/gsd-core/references/edge-probe-fixtures/04-money-rounding/expected-coverage.json +28 -3
- package/gsd-core/references/edge-probe-fixtures/05-list-dedupe/expected-coverage.json +37 -4
- package/gsd-core/references/edge-probe-fixtures/06-resolved-mixed/expected-coverage.json +37 -4
- package/gsd-core/references/edge-probe.md +195 -21
- package/gsd-core/references/execute-mvp-tdd.md +5 -10
- package/gsd-core/references/execute-phase-between-wave-reset.md +10 -6
- package/gsd-core/references/execute-phase-response-language.md +1 -1
- package/gsd-core/references/execute-phase-wave-guard.md +22 -11
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/loop-hook-dispatch.md +7 -1
- package/gsd-core/references/model-profiles.md +1 -1
- package/gsd-core/references/offer-next.md +1 -1
- package/gsd-core/references/phase-argument-parsing.md +9 -7
- package/gsd-core/references/phase-id-convention.md +28 -0
- package/gsd-core/references/planner-gap-closure.md +2 -0
- package/gsd-core/references/planner-load-graph-context.md +24 -13
- package/gsd-core/references/planner-verify-command-grounding.md +14 -0
- package/gsd-core/references/planning-config.md +12 -3
- package/gsd-core/references/spidr-splitting.md +1 -1
- package/gsd-core/references/tdd.md +37 -8
- package/gsd-core/references/ui-consideration-probe.md +10 -5
- package/gsd-core/references/verifier-phase-gates.md +5 -2
- package/gsd-core/references/verify-command-path-resolvability.md +10 -2
- package/gsd-core/references/verify-mvp-mode.md +2 -2
- package/gsd-core/references/workstream-flag.md +33 -3
- package/gsd-core/references/worktree-path-safety.md +321 -0
- 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 +4 -3
- package/gsd-core/workflows/add-todo.md +6 -5
- package/gsd-core/workflows/ai-integration-phase.md +13 -4
- 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/steps/converge-fail-fast.md +9 -18
- package/gsd-core/workflows/autonomous.md +43 -23
- package/gsd-core/workflows/check-todos.md +7 -6
- package/gsd-core/workflows/cleanup.md +2 -2
- package/gsd-core/workflows/code-review/steps/dispatch-fix.md +4 -3
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +20 -13
- package/gsd-core/workflows/code-review-fix.md +112 -25
- package/gsd-core/workflows/code-review.md +146 -135
- package/gsd-core/workflows/complete-milestone/detail/elaboration.md +4 -3
- package/gsd-core/workflows/complete-milestone.md +13 -8
- package/gsd-core/workflows/debug.md +32 -7
- 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 +2 -2
- package/gsd-core/workflows/docs-update.md +6 -5
- package/gsd-core/workflows/edit-phase.md +4 -3
- package/gsd-core/workflows/eval-review.md +14 -5
- package/gsd-core/workflows/execute-phase/detail/elaboration.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +1019 -0
- 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 +37 -3
- 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 +46 -9
- package/gsd-core/workflows/execute-phase/steps/protected-branch.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/ready-wave-gate.md +37 -0
- 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/threat-id-gate.md +28 -0
- 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/steps/worktree-base-check.md +25 -0
- package/gsd-core/workflows/execute-phase.md +96 -178
- package/gsd-core/workflows/execute-plan.md +18 -23
- package/gsd-core/workflows/explore.md +4 -4
- package/gsd-core/workflows/extract-learnings.md +4 -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 +3 -2
- package/gsd-core/workflows/help/modes/full.compact.md +3 -3
- package/gsd-core/workflows/help/modes/full.md +5 -5
- package/gsd-core/workflows/help/modes/topic.md +15 -5
- package/gsd-core/workflows/import.md +4 -3
- package/gsd-core/workflows/inbox.md +2 -2
- package/gsd-core/workflows/ingest-docs.md +3 -3
- 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 +6 -4
- package/gsd-core/workflows/map-codebase.md +5 -4
- 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 +11 -11
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +3 -3
- package/gsd-core/workflows/new-project/steps/codebase-map-offer.md +1 -1
- package/gsd-core/workflows/new-project.md +7 -7
- package/gsd-core/workflows/new-workspace.md +2 -2
- package/gsd-core/workflows/next.md +1 -1
- package/gsd-core/workflows/note.md +1 -1
- package/gsd-core/workflows/onboard.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 +17 -5
- 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 +23 -5
- package/gsd-core/workflows/plan-phase.md +50 -24
- package/gsd-core/workflows/plan-review-convergence.md +21 -5
- package/gsd-core/workflows/plant-seed.md +62 -20
- package/gsd-core/workflows/pr-branch.md +113 -13
- package/gsd-core/workflows/profile-user.md +2 -2
- package/gsd-core/workflows/progress.md +19 -49
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +27 -0
- 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 +62 -39
- package/gsd-core/workflows/reapply-patches.md +9 -3
- package/gsd-core/workflows/remove-phase.md +3 -2
- package/gsd-core/workflows/remove-workspace.md +2 -2
- package/gsd-core/workflows/resume-project.md +3 -2
- package/gsd-core/workflows/review.md +33 -17
- package/gsd-core/workflows/scan.md +3 -2
- package/gsd-core/workflows/secure-phase.md +13 -13
- package/gsd-core/workflows/settings-advanced.md +30 -10
- package/gsd-core/workflows/settings-integrations.md +2 -3
- package/gsd-core/workflows/settings.md +4 -4
- package/gsd-core/workflows/ship.md +14 -13
- 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 +2 -2
- package/gsd-core/workflows/spec-phase.md +15 -5
- 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 +5 -5
- package/gsd-core/workflows/thread.md +2 -2
- package/gsd-core/workflows/transition.md +13 -23
- package/gsd-core/workflows/ui-phase.md +48 -11
- package/gsd-core/workflows/ui-review.md +21 -6
- package/gsd-core/workflows/ultraplan-phase.md +3 -2
- package/gsd-core/workflows/undo.md +339 -20
- package/gsd-core/workflows/update.md +7 -7
- package/gsd-core/workflows/validate-phase.md +12 -13
- 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 +129 -55
- package/hooks/dist/gsd-agent-isolation-guard.js +32 -0
- package/hooks/dist/gsd-check-update-worker.js +8 -0
- package/hooks/dist/gsd-check-update.js +8 -0
- package/hooks/dist/gsd-context-monitor.js +31 -8
- package/hooks/dist/gsd-cursor-subagent-start.js +8 -0
- package/hooks/dist/gsd-secret-read-guard.js +161 -4
- package/hooks/dist/gsd-statusline.js +85 -20
- package/hooks/dist/gsd-update-banner.js +8 -0
- package/hooks/dist/gsd-validate-commit.sh +63 -4
- 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 +32 -0
- package/hooks/gsd-check-update-worker.js +8 -0
- package/hooks/gsd-check-update.js +8 -0
- package/hooks/gsd-context-monitor.js +31 -8
- package/hooks/gsd-cursor-subagent-start.js +8 -0
- package/hooks/gsd-secret-read-guard.js +161 -4
- package/hooks/gsd-statusline.js +85 -20
- package/hooks/gsd-update-banner.js +8 -0
- package/hooks/gsd-validate-commit.sh +63 -4
- 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 +22 -4
- package/scripts/build-hooks.js +15 -6
- package/scripts/changeset/parse.cjs +52 -4
- package/scripts/check-contract-drift.cjs +127 -11
- package/scripts/ci-timeout-report.cjs +770 -4
- package/scripts/command-contract-helpers.cjs +15 -8
- package/scripts/docs-guard-registry.cjs +34 -0
- package/scripts/gen-features.cjs +13 -8
- package/scripts/gen-hooks-cli-exit.cjs +12 -28
- package/scripts/gen-loop-host-contract.cjs +79 -1
- 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 +34 -2
- package/scripts/lib/ndjson-reporter.cjs +31 -5
- package/scripts/lib/platform-conformance-tier.generated.cjs +45 -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 +38 -1
- 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-arg-assignment.cjs +257 -0
- package/scripts/lint-phase-enumeration-drift.cjs +12 -8
- package/scripts/lint-phase-id-drift.cjs +319 -5
- package/scripts/lint-planning-document-positive-control.cjs +329 -0
- package/scripts/lint-pr-branch-pattern-drift.cjs +148 -0
- package/scripts/lint-response-language-coverage.cjs +3 -0
- package/scripts/lint-retired-runtime-name.cjs +619 -0
- package/scripts/lint-skill-deps.cjs +7 -3
- package/scripts/lint-state-write-path-drift.cjs +93 -0
- package/scripts/lint-test-file-count.allowlist.json +38 -9
- package/scripts/lint-test-file-count.cjs +34 -1
- package/scripts/lint-vendored-deps.cjs +41 -5
- package/scripts/lint-workflow-shellcheck-baseline.json +25 -10
- package/scripts/mutation-matrix.cjs +50 -5
- package/scripts/prompt-injection-scan.sh +4 -0
- package/scripts/release-tarball-smoke.cjs +194 -1
- 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 +7 -2
- package/skills/gsd-capture/SKILL.md +9 -5
- 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 +12 -4
- 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 +10 -6
- package/skills/gsd-pr-branch/SKILL.md +4 -0
- package/skills/gsd-profile-user/SKILL.md +5 -1
- package/skills/gsd-progress/SKILL.md +7 -2
- package/skills/gsd-quick/SKILL.md +16 -10
- package/skills/gsd-quick-batch/SKILL.md +21 -9
- package/skills/gsd-review/SKILL.md +7 -4
- 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
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Canonical bracket convention card (#3638 / ADR-612 PR-5).
|
|
4
|
+
*
|
|
5
|
+
* This module is the sole editable source of the compact grammar diagram.
|
|
6
|
+
* Render sites import phaseIdCard(); generated documentation is held to the
|
|
7
|
+
* same bytes by tests/phase-id-card.test.cjs. PR-6 can therefore inject the
|
|
8
|
+
* card broadly without inventing another copy.
|
|
9
|
+
*/
|
|
10
|
+
const PHASE_ID_CARD = [
|
|
11
|
+
'[GSD.02] 05.03-01',
|
|
12
|
+
' │ │ │ │ │',
|
|
13
|
+
' │ │ │ │ └── plan 01',
|
|
14
|
+
' │ │ │ └────── subphase 03',
|
|
15
|
+
' │ │ └───────── phase 05',
|
|
16
|
+
' │ └───────────── milestone 02',
|
|
17
|
+
' └───────────────── project GSD',
|
|
18
|
+
].join('\n');
|
|
19
|
+
const PHASE_ID_LEGEND = "milestone = bracket integer; dots = phase-levels; one hyphen = plan; "
|
|
20
|
+
+ "no 'Phase' word, no vX.Y";
|
|
21
|
+
function phaseIdCard(options = {}) {
|
|
22
|
+
const parts = [];
|
|
23
|
+
if (options.title)
|
|
24
|
+
parts.push(options.title, '');
|
|
25
|
+
parts.push(PHASE_ID_CARD, '', PHASE_ID_LEGEND);
|
|
26
|
+
return parts.join('\n');
|
|
27
|
+
}
|
|
28
|
+
module.exports = {
|
|
29
|
+
phaseIdCard,
|
|
30
|
+
PHASE_ID_CARD,
|
|
31
|
+
PHASE_ID_LEGEND,
|
|
32
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Phase-ID display adapters (#3638 / ADR-612 PR-5).
|
|
4
|
+
*
|
|
5
|
+
* STATE.md and milestone metadata still expose the legacy `vN.0` marker on
|
|
6
|
+
* this stacked base. Display surfaces need to translate that metadata into a
|
|
7
|
+
* bracket identity without growing another renderer. These pure adapters do
|
|
8
|
+
* only the boundary normalization, then delegate identity parsing/rendering to
|
|
9
|
+
* phase-id.cts's canonical pair.
|
|
10
|
+
*/
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
12
|
+
const phaseId = require("./phase-id.cjs");
|
|
13
|
+
const { parsePhaseId, renderMilestoneId, renderPhaseId } = phaseId;
|
|
14
|
+
function canonicalNumeric(value) {
|
|
15
|
+
let offset = 0;
|
|
16
|
+
while (offset < value.length - 1 && value[offset] === '0')
|
|
17
|
+
offset++;
|
|
18
|
+
const stripped = value.slice(offset);
|
|
19
|
+
return stripped.length < 2 ? stripped.padStart(2, '0') : stripped;
|
|
20
|
+
}
|
|
21
|
+
function isDigits(value) {
|
|
22
|
+
return value.length > 0
|
|
23
|
+
&& [...value].every(char => char >= '0' && char <= '9');
|
|
24
|
+
}
|
|
25
|
+
function milestoneToken(value) {
|
|
26
|
+
if (typeof value !== 'string' && typeof value !== 'number')
|
|
27
|
+
return null;
|
|
28
|
+
const raw = String(value).replace(/^v/i, '');
|
|
29
|
+
const parts = raw.split('.');
|
|
30
|
+
if (parts.length > 2 || parts.some(part => !isDigits(part)))
|
|
31
|
+
return null;
|
|
32
|
+
return canonicalNumeric(parts[0]);
|
|
33
|
+
}
|
|
34
|
+
function phaseToken(value) {
|
|
35
|
+
if (typeof value !== 'string' && typeof value !== 'number')
|
|
36
|
+
return null;
|
|
37
|
+
const raw = String(value);
|
|
38
|
+
const parts = raw.split('.');
|
|
39
|
+
if (parts.length > 2 || parts.some(part => !isDigits(part)))
|
|
40
|
+
return null;
|
|
41
|
+
return parts.map(canonicalNumeric).join('.');
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Render a bracket phase display from legacy milestone metadata.
|
|
45
|
+
* Returns null for incomplete or invalid metadata so cosmetic callers can
|
|
46
|
+
* degrade without breaking a command/statusline render.
|
|
47
|
+
*/
|
|
48
|
+
function renderBracketPhaseDisplay(milestone, phase, projectCode) {
|
|
49
|
+
const project = typeof projectCode === 'string' ? projectCode : '';
|
|
50
|
+
const mm = milestoneToken(milestone);
|
|
51
|
+
const pp = phaseToken(phase);
|
|
52
|
+
if (!project || mm === null || pp === null)
|
|
53
|
+
return null;
|
|
54
|
+
try {
|
|
55
|
+
return renderPhaseId(parsePhaseId(`${project}.${mm}-${pp}`));
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/** Render only the bracket milestone label, still through canonical parsing. */
|
|
62
|
+
function renderBracketMilestoneDisplay(milestone, projectCode) {
|
|
63
|
+
const project = typeof projectCode === 'string' ? projectCode : '';
|
|
64
|
+
const mm = milestoneToken(milestone);
|
|
65
|
+
if (!project || mm === null)
|
|
66
|
+
return null;
|
|
67
|
+
try {
|
|
68
|
+
// The sentinel phase is a validation vehicle, not a rendering artifact.
|
|
69
|
+
return renderMilestoneId(parsePhaseId(`${project}.${mm}-00`));
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
module.exports = {
|
|
76
|
+
renderBracketPhaseDisplay,
|
|
77
|
+
renderBracketMilestoneDisplay,
|
|
78
|
+
};
|
|
@@ -59,6 +59,20 @@ const OPTIONAL_PHASE_TAG_SOURCE = '(?:\\s*\\([^)\\n]{0,200}\\))?';
|
|
|
59
59
|
// (scripts/lint-phase-id-drift.cjs) fails CI if a literal re-derivation is
|
|
60
60
|
// introduced outside this module without a `// phase-id-owner:` justification.
|
|
61
61
|
const PHASE_NUMBER_TOKEN_SOURCE = '\\d+[A-Z]?(?:\\.\\d+)*';
|
|
62
|
+
// #4764: a phase REFERENCE in depends-on PROSE — the token in context, directly
|
|
63
|
+
// following "Phase"/"Phases", with bare-token list continuation ("Phases 1 and 2",
|
|
64
|
+
// "Phase 1, 2, and 3", "Phase 1-3"). Built HERE, beside the token grammar it is
|
|
65
|
+
// anchored on, because two readers consume Depends-on prose (init.manager's
|
|
66
|
+
// dep_phases and planning-inspect's dependencies) and re-deriving the anchored
|
|
67
|
+
// form at each would drift exactly the way PHASE_NUMBER_TOKEN_SOURCE's own
|
|
68
|
+
// anti-divergence rule exists to prevent. A bare digit run is the right shape
|
|
69
|
+
// test for a phase id and the WRONG test for a reference: the whole-field
|
|
70
|
+
// scrape this replaces pulled calendar dates ("2026-09-14" → 2026/09/14), git
|
|
71
|
+
// shas ("8bf403100d" → 8b/403100d/…) and ledger ids (WINDOWS #1843) in as
|
|
72
|
+
// dependencies. The `-` separator deliberately extracts range ENDPOINTS only
|
|
73
|
+
// ("Phase 1-3" → 1, 3) — the pre-#4764 behavior; interior enumeration stays
|
|
74
|
+
// out (a range's middle is not written as a reference).
|
|
75
|
+
const PHASE_DEP_REF_SOURCE = `\\bphases?\\s+(${PHASE_NUMBER_TOKEN_SOURCE}(?:(?:\\s*,\\s*(?:and\\s+)?|\\s+and\\s+|\\s*&\\s*|\\s+(?:to|through)\\s+|\\s*-\\s*)${PHASE_NUMBER_TOKEN_SOURCE})*)`;
|
|
62
76
|
// #2528 review: the CASE-FLEXIBLE renderings of the two sources above, for call
|
|
63
77
|
// sites that scan directory names (where a project code or a variant suffix may
|
|
64
78
|
// legitimately be lowercase) and therefore cannot use a case-sensitive class.
|
|
@@ -308,6 +322,30 @@ function phaseHeadingPrefixSrcFor(baseline, convention, capturing = false) {
|
|
|
308
322
|
const bracketAlt = `\\[${id}\\][ \\t]*(?:Phase\\s+|(?=\\d))`;
|
|
309
323
|
return `(?:${bracketAlt}|${base})`;
|
|
310
324
|
}
|
|
325
|
+
/**
|
|
326
|
+
* The single owner of the "scan a whole document for every phase heading"
|
|
327
|
+
* pattern (#4865 / ADR-4910 §8) — anchored (`^ {0,3}#{2,4}`, so indentation up
|
|
328
|
+
* to 3 spaces is tolerated but a heading is never matched mid-line), global,
|
|
329
|
+
* multiline, convention-aware via `phaseHeadingPrefixSrcFor`. Returns the
|
|
330
|
+
* capture-group layout alongside the regex so a caller never re-derives the
|
|
331
|
+
* bracket-convention offset (`const G = convention === 'bracket' ? 1 : 0`)
|
|
332
|
+
* itself — a second, independently-computed offset is exactly the kind of
|
|
333
|
+
* drift `scripts/lint-phase-id-drift.cjs` exists to catch structurally, not
|
|
334
|
+
* just by pattern text.
|
|
335
|
+
*
|
|
336
|
+
* Distinct from `buildPhaseHeadingRegex` (`src/roadmap.cts`), which searches
|
|
337
|
+
* for ONE already-known phase number (anchored `^`, no `g` flag, phase number
|
|
338
|
+
* interpolated literally) — a different contract for a different question.
|
|
339
|
+
* This function answers "which phases exist in this content", not "does this
|
|
340
|
+
* specific phase exist".
|
|
341
|
+
*/
|
|
342
|
+
function buildPhaseHeadingScanRegex(baseline, convention) {
|
|
343
|
+
const bracketGroup = convention === 'bracket' ? 1 : null;
|
|
344
|
+
const phaseNumGroup = bracketGroup ? 2 : 1;
|
|
345
|
+
const phaseNameGroup = phaseNumGroup + 1;
|
|
346
|
+
const regex = new RegExp(`^ {0,3}#{2,4}\\s*${phaseHeadingPrefixSrcFor(baseline, convention, true)}(${PHASE_NUMBER_TOKEN_SOURCE})${OPTIONAL_PHASE_TAG_SOURCE}:\\s*([^\\n]+)`, 'gim');
|
|
347
|
+
return { regex, bracketGroup, phaseNumGroup, phaseNameGroup };
|
|
348
|
+
}
|
|
311
349
|
function stripProjectCodePrefix(value, caseInsensitive = true) {
|
|
312
350
|
const input = String(value);
|
|
313
351
|
const re = caseInsensitive ? PROJECT_CODE_PREFIX_STRIP_RE_I : PROJECT_CODE_PREFIX_STRIP_RE;
|
|
@@ -451,10 +489,27 @@ function parsePhaseId(input) {
|
|
|
451
489
|
// tokens unchanged.
|
|
452
490
|
throw new Error(`parsePhaseId: not a bracket phase id: ${JSON.stringify(input)}`);
|
|
453
491
|
}
|
|
492
|
+
function renderMilestoneId(id) {
|
|
493
|
+
return `[${id.project}.${id.milestone}]`;
|
|
494
|
+
}
|
|
454
495
|
function renderPhaseId(id) {
|
|
455
496
|
const sub = id.subphase ? `.${id.subphase}` : '';
|
|
456
497
|
const plan = id.plan ? `-${id.plan}` : '';
|
|
457
|
-
return
|
|
498
|
+
return `${renderMilestoneId(id)} ${id.phase}${sub}${plan}`;
|
|
499
|
+
}
|
|
500
|
+
/** Whether a legacy phase token has a lossless spelling in bracket display grammar. */
|
|
501
|
+
function isBracketPhaseTokenRepresentable(token) {
|
|
502
|
+
try {
|
|
503
|
+
const bracketToken = normalizePhaseName(token)
|
|
504
|
+
.split('.')
|
|
505
|
+
.map((segment) => segment.padStart(2, '0'))
|
|
506
|
+
.join('.');
|
|
507
|
+
parsePhaseId(`[GSD.00] ${bracketToken}`);
|
|
508
|
+
return true;
|
|
509
|
+
}
|
|
510
|
+
catch {
|
|
511
|
+
return false;
|
|
512
|
+
}
|
|
458
513
|
}
|
|
459
514
|
// PhaseId is a structural type: nothing forces a caller through parsePhaseId,
|
|
460
515
|
// so toDir cannot trust project/milestone/phase/subphase are already
|
|
@@ -1017,7 +1072,7 @@ function isPhaseArtifact(fileName, phaseDirName, convention) {
|
|
|
1017
1072
|
* whichever path produced the candidates, which is what makes a bracket dir
|
|
1018
1073
|
* read exactly what its legacy twin reads.
|
|
1019
1074
|
*/
|
|
1020
|
-
function
|
|
1075
|
+
function expandPhaseTokenCandidates(rawCandidates) {
|
|
1021
1076
|
// Each reading is compared in BOTH its padded and de-padded form: files are
|
|
1022
1077
|
// written padded by `normalizePhaseName` (`cmdScaffold`) while directories
|
|
1023
1078
|
// are often not (`1-unpadded`), and legacy trees carry the reverse pairing.
|
|
@@ -1025,9 +1080,19 @@ function matchesPhaseTokenCandidates(fileName, rawCandidates) {
|
|
|
1025
1080
|
// sub-phase (`03A`, `03.1`) has no meaningful de-padded form and is left
|
|
1026
1081
|
// alone, so this only ever ADDS a reading and can never drop one.
|
|
1027
1082
|
const depad = (t) => (/^\d+$/.test(t) ? String(Number(t)) : t);
|
|
1028
|
-
|
|
1083
|
+
return new Set(rawCandidates
|
|
1029
1084
|
.flatMap(t => [t, normalizePhaseName(t), depad(t)])
|
|
1030
1085
|
.map(t => t.toUpperCase()));
|
|
1086
|
+
}
|
|
1087
|
+
function matchesPhaseTokenCandidates(fileName, rawCandidates) {
|
|
1088
|
+
const candidates = expandPhaseTokenCandidates(rawCandidates);
|
|
1089
|
+
if (matchPhaseTokenCandidateSpan(fileName, candidates) !== null)
|
|
1090
|
+
return true;
|
|
1091
|
+
// FIX 2: token-less filename (bare "VERIFICATION.md"/"UAT.md") — containment
|
|
1092
|
+
// in this phase's own directory listing is sufficient.
|
|
1093
|
+
return derivePhaseTokenSegments(fileName).tokenSegments.length === 0;
|
|
1094
|
+
}
|
|
1095
|
+
function matchPhaseTokenCandidateSpan(fileName, candidates) {
|
|
1031
1096
|
const fileUpper = fileName.toUpperCase();
|
|
1032
1097
|
for (const candidate of candidates) {
|
|
1033
1098
|
// A dotted sub-phase segment (e.g. `01.1-CONTEXT.md`) is a legitimate
|
|
@@ -1053,11 +1118,43 @@ function matchesPhaseTokenCandidates(fileName, rawCandidates) {
|
|
|
1053
1118
|
if (fileUpper.startsWith(`${candidate}-`) ||
|
|
1054
1119
|
fileUpper.startsWith(`${candidate}.`) ||
|
|
1055
1120
|
fileUpper.startsWith(`${candidate}_`))
|
|
1056
|
-
return
|
|
1121
|
+
return { start: 0, end: candidate.length };
|
|
1057
1122
|
}
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1123
|
+
return null;
|
|
1124
|
+
}
|
|
1125
|
+
/**
|
|
1126
|
+
* Return the exact leading token span by which the phase-artifact reader
|
|
1127
|
+
* attributes a phase-qualified filename to `phaseDirName`.
|
|
1128
|
+
*
|
|
1129
|
+
* Membership is first decided by `isPhaseArtifact`, then the span is selected
|
|
1130
|
+
* from the same padded, de-padded, case-folded candidate set used by
|
|
1131
|
+
* `matchesPhaseTokenCandidates`. Token-less containment fallbacks return null
|
|
1132
|
+
* because there is no phase token in the filename to replace.
|
|
1133
|
+
*/
|
|
1134
|
+
function phaseArtifactTokenSpan(fileName, phaseDirName, convention) {
|
|
1135
|
+
if (!isPhaseArtifact(fileName, phaseDirName, convention))
|
|
1136
|
+
return null;
|
|
1137
|
+
if (convention === 'bracket') {
|
|
1138
|
+
const bracketDir = phaseDirName.match(BRACKET_DIR_TOKEN_RE);
|
|
1139
|
+
if (bracketDir) {
|
|
1140
|
+
const qualified = fileName.match(BRACKET_QUALIFIED_KEY_RE);
|
|
1141
|
+
if (qualified && bracketQualifiedKey(fileName, convention) !== null) {
|
|
1142
|
+
return { start: 0, end: qualified[0].length };
|
|
1143
|
+
}
|
|
1144
|
+
const bracketCandidates = expandPhaseTokenCandidates([bracketDir[1]]);
|
|
1145
|
+
return matchPhaseTokenCandidateSpan(fileName, bracketCandidates);
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
const { tokenSegments } = derivePhaseTokenSegments(phaseDirName);
|
|
1149
|
+
if (tokenSegments.length === 0)
|
|
1150
|
+
return null;
|
|
1151
|
+
const literalToken = extractPhaseToken(phaseDirName);
|
|
1152
|
+
const strippedDir = stripProjectCodePrefix(phaseDirName);
|
|
1153
|
+
const strippedToken = strippedDir !== phaseDirName ? extractPhaseToken(strippedDir) : literalToken;
|
|
1154
|
+
const leadingRunMatch = strippedDir.match(LEADING_DIGIT_RUN_RE);
|
|
1155
|
+
const rawCandidates = [literalToken, strippedToken, leadingRunMatch?.[1]].filter((token) => Boolean(token));
|
|
1156
|
+
const candidates = expandPhaseTokenCandidates(rawCandidates);
|
|
1157
|
+
return matchPhaseTokenCandidateSpan(fileName, candidates);
|
|
1061
1158
|
}
|
|
1062
1159
|
/**
|
|
1063
1160
|
* #3511: scope `fileNames` to the subset that passes
|
|
@@ -1245,7 +1342,7 @@ const unpad = (digits) => digits.replace(/^0+(?=\d)/, '');
|
|
|
1245
1342
|
* candidates (#2237).
|
|
1246
1343
|
*
|
|
1247
1344
|
* TAKE `matches[0]` — `cmdPhasesList`, `cmdInitManager`, `cmdRoadmapAnalyze`,
|
|
1248
|
-
* `
|
|
1345
|
+
* the schema-drift gate (`resolvePhaseDirByToken`), `detectVerifyFailed`. Each read a directory to
|
|
1249
1346
|
* DECORATE a row they are already emitting; each used `.find()` before this
|
|
1250
1347
|
* PR, so first-match is their prior behavior preserved verbatim, and each is
|
|
1251
1348
|
* order-stable because the directory list is sorted and this function filters
|
|
@@ -1538,6 +1635,7 @@ module.exports = {
|
|
|
1538
1635
|
OPTIONAL_PROJECT_CODE_PREFIX_SOURCE,
|
|
1539
1636
|
OPTIONAL_PHASE_TAG_SOURCE,
|
|
1540
1637
|
PHASE_NUMBER_TOKEN_SOURCE,
|
|
1638
|
+
PHASE_DEP_REF_SOURCE,
|
|
1541
1639
|
CASE_FLEXIBLE_PROJECT_CODE_PREFIX_SOURCE,
|
|
1542
1640
|
CASE_FLEXIBLE_PHASE_NUMBER_TOKEN_SOURCE,
|
|
1543
1641
|
PHASE_CONTINUATION_SEGMENT_SOURCE,
|
|
@@ -1554,6 +1652,7 @@ module.exports = {
|
|
|
1554
1652
|
BASE_PHASE_LABEL_PREFIX_SRC,
|
|
1555
1653
|
PHASE_HEADING_BASELINE,
|
|
1556
1654
|
phaseHeadingPrefixSrcFor,
|
|
1655
|
+
buildPhaseHeadingScanRegex,
|
|
1557
1656
|
foldBracketId,
|
|
1558
1657
|
bracketQualifiedKey,
|
|
1559
1658
|
stripProjectCodePrefix,
|
|
@@ -1561,7 +1660,9 @@ module.exports = {
|
|
|
1561
1660
|
getMilestoneFromPhaseId,
|
|
1562
1661
|
getPhaseDirFromPhaseId,
|
|
1563
1662
|
parsePhaseId,
|
|
1663
|
+
renderMilestoneId,
|
|
1564
1664
|
renderPhaseId,
|
|
1665
|
+
isBracketPhaseTokenRepresentable,
|
|
1565
1666
|
toDir,
|
|
1566
1667
|
SENTINEL_RANGES,
|
|
1567
1668
|
isSentinelPhaseId,
|
|
@@ -1571,6 +1672,7 @@ module.exports = {
|
|
|
1571
1672
|
comparePhaseNum,
|
|
1572
1673
|
extractPhaseToken,
|
|
1573
1674
|
isPhaseArtifact,
|
|
1675
|
+
phaseArtifactTokenSpan,
|
|
1574
1676
|
scopeToPhase,
|
|
1575
1677
|
phaseTokenMatches,
|
|
1576
1678
|
matchPhaseDirs,
|
|
@@ -31,6 +31,9 @@ const markdown_table_cjs_1 = require("./markdown-table.cjs");
|
|
|
31
31
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- phase-id.cjs is an export= CommonJS module
|
|
32
32
|
const phaseIdMod = require("./phase-id.cjs");
|
|
33
33
|
const { isSentinelPhaseId } = phaseIdMod;
|
|
34
|
+
// #5060: `phase-status.cjs` is a load-time leaf (no top-level requires), safe
|
|
35
|
+
// to import here for the ROADMAP Status-cell reader.
|
|
36
|
+
const phase_status_cjs_1 = require("./phase-status.cjs");
|
|
34
37
|
/**
|
|
35
38
|
* #3227: the single owner of "where is this ROADMAP's Progress table".
|
|
36
39
|
* Lifted verbatim out of deriveProgressFromRoadmap so `state-contract.cts`
|
|
@@ -93,8 +96,6 @@ function deriveProgressFromRoadmap(roadmapContent) {
|
|
|
93
96
|
const table = locateProgressTable(roadmapContent);
|
|
94
97
|
if (table) {
|
|
95
98
|
const allRows = table.rows;
|
|
96
|
-
const completed = allRows.filter((r) => /^complete$/i.test((r['Status'] ?? '').trim())).length;
|
|
97
|
-
completedPhases = completed > 0 ? completed : null;
|
|
98
99
|
// Data rows only (exclude sentinel phases 0 and 999.x).
|
|
99
100
|
// #3185: canonical sentinel predicate (SENTINEL_RANGES [0,999]) — this was a local 999-only literal that admitted Phase 0.
|
|
100
101
|
const dataRows = allRows.filter((r) => {
|
|
@@ -102,6 +103,12 @@ function deriveProgressFromRoadmap(roadmapContent) {
|
|
|
102
103
|
return /^\d/.test(phase) && !isSentinelPhaseId(phase);
|
|
103
104
|
});
|
|
104
105
|
totalPhases = dataRows.length > 0 ? dataRows.length : null;
|
|
106
|
+
// #5060: routed through the Phase Status Module's `parseRoadmapStatusCell`
|
|
107
|
+
// owner (rather than a local `/^complete$/i` regex) and counted over
|
|
108
|
+
// `dataRows` (not `allRows`) — a sentinel row's Status cell must never
|
|
109
|
+
// contribute to `completedPhases`.
|
|
110
|
+
const completed = dataRows.filter((r) => (0, phase_status_cjs_1.parseRoadmapStatusCell)(r['Status']) === phase_status_cjs_1.WIRE_STATUS.COMPLETE).length;
|
|
111
|
+
completedPhases = completed > 0 ? completed : null;
|
|
105
112
|
let totalPlansSum = 0;
|
|
106
113
|
for (const r of allRows) {
|
|
107
114
|
const cell = (r['Plans Complete'] ?? '').trim();
|
|
@@ -35,7 +35,7 @@ const frontmatterModule = require("./frontmatter.cjs");
|
|
|
35
35
|
const { extractFrontmatter } = frontmatterModule;
|
|
36
36
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
37
37
|
const planDependencyGraphModule = require("./plan-dependency-graph.cjs");
|
|
38
|
-
const { computeHaltPropagation, buildSummaryFileIndex, isSummaryFileHalted } = planDependencyGraphModule;
|
|
38
|
+
const { computeHaltPropagation, buildSummaryFileIndex, isSummaryFileHalted, isSummaryFileBlocked } = planDependencyGraphModule;
|
|
39
39
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
40
40
|
const roadmapParserModule = require("./roadmap-parser.cjs");
|
|
41
41
|
const { getMilestonePhaseFilter } = roadmapParserModule;
|
|
@@ -146,13 +146,15 @@ function listArchiveVersionDirs(cwd, wsOverride) {
|
|
|
146
146
|
}
|
|
147
147
|
return out;
|
|
148
148
|
}
|
|
149
|
-
function searchPhaseInDir(baseDir, relBase, normalized) {
|
|
149
|
+
function searchPhaseInDir(baseDir, relBase, normalized, convention) {
|
|
150
150
|
try {
|
|
151
151
|
const dirs = readSubdirectories(baseDir, true);
|
|
152
152
|
// #2528: canonical two-pass selection (exact token match, then the
|
|
153
153
|
// bare-integer leading-digit-run fallback) shared with the find-phase and
|
|
154
154
|
// phase-plan-index scans — see phase-id.cts::matchPhaseDirs.
|
|
155
|
-
|
|
155
|
+
// #4801: the convention is threaded (optional) so bracket-convention
|
|
156
|
+
// consumers get exact token matching here too.
|
|
157
|
+
const { matches, usedBareFallback } = matchPhaseDirs(dirs, normalized, convention);
|
|
156
158
|
if (matches.length === 0)
|
|
157
159
|
return null;
|
|
158
160
|
// #2237: fail loud when multiple directories match the same bare phase
|
|
@@ -176,6 +178,7 @@ function searchPhaseInDir(baseDir, relBase, normalized) {
|
|
|
176
178
|
halted_plans: [],
|
|
177
179
|
blocked_by: {},
|
|
178
180
|
runnable_plans: [],
|
|
181
|
+
ready_plans: [],
|
|
179
182
|
};
|
|
180
183
|
}
|
|
181
184
|
const match = matches[0];
|
|
@@ -208,12 +211,19 @@ function searchPhaseInDir(baseDir, relBase, normalized) {
|
|
|
208
211
|
const planIds = plans.map(p => p.replace('-PLAN.md', '').replace('PLAN.md', ''));
|
|
209
212
|
const planIdByLower = new Map(planIds.map(id => [id.toLowerCase(), id]));
|
|
210
213
|
const canonicalToPlanId = new Map(plans.map((p, i) => [extractCanonicalPlanId(p).toLowerCase(), planIds[i]]));
|
|
214
|
+
// #4628: raw depends_on per plan, so readiness can fail closed on a
|
|
215
|
+
// DROPPED edge (a dep token that resolves to nothing carries no evidence)
|
|
216
|
+
// instead of the resolution silently shrinking the dependency list.
|
|
217
|
+
const rawDeps = plans.map((p) => parsePlanDependsOn(phaseDir, p));
|
|
218
|
+
// #4628: completion evidence excludes status:blocked summaries (#3345) —
|
|
219
|
+
// a failure record is not completion, matching cmdPhasePlanIndex's count.
|
|
220
|
+
const completionEvidence = buildSummaryFileIndex(summaries.filter((f) => !isSummaryFileBlocked(node_path_1.default.join(phaseDir, f))), extractCanonicalPlanId);
|
|
211
221
|
const haltNodes = plans.map((p, i) => {
|
|
212
222
|
const planId = planIds[i];
|
|
213
223
|
const canonical = extractCanonicalPlanId(p);
|
|
214
224
|
const summaryFile = summaryFileByPlanId.get(planId) ?? summaryFileByPlanId.get(canonical);
|
|
215
225
|
const halted = summaryFile !== undefined && isSummaryFileHalted(node_path_1.default.join(phaseDir, summaryFile));
|
|
216
|
-
const resolvedDependsOn =
|
|
226
|
+
const resolvedDependsOn = rawDeps[i]
|
|
217
227
|
.map((dep) => {
|
|
218
228
|
const lower = dep.toLowerCase();
|
|
219
229
|
return planIdByLower.get(lower) ?? canonicalToPlanId.get(lower) ?? null;
|
|
@@ -226,6 +236,7 @@ function searchPhaseInDir(baseDir, relBase, normalized) {
|
|
|
226
236
|
const incompletePlanSet = new Set(incompletePlans);
|
|
227
237
|
const blockedByFiles = {};
|
|
228
238
|
const runnablePlans = [];
|
|
239
|
+
const readyPlans = [];
|
|
229
240
|
for (let i = 0; i < plans.length; i++) {
|
|
230
241
|
const p = plans[i];
|
|
231
242
|
if (!incompletePlanSet.has(p))
|
|
@@ -233,10 +244,16 @@ function searchPhaseInDir(baseDir, relBase, normalized) {
|
|
|
233
244
|
const causes = blockedBy.get(planIds[i]) ?? [];
|
|
234
245
|
if (causes.length > 0) {
|
|
235
246
|
blockedByFiles[p] = causes;
|
|
247
|
+
continue;
|
|
236
248
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
249
|
+
runnablePlans.push(p);
|
|
250
|
+
// #4628: DAG-ready on top of runnable — every dependency must have
|
|
251
|
+
// completion evidence (a matching, non-blocked SUMMARY) and no dropped
|
|
252
|
+
// edge: both readers of this contract fail closed identically.
|
|
253
|
+
const depsComplete = rawDeps[i].length === haltNodes[i].resolvedDependsOn.length &&
|
|
254
|
+
haltNodes[i].resolvedDependsOn.every((dep) => completionEvidence.has(dep));
|
|
255
|
+
if (depsComplete)
|
|
256
|
+
readyPlans.push(p);
|
|
240
257
|
}
|
|
241
258
|
return {
|
|
242
259
|
found: true,
|
|
@@ -259,19 +276,21 @@ function searchPhaseInDir(baseDir, relBase, normalized) {
|
|
|
259
276
|
halted_plans: haltedPlans,
|
|
260
277
|
blocked_by: blockedByFiles,
|
|
261
278
|
runnable_plans: runnablePlans,
|
|
279
|
+
ready_plans: readyPlans,
|
|
262
280
|
};
|
|
263
281
|
}
|
|
264
282
|
catch {
|
|
265
283
|
return null;
|
|
266
284
|
}
|
|
267
285
|
}
|
|
268
|
-
function findPhaseInternal(cwd, phase) {
|
|
286
|
+
function findPhaseInternal(cwd, phase, convention) {
|
|
269
287
|
if (!phase)
|
|
270
288
|
return null;
|
|
271
289
|
const phasesDir = node_path_1.default.join(planningDir(cwd), 'phases');
|
|
272
290
|
const normalized = normalizePhaseName(phase);
|
|
273
291
|
const relPhasesDir = toPosixPath(node_path_1.default.relative(cwd, phasesDir));
|
|
274
|
-
|
|
292
|
+
// #4801: convention threaded through to the matcher (see searchPhaseInDir).
|
|
293
|
+
const current = searchPhaseInDir(phasesDir, relPhasesDir, normalized, convention);
|
|
275
294
|
if (current)
|
|
276
295
|
return current;
|
|
277
296
|
// #2855: scope the archived-milestone fallback to the SAME workstream as the
|
|
@@ -285,7 +304,7 @@ function findPhaseInternal(cwd, phase) {
|
|
|
285
304
|
// getArchivedPhaseDirs via listArchiveVersionDirs (see its doc comment).
|
|
286
305
|
for (const { version, archivePath } of listArchiveVersionDirs(cwd)) {
|
|
287
306
|
const relBase = toPosixPath(node_path_1.default.relative(cwd, archivePath));
|
|
288
|
-
const result = searchPhaseInDir(archivePath, relBase, normalized);
|
|
307
|
+
const result = searchPhaseInDir(archivePath, relBase, normalized, convention);
|
|
289
308
|
if (result) {
|
|
290
309
|
result.archived = version;
|
|
291
310
|
return result;
|