@opengsd/gsd-core 1.10.0 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/agents/gsd-code-fixer.md +1 -1
- package/agents/gsd-debug-session-manager.md +12 -1
- package/agents/gsd-debugger.md +1 -1
- package/agents/gsd-doc-synthesizer.md +2 -4
- package/agents/gsd-dom-verifier.md +169 -0
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +22 -14
- package/agents/gsd-framework-selector.md +1 -3
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.md +5 -3
- package/agents/gsd-pattern-mapper.md +11 -0
- package/agents/gsd-phase-researcher.md +23 -2
- package/agents/gsd-plan-checker.md +50 -53
- package/agents/gsd-planner.md +50 -50
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.md +2 -2
- package/agents/gsd-roadmapper.md +15 -11
- package/agents/gsd-ui-checker.md +63 -4
- package/agents/gsd-ui-researcher.md +41 -3
- package/agents/gsd-user-profiler.md +3 -0
- package/agents/gsd-verifier.md +13 -4
- package/bin/install.js +1448 -1103
- package/commands/gsd/code-review.md +1 -1
- package/commands/gsd/discuss-phase.md +1 -1
- package/commands/gsd/execute-phase.md +1 -1
- package/commands/gsd/import.md +1 -1
- package/commands/gsd/map-codebase.md +1 -1
- package/commands/gsd/mempalace-capture.md +1 -1
- package/commands/gsd/mempalace-recall.md +1 -1
- package/commands/gsd/new-milestone.md +1 -1
- package/commands/gsd/quick.md +9 -5
- package/commands/gsd/review-backlog.md +2 -1
- package/commands/gsd/verify-work.md +1 -1
- package/gsd-core/bin/gsd-tools.cjs +1035 -138
- package/gsd-core/bin/lib/active-workstream-store.cjs +146 -22
- package/gsd-core/bin/lib/adr-parser.cjs +13 -7
- package/gsd-core/bin/lib/agent-install-check.cjs +392 -32
- package/gsd-core/bin/lib/api-coverage.cjs +33 -14
- package/gsd-core/bin/lib/artifacts.cjs +5 -0
- package/gsd-core/bin/lib/assumption-delta.cjs +32 -15
- package/gsd-core/bin/lib/audit-command-router.cjs +9 -2
- package/gsd-core/bin/lib/audit.cjs +1026 -268
- package/gsd-core/bin/lib/broken-windows.cjs +306 -28
- package/gsd-core/bin/lib/capability-consent.cjs +149 -15
- package/gsd-core/bin/lib/capability-lifecycle.cjs +45 -0
- package/gsd-core/bin/lib/capability-lock.cjs +10 -4
- package/gsd-core/bin/lib/capability-registry.cjs +845 -130
- package/gsd-core/bin/lib/capability-source.cjs +92 -0
- package/gsd-core/bin/lib/capability-state.cjs +18 -3
- package/gsd-core/bin/lib/capability-trust.cjs +444 -25
- package/gsd-core/bin/lib/capability-validator.cjs +700 -40
- package/gsd-core/bin/lib/capability-writer.cjs +3 -2
- package/gsd-core/bin/lib/check-command-router.cjs +216 -42
- package/gsd-core/bin/lib/claude-orchestration.cjs +56 -3
- package/gsd-core/bin/lib/cli-exit.cjs +496 -10
- package/gsd-core/bin/lib/code-review-depth.cjs +288 -0
- package/gsd-core/bin/lib/codex-agent-toml.cjs +735 -0
- package/gsd-core/bin/lib/command-aliases.cjs +22 -0
- package/gsd-core/bin/lib/command-arg-projection.cjs +144 -14
- package/gsd-core/bin/lib/command-roster.cjs +44 -1
- package/gsd-core/bin/lib/command-routing-hub.cjs +31 -2
- package/gsd-core/bin/lib/commands.cjs +1172 -108
- package/gsd-core/bin/lib/commonjs-marker.cjs +12 -6
- package/gsd-core/bin/lib/complexity-trigger.cjs +1192 -0
- package/gsd-core/bin/lib/config-loader.cjs +187 -23
- package/gsd-core/bin/lib/config.cjs +102 -3
- package/gsd-core/bin/lib/configuration.cjs +129 -37
- package/gsd-core/bin/lib/core-utils.cjs +208 -33
- package/gsd-core/bin/lib/decisions.cjs +23 -0
- package/gsd-core/bin/lib/edge-probe.cjs +9 -1
- package/gsd-core/bin/lib/estimate-cli.cjs +55 -11
- package/gsd-core/bin/lib/exit-code-registry.cjs +98 -0
- package/gsd-core/bin/lib/fallow-runner.cjs +20 -44
- package/gsd-core/bin/lib/frontmatter.cjs +899 -229
- package/gsd-core/bin/lib/gap-checker.cjs +95 -10
- package/gsd-core/bin/lib/git-base-branch.cjs +276 -39
- package/gsd-core/bin/lib/gsd2-import.cjs +10 -1
- package/gsd-core/bin/lib/health-diagnostic-rules/agent-install.cjs +101 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/config-validation.cjs +348 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +149 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/install-surface-shadowing.cjs +98 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/milestone-archive-hygiene.cjs +100 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +222 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +268 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/root-existence.cjs +161 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +303 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +187 -0
- package/gsd-core/bin/lib/health-diagnostic-types.cjs +68 -0
- package/gsd-core/bin/lib/health-diagnostic.cjs +451 -0
- package/gsd-core/bin/lib/host-integration.cjs +39 -6
- package/gsd-core/bin/lib/host-runtime-detection.cjs +134 -0
- package/gsd-core/bin/lib/init-command-router.cjs +118 -21
- package/gsd-core/bin/lib/init.cjs +439 -168
- package/gsd-core/bin/lib/install-effort-resolver.cjs +73 -30
- package/gsd-core/bin/lib/install-engine.cjs +811 -259
- package/gsd-core/bin/lib/install-fs-adapter.cjs +262 -0
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +235 -0
- package/gsd-core/bin/lib/install-profiles.cjs +212 -61
- package/gsd-core/bin/lib/install-scope.cjs +270 -0
- package/gsd-core/bin/lib/install-shadow-report.cjs +385 -0
- package/gsd-core/bin/lib/installed-surface-resolver.cjs +381 -0
- package/gsd-core/bin/lib/installer-migration-report.cjs +3 -0
- package/gsd-core/bin/lib/installer-migrations/010-antigravity-retire-confighome-artifacts.cjs +169 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +148 -38
- package/gsd-core/bin/lib/intel.cjs +101 -26
- package/gsd-core/bin/lib/io.cjs +170 -15
- package/gsd-core/bin/lib/learnings.cjs +85 -14
- package/gsd-core/bin/lib/legacy-cleanup.cjs +8 -2
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +2 -1
- package/gsd-core/bin/lib/markdown-table.cjs +183 -22
- package/gsd-core/bin/lib/milestone-lock.cjs +248 -0
- package/gsd-core/bin/lib/milestone.cjs +842 -73
- package/gsd-core/bin/lib/model-catalog.cjs +232 -16
- package/gsd-core/bin/lib/model-resolver.cjs +193 -68
- package/gsd-core/bin/lib/normalize-test-command.cjs +1 -1
- package/gsd-core/bin/lib/onboard-projection.cjs +5 -1
- package/gsd-core/bin/lib/pattern.cjs +122 -0
- package/gsd-core/bin/lib/phase-estimation.cjs +18 -9
- package/gsd-core/bin/lib/phase-id.cjs +514 -40
- package/gsd-core/bin/lib/phase-lifecycle.cjs +52 -19
- package/gsd-core/bin/lib/phase-locator.cjs +262 -34
- package/gsd-core/bin/lib/phase.cjs +1038 -214
- package/gsd-core/bin/lib/plan-dependency-graph.cjs +72 -1
- package/gsd-core/bin/lib/plan-document.cjs +263 -0
- package/gsd-core/bin/lib/plan-drift-guard.cjs +120 -0
- package/gsd-core/bin/lib/plan-scan.cjs +98 -3
- package/gsd-core/bin/lib/planning-command-router.cjs +61 -0
- package/gsd-core/bin/lib/planning-inspect.cjs +1168 -0
- package/gsd-core/bin/lib/planning-scope.cjs +31 -0
- package/gsd-core/bin/lib/planning-snapshot.cjs +894 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +112 -6
- package/gsd-core/bin/lib/probe-core.cjs +5 -2
- package/gsd-core/bin/lib/profile-output.cjs +1 -1
- package/gsd-core/bin/lib/profile-pipeline-command-router.cjs +50 -7
- package/gsd-core/bin/lib/profile-pipeline.cjs +6 -3
- package/gsd-core/bin/lib/real-home-guard.cjs +419 -0
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +766 -0
- package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +11 -6
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +22 -13
- package/gsd-core/bin/lib/review-lane-invocation.cjs +30 -0
- package/gsd-core/bin/lib/review-lane-runner.cjs +421 -66
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +13 -18
- package/gsd-core/bin/lib/roadmap-command-router.cjs +59 -11
- package/gsd-core/bin/lib/roadmap-parser.cjs +1006 -184
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +37 -10
- package/gsd-core/bin/lib/roadmap.cjs +442 -96
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +702 -52
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +14 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +459 -55
- package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +3 -2
- package/gsd-core/bin/lib/runtime-homes.cjs +69 -3
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +402 -58
- package/gsd-core/bin/lib/runtime-identity.cjs +234 -0
- package/gsd-core/bin/lib/runtime-name-policy.cjs +3 -1
- package/gsd-core/bin/lib/runtime-slash.cjs +96 -8
- package/gsd-core/bin/lib/security.cjs +104 -5
- package/gsd-core/bin/lib/shell-command-projection.cjs +342 -7
- package/gsd-core/bin/lib/smart-entry.cjs +133 -23
- package/gsd-core/bin/lib/spec-section.cjs +12 -7
- package/gsd-core/bin/lib/state-command-router.cjs +52 -19
- package/gsd-core/bin/lib/state-contract.cjs +359 -0
- package/gsd-core/bin/lib/state-document.cjs +338 -8
- package/gsd-core/bin/lib/state-md-schema.cjs +221 -0
- package/gsd-core/bin/lib/state-transition.cjs +846 -176
- package/gsd-core/bin/lib/state.cjs +2589 -369
- package/gsd-core/bin/lib/surface.cjs +33 -11
- package/gsd-core/bin/lib/task-command-router.cjs +111 -1
- package/gsd-core/bin/lib/task-content-resolution.cjs +368 -0
- package/gsd-core/bin/lib/teams-status.cjs +4 -1
- package/gsd-core/bin/lib/text-lines.cjs +80 -0
- package/gsd-core/bin/lib/token-scanner.cjs +76 -0
- package/gsd-core/bin/lib/uat-predicate.cjs +67 -23
- package/gsd-core/bin/lib/uat.cjs +1761 -167
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +9 -1
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +157 -0
- package/gsd-core/bin/lib/ui-safety-gate.cjs +51 -12
- package/gsd-core/bin/lib/unusable-input.cjs +37 -0
- package/gsd-core/bin/lib/update-context.cjs +8 -2
- package/gsd-core/bin/lib/user-artifact-staging.cjs +705 -0
- package/gsd-core/bin/lib/validate-command-router.cjs +2 -2
- package/gsd-core/bin/lib/validate.cjs +20 -6
- package/gsd-core/bin/lib/vendor/README.md +75 -0
- package/gsd-core/bin/lib/vendor/js-yaml.cjs +3014 -0
- package/gsd-core/bin/lib/vendor/re2js.cjs +6480 -0
- package/gsd-core/bin/lib/vendor/re2js.d.cts +938 -0
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +272 -9
- package/gsd-core/bin/lib/verify-command-grounding.cjs +846 -0
- package/gsd-core/bin/lib/verify.cjs +453 -918
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +53 -32
- package/gsd-core/bin/lib/workstream-inventory.cjs +63 -10
- package/gsd-core/bin/lib/workstream-name-policy.cjs +25 -4
- package/gsd-core/bin/lib/workstream.cjs +2 -2
- package/gsd-core/bin/lib/worktree-base-ref.cjs +66 -12
- package/gsd-core/bin/lib/worktree-safety.cjs +341 -18
- package/gsd-core/bin/shared/config-defaults.manifest.json +8 -1
- package/gsd-core/bin/shared/config-schema.manifest.json +12 -1
- package/gsd-core/bin/shared/exit-codes.json +8 -0
- package/gsd-core/bin/shared/exit-codes.sh +20 -0
- package/gsd-core/bin/shared/model-catalog.json +8 -1
- package/gsd-core/references/agent-contracts.md +44 -26
- package/gsd-core/references/api-coverage.md +24 -2
- package/gsd-core/references/autonomous-smart-discuss.md +3 -3
- package/gsd-core/references/checkpoints.md +39 -21
- package/gsd-core/references/context-budget.md +1 -1
- package/gsd-core/references/decimal-phase-calculation.md +5 -5
- package/gsd-core/references/dispatch-isolation-gate.md +138 -0
- package/gsd-core/references/doc-conflict-engine.md +1 -1
- package/gsd-core/references/edge-probe.md +8 -0
- package/gsd-core/references/execute-mvp-tdd.md +4 -6
- package/gsd-core/references/execute-phase-between-wave-reset.md +15 -14
- package/gsd-core/references/execute-phase-context-guard.md +1 -1
- package/gsd-core/references/execute-phase-response-language.md +1 -1
- package/gsd-core/references/execute-phase-wave-guard.md +17 -11
- package/gsd-core/references/failing-direction.md +78 -0
- package/gsd-core/references/gate-prompts.md +1 -1
- package/gsd-core/references/git-integration.md +5 -5
- package/gsd-core/references/git-planning-commit.md +5 -4
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/loop-hook-dispatch.md +61 -2
- package/gsd-core/references/model-profiles.md +12 -4
- package/gsd-core/references/mvp-concepts.md +9 -9
- package/gsd-core/references/nyquist-compliance.md +74 -0
- package/gsd-core/references/offer-next.md +3 -5
- package/gsd-core/references/phase-argument-parsing.md +3 -3
- package/gsd-core/references/planner-failing-direction.md +53 -0
- package/gsd-core/references/planner-guidance.md +3 -9
- package/gsd-core/references/planner-human-verify-mode.md +15 -1
- package/gsd-core/references/planner-preconditions.md +1 -1
- package/gsd-core/references/planner-reviews.md +1 -1
- package/gsd-core/references/planner-revision.md +1 -1
- package/gsd-core/references/planner-verify-command-grounding.md +17 -0
- package/gsd-core/references/planning-config.md +44 -13
- package/gsd-core/references/reviewer-instances.md +31 -0
- package/gsd-core/references/revision-loop.md +1 -1
- package/gsd-core/references/runtime-aware-dispatch.md +1 -1
- package/gsd-core/references/specless-probe-fallback.md +1 -1
- package/gsd-core/references/tdd.md +1 -3
- package/gsd-core/references/ui-brand.md +65 -21
- package/gsd-core/references/ui-consideration-probe.md +1 -1
- package/gsd-core/references/universal-anti-patterns.md +5 -5
- package/gsd-core/references/verifier-phase-gates.md +192 -0
- package/gsd-core/references/verify-command-path-resolvability.md +42 -0
- package/gsd-core/references/verify-mvp-mode.md +2 -2
- package/gsd-core/references/workstream-flag.md +33 -17
- package/gsd-core/templates/README.md +1 -1
- package/gsd-core/templates/SECURITY.md +3 -3
- package/gsd-core/templates/UI-SPEC.md +25 -3
- package/gsd-core/templates/VALIDATION.md +3 -3
- package/gsd-core/templates/discussion-log.md +1 -1
- package/gsd-core/templates/phase-prompt.md +5 -4
- package/gsd-core/templates/state.md +11 -4
- package/gsd-core/templates/verification-report.md +9 -1
- package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
- package/gsd-core/workflows/add-backlog.md +1 -1
- package/gsd-core/workflows/add-phase.md +3 -3
- package/gsd-core/workflows/add-tests.md +3 -8
- package/gsd-core/workflows/add-todo.md +1 -1
- package/gsd-core/workflows/ai-integration-phase.md +13 -20
- package/gsd-core/workflows/audit-fix.md +12 -3
- package/gsd-core/workflows/audit-milestone.md +9 -9
- package/gsd-core/workflows/audit-uat.md +17 -2
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +2 -2
- package/gsd-core/workflows/autonomous.md +11 -27
- package/gsd-core/workflows/check-todos.md +1 -1
- package/gsd-core/workflows/cleanup.md +64 -5
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +14 -4
- package/gsd-core/workflows/code-review-fix.md +38 -11
- package/gsd-core/workflows/code-review.md +159 -52
- package/gsd-core/workflows/complete-milestone.md +151 -23
- package/gsd-core/workflows/debug.md +12 -8
- package/gsd-core/workflows/diagnose-issues.md +47 -15
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +5 -8
- package/gsd-core/workflows/discuss-phase/modes/default.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/text.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +1 -3
- package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
- package/gsd-core/workflows/discuss-phase.md +1 -1
- package/gsd-core/workflows/do.md +3 -6
- package/gsd-core/workflows/docs-update.md +5 -4
- package/gsd-core/workflows/edit-phase.md +27 -2
- package/gsd-core/workflows/eval-review.md +7 -14
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +142 -15
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +77 -0
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +24 -4
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/protected-branch.md +21 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +39 -0
- package/gsd-core/workflows/execute-phase.md +72 -100
- package/gsd-core/workflows/execute-plan.md +52 -15
- package/gsd-core/workflows/explore.md +131 -4
- package/gsd-core/workflows/extract-learnings.md +1 -1
- package/gsd-core/workflows/fast.md +10 -2
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +5 -5
- package/gsd-core/workflows/health.md +76 -10
- package/gsd-core/workflows/import.md +18 -15
- package/gsd-core/workflows/inbox.md +4 -5
- package/gsd-core/workflows/ingest-docs.md +49 -16
- package/gsd-core/workflows/insert-phase.md +5 -5
- package/gsd-core/workflows/list-seeds.md +5 -3
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +12 -23
- package/gsd-core/workflows/map-codebase.md +1 -1
- package/gsd-core/workflows/milestone-summary.md +1 -1
- package/gsd-core/workflows/mvp-phase.md +8 -5
- package/gsd-core/workflows/new-milestone.md +22 -29
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
- package/gsd-core/workflows/new-project.md +26 -40
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +14 -2
- package/gsd-core/workflows/pause-work.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +2 -4
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +3 -3
- package/gsd-core/workflows/plan-phase.md +162 -59
- package/gsd-core/workflows/plan-review-convergence.md +96 -11
- package/gsd-core/workflows/plant-seed.md +2 -2
- package/gsd-core/workflows/pr-branch.md +187 -51
- package/gsd-core/workflows/profile-user.md +16 -14
- package/gsd-core/workflows/progress.md +61 -18
- package/gsd-core/workflows/quick/steps/discussion-phase.md +1 -3
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +5 -7
- package/gsd-core/workflows/quick/steps/quick-verification.md +28 -9
- package/gsd-core/workflows/quick/steps/research-phase.md +4 -6
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +3 -3
- package/gsd-core/workflows/quick.md +55 -44
- package/gsd-core/workflows/remove-phase.md +4 -4
- package/gsd-core/workflows/remove-workspace.md +2 -2
- package/gsd-core/workflows/resume-project.md +8 -12
- package/gsd-core/workflows/review.md +219 -20
- package/gsd-core/workflows/scan.md +1 -1
- package/gsd-core/workflows/secure-phase.md +3 -3
- package/gsd-core/workflows/session-report.md +2 -1
- package/gsd-core/workflows/settings-advanced.md +7 -9
- package/gsd-core/workflows/settings-integrations.md +64 -31
- package/gsd-core/workflows/settings.md +69 -7
- package/gsd-core/workflows/ship.md +116 -50
- package/gsd-core/workflows/sketch-wrap-up.md +11 -17
- package/gsd-core/workflows/sketch.md +12 -18
- package/gsd-core/workflows/smart-entry.md +3 -5
- package/gsd-core/workflows/spec-phase.md +53 -13
- package/gsd-core/workflows/spike-wrap-up.md +7 -11
- package/gsd-core/workflows/spike.md +20 -31
- package/gsd-core/workflows/stats.md +2 -2
- package/gsd-core/workflows/sync-skills.md +64 -9
- package/gsd-core/workflows/thread.md +11 -7
- package/gsd-core/workflows/transition.md +49 -14
- package/gsd-core/workflows/ui-phase.md +15 -21
- package/gsd-core/workflows/ui-review.md +8 -12
- package/gsd-core/workflows/ultraplan-phase.md +5 -13
- package/gsd-core/workflows/undo.md +8 -16
- package/gsd-core/workflows/update.md +7 -11
- package/gsd-core/workflows/validate-phase.md +3 -3
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +25 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
- package/gsd-core/workflows/verify-work.md +66 -25
- package/hooks/dist/gsd-agent-isolation-guard.js +158 -30
- package/hooks/dist/gsd-check-update-worker.js +56 -13
- package/hooks/dist/gsd-check-update.js +19 -1
- package/hooks/dist/gsd-config-reload.js +18 -12
- package/hooks/dist/gsd-context-monitor.js +19 -10
- package/hooks/dist/gsd-cursor-post-tool.js +3 -1
- package/hooks/dist/gsd-cursor-pre-tool.js +2 -3
- package/hooks/dist/gsd-cursor-session-start.js +2 -1
- package/hooks/dist/gsd-cursor-stop.js +2 -1
- package/hooks/dist/gsd-cursor-subagent-start.js +83 -3
- package/hooks/dist/gsd-cursor-subagent-stop.js +6 -3
- package/hooks/dist/gsd-ensure-canonical-path.js +2 -1
- package/hooks/dist/gsd-graphify-update.sh +22 -18
- package/hooks/dist/gsd-node-runner.sh +76 -0
- package/hooks/dist/gsd-phase-boundary.sh +1 -0
- package/hooks/dist/gsd-prompt-guard.js +37 -27
- package/hooks/dist/gsd-read-guard.js +16 -7
- package/hooks/dist/gsd-read-injection-scanner.js +55 -32
- package/hooks/dist/gsd-session-state.sh +1 -0
- package/hooks/dist/gsd-statusline.js +231 -24
- package/hooks/dist/gsd-update-banner.js +22 -1
- package/hooks/dist/gsd-validate-commit.sh +80 -6
- package/hooks/dist/gsd-windsurf-pre-command.js +16 -11
- package/hooks/dist/gsd-windsurf-pre-write.js +22 -13
- package/hooks/dist/gsd-workflow-guard.js +162 -46
- package/hooks/dist/gsd-worktree-path-guard.js +36 -21
- package/hooks/dist/gsd-write-guard.js +35 -25
- package/hooks/dist/lib/cli-exit.js +560 -0
- package/hooks/dist/lib/exit-code-registry.js +98 -0
- package/hooks/dist/lib/git-cmd.js +92 -59
- package/hooks/dist/lib/git-probe.js +84 -0
- package/hooks/dist/lib/hook-exit.js +81 -0
- package/hooks/dist/lib/injection-patterns.js +45 -0
- package/hooks/dist/lib/isolation-deny-reason.js +39 -0
- package/hooks/dist/lib/isolation-sentinel.js +9 -0
- package/hooks/dist/managed-hooks-registry.cjs +3 -0
- package/hooks/gsd-agent-isolation-guard.js +158 -30
- package/hooks/gsd-check-update-worker.js +56 -13
- package/hooks/gsd-check-update.js +19 -1
- package/hooks/gsd-config-reload.js +18 -12
- package/hooks/gsd-context-monitor.js +19 -10
- package/hooks/gsd-cursor-post-tool.js +3 -1
- package/hooks/gsd-cursor-pre-tool.js +2 -3
- package/hooks/gsd-cursor-session-start.js +2 -1
- package/hooks/gsd-cursor-stop.js +2 -1
- package/hooks/gsd-cursor-subagent-start.js +83 -3
- package/hooks/gsd-cursor-subagent-stop.js +6 -3
- package/hooks/gsd-ensure-canonical-path.js +2 -1
- package/hooks/gsd-graphify-update.sh +22 -18
- package/hooks/gsd-node-runner.sh +76 -0
- package/hooks/gsd-phase-boundary.sh +1 -0
- package/hooks/gsd-prompt-guard.js +37 -27
- package/hooks/gsd-read-guard.js +16 -7
- package/hooks/gsd-read-injection-scanner.js +55 -32
- package/hooks/gsd-session-state.sh +1 -0
- package/hooks/gsd-statusline.js +231 -24
- package/hooks/gsd-update-banner.js +22 -1
- package/hooks/gsd-validate-commit.sh +80 -6
- package/hooks/gsd-windsurf-pre-command.js +16 -11
- package/hooks/gsd-windsurf-pre-write.js +22 -13
- package/hooks/gsd-workflow-guard.js +162 -46
- package/hooks/gsd-worktree-path-guard.js +36 -21
- package/hooks/gsd-write-guard.js +35 -25
- package/hooks/lib/cli-exit.js +560 -0
- package/hooks/lib/exit-code-registry.js +98 -0
- package/hooks/lib/git-cmd.js +92 -59
- package/hooks/lib/git-probe.js +84 -0
- package/hooks/lib/hook-exit.js +81 -0
- package/hooks/lib/injection-patterns.js +45 -0
- package/hooks/lib/isolation-deny-reason.js +39 -0
- package/hooks/lib/isolation-sentinel.js +9 -0
- package/hooks/managed-hooks-registry.cjs +3 -0
- package/package.json +28 -11
- package/pi/gsd.cjs +19 -5
- package/scripts/base64-scan.sh +74 -12
- package/scripts/baselines/planning-prompt-drift-baseline.json +4 -0
- package/scripts/baselines/planning-snapshot-bypass-baseline.json +12 -0
- package/scripts/baselines/unreachable-guard-drift-baseline.json +4 -0
- package/scripts/build-hooks.js +5 -0
- package/scripts/changeset/lint.cjs +60 -5
- package/scripts/check-alias-drift.cjs +7 -43
- package/scripts/check-contract-drift.cjs +297 -0
- package/scripts/check-glossary-refs.cjs +77 -15
- package/scripts/check-mutation-score-ratchet.cjs +156 -0
- package/scripts/ci-check-job-near-cap.cjs +49 -0
- package/scripts/ci-pr-mergeability.cjs +262 -0
- package/scripts/ci-test-scope.cjs +64 -14
- package/scripts/ci-timeout-report.cjs +230 -0
- package/scripts/command-contract-helpers.cjs +903 -1
- package/scripts/docs-guard-registry.cjs +396 -0
- package/scripts/gen-adr-index.cjs +728 -38
- package/scripts/gen-capability-registry.cjs +11 -21
- package/scripts/gen-context-index.cjs +2 -11
- package/scripts/gen-exit-code-docs.cjs +318 -0
- package/scripts/gen-exit-code-registry.cjs +891 -0
- package/scripts/gen-features.cjs +836 -0
- package/scripts/gen-health-docs.cjs +390 -0
- package/scripts/gen-hooks-cli-exit.cjs +239 -0
- package/scripts/gen-install-tree-fixtures.cjs +2 -2
- package/scripts/gen-inventory-manifest.cjs +50 -4
- package/scripts/gen-loop-host-contract.cjs +138 -25
- package/scripts/gen-registry.cjs +3 -14
- package/scripts/gen-scripts-cli-exit.cjs +185 -0
- package/scripts/gen-state-md-docs.cjs +727 -0
- package/scripts/{test-failure-reasons.cjs → gsd-test-gate-reasons.cjs} +6 -0
- package/scripts/lib/alias-drift-families.cjs +46 -0
- package/scripts/lib/ci-job-timing.cjs +72 -0
- package/scripts/lib/cli-exit.cjs +546 -44
- package/scripts/lib/drift-scan.cjs +308 -0
- package/scripts/lib/exit-code-registry.cjs +98 -0
- package/scripts/lib/ndjson-reporter.cjs +119 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +1 -26
- package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +4 -0
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +3 -0
- package/scripts/lint-canary-version-leak.cjs +73 -0
- package/scripts/lint-command-contract.cjs +96 -13
- package/scripts/lint-completion-predicate-drift.cjs +933 -0
- package/scripts/lint-completion-ratio-drift.cjs +214 -0
- package/scripts/lint-default-flip-documentation.cjs +193 -0
- package/scripts/lint-docs-guard-registration.cjs +495 -0
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +193 -0
- package/scripts/lint-eslint-glob-coverage.allowlist.json +38 -0
- package/scripts/lint-eslint-glob-coverage.cjs +340 -0
- package/scripts/{lint-fix-has-regression-test.cjs → lint-fix-has-regression-tests.cjs} +12 -6
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +237 -0
- package/scripts/lint-health-diagnostic-rule-table.cjs +461 -0
- package/scripts/lint-hooks-runtime-build-seam.cjs +262 -0
- package/scripts/lint-milestone-window-drift.cjs +468 -0
- package/scripts/lint-mutation-test-derivation-drift.cjs +86 -0
- package/scripts/lint-phase-enumeration-drift.cjs +492 -0
- package/scripts/lint-plan-count-drift.cjs +318 -0
- package/scripts/lint-planning-artifact-writer-drift.cjs +398 -0
- package/scripts/lint-planning-prompt-drift.cjs +471 -0
- package/scripts/lint-planning-snapshot-bypass-drift.cjs +544 -0
- package/scripts/lint-regression-test-names.cjs +15 -13
- package/scripts/lint-removed-but-needed.cjs +488 -0
- package/scripts/lint-seam-enforcement.cjs +182 -0
- package/scripts/lint-slug-derivation-drift.cjs +921 -0
- package/scripts/lint-source-test-name-collision.cjs +241 -0
- package/scripts/lint-state-field-drift.cjs +805 -0
- package/scripts/lint-state-write-path-drift.cjs +950 -0
- package/scripts/lint-test-file-count.allowlist.json +137 -8
- package/scripts/lint-test-file-count.cjs +25 -3
- package/scripts/lint-unreachable-guard-drift.cjs +830 -0
- package/scripts/lint-vendored-deps.cjs +297 -0
- package/scripts/mutation-matrix.cjs +599 -50
- package/scripts/pr-changed-files.cjs +63 -0
- package/scripts/pr-template-policy.cjs +14 -4
- package/scripts/prompt-injection-scan.sh +100 -14
- package/scripts/require-issue-link-policy.cjs +192 -0
- package/scripts/secret-scan.sh +75 -13
- package/scripts/select-docs-guards.cjs +56 -0
- package/scripts/sync-runtime-launcher.cjs +24 -7
- package/skills/gsd-autonomous/SKILL.md +0 -1
- package/skills/gsd-code-review/SKILL.md +1 -1
- package/skills/gsd-discuss-phase/SKILL.md +1 -1
- package/skills/gsd-execute-phase/SKILL.md +1 -2
- package/skills/gsd-import/SKILL.md +1 -1
- package/skills/gsd-map-codebase/SKILL.md +1 -1
- package/skills/gsd-mempalace-capture/SKILL.md +1 -1
- package/skills/gsd-mempalace-recall/SKILL.md +1 -1
- package/skills/gsd-new-milestone/SKILL.md +1 -1
- package/skills/gsd-next/SKILL.md +0 -1
- package/skills/gsd-plan-phase/SKILL.md +0 -1
- package/skills/gsd-progress/SKILL.md +0 -1
- package/skills/gsd-quick/SKILL.md +9 -5
- package/skills/gsd-review-backlog/SKILL.md +2 -1
- package/skills/gsd-stats/SKILL.md +0 -1
- package/skills/gsd-verify-work/SKILL.md +1 -1
- package/vscode/package.json +1 -1
- package/bin/lib/ui-safety-gate.cjs +0 -107
- package/gsd-core/workflows/discovery-phase.md +0 -298
- package/gsd-core/workflows/plan-milestone-gaps.md +0 -281
- package/gsd-core/workflows/verify-phase.md +0 -574
- package/scripts/affected-tests-lib.cjs +0 -554
- package/scripts/lint-allow-test-rule-refs.cjs +0 -162
- package/scripts/lint-emitted-drift-ack.cjs +0 -344
- package/scripts/run-affected-tests.cjs +0 -7
- package/scripts/run-tests.cjs +0 -1051
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
const cjsCommandRouterAdapter = require("./cjs-command-router-adapter.cjs");
|
|
14
14
|
const { routeCjsCommandFamily } = cjsCommandRouterAdapter;
|
|
15
15
|
// ─── Implementation ───────────────────────────────────────────────────────────
|
|
16
|
-
const VERIFICATION_SUBCOMMANDS = ['status'];
|
|
16
|
+
const VERIFICATION_SUBCOMMANDS = ['status', 'resolve-file'];
|
|
17
17
|
function routeVerificationCommand({ verification, args, cwd, raw, error, }) {
|
|
18
18
|
routeCjsCommandFamily({
|
|
19
19
|
args,
|
|
@@ -23,6 +23,7 @@ function routeVerificationCommand({ verification, args, cwd, raw, error, }) {
|
|
|
23
23
|
unknownMessage: (_subcommand, available) => `Unknown verification subcommand. Available: ${available.join(', ')}`,
|
|
24
24
|
handlers: {
|
|
25
25
|
status: () => verification.cmdVerificationStatus(cwd, args[2], raw),
|
|
26
|
+
'resolve-file': () => verification.cmdVerificationResolveFile(cwd, args[2], raw),
|
|
26
27
|
},
|
|
27
28
|
});
|
|
28
29
|
}
|
|
@@ -40,11 +40,17 @@ const phaseId = require("./phase-id.cjs");
|
|
|
40
40
|
const frontmatterMod = require("./frontmatter.cjs");
|
|
41
41
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- plan-scan.cjs is an export= CommonJS module
|
|
42
42
|
const scanPhasePlans = require("./plan-scan.cjs");
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports -- core-utils.cjs is an export= CommonJS module
|
|
44
|
+
const coreUtilsMod = require("./core-utils.cjs");
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports -- planning-scope.cjs is an export= CommonJS module
|
|
46
|
+
const planningScopeMod = require("./planning-scope.cjs");
|
|
43
47
|
const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
|
|
44
48
|
const runtime_slash_cjs_1 = require("./runtime-slash.cjs");
|
|
45
49
|
const { output, error } = io;
|
|
46
|
-
const { extractPhaseToken } = phaseId;
|
|
50
|
+
const { extractPhaseToken, scopeToPhase } = phaseId;
|
|
47
51
|
const { extractFrontmatter } = frontmatterMod;
|
|
52
|
+
const { normalizeLineEndings } = coreUtilsMod;
|
|
53
|
+
const { SCOPE } = planningScopeMod;
|
|
48
54
|
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
49
55
|
/** The set of status values that the gsd-verifier agent emits. */
|
|
50
56
|
const VERIFIER_STATUSES = ['passed', 'gaps_found', 'human_needed'];
|
|
@@ -100,7 +106,7 @@ const VERIFICATION_ROUTING_TABLE = {
|
|
|
100
106
|
// the file has no parseable frontmatter status. Never emitted by the verifier.
|
|
101
107
|
missing: {
|
|
102
108
|
status: 'missing',
|
|
103
|
-
next_action: 'No verification report found — the verify step never completed.
|
|
109
|
+
next_action: 'No verification report found — the verify step never completed. Running execute-phase is safe here: it resumes at the verification gates and does not re-run plans that already have a SUMMARY.md (see #2868).',
|
|
104
110
|
next_command: 'execute-phase',
|
|
105
111
|
},
|
|
106
112
|
// INTERNAL SENTINEL: constructed when the file has a status value not in
|
|
@@ -211,6 +217,145 @@ function missingResult(runtime, phaseArg) {
|
|
|
211
217
|
next_command: projectNextCommand(route.next_command, runtime, phaseArg),
|
|
212
218
|
};
|
|
213
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* #3518: the shared phase-pinned artifact-selection core BOTH single-pick
|
|
222
|
+
* resolvers (`resolveVerificationFile` for `*-VERIFICATION.md`,
|
|
223
|
+
* `resolveUatFile` for `*-UAT.md`) delegate to — one rule, not two grammars
|
|
224
|
+
* that agree today and drift tomorrow (epic #3473 F2's defect class).
|
|
225
|
+
*
|
|
226
|
+
* `bareName` is the artifact filename WITHOUT the leading dash (`'UAT.md'`);
|
|
227
|
+
* a "dashed" candidate is any entry ending `-${bareName}`.
|
|
228
|
+
*
|
|
229
|
+
* Selection order:
|
|
230
|
+
* 1. `options.phaseToken` given and `<phaseToken>-${bareName}` is among
|
|
231
|
+
* the candidates — that exact file always wins: it is THIS phase's own
|
|
232
|
+
* artifact, and no other candidate (whichever phase's token it carries)
|
|
233
|
+
* can outrank it (#3492 / #3518).
|
|
234
|
+
* 2. Fallback — no exact phase-token match (or no token given): alphabetically
|
|
235
|
+
* first of the dashed candidates that are THIS phase's own, per
|
|
236
|
+
* `scopeToPhase(candidates, options.phaseDirName)` (#3511 reconciliation,
|
|
237
|
+
* below). Load-bearing: a phase whose only artifact is non-canonically
|
|
238
|
+
* named must keep resolving to it, not to null — this fix must not turn
|
|
239
|
+
* "found an artifact" into "found nothing" for anyone. A
|
|
240
|
+
* non-canonically-named artifact of THIS phase (e.g.
|
|
241
|
+
* `03-CORRECTION-VERIFICATION.md` in `03-foo`) still passes
|
|
242
|
+
* `isPhaseArtifact` (it names phase 03, same as the directory), so it
|
|
243
|
+
* is still returned here.
|
|
244
|
+
* 3. `options.allowBare` only — a bare `${bareName}`, ranked BELOW both
|
|
245
|
+
* of the above. Rationale: a dashed file names its phase, a bare one
|
|
246
|
+
* does not, so a dashed file (canonical or not) is always the better
|
|
247
|
+
* answer when both exist. Reached when neither (1) nor (2) found any
|
|
248
|
+
* candidate — including when (2)'s scoping filtered every dashed
|
|
249
|
+
* candidate out as belonging to some OTHER phase.
|
|
250
|
+
*
|
|
251
|
+
* #3511 RECONCILIATION with `isPhaseArtifact` (`src/phase-id.cts`): that
|
|
252
|
+
* predicate's own docblock used to flag this fallback as an open gap — its
|
|
253
|
+
* aggregate scans exclude a cross-phase stray, but this single-pick resolver
|
|
254
|
+
* did not, so it could return a stray as THE artifact while the aggregate
|
|
255
|
+
* scans correctly ignored it. Closed by scoping step (2) above through
|
|
256
|
+
* `scopeToPhase` (`src/phase-id.cts`, itself built on `isPhaseArtifact`):
|
|
257
|
+
* `options.phaseDirName` threads the phase directory's basename in, and the
|
|
258
|
+
* fallback now filters candidates through `scopeToPhase(candidates,
|
|
259
|
+
* phaseDirName)` before picking alphabetically-first. This does NOT reopen
|
|
260
|
+
* the #3357 guarantee — that guarantee is "a phase whose only report is
|
|
261
|
+
* non-canonically named must keep working", and a non-canonically-named
|
|
262
|
+
* artifact of THIS phase still passes `isPhaseArtifact` (it is membership by
|
|
263
|
+
* phase number, not by canonical shape), so it is still returned. Only a
|
|
264
|
+
* file belonging to a DIFFERENT phase is now excluded — and excluding it is
|
|
265
|
+
* correct: returning another phase's artifact as this phase's own is worse
|
|
266
|
+
* than reporting none (confidently wrong beats honestly empty).
|
|
267
|
+
* The fail-safe now lives entirely inside `isPhaseArtifact`, not in
|
|
268
|
+
* `scopeToPhase` (which is a plain filter with no unfiltered fallback):
|
|
269
|
+
* (a) when phase-number membership cannot be determined for `phaseDirName` at
|
|
270
|
+
* all (no reliable token — the zero-token directory case), every candidate is
|
|
271
|
+
* treated as belonging to the phase; (b) the `firstLetterPrefixed`
|
|
272
|
+
* bracket-ambiguity case, where a letter-prefixed-decimal dir is
|
|
273
|
+
* string-indistinguishable from a bracket-dir token, also includes
|
|
274
|
+
* everything rather than guess; (c) a token-less filename (bare
|
|
275
|
+
* `${bareName}`) is accepted by directory containment alone. Outside
|
|
276
|
+
* those cases, when scoping DOES remove every dashed candidate — a real
|
|
277
|
+
* cross-phase stray, or a phase whose own artifact is genuinely absent — the
|
|
278
|
+
* fallback below correctly falls through to `allowBare`/`null`: reporting no
|
|
279
|
+
* artifact, not another phase's. `options.phaseDirName` omitted entirely skips
|
|
280
|
+
* the filter outright (the ternary below), which is unscoped, pre-#3511
|
|
281
|
+
* behavior.
|
|
282
|
+
*
|
|
283
|
+
* Pure — takes an already-read directory listing and does no I/O of its own,
|
|
284
|
+
* so every call site keeps its existing `fsImpl` seam and no-throw contract
|
|
285
|
+
* untouched.
|
|
286
|
+
*/
|
|
287
|
+
function resolvePhaseArtifactFile(entries, bareName, options = {}) {
|
|
288
|
+
const candidates = entries.filter((f) => f.endsWith(`-${bareName}`)).sort();
|
|
289
|
+
if (candidates.length > 0) {
|
|
290
|
+
if (options.phaseToken) {
|
|
291
|
+
const thisPhaseFile = `${options.phaseToken}-${bareName}`;
|
|
292
|
+
if (candidates.includes(thisPhaseFile))
|
|
293
|
+
return thisPhaseFile;
|
|
294
|
+
}
|
|
295
|
+
// #3511: scope the fallback to files that belong to THIS phase, so a
|
|
296
|
+
// stray cross-phase file can no longer outrank a return of null.
|
|
297
|
+
// `phaseDirName` omitted, or membership undeterminable for it, →
|
|
298
|
+
// unscoped `candidates` (pre-#3511 behavior); otherwise strays are
|
|
299
|
+
// filtered out, and if that leaves nothing the code falls through to
|
|
300
|
+
// `allowBare`/`null` deliberately.
|
|
301
|
+
const scoped = options.phaseDirName
|
|
302
|
+
? scopeToPhase(candidates, options.phaseDirName)
|
|
303
|
+
: candidates;
|
|
304
|
+
if (scoped.length > 0)
|
|
305
|
+
return scoped[0];
|
|
306
|
+
}
|
|
307
|
+
if (options.allowBare && entries.includes(bareName))
|
|
308
|
+
return bareName;
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Resolve which `*-VERIFICATION.md` entry in a phase directory's listing IS
|
|
313
|
+
* the phase's verification report, when more than one such file exists.
|
|
314
|
+
*
|
|
315
|
+
* #3357: a phase dir can legitimately hold more than one `*-VERIFICATION.md`
|
|
316
|
+
* — the real per-phase report (`03-VERIFICATION.md`) alongside an ad-hoc plan
|
|
317
|
+
* worksheet (`03-CORRECTION-VERIFICATION.md`). Picking "alphabetically first"
|
|
318
|
+
* (`'C' < 'V'`) silently chose the worksheet, which usually has no
|
|
319
|
+
* frontmatter `status:`, so a phase with a PASSING report read as `missing`.
|
|
320
|
+
* This was two independent hand-rolled `.sort()[0]` picks
|
|
321
|
+
* (findStaleVerificationSummary and readVerificationStatus) — this is the
|
|
322
|
+
* single resolver both now call (#3473 F2).
|
|
323
|
+
*
|
|
324
|
+
* Selection order: see `resolvePhaseArtifactFile` (the shared core this
|
|
325
|
+
* delegates to since #3518, itself phase-scoped since #3511) —
|
|
326
|
+
* phase-token-pinned, then phase-scoped alphabetically-first dashed
|
|
327
|
+
* fallback, then (allowBare only) a bare `VERIFICATION.md`. #3518 extracted
|
|
328
|
+
* this into the shared core without changing behavior; #3511's
|
|
329
|
+
* `phaseDirName` scoping now lives inside that shared core rather than here.
|
|
330
|
+
*/
|
|
331
|
+
function resolveVerificationFile(entries, options = {}) {
|
|
332
|
+
return resolvePhaseArtifactFile(entries, 'VERIFICATION.md', options);
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* #3518: resolve which `*-UAT.md` entry in a phase directory's listing IS
|
|
336
|
+
* the phase's UAT artifact, when more than one such file exists — the UAT
|
|
337
|
+
* counterpart of `resolveVerificationFile`, sharing its exact selection rule
|
|
338
|
+
* via `resolvePhaseArtifactFile`.
|
|
339
|
+
*
|
|
340
|
+
* The bug this closes: both `uat_path` projectors in `src/init.cts` picked
|
|
341
|
+
* with a bare `.find((f) => f.endsWith('-UAT.md') || f === 'UAT.md')` over an
|
|
342
|
+
* unsorted `readdir` listing — no phase-membership check and no ordering — so
|
|
343
|
+
* a stray or cross-phase `04-UAT.md` sitting in phase 03's directory could
|
|
344
|
+
* become phase 03's `uat_path`, and WHICH file won was filesystem-dependent
|
|
345
|
+
* (creation order on APFS, hash order on ext4/XFS): two machines on the same
|
|
346
|
+
* commit could emit different `uat_path` values for the same phase. `uat_path`
|
|
347
|
+
* is consumed downstream by workflows that then read the named file, so a
|
|
348
|
+
* wrong path routes UAT state from another phase.
|
|
349
|
+
*
|
|
350
|
+
* Deterministic by construction: same answer on every machine. Phase-scoped
|
|
351
|
+
* (#3511): passing `options.phaseDirName` filters the alphabetically-first
|
|
352
|
+
* fallback (tier 2) to artifacts that belong to THIS phase — see
|
|
353
|
+
* `resolvePhaseArtifactFile` for the full selection order and scoping
|
|
354
|
+
* rationale.
|
|
355
|
+
*/
|
|
356
|
+
function resolveUatFile(entries, options = {}) {
|
|
357
|
+
return resolvePhaseArtifactFile(entries, 'UAT.md', options);
|
|
358
|
+
}
|
|
214
359
|
function findStaleVerificationSummary(phaseDir, fsImpl = node_fs_1.default, phaseCleanCommitTimesMs = defaultPhaseCleanCommitTimesMs) {
|
|
215
360
|
// FS errors (TOCTOU: a SUMMARY listed by scanPhasePlans then removed before statSync;
|
|
216
361
|
// unreadable dir; broken symlink; file->dir swap) must degrade rather than throw
|
|
@@ -223,7 +368,13 @@ function findStaleVerificationSummary(phaseDir, fsImpl = node_fs_1.default, phas
|
|
|
223
368
|
// this function only reports what it actually knows.
|
|
224
369
|
try {
|
|
225
370
|
const phaseFiles = fsImpl.readdirSync(phaseDir);
|
|
226
|
-
|
|
371
|
+
// #3492: pin selection to THIS phase's own token so a stray cross-phase
|
|
372
|
+
// or sentinel-numbered canonically-shaped file cannot outrank this
|
|
373
|
+
// phase's own (possibly non-canonical) report. #3511: phaseDirName scopes
|
|
374
|
+
// the fallback path to this same phase (see resolveVerificationFile docs).
|
|
375
|
+
const phaseDirName = node_path_1.default.basename(phaseDir);
|
|
376
|
+
const phaseToken = extractPhaseToken(phaseDirName);
|
|
377
|
+
const verificationFile = resolveVerificationFile(phaseFiles, { phaseToken, phaseDirName });
|
|
227
378
|
if (!verificationFile)
|
|
228
379
|
return { determined: true, stale: false };
|
|
229
380
|
const summaryFiles = scanPhasePlans(phaseDir).summaryFiles
|
|
@@ -261,8 +412,10 @@ function findStaleVerificationSummary(phaseDir, fsImpl = node_fs_1.default, phas
|
|
|
261
412
|
* phaseDir and return the routing result.
|
|
262
413
|
*
|
|
263
414
|
* Behavior:
|
|
264
|
-
* 1. Find the
|
|
265
|
-
*
|
|
415
|
+
* 1. Find the phase's verification report via `resolveVerificationFile`
|
|
416
|
+
* (canonical `<phase-token>-VERIFICATION.md` preferred; falls back to the
|
|
417
|
+
* alphabetically-first `*-VERIFICATION.md` that belongs to THIS phase when
|
|
418
|
+
* none is canonical — #3357/#3511). If none → status 'missing'.
|
|
266
419
|
* 2. Extract `status` from FRONTMATTER ONLY via the shared extractFrontmatter
|
|
267
420
|
* parser (DEFECT.FRONTMATTER-SCALAR-BROAD-GREP fix — parser anchors at byte 0).
|
|
268
421
|
* If no frontmatter block or no `status` key → status 'missing'.
|
|
@@ -299,8 +452,12 @@ function readVerificationStatus(phaseDir, opts = {}) {
|
|
|
299
452
|
let verificationFile = null;
|
|
300
453
|
try {
|
|
301
454
|
const entries = fsImpl.readdirSync(phaseDir);
|
|
302
|
-
|
|
303
|
-
|
|
455
|
+
// #3492: pin selection to THIS phase's own token (already derived above
|
|
456
|
+
// for the routed command argument) so a stray cross-phase or
|
|
457
|
+
// sentinel-numbered canonically-shaped file cannot outrank this phase's
|
|
458
|
+
// own (possibly non-canonical) report. #3511: baseName also scopes the
|
|
459
|
+
// fallback path to this same phase (see resolveVerificationFile docs).
|
|
460
|
+
verificationFile = resolveVerificationFile(entries, { phaseToken, phaseDirName: baseName });
|
|
304
461
|
}
|
|
305
462
|
catch {
|
|
306
463
|
// Directory unreadable → treat as missing
|
|
@@ -314,7 +471,17 @@ function readVerificationStatus(phaseDir, opts = {}) {
|
|
|
314
471
|
const filePath = node_path_1.default.join(phaseDir, verificationFile);
|
|
315
472
|
let rawStatus = null;
|
|
316
473
|
try {
|
|
317
|
-
|
|
474
|
+
// #3707-CR follow-up MINOR 1: normalize line endings at this read
|
|
475
|
+
// boundary — this function's own `readFileSync` is the equivalent seam
|
|
476
|
+
// `planning.inspect`'s `buildUatRows`/`readDocument` route through for
|
|
477
|
+
// UAT/REQUIREMENTS documents, but `readVerificationStatus` had no such
|
|
478
|
+
// normalization of its own. A lone-CR VERIFICATION.md's `---\r...\r---`
|
|
479
|
+
// frontmatter fence never matched `extractFrontmatter`'s byte-0
|
|
480
|
+
// `---\n`/`---\r\n` check, so `status: passed` was read as absent and
|
|
481
|
+
// this function reported 'missing' — under-reporting a completed
|
|
482
|
+
// verification as if the step never ran, the fail-safe direction but the
|
|
483
|
+
// same root cause as the false-clean class fixed elsewhere in #3707-CR.
|
|
484
|
+
const content = normalizeLineEndings(fsImpl.readFileSync(filePath, 'utf-8'));
|
|
318
485
|
const fm = extractFrontmatter(content, filePath);
|
|
319
486
|
const statusVal = fm['status'];
|
|
320
487
|
// status is always a scalar string in a well-formed VERIFICATION.md frontmatter;
|
|
@@ -374,11 +541,63 @@ function readVerificationStatus(phaseDir, opts = {}) {
|
|
|
374
541
|
const unknownRoute = VERIFICATION_ROUTING_TABLE['unknown'];
|
|
375
542
|
return {
|
|
376
543
|
status: unknownRoute.status,
|
|
377
|
-
next_action: `Unexpected verification status '${rawStatus}'.
|
|
544
|
+
next_action: `Unexpected verification status '${rawStatus}'. If this is an intentional non-standard marker (e.g. a hand-set failed/superseded state), no action is needed. Otherwise, run execute-phase to regenerate verification — it will not re-run plans that already have a SUMMARY.md.`,
|
|
378
545
|
next_command: projectNextCommand(unknownRoute.next_command, runtime, phaseArg),
|
|
379
546
|
...(staleCheckIndeterminate ? { staleCheckIndeterminate: true } : {}),
|
|
380
547
|
};
|
|
381
548
|
}
|
|
549
|
+
/**
|
|
550
|
+
* isPhaseComplete — the single canonical owner of "is phase P complete?"
|
|
551
|
+
* (ADR-3180 §7.4, Decision 1). Sited beside readVerificationStatus, which it
|
|
552
|
+
* wraps.
|
|
553
|
+
*
|
|
554
|
+
* DISK-STRICT (#2957, maintainer decision 2026-08-08; ADR-3180 §7.4 amended
|
|
555
|
+
* af92fd4c9): readVerificationStatus is called UNCONDITIONALLY here — plan
|
|
556
|
+
* count is NOT a precondition. A phase with zero plans and a passing
|
|
557
|
+
* `*-VERIFICATION.md` is complete (#3168). A ROADMAP checkbox has no machine
|
|
558
|
+
* authority and is never consulted — this function never reads ROADMAP.md.
|
|
559
|
+
*
|
|
560
|
+
* `complete` is exactly `verification.status === 'passed'`. `verification`
|
|
561
|
+
* carries the FULL routing result (status/next_action/next_command), so a
|
|
562
|
+
* caller can distinguish a failing verdict (`gaps_found`/`human_needed`/
|
|
563
|
+
* `stale`/`unknown`) from an absent one (`missing`) — both are "not
|
|
564
|
+
* complete", but they are not the same non-answer.
|
|
565
|
+
*
|
|
566
|
+
* `scope` is UNREADABLE when `phaseDir` itself could not be listed — this is
|
|
567
|
+
* INDEPENDENT of readVerificationStatus's own no-throw fail-open contract for
|
|
568
|
+
* a missing `*-VERIFICATION.md` file (a well-formed answer,
|
|
569
|
+
* `verification.status === 'missing'`, scope COMPLETE): a caller must not
|
|
570
|
+
* read `value.complete: false` here as a confident "not complete" the way it
|
|
571
|
+
* can for a genuinely-checked missing file.
|
|
572
|
+
*
|
|
573
|
+
* Does NOT import scanPhasePlans / plan-scan.cjs — the owner consumes plan
|
|
574
|
+
* counts from its caller when a caller needs them for a different question
|
|
575
|
+
* (e.g. buildPhaseCompletionProjection's own `implementation_complete`); it
|
|
576
|
+
* never re-derives or requires them itself.
|
|
577
|
+
*/
|
|
578
|
+
function isPhaseComplete(phaseDir, deps = {}) {
|
|
579
|
+
const fsImpl = deps.fs ?? node_fs_1.default;
|
|
580
|
+
let readable = true;
|
|
581
|
+
try {
|
|
582
|
+
fsImpl.readdirSync(phaseDir);
|
|
583
|
+
}
|
|
584
|
+
catch {
|
|
585
|
+
readable = false;
|
|
586
|
+
}
|
|
587
|
+
const verification = readVerificationStatus(phaseDir, {
|
|
588
|
+
fs: deps.fs,
|
|
589
|
+
phaseCleanCommitTimesMs: deps.phaseCleanCommitTimesMs,
|
|
590
|
+
runtime: deps.runtime,
|
|
591
|
+
phaseNumber: deps.phaseNumber,
|
|
592
|
+
});
|
|
593
|
+
return {
|
|
594
|
+
value: {
|
|
595
|
+
complete: verification.status === 'passed',
|
|
596
|
+
verification,
|
|
597
|
+
},
|
|
598
|
+
scope: readable ? SCOPE.COMPLETE : SCOPE.UNREADABLE,
|
|
599
|
+
};
|
|
600
|
+
}
|
|
382
601
|
/**
|
|
383
602
|
* CLI command handler: resolve phaseDir against cwd, call readVerificationStatus,
|
|
384
603
|
* emit via io.output().
|
|
@@ -396,11 +615,55 @@ function cmdVerificationStatus(cwd, phaseDirArg, raw) {
|
|
|
396
615
|
const result = readVerificationStatus(phaseDir, { runtime: (0, runtime_slash_cjs_1.resolveRuntime)(cwd) });
|
|
397
616
|
output(result, raw);
|
|
398
617
|
}
|
|
618
|
+
/**
|
|
619
|
+
* CLI command handler: resolve which `*-VERIFICATION.md` in `phaseDirArg` is
|
|
620
|
+
* the phase's own report, via the shared `resolveVerificationFile` seam, and
|
|
621
|
+
* emit its absolute path.
|
|
622
|
+
*
|
|
623
|
+
* #3492 F3: the ONE seam shell callers (verify-work.md's writer, transition.md's
|
|
624
|
+
* awk reader) route through instead of hand-rolling `ls *-VERIFICATION.md |
|
|
625
|
+
* head -1` / an awk glob scan — both of which pick alphabetically-first and so
|
|
626
|
+
* diverge from every JS reader now pinned to the phase's own token.
|
|
627
|
+
*
|
|
628
|
+
* Emits `{ verification_file: "<absolute path>" | "" }` (empty when no
|
|
629
|
+
* candidate resolves, including an unreadable directory). `raw` emits the
|
|
630
|
+
* bare path string (possibly empty) so `VAR=$(gsd_run query
|
|
631
|
+
* verification.resolve-file "$PHASE_DIR" --raw)` is directly assignable.
|
|
632
|
+
*
|
|
633
|
+
* @param cwd - Current working directory (used to resolve phaseDirArg).
|
|
634
|
+
* @param phaseDirArg - Phase directory path (absolute or relative to cwd).
|
|
635
|
+
* @param raw - Whether to emit raw (non-JSON) output.
|
|
636
|
+
*/
|
|
637
|
+
function cmdVerificationResolveFile(cwd, phaseDirArg, raw) {
|
|
638
|
+
if (!phaseDirArg) {
|
|
639
|
+
error('phase directory required for verification.resolve-file');
|
|
640
|
+
return;
|
|
641
|
+
}
|
|
642
|
+
const phaseDir = node_path_1.default.resolve(cwd, phaseDirArg);
|
|
643
|
+
let verificationPath = '';
|
|
644
|
+
try {
|
|
645
|
+
const entries = node_fs_1.default.readdirSync(phaseDir);
|
|
646
|
+
const phaseDirName = node_path_1.default.basename(phaseDir);
|
|
647
|
+
const phaseToken = extractPhaseToken(phaseDirName);
|
|
648
|
+
const verificationFile = resolveVerificationFile(entries, { allowBare: true, phaseToken, phaseDirName });
|
|
649
|
+
if (verificationFile) {
|
|
650
|
+
verificationPath = node_path_1.default.join(phaseDir, verificationFile);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
catch {
|
|
654
|
+
verificationPath = '';
|
|
655
|
+
}
|
|
656
|
+
output({ verification_file: verificationPath }, raw, verificationPath);
|
|
657
|
+
}
|
|
399
658
|
module.exports = {
|
|
400
659
|
VERIFIER_STATUSES,
|
|
401
660
|
VERIFICATION_ROUTING_TABLE,
|
|
402
661
|
defaultPhaseCleanCommitTimesMs,
|
|
662
|
+
resolveVerificationFile,
|
|
663
|
+
resolveUatFile,
|
|
403
664
|
findStaleVerificationSummary,
|
|
404
665
|
readVerificationStatus,
|
|
666
|
+
isPhaseComplete,
|
|
405
667
|
cmdVerificationStatus,
|
|
668
|
+
cmdVerificationResolveFile,
|
|
406
669
|
};
|