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.
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