@opengsd/gsd-core 1.10.0 → 1.11.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-debug-session-manager.md +11 -0
- package/agents/gsd-doc-synthesizer.md +2 -4
- package/agents/gsd-executor.md +5 -5
- package/agents/gsd-mempalace-curator.md +5 -2
- package/agents/gsd-phase-researcher.md +20 -1
- package/agents/gsd-plan-checker.md +37 -0
- package/agents/gsd-planner.md +44 -46
- package/agents/gsd-user-profiler.md +3 -0
- package/agents/gsd-verifier.md +12 -3
- package/bin/install.js +841 -971
- package/bin/lib/ui-safety-gate.cjs +2 -0
- package/commands/gsd/code-review.md +1 -1
- package/commands/gsd/execute-phase.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 +1 -1
- package/commands/gsd/review-backlog.md +2 -1
- package/commands/gsd/verify-work.md +1 -1
- package/gsd-core/bin/gsd-tools.cjs +469 -88
- package/gsd-core/bin/lib/active-workstream-store.cjs +138 -22
- package/gsd-core/bin/lib/agent-install-check.cjs +230 -32
- package/gsd-core/bin/lib/api-coverage.cjs +3 -5
- package/gsd-core/bin/lib/artifacts.cjs +3 -0
- package/gsd-core/bin/lib/assumption-delta.cjs +2 -4
- package/gsd-core/bin/lib/audit-command-router.cjs +9 -2
- package/gsd-core/bin/lib/audit.cjs +876 -240
- package/gsd-core/bin/lib/broken-windows.cjs +1 -1
- 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-registry.cjs +575 -101
- package/gsd-core/bin/lib/capability-source.cjs +92 -0
- package/gsd-core/bin/lib/capability-trust.cjs +444 -25
- package/gsd-core/bin/lib/capability-validator.cjs +495 -22
- package/gsd-core/bin/lib/capability-writer.cjs +3 -2
- package/gsd-core/bin/lib/check-command-router.cjs +71 -37
- package/gsd-core/bin/lib/claude-orchestration.cjs +56 -3
- package/gsd-core/bin/lib/codex-agent-toml.cjs +329 -0
- package/gsd-core/bin/lib/command-aliases.cjs +22 -0
- package/gsd-core/bin/lib/command-roster.cjs +44 -1
- package/gsd-core/bin/lib/commands.cjs +651 -86
- package/gsd-core/bin/lib/commonjs-marker.cjs +12 -6
- package/gsd-core/bin/lib/complexity-trigger.cjs +1172 -0
- package/gsd-core/bin/lib/config-loader.cjs +75 -0
- package/gsd-core/bin/lib/config.cjs +10 -1
- package/gsd-core/bin/lib/core-utils.cjs +127 -29
- package/gsd-core/bin/lib/decisions.cjs +23 -0
- package/gsd-core/bin/lib/fallow-runner.cjs +20 -44
- package/gsd-core/bin/lib/frontmatter.cjs +155 -20
- package/gsd-core/bin/lib/gap-checker.cjs +68 -7
- package/gsd-core/bin/lib/git-base-branch.cjs +102 -0
- 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 +145 -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 +265 -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 +173 -0
- package/gsd-core/bin/lib/health-diagnostic-types.cjs +68 -0
- package/gsd-core/bin/lib/health-diagnostic.cjs +431 -0
- package/gsd-core/bin/lib/host-runtime-detection.cjs +134 -0
- package/gsd-core/bin/lib/init.cjs +321 -129
- package/gsd-core/bin/lib/install-effort-resolver.cjs +73 -30
- package/gsd-core/bin/lib/install-engine.cjs +745 -258
- package/gsd-core/bin/lib/install-fs-adapter.cjs +262 -0
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +203 -0
- package/gsd-core/bin/lib/install-profiles.cjs +134 -57
- 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-migrations.cjs +138 -31
- package/gsd-core/bin/lib/io.cjs +10 -0
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +2 -1
- package/gsd-core/bin/lib/markdown-table.cjs +133 -20
- package/gsd-core/bin/lib/milestone-lock.cjs +248 -0
- package/gsd-core/bin/lib/milestone.cjs +754 -70
- package/gsd-core/bin/lib/model-catalog.cjs +59 -1
- package/gsd-core/bin/lib/model-resolver.cjs +183 -40
- package/gsd-core/bin/lib/normalize-test-command.cjs +1 -1
- package/gsd-core/bin/lib/pattern.cjs +122 -0
- package/gsd-core/bin/lib/phase-estimation.cjs +1 -1
- package/gsd-core/bin/lib/phase-id.cjs +444 -36
- package/gsd-core/bin/lib/phase-lifecycle.cjs +28 -3
- package/gsd-core/bin/lib/phase-locator.cjs +125 -18
- package/gsd-core/bin/lib/phase.cjs +646 -143
- package/gsd-core/bin/lib/plan-dependency-graph.cjs +72 -1
- package/gsd-core/bin/lib/plan-drift-guard.cjs +120 -0
- package/gsd-core/bin/lib/plan-scan.cjs +86 -2
- package/gsd-core/bin/lib/planning-scope.cjs +31 -0
- package/gsd-core/bin/lib/planning-snapshot.cjs +890 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +56 -6
- package/gsd-core/bin/lib/probe-core.cjs +1 -1
- package/gsd-core/bin/lib/profile-output.cjs +1 -1
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +740 -0
- package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +11 -6
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +13 -4
- 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 +34 -0
- package/gsd-core/bin/lib/roadmap-parser.cjs +943 -184
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +37 -10
- package/gsd-core/bin/lib/roadmap.cjs +385 -94
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +608 -46
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +14 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +426 -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 +115 -3
- package/gsd-core/bin/lib/runtime-name-policy.cjs +3 -1
- package/gsd-core/bin/lib/runtime-slash.cjs +27 -9
- package/gsd-core/bin/lib/security.cjs +104 -5
- package/gsd-core/bin/lib/shell-command-projection.cjs +275 -3
- package/gsd-core/bin/lib/smart-entry.cjs +142 -22
- package/gsd-core/bin/lib/state-command-router.cjs +5 -1
- package/gsd-core/bin/lib/state-document.cjs +152 -8
- package/gsd-core/bin/lib/state-transition.cjs +371 -117
- package/gsd-core/bin/lib/state.cjs +1794 -357
- package/gsd-core/bin/lib/surface.cjs +23 -9
- 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 +9 -3
- package/gsd-core/bin/lib/uat.cjs +399 -56
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +157 -0
- package/gsd-core/bin/lib/ui-safety-gate.cjs +14 -5
- package/gsd-core/bin/lib/unusable-input.cjs +24 -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.cjs +20 -6
- package/gsd-core/bin/lib/vendor/README.md +37 -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 +258 -8
- package/gsd-core/bin/lib/verify.cjs +368 -888
- 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.cjs +2 -2
- package/gsd-core/bin/lib/worktree-safety.cjs +176 -9
- package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +7 -1
- package/gsd-core/references/agent-contracts.md +43 -26
- package/gsd-core/references/checkpoints.md +2 -2
- package/gsd-core/references/context-budget.md +1 -1
- package/gsd-core/references/dispatch-isolation-gate.md +138 -0
- package/gsd-core/references/doc-conflict-engine.md +1 -1
- package/gsd-core/references/execute-mvp-tdd.md +3 -3
- package/gsd-core/references/execute-phase-between-wave-reset.md +6 -2
- 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 +6 -2
- package/gsd-core/references/gate-prompts.md +1 -1
- package/gsd-core/references/git-planning-commit.md +2 -1
- package/gsd-core/references/loop-hook-dispatch.md +39 -2
- package/gsd-core/references/model-profiles.md +12 -4
- package/gsd-core/references/mvp-concepts.md +9 -9
- package/gsd-core/references/planner-guidance.md +3 -9
- package/gsd-core/references/planner-preconditions.md +1 -1
- package/gsd-core/references/planner-reviews.md +1 -1
- package/gsd-core/references/planning-config.md +8 -6
- package/gsd-core/references/revision-loop.md +1 -1
- package/gsd-core/references/specless-probe-fallback.md +1 -1
- package/gsd-core/references/universal-anti-patterns.md +3 -3
- package/gsd-core/references/verifier-phase-gates.md +192 -0
- package/gsd-core/references/verify-mvp-mode.md +1 -1
- package/gsd-core/references/workstream-flag.md +22 -6
- package/gsd-core/templates/discussion-log.md +1 -1
- package/gsd-core/templates/phase-prompt.md +2 -4
- package/gsd-core/templates/state.md +4 -4
- package/gsd-core/templates/verification-report.md +9 -1
- package/gsd-core/workflows/ai-integration-phase.md +9 -11
- package/gsd-core/workflows/autonomous.md +1 -1
- package/gsd-core/workflows/cleanup.md +62 -3
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +13 -3
- package/gsd-core/workflows/code-review-fix.md +37 -10
- package/gsd-core/workflows/code-review.md +38 -12
- package/gsd-core/workflows/complete-milestone.md +141 -18
- package/gsd-core/workflows/debug.md +7 -5
- package/gsd-core/workflows/diagnose-issues.md +35 -9
- package/gsd-core/workflows/discuss-phase/modes/chain.md +2 -1
- package/gsd-core/workflows/discuss-phase/modes/default.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +2 -1
- package/gsd-core/workflows/edit-phase.md +26 -1
- package/gsd-core/workflows/eval-review.md +3 -5
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +31 -6
- 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 +2 -0
- package/gsd-core/workflows/execute-phase.md +38 -50
- package/gsd-core/workflows/execute-plan.md +36 -4
- package/gsd-core/workflows/explore.md +131 -4
- package/gsd-core/workflows/fast.md +10 -2
- package/gsd-core/workflows/health.md +73 -4
- package/gsd-core/workflows/import.md +4 -4
- package/gsd-core/workflows/ingest-docs.md +5 -5
- package/gsd-core/workflows/mvp-phase.md +6 -3
- package/gsd-core/workflows/new-milestone.md +14 -9
- package/gsd-core/workflows/new-project.md +14 -14
- package/gsd-core/workflows/next.md +12 -0
- package/gsd-core/workflows/plan-phase.md +41 -17
- package/gsd-core/workflows/plan-review-convergence.md +50 -2
- package/gsd-core/workflows/progress.md +34 -6
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +4 -4
- package/gsd-core/workflows/quick/steps/quick-verification.md +27 -6
- package/gsd-core/workflows/quick/steps/research-phase.md +2 -2
- package/gsd-core/workflows/quick.md +35 -15
- package/gsd-core/workflows/review.md +26 -5
- package/gsd-core/workflows/secure-phase.md +1 -1
- package/gsd-core/workflows/session-report.md +2 -1
- package/gsd-core/workflows/settings.md +66 -2
- package/gsd-core/workflows/ship.md +104 -44
- package/gsd-core/workflows/spec-phase.md +30 -12
- package/gsd-core/workflows/sync-skills.md +63 -8
- package/gsd-core/workflows/transition.md +46 -11
- package/gsd-core/workflows/ui-phase.md +5 -5
- package/gsd-core/workflows/ui-review.md +2 -2
- package/gsd-core/workflows/update.md +1 -1
- package/gsd-core/workflows/validate-phase.md +1 -1
- package/gsd-core/workflows/verify-work.md +9 -7
- package/hooks/dist/gsd-agent-isolation-guard.js +103 -14
- package/hooks/dist/gsd-check-update-worker.js +56 -13
- package/hooks/dist/gsd-check-update.js +19 -1
- package/hooks/dist/gsd-cursor-pre-tool.js +0 -3
- package/hooks/dist/gsd-cursor-subagent-start.js +77 -2
- package/hooks/dist/gsd-cursor-subagent-stop.js +3 -2
- package/hooks/dist/gsd-prompt-guard.js +21 -20
- package/hooks/dist/gsd-read-injection-scanner.js +38 -24
- package/hooks/dist/gsd-statusline.js +18 -0
- package/hooks/dist/gsd-update-banner.js +22 -1
- package/hooks/dist/gsd-workflow-guard.js +134 -36
- package/hooks/dist/lib/git-cmd.js +92 -59
- 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/gsd-agent-isolation-guard.js +103 -14
- package/hooks/gsd-check-update-worker.js +56 -13
- package/hooks/gsd-check-update.js +19 -1
- package/hooks/gsd-cursor-pre-tool.js +0 -3
- package/hooks/gsd-cursor-subagent-start.js +77 -2
- package/hooks/gsd-cursor-subagent-stop.js +3 -2
- package/hooks/gsd-prompt-guard.js +21 -20
- package/hooks/gsd-read-injection-scanner.js +38 -24
- package/hooks/gsd-statusline.js +18 -0
- package/hooks/gsd-update-banner.js +22 -1
- package/hooks/gsd-workflow-guard.js +134 -36
- package/hooks/lib/git-cmd.js +92 -59
- 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/package.json +21 -9
- package/pi/gsd.cjs +19 -5
- 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/changeset/lint.cjs +60 -5
- package/scripts/check-alias-drift.cjs +7 -43
- package/scripts/check-contract-drift.cjs +297 -0
- package/scripts/ci-test-scope.cjs +19 -2
- package/scripts/command-contract-helpers.cjs +903 -1
- package/scripts/gen-adr-index.cjs +728 -38
- package/scripts/gen-capability-registry.cjs +3 -15
- package/scripts/gen-context-index.cjs +2 -11
- package/scripts/gen-health-docs.cjs +390 -0
- package/scripts/gen-inventory-manifest.cjs +50 -4
- package/scripts/gen-loop-host-contract.cjs +4 -24
- package/scripts/gen-registry.cjs +3 -14
- package/scripts/lib/alias-drift-families.cjs +46 -0
- package/scripts/lib/drift-scan.cjs +278 -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-eslint-glob-coverage.allowlist.json +34 -0
- package/scripts/lint-eslint-glob-coverage.cjs +340 -0
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +237 -0
- package/scripts/lint-health-diagnostic-rule-table.cjs +404 -0
- package/scripts/lint-hooks-runtime-build-seam.cjs +262 -0
- package/scripts/lint-milestone-window-drift.cjs +468 -0
- package/scripts/lint-phase-enumeration-drift.cjs +479 -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 +434 -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 +320 -0
- package/scripts/lint-state-field-drift.cjs +805 -0
- package/scripts/lint-state-write-path-drift.cjs +1045 -0
- package/scripts/lint-test-file-count.allowlist.json +21 -10
- package/scripts/lint-unreachable-guard-drift.cjs +843 -0
- package/scripts/lint-vendored-deps.cjs +124 -0
- package/scripts/pr-changed-files.cjs +63 -0
- package/scripts/pr-template-policy.cjs +14 -4
- package/scripts/prompt-injection-scan.sh +25 -0
- package/scripts/require-issue-link-policy.cjs +192 -0
- package/scripts/state-write-path-drift-baseline.json +19 -0
- package/scripts/sync-runtime-launcher.cjs +2 -4
- package/skills/gsd-autonomous/SKILL.md +0 -1
- package/skills/gsd-code-review/SKILL.md +1 -1
- package/skills/gsd-execute-phase/SKILL.md +1 -2
- 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 +1 -1
- 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/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/run-affected-tests.cjs +0 -7
- package/scripts/run-tests.cjs +0 -1051
|
@@ -61,12 +61,14 @@ gaps = [
|
|
|
61
61
|
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
|
|
62
62
|
USE_WORKTREES=$(gsd_run query config-get workflow.use_worktrees --raw 2>/dev/null || echo "true")
|
|
63
63
|
RUNTIME=$(gsd_run query config-get runtime --default claude --raw 2>/dev/null || echo "claude")
|
|
64
|
-
if [ "$RUNTIME" != "claude" ] && [ "$USE_WORKTREES" != "false" ]; then
|
|
65
|
-
echo "FATAL: git worktree isolation (isolation=\"worktree\") is unsupported on runtime '$RUNTIME' — it would run executor agents unisolated against the main checkout. Set workflow.use_worktrees=false." >&2
|
|
66
|
-
exit 1
|
|
67
|
-
fi
|
|
68
64
|
```
|
|
69
65
|
|
|
66
|
+
**Resolve isolation now (#2584/#2652).** Read @gsd-core/references/dispatch-isolation-gate.md
|
|
67
|
+
and run its `Resolve ISOLATION`, `Single-agent dispatch sites`, and `Resolve the harness flag`
|
|
68
|
+
blocks in order; they set `ISOLATION`/`HARNESS_FLAG` via `query dispatch-isolation`.
|
|
69
|
+
`ISOLATION` — not `RUNTIME` — gates the worktree decision at spawn; the `spawn_agents` step
|
|
70
|
+
below consumes both variables.
|
|
71
|
+
|
|
70
72
|
**Report diagnosis plan to user:**
|
|
71
73
|
|
|
72
74
|
```
|
|
@@ -108,18 +110,32 @@ the fork base cannot be reliably resolved. The verify-only `<worktree_branch_che
|
|
|
108
110
|
stays active as a backstop in both cases.
|
|
109
111
|
|
|
110
112
|
```bash
|
|
111
|
-
if [ "$
|
|
113
|
+
if [ "$ISOLATION" = "harness-worktree" ]; then
|
|
112
114
|
_DIAG_SHOULD_DEGRADE=$(gsd_run query worktree.base-check --pick shouldDegrade 2>/dev/null || true)
|
|
113
115
|
if [ "$_DIAG_SHOULD_DEGRADE" = "true" ]; then
|
|
114
116
|
_DIAG_DEGRADE_MSG=$(gsd_run query worktree.base-check --pick message 2>/dev/null || true)
|
|
115
117
|
[ -n "$_DIAG_DEGRADE_MSG" ] && printf '%s\n' "$_DIAG_DEGRADE_MSG" >&2
|
|
116
118
|
echo "⚠ [#2649] Worktree fork base diverged from orchestrator HEAD — auto-degrading to sequential mode for diagnosis to avoid a base-mismatch halt." >&2
|
|
119
|
+
ISOLATION=none
|
|
117
120
|
USE_WORKTREES=false
|
|
118
121
|
fi
|
|
119
122
|
fi
|
|
123
|
+
|
|
124
|
+
# Re-record after the base-check degrade, immediately before the spawn below, so the
|
|
125
|
+
# #3045 sentinel matches the dispatch the guard is about to see (#3045).
|
|
126
|
+
gsd_run query dispatch-isolation --raw --force-isolation "$ISOLATION" >/dev/null 2>&1 || true
|
|
120
127
|
```
|
|
121
128
|
|
|
122
|
-
**Spawn debug agents
|
|
129
|
+
**Spawn debug agents — parallel only when each one is isolated:**
|
|
130
|
+
|
|
131
|
+
**`ISOLATION` decides the fan-out, not just the flag (#2652).** When
|
|
132
|
+
`ISOLATION = "harness-worktree"`, spawn all agents in a single message: each gets its own
|
|
133
|
+
worktree, so concurrent edits cannot collide. When `ISOLATION = "none"` — including after the
|
|
134
|
+
`orchestrator-worktree` fallback and after the #2649 base-check degrade — the agents would all
|
|
135
|
+
run against the **primary checkout**, so spawn them **one at a time**, waiting for each to
|
|
136
|
+
return before spawning the next. Fanning out unisolated debuggers is the outcome the
|
|
137
|
+
`orchestrator-worktree` degrade exists to avoid; degrading the flag while keeping the
|
|
138
|
+
parallelism would announce sequential mode and then do the opposite.
|
|
123
139
|
|
|
124
140
|
For each gap, fill the debug-subagent-prompt template and spawn:
|
|
125
141
|
|
|
@@ -127,22 +143,32 @@ Print: `◆ Spawning diagnostics agent... (each runs in a subagent — no output
|
|
|
127
143
|
|
|
128
144
|
Before spawning, materialize the guard into WORKTREE_GUARD: read `gsd-core/references/worktree-branch-check.md`, substitute `{EXPECTED_BASE}` with `$EXPECTED_BASE`, and use the resulting `<worktree_branch_check>` block (the runnable guard) as WORKTREE_GUARD below.
|
|
129
145
|
|
|
146
|
+
**Only when `ISOLATION = "harness-worktree"`.** When `ISOLATION = "none"` the agent runs on
|
|
147
|
+
the main working tree, where the guard's HEAD assertion cannot hold — set `WORKTREE_GUARD` to
|
|
148
|
+
the empty string instead, or every diagnostic agent halts on a base mismatch it was never
|
|
149
|
+
meant to check (#2652).
|
|
150
|
+
|
|
151
|
+
**Substitute `{harnessFlag}` in the `Agent()` call below** with `$HARNESS_FLAG` followed by a
|
|
152
|
+
comma when `ISOLATION = "harness-worktree"`, and with the empty string otherwise — the same
|
|
153
|
+
build-time substitution `execute-phase.md` performs. `{harnessFlag}` is a template
|
|
154
|
+
placeholder, not a shell variable.
|
|
155
|
+
|
|
130
156
|
<!-- #2508 runtime-aware-dispatch -->
|
|
131
157
|
|
|
132
158
|
> **Runtime-aware dispatch (#2508 Phase 4).** GSD workflows dispatch specialized subagents by role. Before dispatching on a built-in-only runtime (kimi-code — three built-ins only), resolve the role to a built-in via `gsd_run query resolve-dispatch-type --requested <role> --raw`. On named-dispatch runtimes (Claude/OpenCode/…) the role is returned unchanged; on kimi-code it maps to `coder`/`explore`/`plan` by role-suffix. The persona rides `${AGENT_SKILLS_<ROLE>}` (Phase 3) regardless. See @gsd-core/references/runtime-aware-dispatch.md.
|
|
133
159
|
|
|
134
160
|
```
|
|
135
161
|
Agent(
|
|
136
|
-
prompt=filled_debug_subagent_prompt + "\n\n" + WORKTREE_GUARD + "\n\n<
|
|
162
|
+
prompt=filled_debug_subagent_prompt + "\n\n" + WORKTREE_GUARD + "\n\n<required_reading>\n- {phase_dir}/{phase_num}-UAT.md\n- {state_path}\n</required_reading>\n${AGENT_SKILLS_DEBUGGER}",
|
|
137
163
|
subagent_type="gsd-debugger",
|
|
138
|
-
|
|
164
|
+
{harnessFlag}
|
|
139
165
|
description="Debug: {truth_short}"
|
|
140
166
|
)
|
|
141
167
|
```
|
|
142
168
|
|
|
143
169
|
> **ORCHESTRATOR RULE — CODEX RUNTIME**: After calling Agent() above to spawn debug agent(s), stop working on this task immediately. Do not read more files, edit code, or run tests related to these gaps while the subagent(s) are active. Wait for all subagents to return before proceeding. This prevents duplicate work, conflicting edits, and wasted context.
|
|
144
170
|
|
|
145
|
-
**All agents spawn in single message
|
|
171
|
+
**All agents spawn in a single message (parallel execution) ONLY when `ISOLATION = "harness-worktree"`.** When `ISOLATION = "none"`, spawn one agent per message and wait for each to return — see the fan-out rule above (#2652).
|
|
146
172
|
|
|
147
173
|
Template placeholders:
|
|
148
174
|
- `{truth}`: The expected behavior that failed
|
|
@@ -33,7 +33,8 @@ _GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-pars
|
|
|
33
33
|
|
|
34
34
|
3. Read consolidated auto-mode (`active` = chain flag OR user preference):
|
|
35
35
|
```bash
|
|
36
|
-
AUTO_MODE=$(gsd_run query check auto-mode --pick active 2>/dev/null
|
|
36
|
+
AUTO_MODE=$(gsd_run query check auto-mode --pick active 2>/dev/null)
|
|
37
|
+
AUTO_MODE="${AUTO_MODE:-false}"
|
|
37
38
|
```
|
|
38
39
|
|
|
39
40
|
4. **If `--auto` or `--chain` flag present AND `AUTO_MODE` is not true:**
|
|
@@ -96,7 +96,7 @@ These user-referenced docs are often MORE important than ROADMAP.md refs because
|
|
|
96
96
|
|
|
97
97
|
**Thinking partner (conditional):**
|
|
98
98
|
If `features.thinking_partner` is enabled in config, check the user's answer for tradeoff signals
|
|
99
|
-
(see `references/thinking-partner.md` for signal list). If tradeoff detected:
|
|
99
|
+
(see `gsd-core/references/thinking-partner.md` for signal list). If tradeoff detected:
|
|
100
100
|
|
|
101
101
|
```text
|
|
102
102
|
I notice competing priorities here — {option_A} optimizes for {goal_A} while {option_B} optimizes for {goal_B}.
|
|
@@ -642,7 +642,8 @@ Check for auto-advance trigger:
|
|
|
642
642
|
```
|
|
643
643
|
3. Read consolidated auto-mode (`active` = chain flag OR user preference):
|
|
644
644
|
```bash
|
|
645
|
-
AUTO_MODE=$(gsd_run query check auto-mode --pick active 2>/dev/null
|
|
645
|
+
AUTO_MODE=$(gsd_run query check auto-mode --pick active 2>/dev/null)
|
|
646
|
+
AUTO_MODE="${AUTO_MODE:-false}"
|
|
646
647
|
```
|
|
647
648
|
|
|
648
649
|
**If `--auto` flag present AND `AUTO_MODE` is not true:**
|
|
@@ -233,11 +233,34 @@ Wait for confirmation. If the user says `n`, exit without writing.
|
|
|
233
233
|
</step>
|
|
234
234
|
|
|
235
235
|
<step name="write_updated_phase">
|
|
236
|
+
Before writing, capture the current milestone scope (window scope + phase set) so the write can be verified against it:
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
SCOPE_BEFORE=$(gsd_run query roadmap milestone-scope)
|
|
240
|
+
```
|
|
241
|
+
|
|
236
242
|
Write the updated phase back in place in ROADMAP.md.
|
|
237
243
|
|
|
238
244
|
Read the full ROADMAP.md content, locate the phase section by its header (`## Phase {N}:` or `### Phase {N}:`), and replace exactly the old section text with the new section text. All content before and after the section (including other phases, milestone headers, and the summary checklist) must be left unchanged.
|
|
239
245
|
|
|
240
|
-
After writing
|
|
246
|
+
After writing, re-derive the milestone scope and compare it to the capture:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
SCOPE_AFTER=$(gsd_run query roadmap milestone-scope)
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
If `scope` or `phases` differs from SCOPE_BEFORE, the replacement text introduced a heading that terminates the current milestone window (a level 1-3 heading carrying a version token, a ✅/📋/🚧/🔄 marker, or the word "Milestone"). Restore ROADMAP.md by replacing the new section text with the original section text, then report and stop — do NOT update STATE.md and do NOT retry the write:
|
|
253
|
+
|
|
254
|
+
```
|
|
255
|
+
ERROR: edit rejected — milestone scope changed
|
|
256
|
+
Phase set before: {SCOPE_BEFORE phases} / after: {SCOPE_AFTER phases}
|
|
257
|
+
ROADMAP.md rolled back to the original section.
|
|
258
|
+
The updated phase text must not introduce a milestone-scoping heading; rewrite the offending line as plain text or a list item.
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Exit.
|
|
262
|
+
|
|
263
|
+
If the milestone scope is unchanged, update STATE.md Roadmap Evolution:
|
|
241
264
|
|
|
242
265
|
```bash
|
|
243
266
|
gsd_run query state.add-roadmap-evolution \
|
|
@@ -277,6 +300,7 @@ Fields changed: {changed_field_list}
|
|
|
277
300
|
- Don't edit in_progress/completed phases without --force
|
|
278
301
|
- Don't use raw Write on ROADMAP.md without reading it first; always replace section in place
|
|
279
302
|
- Don't modify the phase directory structure — only ROADMAP.md changes
|
|
303
|
+
- Don't introduce a milestone-scoping heading (level 1-3 with a version token, ✅/📋/🚧/🔄 marker, or "Milestone") in field values — it terminates the current milestone window; the post-write scope check rolls the edit back
|
|
280
304
|
- Don't commit the change — that's the user's decision
|
|
281
305
|
</anti_patterns>
|
|
282
306
|
|
|
@@ -290,6 +314,7 @@ Edit-phase is complete when:
|
|
|
290
314
|
- [ ] depends_on references validated; invalid references blocked
|
|
291
315
|
- [ ] Diff shown and confirmed by user
|
|
292
316
|
- [ ] Updated phase written back in place; number, position, and status preserved
|
|
317
|
+
- [ ] Milestone scope verified unchanged after the write (rollback + error on mismatch)
|
|
293
318
|
- [ ] STATE.md Roadmap Evolution updated
|
|
294
319
|
- [ ] User informed of next steps
|
|
295
320
|
</success_criteria>
|
|
@@ -91,11 +91,11 @@ Conduct evaluation coverage audit of Phase {phase_number}: {phase_name}
|
|
|
91
91
|
{If no AI-SPEC: "Audit against general AI eval best practices."}
|
|
92
92
|
</objective>
|
|
93
93
|
|
|
94
|
-
<
|
|
94
|
+
<required_reading>
|
|
95
95
|
- {summary_paths}
|
|
96
96
|
- {plan_paths}
|
|
97
97
|
- {ai_spec_path if exists}
|
|
98
|
-
</
|
|
98
|
+
</required_reading>
|
|
99
99
|
|
|
100
100
|
<input>
|
|
101
101
|
ai_spec_path: {ai_spec_path or "none"}
|
|
@@ -143,10 +143,8 @@ Read the written EVAL-REVIEW.md. Extract:
|
|
|
143
143
|
|
|
144
144
|
## 6. Commit
|
|
145
145
|
|
|
146
|
-
**If `commit_docs` is true:**
|
|
147
146
|
```bash
|
|
148
|
-
|
|
149
|
-
git commit -m "docs({phase_slug}): add EVAL-REVIEW.md — score {overall_score}/100 ({verdict})"
|
|
147
|
+
gsd_run query commit "docs({phase_slug}): add EVAL-REVIEW.md — score {overall_score}/100 ({verdict})" --files "${EVAL_REVIEW_FILE}"
|
|
150
148
|
```
|
|
151
149
|
|
|
152
150
|
</process>
|
|
@@ -7,6 +7,11 @@ resolution and its fail-closed guard.
|
|
|
7
7
|
|
|
8
8
|
## Resolve ISOLATION
|
|
9
9
|
|
|
10
|
+
The resolution rule is shared with every other dispatch site — see
|
|
11
|
+
@gsd-core/references/dispatch-isolation-gate.md, the canonical statement of the
|
|
12
|
+
`ISOLATION`-not-`RUNTIME` contract (#2652). This fragment keeps the wave-specific
|
|
13
|
+
extras (`worktree.reap-orphans`, the `worktree.base-check` auto-degrade) inline below.
|
|
14
|
+
|
|
10
15
|
Run this in the config-gate step, right after `RUNTIME`/`USE_WORKTREES` are read.
|
|
11
16
|
|
|
12
17
|
```bash
|
|
@@ -20,16 +25,33 @@ _GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-pars
|
|
|
20
25
|
# threads the phase identifier into that same atomic write (mode + harnessFlag
|
|
21
26
|
# + phase together — see hooks/lib/isolation-sentinel.js for how the guards
|
|
22
27
|
# consume it).
|
|
23
|
-
|
|
28
|
+
# Keep the resolver's own failure DISTINGUISHABLE from a genuine `none`, exactly
|
|
29
|
+
# as references/dispatch-isolation-gate.md does — this site declares that gate
|
|
30
|
+
# canonical, so it must not carry the older collapsing shape. Both outcomes fail
|
|
31
|
+
# closed, which is right, but only one of them may claim the host declared no
|
|
32
|
+
# primitive (#2652 review).
|
|
33
|
+
_ISOLATION_RAW=$(gsd_run query dispatch-isolation --raw --phase "${PHASE_NUMBER:-}" 2>/dev/null)
|
|
34
|
+
_ISOLATION_RC=$?
|
|
35
|
+
if [ $_ISOLATION_RC -ne 0 ] || [ -z "$_ISOLATION_RAW" ]; then
|
|
36
|
+
ISOLATION=none
|
|
37
|
+
ISOLATION_RESOLVED=false # fail closed, but we did NOT learn a verdict
|
|
38
|
+
else
|
|
39
|
+
ISOLATION="$_ISOLATION_RAW"
|
|
40
|
+
ISOLATION_RESOLVED=true
|
|
41
|
+
fi
|
|
24
42
|
case "$ISOLATION" in
|
|
25
43
|
harness-worktree|orchestrator-worktree|none) ;;
|
|
26
|
-
*) ISOLATION=none ;;
|
|
44
|
+
*) ISOLATION=none; ISOLATION_RESOLVED=false ;; # out of vocabulary is not a verdict either
|
|
27
45
|
esac
|
|
28
46
|
|
|
29
47
|
# Project-level opt-out wins on every host; a host with no primitive fails closed.
|
|
30
48
|
[ "$USE_WORKTREES" = "false" ] && ISOLATION=none
|
|
31
49
|
if [ "$ISOLATION" = "none" ] && [ "$USE_WORKTREES" != "false" ]; then
|
|
32
|
-
|
|
50
|
+
if [ "$ISOLATION_RESOLVED" = "true" ]; then
|
|
51
|
+
echo "FATAL: runtime '$RUNTIME' declares no executor-isolation primitive (dispatch.isolation=none) — executors would run unisolated against the main checkout. Set workflow.use_worktrees=false." >&2
|
|
52
|
+
else
|
|
53
|
+
echo "FATAL: could not resolve this runtime's executor-isolation capability — 'gsd_run query dispatch-isolation' failed or returned nothing, so GSD cannot tell whether isolation is available. Refusing to dispatch rather than guess (a guard that cannot verify must not answer 'safe'). Re-run once the gsd-tools shim resolves, or set workflow.use_worktrees=false to run sequentially on purpose." >&2
|
|
54
|
+
fi
|
|
33
55
|
exit 1
|
|
34
56
|
fi
|
|
35
57
|
|
|
@@ -108,7 +130,7 @@ Run the loop below once per runnable plan in the wave, **one plan at a time** (`
|
|
|
108
130
|
|
|
109
131
|
**Before running the bash block, substitute the plan's identifiers into it** exactly as you do for the `Agent()` prompt on the harness path: replace `{plan_number}` and `{phase_number}` with this plan's values. They are template placeholders, not shell variables. `$ORCH_ROOT` and `$EXPECTED_BASE` are real shell variables, already assigned earlier in this step; `$WAVE_WORKTREE_MANIFEST` was initialized above.
|
|
110
132
|
|
|
111
|
-
First build the executor prompt. It is the **same prompt text the harness path's `Agent()` call uses**, with the harness-only framing removed — drop the `<worktree_branch_check>` build-time embed note and the `<parallel_execution>` harness block, keep `<objective>`, the execution context, and `<success_criteria>` verbatim. Assign it to a shell variable so it can be passed as one argument:
|
|
133
|
+
First build the executor prompt. It is the **same prompt text the harness path's `Agent()` call uses**, with the harness-only framing removed — drop the `<worktree_branch_check>` build-time embed note and the `<parallel_execution>` harness block, keep `<objective>`, the execution context, and `<success_criteria>` verbatim. The checkpoint gate rule (#3370, in `per-plan-executor-routing.md`) applies here too: add no prompt text refusing or overriding auto-approval for the default `gate="blocking"` — only `blocking-human` always surfaces. Assign it to a shell variable so it can be passed as one argument:
|
|
112
134
|
|
|
113
135
|
```bash
|
|
114
136
|
# Compose the executor prompt for THIS plan. Single-quoted multi-line
|
|
@@ -154,7 +176,8 @@ CREATE_JSON=$(gsd_run query worktree.create \
|
|
|
154
176
|
--path "$WT_PATH" \
|
|
155
177
|
--branch "$WT_BRANCH" \
|
|
156
178
|
--base "$EXPECTED_BASE" \
|
|
157
|
-
--root "$ORCH_ROOT"
|
|
179
|
+
--root "$ORCH_ROOT" \
|
|
180
|
+
--files "$PLAN_FILES" 2>&1) || {
|
|
158
181
|
echo "FATAL: worktree create failed for plan {plan_number}: $CREATE_JSON" >&2
|
|
159
182
|
exit 1
|
|
160
183
|
}
|
|
@@ -180,6 +203,8 @@ if [ "$EXEC_OK" != "true" ]; then
|
|
|
180
203
|
fi
|
|
181
204
|
```
|
|
182
205
|
|
|
206
|
+
`--files` carries the plan's declared `files_modified` (the same `PLAN_FILES` the per-plan worktree gate extracts) so this backend routes through the SAME advisory scope-conformance check the Claude worktree path uses at merge (#2596) — one validation, both backends. It is advisory and never blocks; omitting it just skips the check.
|
|
207
|
+
|
|
183
208
|
`worktree create` records the entry in `$WAVE_WORKTREE_MANIFEST` itself, so **do not** call `worktree.record-agent` for these plans — that verb is the harness-path counterpart, used because the harness creates the worktree behind GSD's back. Double-recording is deduped by path+branch, but the create verb is the single writer here.
|
|
184
209
|
|
|
185
210
|
Spawn `EXEC_JSON`'s `command` + `args` as a background process with its working directory set to `EXEC_JSON.cwd`. The `cwd` is returned for **every** host, including those whose descriptor has no cwd flag (`cwdFlag: null`) and therefore bind through the process's own working directory — always set it, never assume the flag did the job. Wait for all spawned executors in the wave before merging.
|
|
@@ -188,5 +213,5 @@ The executor never touches `STATE.md`/`ROADMAP.md`, and that guard needs no new
|
|
|
188
213
|
|
|
189
214
|
Merge-back, validation, and cleanup are the **existing** gauntlet, unchanged: the serialized `worktree.cleanup-wave` merge loop that stops the wave and retains the worktree on conflict, and manifest-only cleanup (never glob-inferred). Because the manifest shape is identical, the orchestrator path reuses it verbatim.
|
|
190
215
|
|
|
191
|
-
> **Declared-scope conformance (#2596):** ADR-1239 specifies that *both* isolation adapters route their merge through a check that each plan branch's committed diff stayed inside its declared `files_modified` scope. That check
|
|
216
|
+
> **Declared-scope conformance (#2596):** ADR-1239 specifies that *both* isolation adapters route their merge through a check that each plan branch's committed diff stayed inside its declared `files_modified` scope. That check now exists, advisory-first, and is wired into **both** paths: this one passes `--files "$PLAN_FILES"` to `worktree create` above, the harness path passes it to `worktree record-agent`, and `cleanup-wave` runs the one comparison for both. A path outside the declared scope is reported in the result's `warnings` array; it does not block the merge. Promotion to a hard gate is a separate, disclosed change.
|
|
192
217
|
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Per-plan executor routing (#1689)
|
|
2
|
+
|
|
3
|
+
Run for each plan, immediately before its `Agent()` dispatch in step 3. Sets
|
|
4
|
+
`EXECUTOR_TYPE` so a plan can opt into a specialist executor instead of the
|
|
5
|
+
default `gsd-executor`. `plan_json` (the current plan's object from
|
|
6
|
+
`phase-plan-index`, same scope step 2.5 uses) is in scope.
|
|
7
|
+
|
|
8
|
+
## Contract
|
|
9
|
+
|
|
10
|
+
- Default: `EXECUTOR_TYPE="gsd-executor"` — byte-identical to pre-#1689 dispatch.
|
|
11
|
+
- A plan opts into a specialist by declaring `agent_hint: <name>` in its PLAN.md
|
|
12
|
+
frontmatter. The field reaches the orchestrator as `plan_json.agent_hint`
|
|
13
|
+
(parsed by `phase-plan-index`; `null` when unset).
|
|
14
|
+
- When routing is enabled AND the hint is non-empty AND the named agent resolves
|
|
15
|
+
on the active runtime, `EXECUTOR_TYPE` becomes the hint. Otherwise it stays
|
|
16
|
+
`gsd-executor`.
|
|
17
|
+
- The resolved `EXECUTOR_TYPE` is used as `subagent_type` in BOTH worktree and
|
|
18
|
+
sequential dispatch (sequential reuses the worktree-mode `Agent()` template).
|
|
19
|
+
|
|
20
|
+
## Resolution
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
|
|
24
|
+
# Default-on; opt out with: gsd config-set workflow.agent_hint_routing false
|
|
25
|
+
AGENT_HINT_ROUTING=$(gsd_run query config-get workflow.agent_hint_routing --raw 2>/dev/null || echo "true")
|
|
26
|
+
|
|
27
|
+
EXECUTOR_TYPE="gsd-executor"
|
|
28
|
+
if [ "${AGENT_HINT_ROUTING:-true}" != "false" ]; then
|
|
29
|
+
PLAN_HINT=$(jq -r '.agent_hint // empty' <<<"$plan_json" 2>/dev/null | tr -d '"')
|
|
30
|
+
if [ -n "$PLAN_HINT" ]; then
|
|
31
|
+
EXECUTOR_TYPE=$(gsd_run query resolve-agent --name "$PLAN_HINT" --raw 2>/dev/null || echo "gsd-executor")
|
|
32
|
+
fi
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# #1689 v1 routes only the Agent()-based dispatch. On the orchestrator-worktree
|
|
36
|
+
# backend (process-spawn; no subagent_type) a resolved hint cannot be honored
|
|
37
|
+
# yet — surface it so a set hint is never silently ignored.
|
|
38
|
+
if [ "${ISOLATION:-}" = "orchestrator-worktree" ] && [ -n "${PLAN_HINT:-}" ]; then
|
|
39
|
+
echo "note: plan ${plan_id} agent_hint='${PLAN_HINT}' resolved, but orchestrator-worktree dispatch does not route subagent types in this release — using the default executor." >&2
|
|
40
|
+
fi
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`gsd_run query resolve-agent` consults the **active runtime's agent directory**
|
|
44
|
+
(both project-local and user-global, across runtime filename variants — `.md`,
|
|
45
|
+
`.agent.md`, `.toml`, the kimi `subagents/<name>.{yaml,md}` pair) and fails
|
|
46
|
+
closed to `gsd-executor` when the named agent does not resolve or on any error,
|
|
47
|
+
so a missing or misspelled hint never blocks dispatch.
|
|
48
|
+
|
|
49
|
+
## Scope
|
|
50
|
+
|
|
51
|
+
Routing applies to the `Agent()`-based dispatch (harness-worktree and sequential
|
|
52
|
+
modes). The `orchestrator-worktree` isolation backend spawns executors via a
|
|
53
|
+
separate process path that has no `subagent_type` and is not routed in this
|
|
54
|
+
release.
|
|
55
|
+
|
|
56
|
+
## Checkpoint gate rule (#3370)
|
|
57
|
+
|
|
58
|
+
Loaded with the routing resolution so the orchestrator reads it immediately
|
|
59
|
+
before composing each dispatch prompt, in every isolation mode.
|
|
60
|
+
|
|
61
|
+
On `checkpoint:human-verify` / `checkpoint:decision` tasks, `gate="blocking"`
|
|
62
|
+
(the default) is auto-approvable in auto-mode — that is the executor's own
|
|
63
|
+
`<checkpoint_protocol>` (`agents/gsd-executor.md`), and `checkpoints.md` (the
|
|
64
|
+
full gate table) is embedded in the dispatch `<execution_context>` verbatim.
|
|
65
|
+
Only `gate="blocking-human"` always surfaces to a human, regardless of
|
|
66
|
+
auto-mode. An unmet `<precondition>` checkpoint (executor step 0, `Blocked by:
|
|
67
|
+
Precondition not met` — unmet `user_setup` step, missing env var, absent
|
|
68
|
+
prior-phase artifact) reports `blocking-human` and therefore always surfaces
|
|
69
|
+
to a human, in every mode (#3210): the missing prerequisite is a fact only a
|
|
70
|
+
human can establish, not a verification step to rubber-stamp.
|
|
71
|
+
|
|
72
|
+
When composing the `Agent()` prompt, do NOT add text refusing or overriding
|
|
73
|
+
auto-approval for a `blocking` gate. Orchestrator-composed instructions that contradict the
|
|
74
|
+
executor's protocol win the executor's attention, stall autonomous runs at the
|
|
75
|
+
checkpoint, and defeat `_auto_chain_active`/auto-advance for the common case.
|
|
76
|
+
Executor-side gate semantics are already complete; compose nothing about gates
|
|
77
|
+
beyond what the template already embeds.
|
|
@@ -111,3 +111,5 @@ else
|
|
|
111
111
|
gsd_run query dispatch-isolation --raw --phase "${PHASE_NUMBER:-}" --plan "$plan_id" >/dev/null 2>&1 || true
|
|
112
112
|
fi
|
|
113
113
|
```
|
|
114
|
+
|
|
115
|
+
**`PLAN_FILES` is reused after dispatch (#2596):** pass it as `--files "$PLAN_FILES"` on the step-3 `worktree.record-agent` call (and on `worktree.create` in the orchestrator-worktree path) so the post-wave cleanup gauntlet can compare each plan branch's actual committed diff against the scope the plan declared, and report any path outside it. That check is advisory — it warns, it never blocks the merge — and omitting the flag simply skips it for that plan.
|
|
@@ -19,7 +19,7 @@ Orchestrator coordinates, not executes. Each subagent loads the full execute-pla
|
|
|
19
19
|
|
|
20
20
|
<runtime_compatibility>
|
|
21
21
|
**Subagent spawning is runtime-specific:**
|
|
22
|
-
- **Claude Code:** Uses `Agent(subagent_type="gsd-executor", ...)` —
|
|
22
|
+
- **Claude Code:** Uses `Agent(subagent_type="gsd-executor", ...)` — backgrounded by default; verify completion
|
|
23
23
|
- **Copilot:** Subagent spawning does not reliably return completion signals. **Default to
|
|
24
24
|
sequential inline execution**: read and follow execute-plan.md directly for each plan
|
|
25
25
|
instead of spawning parallel agents. Only attempt parallel spawning if the user
|
|
@@ -91,7 +91,7 @@ Parse JSON for: `executor_model`, `verifier_model`, `commit_docs`, `parallelizat
|
|
|
91
91
|
|
|
92
92
|
`section_manifest` (#2932) gates the three `steps/*.md` reads below: read a step file only when its `id` is in `section_manifest.included` (equivalently, its path is in `section_manifest.read`); skip it — without reading — when its `id` is in `section_manifest.excluded`. When `section_manifest` is `null` (degraded: manifest artifact missing/unreadable), read all three unconditionally — the safe superset.
|
|
93
93
|
|
|
94
|
-
**Model resolution:** If `executor_model` is `"inherit"`, omit the `model=` parameter from all `Agent()` calls — do NOT pass `model="inherit"` to Agent. Omitting the `model=` parameter causes Claude Code to inherit the
|
|
94
|
+
**Model resolution:** If `executor_model` is `"inherit"`, omit the `model=` parameter from all `Agent()` calls — do NOT pass `model="inherit"` to Agent. Omitting the `model=` parameter causes Claude Code to inherit the orchestrator model automatically. Only set `model=` when `executor_model` is an explicit model name (e.g., `"claude-sonnet-5"`, `"claude-opus-4-8"`).
|
|
95
95
|
|
|
96
96
|
@~/.claude/gsd-core/references/execute-phase-response-language.md
|
|
97
97
|
|
|
@@ -653,9 +653,9 @@ increases monotonically across waves. `{status}` is `complete` (success),
|
|
|
653
653
|
|
|
654
654
|
`[checkpoint] phase {PHASE_NUMBER} wave {N}/{M} plan {plan_id} starting ({P}/{Q} plans done)`
|
|
655
655
|
|
|
656
|
-
Pass paths only — executors read files themselves
|
|
657
|
-
|
|
658
|
-
|
|
656
|
+
Pass paths only — executors read files themselves.
|
|
657
|
+
|
|
658
|
+
**Executor routing (#1689/#3370).** Per plan, run `gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md` to set `EXECUTOR_TYPE` for `subagent_type="{EXECUTOR_TYPE}"` below.
|
|
659
659
|
|
|
660
660
|
**Worktree mode** (`USE_WORKTREES` and `USE_WORKTREES_FOR_PLAN` not `false`):
|
|
661
661
|
|
|
@@ -690,8 +690,8 @@ increases monotonically across waves. `{status}` is `complete` (success),
|
|
|
690
690
|
|
|
691
691
|
```text
|
|
692
692
|
Agent(
|
|
693
|
-
|
|
694
|
-
|
|
693
|
+
subagent_type="{EXECUTOR_TYPE}",
|
|
694
|
+
description="Execute plan {plan_number} of phase {phase_number}",
|
|
695
695
|
# Only include model= when executor_model is an explicit model name.
|
|
696
696
|
# When executor_model is "inherit", omit this parameter entirely so
|
|
697
697
|
# Claude Code inherits the orchestrator model automatically.
|
|
@@ -709,7 +709,7 @@ increases monotonically across waves. `{status}` is `complete` (success),
|
|
|
709
709
|
|
|
710
710
|
<worktree_branch_check>
|
|
711
711
|
ORCHESTRATOR build-time embed (NOT a sub-agent runtime step): before this dispatch, read `gsd-core/references/worktree-branch-check.md`, substitute `{EXPECTED_BASE}` with the base SHA captured above ({EXPECTED_BASE}), and replace this note with that fragment's `<worktree_branch_check>` block so the dispatched prompt carries the runnable guard verbatim — do not pass this instruction through in its place.
|
|
712
|
-
Per-commit HEAD/cwd-drift/path-guard: `agents/gsd-executor.md` steps 0/0a/0b + `references/worktree-path-safety.md` (in <execution_context>).
|
|
712
|
+
Per-commit HEAD/cwd-drift/path-guard: `agents/gsd-executor.md` steps 0/0a/0b + `gsd-core/references/worktree-path-safety.md` (in <execution_context>).
|
|
713
713
|
</worktree_branch_check>
|
|
714
714
|
|
|
715
715
|
<parallel_execution>
|
|
@@ -733,15 +733,16 @@ increases monotonically across waves. `{status}` is `complete` (success),
|
|
|
733
733
|
</parallel_execution>
|
|
734
734
|
|
|
735
735
|
<execution_context>
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
736
|
+
ORCHESTRATOR build-time embed (NOT a sub-agent runtime step): before this dispatch, read each file listed below and replace this note with those files' contents, inlined verbatim in this block in the listed order. Never leave `@`-include lines in the dispatched prompt — `@path` never expands inside an Agent() `prompt="..."` string (#3324), so an include arrives as literal text the executor never sees.
|
|
737
|
+
- `~/.claude/gsd-core/workflows/execute-plan.md`
|
|
738
|
+
- `~/.claude/gsd-core/templates/summary.md`
|
|
739
|
+
- `~/.claude/gsd-core/references/checkpoints.md`
|
|
740
|
+
- `~/.claude/gsd-core/references/tdd.md`
|
|
741
|
+
- `~/.claude/gsd-core/references/worktree-path-safety.md`
|
|
742
|
+
${CONTEXT_WINDOW < 200000 ? '' : '- `~/.claude/gsd-core/references/executor-examples.md`'}
|
|
742
743
|
</execution_context>
|
|
743
744
|
|
|
744
|
-
<
|
|
745
|
+
<required_reading>
|
|
745
746
|
Read these files at execution start using the Read tool.
|
|
746
747
|
First resolve repo root so every path is anchored:
|
|
747
748
|
\`PROJECT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)\`
|
|
@@ -756,7 +757,7 @@ increases monotonically across waves. `{status}` is `complete` (success),
|
|
|
756
757
|
` : ''}
|
|
757
758
|
- ${PROJECT_ROOT}/CLAUDE.md (Project instructions, if exists — follow project-specific guidelines and coding conventions)
|
|
758
759
|
- ${PROJECT_ROOT}/.claude/skills/ or ${PROJECT_ROOT}/.agents/skills/ (Project skills, if either exists — list skills, read SKILL.md for each, follow relevant rules during implementation)
|
|
759
|
-
</
|
|
760
|
+
</required_reading>
|
|
760
761
|
|
|
761
762
|
${AGENT_SKILLS}
|
|
762
763
|
|
|
@@ -777,7 +778,7 @@ increases monotonically across waves. `{status}` is `complete` (success),
|
|
|
777
778
|
)
|
|
778
779
|
```
|
|
779
780
|
|
|
780
|
-
After each `Agent()` returns, parse executor-returned worktree metadata (`<worktree_metadata>`) before harness metadata, then record the `{agent_id, worktree_path, branch, expected_base}` entry with `gsd_run query worktree.record-agent --manifest "$WAVE_WORKTREE_MANIFEST" --agent-id … --path … --branch … --base
|
|
781
|
+
After each `Agent()` returns, parse executor-returned worktree metadata (`<worktree_metadata>`) before harness metadata, then record the `{agent_id, worktree_path, branch, expected_base}` entry with `gsd_run query worktree.record-agent --manifest "$WAVE_WORKTREE_MANIFEST" --agent-id … --path … --branch … --base … --files "$PLAN_FILES"`. The verb validates every field at write time using the `cleanup-wave` reader's own rules (write-strict `--agent-id`), failing loudly with a recovery hint rather than appending an under-populated entry the reader would later drop silently. On a non-zero exit or any missing field: stop and ask for recovery instead of scanning worktrees.
|
|
781
782
|
|
|
782
783
|
> **Worktree recovery policy (#48 + #1292):** See `execute-phase/steps/worktree-recovery-policy.md` — FAIL-CLOSED rule for base/HEAD-namespace mismatches AND isolated-run fail-safe recovery.
|
|
783
784
|
|
|
@@ -852,8 +853,8 @@ increases monotonically across waves. `{status}` is `complete` (success),
|
|
|
852
853
|
|
|
853
854
|
If the stalled executor ran in an isolated worktree, `kill and switch to inline execution` edits the primary checkout — see worktree recovery policy (`execute-phase/steps/worktree-recovery-policy.md`). Prefer `kill and retry` in a fresh worktree; inline execution requires explicit confirmation, never the default.
|
|
854
855
|
|
|
855
|
-
**This fallback applies
|
|
856
|
-
|
|
856
|
+
**This fallback applies to all runtimes.** Claude Code's Agent() backgrounds by
|
|
857
|
+
default: the completion signal may never arrive. Verify, never wait.
|
|
857
858
|
|
|
858
859
|
5. **Post-wave hook validation (parallel mode only):** Hooks run on every executor commit by default (#2924); this post-wave run only fires when `workflow.worktree_skip_hooks=true` opted out of per-commit hooks:
|
|
859
860
|
```bash
|
|
@@ -1013,7 +1014,9 @@ increases monotonically across waves. `{status}` is `complete` (success),
|
|
|
1013
1014
|
|
|
1014
1015
|
**If `activeHooks` is empty or absent:** Skip silently to step 5.8.
|
|
1015
1016
|
|
|
1016
|
-
**
|
|
1017
|
+
⚠ **Validate `check` before shell use** (third-party manifest input) — `loop-hook-dispatch.md` § `gate`.
|
|
1018
|
+
|
|
1019
|
+
**For each active entry where `kind == "gate"`** (process in array order), run the gate check — a `predicate` gate (ADR-2008 / #2008) substitutes `gsd_run check predicate --predicate '<predicate JSON>' --phase-number "${PHASE_NUMBER}" --raw`:
|
|
1017
1020
|
|
|
1018
1021
|
```bash
|
|
1019
1022
|
GATE_RESULT=$(gsd_run check ${hook.check.query} "${PHASE_NUMBER}" --raw)
|
|
@@ -1132,7 +1135,7 @@ Plans with `autonomous: false` require user interaction.
|
|
|
1132
1135
|
**Auto-mode checkpoint handling:**
|
|
1133
1136
|
Read auto-advance config (chain flag OR user preference — same boolean as `check.auto-mode`):
|
|
1134
1137
|
```bash
|
|
1135
|
-
AUTO_MODE=$(gsd_run query check auto-mode --pick active 2>/dev/null
|
|
1138
|
+
AUTO_MODE=$(gsd_run query check auto-mode --pick active 2>/dev/null)
|
|
1136
1139
|
```
|
|
1137
1140
|
|
|
1138
1141
|
When executor returns a checkpoint AND `AUTO_MODE` is `true`:
|
|
@@ -1140,7 +1143,7 @@ When executor returns a checkpoint AND `AUTO_MODE` is `true`:
|
|
|
1140
1143
|
- **decision** → Auto-spawn continuation agent with `{user_response}` = first option from checkpoint details. Log `⚡ Auto-selected: [option]`. **Except `blocking-human`.**
|
|
1141
1144
|
- **human-action** → Present to user (existing behavior below). Auth gates cannot be automated.
|
|
1142
1145
|
|
|
1143
|
-
**Carve-out — overrides all branches above.** If the returned `Gate:` is `blocking-human
|
|
1146
|
+
**Carve-out — overrides all branches above.** If the returned `Gate:` is `blocking-human` (precondition-unmet, #3210), or its `<what-built>` mentions `Package verification required before install` or `Package install failed — human verification required`, never auto-approve or auto-select. Present to user (standard flow). Log `⛔ blocking-human gate — auto-mode suspended`.
|
|
1144
1147
|
|
|
1145
1148
|
**Standard flow (not auto-mode, human-action, or blocking-human):**
|
|
1146
1149
|
|
|
@@ -1229,7 +1232,7 @@ If `section_manifest` is `null` or `"partial-wave"` is in its `included` list: r
|
|
|
1229
1232
|
EXECUTE_POST_HOOKS_JSON=${EXECUTE_POST_HOOKS_JSON:-$(gsd_run loop render-hooks execute:post --raw)}
|
|
1230
1233
|
```
|
|
1231
1234
|
|
|
1232
|
-
|
|
1235
|
+
Dispatch `kind == "step"` hooks per @gsd-core/references/loop-hook-dispatch.md. `ref.skill == "code-review"`:
|
|
1233
1236
|
|
|
1234
1237
|
If no active code-review step hook exists: display "Code review skipped (code-review capability inactive)" and proceed to gate dispatch.
|
|
1235
1238
|
|
|
@@ -1253,14 +1256,14 @@ Code review found issues. Consider running:
|
|
|
1253
1256
|
|
|
1254
1257
|
**Error handling:** If the Skill invocation fails or throws, catch the error, display "Code review encountered an error (non-blocking): {error}" and proceed to gate dispatch. Review failures must never block execution.
|
|
1255
1258
|
|
|
1256
|
-
**Execute:post gate hook dispatch.** After code review, dispatch all active gate hooks from `EXECUTE_POST_HOOKS_JSON` where `kind == "gate"`. For each, run
|
|
1259
|
+
**Execute:post gate hook dispatch.** After code review, dispatch all active gate hooks from `EXECUTE_POST_HOOKS_JSON` where `kind == "gate"`. ⚠ **Validate `check` before shell use** (third-party manifest input) — `loop-hook-dispatch.md` § `gate`. For each, run the form below, or — for a `predicate` gate (ADR-2008 / #2008) — `gsd_run check predicate --predicate '<predicate JSON>' --phase-number "${PHASE_NUMBER}" --raw`:
|
|
1257
1260
|
|
|
1258
1261
|
```bash
|
|
1259
1262
|
GATE_RESULT=$(gsd_run check ${hook.check.query} "${PHASE_NUMBER}" --raw)
|
|
1260
1263
|
CHECK_EXIT=$?
|
|
1261
1264
|
```
|
|
1262
1265
|
|
|
1263
|
-
**Gate evaluation** uses the same two-step contract as `execute:wave:post` above
|
|
1266
|
+
**Gate evaluation** uses the same two-step contract as `execute:wave:post` above.
|
|
1264
1267
|
|
|
1265
1268
|
**TDD review escalation (overrides the advisory default for the `tdd.review-checkpoint` gate only).** The tdd `execute:post` gate is declared `blocking: false`, so by the generic contract above it displays its `message`/table and continues. There is ONE documented exception (see `~/.claude/gsd-core/references/execute-mvp-tdd.md`): when `MVP_MODE=true` AND `TDD_MODE=true` AND `GATE_RESULT.block == true` (one or more TDD plans miss a RED or GREEN gate commit), the end-of-phase TDD review escalates from advisory to **blocking under MVP+TDD** — refuse to mark the phase complete and present:
|
|
1266
1269
|
|
|
@@ -1300,7 +1303,7 @@ Check must_haves against actual codebase.
|
|
|
1300
1303
|
Cross-reference requirement IDs from PLAN frontmatter against REQUIREMENTS.md — every ID MUST be accounted for.
|
|
1301
1304
|
Create VERIFICATION.md.
|
|
1302
1305
|
|
|
1303
|
-
<
|
|
1306
|
+
<required_reading>
|
|
1304
1307
|
Read these files before verification:
|
|
1305
1308
|
- {phase_dir}/*-PLAN.md (All plans — understand intent, check must_haves)
|
|
1306
1309
|
- {phase_dir}/*-SUMMARY.md (All summaries — cross-reference claimed vs actual)
|
|
@@ -1309,7 +1312,7 @@ ${CONTEXT_WINDOW >= 500000 ? `- {phase_dir}/*-CONTEXT.md (User decisions — ver
|
|
|
1309
1312
|
- {phase_dir}/*-RESEARCH.md (Known pitfalls — check for traps)
|
|
1310
1313
|
- Prior VERIFICATION.md files from earlier phases (regression check)
|
|
1311
1314
|
` : ''}
|
|
1312
|
-
</
|
|
1315
|
+
</required_reading>
|
|
1313
1316
|
|
|
1314
1317
|
${VERIFIER_SKILLS}",
|
|
1315
1318
|
subagent_type="gsd-verifier",
|
|
@@ -1519,30 +1522,15 @@ fi
|
|
|
1519
1522
|
**No matches:** skip silently (always additive, non-blocking).
|
|
1520
1523
|
</step>
|
|
1521
1524
|
|
|
1522
|
-
<step name="
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
2. If the file exists and has a `## Validated Requirements` or `## Requirements` section:
|
|
1530
|
-
- Move any requirements validated by this phase from Active → Validated
|
|
1531
|
-
- Add a brief note: `Validated in Phase {X}: {Name}`
|
|
1532
|
-
3. If the file has a `## Current State` or similar section:
|
|
1533
|
-
- Update it to reflect this phase's completion (e.g., "Phase {X} complete — {one-liner}")
|
|
1534
|
-
4. Update the `Last updated:` footer to today's date
|
|
1535
|
-
5. Commit the change:
|
|
1536
|
-
|
|
1537
|
-
```bash
|
|
1538
|
-
gsd_run query commit "docs(phase-{X}): evolve PROJECT.md after phase completion" --files .planning/PROJECT.md
|
|
1539
|
-
```
|
|
1540
|
-
|
|
1541
|
-
**Skip this step if** `.planning/PROJECT.md` does not exist.
|
|
1542
|
-
</step>
|
|
1525
|
+
<step name="delegate_post_completion_to_transition">
|
|
1526
|
+
**#1526 — Delegate post-completion to the transition workflow** (parity: the auto-chain
|
|
1527
|
+
path must run the SAME post-processing as a normal transition). `phase.complete`
|
|
1528
|
+
(`update_roadmap` above) and verification (`verify_phase_goal`) already ran, so invoke
|
|
1529
|
+
transition in **post-completion mode**: SKIP its `verify_completion` and
|
|
1530
|
+
`update_roadmap_and_state` (re-running `phase.complete` would double-write state) and
|
|
1531
|
+
BEGIN at `evolve_project`, running the full set through `offer_next_phase`.
|
|
1543
1532
|
|
|
1544
|
-
|
|
1545
|
-
@~/.claude/gsd-core/references/offer-next.md
|
|
1533
|
+
@~/.claude/gsd-core/workflows/transition.md
|
|
1546
1534
|
</step>
|
|
1547
1535
|
|
|
1548
1536
|
</process>
|