feat(capabilities): add claude-orchestration capability (Workflow backend) (#1143)
Default-off, BETA, claude-only capability adopting Claude Code's Workflow tool (/effort ultracode, Agent SDK >= v0.3.149) as an optional parallel-execution backend for the GSD loop. Restores the wave parallelism + plan-checker + verifier that #853 forces inline on Claude Code, and folds gsd-ultraplan-phase under one runtime gate. - Pure fail-closed core (src/claude-orchestration.cts): detectWorkflowBackend (gate ladder: enabled -> Claude -> backend != inline -> nested+background host -> valid Agent SDK -> SDK >= floor; every miss degrades to inline) and emitWorkflowScript (waves -> parallel() barriers, plans -> gsd-executor + worktree, files_modified overlap -> separate stages, resumeFromRunId, budget). All interpolated identifiers validated script-safe; briefs JSON-quoted. - claude-orchestration command family (gsd-tools claude-orchestration detect-backend|emit-workflow) for orchestrator invocation. - Two gated loop contributions at wired points (execute:wave:post, plan:post); federated config keys (enabled/execution_backend/min_agent_sdk_version). - ADR-1143 implementation amendment; CONTEXT.md glossary entry; explanation doc. On any runtime lacking the Workflow tool, behaviour is byte-identical to today. closes #1143
This commit is contained in:
85
capabilities/claude-orchestration/capability.json
Normal file
85
capabilities/claude-orchestration/capability.json
Normal file
@@ -0,0 +1,85 @@
|
||||
{
|
||||
"id": "claude-orchestration",
|
||||
"role": "feature",
|
||||
"version": "1.7.0-rc.3",
|
||||
"title": "Claude orchestration (Workflow backend)",
|
||||
"description": "Default-off, BETA, claude-only capability that adopts Claude Code's Workflow tool (the engine behind /effort ultracode) as an optional parallel-execution backend for the GSD loop. When the runtime exposes the Workflow tool and claude_orchestration.execution_backend resolves to 'workflow', execute-phase emits a generated Workflow script (waves -> parallel() barriers, plans -> agent({ agentType: 'gsd-executor', isolation: 'worktree' }), files_modified overlap -> separate sequential stages, resumeFromRunId wired to the phase run id, shared token budget) that composes the SAME gsd-executor agent and worktree isolation the inline path uses, restoring the parallelism + plan-checker + verifier that the #853 backgrounded-agent nesting limitation forces inline on Claude Code. Also folds the ultraplan plan-offload under one runtime gate (plan:* surface). On any runtime lacking the Workflow tool, or when the capability is disabled, behaviour is byte-identical to today (inline/manual dispatch). Detection + emission live in gsd-core/bin/lib/claude-orchestration.cjs (pure, fail-closed). Mirrors the existing gsd-ultraplan-phase BETA-isolation posture.",
|
||||
"tier": "full",
|
||||
"requires": [],
|
||||
"engines": {
|
||||
"gsd": ">=1.7.0"
|
||||
},
|
||||
"runtimeCompat": {
|
||||
"supported": [
|
||||
"claude"
|
||||
],
|
||||
"unsupported": []
|
||||
},
|
||||
"skills": [],
|
||||
"agents": [],
|
||||
"hooks": [],
|
||||
"commands": [
|
||||
{
|
||||
"family": "claude-orchestration",
|
||||
"module": "claude-orchestration-command-router.cjs",
|
||||
"router": "routeClaudeOrchestrationCommand",
|
||||
"subcommands": [
|
||||
"detect-backend",
|
||||
"emit-workflow"
|
||||
]
|
||||
}
|
||||
],
|
||||
"activationKey": "claude_orchestration.enabled",
|
||||
"config": {
|
||||
"claude_orchestration.enabled": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Master toggle for the Claude orchestration capability. Default-off + BETA: the Workflow-tool execution backend and the ultraplan plan-offload surface are inert unless this is true. When false, loop behaviour is byte-identical to a non-Claude runtime (inline/manual dispatch)."
|
||||
},
|
||||
"claude_orchestration.execution_backend": {
|
||||
"type": "enum",
|
||||
"values": [
|
||||
"auto",
|
||||
"workflow",
|
||||
"inline"
|
||||
],
|
||||
"default": "auto",
|
||||
"description": "Which execute-phase dispatch backend to use when the capability is enabled. 'auto' (default) activates the Workflow backend only when the runtime is Claude AND the Workflow tool is detected AND the Agent SDK meets claude_orchestration.min_agent_sdk_version; otherwise it falls back to inline. 'workflow' forces the Workflow backend when the tool is present AND the Agent SDK meets the floor (still fails closed to inline if the tool is absent or the SDK is too old — the floor applies in both modes). 'inline' forces today's manual one-agent-per-message dispatch regardless of tool availability."
|
||||
},
|
||||
"claude_orchestration.min_agent_sdk_version": {
|
||||
"type": "string",
|
||||
"default": "0.3.149",
|
||||
"description": "Minimum Agent SDK version required to activate the Workflow backend under execution_backend='auto'. Defaults to 0.3.149 (the release that introduced the Workflow tool). Raise to pin a higher floor; the detection seam fails closed to inline for any runtime reporting an older or unknown version."
|
||||
}
|
||||
},
|
||||
"steps": [],
|
||||
"contributions": [
|
||||
{
|
||||
"point": "execute:wave:post",
|
||||
"into": "executor",
|
||||
"fragment": {
|
||||
"path": "fragments/execute-wave-post.md"
|
||||
},
|
||||
"produces": [],
|
||||
"consumes": [
|
||||
"PLAN.md"
|
||||
],
|
||||
"when": "claude_orchestration.enabled",
|
||||
"onError": "skip"
|
||||
},
|
||||
{
|
||||
"point": "plan:post",
|
||||
"into": "planner",
|
||||
"fragment": {
|
||||
"path": "fragments/plan-post.md"
|
||||
},
|
||||
"produces": [],
|
||||
"consumes": [
|
||||
"CONTEXT.md"
|
||||
],
|
||||
"when": "claude_orchestration.enabled",
|
||||
"onError": "skip"
|
||||
}
|
||||
],
|
||||
"gates": []
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
# Claude orchestration — Workflow execution backend (BETA)
|
||||
|
||||
> Injected at `execute:wave:post` `into: executor` only when
|
||||
> `claude_orchestration.enabled` is 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:
|
||||
|
||||
1. `claude_orchestration.enabled` is `true` in `.planning/config.json`, AND
|
||||
2. the active runtime is **Claude Code** (the Workflow tool is Claude / Agent
|
||||
SDK-specific), AND
|
||||
3. `claude_orchestration.execution_backend` resolves to `workflow` — either
|
||||
explicitly, or via `auto` — **and** the Agent SDK version is
|
||||
`>= claude_orchestration.min_agent_sdk_version` (default `0.3.149`). The SDK
|
||||
floor applies in both `auto` and `workflow` modes (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 → `parallel()` barriers** — each wave is one barrier; the next wave
|
||||
waits for the previous to complete.
|
||||
- **plans → `agent(brief, { agentType: 'gsd-executor', isolation: 'worktree' })`**
|
||||
— the SAME executor agent and worktree isolation the inline path uses, so the
|
||||
produced `SUMMARY.md` and commits are identical.
|
||||
- **`files_modified` overlap → 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 a `budgetTokens` value to `emitWorkflowScript` (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. Use `gsd-tools claude-orchestration detect-backend` to resolve whether
|
||||
the Workflow backend should activate for the current runtime.
|
||||
|
||||
## 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.
|
||||
28
capabilities/claude-orchestration/fragments/plan-post.md
Normal file
28
capabilities/claude-orchestration/fragments/plan-post.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Claude orchestration — ultraplan plan-offload ownership (BETA)
|
||||
|
||||
> Injected at `plan:post` `into: planner` only when
|
||||
> `claude_orchestration.enabled` is true. Default-off; `onError: skip`.
|
||||
|
||||
## Ownership declaration
|
||||
|
||||
The `gsd-ultraplan-phase` plan-offload surface (offloading GSD's plan phase to
|
||||
Claude Code's ultraplan cloud) is **owned by this capability**, not by a
|
||||
standalone BETA skill. Both surfaces share one runtime gate
|
||||
(`claude_orchestration.enabled`), one BETA boundary, and one Claude-Code-only
|
||||
detection seam.
|
||||
|
||||
## When the planner should consider ultraplan offload
|
||||
|
||||
When this contribution is active (capability enabled, Claude Code runtime), the
|
||||
planner MAY offer the `/gsd-ultraplan-phase` path as an alternative to local
|
||||
`/gsd-plan-phase` for phases where cloud-assisted planning adds value. This is
|
||||
advisory, not mandatory — the stable local planner remains the default.
|
||||
|
||||
## Fallback contract
|
||||
|
||||
If the capability is disabled, or the runtime is not Claude Code, ultraplan
|
||||
offload is **not surfaced** and the planner proceeds with the standard local
|
||||
`/gsd-plan-phase`. The `gsd-ultraplan-phase` command itself remains installed
|
||||
(its own runtime gate already no-ops on non-Claude runtimes); this contribution
|
||||
only governs whether the capability manifest advertises it as part of the
|
||||
orchestration surface.
|
||||
Reference in New Issue
Block a user