docs/adr/0011-review-default-reviewers.md
review.default_reviewers config key scopes the no-flag /gsd-review fan-outWe propose adding a review.default_reviewers key to .planning/config.json that scopes the no-flag default of /gsd-review to a user-chosen subset of detected CLI reviewers. Today the no-flag branch of workflows/review.md (line 52) invokes all available CLIs, which for multi-CLI users plus local model servers (ollama, lm-studio, llama.cpp) means probing up to ~10 backends per review, paying timeout costs on servers that aren't running and burning tokens on reviewers the user doesn't want for routine work (#3079). The only workaround today is patching workflows/review.md in place; that patch is wiped on every /gsd-update and requires /gsd-update --reapply to restore, with no machine-readable record of intent. The proposed key sits inside the existing review.* namespace (alongside review.models.<cli> and review.*_host), follows GSD's absent = enabled config philosophy, and is implementable as a one-line config read plus an intersection on the detected reviewer set.
review.default_reviewers to the config.json schema as string[], validated against the existing CLI slug pattern ^[a-zA-Z0-9_-]+$ (the same pattern used for review.models.<cli> slugs)./gsd-review invokes only the reviewers listed in the key, intersected with the host's detect_clis result.docs/CONFIGURATION.md.--all continues to mean "every detected reviewer" and ignores the config key.--gemini, --codex, --cursor, --claude, --opencode, …) continue to win over both config and --all.detect_clis step of workflows/review.md: detect first, then filter by review.default_reviewers only on the no-flag branch.Precedence (highest first):
--allreview.default_reviewersFirst slice should land the config plumbing and the no-flag branch behavior without expanding into adjacent reviewer-selection design:
review.default_reviewers in the config loader; validation as string[] with slug pattern; lowercase normalization; clear schema errors for non-array / non-string-element values.workflows/review.md detect_clis no-flag branch:
detected ∩ default_reviewers--all / explicit flags / no config)docs/CONFIGURATION.md with a review.* subsection documenting the key, allowed values, defaults, and override precedence; add the key to the schema block at the top of that file; update workflows/review.md to reference the key in the no-flag branch.detect_clis intersection; integration coverage of no-flag honors config, --all overrides, individual flags override, unknown slug warns, only-undetected slugs errors.It should not in the first pass:
--no-default or any new CLI flag (track in "Open questions" Q-2 — likely equivalent to --all).review.profiles.*). The namespace is left open for this as a future ADR (see "Open questions" Q-3).review.groups.cheap = [...]). Same — namespace deliberately left open./gsd-config --integrations to set the key interactively. Track as a fast follow (see "Open questions" Q-4).--all semantics or the individual flag set.workflows/review.mddetect_clis step, no-flag branch (current line 52: "No flags → include all available") — replace with: "No flags → if review.default_reviewers is set, intersect detected with the listed slugs; otherwise include all detected."review.default_reviewers: string[] to the JSON schema for .planning/config.json. Pattern per element: ^[a-zA-Z0-9_-]+$. Slug list de-dup on read; lowercase-normalize on read.review.* keys.docs/CONFIGURATION.mdreview.default_reviewers to the Full Schema code block at the top of the file as an optional array key under a "review": { ... } object.review.* section if one exists) covering: purpose, type, default, precedence vs. --all and individual flags, edge-case behavior (unknown slugs, undetected slugs, empty result).workflows/review.md for how the key is consumed at review time.tests/review-default-reviewers-config.test.cjs:
["gemini", "codex"] parses; lowercase normalization works[] schema decision per Q-1 (proposed: parse-time error)tests/review-default-reviewers-resolution.test.cjs:
--all + key set → every detected reviewer invoked, key ignored--gemini + key set to ["codex"] → only Gemini invoked/gsd-review integration tests to cover the new selection-source log line.docs/CONFIGURATION.md to include "review": { "default_reviewers": ["gemini", "codex"] } so the key is discoverable from the canonical schema view.{
"review": {
"default_reviewers": ["gemini", "codex"]
}
}
With this set, /gsd-review (no flags) invokes only Gemini and Codex. /gsd-review --all invokes every detected reviewer. /gsd-review --cursor invokes only Cursor. Today's behavior is preserved by simply omitting the key.
detected = detect_clis() # unchanged
if any individual flag passed:
selected = flags_to_set(flags) ∩ detected
elif --all:
selected = detected
elif config.review.default_reviewers is set:
valid = filter(config.review.default_reviewers, is_known_slug)
# warn on each invalid slug
selected = valid ∩ detected
# info on each valid-but-undetected slug
if selected is empty:
error with actionable message # see Q-1
else:
selected = detected # today's behavior
log_selection_source(selected, source)
workflows/review.md; the patch class that /gsd-update wipes goes away for this case..planning/config.json and share a default reviewer set across machines and contributors, without forking the workflow file./gsd-review wall-clock time drops on machines where detection probes idle local model servers — the timeout cost on stopped daemons is no longer paid on every routine review.review.* namespace stays internally consistent. Future review.profiles.* or review.groups.* can coexist with review.default_reviewers without renaming.detect_clis, not on any per-runtime adapter. The existing resolve_model_ids: "omit" path used by non-Claude runtimes (Codex, OpenCode, Gemini CLI, Kilo) is unaffected.--all / individual flags, which the test plan covers..planning/config.json shape, adoption of this key becomes a useful signal for whether to invest in the richer profiles design (see Q-3).review.default_reviewers: [] be a schema error, or should it fall back to "all detected"? Proposal: schema error. Rationale: users who want "all detected" can simply omit the key (more readable); [] looks like a typo or programmatic mistake; surfacing the ambiguity is more helpful than silently swallowing it. Blocking — affects schema validation and tests.--no-default flag warranted, or is it equivalent to --all for this use case? Proposal: drop unless a concrete difference surfaces during implementation. Non-blocking.review.profiles.* open as a future namespace, or is that premature? Proposal: leave open; document the intent in docs/CONFIGURATION.md so the next contributor doesn't pick a conflicting key. Non-blocking./gsd-config --integrations learn the new key in this pass, or as a fast follow once the schema + resolution land? Proposal: fast follow. Non-blocking; depends on contributor bandwidth.--verbose? Proposal: behind --verbose. Non-blocking.#3079docs/CONFIGURATION.md — review.models.<cli>, review.*_host, and the absent = enabled patternworkflows/review.md (line 52)^[a-zA-Z0-9_-]+$ (used for review.models.<cli> keys)0011-review-default-reviewers-prd.md