`review-lane plan` resolved every cross-AI reviewer lane's reasoning effort by spawning `query resolve-execution gsd-plan-checker --host <slug>`. The agent id was a hardcoded literal, so `--host` chose only the argv RENDERING while the LEVEL always came from the installed plan-checker's frontmatter — `low` under every shipped model profile. Every prompt-fed lane therefore ran at a fast structural verifier's effort, and because the rendered argument is a CLI config override it silently beat the effort the operator had configured for that CLI. At `low` a large source-grounded prompt makes a model end its turn with no final message, so the lane came back empty and its stub read as a crash. Effort is a property of the review, so the lane declares it. Two new fields on ReviewerLane — `effortConfigKey` (`review.effort.<slug>`) and `defaultEffort` — carried through each capability manifest and the generated registry, set on the three lanes with an argv effort channel and null on the other nine. A new pure `resolveLaneEffort()` resolves config key -> lane default -> nothing, where "nothing" emits no effort argument at all and the reviewer CLI's own configuration decides; `inherit` selects that path explicitly and an unrecognized level falls back to the lane default rather than being forwarded to a CLI that would reject it. The host's negotiated effortSurface still gates the rendering, so ADR-1239/#2481's trust boundary holds on this path too. Resolving in-process also removes up to twelve subprocess spawns per review. The empty-output stub now names the effort the lane ran at and distinguishes a clean exit from a timeout kill, a non-zero exit, and a process that never ran — `status` is null for both a timeout and a signal, so those were indistinguishable before. The hint is hedged: a clean empty exit is most often a model stopping short, but it is also consistent with a CLI writing its output elsewhere. Also: the capability validator now knows both fields, rejects a malformed key or an out-of-vocabulary default, and rejects a default declared without a config key (a level the operator could never override). An existing end-to-end row in tests/effort-surface-axis.test.cjs asserted the old coupling; it now configures the lane's own key and pins the decoupling in the same real spawn, with the agent execution tier set to a level that must not appear. Emitted-Drift-Ack-Growth: review.md — the effort/model resolution-order table this fix adds. The workflow is where an operator looks to find out which knob set a lane's model and effort; leaving the new key undocumented there is the same invisibility that made the plan-checker coupling survive this long. Emitted-Drift-Ack-Growth: review.md — the effort/model resolution-order table this fix adds. The workflow is where an operator looks to find out which knob set a lane's model and effort, so leaving the new key undocumented there is the same invisibility that let the plan-checker coupling survive. Claude-Session: https://claude.ai/code/session_01CRMEuzNMWn3gs5uUW2ghcF Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Tom Boucher <trekkie@nomorestars.com>
This commit is contained in:
committed by
GitHub
parent
925a363879
commit
5ad9a36f35
@@ -350,6 +350,41 @@ timeout key either, matching the same narrow key-ownership invariant their `revi
|
||||
keys already follow (each owns only its own prompt-budget key). `cursor` gained a model flag
|
||||
(`review.models.cursor`, #3653) but still owns no federated timeout key of its own.
|
||||
|
||||
### Reviewer lane reasoning effort (`review.effort.*`, #4255)
|
||||
|
||||
The three lanes that can carry a reasoning level on their command line — `codex`, `claude`,
|
||||
`opencode` — federate a `review.effort.<slug>` key, owned by that lane's capability manifest like
|
||||
its model and timeout keys. Accepted values are the usual effort levels (`minimal`, `low`,
|
||||
`medium`, `high`, `xhigh`, `max`) plus `inherit`.
|
||||
|
||||
**Resolution order for a lane's effort, highest first:**
|
||||
|
||||
| # | Source | Result |
|
||||
|---|---|---|
|
||||
| 1 | `review.effort.<slug>` | the level you set, rendered in the host's own effort syntax and clamped to what that host supports |
|
||||
| 2 | the lane's declared review default | `high` on all three lanes today |
|
||||
| 3 | nothing declared | **no effort argument is emitted** — the reviewer CLI's own configuration decides |
|
||||
|
||||
Row 1 is the level you asked for, not always the level that runs: each host clamps to its own
|
||||
supported set. Verified against the shipped catalog, `minimal` reaches Codex and Claude as `low`
|
||||
while OpenCode takes it as-is; every other level passes through on all three. `REVIEWS.md` records
|
||||
the level that actually ran, not the one requested.
|
||||
|
||||
`inherit` selects row 3 explicitly: use it when you want your own `~/.codex/config.toml` (or the
|
||||
equivalent for another CLI) to be the authority, because the argument GSD renders is a
|
||||
command-line config override and beats that file for the invocation. A value that is not a
|
||||
recognized level falls back to row 2 rather than being forwarded, since an argument the CLI
|
||||
rejects kills the lane outright.
|
||||
|
||||
Before #4255 there was no review-specific source at all: every lane's level came from the
|
||||
`gsd-plan-checker` agent's installed frontmatter — `low` under every shipped model profile — so a
|
||||
prompt-fed, source-grounded review ran at the level chosen for a fast structural verifier, and a
|
||||
large plan set could come back as an empty lane. Effort is now a property of the review.
|
||||
|
||||
The lanes with no effort channel (`gemini`, `cursor`, `antigravity`, `qwen`, `coderabbit`,
|
||||
`kimi-code`, `ollama`, `lm_studio`, `llama_cpp`) federate no key and emit no argument, matching the
|
||||
same narrow key-ownership invariant their model and timeout keys already follow.
|
||||
|
||||
### Reviewer defaults for `/gsd-review`
|
||||
|
||||
Use `review.default_reviewers` to scope the no-flag `/gsd-review` run to a subset of detected reviewers.
|
||||
|
||||
Reference in New Issue
Block a user