* 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:
@@ -527,7 +527,7 @@ All workflow toggles follow the **absent = enabled** pattern. If a key is missin
|
||||
| `workflow.plan_bounce_passes` | number | `2` | Number of sequential bounce passes to run. Each pass feeds the previous pass's output back into the validator. Higher values increase rigor at the cost of latency. Added in v1.36 |
|
||||
| `workflow.post_planning_gaps` | boolean | `true` | Unified post-planning gap report (#2493). After all plans are generated and committed, scans REQUIREMENTS.md and CONTEXT.md `<decisions>` against every PLAN.md in the phase directory, then prints one `Source \| Item \| Status` table. Word-boundary matching (REQ-1 vs REQ-10) and natural sort (REQ-02 before REQ-10). Non-blocking — informational report only. Set to `false` to skip Step 13e of plan-phase. |
|
||||
| `workflow.plan_review_convergence` | boolean | `false` | Enable the `/gsd-plan-review-convergence` command. Disabled by default — the command exits with an enable instruction when this key is `false`. The command automates the manual plan→review→replan loop: it spawns configured reviewers (Codex, Gemini, Claude, OpenCode, Ollama, LM Studio, llama.cpp), counts unresolved HIGH concerns and actionable MEDIUM/LOW findings via the CYCLE_SUMMARY contract, replans with `--reviews` feedback, and repeats until converged or max cycles reached. Enable with `gsd config-set workflow.plan_review_convergence true`. Added in v1.39 |
|
||||
| `workflow.plan_chunked` | boolean | `false` | Enable chunked planning mode. When `true` (or when `--chunked` flag is passed to `/gsd-plan-phase`), the orchestrator splits the single long-lived planner Task into a short outline Task followed by N short per-plan Tasks (~3-5 min each). Each plan is committed individually for crash resilience. If a Task hangs and the terminal is force-killed, rerunning with `--chunked` resumes from the last completed plan. Particularly useful on Windows where long-lived Tasks may hang on stdio. Added in v1.38 |
|
||||
| `workflow.plan_chunked` | boolean | `false` | Enable chunked planning mode. When `true` (or when `--chunked` flag is passed to `/gsd-plan-phase`), the orchestrator splits the single long-lived planner Task into a short outline Task followed by N short per-plan Tasks (~3-5 min each). Each plan is committed individually for crash resilience. If a Task hangs and the terminal is force-killed, rerunning with `--chunked` resumes from the last completed plan. Particularly useful on Windows where long-lived Tasks may hang on stdio. See [`planning.chunked_parallel`](#planning-settings) to dispatch the per-plan Tasks concurrently instead of one at a time. Added in v1.38 |
|
||||
| `workflow.code_review_command` | string | (none) | Shell command for external code review integration in `/gsd-ship`. Receives changed file paths via stdin. Non-zero exit blocks the ship workflow. Added in v1.36 |
|
||||
| `workflow.tdd_mode` | boolean | `false` | Enable TDD pipeline as a first-class execution mode. When `true`, the planner aggressively applies `type: tdd` to eligible tasks (business logic, APIs, validations, algorithms) and the executor enforces RED/GREEN/REFACTOR gate sequence. An end-of-phase collaborative review checkpoint verifies gate compliance. Added in v1.36 |
|
||||
| `workflow.mvp_mode` | boolean | `false` | Persist the MVP-mode flag in config so every phase defaults to MVP framing without requiring `--mvp` on the CLI. Resolved via the precedence chain: `--mvp` CLI flag → ROADMAP.md `**Mode:** mvp` field → this config value → `false`. When `true`, the planner, executor, verifier, and discovery surfaces treat the phase as an MVP vertical slice (UI → API → DB) of one user-visible capability instead of a horizontal layer. |
|
||||
@@ -664,6 +664,47 @@ The following combinations of `mode`, `granularity`, `model_profile`, and workfl
|
||||
| `planning.pr_strict` | boolean | `false` | Filter mode for [`/gsd-pr-branch`](COMMANDS.md#gsd-pr-branch). `false` — the generated PR branch keeps structural planning state (`STATE.md`, `ROADMAP.md`, `MILESTONES.md`, `PROJECT.md`, `REQUIREMENTS.md`, `milestones/**`) and drops the transient subdirectories. `true` — every `.planning/` path is dropped, structural files included, and a commit is carried over only when it touches at least one file outside `.planning/`. Applies to the root repository's PR branch only; `planning.sub_repos` companion branches are unaffected |
|
||||
| `planning.search_gitignored` | boolean | `false` | Add `--no-ignore` to broad searches to include `.planning/` |
|
||||
| `planning.sub_repos` | array of strings | `[]` | Paths of nested sub-repos relative to the project root. When set, GSD-aware tooling scopes phase-lookup, path-resolution, and commit operations per sub-repo instead of treating the outer repo as a monorepo |
|
||||
| `planning.chunked_parallel` | boolean | `false` | Opt-in concurrent per-plan planners in chunked mode. See [Concurrent per-plan planners in chunked mode](#concurrent-per-plan-planners-in-chunked-mode-3777) below. |
|
||||
|
||||
### Concurrent per-plan planners in chunked mode (#3777)
|
||||
|
||||
[`workflow.plan_chunked`](#workflow-toggles) splits a phase's planning into a short outline Task
|
||||
followed by N short per-plan Tasks, committing each plan individually for crash resilience. By
|
||||
default those per-plan Tasks still run **one at a time** — a phase with 6 plans at ~3-5 minutes
|
||||
each pays roughly the sum of their runtimes, even though each plan writes a disjoint
|
||||
`{plan_id}-PLAN.md` file with no data dependency on its siblings.
|
||||
|
||||
```json
|
||||
{
|
||||
"planning": {
|
||||
"chunked_parallel": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
gsd config-set planning.chunked_parallel true
|
||||
/gsd-plan-phase 3 --chunked
|
||||
```
|
||||
|
||||
When `true`, the runnable per-plan planners that share one outline Wave are dispatched together
|
||||
(one message, `run_in_background=true` on each) instead of one at a time; a later Wave still waits
|
||||
for every plan in the current Wave to be verified on disk and committed, honoring the outline's
|
||||
Wave column as the schedule. `Depends On` itself is not separately parsed — it is expected to name
|
||||
only a plan in an earlier Wave, so batching strictly by Wave already respects it; a same-Wave
|
||||
`Depends On` would be a defect in the outline, not something this dispatch mechanism detects.
|
||||
|
||||
**This is gated, not unconditional.** Concurrent dispatch only fires when the runtime's negotiated
|
||||
dispatch capacity (`gsd-tools query dispatch-capacity`, #3673) is greater than `1`. A runtime that
|
||||
declares no `maxConcurrency` — most non-Claude runtimes today — resolves to the fail-closed floor
|
||||
of `1` and stays serial regardless of this setting, exactly like the pre-#3777 loop. Claude Code
|
||||
declares a capacity of 20, so this setting has an effect there out of the box.
|
||||
|
||||
**Trade-offs accepted by this setting.** Per-plan commits interleave within a batch instead of
|
||||
landing strictly one-at-a-time, and a stalled plan's retry no longer blocks sibling plans in the
|
||||
same batch that already completed and committed — a mid-batch interrupt leaves whichever plans
|
||||
finished first already committed, rather than stopping after the last plan in strict outline
|
||||
order. Default `false` keeps the original serial behavior byte-for-byte.
|
||||
|
||||
### Project-Root Resolution in Multi-Repo Workspaces
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ Language versions: [English](README.md) · [Português (pt-BR)](pt-BR/README.md)
|
||||
- [Verify a dependency-compatibility claim](how-to/verify-a-dependency-compatibility-claim.md) — act on a compatibility claim the researcher left `[ASSUMED]`, and tell "nothing declared" apart from "a constraint is declared" and "the lookup failed"
|
||||
- [Execute a phase](how-to/execute-a-phase.md) — run plans in parallel waves with fresh-context subagents
|
||||
- [Enable parallel reviewer lanes](how-to/enable-parallel-reviewer-lanes.md) — cut a multi-reviewer `/gsd-review` pass toward its slowest lane, and tell a rate-limited lane apart from one that was never selected
|
||||
- [Enable concurrent per-plan planners in chunked mode](how-to/enable-concurrent-chunked-planning.md) — dispatch chunked `/gsd-plan-phase`'s per-plan Tasks together within one outline Wave instead of one at a time, and know when the setting has no effect
|
||||
- [Verify and ship](how-to/verify-and-ship.md) — walk through completed work, diagnose failures, and create the PR
|
||||
- [Catch complexity before it compounds](how-to/act-on-a-refactor-proposal.md) — enable the post-execute refactor hook, read a proposal's score vs. anchor delta, and accept or decline it
|
||||
- [Run phases autonomously](how-to/run-phases-autonomously.md) — use autonomous mode for unattended phase execution
|
||||
|
||||
80
docs/how-to/enable-concurrent-chunked-planning.md
Normal file
80
docs/how-to/enable-concurrent-chunked-planning.md
Normal 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).
|
||||
Reference in New Issue
Block a user