@opengsd/gsd-core 1.13.0 → 1.15.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/README.ja-JP.md +3 -3
- package/README.ko-KR.md +3 -3
- package/README.pt-BR.md +3 -3
- package/README.zh-CN.md +3 -3
- package/agents/gsd-advisor-researcher.compact.md +85 -0
- package/agents/gsd-ai-researcher.compact.md +96 -0
- package/agents/gsd-assumptions-analyzer.compact.md +81 -0
- package/agents/gsd-code-fixer.compact.md +459 -0
- package/agents/gsd-code-fixer.md +9 -8
- package/agents/gsd-code-reviewer.compact.md +269 -0
- package/agents/gsd-code-reviewer.md +15 -3
- package/agents/gsd-codebase-mapper.compact.md +760 -0
- package/agents/gsd-debug-session-manager.compact.md +360 -0
- package/agents/gsd-debug-session-manager.md +17 -2
- package/agents/gsd-debugger.md +2 -2
- package/agents/gsd-doc-classifier.compact.md +192 -0
- package/agents/gsd-doc-synthesizer.compact.md +200 -0
- package/agents/gsd-doc-verifier.compact.md +143 -0
- package/agents/gsd-doc-writer.compact.md +440 -0
- package/agents/gsd-dom-verifier.compact.md +138 -0
- package/agents/gsd-domain-researcher.compact.md +141 -0
- package/agents/gsd-eval-auditor.compact.md +160 -0
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-eval-planner.compact.md +137 -0
- package/agents/gsd-executor.md +13 -8
- package/agents/gsd-framework-selector.compact.md +82 -0
- package/agents/gsd-integration-checker.compact.md +245 -0
- package/agents/gsd-intel-updater.compact.md +226 -0
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.compact.md +45 -0
- package/agents/gsd-nyquist-auditor.compact.md +179 -0
- package/agents/gsd-pattern-mapper.compact.md +275 -0
- package/agents/gsd-phase-researcher.md +19 -11
- package/agents/gsd-plan-checker.md +8 -7
- package/agents/gsd-planner.md +12 -8
- package/agents/gsd-project-researcher.compact.md +587 -0
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.compact.md +212 -0
- package/agents/gsd-research-synthesizer.md +1 -1
- package/agents/gsd-roadmapper.compact.md +454 -0
- package/agents/gsd-roadmapper.md +13 -0
- package/agents/gsd-security-auditor.compact.md +162 -0
- package/agents/gsd-ui-auditor.compact.md +404 -0
- package/agents/gsd-ui-auditor.md +155 -17
- package/agents/gsd-ui-checker.compact.md +277 -0
- package/agents/gsd-ui-researcher.compact.md +282 -0
- package/agents/gsd-ui-researcher.md +1 -1
- package/agents/gsd-user-profiler.compact.md +108 -0
- package/agents/gsd-verifier.md +10 -9
- package/bin/install.js +848 -163
- package/commands/gsd/autonomous.md +2 -2
- package/commands/gsd/capture.md +1 -1
- package/commands/gsd/cleanup.md +1 -0
- package/commands/gsd/code-review.md +2 -1
- package/commands/gsd/complete-milestone.md +1 -0
- package/commands/gsd/config.md +1 -0
- package/commands/gsd/debug.md +1 -0
- package/commands/gsd/graphify.md +1 -0
- package/commands/gsd/health.md +1 -0
- package/commands/gsd/mempalace-capture.md +8 -3
- package/commands/gsd/mempalace-recall.md +1 -0
- package/commands/gsd/new-milestone.md +1 -0
- package/commands/gsd/new-project.md +1 -0
- package/commands/gsd/next.md +1 -0
- package/commands/gsd/pause-work.md +1 -0
- package/commands/gsd/phase.md +1 -0
- package/commands/gsd/plan-review-convergence.md +6 -6
- package/commands/gsd/pr-branch.md +1 -0
- package/commands/gsd/progress.md +1 -1
- package/commands/gsd/quick-batch.md +1 -1
- package/commands/gsd/resume-work.md +1 -0
- package/commands/gsd/review-backlog.md +1 -0
- package/commands/gsd/review.md +2 -3
- package/commands/gsd/settings.md +2 -1
- package/commands/gsd/stats.md +1 -0
- package/commands/gsd/thread.md +1 -0
- package/commands/gsd/workspace.md +1 -0
- package/commands/gsd/workstreams.md +1 -0
- package/gsd-core/bin/check-latest-version.cjs +8 -3
- package/gsd-core/bin/gsd-tools.cjs +672 -146
- package/gsd-core/bin/lib/adr-parser.cjs +4 -2
- package/gsd-core/bin/lib/artifacts.cjs +2 -1
- package/gsd-core/bin/lib/audit.cjs +119 -34
- package/gsd-core/bin/lib/broken-windows.cjs +168 -49
- package/gsd-core/bin/lib/capability-lifecycle.cjs +10 -6
- package/gsd-core/bin/lib/capability-loader.cjs +135 -1
- package/gsd-core/bin/lib/capability-registry.cjs +96 -189
- package/gsd-core/bin/lib/capability-source.cjs +19 -2
- package/gsd-core/bin/lib/capability-validator.cjs +14 -2
- package/gsd-core/bin/lib/check-command-router.cjs +213 -49
- package/gsd-core/bin/lib/code-review-depth.cjs +2 -2
- package/gsd-core/bin/lib/codex-agent-toml.cjs +21 -25
- package/gsd-core/bin/lib/commands.cjs +823 -112
- package/gsd-core/bin/lib/config-loader.cjs +66 -4
- package/gsd-core/bin/lib/config.cjs +186 -45
- package/gsd-core/bin/lib/coverage.cjs +1 -1
- package/gsd-core/bin/lib/decisions.cjs +164 -45
- package/gsd-core/bin/lib/external-descriptor-trust.cjs +29 -14
- package/gsd-core/bin/lib/frontmatter.cjs +13 -0
- package/gsd-core/bin/lib/graphify.cjs +10 -2
- package/gsd-core/bin/lib/gsd2-import.cjs +1 -2
- package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +12 -1
- package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +1 -1
- package/gsd-core/bin/lib/host-runtime-detection.cjs +9 -0
- package/gsd-core/bin/lib/init.cjs +614 -86
- package/gsd-core/bin/lib/install-engine.cjs +29 -3
- package/gsd-core/bin/lib/install-profiles.cjs +14 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +41 -5
- package/gsd-core/bin/lib/loop-resolver.cjs +50 -31
- package/gsd-core/bin/lib/mcp-catalog.cjs +2 -2
- package/gsd-core/bin/lib/milestone.cjs +37 -13
- package/gsd-core/bin/lib/model-resolver.cjs +253 -53
- package/gsd-core/bin/lib/phase-command-router.cjs +16 -2
- package/gsd-core/bin/lib/phase-id-card.cjs +32 -0
- package/gsd-core/bin/lib/phase-id-display.cjs +78 -0
- package/gsd-core/bin/lib/phase-id.cjs +268 -27
- package/gsd-core/bin/lib/phase-lifecycle.cjs +61 -0
- package/gsd-core/bin/lib/phase-locator.cjs +29 -10
- package/gsd-core/bin/lib/phase.cjs +393 -88
- package/gsd-core/bin/lib/plan-document.cjs +49 -1
- package/gsd-core/bin/lib/planning-document.cjs +459 -0
- package/gsd-core/bin/lib/planning-inspect.cjs +52 -19
- package/gsd-core/bin/lib/planning-snapshot.cjs +61 -12
- package/gsd-core/bin/lib/planning-workspace.cjs +57 -3
- package/gsd-core/bin/lib/pr-branch-patterns.cjs +57 -0
- package/gsd-core/bin/lib/pristine-baseline.cjs +182 -0
- package/gsd-core/bin/lib/probe-core.cjs +7 -1
- package/gsd-core/bin/lib/prohibition-enforcement.cjs +91 -4
- package/gsd-core/bin/lib/project-root.cjs +41 -2
- package/gsd-core/bin/lib/quick-batch.cjs +1 -1
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +61 -2
- package/gsd-core/bin/lib/research-store.cjs +11 -12
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +10 -30
- package/gsd-core/bin/lib/review-lane-invocation.cjs +23 -0
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +2 -2
- package/gsd-core/bin/lib/reviewer-step-dispatch.cjs +337 -0
- package/gsd-core/bin/lib/roadmap-command-router.cjs +12 -4
- package/gsd-core/bin/lib/roadmap-parser.cjs +219 -18
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +1539 -13
- package/gsd-core/bin/lib/roadmap.cjs +356 -42
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +310 -41
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +15 -4
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +13 -5
- package/gsd-core/bin/lib/runtime-homes.cjs +4 -0
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +408 -37
- package/gsd-core/bin/lib/runtime-name-policy.cjs +111 -1
- package/gsd-core/bin/lib/security.cjs +126 -7
- package/gsd-core/bin/lib/shell-command-projection.cjs +10 -6
- package/gsd-core/bin/lib/state-document.cjs +130 -28
- package/gsd-core/bin/lib/state-md-schema.cjs +21 -14
- package/gsd-core/bin/lib/state-transition.cjs +181 -30
- package/gsd-core/bin/lib/state.cjs +265 -27
- package/gsd-core/bin/lib/surface.cjs +77 -3
- package/gsd-core/bin/lib/task-command-router.cjs +12 -6
- package/gsd-core/bin/lib/tdd-red-evidence.cjs +78 -5
- package/gsd-core/bin/lib/uat-predicate.cjs +47 -4
- package/gsd-core/bin/lib/uat.cjs +9 -1
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +15 -2
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +100 -9
- package/gsd-core/bin/lib/undo-commit-selection.cjs +131 -0
- package/gsd-core/bin/lib/update-context.cjs +30 -24
- package/gsd-core/bin/lib/vendor/js-yaml.cjs +11 -3
- package/gsd-core/bin/lib/verification.cjs +315 -30
- package/gsd-core/bin/lib/verify-command-grounding.cjs +47 -3
- package/gsd-core/bin/lib/verify.cjs +320 -48
- package/gsd-core/bin/lib/workstream-inventory.cjs +1 -0
- package/gsd-core/bin/lib/worktree-base-ref.cjs +482 -73
- package/gsd-core/bin/lib/worktree-safety.cjs +797 -58
- package/gsd-core/bin/shared/config-defaults.manifest.json +4 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +6 -0
- package/gsd-core/bin/verify-reapply-patches.cjs +439 -80
- package/gsd-core/references/checkpoints.md +5 -3
- package/gsd-core/references/compact-content-gate.md +66 -0
- package/gsd-core/references/edge-probe-fixtures/01-round-half-even/expected-coverage.json +28 -3
- package/gsd-core/references/edge-probe-fixtures/02-merge-intervals/expected-coverage.json +37 -4
- package/gsd-core/references/edge-probe-fixtures/03-truncate-graphemes/expected-coverage.json +28 -3
- package/gsd-core/references/edge-probe-fixtures/04-money-rounding/expected-coverage.json +28 -3
- package/gsd-core/references/edge-probe-fixtures/05-list-dedupe/expected-coverage.json +37 -4
- package/gsd-core/references/edge-probe-fixtures/06-resolved-mixed/expected-coverage.json +37 -4
- package/gsd-core/references/edge-probe.md +195 -21
- package/gsd-core/references/execute-phase-between-wave-reset.md +7 -6
- package/gsd-core/references/execute-phase-wave-guard.md +22 -11
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/loop-hook-dispatch.md +18 -0
- package/gsd-core/references/model-profiles.md +13 -4
- package/gsd-core/references/phase-argument-parsing.md +9 -7
- package/gsd-core/references/phase-id-convention.md +28 -0
- package/gsd-core/references/planner-gap-closure.md +2 -0
- package/gsd-core/references/planner-load-graph-context.md +24 -13
- package/gsd-core/references/planner-verify-command-grounding.md +14 -0
- package/gsd-core/references/planning-config.md +14 -2
- package/gsd-core/references/tdd.md +30 -4
- package/gsd-core/references/thinking-models-planning.md +18 -2
- package/gsd-core/references/ui-consideration-probe.md +10 -5
- package/gsd-core/references/verification-patterns.md +17 -4
- package/gsd-core/references/verify-command-path-resolvability.md +10 -2
- package/gsd-core/references/worktree-path-safety.md +433 -2
- package/gsd-core/templates/README.md +7 -1
- package/gsd-core/templates/state.md +6 -3
- package/gsd-core/templates/summary.compact.md +212 -0
- package/gsd-core/templates/user-setup.compact.md +199 -0
- package/gsd-core/templates/user-setup.md +0 -9
- package/gsd-core/templates/verification-report.md +1 -1
- package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
- package/gsd-core/workflows/add-backlog.md +1 -1
- package/gsd-core/workflows/add-phase.md +1 -1
- package/gsd-core/workflows/add-tests.md +2 -2
- package/gsd-core/workflows/add-todo.md +6 -5
- package/gsd-core/workflows/ai-integration-phase.md +11 -3
- package/gsd-core/workflows/audit-fix.md +1 -1
- package/gsd-core/workflows/audit-milestone.md +1 -1
- package/gsd-core/workflows/audit-uat.md +1 -1
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +9 -18
- package/gsd-core/workflows/autonomous.md +29 -16
- package/gsd-core/workflows/check-todos.md +6 -4
- package/gsd-core/workflows/cleanup.md +5 -3
- package/gsd-core/workflows/code-review/steps/dispatch-fix.md +4 -3
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +8 -1
- package/gsd-core/workflows/code-review-fix.md +108 -22
- package/gsd-core/workflows/code-review.md +216 -73
- package/gsd-core/workflows/complete-milestone/detail/elaboration.md +274 -0
- package/gsd-core/workflows/complete-milestone.md +41 -264
- package/gsd-core/workflows/debug.md +3 -3
- package/gsd-core/workflows/diagnose-issues.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +1 -1
- package/gsd-core/workflows/discuss-phase.md +1 -1
- package/gsd-core/workflows/do.md +2 -2
- package/gsd-core/workflows/docs-update/detail/elaboration.md +179 -0
- package/gsd-core/workflows/docs-update.md +17 -158
- package/gsd-core/workflows/edit-phase.md +1 -1
- package/gsd-core/workflows/eval-review.md +10 -3
- package/gsd-core/workflows/execute-phase/detail/elaboration.md +124 -0
- package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +1017 -0
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +19 -4
- package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +56 -0
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +43 -4
- package/gsd-core/workflows/execute-phase/steps/executor-progress-policy.md +43 -0
- 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 +1 -1
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +46 -9
- package/gsd-core/workflows/execute-phase/steps/protected-branch.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/ready-wave-gate.md +37 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/sequential-root-pin.md +35 -0
- package/gsd-core/workflows/execute-phase/steps/stale-reverification.md +24 -0
- package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/threat-id-gate.md +28 -0
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/worktree-base-check.md +25 -0
- package/gsd-core/workflows/execute-phase.md +83 -172
- package/gsd-core/workflows/execute-plan.md +24 -10
- package/gsd-core/workflows/explore.md +3 -3
- package/gsd-core/workflows/extract-learnings.md +2 -1
- package/gsd-core/workflows/fast.md +1 -1
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +1 -1
- package/gsd-core/workflows/health.md +2 -2
- package/gsd-core/workflows/help/modes/full.compact.md +398 -0
- package/gsd-core/workflows/help/modes/full.md +5 -5
- package/gsd-core/workflows/help/modes/topic.md +15 -5
- package/gsd-core/workflows/help.md +1 -1
- package/gsd-core/workflows/import.md +2 -2
- package/gsd-core/workflows/inbox.md +2 -2
- package/gsd-core/workflows/ingest-docs.md +3 -3
- package/gsd-core/workflows/insert-phase.md +1 -1
- package/gsd-core/workflows/list-seeds.md +1 -1
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +2 -2
- package/gsd-core/workflows/map-codebase.md +52 -5
- package/gsd-core/workflows/milestone-summary.md +1 -1
- package/gsd-core/workflows/mvp-phase.md +1 -1
- package/gsd-core/workflows/new-milestone.md +56 -14
- package/gsd-core/workflows/new-project/detail/elaboration.md +216 -0
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +3 -3
- package/gsd-core/workflows/new-project/steps/codebase-map-offer.md +1 -1
- package/gsd-core/workflows/new-project.md +39 -209
- package/gsd-core/workflows/new-workspace.md +2 -2
- package/gsd-core/workflows/next.md +1 -1
- package/gsd-core/workflows/note.md +1 -1
- package/gsd-core/workflows/onboard.md +1 -1
- package/gsd-core/workflows/pause-work.md +1 -1
- package/gsd-core/workflows/plan-phase/detail/elaboration.md +209 -0
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +17 -5
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +23 -5
- package/gsd-core/workflows/plan-phase.md +45 -187
- package/gsd-core/workflows/plan-review-convergence.md +21 -5
- package/gsd-core/workflows/plant-seed.md +62 -20
- package/gsd-core/workflows/pr-branch.md +132 -20
- package/gsd-core/workflows/profile-user.md +2 -2
- package/gsd-core/workflows/progress.md +1 -1
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +25 -0
- package/gsd-core/workflows/quick/steps/quick-verification.md +1 -1
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/batch-init.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/completion.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/merge-wave.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/planner-wave.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/research-phase.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/resume-mode.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/verification-wave.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +1 -1
- package/gsd-core/workflows/quick-batch.md +1 -1
- package/gsd-core/workflows/quick.md +29 -10
- package/gsd-core/workflows/reapply-patches.md +86 -6
- package/gsd-core/workflows/remove-phase.md +1 -1
- package/gsd-core/workflows/remove-workspace.md +2 -2
- package/gsd-core/workflows/resume-project.md +1 -1
- package/gsd-core/workflows/review.md +31 -16
- package/gsd-core/workflows/scan.md +1 -1
- package/gsd-core/workflows/secure-phase.md +3 -2
- package/gsd-core/workflows/settings-advanced.md +30 -10
- package/gsd-core/workflows/settings-integrations.md +2 -3
- package/gsd-core/workflows/settings.md +22 -9
- package/gsd-core/workflows/ship.md +3 -2
- package/gsd-core/workflows/sketch-wrap-up.md +1 -1
- package/gsd-core/workflows/sketch.md +1 -1
- package/gsd-core/workflows/smart-entry.md +2 -2
- package/gsd-core/workflows/spec-phase.md +15 -5
- package/gsd-core/workflows/spike-wrap-up.md +1 -1
- package/gsd-core/workflows/spike.md +1 -1
- package/gsd-core/workflows/stats.md +1 -1
- package/gsd-core/workflows/sync-skills.md +5 -5
- package/gsd-core/workflows/thread.md +1 -1
- package/gsd-core/workflows/transition.md +1 -1
- package/gsd-core/workflows/ui-phase.md +44 -8
- package/gsd-core/workflows/ui-review.md +18 -4
- package/gsd-core/workflows/ultraplan-phase.md +1 -1
- package/gsd-core/workflows/undo.md +339 -20
- package/gsd-core/workflows/update.md +14 -12
- package/gsd-core/workflows/validate-phase.md +3 -2
- package/gsd-core/workflows/verify-work/detail/elaboration.md +230 -0
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +1 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
- package/gsd-core/workflows/verify-work.md +101 -196
- package/hooks/dist/gsd-agent-isolation-guard.js +66 -16
- package/hooks/dist/gsd-context-monitor.js +88 -15
- package/hooks/dist/gsd-cursor-subagent-start.js +34 -14
- package/hooks/dist/gsd-secret-read-guard.js +71 -19
- package/hooks/dist/gsd-statusline.js +81 -20
- package/hooks/dist/gsd-validate-commit.sh +97 -8
- package/hooks/dist/gsd-worktree-path-guard.js +25 -14
- package/hooks/dist/gsd-write-guard.js +46 -1
- package/hooks/dist/lib/dispatch-identity.js +187 -0
- package/hooks/dist/lib/filename-classification.js +64 -0
- package/hooks/dist/lib/isolation-deny-reason.js +53 -1
- package/hooks/dist/lib/isolation-sentinel.js +58 -19
- package/hooks/gsd-agent-isolation-guard.js +66 -16
- package/hooks/gsd-context-monitor.js +88 -15
- package/hooks/gsd-cursor-subagent-start.js +34 -14
- package/hooks/gsd-secret-read-guard.js +71 -19
- package/hooks/gsd-statusline.js +81 -20
- package/hooks/gsd-validate-commit.sh +97 -8
- package/hooks/gsd-worktree-path-guard.js +25 -14
- package/hooks/gsd-write-guard.js +46 -1
- package/hooks/lib/dispatch-identity.js +187 -0
- package/hooks/lib/filename-classification.js +64 -0
- package/hooks/lib/isolation-deny-reason.js +53 -1
- package/hooks/lib/isolation-sentinel.js +58 -19
- package/package.json +11 -6
- package/scripts/benchmark-compact-content-variants.cjs +298 -0
- package/scripts/benchmark-compact-content.cjs +368 -0
- package/scripts/build-hooks.js +15 -6
- package/scripts/check-contract-drift.cjs +131 -12
- package/scripts/check-env.cjs +36 -8
- package/scripts/check-glossary-refs.cjs +25 -21
- package/scripts/ci-next-health.cjs +271 -0
- package/scripts/ci-prepare-test-scope.cjs +7 -7
- package/scripts/ci-test-scope.cjs +126 -20
- package/scripts/ci-timeout-report.cjs +1 -1
- package/scripts/command-contract-helpers.cjs +3 -0
- package/scripts/diff-touches-shipped-paths.cjs +1 -1
- package/scripts/docs-guard-registry.cjs +35 -2
- package/scripts/gen-adr-index.cjs +8 -2
- package/scripts/gen-inventory-manifest.cjs +12 -0
- package/scripts/gen-loop-host-contract.cjs +69 -0
- package/scripts/gen-platform-conformance-tier.cjs +557 -0
- package/scripts/lib/drift-scan.cjs +1 -1
- package/scripts/lib/macos-conformance-tier.generated.cjs +224 -0
- package/scripts/lib/ndjson-reporter.cjs +3 -2
- package/scripts/lib/npm-version-check-diagnosis.cjs +59 -0
- package/scripts/lib/platform-conformance-tier.generated.cjs +287 -0
- package/scripts/lib/suite-detection.cjs +32 -0
- package/scripts/lint-allowed-tools-parity.cjs +221 -0
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +47 -3
- package/scripts/lint-phase-arg-assignment.cjs +257 -0
- package/scripts/lint-phase-id-drift.cjs +623 -13
- package/scripts/lint-pr-branch-pattern-drift.cjs +148 -0
- package/scripts/lint-response-language-coverage.cjs +9 -3
- package/scripts/lint-retired-runtime-name.cjs +619 -0
- package/scripts/lint-source-test-name-collision.cjs +1 -1
- package/scripts/lint-state-write-path-drift.cjs +93 -0
- package/scripts/lint-test-file-count.allowlist.json +29 -9
- package/scripts/lint-vendored-deps.cjs +128 -17
- package/scripts/lint-workflow-shellcheck-baseline.json +100 -0
- package/scripts/prompt-injection-scan.sh +18 -0
- package/scripts/release-tarball-smoke.cjs +194 -1
- package/scripts/workflow-size.cjs +139 -0
- package/skills/gsd-autonomous/SKILL.md +2 -2
- package/skills/gsd-capture/SKILL.md +1 -1
- package/skills/gsd-cleanup/SKILL.md +1 -0
- package/skills/gsd-code-review/SKILL.md +2 -1
- package/skills/gsd-complete-milestone/SKILL.md +1 -0
- package/skills/gsd-config/SKILL.md +1 -0
- package/skills/gsd-debug/SKILL.md +1 -0
- package/skills/gsd-graphify/SKILL.md +1 -0
- package/skills/gsd-health/SKILL.md +1 -0
- package/skills/gsd-mempalace-capture/SKILL.md +8 -3
- package/skills/gsd-mempalace-recall/SKILL.md +1 -0
- package/skills/gsd-new-milestone/SKILL.md +1 -0
- package/skills/gsd-new-project/SKILL.md +1 -0
- package/skills/gsd-next/SKILL.md +1 -0
- package/skills/gsd-pause-work/SKILL.md +1 -0
- package/skills/gsd-phase/SKILL.md +1 -0
- package/skills/gsd-plan-review-convergence/SKILL.md +5 -5
- package/skills/gsd-pr-branch/SKILL.md +1 -0
- package/skills/gsd-progress/SKILL.md +1 -1
- package/skills/gsd-quick-batch/SKILL.md +1 -1
- package/skills/gsd-resume-work/SKILL.md +1 -0
- package/skills/gsd-review/SKILL.md +2 -3
- package/skills/gsd-review-backlog/SKILL.md +1 -0
- package/skills/gsd-settings/SKILL.md +2 -1
- package/skills/gsd-stats/SKILL.md +1 -0
- package/skills/gsd-thread/SKILL.md +1 -0
- package/skills/gsd-workspace/SKILL.md +1 -0
- package/skills/gsd-workstreams/SKILL.md +1 -0
- package/vscode/package.json +1 -1
- package/gsd-core/templates/claude-md.md +0 -145
- package/gsd-core/templates/codebase/concerns.md +0 -310
- package/gsd-core/templates/codebase/conventions.md +0 -307
- package/gsd-core/templates/codebase/integrations.md +0 -280
- package/gsd-core/templates/codebase/structure.md +0 -285
- package/gsd-core/templates/codebase/testing.md +0 -480
- package/gsd-core/templates/debug-subagent-prompt.md +0 -91
- package/gsd-core/templates/discovery.md +0 -146
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Reviewer Step Dispatch (#4209 Phase 1 Plan 2, ADR-2782 seam).
|
|
4
|
+
*
|
|
5
|
+
* ONE interpreter for "a step declares `supportsReviewerLanes: true`" — see
|
|
6
|
+
* `gsd-core/references/loop-hook-dispatch.md` for the canonical explanation of the trait and how
|
|
7
|
+
* `review-lane dispatch-step` re-derives it. This module trusts `trait` exactly as given: it is
|
|
8
|
+
* the CALLER's job to have derived it correctly. Every direct or lifecycle caller routes through
|
|
9
|
+
* `dispatchReviewerLanes` so selection/plan/invoke logic is owned once, not re-derived per
|
|
10
|
+
* feature. This module owns NONE of those primitives — it wires `resolveReviewerSelection`
|
|
11
|
+
* (selection) and `resolveLanePlan` (planning), the same building blocks
|
|
12
|
+
* `gsd-core/bin/gsd-tools.cjs`'s `review-lane plan` subcommand uses. Invocation (`runLane`) needs
|
|
13
|
+
* OS-aware spawn/probe plumbing this module does not own, so `deps.invoke` is the one required,
|
|
14
|
+
* caller-supplied seam (wired for real in `gsd-core/bin/gsd-tools.cjs`'s `review-lane
|
|
15
|
+
* dispatch-step` route).
|
|
16
|
+
*
|
|
17
|
+
* Fail-closed contract:
|
|
18
|
+
* - Trait not exactly `true`, or nothing selected → inert. Zero plan/invoke calls.
|
|
19
|
+
* - Missing/unsafe request-level input (paths escaping `repoRoot`, absent depth/base SHA) stops
|
|
20
|
+
* the WHOLE dispatch before any lane is planned or invoked.
|
|
21
|
+
* - An explicitly requested lane the selector could not resolve does not silently narrow the
|
|
22
|
+
* result to only what worked: lanes that DID resolve still run and their results are kept,
|
|
23
|
+
* but the aggregate `ok` is `false` so no caller mistakes a partial run for a clean one.
|
|
24
|
+
* - Once a lane is planned, a per-lane plan/budget/invoke failure never displaces or cancels a
|
|
25
|
+
* sibling lane already run.
|
|
26
|
+
* - A lane whose `promptChannel` is `'none'` (it reviews the working tree on its own terms, fed
|
|
27
|
+
* nothing — e.g. `coderabbit`) cannot receive the bounded prompt below and is rejected before
|
|
28
|
+
* plan/invoke, same as an unresolved slug.
|
|
29
|
+
*
|
|
30
|
+
* The bounded source-review prompt built here is METADATA ONLY — repository root, canonical
|
|
31
|
+
* file paths, review depth, base SHA, and four fixed prohibitions. It never embeds file
|
|
32
|
+
* contents. If the assembled prompt exceeds a lane's resolved budget, that lane's dispatch
|
|
33
|
+
* hard-fails before `invoke` runs for it — no silent truncation of the file list.
|
|
34
|
+
*/
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.SOURCE_REVIEW_PROHIBITIONS = exports.DISPATCH_REASON = void 0;
|
|
40
|
+
exports.buildSourceReviewPrompt = buildSourceReviewPrompt;
|
|
41
|
+
exports.dispatchReviewerLanes = dispatchReviewerLanes;
|
|
42
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
43
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
44
|
+
const prompt_budget_cjs_1 = require("./prompt-budget.cjs");
|
|
45
|
+
const security_cjs_1 = require("./security.cjs");
|
|
46
|
+
const review_lane_invocation_cjs_1 = require("./review-lane-invocation.cjs");
|
|
47
|
+
const review_reviewer_selection_cjs_1 = require("./review-reviewer-selection.cjs");
|
|
48
|
+
/** Closed set of request-level (not per-lane) halt reasons. Mirrors `LANE_UNAVAILABLE`'s shape. */
|
|
49
|
+
exports.DISPATCH_REASON = Object.freeze({
|
|
50
|
+
TRAIT_NOT_ENABLED: 'trait_not_enabled',
|
|
51
|
+
NO_LANES_SELECTED: 'no_lanes_selected',
|
|
52
|
+
SELECTION_FAILED: 'selection_failed',
|
|
53
|
+
INVALID_PATHS: 'invalid_paths',
|
|
54
|
+
PATH_ESCAPES_REPO_ROOT: 'path_escapes_repo_root',
|
|
55
|
+
MISSING_PROVENANCE: 'missing_provenance',
|
|
56
|
+
INVALID_PROVENANCE: 'invalid_provenance',
|
|
57
|
+
PROMPT_WRITE_FAILED: 'prompt_write_failed',
|
|
58
|
+
});
|
|
59
|
+
/** Fixed, non-negotiable prompt constraints (SAFE-03..SAFE-06). Order is the display order. */
|
|
60
|
+
exports.SOURCE_REVIEW_PROHIBITIONS = Object.freeze([
|
|
61
|
+
'Do not modify any source file.',
|
|
62
|
+
'Do not run tests.',
|
|
63
|
+
'Do not start background processes.',
|
|
64
|
+
'Do not poll or wait — return findings from a single read-only pass.',
|
|
65
|
+
]);
|
|
66
|
+
// #4209 RQ-04: a control character (newline, CR, NUL, ...) in ANY string this module embeds
|
|
67
|
+
// into the external prompt (`buildSourceReviewPrompt`) lets it inject a fabricated section —
|
|
68
|
+
// not just via `paths` (agy-F1's original finding), since `depth`, `baseSha`, and `repoRoot` land
|
|
69
|
+
// in that same markdown. Every embedded string is checked against this ONE shared boundary.
|
|
70
|
+
const CONTROL_CHAR = /[\x00-\x1f\x7f\u2028\u2029]/;
|
|
71
|
+
function defaultWritePromptFile(filePath, content) {
|
|
72
|
+
node_fs_1.default.writeFileSync(filePath, content, 'utf8');
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Validate that every path is a non-empty string resolving INSIDE `repoRoot` — blocks `..`
|
|
76
|
+
* traversal and absolute paths pointing elsewhere before any lane sees them.
|
|
77
|
+
*/
|
|
78
|
+
function validatePaths(repoRoot, paths) {
|
|
79
|
+
if (!Array.isArray(paths) || paths.length === 0) {
|
|
80
|
+
return { ok: false, reason: exports.DISPATCH_REASON.INVALID_PATHS };
|
|
81
|
+
}
|
|
82
|
+
const root = node_path_1.default.resolve(String(repoRoot ?? ''));
|
|
83
|
+
// repoRoot itself may be a symlink (e.g. a `/tmp`-based worktree on macOS, where `/tmp` is
|
|
84
|
+
// itself a symlink to `/private/tmp`) — realpath it once so the per-path comparison below
|
|
85
|
+
// compares like with like, not a resolved child path against an unresolved root.
|
|
86
|
+
let realRoot;
|
|
87
|
+
try {
|
|
88
|
+
realRoot = node_fs_1.default.realpathSync(root);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
realRoot = root;
|
|
92
|
+
}
|
|
93
|
+
// #4209 agy-F1: a control character (newline, CR, NUL, ...) in a path lets a maliciously
|
|
94
|
+
// named repo file inject a fabricated section into the markdown prompt built from `paths`
|
|
95
|
+
// below (buildSourceReviewPrompt) — reject it here, at the shared trust boundary, rather than
|
|
96
|
+
// relying on the incidental quoting `git diff --name-only` happens to apply upstream.
|
|
97
|
+
for (const p of paths) {
|
|
98
|
+
if (typeof p !== 'string' || p.length === 0 || CONTROL_CHAR.test(p)) {
|
|
99
|
+
return { ok: false, reason: exports.DISPATCH_REASON.INVALID_PATHS };
|
|
100
|
+
}
|
|
101
|
+
// ADR-4650 decision 6: lexical family — this is the first of the two
|
|
102
|
+
// deliberate halves (#4209 WR-05); the ENOENT-tolerant realpath half
|
|
103
|
+
// below cannot be folded into a single `tryWithinRoot` call (its
|
|
104
|
+
// ancestor-walk would accept a deleted path via the nearest existing
|
|
105
|
+
// ancestor, not the explicit `continue` this code requires).
|
|
106
|
+
const resolved = node_path_1.default.resolve(root, p);
|
|
107
|
+
if ((0, security_cjs_1.tryWithinRootLexical)(p, root) === null) {
|
|
108
|
+
return { ok: false, reason: exports.DISPATCH_REASON.PATH_ESCAPES_REPO_ROOT };
|
|
109
|
+
}
|
|
110
|
+
// #4209 WR-05: `path.resolve` is lexical only — a symlink whose OWN path sits inside
|
|
111
|
+
// repoRoot can still point outside it, passing the check above while listing an
|
|
112
|
+
// out-of-repo file for the external lane to read. `fs.realpathSync` follows the link;
|
|
113
|
+
// ENOENT is expected and benign here (a `git diff --name-only` path can legitimately name
|
|
114
|
+
// a file already deleted in a stale worktree) and is not itself an escape.
|
|
115
|
+
let real;
|
|
116
|
+
try {
|
|
117
|
+
real = node_fs_1.default.realpathSync(resolved);
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if ((0, security_cjs_1.tryWithinRootLexical)(real, realRoot) === null) {
|
|
123
|
+
return { ok: false, reason: exports.DISPATCH_REASON.PATH_ESCAPES_REPO_ROOT };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return { ok: true };
|
|
127
|
+
}
|
|
128
|
+
// `resolveLaneBudget` (review-lane-invocation.cjs) resolves the number; `null` and a resolved
|
|
129
|
+
// `0` both mean unbounded (#2797) — the caller's overflow check must test both `!== null` and
|
|
130
|
+
// `!== 0`. See the call site below.
|
|
131
|
+
/**
|
|
132
|
+
* One-line depth definition for an external reviewer lane, condensed from `<depth_levels>` in
|
|
133
|
+
* `agents/gsd-code-reviewer.md` (#4209 review: a bare `quick`/`standard`/`deep` label means
|
|
134
|
+
* nothing to a third-party CLI that never sees that agent's system prompt — unlike the internal
|
|
135
|
+
* reviewer, whose own persona fully defines these three terms). Every category named here must
|
|
136
|
+
* stay a strict subset of what `<depth_levels>` actually does — `tests/reviewer-step-dispatch
|
|
137
|
+
* .test.cjs`'s "depthMeaning tracks depth_levels" tests assert each case against the real agent
|
|
138
|
+
* file, not just against this function, so the two cannot silently drift again. An unrecognised
|
|
139
|
+
* depth normalizes to `standard`'s text, matching `agents/gsd-code-reviewer.md`'s own "if depth
|
|
140
|
+
* is not one of quick/standard/deep, default to standard" rule — the raw label is not repeated
|
|
141
|
+
* here since `buildSourceReviewPrompt` already states it once, verbatim, earlier in the prompt.
|
|
142
|
+
*/
|
|
143
|
+
function depthMeaning(depth) {
|
|
144
|
+
switch (depth) {
|
|
145
|
+
case 'quick':
|
|
146
|
+
return 'pattern-scan without reading full file contents: hardcoded secrets, dangerous functions, debug artifacts, empty catch blocks, commented-out code';
|
|
147
|
+
case 'standard':
|
|
148
|
+
return 'read each changed file in context for bugs, security, and quality problems; cross-reference imports and exports';
|
|
149
|
+
case 'deep':
|
|
150
|
+
return 'standard, plus cross-file analysis: trace call chains, check type consistency at API boundaries, verify error propagation, check state mutation consistency, detect circular dependencies';
|
|
151
|
+
default:
|
|
152
|
+
return depthMeaning('standard');
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Build the bounded source-review prompt. Metadata only — repoRoot, paths, depth, base SHA, and
|
|
157
|
+
* the four fixed prohibitions. NEVER embeds file contents.
|
|
158
|
+
*/
|
|
159
|
+
function buildSourceReviewPrompt(input) {
|
|
160
|
+
// Base SHA is identical for every file and already stated once above — repeating it per line
|
|
161
|
+
// (as an earlier version of this prompt did) wastes real tokens at O(files), for zero
|
|
162
|
+
// information gain, on every dispatched lane.
|
|
163
|
+
const fileLines = input.paths.map((p) => `- ${p}`).join('\n');
|
|
164
|
+
const ruleLines = exports.SOURCE_REVIEW_PROHIBITIONS.map((r, i) => `${i + 1}. ${r}`).join('\n');
|
|
165
|
+
return [
|
|
166
|
+
'## Source Review Request',
|
|
167
|
+
'',
|
|
168
|
+
`Repository root: ${input.repoRoot}`,
|
|
169
|
+
`Review depth: ${input.depth}`,
|
|
170
|
+
`Base SHA: ${input.baseSha}`,
|
|
171
|
+
'',
|
|
172
|
+
'Review the changes introduced in each file below relative to the base SHA above, at the',
|
|
173
|
+
`requested depth (${depthMeaning(input.depth)}). Report every bug, security issue, and`,
|
|
174
|
+
'code-quality problem you find. For every claim you make, cite the exact file path and line',
|
|
175
|
+
'number(s) it applies to — a claim with no file:line citation cannot be independently',
|
|
176
|
+
're-verified and will be discarded by the consolidating reviewer. Performance issues',
|
|
177
|
+
'(O(n²), memory leaks) are out of scope unless also correctness issues (e.g. an infinite',
|
|
178
|
+
'loop) — do not flag them otherwise.',
|
|
179
|
+
'',
|
|
180
|
+
'### Files in scope',
|
|
181
|
+
fileLines,
|
|
182
|
+
'',
|
|
183
|
+
'### Rules',
|
|
184
|
+
ruleLines,
|
|
185
|
+
].join('\n');
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Dispatch every selected reviewer lane for one opted-in step. See module docstring for scope.
|
|
189
|
+
*/
|
|
190
|
+
async function dispatchReviewerLanes(input, deps) {
|
|
191
|
+
if (input.trait !== true) {
|
|
192
|
+
return { dispatched: false, ok: true, reason: exports.DISPATCH_REASON.TRAIT_NOT_ENABLED, results: [] };
|
|
193
|
+
}
|
|
194
|
+
const resolveSelection = deps.resolveSelection ?? review_reviewer_selection_cjs_1.resolveReviewerSelection;
|
|
195
|
+
const selection = resolveSelection(input.selection);
|
|
196
|
+
if (selection.selected.length === 0) {
|
|
197
|
+
// Distinguish "explicitly requested but every candidate was unavailable" (a real failure —
|
|
198
|
+
// `errors` is non-empty) from "nothing was ever requested" (a clean, inert no-op).
|
|
199
|
+
const reason = selection.errors.length > 0
|
|
200
|
+
? exports.DISPATCH_REASON.SELECTION_FAILED
|
|
201
|
+
: exports.DISPATCH_REASON.NO_LANES_SELECTED;
|
|
202
|
+
return { dispatched: false, ok: selection.errors.length === 0, reason, selection, results: [] };
|
|
203
|
+
}
|
|
204
|
+
const pathCheck = validatePaths(input.repoRoot, input.paths);
|
|
205
|
+
if (!pathCheck.ok) {
|
|
206
|
+
return { dispatched: false, ok: false, reason: pathCheck.reason, selection, results: [] };
|
|
207
|
+
}
|
|
208
|
+
// #4209 RQ-04: depth/baseSha/repoRoot/runDir land in the SAME markdown prompt `paths` does
|
|
209
|
+
// (buildSourceReviewPrompt, `dispatchReviewerLanes`'s `runDir`-derived promptPath write) — a
|
|
210
|
+
// control character in any of them is the identical injection vector agy-F1 found in `paths`,
|
|
211
|
+
// so this trust boundary must reject it here too, not just for the file list.
|
|
212
|
+
if (typeof input.depth !== 'string' || input.depth.length === 0
|
|
213
|
+
|| typeof input.baseSha !== 'string' || input.baseSha.length === 0
|
|
214
|
+
|| typeof input.repoRoot !== 'string' || input.repoRoot.length === 0
|
|
215
|
+
|| typeof input.runDir !== 'string' || input.runDir.length === 0) {
|
|
216
|
+
return { dispatched: false, ok: false, reason: exports.DISPATCH_REASON.MISSING_PROVENANCE, selection, results: [] };
|
|
217
|
+
}
|
|
218
|
+
// #4209 WR-04: a present-but-malicious field (control character) is a different failure mode
|
|
219
|
+
// than an absent one — MISSING_PROVENANCE above means "the caller never supplied this"; this
|
|
220
|
+
// branch means "the caller supplied something and it's an injection attempt," which a caller
|
|
221
|
+
// handling the two reasons differently (e.g. surfacing one as a config problem, the other as
|
|
222
|
+
// a security event) must be able to tell apart.
|
|
223
|
+
if (CONTROL_CHAR.test(input.depth) || CONTROL_CHAR.test(input.baseSha)
|
|
224
|
+
|| CONTROL_CHAR.test(input.repoRoot) || CONTROL_CHAR.test(input.runDir)) {
|
|
225
|
+
return { dispatched: false, ok: false, reason: exports.DISPATCH_REASON.INVALID_PROVENANCE, selection, results: [] };
|
|
226
|
+
}
|
|
227
|
+
// #4209 WR-03 (considered, declined): gating `depth` to code-review's quick/standard/deep
|
|
228
|
+
// enum here would reject the deliberately capability-neutral case this function supports —
|
|
229
|
+
// see "a second, unrelated synthetic step context dispatches through the same function
|
|
230
|
+
// identically" below, which passes a wholly different depth vocabulary on purpose to prove
|
|
231
|
+
// this dispatcher has no code-review-specific special-casing. `depthMeaning()`'s `standard`
|
|
232
|
+
// fallback for an off-enum value is accepted, not a bug, for that reason.
|
|
233
|
+
const { configGet, getLane, plan } = deps;
|
|
234
|
+
const writePromptFile = deps.writePromptFile ?? defaultWritePromptFile;
|
|
235
|
+
const prompt = buildSourceReviewPrompt(input);
|
|
236
|
+
const estimatedTokens = (0, prompt_budget_cjs_1.estimateTokens)(prompt);
|
|
237
|
+
// Written once, before any lane's plan() runs: `promptPath` is derived from `runDir` alone
|
|
238
|
+
// (see `artifactPaths`), constant across every lane in this dispatch by construction — there
|
|
239
|
+
// is no per-lane variance to defend against, so writing it per-lane (as an earlier version of
|
|
240
|
+
// this function did) was pure redundancy, not a real safeguard.
|
|
241
|
+
// A hoisted, whole-dispatch write (see the doc comment above) that throws must not escape as
|
|
242
|
+
// an uncaught exception — no lane can succeed anyway if the shared prompt file was never
|
|
243
|
+
// written, so this is a dispatch-level halt like `validatePaths`/`MISSING_PROVENANCE` above,
|
|
244
|
+
// not a per-lane failure.
|
|
245
|
+
try {
|
|
246
|
+
writePromptFile((0, review_lane_invocation_cjs_1.artifactPaths)(input.runDir, '').promptPath, prompt);
|
|
247
|
+
}
|
|
248
|
+
catch {
|
|
249
|
+
return { dispatched: false, ok: false, reason: exports.DISPATCH_REASON.PROMPT_WRITE_FAILED, selection, results: [] };
|
|
250
|
+
}
|
|
251
|
+
const results = [];
|
|
252
|
+
// Never narrow the requested set: an explicit reviewer the selector could not resolve is
|
|
253
|
+
// already surfaced in `selection.errors` — reflect that in the aggregate `ok` even though
|
|
254
|
+
// lanes that DID resolve still run below and keep their own results.
|
|
255
|
+
let anyFailed = selection.errors.length > 0;
|
|
256
|
+
// Tracks whether any lane actually reached plan() — `dispatched` must stay false when every
|
|
257
|
+
// selected slug turned out to be unresolvable, even though a `results` entry was still pushed.
|
|
258
|
+
let planned = false;
|
|
259
|
+
for (const slug of selection.selected) {
|
|
260
|
+
const lane = getLane(slug);
|
|
261
|
+
if (!lane) {
|
|
262
|
+
results.push({ slug, ok: false, reason: 'malformed_lane', detail: 'no such declared lane' });
|
|
263
|
+
anyFailed = true;
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
// #4209 review: a `promptChannel: 'none'` lane (coderabbit) is fed nothing and reviews
|
|
267
|
+
// whatever it independently sees fit (its own working-tree diff, review.md:367) rather than
|
|
268
|
+
// the bounded `paths`/`depth`/`baseSha` scope `buildSourceReviewPrompt` promises — silently
|
|
269
|
+
// dispatching it here would violate this interpreter's own scoped, metadata-only review
|
|
270
|
+
// contract. Reject before plan()/invoke() rather than let the mismatch surface as an
|
|
271
|
+
// unexplained out-of-scope review.
|
|
272
|
+
if (lane.transport === 'spawn' && lane.invoke.promptChannel === 'none') {
|
|
273
|
+
results.push({
|
|
274
|
+
slug,
|
|
275
|
+
ok: false,
|
|
276
|
+
reason: 'prompt_channel_unsupported',
|
|
277
|
+
detail: `lane '${slug}' declares promptChannel 'none' and cannot receive a scoped source-review prompt`,
|
|
278
|
+
});
|
|
279
|
+
anyFailed = true;
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
// A single throwing plan()/invoke() must not take down every sibling lane already collected
|
|
283
|
+
// in `results` — same rationale as gsd-tools.cjs's resolveLanePlan guard
|
|
284
|
+
// (#2494/#2605/#1698/#1936/#2073/#2176/#2589/#2794): belt and braces on purpose.
|
|
285
|
+
let planOutcome;
|
|
286
|
+
try {
|
|
287
|
+
planOutcome = plan(lane, { configGet, runDir: input.runDir, repoRoot: input.repoRoot });
|
|
288
|
+
}
|
|
289
|
+
catch (e) {
|
|
290
|
+
results.push({ slug, ok: false, reason: 'malformed_lane', detail: e instanceof Error ? e.message : String(e) });
|
|
291
|
+
anyFailed = true;
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
if (!planOutcome.ok) {
|
|
295
|
+
results.push({ slug, ok: false, reason: planOutcome.reason, detail: planOutcome.detail });
|
|
296
|
+
anyFailed = true;
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
const budget = (0, review_lane_invocation_cjs_1.resolveLaneBudget)(lane, configGet);
|
|
300
|
+
if (budget !== null && budget !== 0 && estimatedTokens > budget) {
|
|
301
|
+
results.push({
|
|
302
|
+
slug,
|
|
303
|
+
ok: false,
|
|
304
|
+
reason: 'budget_exceeded',
|
|
305
|
+
detail: `estimated ${estimatedTokens} tokens exceeds resolved budget ${budget} for lane '${slug}'`,
|
|
306
|
+
});
|
|
307
|
+
anyFailed = true;
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
planned = true;
|
|
311
|
+
let invokeOutcome;
|
|
312
|
+
try {
|
|
313
|
+
invokeOutcome = await deps.invoke(lane, planOutcome.plan);
|
|
314
|
+
}
|
|
315
|
+
catch (e) {
|
|
316
|
+
results.push({ slug, ok: false, reason: 'invoke_failed', detail: e instanceof Error ? e.message : String(e) });
|
|
317
|
+
anyFailed = true;
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
if (!invokeOutcome.ok)
|
|
321
|
+
anyFailed = true;
|
|
322
|
+
results.push({
|
|
323
|
+
slug,
|
|
324
|
+
ok: invokeOutcome.ok,
|
|
325
|
+
reason: invokeOutcome.reason,
|
|
326
|
+
detail: invokeOutcome.detail,
|
|
327
|
+
reviewPath: invokeOutcome.reviewPath,
|
|
328
|
+
errPath: invokeOutcome.errPath,
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
return {
|
|
332
|
+
dispatched: planned,
|
|
333
|
+
ok: !anyFailed,
|
|
334
|
+
selection,
|
|
335
|
+
results,
|
|
336
|
+
};
|
|
337
|
+
}
|
|
@@ -19,6 +19,9 @@ const { routeCjsCommandFamily } = cjsCommandRouterAdapter;
|
|
|
19
19
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
20
20
|
const roadmapUpgrade = require("./roadmap-upgrade.cjs");
|
|
21
21
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
22
|
+
const phaseIdCardMod = require("./phase-id-card.cjs");
|
|
23
|
+
const { phaseIdCard } = phaseIdCardMod;
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
22
25
|
const planningWorkspace = require("./planning-workspace.cjs");
|
|
23
26
|
const { planningDir } = planningWorkspace;
|
|
24
27
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
@@ -234,7 +237,7 @@ function routeRoadmapCommand({ roadmap, args, cwd, raw, error }) {
|
|
|
234
237
|
'upgrade': () => {
|
|
235
238
|
const dryRun = !args.includes('--apply');
|
|
236
239
|
// Parse `--convention <value>` and `--convention=<value>`. When the flag is
|
|
237
|
-
// absent entirely, default to the
|
|
240
|
+
// absent entirely, default to the legacy supported convention; when present
|
|
238
241
|
// with a missing/unsupported value, fall through to the rejection below
|
|
239
242
|
// (fail-closed — never silently run a migration the user did not request).
|
|
240
243
|
let convention = 'milestone-prefixed';
|
|
@@ -245,13 +248,18 @@ function routeRoadmapCommand({ roadmap, args, cwd, raw, error }) {
|
|
|
245
248
|
? token.slice(token.indexOf('=') + 1)
|
|
246
249
|
: (args[conventionFlagIdx + 1] ?? '');
|
|
247
250
|
}
|
|
248
|
-
if (convention !== 'milestone-prefixed') {
|
|
251
|
+
if (convention !== 'milestone-prefixed' && convention !== 'bracket') {
|
|
249
252
|
// No-throw hub contract (ADR-0012): a hub-dispatched handler must not call
|
|
250
253
|
// process.exit. Throw instead — the hub converts this to HandlerFailure and
|
|
251
254
|
// the adapter routes it through the injected error() boundary.
|
|
252
|
-
throw new Error('Only --convention milestone-prefixed is supported');
|
|
255
|
+
throw new Error('Only --convention milestone-prefixed or bracket is supported');
|
|
256
|
+
}
|
|
257
|
+
if (convention === 'bracket') {
|
|
258
|
+
// Keep stdout machine-readable for the dry-run JSON plan. The card is
|
|
259
|
+
// human guidance emitted at command start for both dry-run and apply.
|
|
260
|
+
process.stderr.write(`${phaseIdCard({ title: 'Bracket phase-ID convention' })}\n`);
|
|
253
261
|
}
|
|
254
|
-
const plan = roadmapUpgrade.computeMigrationPlan(cwd);
|
|
262
|
+
const plan = roadmapUpgrade.computeMigrationPlan(cwd, { convention });
|
|
255
263
|
roadmapUpgrade.applyMigration(cwd, plan, { dryRun });
|
|
256
264
|
},
|
|
257
265
|
},
|