Files
msd-core/docs/how-to/enable-parallel-reviewer-lanes.md
Jakub Zych a9a7a328e6 refactor: hard-fork GSD -> MSD (Make Software Done)
Mechanical rename produced by scripts/msd-rename.cjs: gsd/Gsd/GSD -> msd/Msd/MSD
across contents and paths, upstream package/repo coordinates -> @golem15/msd-core
and golem15com/msd-core. Deep links into upstream history, sibling upstream
packages, the GSD-2 import feature, CHANGELOG.md and .changeset/ are kept as-is.

Hand edits on top: MSD block-letter banner and logos, LICENSE copyright line,
package/plugin identity, regenerated lockfile, install-tree fixtures, derived
registries and benchmark baseline; migration checksum baseline re-locked
(MSD keeps its own install state, so no install had applied the old sums);
sort-order and regex-escaped expectations in tests adjusted.
2026-10-06 01:47:40 +02:00

6.5 KiB

How to enable parallel reviewer lanes

Cut the wall-clock cost of a multi-reviewer /msd-review pass from the sum of its lanes toward its slowest lane — without losing the rate-limit protection the sequential default exists to provide.

Default-off, and deliberately so. Reviewer lanes are dispatched one at a time because concurrent invocation can trip provider rate limits, and a lane lost to a rate limit is a cross-AI review that quietly went blind in one eye. Turning this on is you asserting that your providers can take the concurrency. Nothing detects that for you.

What you need:

  • Two or more reviewer lanes that actually run on this host. With one lane there is nothing to overlap and the setting changes nothing.
  • Provider capacity for concurrent requests — separate accounts, generous quota, or local model servers (ollama, lm-studio, llama-cpp) that have no external limit at all.

Step 1 — Check what your review pass actually runs

Parallelism only helps if several lanes are selected. Confirm the set first:

msd config-get review.default_reviewers

If that returns Key not found, no-flag runs use every detected reviewer and --all is redundant. If it names a single reviewer, stop here — enabling the key would change nothing.


Step 2 — Turn the key on

msd config-set review.parallel_lanes true

Verify it took:

msd config-get review.parallel_lanes --raw
# → true

The guard is strict equality. Only the exact value true opts in. "1", "yes", "on" and "TRUE" are all read as not enabled and leave dispatch sequential. This is intentional: a mistyped config gets the conservative behavior rather than firing concurrent requests at a rate-limited provider. If config-get shows anything other than true, the setting is off.


Step 3 — Run a review and read the result

/msd-review --phase 3 --all

or, for the convergence loop:

/msd-plan-review-convergence 3 --all

Open {phase_dir}/{padded_phase}-REVIEWS.md and check the reviewers: frontmatter list. Every lane you selected must appear there. That list is the contract: lanes are joined before the file is rendered, so a missing reviewer means that lane did not produce a review — never that aggregation ran early.

If every selected lane failed, REVIEWS.md is not written at all (ADR-3473 §8.5, #3885) — the run reports the failure instead of synthesizing a review artifact from zero lane results. This is not specific to parallel dispatch (a sequential run where every lane fails behaves the same way), but concurrency gives you more ways to lose every lane in one pass. Each lane's raw output and any non-empty .err file are preserved beside the phase's artifacts before the run's own cleanup runs, so a missing REVIEWS.md is diagnosable, not silent — see the table below for what a partial failure (some, not all, lanes down) looks like instead.

Section order in REVIEWS.md, and line order in the run's msd-review-lane-results.jsonl, are unchanged from sequential dispatch. They follow reviewer-selection order, not completion order, so a diff of two runs shows no reordering churn.


Telling the outcomes apart

The single most useful habit: an empty or stub review is a dropped lane, not a clean review. That is true sequentially too, but concurrency gives you more ways to drop one at once.

What you see What it means What to do
Every selected lane in reviewers:, all sections populated Working as intended Nothing
A lane's section carries the "failed or returned empty output" header The lane ran and produced nothing usable. Read the captured stderr in the stub If it names a rate limit or quota, your provider cannot take this concurrency — see below
A lane reports probe_timeout or host_unreachable The lane could not be reached at all — a local server that is down, not a concurrency effect Start the server; unrelated to this setting
A lane reports budget_too_small Its prompt budget cannot fit the minimum review set Raise review.max_prompt_tokens_per_reviewer.<slug>; unrelated to this setting
A lane reports egress_host_changed The lane was consented to one destination and the config now names another. It is blocked, not redirected Re-consent deliberately; unrelated to this setting
A lane is missing from reviewers: entirely It was never selected Check your flags and review.default_reviewers
Several lanes stub out at once, with provider errors The concurrency is more than your account can take Turn the key back off, or narrow review.default_reviewers

Rate-limited lanes fail loudly. A lane that gets throttled goes down the same path as any other failing lane — a diagnostic stub carrying its stderr, kept distinguishable from a real review by its header. It is not silently dropped and it does not abort its sibling lanes.


Turning it back off

msd config-set review.parallel_lanes false

The next pass dispatches sequentially again. Nothing else changes: no artifact written under the parallel setting needs migrating, because the output layout is identical in both modes.


What this does not speed up

Convergence cycles stay sequential. /msd-plan-review-convergence runs plan-phase → review → replan → re-review, and each cycle genuinely depends on the previous one's output. Enabling this key makes each review pass inside a cycle faster; it does not reduce the number of cycles, and it does not overlap planning with reviewing. A three-cycle convergence run is still three sequential rounds.

There is no concurrency bound. Every selected lane dispatches at once. Eleven selected lanes means eleven concurrent requests. If that is more than you want, the control is the size of your selected set — review.default_reviewers or explicit flags — not a throttle on this setting.

Reviewer instances sharing an adapter are not grouped. Two review.reviewer_instances entries backed by the same CLI dispatch concurrently against that one provider. If you run several same-provider instances, you are the most likely configuration to hit a limit, and this setting gives you no way to serialize just those.


See also: Configuration reference · Reviewer instances · /msd-review command reference