@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
|
@@ -15,7 +15,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
15
15
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
16
|
};
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.NO_LOCAL_CONFIG_DIR_SENTINEL = void 0;
|
|
18
|
+
exports.NO_LOCAL_CONFIG_DIR_SENTINEL = exports.FALLBACK_HOST_BEHAVIORS = exports.LEGACY_NON_REGISTRY_RUNTIME_IDS = exports.LEGACY_NON_REGISTRY_RUNTIME_HOMES = exports.RetiredRuntimeError = exports.UnknownRuntimeError = exports.RETIRED_RUNTIME_IDS = void 0;
|
|
19
|
+
exports.isRetiredRuntimeId = isRetiredRuntimeId;
|
|
20
|
+
exports.assertNotRetiredRuntime = assertNotRetiredRuntime;
|
|
21
|
+
exports.isKnownRuntimeId = isKnownRuntimeId;
|
|
22
|
+
exports.assertKnownRuntime = assertKnownRuntime;
|
|
23
|
+
exports.hostBehaviorsFor = hostBehaviorsFor;
|
|
19
24
|
exports.canonicalizeRuntimeName = canonicalizeRuntimeName;
|
|
20
25
|
exports.resolveRuntimeNameFromCandidates = resolveRuntimeNameFromCandidates;
|
|
21
26
|
exports.getProjectInstructionFile = getProjectInstructionFile;
|
|
@@ -23,9 +28,237 @@ exports.getDirName = getDirName;
|
|
|
23
28
|
exports.getRuntimeLabel = getRuntimeLabel;
|
|
24
29
|
exports.getGlobalConfigHomeFragment = getGlobalConfigHomeFragment;
|
|
25
30
|
exports.runtimeFlags = runtimeFlags;
|
|
26
|
-
exports.getRuntimeNewProjectCommand = getRuntimeNewProjectCommand;
|
|
27
31
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
28
32
|
const node_path_1 = __importDefault(require("node:path"));
|
|
33
|
+
/**
|
|
34
|
+
* Runtime ids that GSD deliberately RETIRED, as opposed to ids it has simply
|
|
35
|
+
* never heard of. The distinction is load-bearing: an unknown id degrades to a
|
|
36
|
+
* safe cross-agent default on purpose (the #1529 contract in
|
|
37
|
+
* `getProjectInstructionFile` below), because GSD cannot know what a future
|
|
38
|
+
* runtime wants. A retired id is the opposite case — there is a recorded
|
|
39
|
+
* decision that it is gone and a named successor to point at, so resolving it
|
|
40
|
+
* to a DIFFERENT product's label and config home is a silent wrong answer.
|
|
41
|
+
*
|
|
42
|
+
* Measured before this guard existed: `getGlobalConfigDir('gemini')` and
|
|
43
|
+
* `getGlobalConfigDir('claude')` returned byte-identical paths, so asking for a
|
|
44
|
+
* runtime Google sunset on 2026-06-18 wrote into Claude Code's config home and
|
|
45
|
+
* labelled the install "Claude Code".
|
|
46
|
+
*
|
|
47
|
+
* Same table shape as `RETIRED_RUNTIMES` in
|
|
48
|
+
* `scripts/lint-retired-runtime-name.cjs` (#4753), which guards PROSE at build
|
|
49
|
+
* time while this guards IDS at runtime. They are deliberately NOT shared code
|
|
50
|
+
* — coupling them would make a build-time lint depend on compiled `src/` output
|
|
51
|
+
* it does not otherwise need — so a parity test asserts the two sets agree
|
|
52
|
+
* (CLAUDE.md, Generative Fix Divergence).
|
|
53
|
+
*/
|
|
54
|
+
const RETIRED_RUNTIME_DETAILS = new Map([
|
|
55
|
+
['gem' + 'ini', { successor: 'Antigravity', retiredBy: '#1928', sunset: '2026-06-18' }],
|
|
56
|
+
]);
|
|
57
|
+
/**
|
|
58
|
+
* Normalise a candidate id for retirement matching: NFKC-fold, lowercase, and
|
|
59
|
+
* drop every non-alphanumeric character.
|
|
60
|
+
*
|
|
61
|
+
* Folding the separators is what makes `gemini-cli`, `gemini_cli`,
|
|
62
|
+
* `gemini.cli` and `geminicli` one key instead of four near-misses a reviewer
|
|
63
|
+
* has to find one at a time — and NFKC folds the full-width `gemini` a CJK
|
|
64
|
+
* keyboard produces. It stays MEMBERSHIP matching, not a prefix or substring
|
|
65
|
+
* test: `gemini-2.5-pro` folds to `gemini25pro` and `gemini-3.1-pro-preview`
|
|
66
|
+
* to `gemini31propreview`, neither of which is a member, so Google's live
|
|
67
|
+
* model ids — part of Antigravity's real on-disk contract — are untouched.
|
|
68
|
+
*
|
|
69
|
+
* Homoglyph folding is deliberately NOT attempted. A Cyrillic `і` in place of
|
|
70
|
+
* `i` would slip through, and that is accepted: these values arrive from argv
|
|
71
|
+
* and env, which are trusted inputs here, and a mapping broad enough to catch
|
|
72
|
+
* deliberate homoglyphs would start catching legitimate ids.
|
|
73
|
+
*/
|
|
74
|
+
function normalizeForRetirementMatch(value) {
|
|
75
|
+
return value.normalize('NFKC').toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Every spelling that names a retired runtime, mapped to its canonical id.
|
|
79
|
+
* A Map, not an object literal: an object literal indexed by a computed key
|
|
80
|
+
* resolves INHERITED properties, so `'__proto__'` and `'constructor'` were
|
|
81
|
+
* truthy and threw with every field `undefined` — while `isRetiredRuntimeId`,
|
|
82
|
+
* which already went through a Set, correctly answered false for the same
|
|
83
|
+
* input. Two guards disagreeing about one id is worse than either answer.
|
|
84
|
+
* A Map has no prototype keys, so the hazard is structural, not patched.
|
|
85
|
+
*/
|
|
86
|
+
const RETIRED_RUNTIME_SPELLINGS = new Map(Array.from(RETIRED_RUNTIME_DETAILS.keys()).flatMap((id) => [
|
|
87
|
+
[normalizeForRetirementMatch(id), id],
|
|
88
|
+
[normalizeForRetirementMatch(`${id}-cli`), id],
|
|
89
|
+
]));
|
|
90
|
+
/**
|
|
91
|
+
* The canonical retired runtime ids, lowercase. Deliberately the canonical ids
|
|
92
|
+
* ONLY, not their alias spellings, so the parity assertion against
|
|
93
|
+
* `scripts/lint-retired-runtime-name.cjs`'s `RETIRED_RUNTIMES` compares like
|
|
94
|
+
* with like.
|
|
95
|
+
*/
|
|
96
|
+
exports.RETIRED_RUNTIME_IDS = new Set(RETIRED_RUNTIME_DETAILS.keys());
|
|
97
|
+
/**
|
|
98
|
+
* Error thrown when a non-empty runtime id that is neither registered nor a
|
|
99
|
+
* known non-registry host reaches a descriptor accessor (ADR-5057 §5, #5169).
|
|
100
|
+
* Before this, such an id silently resolved to Claude Code's values.
|
|
101
|
+
*/
|
|
102
|
+
class UnknownRuntimeError extends Error {
|
|
103
|
+
code = 'GSD_UNKNOWN_RUNTIME';
|
|
104
|
+
runtimeId;
|
|
105
|
+
constructor(runtimeId) {
|
|
106
|
+
super(`Runtime "${runtimeId}" is not registered in the capability registry. `
|
|
107
|
+
+ 'Refusing to resolve it, because the previous behaviour silently returned Claude Code\'s values.');
|
|
108
|
+
this.name = 'UnknownRuntimeError';
|
|
109
|
+
this.runtimeId = runtimeId;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
exports.UnknownRuntimeError = UnknownRuntimeError;
|
|
113
|
+
/** Error thrown when a retired runtime id reaches a resolution accessor. */
|
|
114
|
+
class RetiredRuntimeError extends Error {
|
|
115
|
+
code = 'GSD_RETIRED_RUNTIME';
|
|
116
|
+
runtimeId;
|
|
117
|
+
constructor(runtimeId, detail) {
|
|
118
|
+
super(`Runtime "${runtimeId}" was retired by ${detail.retiredBy} (sunset ${detail.sunset}); `
|
|
119
|
+
+ `use "${detail.successor}" instead. Refusing to resolve it, because the previous `
|
|
120
|
+
+ `behaviour silently returned Claude Code's values.`);
|
|
121
|
+
this.name = 'RetiredRuntimeError';
|
|
122
|
+
this.runtimeId = runtimeId;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
exports.RetiredRuntimeError = RetiredRuntimeError;
|
|
126
|
+
/**
|
|
127
|
+
* Is `runtime` a deliberately retired runtime, under any of its spellings?
|
|
128
|
+
* Shares one normaliser and one table with `assertNotRetiredRuntime`, so the
|
|
129
|
+
* predicate and the assertion can never disagree.
|
|
130
|
+
*/
|
|
131
|
+
function isRetiredRuntimeId(runtime) {
|
|
132
|
+
if (typeof runtime !== 'string')
|
|
133
|
+
return false;
|
|
134
|
+
return RETIRED_RUNTIME_SPELLINGS.has(normalizeForRetirementMatch(runtime));
|
|
135
|
+
}
|
|
136
|
+
/** Throw if `runtime` names a retired runtime. No-op otherwise. */
|
|
137
|
+
function assertNotRetiredRuntime(runtime) {
|
|
138
|
+
if (typeof runtime !== 'string')
|
|
139
|
+
return;
|
|
140
|
+
const id = RETIRED_RUNTIME_SPELLINGS.get(normalizeForRetirementMatch(runtime));
|
|
141
|
+
if (id === undefined)
|
|
142
|
+
return;
|
|
143
|
+
const detail = RETIRED_RUNTIME_DETAILS.get(id);
|
|
144
|
+
if (detail === undefined)
|
|
145
|
+
return;
|
|
146
|
+
throw new RetiredRuntimeError(id, detail);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Legacy runtime ids that have a genuine, dedicated resolution branch in
|
|
150
|
+
* `runtime-homes.cts` but no capability-registry descriptor (#3024). They are
|
|
151
|
+
* KNOWN ids: every accessor resolves them rather than refusing. Enumerated by
|
|
152
|
+
* hand and MUST stay in lockstep with `getGlobalConfigDir`'s hardcoded
|
|
153
|
+
* branches — add an id only after confirming it has a real dedicated branch.
|
|
154
|
+
*/
|
|
155
|
+
exports.LEGACY_NON_REGISTRY_RUNTIME_HOMES = Object.freeze({
|
|
156
|
+
// Grok's agents home: `GROK_AGENTS_HOME`, else `~/.agents` (dir = path segments under $HOME).
|
|
157
|
+
grok: Object.freeze({ env: 'GROK_AGENTS_HOME', dir: Object.freeze(['.agents']) }),
|
|
158
|
+
});
|
|
159
|
+
exports.LEGACY_NON_REGISTRY_RUNTIME_IDS = new Set(Object.keys(exports.LEGACY_NON_REGISTRY_RUNTIME_HOMES));
|
|
160
|
+
/** The capability registry's `runtimes` map, or `null` when it fails to load. */
|
|
161
|
+
function loadRegistryRuntimes() {
|
|
162
|
+
try {
|
|
163
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
164
|
+
const reg = require('./capability-registry.cjs');
|
|
165
|
+
return (reg && reg.runtimes) || null;
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* True when `runtime` is a registered runtime id (own property of the registry
|
|
173
|
+
* `runtimes` map — never an inherited key such as `__proto__`/`constructor`)
|
|
174
|
+
* or one of {@link LEGACY_NON_REGISTRY_RUNTIME_IDS}. Raw-id match: no trimming,
|
|
175
|
+
* no case folding, no alias expansion.
|
|
176
|
+
*/
|
|
177
|
+
function isKnownRuntimeId(runtime) {
|
|
178
|
+
if (typeof runtime !== 'string' || runtime.length === 0)
|
|
179
|
+
return false;
|
|
180
|
+
const runtimes = loadRegistryRuntimes();
|
|
181
|
+
if (runtimes && Object.prototype.hasOwnProperty.call(runtimes, runtime))
|
|
182
|
+
return true;
|
|
183
|
+
return exports.LEGACY_NON_REGISTRY_RUNTIME_IDS.has(runtime);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* The ONE refusal every descriptor accessor shares (ADR-5057 §5, #5169).
|
|
187
|
+
* No-op for an absent id (`''`, non-string): that is the documented
|
|
188
|
+
* "no runtime selected" generic path. A retired id throws
|
|
189
|
+
* {@link RetiredRuntimeError}; any other non-empty id that is not known throws
|
|
190
|
+
* {@link UnknownRuntimeError} instead of silently resolving to Claude Code's
|
|
191
|
+
* values. When the registry itself failed to load, unknown-ness cannot be
|
|
192
|
+
* proven, so the check degrades to a no-op (the #338 floor in
|
|
193
|
+
* {@link hostBehaviorsFor} still protects the reference host).
|
|
194
|
+
*/
|
|
195
|
+
function assertKnownRuntime(runtime) {
|
|
196
|
+
if (typeof runtime !== 'string' || runtime.length === 0)
|
|
197
|
+
return;
|
|
198
|
+
assertNotRetiredRuntime(runtime);
|
|
199
|
+
if (loadRegistryRuntimes() === null)
|
|
200
|
+
return;
|
|
201
|
+
if (!isKnownRuntimeId(runtime))
|
|
202
|
+
throw new UnknownRuntimeError(runtime);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* The #338-privacy fail-safe floor: host behaviors for the two hosts whose
|
|
206
|
+
* generic fallthrough would be WRONG if the registry failed to load. Moved
|
|
207
|
+
* here from `bin/install.js` so the registry-load-failure degrade lives in the
|
|
208
|
+
* single host-behaviors accessor instead of one of three copies (#5169).
|
|
209
|
+
*/
|
|
210
|
+
exports.FALLBACK_HOST_BEHAVIORS = Object.freeze({
|
|
211
|
+
claude: Object.freeze({
|
|
212
|
+
settingsFileByScope: Object.freeze({ local: 'settings.local.json', global: 'settings.json' }),
|
|
213
|
+
permissionsSchema: 'claude',
|
|
214
|
+
sourceMarkerFile: '.gsd-source',
|
|
215
|
+
hyphenNameAgentBody: true,
|
|
216
|
+
legacyCommandsGsdInstallMigration: true,
|
|
217
|
+
legacyCommandsGsdUninstall: 'global',
|
|
218
|
+
}),
|
|
219
|
+
// antigravity's global config dir is resolved dynamically (env-overridable,
|
|
220
|
+
// multi-segment); this floor keeps that routing intact if the registry fails
|
|
221
|
+
// to load instead of falling through to the wrong '.claude' fragment (#2096).
|
|
222
|
+
antigravity: Object.freeze({ globalDirResolver: 'antigravity' }),
|
|
223
|
+
});
|
|
224
|
+
/**
|
|
225
|
+
* The single accessor for a runtime's host behaviors
|
|
226
|
+
* (capabilities/<runtime>/capability.json -> runtime.hostBehaviors). Replaces
|
|
227
|
+
* the three private `_hostBehaviors` copies in `bin/install.js`,
|
|
228
|
+
* `install-engine.cts` and `runtime-artifact-conversion.cts`.
|
|
229
|
+
*
|
|
230
|
+
* - absent id (`''`, non-string) → `{}` (generic path).
|
|
231
|
+
* - registered id → the descriptor's `hostBehaviors` (or `{}` when it declares
|
|
232
|
+
* none).
|
|
233
|
+
* - known non-registry id (`grok`) → `{}`.
|
|
234
|
+
* - registry failed to load → the #338 floor for the ids it covers, else `{}`.
|
|
235
|
+
* - any other id (unregistered, retired, a prototype key) → `{}`: no declared
|
|
236
|
+
* behaviors, which is the GENERIC path — never Claude Code's behaviors.
|
|
237
|
+
*
|
|
238
|
+
* Unlike the path/label accessors (`getDirName`, `getGlobalConfigDir`, …), whose
|
|
239
|
+
* fallthrough answer is Claude Code's value and therefore a silent wrong answer
|
|
240
|
+
* (#4632), an absent behavior is the correct answer for a label GSD does not
|
|
241
|
+
* know — and this accessor is read by guard and hook code on user-supplied
|
|
242
|
+
* runtime labels (stale config, a retired id), where a throw would crash the
|
|
243
|
+
* session rather than skip a behavior. ADR-5057 §5 Phase 10 amendment.
|
|
244
|
+
*
|
|
245
|
+
* `registry` is injectable so the load-failure branch is unit-testable.
|
|
246
|
+
*/
|
|
247
|
+
function hostBehaviorsFor(runtime, registry) {
|
|
248
|
+
if (typeof runtime !== 'string' || runtime.length === 0)
|
|
249
|
+
return {};
|
|
250
|
+
const floor = () => Object.prototype.hasOwnProperty.call(exports.FALLBACK_HOST_BEHAVIORS, runtime)
|
|
251
|
+
? exports.FALLBACK_HOST_BEHAVIORS[runtime]
|
|
252
|
+
: {};
|
|
253
|
+
const runtimes = registry === undefined ? loadRegistryRuntimes() : (registry && registry.runtimes) || null;
|
|
254
|
+
if (runtimes === null)
|
|
255
|
+
return floor();
|
|
256
|
+
if (Object.prototype.hasOwnProperty.call(runtimes, runtime)) {
|
|
257
|
+
const declared = runtimes[runtime]?.runtime?.hostBehaviors;
|
|
258
|
+
return declared ? declared : floor();
|
|
259
|
+
}
|
|
260
|
+
return {};
|
|
261
|
+
}
|
|
29
262
|
const FALLBACK_ALIASES = {
|
|
30
263
|
claude: ['claude', 'claude-code', 'claude-cli'],
|
|
31
264
|
opencode: ['opencode', 'open-code', 'opencode-cli'],
|
|
@@ -145,6 +378,7 @@ function resolveRuntimeNameFromCandidates(...candidates) {
|
|
|
145
378
|
* avoid a circular dependency at module load.
|
|
146
379
|
*/
|
|
147
380
|
function getProjectInstructionFile(runtime) {
|
|
381
|
+
assertNotRetiredRuntime(runtime);
|
|
148
382
|
const canonical = canonicalizeRuntimeName(runtime);
|
|
149
383
|
if (canonical === 'claude')
|
|
150
384
|
return '.claude/CLAUDE.md';
|
|
@@ -198,6 +432,9 @@ exports.NO_LOCAL_CONFIG_DIR_SENTINEL = '(no-local-config-dir)';
|
|
|
198
432
|
* compatibility spine had no production consumer at all.
|
|
199
433
|
*/
|
|
200
434
|
function getDirName(runtime) {
|
|
435
|
+
// Same silent-wrong-answer class as the four accessors AC#1 names: this
|
|
436
|
+
// returned '.claude' for a retired id, and it feeds runtimeConfigDir.
|
|
437
|
+
assertKnownRuntime(runtime);
|
|
201
438
|
if (!runtime)
|
|
202
439
|
return '.claude';
|
|
203
440
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
@@ -268,6 +505,7 @@ const RUNTIME_LABELS = {
|
|
|
268
505
|
* 'Claude Code'. Sibling to `getDirName`; pure (no I/O).
|
|
269
506
|
*/
|
|
270
507
|
function getRuntimeLabel(runtime) {
|
|
508
|
+
assertKnownRuntime(runtime);
|
|
271
509
|
if (!runtime)
|
|
272
510
|
return 'Claude Code';
|
|
273
511
|
const label = RUNTIME_LABELS[runtime];
|
|
@@ -323,6 +561,7 @@ const GLOBAL_CONFIG_HOME_FRAGMENTS = {
|
|
|
323
561
|
* dynamically). Pure: no I/O. Sibling to `getDirName` / `getRuntimeLabel`.
|
|
324
562
|
*/
|
|
325
563
|
function getGlobalConfigHomeFragment(runtime) {
|
|
564
|
+
assertKnownRuntime(runtime);
|
|
326
565
|
if (!runtime)
|
|
327
566
|
return DEFAULT_CONFIG_HOME_FRAGMENT;
|
|
328
567
|
const frag = GLOBAL_CONFIG_HOME_FRAGMENTS[runtime];
|
|
@@ -368,22 +607,8 @@ function runtimeFlags(runtime) {
|
|
|
368
607
|
}
|
|
369
608
|
return Object.freeze(flags);
|
|
370
609
|
}
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
* message (ADR-1239 Phase B / #1679 AC2). Pure: no I/O.
|
|
377
|
-
*/
|
|
378
|
-
const DEFAULT_NEW_PROJECT_COMMAND = '/gsd-new-project';
|
|
379
|
-
const RUNTIME_NEW_PROJECT_COMMANDS = {
|
|
380
|
-
codex: '$gsd-new-project',
|
|
381
|
-
cursor: 'gsd-new-project (mention the skill name)',
|
|
382
|
-
kimi: '/skill:gsd-new-project',
|
|
383
|
-
};
|
|
384
|
-
function getRuntimeNewProjectCommand(runtime) {
|
|
385
|
-
if (!runtime)
|
|
386
|
-
return DEFAULT_NEW_PROJECT_COMMAND;
|
|
387
|
-
const c = RUNTIME_NEW_PROJECT_COMMANDS[runtime];
|
|
388
|
-
return typeof c === 'string' && c.length > 0 ? c : DEFAULT_NEW_PROJECT_COMMAND;
|
|
389
|
-
}
|
|
610
|
+
// The `/gsd-new-project` next-step command is no longer a per-runtime table
|
|
611
|
+
// here: it is generated from the runtime's registered trigger surface by
|
|
612
|
+
// `resolveAdvertisedNewProject` (runtime-artifact-layout.cts, #5215, ADR-5057
|
|
613
|
+
// §5 Phase 12), so what the installer advertises cannot differ from what a
|
|
614
|
+
// runtime registered.
|
|
@@ -34,6 +34,7 @@ exports._setInstallRuntimeMarkerForTests = _setInstallRuntimeMarkerForTests;
|
|
|
34
34
|
exports._resetInstallRuntimeMarkerCacheForTests = _resetInstallRuntimeMarkerCacheForTests;
|
|
35
35
|
exports.resolveExplicitRuntime = resolveExplicitRuntime;
|
|
36
36
|
exports.resolveRuntime = resolveRuntime;
|
|
37
|
+
exports.resolveActiveRuntime = resolveActiveRuntime;
|
|
37
38
|
exports.formatGsdSlashFor = formatGsdSlashFor;
|
|
38
39
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
39
40
|
const node_path_1 = __importDefault(require("node:path"));
|
|
@@ -148,31 +149,36 @@ function resolveExplicitRuntime(projectDir, env = process.env) {
|
|
|
148
149
|
const envRuntime = (0, runtime_name_policy_cjs_1.resolveRuntimeNameFromCandidates)(env['GSD_RUNTIME']);
|
|
149
150
|
if (envRuntime)
|
|
150
151
|
return envRuntime;
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
// would mutate the project file just to read the runtime name. We only
|
|
156
|
-
// need the literal `runtime:` value, so a plain JSON read is sufficient
|
|
157
|
-
// and side-effect-free.
|
|
158
|
-
const configPath = node_path_1.default.join(projectDir, '.planning', 'config.json');
|
|
159
|
-
if (node_fs_1.default.existsSync(configPath)) {
|
|
160
|
-
const raw = node_fs_1.default.readFileSync(configPath, 'utf-8');
|
|
161
|
-
const parsed = JSON.parse(raw);
|
|
162
|
-
if (parsed && typeof parsed === 'object' && 'runtime' in parsed) {
|
|
163
|
-
const configRuntime = (0, runtime_name_policy_cjs_1.resolveRuntimeNameFromCandidates)(parsed['runtime']);
|
|
164
|
-
if (configRuntime)
|
|
165
|
-
return configRuntime;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
catch {
|
|
170
|
-
// Fall through to default — a missing/broken config must not crash
|
|
171
|
-
// runtime output formatting.
|
|
172
|
-
}
|
|
173
|
-
}
|
|
152
|
+
const config = readProjectConfig(projectDir);
|
|
153
|
+
const configRuntime = (0, runtime_name_policy_cjs_1.resolveRuntimeNameFromCandidates)(config ? config['runtime'] : undefined);
|
|
154
|
+
if (configRuntime)
|
|
155
|
+
return configRuntime;
|
|
174
156
|
return null;
|
|
175
157
|
}
|
|
158
|
+
/**
|
|
159
|
+
* Read `<projectDir>/.planning/config.json` as a plain object, or `null` when
|
|
160
|
+
* there is no project, no file, or it is unreadable or not an object.
|
|
161
|
+
*
|
|
162
|
+
* Read directly (not via loadConfig). loadConfig has a side effect of
|
|
163
|
+
* normalizing and re-writing legacy keys back to disk, which would mutate the
|
|
164
|
+
* project file just to read the runtime name. A plain JSON read is sufficient
|
|
165
|
+
* and side-effect-free. A missing or broken config must not crash runtime
|
|
166
|
+
* output formatting, so every failure degrades to `null`.
|
|
167
|
+
*/
|
|
168
|
+
function readProjectConfig(projectDir) {
|
|
169
|
+
if (!projectDir)
|
|
170
|
+
return null;
|
|
171
|
+
try {
|
|
172
|
+
const configPath = node_path_1.default.join(projectDir, '.planning', 'config.json');
|
|
173
|
+
if (!node_fs_1.default.existsSync(configPath))
|
|
174
|
+
return null;
|
|
175
|
+
const parsed = JSON.parse(node_fs_1.default.readFileSync(configPath, 'utf-8'));
|
|
176
|
+
return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : null;
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
176
182
|
/**
|
|
177
183
|
* Resolve the effective runtime for a project directory.
|
|
178
184
|
*
|
|
@@ -195,13 +201,24 @@ function resolveExplicitRuntime(projectDir, env = process.env) {
|
|
|
195
201
|
* @returns the resolved runtime name
|
|
196
202
|
*/
|
|
197
203
|
function resolveRuntime(projectDir) {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
204
|
+
// The same chain `resolveActiveRuntime` owns, fed by a project directory:
|
|
205
|
+
// one implementation, so the two entry points cannot drift (#5169).
|
|
206
|
+
return resolveActiveRuntime(readProjectConfig(projectDir));
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Resolve the effective runtime from an ALREADY-LOADED config object — the one
|
|
210
|
+
* chain every consumer of "which runtime is this install" shares (#5169,
|
|
211
|
+
* ADR-5057 §5, #4690):
|
|
212
|
+
*
|
|
213
|
+
* env.GSD_RUNTIME > config.runtime > install marker > 'claude'
|
|
214
|
+
*
|
|
215
|
+
* Canonicalized, so an alias or case variant (`claude-code`, `Claude`) cannot
|
|
216
|
+
* defeat a downstream comparison. `resolveRuntime` above is the same chain for
|
|
217
|
+
* callers that hold a project directory rather than a parsed config; the marker
|
|
218
|
+
* is read through `readInstallRuntimeMarker` in both.
|
|
219
|
+
*/
|
|
220
|
+
function resolveActiveRuntime(config, env = process.env) {
|
|
221
|
+
return (0, runtime_name_policy_cjs_1.resolveRuntimeNameFromCandidates)(env['GSD_RUNTIME'], config ? config['runtime'] : undefined, readInstallRuntimeMarker()) || 'claude';
|
|
205
222
|
}
|
|
206
223
|
/**
|
|
207
224
|
* Convenience: format using the runtime resolved from a project directory.
|
|
@@ -64,6 +64,8 @@ const node_fs_1 = __importDefault(require("node:fs"));
|
|
|
64
64
|
// at load time and become un-mockable.
|
|
65
65
|
const node_child_process_1 = __importDefault(require("node:child_process"));
|
|
66
66
|
const pattern_cjs_1 = require("./pattern.cjs");
|
|
67
|
+
const frontmatter_fence_cjs_1 = require("./frontmatter-fence.cjs");
|
|
68
|
+
const runtime_name_policy_cjs_1 = require("./runtime-name-policy.cjs");
|
|
67
69
|
/**
|
|
68
70
|
* Convert a filesystem path to POSIX form (forward slashes) by translating the
|
|
69
71
|
* platform-native separator. Single seam for native→POSIX conversion.
|
|
@@ -146,7 +148,10 @@ function formatHookCommandForRuntime(command, opts = {}) {
|
|
|
146
148
|
// path missed this guard and reintroduced the #166/#377 failure (#580).
|
|
147
149
|
function shellHookOmitsBashRunner({ platform, runtime = 'generic', isShellHook = false } = {}) {
|
|
148
150
|
const p = platform ?? process.platform;
|
|
149
|
-
|
|
151
|
+
// #5169: descriptor-declared (`hostBehaviors.omitBashRunnerOnWindows`). The
|
|
152
|
+
// `'generic'` default and any other non-registered label declares nothing, so
|
|
153
|
+
// it never omits the runner, exactly as before.
|
|
154
|
+
return p === 'win32' && isShellHook && (0, runtime_name_policy_cjs_1.hostBehaviorsFor)(runtime).omitBashRunnerOnWindows === true;
|
|
150
155
|
}
|
|
151
156
|
// Builds the command string for a local-install managed `.sh` hook. Mirrors the
|
|
152
157
|
// global buildHookCommand path but uses the $CLAUDE_PROJECT_DIR-anchored prefix
|
|
@@ -263,6 +268,7 @@ const MANAGED_HOOK_COMMAND_BASENAMES_BY_SURFACE = {
|
|
|
263
268
|
'gsd-session-state.sh',
|
|
264
269
|
'gsd-validate-commit.sh',
|
|
265
270
|
'gsd-phase-boundary.sh',
|
|
271
|
+
'gsd-graphify-update.sh',
|
|
266
272
|
// #3662: same three guards as MANAGED_HOOK_BASENAMES_BY_SURFACE above —
|
|
267
273
|
// their absence here meant isManagedHookCommand never recognized them, so
|
|
268
274
|
// the settings.json→settings.local.json migration filter (and uninstall
|
|
@@ -1032,16 +1038,39 @@ function probeTty(opts = {}) {
|
|
|
1032
1038
|
}
|
|
1033
1039
|
}
|
|
1034
1040
|
// ─── Platform file I/O ────────────────────────────────────────────────────────
|
|
1041
|
+
/**
|
|
1042
|
+
* How many leading lines of LF-only `text` are its closed YAML frontmatter block (opening
|
|
1043
|
+
* fence through closing fence), or 0 when there is none (an unterminated block is not
|
|
1044
|
+
* frontmatter). The fence is `locateFrontmatterFence`'s — the one owner the frontmatter reader
|
|
1045
|
+
* and writer (`frontmatter.cts`) also read — so the normalizer skips exactly the block every
|
|
1046
|
+
* reader sees (found while implementing #5105: this was a private mirror of the reader's
|
|
1047
|
+
* fence rule, because `frontmatter.cts` imports this module, and the two drifted).
|
|
1048
|
+
*/
|
|
1049
|
+
function leadingFrontmatterLineCount(text) {
|
|
1050
|
+
const fence = (0, frontmatter_fence_cjs_1.locateFrontmatterFence)(text);
|
|
1051
|
+
if (!fence || !fence.closed)
|
|
1052
|
+
return 0;
|
|
1053
|
+
// The lines before the closing fence, plus the closing fence line itself.
|
|
1054
|
+
return text.slice(0, fence.closingStart).split('\n').length;
|
|
1055
|
+
}
|
|
1035
1056
|
function _normalizeMd(content) {
|
|
1036
1057
|
if (!content || typeof content !== 'string')
|
|
1037
1058
|
return content;
|
|
1038
1059
|
let text = content.replace(/\r\n/g, '\n');
|
|
1039
1060
|
const lines = text.split('\n');
|
|
1061
|
+
// The frontmatter block is YAML, not markdown: its lines are published exactly as written.
|
|
1062
|
+
// A `# comment` is not a heading, and a blank line inserted into a multi-line quoted scalar
|
|
1063
|
+
// or removed from a block scalar changes the value (found while implementing #5105).
|
|
1064
|
+
const frontmatterLines = leadingFrontmatterLineCount(text);
|
|
1040
1065
|
const result = [];
|
|
1041
1066
|
const fenceRegex = /^```/;
|
|
1042
1067
|
const insideFence = new Array(lines.length);
|
|
1043
1068
|
let fenceOpen = false;
|
|
1044
1069
|
for (let i = 0; i < lines.length; i++) {
|
|
1070
|
+
if (i < frontmatterLines) {
|
|
1071
|
+
insideFence[i] = false;
|
|
1072
|
+
continue;
|
|
1073
|
+
}
|
|
1045
1074
|
if (fenceRegex.test(lines[i].trimEnd())) {
|
|
1046
1075
|
if (fenceOpen) {
|
|
1047
1076
|
insideFence[i] = false;
|
|
@@ -1058,6 +1087,10 @@ function _normalizeMd(content) {
|
|
|
1058
1087
|
}
|
|
1059
1088
|
for (let i = 0; i < lines.length; i++) {
|
|
1060
1089
|
const line = lines[i];
|
|
1090
|
+
if (i < frontmatterLines) {
|
|
1091
|
+
result.push(line);
|
|
1092
|
+
continue;
|
|
1093
|
+
}
|
|
1061
1094
|
const prev = i > 0 ? lines[i - 1] : '';
|
|
1062
1095
|
const prevTrimmed = prev.trimEnd();
|
|
1063
1096
|
const trimmed = line.trimEnd();
|
|
@@ -1068,12 +1101,15 @@ function _normalizeMd(content) {
|
|
|
1068
1101
|
if (i === 0 || !insideFence[i - 1])
|
|
1069
1102
|
result.push('');
|
|
1070
1103
|
}
|
|
1071
|
-
//
|
|
1072
|
-
//
|
|
1073
|
-
//
|
|
1074
|
-
//
|
|
1075
|
-
|
|
1076
|
-
|
|
1104
|
+
// No "separate a list from a preceding paragraph" rule (#3854, #4725).
|
|
1105
|
+
// This pass re-normalizes the ENTIRE document on every .md write, so an
|
|
1106
|
+
// inserted blank before a bullet whose previous line is ordinary prose
|
|
1107
|
+
// reflowed text the command never touched (converting tight lists to
|
|
1108
|
+
// loose ones); #3854 first guarded the indented-continuation predecessor,
|
|
1109
|
+
// #4725 removed the rule outright. A paragraph→list transition stays
|
|
1110
|
+
// exactly as the author wrote it; a heading→list separation still comes
|
|
1111
|
+
// from the after-heading rule below. The after-a-bullet rule at the end
|
|
1112
|
+
// of this loop is a different transition (list→prose) and is unaffected.
|
|
1077
1113
|
result.push(line);
|
|
1078
1114
|
if (/^#{1,6}\s/.test(trimmed) && i < lines.length - 1 && (lines[i + 1] ?? '').trimEnd() !== '')
|
|
1079
1115
|
result.push('');
|
|
@@ -1085,8 +1121,11 @@ function _normalizeMd(content) {
|
|
|
1085
1121
|
result.push('');
|
|
1086
1122
|
}
|
|
1087
1123
|
}
|
|
1124
|
+
// The frontmatter lines are `result`'s first entries, unchanged; the blank-run collapse
|
|
1125
|
+
// applies from the line ending that closes the block onward.
|
|
1126
|
+
const head = result.slice(0, frontmatterLines).join('\n');
|
|
1088
1127
|
text = result.join('\n');
|
|
1089
|
-
text = text.replace(/\n{3,}/g, '\n\n');
|
|
1128
|
+
text = head + text.slice(head.length).replace(/\n{3,}/g, '\n\n');
|
|
1090
1129
|
text = text.replace(/\n*$/, '\n');
|
|
1091
1130
|
return text;
|
|
1092
1131
|
}
|
|
@@ -55,7 +55,7 @@ const planningWorkspace = require("./planning-workspace.cjs");
|
|
|
55
55
|
const { planningPaths } = planningWorkspace;
|
|
56
56
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
57
57
|
const frontmatter = require("./frontmatter.cjs");
|
|
58
|
-
const { extractFrontmatter } = frontmatter;
|
|
58
|
+
const { extractFrontmatter, frontmatterBlock } = frontmatter;
|
|
59
59
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- phase-lifecycle.cjs is an export= CommonJS module
|
|
60
60
|
const phaseLifecycle = require("./phase-lifecycle.cjs");
|
|
61
61
|
const { deriveProgressFromRoadmap } = phaseLifecycle;
|
|
@@ -71,6 +71,10 @@ const { readStateHeadFreshness } = stateMod;
|
|
|
71
71
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
72
72
|
const unusableInput = require("./unusable-input.cjs");
|
|
73
73
|
const { warnUnusableInput, UNUSABLE_REASON } = unusableInput;
|
|
74
|
+
// #5118: the verification-status owner's frontmatter-only report check.
|
|
75
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
76
|
+
const verificationMod = require("./verification.cjs");
|
|
77
|
+
const { findVerificationStatusError } = verificationMod;
|
|
74
78
|
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
75
79
|
/**
|
|
76
80
|
* Staleness threshold for idle-stranded detection. A clean tree whose last
|
|
@@ -285,11 +289,20 @@ function detectVerifyFailed(cwd, currentPhaseRaw) {
|
|
|
285
289
|
catch {
|
|
286
290
|
return false;
|
|
287
291
|
}
|
|
292
|
+
// #5118: this phase's VERIFICATION report `status` is judged by its owner
|
|
293
|
+
// (src/verification.cts, the same frontmatter-only, containment-checked
|
|
294
|
+
// locator every reader shares) — an out-of-set value is the owner's hard
|
|
295
|
+
// error here as at every other reader, never a silent "not failed". The
|
|
296
|
+
// body `STATUS:` marker scan below is this probe's own signal.
|
|
297
|
+
const statusError = findVerificationStatusError([latestDir]);
|
|
298
|
+
if (statusError)
|
|
299
|
+
throw statusError;
|
|
288
300
|
const candidates = files.filter((f) => /summary|verif(?:y|ication)|uat/i.test(f));
|
|
289
301
|
for (const name of candidates) {
|
|
290
302
|
let content = '';
|
|
303
|
+
const filePath = node_path_1.default.join(latestDir, name);
|
|
291
304
|
try {
|
|
292
|
-
content = node_fs_1.default.readFileSync(
|
|
305
|
+
content = node_fs_1.default.readFileSync(filePath, 'utf-8');
|
|
293
306
|
}
|
|
294
307
|
catch {
|
|
295
308
|
continue;
|
|
@@ -311,7 +324,10 @@ function readStateFile(statePath) {
|
|
|
311
324
|
return null;
|
|
312
325
|
}
|
|
313
326
|
const fm = extractFrontmatter(content, statePath);
|
|
314
|
-
|
|
327
|
+
// The body starts after the block `extractFrontmatter` just read (the one fence owner), so a
|
|
328
|
+
// `---` inside a value, a BOM, or an adjacent empty block cannot cut it somewhere else.
|
|
329
|
+
const block = frontmatterBlock(content);
|
|
330
|
+
const body = block ? block.rest.replace(/^\s+/, '') : content;
|
|
315
331
|
return { fm, body };
|
|
316
332
|
}
|
|
317
333
|
/** Collect the full signal set from disk for `cwd`. Exported for unit tests. */
|