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.
140 lines
6.5 KiB
Markdown
140 lines
6.5 KiB
Markdown
# 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:
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
msd config-set review.parallel_lanes true
|
|
```
|
|
|
|
Verify it took:
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
/msd-review --phase 3 --all
|
|
```
|
|
|
|
or, for the convergence loop:
|
|
|
|
```bash
|
|
/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
|
|
|
|
```bash
|
|
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`](../CONFIGURATION.md#reviewer-instances-for-msd-review-1517) 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](../CONFIGURATION.md#parallel-reviewer-lanes-for-msd-review-3034)
|
|
· [Reviewer instances](../CONFIGURATION.md#reviewer-instances-for-msd-review-1517)
|
|
· [`/msd-review` command reference](../COMMANDS.md)
|