@opengsd/gsd-core 1.10.0 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/agents/gsd-code-fixer.md +1 -1
- package/agents/gsd-debug-session-manager.md +12 -1
- package/agents/gsd-debugger.md +1 -1
- package/agents/gsd-doc-synthesizer.md +2 -4
- package/agents/gsd-dom-verifier.md +169 -0
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +22 -14
- package/agents/gsd-framework-selector.md +1 -3
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.md +5 -3
- package/agents/gsd-pattern-mapper.md +11 -0
- package/agents/gsd-phase-researcher.md +23 -2
- package/agents/gsd-plan-checker.md +50 -53
- package/agents/gsd-planner.md +50 -50
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.md +2 -2
- package/agents/gsd-roadmapper.md +15 -11
- package/agents/gsd-ui-checker.md +63 -4
- package/agents/gsd-ui-researcher.md +41 -3
- package/agents/gsd-user-profiler.md +3 -0
- package/agents/gsd-verifier.md +13 -4
- package/bin/install.js +1448 -1103
- package/commands/gsd/code-review.md +1 -1
- package/commands/gsd/discuss-phase.md +1 -1
- package/commands/gsd/execute-phase.md +1 -1
- package/commands/gsd/import.md +1 -1
- package/commands/gsd/map-codebase.md +1 -1
- package/commands/gsd/mempalace-capture.md +1 -1
- package/commands/gsd/mempalace-recall.md +1 -1
- package/commands/gsd/new-milestone.md +1 -1
- package/commands/gsd/quick.md +9 -5
- package/commands/gsd/review-backlog.md +2 -1
- package/commands/gsd/verify-work.md +1 -1
- package/gsd-core/bin/gsd-tools.cjs +1035 -138
- package/gsd-core/bin/lib/active-workstream-store.cjs +146 -22
- package/gsd-core/bin/lib/adr-parser.cjs +13 -7
- package/gsd-core/bin/lib/agent-install-check.cjs +392 -32
- package/gsd-core/bin/lib/api-coverage.cjs +33 -14
- package/gsd-core/bin/lib/artifacts.cjs +5 -0
- package/gsd-core/bin/lib/assumption-delta.cjs +32 -15
- package/gsd-core/bin/lib/audit-command-router.cjs +9 -2
- package/gsd-core/bin/lib/audit.cjs +1026 -268
- package/gsd-core/bin/lib/broken-windows.cjs +306 -28
- package/gsd-core/bin/lib/capability-consent.cjs +149 -15
- package/gsd-core/bin/lib/capability-lifecycle.cjs +45 -0
- package/gsd-core/bin/lib/capability-lock.cjs +10 -4
- package/gsd-core/bin/lib/capability-registry.cjs +845 -130
- package/gsd-core/bin/lib/capability-source.cjs +92 -0
- package/gsd-core/bin/lib/capability-state.cjs +18 -3
- package/gsd-core/bin/lib/capability-trust.cjs +444 -25
- package/gsd-core/bin/lib/capability-validator.cjs +700 -40
- package/gsd-core/bin/lib/capability-writer.cjs +3 -2
- package/gsd-core/bin/lib/check-command-router.cjs +216 -42
- package/gsd-core/bin/lib/claude-orchestration.cjs +56 -3
- package/gsd-core/bin/lib/cli-exit.cjs +496 -10
- package/gsd-core/bin/lib/code-review-depth.cjs +288 -0
- package/gsd-core/bin/lib/codex-agent-toml.cjs +735 -0
- package/gsd-core/bin/lib/command-aliases.cjs +22 -0
- package/gsd-core/bin/lib/command-arg-projection.cjs +144 -14
- package/gsd-core/bin/lib/command-roster.cjs +44 -1
- package/gsd-core/bin/lib/command-routing-hub.cjs +31 -2
- package/gsd-core/bin/lib/commands.cjs +1172 -108
- package/gsd-core/bin/lib/commonjs-marker.cjs +12 -6
- package/gsd-core/bin/lib/complexity-trigger.cjs +1192 -0
- package/gsd-core/bin/lib/config-loader.cjs +187 -23
- package/gsd-core/bin/lib/config.cjs +102 -3
- package/gsd-core/bin/lib/configuration.cjs +129 -37
- package/gsd-core/bin/lib/core-utils.cjs +208 -33
- package/gsd-core/bin/lib/decisions.cjs +23 -0
- package/gsd-core/bin/lib/edge-probe.cjs +9 -1
- package/gsd-core/bin/lib/estimate-cli.cjs +55 -11
- package/gsd-core/bin/lib/exit-code-registry.cjs +98 -0
- package/gsd-core/bin/lib/fallow-runner.cjs +20 -44
- package/gsd-core/bin/lib/frontmatter.cjs +899 -229
- package/gsd-core/bin/lib/gap-checker.cjs +95 -10
- package/gsd-core/bin/lib/git-base-branch.cjs +276 -39
- package/gsd-core/bin/lib/gsd2-import.cjs +10 -1
- package/gsd-core/bin/lib/health-diagnostic-rules/agent-install.cjs +101 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/config-validation.cjs +348 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +149 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/install-surface-shadowing.cjs +98 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/milestone-archive-hygiene.cjs +100 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +222 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +268 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/root-existence.cjs +161 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +303 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +187 -0
- package/gsd-core/bin/lib/health-diagnostic-types.cjs +68 -0
- package/gsd-core/bin/lib/health-diagnostic.cjs +451 -0
- package/gsd-core/bin/lib/host-integration.cjs +39 -6
- package/gsd-core/bin/lib/host-runtime-detection.cjs +134 -0
- package/gsd-core/bin/lib/init-command-router.cjs +118 -21
- package/gsd-core/bin/lib/init.cjs +439 -168
- package/gsd-core/bin/lib/install-effort-resolver.cjs +73 -30
- package/gsd-core/bin/lib/install-engine.cjs +811 -259
- package/gsd-core/bin/lib/install-fs-adapter.cjs +262 -0
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +235 -0
- package/gsd-core/bin/lib/install-profiles.cjs +212 -61
- package/gsd-core/bin/lib/install-scope.cjs +270 -0
- package/gsd-core/bin/lib/install-shadow-report.cjs +385 -0
- package/gsd-core/bin/lib/installed-surface-resolver.cjs +381 -0
- package/gsd-core/bin/lib/installer-migration-report.cjs +3 -0
- package/gsd-core/bin/lib/installer-migrations/010-antigravity-retire-confighome-artifacts.cjs +169 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +148 -38
- package/gsd-core/bin/lib/intel.cjs +101 -26
- package/gsd-core/bin/lib/io.cjs +170 -15
- package/gsd-core/bin/lib/learnings.cjs +85 -14
- package/gsd-core/bin/lib/legacy-cleanup.cjs +8 -2
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +2 -1
- package/gsd-core/bin/lib/markdown-table.cjs +183 -22
- package/gsd-core/bin/lib/milestone-lock.cjs +248 -0
- package/gsd-core/bin/lib/milestone.cjs +842 -73
- package/gsd-core/bin/lib/model-catalog.cjs +232 -16
- package/gsd-core/bin/lib/model-resolver.cjs +193 -68
- package/gsd-core/bin/lib/normalize-test-command.cjs +1 -1
- package/gsd-core/bin/lib/onboard-projection.cjs +5 -1
- package/gsd-core/bin/lib/pattern.cjs +122 -0
- package/gsd-core/bin/lib/phase-estimation.cjs +18 -9
- package/gsd-core/bin/lib/phase-id.cjs +514 -40
- package/gsd-core/bin/lib/phase-lifecycle.cjs +52 -19
- package/gsd-core/bin/lib/phase-locator.cjs +262 -34
- package/gsd-core/bin/lib/phase.cjs +1038 -214
- package/gsd-core/bin/lib/plan-dependency-graph.cjs +72 -1
- package/gsd-core/bin/lib/plan-document.cjs +263 -0
- package/gsd-core/bin/lib/plan-drift-guard.cjs +120 -0
- package/gsd-core/bin/lib/plan-scan.cjs +98 -3
- package/gsd-core/bin/lib/planning-command-router.cjs +61 -0
- package/gsd-core/bin/lib/planning-inspect.cjs +1168 -0
- package/gsd-core/bin/lib/planning-scope.cjs +31 -0
- package/gsd-core/bin/lib/planning-snapshot.cjs +894 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +112 -6
- package/gsd-core/bin/lib/probe-core.cjs +5 -2
- package/gsd-core/bin/lib/profile-output.cjs +1 -1
- package/gsd-core/bin/lib/profile-pipeline-command-router.cjs +50 -7
- package/gsd-core/bin/lib/profile-pipeline.cjs +6 -3
- package/gsd-core/bin/lib/real-home-guard.cjs +419 -0
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +766 -0
- package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +11 -6
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +22 -13
- package/gsd-core/bin/lib/review-lane-invocation.cjs +30 -0
- package/gsd-core/bin/lib/review-lane-runner.cjs +421 -66
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +13 -18
- package/gsd-core/bin/lib/roadmap-command-router.cjs +59 -11
- package/gsd-core/bin/lib/roadmap-parser.cjs +1006 -184
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +37 -10
- package/gsd-core/bin/lib/roadmap.cjs +442 -96
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +702 -52
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +14 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +459 -55
- package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +3 -2
- package/gsd-core/bin/lib/runtime-homes.cjs +69 -3
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +402 -58
- package/gsd-core/bin/lib/runtime-identity.cjs +234 -0
- package/gsd-core/bin/lib/runtime-name-policy.cjs +3 -1
- package/gsd-core/bin/lib/runtime-slash.cjs +96 -8
- package/gsd-core/bin/lib/security.cjs +104 -5
- package/gsd-core/bin/lib/shell-command-projection.cjs +342 -7
- package/gsd-core/bin/lib/smart-entry.cjs +133 -23
- package/gsd-core/bin/lib/spec-section.cjs +12 -7
- package/gsd-core/bin/lib/state-command-router.cjs +52 -19
- package/gsd-core/bin/lib/state-contract.cjs +359 -0
- package/gsd-core/bin/lib/state-document.cjs +338 -8
- package/gsd-core/bin/lib/state-md-schema.cjs +221 -0
- package/gsd-core/bin/lib/state-transition.cjs +846 -176
- package/gsd-core/bin/lib/state.cjs +2589 -369
- package/gsd-core/bin/lib/surface.cjs +33 -11
- package/gsd-core/bin/lib/task-command-router.cjs +111 -1
- package/gsd-core/bin/lib/task-content-resolution.cjs +368 -0
- package/gsd-core/bin/lib/teams-status.cjs +4 -1
- package/gsd-core/bin/lib/text-lines.cjs +80 -0
- package/gsd-core/bin/lib/token-scanner.cjs +76 -0
- package/gsd-core/bin/lib/uat-predicate.cjs +67 -23
- package/gsd-core/bin/lib/uat.cjs +1761 -167
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +9 -1
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +157 -0
- package/gsd-core/bin/lib/ui-safety-gate.cjs +51 -12
- package/gsd-core/bin/lib/unusable-input.cjs +37 -0
- package/gsd-core/bin/lib/update-context.cjs +8 -2
- package/gsd-core/bin/lib/user-artifact-staging.cjs +705 -0
- package/gsd-core/bin/lib/validate-command-router.cjs +2 -2
- package/gsd-core/bin/lib/validate.cjs +20 -6
- package/gsd-core/bin/lib/vendor/README.md +75 -0
- package/gsd-core/bin/lib/vendor/js-yaml.cjs +3014 -0
- package/gsd-core/bin/lib/vendor/re2js.cjs +6480 -0
- package/gsd-core/bin/lib/vendor/re2js.d.cts +938 -0
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +272 -9
- package/gsd-core/bin/lib/verify-command-grounding.cjs +846 -0
- package/gsd-core/bin/lib/verify.cjs +453 -918
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +53 -32
- package/gsd-core/bin/lib/workstream-inventory.cjs +63 -10
- package/gsd-core/bin/lib/workstream-name-policy.cjs +25 -4
- package/gsd-core/bin/lib/workstream.cjs +2 -2
- package/gsd-core/bin/lib/worktree-base-ref.cjs +66 -12
- package/gsd-core/bin/lib/worktree-safety.cjs +341 -18
- package/gsd-core/bin/shared/config-defaults.manifest.json +8 -1
- package/gsd-core/bin/shared/config-schema.manifest.json +12 -1
- package/gsd-core/bin/shared/exit-codes.json +8 -0
- package/gsd-core/bin/shared/exit-codes.sh +20 -0
- package/gsd-core/bin/shared/model-catalog.json +8 -1
- package/gsd-core/references/agent-contracts.md +44 -26
- package/gsd-core/references/api-coverage.md +24 -2
- package/gsd-core/references/autonomous-smart-discuss.md +3 -3
- package/gsd-core/references/checkpoints.md +39 -21
- package/gsd-core/references/context-budget.md +1 -1
- package/gsd-core/references/decimal-phase-calculation.md +5 -5
- package/gsd-core/references/dispatch-isolation-gate.md +138 -0
- package/gsd-core/references/doc-conflict-engine.md +1 -1
- package/gsd-core/references/edge-probe.md +8 -0
- package/gsd-core/references/execute-mvp-tdd.md +4 -6
- package/gsd-core/references/execute-phase-between-wave-reset.md +15 -14
- package/gsd-core/references/execute-phase-context-guard.md +1 -1
- package/gsd-core/references/execute-phase-response-language.md +1 -1
- package/gsd-core/references/execute-phase-wave-guard.md +17 -11
- package/gsd-core/references/failing-direction.md +78 -0
- package/gsd-core/references/gate-prompts.md +1 -1
- package/gsd-core/references/git-integration.md +5 -5
- package/gsd-core/references/git-planning-commit.md +5 -4
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/loop-hook-dispatch.md +61 -2
- package/gsd-core/references/model-profiles.md +12 -4
- package/gsd-core/references/mvp-concepts.md +9 -9
- package/gsd-core/references/nyquist-compliance.md +74 -0
- package/gsd-core/references/offer-next.md +3 -5
- package/gsd-core/references/phase-argument-parsing.md +3 -3
- package/gsd-core/references/planner-failing-direction.md +53 -0
- package/gsd-core/references/planner-guidance.md +3 -9
- package/gsd-core/references/planner-human-verify-mode.md +15 -1
- package/gsd-core/references/planner-preconditions.md +1 -1
- package/gsd-core/references/planner-reviews.md +1 -1
- package/gsd-core/references/planner-revision.md +1 -1
- package/gsd-core/references/planner-verify-command-grounding.md +17 -0
- package/gsd-core/references/planning-config.md +44 -13
- package/gsd-core/references/reviewer-instances.md +31 -0
- package/gsd-core/references/revision-loop.md +1 -1
- package/gsd-core/references/runtime-aware-dispatch.md +1 -1
- package/gsd-core/references/specless-probe-fallback.md +1 -1
- package/gsd-core/references/tdd.md +1 -3
- package/gsd-core/references/ui-brand.md +65 -21
- package/gsd-core/references/ui-consideration-probe.md +1 -1
- package/gsd-core/references/universal-anti-patterns.md +5 -5
- package/gsd-core/references/verifier-phase-gates.md +192 -0
- package/gsd-core/references/verify-command-path-resolvability.md +42 -0
- package/gsd-core/references/verify-mvp-mode.md +2 -2
- package/gsd-core/references/workstream-flag.md +33 -17
- package/gsd-core/templates/README.md +1 -1
- package/gsd-core/templates/SECURITY.md +3 -3
- package/gsd-core/templates/UI-SPEC.md +25 -3
- package/gsd-core/templates/VALIDATION.md +3 -3
- package/gsd-core/templates/discussion-log.md +1 -1
- package/gsd-core/templates/phase-prompt.md +5 -4
- package/gsd-core/templates/state.md +11 -4
- package/gsd-core/templates/verification-report.md +9 -1
- package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
- package/gsd-core/workflows/add-backlog.md +1 -1
- package/gsd-core/workflows/add-phase.md +3 -3
- package/gsd-core/workflows/add-tests.md +3 -8
- package/gsd-core/workflows/add-todo.md +1 -1
- package/gsd-core/workflows/ai-integration-phase.md +13 -20
- package/gsd-core/workflows/audit-fix.md +12 -3
- package/gsd-core/workflows/audit-milestone.md +9 -9
- package/gsd-core/workflows/audit-uat.md +17 -2
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +2 -2
- package/gsd-core/workflows/autonomous.md +11 -27
- package/gsd-core/workflows/check-todos.md +1 -1
- package/gsd-core/workflows/cleanup.md +64 -5
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +14 -4
- package/gsd-core/workflows/code-review-fix.md +38 -11
- package/gsd-core/workflows/code-review.md +159 -52
- package/gsd-core/workflows/complete-milestone.md +151 -23
- package/gsd-core/workflows/debug.md +12 -8
- package/gsd-core/workflows/diagnose-issues.md +47 -15
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +5 -8
- package/gsd-core/workflows/discuss-phase/modes/default.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/text.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +1 -3
- package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
- package/gsd-core/workflows/discuss-phase.md +1 -1
- package/gsd-core/workflows/do.md +3 -6
- package/gsd-core/workflows/docs-update.md +5 -4
- package/gsd-core/workflows/edit-phase.md +27 -2
- package/gsd-core/workflows/eval-review.md +7 -14
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +142 -15
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +77 -0
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +24 -4
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/protected-branch.md +21 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +39 -0
- package/gsd-core/workflows/execute-phase.md +72 -100
- package/gsd-core/workflows/execute-plan.md +52 -15
- package/gsd-core/workflows/explore.md +131 -4
- package/gsd-core/workflows/extract-learnings.md +1 -1
- package/gsd-core/workflows/fast.md +10 -2
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +5 -5
- package/gsd-core/workflows/health.md +76 -10
- package/gsd-core/workflows/import.md +18 -15
- package/gsd-core/workflows/inbox.md +4 -5
- package/gsd-core/workflows/ingest-docs.md +49 -16
- package/gsd-core/workflows/insert-phase.md +5 -5
- package/gsd-core/workflows/list-seeds.md +5 -3
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +12 -23
- package/gsd-core/workflows/map-codebase.md +1 -1
- package/gsd-core/workflows/milestone-summary.md +1 -1
- package/gsd-core/workflows/mvp-phase.md +8 -5
- package/gsd-core/workflows/new-milestone.md +22 -29
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
- package/gsd-core/workflows/new-project.md +26 -40
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +14 -2
- package/gsd-core/workflows/pause-work.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +2 -4
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +3 -3
- package/gsd-core/workflows/plan-phase.md +162 -59
- package/gsd-core/workflows/plan-review-convergence.md +96 -11
- package/gsd-core/workflows/plant-seed.md +2 -2
- package/gsd-core/workflows/pr-branch.md +187 -51
- package/gsd-core/workflows/profile-user.md +16 -14
- package/gsd-core/workflows/progress.md +61 -18
- package/gsd-core/workflows/quick/steps/discussion-phase.md +1 -3
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +5 -7
- package/gsd-core/workflows/quick/steps/quick-verification.md +28 -9
- package/gsd-core/workflows/quick/steps/research-phase.md +4 -6
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +3 -3
- package/gsd-core/workflows/quick.md +55 -44
- package/gsd-core/workflows/remove-phase.md +4 -4
- package/gsd-core/workflows/remove-workspace.md +2 -2
- package/gsd-core/workflows/resume-project.md +8 -12
- package/gsd-core/workflows/review.md +219 -20
- package/gsd-core/workflows/scan.md +1 -1
- package/gsd-core/workflows/secure-phase.md +3 -3
- package/gsd-core/workflows/session-report.md +2 -1
- package/gsd-core/workflows/settings-advanced.md +7 -9
- package/gsd-core/workflows/settings-integrations.md +64 -31
- package/gsd-core/workflows/settings.md +69 -7
- package/gsd-core/workflows/ship.md +116 -50
- package/gsd-core/workflows/sketch-wrap-up.md +11 -17
- package/gsd-core/workflows/sketch.md +12 -18
- package/gsd-core/workflows/smart-entry.md +3 -5
- package/gsd-core/workflows/spec-phase.md +53 -13
- package/gsd-core/workflows/spike-wrap-up.md +7 -11
- package/gsd-core/workflows/spike.md +20 -31
- package/gsd-core/workflows/stats.md +2 -2
- package/gsd-core/workflows/sync-skills.md +64 -9
- package/gsd-core/workflows/thread.md +11 -7
- package/gsd-core/workflows/transition.md +49 -14
- package/gsd-core/workflows/ui-phase.md +15 -21
- package/gsd-core/workflows/ui-review.md +8 -12
- package/gsd-core/workflows/ultraplan-phase.md +5 -13
- package/gsd-core/workflows/undo.md +8 -16
- package/gsd-core/workflows/update.md +7 -11
- package/gsd-core/workflows/validate-phase.md +3 -3
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +25 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
- package/gsd-core/workflows/verify-work.md +66 -25
- package/hooks/dist/gsd-agent-isolation-guard.js +158 -30
- package/hooks/dist/gsd-check-update-worker.js +56 -13
- package/hooks/dist/gsd-check-update.js +19 -1
- package/hooks/dist/gsd-config-reload.js +18 -12
- package/hooks/dist/gsd-context-monitor.js +19 -10
- package/hooks/dist/gsd-cursor-post-tool.js +3 -1
- package/hooks/dist/gsd-cursor-pre-tool.js +2 -3
- package/hooks/dist/gsd-cursor-session-start.js +2 -1
- package/hooks/dist/gsd-cursor-stop.js +2 -1
- package/hooks/dist/gsd-cursor-subagent-start.js +83 -3
- package/hooks/dist/gsd-cursor-subagent-stop.js +6 -3
- package/hooks/dist/gsd-ensure-canonical-path.js +2 -1
- package/hooks/dist/gsd-graphify-update.sh +22 -18
- package/hooks/dist/gsd-node-runner.sh +76 -0
- package/hooks/dist/gsd-phase-boundary.sh +1 -0
- package/hooks/dist/gsd-prompt-guard.js +37 -27
- package/hooks/dist/gsd-read-guard.js +16 -7
- package/hooks/dist/gsd-read-injection-scanner.js +55 -32
- package/hooks/dist/gsd-session-state.sh +1 -0
- package/hooks/dist/gsd-statusline.js +231 -24
- package/hooks/dist/gsd-update-banner.js +22 -1
- package/hooks/dist/gsd-validate-commit.sh +80 -6
- package/hooks/dist/gsd-windsurf-pre-command.js +16 -11
- package/hooks/dist/gsd-windsurf-pre-write.js +22 -13
- package/hooks/dist/gsd-workflow-guard.js +162 -46
- package/hooks/dist/gsd-worktree-path-guard.js +36 -21
- package/hooks/dist/gsd-write-guard.js +35 -25
- package/hooks/dist/lib/cli-exit.js +560 -0
- package/hooks/dist/lib/exit-code-registry.js +98 -0
- package/hooks/dist/lib/git-cmd.js +92 -59
- package/hooks/dist/lib/git-probe.js +84 -0
- package/hooks/dist/lib/hook-exit.js +81 -0
- package/hooks/dist/lib/injection-patterns.js +45 -0
- package/hooks/dist/lib/isolation-deny-reason.js +39 -0
- package/hooks/dist/lib/isolation-sentinel.js +9 -0
- package/hooks/dist/managed-hooks-registry.cjs +3 -0
- package/hooks/gsd-agent-isolation-guard.js +158 -30
- package/hooks/gsd-check-update-worker.js +56 -13
- package/hooks/gsd-check-update.js +19 -1
- package/hooks/gsd-config-reload.js +18 -12
- package/hooks/gsd-context-monitor.js +19 -10
- package/hooks/gsd-cursor-post-tool.js +3 -1
- package/hooks/gsd-cursor-pre-tool.js +2 -3
- package/hooks/gsd-cursor-session-start.js +2 -1
- package/hooks/gsd-cursor-stop.js +2 -1
- package/hooks/gsd-cursor-subagent-start.js +83 -3
- package/hooks/gsd-cursor-subagent-stop.js +6 -3
- package/hooks/gsd-ensure-canonical-path.js +2 -1
- package/hooks/gsd-graphify-update.sh +22 -18
- package/hooks/gsd-node-runner.sh +76 -0
- package/hooks/gsd-phase-boundary.sh +1 -0
- package/hooks/gsd-prompt-guard.js +37 -27
- package/hooks/gsd-read-guard.js +16 -7
- package/hooks/gsd-read-injection-scanner.js +55 -32
- package/hooks/gsd-session-state.sh +1 -0
- package/hooks/gsd-statusline.js +231 -24
- package/hooks/gsd-update-banner.js +22 -1
- package/hooks/gsd-validate-commit.sh +80 -6
- package/hooks/gsd-windsurf-pre-command.js +16 -11
- package/hooks/gsd-windsurf-pre-write.js +22 -13
- package/hooks/gsd-workflow-guard.js +162 -46
- package/hooks/gsd-worktree-path-guard.js +36 -21
- package/hooks/gsd-write-guard.js +35 -25
- package/hooks/lib/cli-exit.js +560 -0
- package/hooks/lib/exit-code-registry.js +98 -0
- package/hooks/lib/git-cmd.js +92 -59
- package/hooks/lib/git-probe.js +84 -0
- package/hooks/lib/hook-exit.js +81 -0
- package/hooks/lib/injection-patterns.js +45 -0
- package/hooks/lib/isolation-deny-reason.js +39 -0
- package/hooks/lib/isolation-sentinel.js +9 -0
- package/hooks/managed-hooks-registry.cjs +3 -0
- package/package.json +28 -11
- package/pi/gsd.cjs +19 -5
- package/scripts/base64-scan.sh +74 -12
- package/scripts/baselines/planning-prompt-drift-baseline.json +4 -0
- package/scripts/baselines/planning-snapshot-bypass-baseline.json +12 -0
- package/scripts/baselines/unreachable-guard-drift-baseline.json +4 -0
- package/scripts/build-hooks.js +5 -0
- package/scripts/changeset/lint.cjs +60 -5
- package/scripts/check-alias-drift.cjs +7 -43
- package/scripts/check-contract-drift.cjs +297 -0
- package/scripts/check-glossary-refs.cjs +77 -15
- package/scripts/check-mutation-score-ratchet.cjs +156 -0
- package/scripts/ci-check-job-near-cap.cjs +49 -0
- package/scripts/ci-pr-mergeability.cjs +262 -0
- package/scripts/ci-test-scope.cjs +64 -14
- package/scripts/ci-timeout-report.cjs +230 -0
- package/scripts/command-contract-helpers.cjs +903 -1
- package/scripts/docs-guard-registry.cjs +396 -0
- package/scripts/gen-adr-index.cjs +728 -38
- package/scripts/gen-capability-registry.cjs +11 -21
- package/scripts/gen-context-index.cjs +2 -11
- package/scripts/gen-exit-code-docs.cjs +318 -0
- package/scripts/gen-exit-code-registry.cjs +891 -0
- package/scripts/gen-features.cjs +836 -0
- package/scripts/gen-health-docs.cjs +390 -0
- package/scripts/gen-hooks-cli-exit.cjs +239 -0
- package/scripts/gen-install-tree-fixtures.cjs +2 -2
- package/scripts/gen-inventory-manifest.cjs +50 -4
- package/scripts/gen-loop-host-contract.cjs +138 -25
- package/scripts/gen-registry.cjs +3 -14
- package/scripts/gen-scripts-cli-exit.cjs +185 -0
- package/scripts/gen-state-md-docs.cjs +727 -0
- package/scripts/{test-failure-reasons.cjs → gsd-test-gate-reasons.cjs} +6 -0
- package/scripts/lib/alias-drift-families.cjs +46 -0
- package/scripts/lib/ci-job-timing.cjs +72 -0
- package/scripts/lib/cli-exit.cjs +546 -44
- package/scripts/lib/drift-scan.cjs +308 -0
- package/scripts/lib/exit-code-registry.cjs +98 -0
- package/scripts/lib/ndjson-reporter.cjs +119 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +1 -26
- package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +4 -0
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +3 -0
- package/scripts/lint-canary-version-leak.cjs +73 -0
- package/scripts/lint-command-contract.cjs +96 -13
- package/scripts/lint-completion-predicate-drift.cjs +933 -0
- package/scripts/lint-completion-ratio-drift.cjs +214 -0
- package/scripts/lint-default-flip-documentation.cjs +193 -0
- package/scripts/lint-docs-guard-registration.cjs +495 -0
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +193 -0
- package/scripts/lint-eslint-glob-coverage.allowlist.json +38 -0
- package/scripts/lint-eslint-glob-coverage.cjs +340 -0
- package/scripts/{lint-fix-has-regression-test.cjs → lint-fix-has-regression-tests.cjs} +12 -6
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +237 -0
- package/scripts/lint-health-diagnostic-rule-table.cjs +461 -0
- package/scripts/lint-hooks-runtime-build-seam.cjs +262 -0
- package/scripts/lint-milestone-window-drift.cjs +468 -0
- package/scripts/lint-mutation-test-derivation-drift.cjs +86 -0
- package/scripts/lint-phase-enumeration-drift.cjs +492 -0
- package/scripts/lint-plan-count-drift.cjs +318 -0
- package/scripts/lint-planning-artifact-writer-drift.cjs +398 -0
- package/scripts/lint-planning-prompt-drift.cjs +471 -0
- package/scripts/lint-planning-snapshot-bypass-drift.cjs +544 -0
- package/scripts/lint-regression-test-names.cjs +15 -13
- package/scripts/lint-removed-but-needed.cjs +488 -0
- package/scripts/lint-seam-enforcement.cjs +182 -0
- package/scripts/lint-slug-derivation-drift.cjs +921 -0
- package/scripts/lint-source-test-name-collision.cjs +241 -0
- package/scripts/lint-state-field-drift.cjs +805 -0
- package/scripts/lint-state-write-path-drift.cjs +950 -0
- package/scripts/lint-test-file-count.allowlist.json +137 -8
- package/scripts/lint-test-file-count.cjs +25 -3
- package/scripts/lint-unreachable-guard-drift.cjs +830 -0
- package/scripts/lint-vendored-deps.cjs +297 -0
- package/scripts/mutation-matrix.cjs +599 -50
- package/scripts/pr-changed-files.cjs +63 -0
- package/scripts/pr-template-policy.cjs +14 -4
- package/scripts/prompt-injection-scan.sh +100 -14
- package/scripts/require-issue-link-policy.cjs +192 -0
- package/scripts/secret-scan.sh +75 -13
- package/scripts/select-docs-guards.cjs +56 -0
- package/scripts/sync-runtime-launcher.cjs +24 -7
- package/skills/gsd-autonomous/SKILL.md +0 -1
- package/skills/gsd-code-review/SKILL.md +1 -1
- package/skills/gsd-discuss-phase/SKILL.md +1 -1
- package/skills/gsd-execute-phase/SKILL.md +1 -2
- package/skills/gsd-import/SKILL.md +1 -1
- package/skills/gsd-map-codebase/SKILL.md +1 -1
- package/skills/gsd-mempalace-capture/SKILL.md +1 -1
- package/skills/gsd-mempalace-recall/SKILL.md +1 -1
- package/skills/gsd-new-milestone/SKILL.md +1 -1
- package/skills/gsd-next/SKILL.md +0 -1
- package/skills/gsd-plan-phase/SKILL.md +0 -1
- package/skills/gsd-progress/SKILL.md +0 -1
- package/skills/gsd-quick/SKILL.md +9 -5
- package/skills/gsd-review-backlog/SKILL.md +2 -1
- package/skills/gsd-stats/SKILL.md +0 -1
- package/skills/gsd-verify-work/SKILL.md +1 -1
- package/vscode/package.json +1 -1
- package/bin/lib/ui-safety-gate.cjs +0 -107
- package/gsd-core/workflows/discovery-phase.md +0 -298
- package/gsd-core/workflows/plan-milestone-gaps.md +0 -281
- package/gsd-core/workflows/verify-phase.md +0 -574
- package/scripts/affected-tests-lib.cjs +0 -554
- package/scripts/lint-allow-test-rule-refs.cjs +0 -162
- package/scripts/lint-emitted-drift-ack.cjs +0 -344
- package/scripts/run-affected-tests.cjs +0 -7
- package/scripts/run-tests.cjs +0 -1051
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Health Diagnostic — ROADMAP/disk consistency rules (Phase 11, #3309,
|
|
4
|
+
* ADR-3180 §8.2/§8.3/§8.5).
|
|
5
|
+
*
|
|
6
|
+
* Group: "ROADMAP/disk consistency" (design doc, "Rule table organization"
|
|
7
|
+
* table) — W006, W007.
|
|
8
|
+
*
|
|
9
|
+
* Ported behavior-preserving from `cmdValidateHealth`
|
|
10
|
+
* (`src/verify.cts:2029-2101`, the exact call sites for W006/W007).
|
|
11
|
+
*
|
|
12
|
+
* Both rules share ONE matcher — `matchPhaseDirs` + `normalizePhaseName`
|
|
13
|
+
* (`src/phase-id.cts`), the same canonical directory-resolution owner
|
|
14
|
+
* `verify.cts:2060/2073` already calls (its own #2528 comment explains why:
|
|
15
|
+
* pairing roadmap phases against disk by intersecting independently-derived
|
|
16
|
+
* TOKEN SETS mislabels digit-leading slugs like `05-80-20-cleanup` in BOTH
|
|
17
|
+
* directions at once — phase 5 reads as missing a directory (W006) AND that
|
|
18
|
+
* directory reads as not in the roadmap (W007) — so both rules here resolve
|
|
19
|
+
* through `matchPhaseDirs`, never a hand-rolled string/token comparison, and
|
|
20
|
+
* `dirsForPhase` below is the single call site both go through, so they
|
|
21
|
+
* cannot independently drift on what "matches" means (#2528's own bug
|
|
22
|
+
* class).
|
|
23
|
+
*
|
|
24
|
+
* DISK-SIDE SOURCE — `allPhaseDirNames`, NOT `phaseDirs` (found while
|
|
25
|
+
* implementing this file, fixed inline rather than deferred).
|
|
26
|
+
* `snapshot.phaseDirs` (Phase 10, `listMilestonePhaseDirs`) is WINDOWED: its
|
|
27
|
+
* `inWindow` filter (`getMilestonePhaseFilter`, `src/roadmap-parser.cts:1220`)
|
|
28
|
+
* admits a directory only when its phase id is a MEMBER of the roadmap's
|
|
29
|
+
* current-milestone-declared phase set (`isDirInMilestone`). That makes
|
|
30
|
+
* `phaseDirs.value` a subset that, by construction, can never contain a
|
|
31
|
+
* directory the roadmap does NOT declare — exactly the directory W007 exists
|
|
32
|
+
* to find. Sourced from `phaseDirs`, W007 would be structurally inert: every
|
|
33
|
+
* member of the set is already provably claimable. Verified empirically
|
|
34
|
+
* (`node -e` trace against a real `buildPlanningSnapshot`): a genuine orphan
|
|
35
|
+
* directory (`04-extra`, no roadmap entry) was silently absent from
|
|
36
|
+
* `phaseDirs.value` and W007 fired zero diagnostics. `phaseDirs`'s windowing
|
|
37
|
+
* also risks a W006 false positive for a phase declared in a NON-current
|
|
38
|
+
* milestone section (`roadmapDeclaredPhases` is built from the FULL raw
|
|
39
|
+
* ROADMAP, all milestones — `src/planning-snapshot.cts:398-436` — while
|
|
40
|
+
* `phaseDirs` is scoped to the current milestone only), so both rules here
|
|
41
|
+
* use the new, additive `allPhaseDirNames` field
|
|
42
|
+
* (`src/planning-snapshot.cts`) instead: every directory actually present
|
|
43
|
+
* under the active `phases/` root, unfiltered by roadmap declaration.
|
|
44
|
+
* Archived-milestone directory names (`verify.cts:2050`,
|
|
45
|
+
* `collectArchivedPhaseDirNames`) are still not exposed as directory NAMES
|
|
46
|
+
* on `PlanningSnapshot`, but the equivalent TOKEN set is: `checkW006` below
|
|
47
|
+
* additionally consults `snapshot.archivedPhaseTokens` (added for the
|
|
48
|
+
* W002/state-consistency group's #3652 fix, reused verbatim here — see that
|
|
49
|
+
* field's own doc comment) so a phase whose only directory lives in a
|
|
50
|
+
* milestone archive (shipped OR the current milestone's own archive layout)
|
|
51
|
+
* no longer reads as W006-missing (Bug 1, found post-migration: the archived
|
|
52
|
+
* fixtures under `tests/milestone-archive.test.cjs` and
|
|
53
|
+
* `tests/verify-health.test.cjs` regressed against the pre-migration
|
|
54
|
+
* `verify.cts` behavior). W007 still never scans archived dirs (its loop is
|
|
55
|
+
* `allPhaseDirNames.value`, the active `phases/` root only), so an archived
|
|
56
|
+
* dir still cannot spuriously read as W007-orphaned either — unchanged.
|
|
57
|
+
*
|
|
58
|
+
* Bug 2 (found alongside Bug 1): `dirsForPhase` below also runs a
|
|
59
|
+
* `phaseVariants()`-based fallback when `matchPhaseDirs` finds nothing — see
|
|
60
|
+
* its own doc comment. Pre-migration, `verify.cts:2071-2073`/`2092-2093` ran
|
|
61
|
+
* this as a SECOND, independent check the migrated matchPhaseDirs-only path
|
|
62
|
+
* had dropped, causing a false W006/W007 whenever ROADMAP and disk spelled
|
|
63
|
+
* the same phase with a different zero-padding (e.g. ROADMAP "01A" vs disk
|
|
64
|
+
* "1A-...").
|
|
65
|
+
*
|
|
66
|
+
* Not-started exclusion (verify.cts:2065/2075-2076,
|
|
67
|
+
* `buildNotStartedPhaseVariants`, `src/validate.cts:160`): the design doc's
|
|
68
|
+
* field table assigns this group only `roadmapDeclaredPhases`/`phaseDirs`,
|
|
69
|
+
* and `roadmapDeclaredPhases` (`src/planning-snapshot.cts:398-436`) does
|
|
70
|
+
* NOT filter not-started phases out — it returns every heading- and
|
|
71
|
+
* checklist-declared phase id regardless of checked state (confirmed by
|
|
72
|
+
* direct read: its `buildRoadmapPhaseVariants` call includes BOTH `[x]` and
|
|
73
|
+
* `[ ]` checklist entries). Omitting the exclusion here would regress a
|
|
74
|
+
* COMMON case: `gsd-core/templates/roadmap.md`'s "Initial Roadmap" shape
|
|
75
|
+
* declares every phase as an unchecked `- [ ] **Phase N: [Name]**` checklist
|
|
76
|
+
* item before any phase directory exists, so a freshly created ROADMAP.md
|
|
77
|
+
* would immediately spam one W006 per phase. `snapshot.roadmapPhaseCheckboxes`
|
|
78
|
+
* (`src/planning-snapshot.cts:457-480`, backs W011 in the STATE.md-consistency
|
|
79
|
+
* group) already parses exactly this `[x]`/`[ ]` state — `check(snapshot)`'s
|
|
80
|
+
* signature grants the full snapshot, not just this group's assigned column,
|
|
81
|
+
* so `isPhaseNotStarted` below reads it directly rather than re-deriving a
|
|
82
|
+
* third independent regex over raw ROADMAP text (forbidden by §8.1 rule 2).
|
|
83
|
+
* KNOWN GAP, disclosed rather than silently dropped: `roadmapPhaseCheckboxes`
|
|
84
|
+
* is keyed by `PHASE_NUMBER_TOKEN_SOURCE` (`phase-id.cts:54`, no dash), so a
|
|
85
|
+
* milestone-dash-prefixed phase id ("2-01") can never match a checkbox key —
|
|
86
|
+
* unlike the original `buildNotStartedPhaseVariants`, which captures the
|
|
87
|
+
* fuller `[\w][\w.-]*` grammar (dashes included). For that id shape only,
|
|
88
|
+
* this rule's not-started exclusion silently no-ops (never excludes), which
|
|
89
|
+
* is the conservative direction (a possible false W006, not a suppressed
|
|
90
|
+
* true one).
|
|
91
|
+
*
|
|
92
|
+
* Design: .gsd/phase/refactor-3309-health-diagnostic-rule-table/40-design.md
|
|
93
|
+
*
|
|
94
|
+
* ADR-457 build-at-publish: source in
|
|
95
|
+
* src/health-diagnostic-rules/roadmap-disk-consistency.cts, compiled to
|
|
96
|
+
* gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs
|
|
97
|
+
* (gitignored).
|
|
98
|
+
*/
|
|
99
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
100
|
+
const healthDiagnosticMod = require("../health-diagnostic-types.cjs");
|
|
101
|
+
const { SEVERITY, adviseRemedy } = healthDiagnosticMod;
|
|
102
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
103
|
+
const planningScopeMod = require("../planning-scope.cjs");
|
|
104
|
+
const { SCOPE } = planningScopeMod;
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
106
|
+
const phaseIdMod = require("../phase-id.cjs");
|
|
107
|
+
const { matchPhaseDirs, normalizePhaseName, extractPhaseToken, isSentinelPhaseId, isSentinelPhaseDir } = phaseIdMod;
|
|
108
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
109
|
+
const validateMod = require("../validate.cjs");
|
|
110
|
+
const { phaseVariants } = validateMod;
|
|
111
|
+
// ─── Shared matcher — the single call site both W006 and W007 go through ───
|
|
112
|
+
/**
|
|
113
|
+
* Every on-disk directory (from `allPhaseDirNames.value`) that `phaseId`
|
|
114
|
+
* resolves to via the canonical `matchPhaseDirs` selection. Both `checkW006`
|
|
115
|
+
* (does ANY directory resolve) and `computeClaimedDirs` (which directories
|
|
116
|
+
* does the roadmap claim, for W007) call this — one matcher, reused, per the
|
|
117
|
+
* file-level comment.
|
|
118
|
+
*/
|
|
119
|
+
function dirsForPhase(dirs, phaseId) {
|
|
120
|
+
const canonical = matchPhaseDirs(dirs, normalizePhaseName(phaseId)).matches;
|
|
121
|
+
if (canonical.length > 0)
|
|
122
|
+
return canonical;
|
|
123
|
+
// Bug 2 (#3309 W006/W007 migration cluster, found while fixing the
|
|
124
|
+
// originally-reported archived-directory gap): `matchPhaseDirs`'s
|
|
125
|
+
// `phaseTokenMatches` compares `extractPhaseToken(dir)` (the directory's
|
|
126
|
+
// LITERAL, un-normalized digit run — e.g. "1A" for `1A-suffix-phase`)
|
|
127
|
+
// against `normalizePhaseName(phaseId)` (which PADS — "01A") case-
|
|
128
|
+
// insensitively, but never unifies a padding/letter-suffix mismatch
|
|
129
|
+
// BETWEEN the two sides: "1A" !== "01A" even though they name the same
|
|
130
|
+
// phase. Pre-migration, `verify.cts:2071-2073`/`2092-2093` ran a SECOND,
|
|
131
|
+
// independent check here — `[...phaseVariants(p)].some((v) =>
|
|
132
|
+
// diskPhases.has(v))` — that the migrated matchPhaseDirs-only path
|
|
133
|
+
// dropped. `phaseVariants` (`validate.cts:101`) is symmetric
|
|
134
|
+
// (padded<->unpadded, letter-suffix preserved both ways), so generating
|
|
135
|
+
// variants from `phaseId` and checking raw-disk-token membership is
|
|
136
|
+
// equivalent to intersecting `phaseVariants(phaseId)` with
|
|
137
|
+
// `phaseVariants(diskToken)` — variants always include their own input
|
|
138
|
+
// verbatim, so this fallback catches exactly the cases `matchPhaseDirs`
|
|
139
|
+
// alone misses without re-deriving a second matcher.
|
|
140
|
+
const variants = phaseVariants(phaseId);
|
|
141
|
+
return dirs.filter((d) => {
|
|
142
|
+
const token = extractPhaseToken(d).toUpperCase();
|
|
143
|
+
for (const variant of variants) {
|
|
144
|
+
if (token === variant.toUpperCase())
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
return false;
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* True when `phaseId` has an unchecked (`[ ]`) checklist entry in
|
|
152
|
+
* `roadmapPhaseCheckboxes` under any of its padding/case variants
|
|
153
|
+
* (`phaseVariants`, `src/validate.cts:101` — the same variant-expansion
|
|
154
|
+
* owner `verify.cts:2071/2075` uses for this exact exclusion). See the
|
|
155
|
+
* file-level comment for the KNOWN GAP on dash-shaped ids.
|
|
156
|
+
*/
|
|
157
|
+
function isPhaseNotStarted(phaseId, checkboxes) {
|
|
158
|
+
for (const variant of phaseVariants(phaseId)) {
|
|
159
|
+
if (Object.prototype.hasOwnProperty.call(checkboxes, variant) && checkboxes[variant] === false) {
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
// ─── W006 — ROADMAP.md declares a phase with no directory on disk ─────────
|
|
166
|
+
// (verify.cts:2067-2084)
|
|
167
|
+
function checkW006(snapshot) {
|
|
168
|
+
// Mirrors verify.cts:2029's `if (fs.existsSync(roadmapPath))` guard: ROADMAP.md
|
|
169
|
+
// absent or unreadable means the field degrades to `{value: [], scope:
|
|
170
|
+
// UNREADABLE}` (`src/planning-snapshot.cts:401-403/407-409`) and NEITHER
|
|
171
|
+
// W006 nor W007 evaluates — an empty declared-phase list must not be
|
|
172
|
+
// mistaken for "the roadmap legitimately declares zero phases" here.
|
|
173
|
+
if (snapshot.roadmapDeclaredPhases.scope !== SCOPE.COMPLETE)
|
|
174
|
+
return [];
|
|
175
|
+
const dirs = snapshot.allPhaseDirNames.value;
|
|
176
|
+
const archivedTokens = new Set(snapshot.archivedPhaseTokens.value);
|
|
177
|
+
const checkboxes = snapshot.roadmapPhaseCheckboxes.value;
|
|
178
|
+
const diagnostics = [];
|
|
179
|
+
for (const { phaseId } of snapshot.roadmapDeclaredPhases.value) {
|
|
180
|
+
// #3225: sentinel phase ids (999.x/0.x) are never-on-roadmap by
|
|
181
|
+
// convention; a sentinel heading shouldn't demand a directory.
|
|
182
|
+
if (isSentinelPhaseId(phaseId))
|
|
183
|
+
continue;
|
|
184
|
+
if (dirsForPhase(dirs, phaseId).length > 0)
|
|
185
|
+
continue;
|
|
186
|
+
// Bug 1 (#3309 W006/W007 migration cluster): a phase whose ONLY
|
|
187
|
+
// directory lives under a milestone archive
|
|
188
|
+
// (`.planning/milestones/vX.Y-phases/<phase>/`, shipped OR the current
|
|
189
|
+
// milestone's own archive layout) must not read as "no directory on
|
|
190
|
+
// disk" — mirrors `verify.cts:2038`'s
|
|
191
|
+
// `forEachArchivedPhaseToken(planBase, (token) => diskPhases.add(token))`
|
|
192
|
+
// feeding the archived-phase token set into this exact existence check.
|
|
193
|
+
// `snapshot.archivedPhaseTokens` (`src/planning-snapshot.cts`) is the
|
|
194
|
+
// same token set, reused verbatim from the W002/state-consistency
|
|
195
|
+
// group's own fix for the analogous gap — not a re-derivation.
|
|
196
|
+
if ([...phaseVariants(phaseId)].some((v) => archivedTokens.has(v)))
|
|
197
|
+
continue;
|
|
198
|
+
if (isPhaseNotStarted(phaseId, checkboxes))
|
|
199
|
+
continue;
|
|
200
|
+
diagnostics.push({
|
|
201
|
+
code: 'W006',
|
|
202
|
+
severity: SEVERITY.WARNING,
|
|
203
|
+
message: `Phase ${phaseId} in ROADMAP.md but no directory on disk`,
|
|
204
|
+
remedy: adviseRemedy('Create phase directory or remove from roadmap'),
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
return diagnostics;
|
|
208
|
+
}
|
|
209
|
+
// ─── W007 — an on-disk phase directory has no matching ROADMAP entry ──────
|
|
210
|
+
// (verify.cts:2086-2101)
|
|
211
|
+
/** Every directory in `dirs` that ANY declared roadmap phase resolves to. */
|
|
212
|
+
function computeClaimedDirs(dirs, declaredPhases) {
|
|
213
|
+
const claimed = new Set();
|
|
214
|
+
for (const { phaseId } of declaredPhases) {
|
|
215
|
+
for (const dir of dirsForPhase(dirs, phaseId))
|
|
216
|
+
claimed.add(dir);
|
|
217
|
+
}
|
|
218
|
+
return claimed;
|
|
219
|
+
}
|
|
220
|
+
function checkW007(snapshot) {
|
|
221
|
+
// Same guard as W006 — see its comment.
|
|
222
|
+
if (snapshot.roadmapDeclaredPhases.scope !== SCOPE.COMPLETE)
|
|
223
|
+
return [];
|
|
224
|
+
const dirs = snapshot.allPhaseDirNames.value;
|
|
225
|
+
const claimedDirs = computeClaimedDirs(dirs, snapshot.roadmapDeclaredPhases.value);
|
|
226
|
+
const diagnostics = [];
|
|
227
|
+
for (const dirName of dirs) {
|
|
228
|
+
// `extractPhaseToken` is the phase-id.cts owner `PHASE_TOKEN_FROM_DIR_RE`
|
|
229
|
+
// (`src/validate.cts:73-76`) is documented to match exactly
|
|
230
|
+
// (verify.cts's original `p` key from `collectDiskPhaseEntries`,
|
|
231
|
+
// `verify.cts:1373-1397`) — same token, relocated read, not reinvented.
|
|
232
|
+
const token = extractPhaseToken(dirName);
|
|
233
|
+
// #3225: a sentinel dir on disk (999-interim, 0-drafts) is defined as
|
|
234
|
+
// never-on-roadmap; it must not trigger W007. #3639: judged on the DIR
|
|
235
|
+
// NAME via the dir-aware recognizer — the extracted token is
|
|
236
|
+
// milestone-stripped, so a bracket sentinel (GSD.999-07-icebox) was
|
|
237
|
+
// invisible to the id predicate and false-fired as an orphan.
|
|
238
|
+
if (isSentinelPhaseDir(dirName))
|
|
239
|
+
continue;
|
|
240
|
+
if (claimedDirs.has(dirName))
|
|
241
|
+
continue;
|
|
242
|
+
diagnostics.push({
|
|
243
|
+
code: 'W007',
|
|
244
|
+
severity: SEVERITY.WARNING,
|
|
245
|
+
message: `Phase ${token} exists on disk but not in ROADMAP.md`,
|
|
246
|
+
remedy: adviseRemedy('Add to roadmap or remove directory'),
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
return diagnostics;
|
|
250
|
+
}
|
|
251
|
+
// ─── Exports ────────────────────────────────────────────────────────────────
|
|
252
|
+
const RULES = [
|
|
253
|
+
{
|
|
254
|
+
code: 'W006',
|
|
255
|
+
severity: SEVERITY.WARNING,
|
|
256
|
+
description: 'Phase in ROADMAP but no directory',
|
|
257
|
+
repairable: false,
|
|
258
|
+
check: checkW006,
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
code: 'W007',
|
|
262
|
+
severity: SEVERITY.WARNING,
|
|
263
|
+
description: 'Phase on disk but not in ROADMAP',
|
|
264
|
+
repairable: false,
|
|
265
|
+
check: checkW007,
|
|
266
|
+
},
|
|
267
|
+
];
|
|
268
|
+
module.exports = { RULES };
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Health Diagnostic — Root existence + PROJECT.md rules (Phase 11, #3309,
|
|
4
|
+
* ADR-3180 §8.2/§8.3/§8.5).
|
|
5
|
+
*
|
|
6
|
+
* Group: "Root existence + PROJECT.md" (design doc, "Rule table organization"
|
|
7
|
+
* table) — E002, E003, E004, W001. E001 (the `.planning/` root missing guard)
|
|
8
|
+
* stays OUTSIDE the rule table entirely per the design doc's "Two guards that
|
|
9
|
+
* stay OUTSIDE the rule table entirely" section — it is not a row here.
|
|
10
|
+
*
|
|
11
|
+
* Ported behavior-preserving from `cmdValidateHealth`
|
|
12
|
+
* (`src/verify.cts:1681-1705`), the exact call sites for E002/E003/E004/W001.
|
|
13
|
+
*
|
|
14
|
+
* E002's original message interpolates `${slash('new-project')}`
|
|
15
|
+
* (`verify.cts:1682`, ``Run ${slash('new-project')} to create``) and E003's
|
|
16
|
+
* interpolates `${slash('new-milestone')}` (`verify.cts:1694`, ``Run
|
|
17
|
+
* ${slash('new-milestone')} to create roadmap``) — both per-project
|
|
18
|
+
* runtime-resolved values (`formatGsdSlash`, `src/runtime-slash.cts`) this
|
|
19
|
+
* rule's `(snapshot) => Diagnostic[]` signature has no access to (§8.1 rule
|
|
20
|
+
* 1 forbids ambient I/O, including `cwd`, inside `check`). Hardcodes the
|
|
21
|
+
* canonical `/gsd-new-project`/`/gsd-new-milestone` hyphen form instead,
|
|
22
|
+
* mirroring the sibling "config.json validation" group's W016 rule
|
|
23
|
+
* (`src/health-diagnostic-rules/config-validation.cts`), which hardcodes
|
|
24
|
+
* `/gsd-ai-integration-phase` the same way for the identical reason.
|
|
25
|
+
*
|
|
26
|
+
* Design: .gsd/phase/refactor-3309-health-diagnostic-rule-table/40-design.md
|
|
27
|
+
*
|
|
28
|
+
* ADR-457 build-at-publish: source in src/health-diagnostic-rules/root-existence.cts,
|
|
29
|
+
* compiled to gsd-core/bin/lib/health-diagnostic-rules/root-existence.cjs (gitignored).
|
|
30
|
+
*/
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
32
|
+
const healthDiagnosticMod = require("../health-diagnostic-types.cjs");
|
|
33
|
+
const { SEVERITY, REMEDY_ACTION, REMEDY_RISK, adviseRemedy } = healthDiagnosticMod;
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
35
|
+
const planningScopeMod = require("../planning-scope.cjs");
|
|
36
|
+
const { SCOPE } = planningScopeMod;
|
|
37
|
+
// ─── E002 — PROJECT.md not found (verify.cts:1682) ─────────────────────────
|
|
38
|
+
function checkE002(snapshot) {
|
|
39
|
+
if (snapshot.projectSections.exists)
|
|
40
|
+
return [];
|
|
41
|
+
return [
|
|
42
|
+
{
|
|
43
|
+
code: 'E002',
|
|
44
|
+
severity: SEVERITY.ERROR,
|
|
45
|
+
message: 'PROJECT.md not found',
|
|
46
|
+
remedy: adviseRemedy('/gsd-new-project'),
|
|
47
|
+
},
|
|
48
|
+
];
|
|
49
|
+
}
|
|
50
|
+
// ─── E003 — ROADMAP.md not found (verify.cts:1694) ─────────────────────────
|
|
51
|
+
//
|
|
52
|
+
// Condition uses `snapshot.milestone.scope === SCOPE.UNREADABLE`
|
|
53
|
+
// (`getMilestoneInfo`, `src/roadmap-parser.cts`). KNOWN AMBIGUITY (flagged in
|
|
54
|
+
// this batch's report, not silently papered over): `getMilestoneInfo` returns
|
|
55
|
+
// `SCOPE.UNREADABLE` for TWO distinct causes it does not otherwise
|
|
56
|
+
// distinguish — (1) ROADMAP.md absent (`platformReadSync` returns `null` ->
|
|
57
|
+
// synthetic `Error('missing')`, no errno, `reportUnreadableRoadmap` finds no
|
|
58
|
+
// `.code` and stays silent) and (2) ROADMAP.md present but unreadable (a real
|
|
59
|
+
// read fault, e.g. EACCES/EISDIR, which DOES carry an errno and fires
|
|
60
|
+
// `warnUnusableInput(ROADMAP_UNREADABLE)`). Unlike `config`/`projectSections`,
|
|
61
|
+
// `milestone` carries no `exists` discriminator, so this rule cannot tell the
|
|
62
|
+
// two apart from the snapshot alone without adding cwd/fs access to `check`
|
|
63
|
+
// (forbidden by §8.1 rule 1). This is a best-effort port of the pre-migration
|
|
64
|
+
// condition (`!fs.existsSync(roadmapPath)`), which itself only asked "does
|
|
65
|
+
// the file exist" — this rule now also fires (message-mismatched, but
|
|
66
|
+
// error-preserving) on a present-but-corrupt ROADMAP.md.
|
|
67
|
+
function checkE003(snapshot) {
|
|
68
|
+
if (snapshot.milestone.scope !== SCOPE.UNREADABLE)
|
|
69
|
+
return [];
|
|
70
|
+
return [
|
|
71
|
+
{
|
|
72
|
+
code: 'E003',
|
|
73
|
+
severity: SEVERITY.ERROR,
|
|
74
|
+
message: 'ROADMAP.md not found',
|
|
75
|
+
remedy: adviseRemedy('/gsd-new-milestone'),
|
|
76
|
+
},
|
|
77
|
+
];
|
|
78
|
+
}
|
|
79
|
+
// ─── E004 — STATE.md not found (verify.cts:1697) ───────────────────────────
|
|
80
|
+
//
|
|
81
|
+
// Condition uses `snapshot.currentPhaseLabel.scope === SCOPE.UNREADABLE`
|
|
82
|
+
// (`buildStateFields`, `src/planning-snapshot.cts:210-249`). KNOWN GAP
|
|
83
|
+
// (flagged in this batch's report): `buildStateFields` collapses TWO distinct
|
|
84
|
+
// causes into the same `UNREADABLE` scope with no discriminator field at
|
|
85
|
+
// all — STATE.md absent (`platformReadSync` returns `null`, a real
|
|
86
|
+
// non-answer, `warnUnusableInput` NOT called) and STATE.md present but
|
|
87
|
+
// unreadable (any other read error, e.g. EISDIR, corruption,
|
|
88
|
+
// `warnUnusableInput(STATE_UNREADABLE)` fires). Unlike `config`, there is no
|
|
89
|
+
// `exists` flag on `currentPhaseLabel` (or on `PlanningSnapshot` generally)
|
|
90
|
+
// to distinguish "STATE.md was never created" from "STATE.md exists but
|
|
91
|
+
// could not be read" — this is a REAL gap in the current 15-field
|
|
92
|
+
// `PlanningSnapshot` shape, not something this rule can work around without
|
|
93
|
+
// extending that snapshot (out of this batch's scope per the brief). This
|
|
94
|
+
// rule is therefore a best-effort port: it fires E004 ("STATE.md not found")
|
|
95
|
+
// for both causes, exactly mirroring what `snapshot.currentPhaseLabel.scope`
|
|
96
|
+
// can express today.
|
|
97
|
+
//
|
|
98
|
+
// Remedy is `regenerateState`, one of the two DESTRUCTIVE-risk actions (loses
|
|
99
|
+
// session history, design doc "Risk assignment" section) — per §8.3 rule 3
|
|
100
|
+
// `--repair` will refuse to auto-apply it once `applyRepairs`'s dispatch
|
|
101
|
+
// wires this rule in; the remedy is still described (ADVISE-shaped for
|
|
102
|
+
// display, per `applyRepairs`'s own contract) but never executed.
|
|
103
|
+
function checkE004(snapshot) {
|
|
104
|
+
if (snapshot.currentPhaseLabel.scope !== SCOPE.UNREADABLE)
|
|
105
|
+
return [];
|
|
106
|
+
return [
|
|
107
|
+
{
|
|
108
|
+
code: 'E004',
|
|
109
|
+
severity: SEVERITY.ERROR,
|
|
110
|
+
message: 'STATE.md not found',
|
|
111
|
+
remedy: {
|
|
112
|
+
action: REMEDY_ACTION.REGENERATE_STATE,
|
|
113
|
+
risk: REMEDY_RISK.DESTRUCTIVE,
|
|
114
|
+
args: {},
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
];
|
|
118
|
+
}
|
|
119
|
+
// ─── W001 — PROJECT.md missing a required section (verify.cts:1684-1690) ──
|
|
120
|
+
//
|
|
121
|
+
// `REQUIRED_SECTIONS` carries the exact `## `-prefixed strings
|
|
122
|
+
// `verify.cts:1685` uses in its message text; membership is tested against
|
|
123
|
+
// `snapshot.projectSections.value`, which `buildProjectSectionsField`
|
|
124
|
+
// (`src/planning-snapshot.cts:367-381`) stores WITHOUT the `##` prefix (its
|
|
125
|
+
// `/^##\s+(.+)$/gm` capture group), so each required string's own `## `
|
|
126
|
+
// prefix is stripped before the membership check. `projectSections.value ===
|
|
127
|
+
// null` (PROJECT.md absent OR unreadable) emits zero diagnostics — E002
|
|
128
|
+
// already reports absence; this rule does not double-report it.
|
|
129
|
+
const REQUIRED_SECTIONS = ['## What This Is', '## Core Value', '## Requirements'];
|
|
130
|
+
function checkW001(snapshot) {
|
|
131
|
+
const { value } = snapshot.projectSections;
|
|
132
|
+
if (value === null)
|
|
133
|
+
return [];
|
|
134
|
+
const diagnostics = [];
|
|
135
|
+
for (const required of REQUIRED_SECTIONS) {
|
|
136
|
+
const heading = required.replace(/^##\s+/, '');
|
|
137
|
+
if (!value.includes(heading)) {
|
|
138
|
+
diagnostics.push({
|
|
139
|
+
code: 'W001',
|
|
140
|
+
severity: SEVERITY.WARNING,
|
|
141
|
+
message: `PROJECT.md missing section: ${required}`,
|
|
142
|
+
remedy: adviseRemedy('Add section manually'),
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return diagnostics;
|
|
147
|
+
}
|
|
148
|
+
// ─── Exports ────────────────────────────────────────────────────────────────
|
|
149
|
+
const RULES = [
|
|
150
|
+
{ code: 'E002', severity: SEVERITY.ERROR, description: 'PROJECT.md not found', repairable: false, check: checkE002 },
|
|
151
|
+
{ code: 'E003', severity: SEVERITY.ERROR, description: 'ROADMAP.md not found', repairable: false, check: checkE003 },
|
|
152
|
+
{ code: 'E004', severity: SEVERITY.ERROR, description: 'STATE.md not found', repairable: false, check: checkE004 },
|
|
153
|
+
{
|
|
154
|
+
code: 'W001',
|
|
155
|
+
severity: SEVERITY.WARNING,
|
|
156
|
+
description: 'PROJECT.md missing required section',
|
|
157
|
+
repairable: false,
|
|
158
|
+
check: checkW001,
|
|
159
|
+
},
|
|
160
|
+
];
|
|
161
|
+
module.exports = { RULES };
|