- compareSemver: implement full SemVer 2.0.0 §11 pre-release identifier comparison (two pre-releases of the same triple now order correctly; was 0). - capability description + fragment: scope the plan-checker/verifier claim (this capability delivers the parallel-execution backend; those gates remain inline until separately wired). Correct the 'each wave is one barrier' prose (a wave splits into multiple sequential parallel() barriers on files_modified overlap). Frame detect-backend CLI as a simulation harness; the pure function with the live host descriptor is the real detection seam. - partitionStages docstring: 'near-minimal via greedy first-fit' (not 'fewest'); document empty-files_modified behavior.
3.6 KiB
Claude orchestration — Workflow execution backend (BETA)
Injected at
execute:wave:postinto: executoronly whenclaude_orchestration.enabledis true. Default-off;onError: skip.
When this contribution is active
The Claude orchestration capability is default-off and BETA. It activates only when ALL of the following hold:
claude_orchestration.enabledistruein.planning/config.json, AND- the active runtime is Claude Code (the Workflow tool is Claude / Agent SDK-specific), AND
claude_orchestration.execution_backendresolves toworkflow— either explicitly, or viaauto— and the Agent SDK version is>= claude_orchestration.min_agent_sdk_version(default0.3.149). The SDK floor applies in bothautoandworkflowmodes (fail-closed: a pre-release or older SDK never activates the preview backend).
Detection is fail-closed: any miss degrades to inline, manual, one-agent-per- message dispatch — exactly today's behaviour. On a non-Claude runtime this contribution is a no-op.
What the executor does when the Workflow backend is active
Instead of the orchestrator fanning out one Agent(subagent_type=gsd-executor, isolation=worktree, run_in_background=true) per message (which on Claude Code
cannot nest further subagents — #853 — and so degrades to sequential inline
execution), execute-phase emits a generated Workflow script and lets the main
loop orchestrate it:
- waves → one or more sequential
parallel()barriers — each wave is a barrier group; when plans within a wave sharefiles_modified, they are split into separate sequential stages within that wave's barrier (the next wave still waits for the previous wave to complete). - plans →
agent(brief, { agentType: 'gsd-executor', isolation: 'worktree' })— the SAME executor agent and worktree isolation the inline path uses, so the producedSUMMARY.mdand commits are identical. files_modifiedoverlap → separate sequential stages — two plans that touch the same file are placed in different stages within the wave (the same overlap rule execute-phase already applies inline).resumeFromRunId— wired to the phase run id, so an interrupted phase resumes without re-running completed plans.budget(tokens)— a shared token pool across the whole phase when the orchestrator passes abudgetTokensvalue toemitWorkflowScript(it is a function parameter, not a config key; the orchestrator decides the budget).
The emitter is a pure function exposed through the capability command surface:
gsd-tools claude-orchestration emit-workflow --waves <manifest.json> --run-id <id> [--phase-dir <dir>] [--budget <n>] (or require('gsd-core/bin/lib/claude-orchestration.cjs').emitWorkflowScript
directly). It maps the phase's wave/plan manifest to the Workflow script string
and never invokes the Workflow tool itself; the orchestrator runs the emitted
script. Detection is resolved by the orchestrator calling the pure
detectWorkflowBackend with the LIVE host descriptor (the CLI
gsd-tools claude-orchestration detect-backend is a simulation harness that
assumes a capable host unless --no-nested-dispatch is passed — it does not probe
the real runtime; the orchestrator supplies the real descriptor).
Fallback contract
If detection resolves to inline (tool absent, SDK too old, runtime not Claude,
or the capability disabled), execute-phase MUST proceed with the standard inline
wave dispatch. The executor MUST NOT assume parallelism, a shared budget, or
resume-from-run-id semantics in that mode.