@opengsd/gsd-core 1.11.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 +1 -1
- package/agents/gsd-debugger.md +1 -1
- package/agents/gsd-dom-verifier.md +169 -0
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +17 -9
- package/agents/gsd-framework-selector.md +1 -3
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.md +0 -1
- package/agents/gsd-pattern-mapper.md +11 -0
- package/agents/gsd-phase-researcher.md +3 -1
- package/agents/gsd-plan-checker.md +15 -55
- package/agents/gsd-planner.md +6 -4
- 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-verifier.md +1 -1
- package/bin/install.js +609 -134
- package/commands/gsd/discuss-phase.md +1 -1
- package/commands/gsd/import.md +1 -1
- package/commands/gsd/quick.md +8 -4
- package/gsd-core/bin/gsd-tools.cjs +567 -51
- package/gsd-core/bin/lib/active-workstream-store.cjs +8 -0
- package/gsd-core/bin/lib/adr-parser.cjs +13 -7
- package/gsd-core/bin/lib/agent-install-check.cjs +162 -0
- package/gsd-core/bin/lib/api-coverage.cjs +30 -9
- package/gsd-core/bin/lib/artifacts.cjs +2 -0
- package/gsd-core/bin/lib/assumption-delta.cjs +30 -11
- package/gsd-core/bin/lib/audit.cjs +163 -41
- package/gsd-core/bin/lib/broken-windows.cjs +306 -28
- package/gsd-core/bin/lib/capability-lock.cjs +10 -4
- package/gsd-core/bin/lib/capability-registry.cjs +336 -95
- package/gsd-core/bin/lib/capability-state.cjs +18 -3
- package/gsd-core/bin/lib/capability-validator.cjs +205 -18
- package/gsd-core/bin/lib/check-command-router.cjs +145 -5
- 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 +410 -4
- package/gsd-core/bin/lib/command-arg-projection.cjs +144 -14
- package/gsd-core/bin/lib/command-routing-hub.cjs +31 -2
- package/gsd-core/bin/lib/commands.cjs +543 -44
- package/gsd-core/bin/lib/complexity-trigger.cjs +26 -6
- package/gsd-core/bin/lib/config-loader.cjs +118 -29
- package/gsd-core/bin/lib/config.cjs +92 -2
- package/gsd-core/bin/lib/configuration.cjs +129 -37
- package/gsd-core/bin/lib/core-utils.cjs +84 -7
- 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/frontmatter.cjs +840 -305
- package/gsd-core/bin/lib/gap-checker.cjs +27 -3
- package/gsd-core/bin/lib/git-base-branch.cjs +174 -39
- package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +7 -3
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +6 -3
- package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +22 -8
- package/gsd-core/bin/lib/health-diagnostic.cjs +23 -3
- package/gsd-core/bin/lib/host-integration.cjs +39 -6
- package/gsd-core/bin/lib/init-command-router.cjs +118 -21
- package/gsd-core/bin/lib/init.cjs +120 -41
- package/gsd-core/bin/lib/install-engine.cjs +68 -3
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +33 -1
- package/gsd-core/bin/lib/install-profiles.cjs +78 -4
- 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 +10 -7
- package/gsd-core/bin/lib/intel.cjs +101 -26
- package/gsd-core/bin/lib/io.cjs +160 -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-table.cjs +52 -4
- package/gsd-core/bin/lib/milestone.cjs +90 -5
- package/gsd-core/bin/lib/model-catalog.cjs +177 -19
- package/gsd-core/bin/lib/model-resolver.cjs +10 -28
- package/gsd-core/bin/lib/onboard-projection.cjs +5 -1
- package/gsd-core/bin/lib/phase-estimation.cjs +17 -8
- package/gsd-core/bin/lib/phase-id.cjs +70 -4
- package/gsd-core/bin/lib/phase-lifecycle.cjs +24 -16
- package/gsd-core/bin/lib/phase-locator.cjs +138 -17
- package/gsd-core/bin/lib/phase.cjs +405 -84
- package/gsd-core/bin/lib/plan-document.cjs +263 -0
- package/gsd-core/bin/lib/plan-scan.cjs +13 -2
- 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-snapshot.cjs +18 -14
- package/gsd-core/bin/lib/planning-workspace.cjs +56 -0
- package/gsd-core/bin/lib/probe-core.cjs +4 -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 +71 -45
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +9 -9
- package/gsd-core/bin/lib/roadmap-command-router.cjs +45 -31
- package/gsd-core/bin/lib/roadmap-parser.cjs +79 -16
- package/gsd-core/bin/lib/roadmap.cjs +74 -19
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +96 -8
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +34 -1
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +287 -55
- package/gsd-core/bin/lib/runtime-identity.cjs +234 -0
- package/gsd-core/bin/lib/runtime-slash.cjs +72 -2
- package/gsd-core/bin/lib/shell-command-projection.cjs +71 -8
- package/gsd-core/bin/lib/smart-entry.cjs +12 -22
- package/gsd-core/bin/lib/spec-section.cjs +12 -7
- package/gsd-core/bin/lib/state-command-router.cjs +47 -18
- package/gsd-core/bin/lib/state-contract.cjs +359 -0
- package/gsd-core/bin/lib/state-document.cjs +186 -0
- package/gsd-core/bin/lib/state-md-schema.cjs +221 -0
- package/gsd-core/bin/lib/state-transition.cjs +517 -101
- package/gsd-core/bin/lib/state.cjs +946 -163
- package/gsd-core/bin/lib/surface.cjs +10 -2
- 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/uat-predicate.cjs +58 -20
- package/gsd-core/bin/lib/uat.cjs +1376 -125
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +9 -1
- package/gsd-core/bin/lib/ui-safety-gate.cjs +37 -7
- package/gsd-core/bin/lib/unusable-input.cjs +13 -0
- package/gsd-core/bin/lib/validate-command-router.cjs +2 -2
- package/gsd-core/bin/lib/vendor/README.md +43 -5
- package/gsd-core/bin/lib/vendor/js-yaml.cjs +3014 -0
- package/gsd-core/bin/lib/verification.cjs +14 -1
- package/gsd-core/bin/lib/verify-command-grounding.cjs +846 -0
- package/gsd-core/bin/lib/verify.cjs +95 -40
- package/gsd-core/bin/lib/workstream-name-policy.cjs +25 -4
- package/gsd-core/bin/lib/worktree-base-ref.cjs +66 -12
- package/gsd-core/bin/lib/worktree-safety.cjs +177 -21
- package/gsd-core/bin/shared/config-defaults.manifest.json +7 -1
- package/gsd-core/bin/shared/config-schema.manifest.json +5 -0
- 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 +3 -2
- 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 +37 -19
- package/gsd-core/references/decimal-phase-calculation.md +5 -5
- package/gsd-core/references/edge-probe.md +8 -0
- package/gsd-core/references/execute-mvp-tdd.md +1 -3
- package/gsd-core/references/execute-phase-between-wave-reset.md +9 -12
- package/gsd-core/references/execute-phase-wave-guard.md +11 -9
- 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 +3 -3
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/loop-hook-dispatch.md +22 -0
- package/gsd-core/references/model-profiles.md +1 -1
- 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-human-verify-mode.md +15 -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 +37 -8
- package/gsd-core/references/reviewer-instances.md +31 -0
- package/gsd-core/references/runtime-aware-dispatch.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 +2 -2
- package/gsd-core/references/verify-command-path-resolvability.md +42 -0
- package/gsd-core/references/verify-mvp-mode.md +1 -1
- package/gsd-core/references/workstream-flag.md +11 -11
- 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/phase-prompt.md +3 -0
- package/gsd-core/templates/state.md +7 -0
- 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 +4 -9
- 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 +10 -26
- package/gsd-core/workflows/check-todos.md +1 -1
- package/gsd-core/workflows/cleanup.md +2 -2
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +1 -1
- package/gsd-core/workflows/code-review-fix.md +1 -1
- package/gsd-core/workflows/code-review.md +121 -40
- package/gsd-core/workflows/complete-milestone.md +15 -10
- package/gsd-core/workflows/debug.md +5 -3
- package/gsd-core/workflows/diagnose-issues.md +12 -6
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +3 -7
- 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 +2 -2
- 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 +1 -1
- package/gsd-core/workflows/eval-review.md +4 -9
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +113 -11
- 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 +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +22 -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 +38 -54
- package/gsd-core/workflows/execute-plan.md +17 -12
- package/gsd-core/workflows/explore.md +1 -1
- package/gsd-core/workflows/extract-learnings.md +1 -1
- package/gsd-core/workflows/fast.md +2 -2
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +5 -5
- package/gsd-core/workflows/health.md +3 -6
- package/gsd-core/workflows/import.md +14 -11
- package/gsd-core/workflows/inbox.md +4 -5
- package/gsd-core/workflows/ingest-docs.md +44 -11
- 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 +2 -2
- package/gsd-core/workflows/new-milestone.md +9 -21
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
- package/gsd-core/workflows/new-project.md +12 -26
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +2 -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 +121 -42
- package/gsd-core/workflows/plan-review-convergence.md +46 -9
- 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 +27 -12
- package/gsd-core/workflows/quick/steps/discussion-phase.md +1 -3
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +1 -3
- package/gsd-core/workflows/quick/steps/quick-verification.md +2 -4
- package/gsd-core/workflows/quick/steps/research-phase.md +2 -4
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +3 -3
- package/gsd-core/workflows/quick.md +20 -29
- 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 +193 -15
- package/gsd-core/workflows/scan.md +1 -1
- package/gsd-core/workflows/secure-phase.md +2 -2
- package/gsd-core/workflows/settings-advanced.md +7 -9
- package/gsd-core/workflows/settings-integrations.md +64 -31
- package/gsd-core/workflows/settings.md +3 -5
- package/gsd-core/workflows/ship.md +12 -6
- 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 +23 -1
- 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 +1 -1
- package/gsd-core/workflows/thread.md +11 -7
- package/gsd-core/workflows/transition.md +5 -5
- package/gsd-core/workflows/ui-phase.md +10 -16
- package/gsd-core/workflows/ui-review.md +6 -10
- package/gsd-core/workflows/ultraplan-phase.md +5 -13
- package/gsd-core/workflows/undo.md +8 -16
- package/gsd-core/workflows/update.md +6 -10
- package/gsd-core/workflows/validate-phase.md +2 -2
- 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 +57 -18
- package/hooks/dist/gsd-agent-isolation-guard.js +77 -38
- 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 +3 -1
- 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 +28 -23
- package/hooks/dist/gsd-cursor-subagent-stop.js +3 -1
- 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 +16 -7
- package/hooks/dist/gsd-read-guard.js +16 -7
- package/hooks/dist/gsd-read-injection-scanner.js +17 -8
- package/hooks/dist/gsd-session-state.sh +1 -0
- package/hooks/dist/gsd-statusline.js +215 -26
- 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 +34 -16
- 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-probe.js +84 -0
- package/hooks/dist/lib/hook-exit.js +81 -0
- package/hooks/dist/managed-hooks-registry.cjs +3 -0
- package/hooks/gsd-agent-isolation-guard.js +77 -38
- 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 +3 -1
- package/hooks/gsd-cursor-session-start.js +2 -1
- package/hooks/gsd-cursor-stop.js +2 -1
- package/hooks/gsd-cursor-subagent-start.js +28 -23
- package/hooks/gsd-cursor-subagent-stop.js +3 -1
- 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 +16 -7
- package/hooks/gsd-read-guard.js +16 -7
- package/hooks/gsd-read-injection-scanner.js +17 -8
- package/hooks/gsd-session-state.sh +1 -0
- package/hooks/gsd-statusline.js +215 -26
- 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 +34 -16
- 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-probe.js +84 -0
- package/hooks/lib/hook-exit.js +81 -0
- package/hooks/managed-hooks-registry.cjs +3 -0
- package/package.json +12 -7
- package/scripts/base64-scan.sh +74 -12
- package/scripts/build-hooks.js +5 -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 +45 -12
- package/scripts/ci-timeout-report.cjs +230 -0
- package/scripts/docs-guard-registry.cjs +396 -0
- package/scripts/gen-capability-registry.cjs +8 -6
- 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-hooks-cli-exit.cjs +239 -0
- package/scripts/gen-install-tree-fixtures.cjs +2 -2
- package/scripts/gen-loop-host-contract.cjs +134 -1
- 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/ci-job-timing.cjs +72 -0
- package/scripts/lib/cli-exit.cjs +546 -44
- package/scripts/lib/drift-scan.cjs +32 -2
- package/scripts/lib/exit-code-registry.cjs +98 -0
- package/scripts/lib/ndjson-reporter.cjs +119 -0
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
- 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 +4 -0
- package/scripts/{lint-fix-has-regression-test.cjs → lint-fix-has-regression-tests.cjs} +12 -6
- package/scripts/lint-health-diagnostic-rule-table.cjs +65 -8
- package/scripts/lint-mutation-test-derivation-drift.cjs +86 -0
- package/scripts/lint-phase-enumeration-drift.cjs +21 -8
- package/scripts/lint-planning-prompt-drift.cjs +38 -1
- package/scripts/lint-removed-but-needed.cjs +184 -16
- 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-write-path-drift.cjs +337 -432
- package/scripts/lint-test-file-count.allowlist.json +122 -4
- package/scripts/lint-test-file-count.cjs +25 -3
- package/scripts/lint-unreachable-guard-drift.cjs +51 -64
- package/scripts/lint-vendored-deps.cjs +208 -35
- package/scripts/mutation-matrix.cjs +599 -50
- package/scripts/prompt-injection-scan.sh +75 -14
- package/scripts/secret-scan.sh +75 -13
- package/scripts/select-docs-guards.cjs +56 -0
- package/scripts/sync-runtime-launcher.cjs +22 -3
- package/skills/gsd-discuss-phase/SKILL.md +1 -1
- package/skills/gsd-import/SKILL.md +1 -1
- package/skills/gsd-quick/SKILL.md +8 -4
- package/vscode/package.json +1 -1
- package/bin/lib/ui-safety-gate.cjs +0 -109
- package/scripts/lint-emitted-drift-ack.cjs +0 -344
- package/scripts/state-write-path-drift-baseline.json +0 -19
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Plan Document Module — the single parser for a `*-PLAN.md` document BODY.
|
|
4
|
+
*
|
|
5
|
+
* Owns: objective extraction, the task-block grammar (`<task>` elements, with
|
|
6
|
+
* the legacy `## Task N` heading fallback — including the optional `tracker-id`
|
|
7
|
+
* attribute, ADR-3646 Phase 1, read verbatim and never split here), planned-file
|
|
8
|
+
* extraction, and the frontmatter-derived scheduling metadata (`wave`,
|
|
9
|
+
* `depends_on`, `autonomous`, `agent_hint`, `files_modified`).
|
|
10
|
+
*
|
|
11
|
+
* WHY THIS IS A LEAF MODULE. This logic was written inline inside
|
|
12
|
+
* `cmdPhasePlanIndex` (`src/phase.cts`). Two commands in two different families
|
|
13
|
+
* now need it — `phase.plan-index` and `planning.inspect` (#2790) — so leaving
|
|
14
|
+
* it in `phase.cts` would force `planning` to depend on `phase`, and copying it
|
|
15
|
+
* would be the *Generative Fix Divergence* class `CLAUDE.md` names. A leaf owned
|
|
16
|
+
* by neither family is the seam that matches the actual usage (Conway's Law).
|
|
17
|
+
*
|
|
18
|
+
* NOT an ADR-3180 §7 derivation. §6 puts the document-parsing layer explicitly
|
|
19
|
+
* out of that epic's scope (#2143); this module answers "what does this plan
|
|
20
|
+
* document say", never "how many plans are outstanding" (that is
|
|
21
|
+
* `scanPhasePlans`, §7.5) or "is this phase complete" (`isPhaseComplete`, §7.4).
|
|
22
|
+
*
|
|
23
|
+
* BEHAVIOUR IS PRESERVED BYTE-FOR-BEHAVIOUR from the prior inline code. In
|
|
24
|
+
* particular `tasks.length` is exactly the legacy `taskCount`
|
|
25
|
+
* (`xmlTasks.length || mdTasks.length`), including its known fence-blindness —
|
|
26
|
+
* a `## Task 1` inside a fenced code block still counts, exactly as it does
|
|
27
|
+
* today. That is a characterised limit, not an endorsement: changing it would
|
|
28
|
+
* silently change `phase.plan-index`'s output for existing projects, which is a
|
|
29
|
+
* Hyrum's-Law break that belongs in its own issue rather than riding along on a
|
|
30
|
+
* read-only query addition.
|
|
31
|
+
*
|
|
32
|
+
* ADR-457 build-at-publish: source in src/plan-document.cts, compiled to
|
|
33
|
+
* gsd-core/bin/lib/plan-document.cjs (gitignored).
|
|
34
|
+
*/
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
36
|
+
const frontmatterMod = require("./frontmatter.cjs");
|
|
37
|
+
const { extractFrontmatter } = frontmatterMod;
|
|
38
|
+
// ─── Frozen vocabularies ──────────────────────────────────────────────────────
|
|
39
|
+
/**
|
|
40
|
+
* How a task row was expressed in the document. `auto` is the ordinary
|
|
41
|
+
* executable task; `checkpoint` is a `<task type="checkpoint:*">` block, which
|
|
42
|
+
* carries an entirely different element set (`<decision>`/`<what-built>`, no
|
|
43
|
+
* `<name>`/`<files>`/`<acceptance_criteria>`). Distinguishing them is what
|
|
44
|
+
* stops a checkpoint from being reported as a malformed auto task.
|
|
45
|
+
*/
|
|
46
|
+
const TASK_KIND = Object.freeze({
|
|
47
|
+
AUTO: 'auto',
|
|
48
|
+
CHECKPOINT: 'checkpoint',
|
|
49
|
+
});
|
|
50
|
+
// ─── Task grammar ─────────────────────────────────────────────────────────────
|
|
51
|
+
// The legacy counting rule, preserved verbatim from cmdPhasePlanIndex. `g` is
|
|
52
|
+
// required (we count every occurrence) and these are rebuilt per call rather
|
|
53
|
+
// than hoisted to module scope: a global regex carries mutable `lastIndex`
|
|
54
|
+
// state, and a shared instance is a cross-call contamination bug.
|
|
55
|
+
function xmlTaskOpenings(content) {
|
|
56
|
+
return [...content.matchAll(/<task(?=[\s>])[^>]*>/gi)];
|
|
57
|
+
}
|
|
58
|
+
function markdownTaskHeadings(content) {
|
|
59
|
+
return [...content.matchAll(/##\s*Task\s*\d+[^\n]*/gi)];
|
|
60
|
+
}
|
|
61
|
+
/** Extract the value of one attribute from a `<task ...>` opening tag. */
|
|
62
|
+
function tagAttribute(openTag, attr) {
|
|
63
|
+
const re = new RegExp(`\\b${attr}\\s*=\\s*"([^"]*)"|\\b${attr}\\s*=\\s*'([^']*)'`, 'i');
|
|
64
|
+
const m = re.exec(openTag);
|
|
65
|
+
if (!m)
|
|
66
|
+
return null;
|
|
67
|
+
const value = (m[1] ?? m[2] ?? '').trim();
|
|
68
|
+
return value.length > 0 ? value : null;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Body of the first `<tag>…</tag>` inside `block`, or null. Non-greedy and
|
|
72
|
+
* case-insensitive; a tag that is opened but never closed yields null rather
|
|
73
|
+
* than swallowing the rest of the document.
|
|
74
|
+
*/
|
|
75
|
+
function elementBody(block, tag) {
|
|
76
|
+
const re = new RegExp(`<${tag}\\s*>([\\s\\S]*?)</${tag}\\s*>`, 'i');
|
|
77
|
+
const m = re.exec(block);
|
|
78
|
+
return m ? m[1] : null;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Split a `<files>` body into paths. Comma-separated per the shipped
|
|
82
|
+
* `templates/phase-prompt.md` grammar; newline-separated forms are tolerated
|
|
83
|
+
* too (Postel — liberal in what we accept), and the caller records nothing
|
|
84
|
+
* special for them because a path list is a path list either way.
|
|
85
|
+
*/
|
|
86
|
+
function splitFileList(body) {
|
|
87
|
+
if (body === null)
|
|
88
|
+
return [];
|
|
89
|
+
return body
|
|
90
|
+
.split(/[,\n]/)
|
|
91
|
+
.map((part) => part.trim())
|
|
92
|
+
.filter((part) => part.length > 0);
|
|
93
|
+
}
|
|
94
|
+
/** `<acceptance_criteria>` carries `- ` bullets, one criterion per line. */
|
|
95
|
+
function splitCriteria(body) {
|
|
96
|
+
if (body === null)
|
|
97
|
+
return [];
|
|
98
|
+
return body
|
|
99
|
+
.split(/\r?\n/)
|
|
100
|
+
.map((line) => line.trim())
|
|
101
|
+
.filter((line) => line.length > 0)
|
|
102
|
+
.map((line) => line.replace(/^[-*]\s*/, ''))
|
|
103
|
+
.filter((line) => line.length > 0);
|
|
104
|
+
}
|
|
105
|
+
function collapseWhitespace(value) {
|
|
106
|
+
if (value === null)
|
|
107
|
+
return null;
|
|
108
|
+
const trimmed = value.replace(/\s+/g, ' ').trim();
|
|
109
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Parse the `<task>` blocks. Each opening tag found by `xmlTaskOpenings` yields
|
|
113
|
+
* exactly one row — the block runs from that tag to its `</task>`, or to the
|
|
114
|
+
* next opening tag, or to end-of-document. Bounding on the NEXT OPENING rather
|
|
115
|
+
* than only on `</task>` is what keeps an unclosed block from consuming its
|
|
116
|
+
* siblings, so the row count still equals the opening count.
|
|
117
|
+
*/
|
|
118
|
+
function parseXmlTasks(content) {
|
|
119
|
+
const openings = xmlTaskOpenings(content);
|
|
120
|
+
return openings.map((match, i) => {
|
|
121
|
+
const start = match.index ?? 0;
|
|
122
|
+
const openTag = match[0];
|
|
123
|
+
const nextStart = i + 1 < openings.length ? (openings[i + 1].index ?? content.length) : content.length;
|
|
124
|
+
const window = content.slice(start, nextStart);
|
|
125
|
+
const closeIdx = window.search(/<\/task\s*>/i);
|
|
126
|
+
const block = closeIdx === -1 ? window : window.slice(0, closeIdx);
|
|
127
|
+
const type = tagAttribute(openTag, 'type');
|
|
128
|
+
const kind = type !== null && type.toLowerCase().startsWith('checkpoint')
|
|
129
|
+
? TASK_KIND.CHECKPOINT
|
|
130
|
+
: TASK_KIND.AUTO;
|
|
131
|
+
// A checkpoint block has no <name>/<files>/<acceptance_criteria>/<done> in
|
|
132
|
+
// the shipped grammar. Reading them anyway would be harmless but dishonest:
|
|
133
|
+
// the caller must be able to tell "this element is absent because this kind
|
|
134
|
+
// of task has no such element" from "this element is missing and should not
|
|
135
|
+
// be".
|
|
136
|
+
if (kind === TASK_KIND.CHECKPOINT) {
|
|
137
|
+
return {
|
|
138
|
+
index: i + 1,
|
|
139
|
+
kind,
|
|
140
|
+
type,
|
|
141
|
+
name: null,
|
|
142
|
+
plannedFiles: [],
|
|
143
|
+
acceptanceCriteria: [],
|
|
144
|
+
done: null,
|
|
145
|
+
trackerId: null,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
index: i + 1,
|
|
150
|
+
kind,
|
|
151
|
+
type,
|
|
152
|
+
name: collapseWhitespace(elementBody(block, 'name')),
|
|
153
|
+
plannedFiles: splitFileList(elementBody(block, 'files')),
|
|
154
|
+
acceptanceCriteria: splitCriteria(elementBody(block, 'acceptance_criteria')),
|
|
155
|
+
done: collapseWhitespace(elementBody(block, 'done')),
|
|
156
|
+
trackerId: tagAttribute(openTag, 'tracker-id'),
|
|
157
|
+
};
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Legacy fallback: `## Task N` headings, used ONLY when the document carries no
|
|
162
|
+
* `<task>` blocks at all. Deliberately fence-blind, matching the counting rule
|
|
163
|
+
* `cmdPhasePlanIndex` has always used — see this module's header comment.
|
|
164
|
+
*/
|
|
165
|
+
function parseMarkdownTasks(content) {
|
|
166
|
+
return markdownTaskHeadings(content).map((match, i) => ({
|
|
167
|
+
index: i + 1,
|
|
168
|
+
kind: TASK_KIND.AUTO,
|
|
169
|
+
type: null,
|
|
170
|
+
name: collapseWhitespace(match[0].replace(/^##\s*/, '')),
|
|
171
|
+
plannedFiles: [],
|
|
172
|
+
acceptanceCriteria: [],
|
|
173
|
+
done: null,
|
|
174
|
+
trackerId: null,
|
|
175
|
+
}));
|
|
176
|
+
}
|
|
177
|
+
// ─── Objective ────────────────────────────────────────────────────────────────
|
|
178
|
+
/**
|
|
179
|
+
* Preserved verbatim from `cmdPhasePlanIndex`: the first line following an
|
|
180
|
+
* `<objective>` tag. Deliberately NOT widened to the full element body — that
|
|
181
|
+
* would change `phase.plan-index`'s existing output for any multi-line
|
|
182
|
+
* objective.
|
|
183
|
+
*/
|
|
184
|
+
function extractObjective(content) {
|
|
185
|
+
const m = content.match(/<objective>\s*\n?\s*(.+)/);
|
|
186
|
+
return m ? m[1].trim() : null;
|
|
187
|
+
}
|
|
188
|
+
// ─── Entry point ──────────────────────────────────────────────────────────────
|
|
189
|
+
/**
|
|
190
|
+
* The plan id for a plan FILE ENTRY, exactly as `scanPhasePlans` stores it
|
|
191
|
+
* (root entries bare, nested entries `plans/`-prefixed).
|
|
192
|
+
*
|
|
193
|
+
* This is the established derivation from `cmdPhasePlanIndex`, moved here
|
|
194
|
+
* VERBATIM (#2790) so `phase.plan-index` and `planning.inspect` cannot report
|
|
195
|
+
* different ids for the same plan — a consumer correlating the two surfaces
|
|
196
|
+
* needs them to join. Deliberately NOT "improved": it is a display/lookup key
|
|
197
|
+
* with existing callers, and changing what it returns would be a Hyrum's-Law
|
|
198
|
+
* break on `phase-plan-index`.
|
|
199
|
+
*/
|
|
200
|
+
function planIdFromFile(planFile) {
|
|
201
|
+
return planFile.replace('-PLAN.md', '').replace('PLAN.md', '');
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Parse one plan document.
|
|
205
|
+
*
|
|
206
|
+
* @param content Raw `*-PLAN.md` text.
|
|
207
|
+
* @param planPath Optional path, used only to name the file in `extractFrontmatter`'s
|
|
208
|
+
* truncated-frontmatter diagnostic (#1882). Callers that do not have
|
|
209
|
+
* one omit it — this default IS the shape production uses from the
|
|
210
|
+
* read-only query path.
|
|
211
|
+
*/
|
|
212
|
+
function parsePlanDocument(content, planPath = '') {
|
|
213
|
+
const fm = extractFrontmatter(content, planPath);
|
|
214
|
+
const xmlTasks = parseXmlTasks(content);
|
|
215
|
+
const tasks = xmlTasks.length > 0 ? xmlTasks : parseMarkdownTasks(content);
|
|
216
|
+
const parsedWave = parseInt(fm['wave'], 10);
|
|
217
|
+
const declaredWave = Number.isNaN(parsedWave) ? null : parsedWave;
|
|
218
|
+
let dependsOn = [];
|
|
219
|
+
const fmDeps = fm['depends_on'];
|
|
220
|
+
if (Array.isArray(fmDeps)) {
|
|
221
|
+
dependsOn = fmDeps.map(String);
|
|
222
|
+
}
|
|
223
|
+
else if (typeof fmDeps === 'string' && fmDeps.trim() !== '') {
|
|
224
|
+
dependsOn = [fmDeps];
|
|
225
|
+
}
|
|
226
|
+
let autonomous = true;
|
|
227
|
+
if (fm['autonomous'] !== undefined) {
|
|
228
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string -- FrontmatterValue comparison
|
|
229
|
+
autonomous = fm['autonomous'] === 'true' || String(fm['autonomous']) === 'true';
|
|
230
|
+
}
|
|
231
|
+
let filesModified = [];
|
|
232
|
+
const fmFiles = fm['files_modified'] || fm['files-modified'];
|
|
233
|
+
if (fmFiles) {
|
|
234
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string -- FrontmatterValue scalar-to-string
|
|
235
|
+
filesModified = Array.isArray(fmFiles) ? fmFiles.map(String) : [String(fmFiles)];
|
|
236
|
+
}
|
|
237
|
+
let filesDeleted = [];
|
|
238
|
+
const fmDeleted = fm['files_deleted'] || fm['files-deleted'];
|
|
239
|
+
if (fmDeleted) {
|
|
240
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string -- FrontmatterValue scalar-to-string
|
|
241
|
+
filesDeleted = Array.isArray(fmDeleted) ? fmDeleted.map(String) : [String(fmDeleted)];
|
|
242
|
+
}
|
|
243
|
+
let agentHint = null;
|
|
244
|
+
const fmAgentHint = fm['agent_hint'];
|
|
245
|
+
if (fmAgentHint !== undefined) {
|
|
246
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string -- FrontmatterValue scalar-to-string
|
|
247
|
+
const hintStr = String(fmAgentHint).trim();
|
|
248
|
+
agentHint = hintStr !== '' ? hintStr : null;
|
|
249
|
+
}
|
|
250
|
+
return {
|
|
251
|
+
objective: extractObjective(content) || fm['objective'] || null,
|
|
252
|
+
declaredWave,
|
|
253
|
+
dependsOn,
|
|
254
|
+
autonomous,
|
|
255
|
+
agentHint,
|
|
256
|
+
filesModified,
|
|
257
|
+
filesDeleted,
|
|
258
|
+
tasks,
|
|
259
|
+
taskCount: tasks.length,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
const planDocument = { TASK_KIND, parsePlanDocument, planIdFromFile };
|
|
263
|
+
module.exports = planDocument;
|
|
@@ -88,7 +88,18 @@ function isRootPlanFile(fileName) {
|
|
|
88
88
|
// substring "PLAN") are not double-counted as plans. (#500 RC2)
|
|
89
89
|
if (isRootSummaryFile(fileName))
|
|
90
90
|
return false;
|
|
91
|
-
|
|
91
|
+
// #3741: the PLAN token must be DELIMITED — anchored at the start or after
|
|
92
|
+
// a hyphen, and followed only by an optional `-<digits>…` suffix before
|
|
93
|
+
// `.md` (the `…` keeps the legacy slug form `3-PLAN-01-setup.md` that
|
|
94
|
+
// gsd-plan-phase writes, per #3128). A bare substring test counted
|
|
95
|
+
// REPLAN-INPUTS / PLANNING-INPUTS / PLANNING-NOTES as plans, inflating
|
|
96
|
+
// planCount and STATE.md's derived total_plans. Delimited keeps the
|
|
97
|
+
// fallback's deliberate permissiveness for legacy single-token names
|
|
98
|
+
// (`plan.md`, `Plan.md`, `01-PLAN-02.md`, `3-PLAN-01-setup.md`) while
|
|
99
|
+
// excluding any name where PLAN is merely embedded in a larger word
|
|
100
|
+
// (REPLAN, PLANNING) — the same anchoring discipline isNestedPlanFile
|
|
101
|
+
// already applies.
|
|
102
|
+
return /(^|-)PLAN(-\d+.*)?\.md$/i.test(fileName);
|
|
92
103
|
}
|
|
93
104
|
function isNestedPlanFile(fileName) {
|
|
94
105
|
if (PLAN_OUTLINE_RE.test(fileName))
|
|
@@ -108,7 +119,7 @@ function isNestedSummaryFile(fileName) {
|
|
|
108
119
|
* `allPlanFiles` ENTRY (root form bare, nested form `plans/`-prefixed, exactly
|
|
109
120
|
* as those arrays store them) — root `<phase>-<NN>-PLAN.md`/bare `PLAN.md`,
|
|
110
121
|
* or nested `plans/PLAN-<NN>....md`/`plans/<x>-PLAN-<NN>....md` — WITHOUT
|
|
111
|
-
* `isRootPlanFile`'s loose
|
|
122
|
+
* `isRootPlanFile`'s loose delimited-PLAN fallback.
|
|
112
123
|
*
|
|
113
124
|
* The `plans/` prefix check is load-bearing, not cosmetic: `isNestedPlanFile`
|
|
114
125
|
* matches ANY basename containing `-PLAN-<digits>...md` with no anchor
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Planning command router — CLI subcommand dispatcher for `gsd-tools planning`.
|
|
4
|
+
*
|
|
5
|
+
* Routes `planning inspect` (#2790) to `planningInspect.cmdPlanningInspect`.
|
|
6
|
+
* Both the spaced form (`query planning inspect`) and the dotted canonical form
|
|
7
|
+
* (`query planning.inspect`) reach here identically: `gsd-tools` splits a dotted
|
|
8
|
+
* command on its FIRST dot before dispatch, so the router never sees the dot.
|
|
9
|
+
*
|
|
10
|
+
* v1 accepts NO arguments beyond the subcommand. `--raw`, `--cwd`, `--pick`,
|
|
11
|
+
* `--default` and `--json-errors` are global and are spliced out of argv by
|
|
12
|
+
* `gsd-tools`' own `main()` before any router runs, so anything still present at
|
|
13
|
+
* `args[2]` or beyond is genuinely unrecognised and is a fail-loud USAGE error.
|
|
14
|
+
* That strictness is deliberate: silently ignoring an argument a caller believed
|
|
15
|
+
* was scoping the query would return a full-project snapshot presented as a
|
|
16
|
+
* scoped one — a confidently wrong answer.
|
|
17
|
+
*
|
|
18
|
+
* Router signature `{ args, cwd, raw, error }` — identical to the other host
|
|
19
|
+
* routers. Test seam: pass `_planningInspect` to inject a recording mock; the
|
|
20
|
+
* `_` prefix follows this repo's established seam convention.
|
|
21
|
+
*
|
|
22
|
+
* ADR-457 build-at-publish: source in src/planning-command-router.cts, compiled
|
|
23
|
+
* to gsd-core/bin/lib/planning-command-router.cjs (gitignored).
|
|
24
|
+
*/
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
26
|
+
const planningInspect = require("./planning-inspect.cjs");
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
28
|
+
const cjsCommandRouterAdapter = require("./cjs-command-router-adapter.cjs");
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
30
|
+
const io = require("./io.cjs");
|
|
31
|
+
const { routeCjsCommandFamily } = cjsCommandRouterAdapter;
|
|
32
|
+
const { ERROR_REASON } = io;
|
|
33
|
+
// ─── Implementation ───────────────────────────────────────────────────────────
|
|
34
|
+
const PLANNING_SUBCOMMANDS = ['inspect'];
|
|
35
|
+
function routePlanningCommand({ args, cwd, raw, error, _planningInspect }) {
|
|
36
|
+
const mod = _planningInspect ?? planningInspect;
|
|
37
|
+
routeCjsCommandFamily({
|
|
38
|
+
args,
|
|
39
|
+
subcommands: PLANNING_SUBCOMMANDS,
|
|
40
|
+
unsupported: {},
|
|
41
|
+
error,
|
|
42
|
+
unknownMessage: (_subcommand, available) => `Unknown planning subcommand. Available: ${available.join(', ')}`,
|
|
43
|
+
handlers: {
|
|
44
|
+
inspect: () => {
|
|
45
|
+
const extra = args.slice(2);
|
|
46
|
+
if (extra.length > 0) {
|
|
47
|
+
const offender = extra[0];
|
|
48
|
+
const shape = offender.startsWith('-') ? 'flag' : 'positional argument';
|
|
49
|
+
error(`planning inspect takes no arguments; got ${shape}: ${offender}. ` +
|
|
50
|
+
'Usage: gsd-tools query planning inspect', ERROR_REASON.USAGE);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
mod.cmdPlanningInspect(cwd, raw);
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
module.exports = {
|
|
59
|
+
routePlanningCommand,
|
|
60
|
+
PLANNING_SUBCOMMANDS,
|
|
61
|
+
};
|