enhance(#2295): record the resolved model per reviewer in REVIEWS.md frontmatter (#3649)

* test(#2295): failing-first coverage for per-lane resolved-model recording

* feat(#2295): record the resolved model per reviewer lane

* docs(#2295): document the recorded reviewer model and its provenance

* fix(#2295): refuse control characters in a recorded model value

* test(#2295): correct watermark assertions for the widened mark shape

* fix(#2295): anchor the role-manipulation injection pattern at a word boundary

* feat(#2295): record the applied reasoning effort in the model value

* chore(#2295): backfill changeset pr number

* chore(#2295): restore em-dash in changeset body

---------

Co-authored-by: sim <sim@local>
This commit is contained in:
Tom Boucher
2026-08-19 08:59:37 -04:00
committed by GitHub
parent 1adf6d2245
commit 1bf73d957b
15 changed files with 1328 additions and 75 deletions

View File

@@ -240,6 +240,25 @@ The key suffix is **not** always the lane slug. Each lane declares the config ke
| `review.models.opencode` | string | `null` | Model id for OpenCode review (injected into --model), e.g. `"claude-sonnet-4"` |
| `review.models.kimi-code` | string | `null` | Model id for Kimi Code review (injected into -m) |
### Resolved model recording (#2295)
Every `/gsd-review` run records the resolved model per reviewer in the `REVIEWS.md` frontmatter as `models:` and `model_sources:`, whether or not the lane was pinned via the keys above.
| `model_sources` value | Meaning |
|---|---|
| `pinned` | `review.models.<slug>` (or an ADR-1517 reviewer-instance `--model`) that really reached the invocation |
| `served` | An OpenAI-compatible server echoed the model it actually ran. Most authoritative |
| `requested` | openai-http: discovered from `/v1/models`, or the lane's declared `fallbackModel`; the server did not echo one |
| `banner` | The CLI's own startup banner named it. File-output lanes only (`codex` today) |
| `transcript` | The lane handler's own on-disk session log named it (`agy`'s `transcript_full.jsonl`) |
| `unknown` | Nothing recoverable |
A `models:` value reads `unknown` if and only if its `model_sources:` entry is `unknown`.
When GSD applies a reasoning effort to a lane, the recorded value carries it as a
`(reasoning=<level>)` suffix (for example `gpt-5.6-sol (reasoning=high)`) — the level is GSD's
own resolved effort, not the CLI's default.
**Ownership.** These keys are owned by their reviewer-lane capabilities rather than the central
config schema — `review.models.ollama` belongs to the `ollama` capability, `review.ollama_host`
to the same, and so on. Key names and existing `.planning/config.json` files are unchanged; only