---
name: review-jev-docs
model_tier: light
description: |
  Use when: an ADDITIONAL, machine-scored pass is wanted over documentation sections that
  may have gone STALE because of a diff — never replacing any other reviewer. Dispatched
  by review-orchestrator in Wave B, via the CLI (`keryx review jev-docs`), when
  `review.jev.docs: true` in .metaproject/tasks.config.json and a Jev/OpenRouter
  credential is resolvable. It is not an LLM sub-agent: there is nothing to dispatch
  through a platform-native agent mechanism, and no prose is generated by a model —
  Jev only answers a `noul` staleness probability per doc section; keryx writes every
  word of every finding, and one class of finding (a removed/renamed CLI flag still
  documented) is found with no Jev call at all.
  NOT for: judging whether documentation is well-written, complete, or accurate about
  something the diff never touched — this reviewer only ever looks at sections
  deterministically linked to code the diff changed.
triggers:
  - "jev docs"
  - "stale docs"
  - "review --jev-docs"
metadata:
  author: "MrCipherSmith"
  version: "1.0.0"
  category: "review"
  compatible_harnesses: "cursor,codex,zed,opencode,claude"
  engine: "jev"
  origin: "authored"
license: "MIT"
---

# Review — Jev Docs (stale-documentation detection)

An ADDITIONAL orchestrator reviewer, flow 333. It is a **keryx program**, not an
LLM sub-agent: `review-orchestrator` never dispatches a platform-native agent
for it, it runs `keryx review jev-docs` and reads the `--json` output. Every
finding is composed by keryx; Jev ("System One" on OpenRouter) supplies only a
`noul` staleness probability per doc section — it never writes prose, and
nothing it returns is quoted verbatim into a finding. Its inputs are the reviewer payload only; session memory and earlier conversation are not inputs.

---

## What it does

1. Splits every discovered documentation file — the default corpus is
   USER-FACING docs only: `docs/**`, the root `README*` (never `CHANGELOG*`),
   and gdwiki pages (`.metaproject/wiki/**`) — into sections by heading,
   deterministically (`src/review/jev-docs.ts`'s `extractDocSections` — no
   model call). `--include <glob>` (repeatable) widens the corpus back out
   (skills, rules, anything project-specific); see Input Contract.
2. Links each section to code deterministically — an explicit repo-relative
   path it quotes, a backtick-quoted symbol that appears verbatim in one of
   the diff's own hunks, or a `keryx <verb>` invocation whose command file the
   diff changed. Only sections linked to code the diff CHANGES, and that the
   diff does NOT itself edit, are candidates.
3. Ranks linked sections by link strength — path mention > symbol mention >
   verb mention; more distinct links to changed code within the same kind
   rank higher — and asks Jev exactly ONE `noul` question per selected
   section, up to `--max-calls` (default 30) and 8 per doc file, batched
   under the vendor's 64k token budget, with the ranking basis and every drop
   reported (`selection`), never silent, never alphabetical.
4. Separately, and with NO Jev call: a CLI flag that disappears from a
   changed file's diff (present on a removed line, absent from every added
   line of the same file) and is still mentioned by an untouched doc section
   is flagged deterministically.
5. Synthesizes findings deterministically: `problem` names the section
   (file + heading + line) and the code change that likely outdated it,
   `suggested_fix` names the update target, `evidence` carries Jev's
   probability (or, for the flag check, the deterministic reasoning).
   Severity is always `minor`.

---

## Input Contract

Not dispatched with a prompt — invoked as a CLI command:

```text
keryx review jev-docs (--diff <ref> | --pr <n>) [--max-calls <n>] [--threshold <0..1>]
                      [--repo <owner/repo>] [--model <jev-1.13|jev-latest>]
                      [--fixtures <dir>] [--include <glob>]... [--json]
```

`review-orchestrator` passes `--diff <ref>` (or `--pr <n>`) matching the same
target every other reviewer's dispatch checks.

---

## Opt-in and privacy

Refuses before any doc read or network call unless
`.metaproject/tasks.config.json` declares:

```json
{ "review": { "jev": { "docs": true } } }
```

