enhance(#3777): opt-in concurrent per-plan planners in chunked mode (#4346)

* test(#3777): add failing-first coverage for concurrent per-plan planner dispatch

Extracts and executes the real bash blocks this PR is about to add to
plan-phase.md and chunked-planning-mode.md (CHUNKED_PARALLEL resolution and
the BATCH_PLAN_IDS dedup guard), plus config-set/config-get coverage for the
new planning.chunked_parallel key. Expected RED against the current shipped
workflow text — the extraction anchors do not exist yet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(#3777): dispatch chunked mode's per-plan planners concurrently within a Wave

Adds opt-in planning.chunked_parallel (default false, byte-identical to the
existing serial loop). When true and the runtime's negotiated dispatch
capacity (dispatch-capacity, #3673) is greater than 1, chunked planning's
per-plan Tasks that share one outline Wave are issued together instead of
one at a time; a later Wave still waits for the current one to be verified
on disk and committed. A host with no declared maxConcurrency (most
non-Claude runtimes today) stays serial regardless of the setting.

Resolution and the Plan-ID dedup guard live in chunked-planning-mode.md
itself (gated on the section's own CHUNKED_MODE skip-check) rather than in
plan-phase.md, so a non-chunked run pays no extra gsd_run calls.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* test(#3777): repoint extraction at chunked-planning-mode.md after the move

CHUNKED_PARALLEL resolution moved out of plan-phase.md into
chunked-planning-mode.md itself (see the preceding commit); update the
test's extraction path and header comment to match.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(#3777): relocate the canonical runtime-launcher preamble before its first use

The CHUNKED_PARALLEL resolution block's two gsd_run calls landed earlier in
the file than the sole existing preamble (in the commit step), which
tests/runtime-launcher-parity.test.cjs's (B) check requires to precede every
gsd_run call in the file. Move the preamble (not duplicate it) to the top of
the resolution block; the commit step's fenced block now just calls
gsd_run directly.

Caught by the GREEN checkpoint gsd-test run before push.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(#3777): strip the canonical preamble from the extracted resolution block

The CHUNKED_PARALLEL resolution fence now carries the relocated
runtime-launcher preamble as its first line (previous commit). Extracting
the whole fence and running it after the test's own gsd_run stub let the
embedded preamble's own resolver logic `unset -f gsd_run` and exit 1 before
reaching the resolution logic, since no real gsd-tools.cjs exists in the
temp script dir — every test calling runChunkedParallelResolution() failed.

Strip the preamble (sourced from gsd-core/workflows/_runtime-launcher.snippet.sh,
the same file scripts/sync-runtime-launcher.cjs treats as canonical) before
splicing in the stub, so this suite tests only the resolution logic it is
actually about.

Caught by the post-rebase gsd-test run before push.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(#3777): add the How-To page the phase gate requires

Enablement is 2 commands (config-set, then --chunked), which this repo's
own doc-quadrant gate flags as how-to-owed: a reference table cannot carry
a sequence. Covers enablement, the dispatch-capacity gate's honest
"most runtimes today: no effect" case, and the two accepted trade-offs.

An earlier reasoning pass (recorded in .gsd/phase/.../70-docs.json before
this commit) had incorrectly claimed #3034 shipped with no equivalent
how-to page, as precedent for skipping one here. That claim was false —
docs/how-to/enable-parallel-reviewer-lanes.md exists and is indexed. The
phase gate caught the omission before merge; corrected here.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(#3777): backfill changeset PR number

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

---------

Co-authored-by: sim <sim@local>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-09-05 18:57:17 -04:00
committed by GitHub
parent 1db726ebbf
commit f9f72cb54c
9 changed files with 573 additions and 16 deletions

View File

@@ -0,0 +1,80 @@
# How to enable concurrent per-plan planners in chunked mode
Speed up a multi-plan phase's chunked planning run by letting independent per-plan Tasks run at
the same time instead of one after another.
---
## Before you start
This only matters if you already use chunked mode (`workflow.plan_chunked: true`, or
`/gsd-plan-phase {N} --chunked`). Chunked mode splits planning into a short outline Task followed
by one short Task per plan, committing each plan individually so an interrupted run resumes from
the last committed plan. By default those per-plan Tasks still run one at a time.
## Enable it
```bash
gsd config-set planning.chunked_parallel true
```
```json
{
"planning": {
"chunked_parallel": true
}
}
```
Then run chunked planning as usual:
```bash
/gsd-plan-phase {N} --chunked
```
That's it — no other setting to touch, and no other capability's config is involved.
## What actually changes
Nothing changes for a phase whose outline has only one plan per Wave — there is nothing to run
concurrently. For a phase with several plans in the same Wave, those plans' Tasks are now issued
together instead of one at a time; a later Wave still waits for the current one to finish and
commit before starting, so cross-Wave ordering is unaffected.
## Whether it actually does anything on your runtime
This setting is gated on the runtime's own negotiated concurrency ceiling
(`gsd-tools query dispatch-capacity`), not on the config value alone:
- **Claude Code** declares a capacity above 1, so turning this on has a real effect there.
- **Every other runtime today** (Codex, Cursor, OpenCode, ...) declares no concurrency ceiling and
falls back to the safe floor of `1` — turning this setting on has no effect there; chunked
planning stays exactly as serial as it was before. This is not a bug to work around: it means
the setting never fires concurrent dispatch on a host that cannot usefully run it.
There is no per-runtime flag to set yourself — the gate is automatic and always correct for the
runtime you're on.
## Trade-offs to know before turning this on
- **Per-plan commits interleave.** With serial dispatch, plans commit strictly in outline order.
With concurrent dispatch, whichever plans in a batch finish first commit first — still one
commit per plan, never a combined commit, but not necessarily in outline order within a batch.
- **Crash-resume granularity is coarser.** If a run is interrupted mid-batch, every plan that
already finished and committed stays committed — but "already finished" is no longer
necessarily "everything up to the last plan in outline order," the way serial mode guarantees.
Resuming the run picks up exactly where it left off either way; only the *shape* of what's
already on disk when you resume can differ.
If either of those matters more to you than the speed-up, leave this setting at its default
(`false`) — chunked mode's crash resilience story is otherwise unchanged.
## Turn it off again
```bash
gsd config-set planning.chunked_parallel false
```
Or just remove the key from `.planning/config.json` — `false` is the default.
See also: [Configuration reference — Concurrent per-plan planners in chunked mode](../CONFIGURATION.md#concurrent-per-plan-planners-in-chunked-mode-3777).