feat(#1517): support custom reviewer instances for /gsd:review (#1766)

* feat(#1517): support custom reviewer instances for /gsd:review

Add a bounded review.reviewer_instances config surface so one model-capable
adapter (e.g. opencode) can run as several independent reviewer identities in a
single /gsd:review pass. Instances participate only via review.default_reviewers,
expand before built-in slugs, are available iff their cli is detected, and a
non-matching entry is a hard error (typo must be loud). >=2 same-cli instances
emit a shared-adapter caveat in REVIEWS.md. Default path with no instances is
byte-for-byte unchanged.

Single-source instance->cli resolution lives in resolveReviewerSelection /
normalizeReviewerInstances (parity-locked in
tests/review-reviewer-instances.test.cjs). cli validated against
KNOWN_REVIEWER_SLUGS only (never arbitrary shell); model/agent opaque, never
shell-interpolated.

Closes #1517

* chore(#1517): backfill changeset pr:1766

---------

Co-authored-by: review-bot <review-bot@gsd>
This commit is contained in:
Tom Boucher
2026-06-26 23:35:04 -04:00
committed by GitHub
parent ce62f2b68d
commit b0d5ca3379
30 changed files with 835 additions and 66 deletions

View File

@@ -66,6 +66,11 @@ Reviewer-selection precedence:
- Known-but-undetected slugs emit an info note and are ignored
- If all configured reviewers are unavailable, fail with an actionable message
**Reviewer instances (#1517, optional):** if `review.reviewer_instances` is configured,
instance names in `review.default_reviewers` run as independent identities. Resolution rules
are in `gsd-core/references/reviewer-instances.md` — load it lazily only when instances are
configured. Unconfigured → default path unchanged.
If no CLIs are available:
```
No external AI CLIs found. Install at least one:
@@ -243,6 +248,10 @@ else
fi
```
**Reviewer instances (#1517, optional):** when instances are configured, each selected
instance invokes its base `cli` with its own `model`/`agent` (opaque argv, never
shell-interpolated). Exact invocation in `gsd-core/references/reviewer-instances.md`.
For each selected CLI, invoke in sequence (not parallel — avoid rate limits):
**Gemini:**
@@ -634,6 +643,11 @@ Combine all review responses into `{phase_dir}/{padded_phase}-REVIEWS.md`:
After all reviewers complete, collect trim metadata files written during the run. For each reviewer that was trimmed (i.e. a `.metadata.json` file exists and `hardFailed` or `omitted` is non-empty, or `projectMdShrunk` is true, or `planTruncationPct > 0`), include a `trimmed_reviewers` block in the frontmatter. Omit the key entirely if no reviewer was trimmed.
**Reviewer instances (#1517, optional):** when instances ran, frontmatter records their
names, each gets its own `## <Adapter> Review (<instance>)` section, and ≥2 same-cli
instances print a one-line shared-adapter caveat. Format in
`gsd-core/references/reviewer-instances.md`.
```markdown
---
phase: {N}
@@ -684,6 +698,18 @@ trimmed_reviewers: # only present if at least one reviewer was trimmed
---
## OpenCode Review (opencode-deepseek)
{opencode-deepseek instance review content — only present when this instance was selected}
---
## OpenCode Review (opencode-mimo)
{opencode-mimo instance review content — only present when this instance was selected}
---
## Qwen Review
{qwen review content}