Every doc-section excerpt and hunk sent to Jev is redacted first through
`src/security/service.ts` — the same floor `review conform`/`review jev-rules`
already apply. No cache or output file stores a credential.

---

## Output Contract

Emits a `REVIEW_RESULT`-shaped object matching
`.metaproject/skills/gdskills/review/review-orchestrator/reviewer-finding.schema.json`
— `status`, `reviewer: "review-jev-docs"`, `summary`, `findings`, `stats` —
under `--json`. Its findings merge into the consolidated array exactly like
any other reviewer's: same Quality Gate, same dedup, same Wave C
verification.

### Class scope — required for `blocker` and `major`

Every finding this reviewer emits is `minor` (`docsFindingStats` caps it by
construction), so `class_scope` never applies here — `blocker`/`major`
findings, and the `class_scope` contract that comes with them, belong to the
reviewers named in `review-orchestrator/SKILL.md`'s own Finding Format
section.

---

## Orchestrator integration

- `keryx review reviewers --json` lists it under `bundled` with
  `"engine": "jev"`.
- `review-orchestrator` dispatches it in **Wave B**, alongside the domain/
  convention reviewers, when the opt-in is on and a Jev/OpenRouter credential
  resolves (`resolveJevApiKeyResolution`). When either is false it is
  **skipped with the stated reason**, recorded in `Skipped reviewers` —
  never silently absent.
- It is **ADDITIONAL**: it never replaces any documentation-adjacent finding
  another reviewer already raises; the dedup pass merges rather than
  double-counts.

---

## Red Flags

| Rationalization | Why it is wrong |
|---|---|
| "Jev said 0.9, so the doc is definitely wrong now" | A `noul` score is a probability, not a verdict — read the linked hunk yourself before editing the doc |
| "No findings means the docs are current" | The default corpus is `docs/**`/`README*`/gdwiki only — a project's `.metaproject/skills/**`/`rules/**` need `--include` to be scored at all; `--max-calls`/8-per-file also bound what gets scored (`selection.droppedSections`) |
| "This section wasn't linked, so it's fine" | Linking is deliberately narrow (explicit paths/symbols/verbs) — a section describing behaviour with no explicit code reference is out of this reviewer's reach by design, not proven current |

---

## Verification

Before trusting a run's findings:

1. Read `selection.droppedSections` in the `--json` output — a capped run
   covered less than every linked section.
2. Spot-check a finding against the cited hunk: does the section's own text
   actually conflict with what the diff changed?
3. Confirm every finding carries `reviewer: "review-jev-docs"` and a
   `dedupe_key` — both are required for the orchestrator's Quality Gate and
   Wave C verification to route it correctly.

---

## Iron Laws

### Shared laws (every reviewer)

1. **A claim of runtime harm with no reproducible path is `info`.** If you cannot name the input, call, or condition that reaches the code, you have an observation, not a finding. Report it as `info` and say what would settle it.
2. **Never flag the theoretical.** The path you describe must exist in the code under review. Do not report a safe API because it could be misused, or a pattern because it is often wrong elsewhere.
3. **One finding per class, not one per occurrence.** When the same shape appears at several sites, report it once and list every site. Ten findings that are one finding hide the other nine problems.
4. **A deliberate choice is not a defect until its reason is read and shown wrong.** An explicit override, suppression or exemption, a comment or commit giving a reason, or a sibling doing the same is a decision: read its reason (the comment, `git log -L` or `git blame`, the sibling) before you report it, and report it only when you can show that reason wrong. A project rule is checked against accepted platform practice and its known exceptions before a deviation from it is reported.

Severity levels are defined once, in `review-orchestrator/SKILL.md` →
**Severity (canonical)**. This reviewer does not restate them — it only ever
emits `minor`, capped by construction (`docsFindingStats`), so the
`major`/`blocker` shapes never apply here.

---

## Scope Boundaries

| Concern | This skill | Use instead |
|---------|------------|-------------|
| A doc section linked to changed code likely went stale | YES | — |
| Documentation quality/completeness unrelated to this diff | NO | a human, or a dedicated docs review |
| Judging whether a reported finding is real | NO | `review-verifier` |
| Editing the documentation itself | NO | a human, following `suggested_fix` |
