---
name: review-jev-rules
model_tier: light
description: |
  Use when: an ADDITIONAL, machine-scored pass is wanted over every changed hunk against
  every applicable project rule clause — never replacing any other reviewer. Dispatched
  by review-orchestrator in Wave B, via the CLI (`keryx review jev-rules`), when
  `review.jev.rules: 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` violation probability per (hunk, rule clause) pair; keryx
  writes every word of every finding.
  NOT for: judgement calls a rule clause does not state (logic bugs, architecture,
  security, performance — those stay with the reviewers that already cover them), and
  not a substitute for reading the rules yourself. A finding here says a hunk likely
  contradicts a clause of a rule this project already wrote down; it says nothing about
  code that violates no documented rule.
triggers:
  - "jev rules"
  - "rule check"
  - "review --jev-rules"
metadata:
  author: "MrCipherSmith"
  version: "1.0.0"
  category: "review"
  compatible_harnesses: "cursor,codex,zed,opencode,claude"
  engine: "jev"
  origin: "authored"
license: "MIT"
---

# Review — Jev Rules (deterministic project-rule conformance)

An ADDITIONAL orchestrator reviewer, flow 330. 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-rules` and reads the `--json` output. Every
finding is composed by keryx; Jev ("System One" on OpenRouter) supplies only a
`noul` probability per `(hunk, rule clause)` pair — it never writes prose, and
nothing it returns is quoted verbatim into a finding except the clause text
keryx already had. Its inputs are the reviewer payload only; session memory and earlier conversation are not inputs.

---

## What it does

1. Discovers rule sources deterministically (`src/review/jev-rules.ts`'s
   module header names the exact scope): every file under
   `.metaproject/rules/**` and `rules/**`, every project-skill or installed
   gdskill whose name or `metadata.category` marks it a coding convention, and
   anything named by `--rules <paths>`. **`--rules` bypass is scoped to ONE
   FILE**: an entry naming a single document bypasses the category filter
   below outright; an entry naming a DIRECTORY is walked and its files are
   filtered exactly like auto-discovery — asking for a whole directory is not
   the same as naming one document, and the whole point of the filter is lost
   if it is.
2. **Category filter, before clause extraction.** Each discovered source
   (auto-discovered, or a file found by walking a `--rules` DIRECTORY — never
   a `--rules` entry naming that ONE file explicitly) is classified
   `code`/`process`/`docs` — explicit frontmatter first (`applies_to:
   code|process|docs`, or `metadata.category`), else a documented
   filename/title heuristic (`PROCESS_RULE_HEURISTIC_TERMS`: `commit`, `git`,
   `tdd`, `workflow`, `definition-of-done`, `documentation`, `requirements`,
   `plan`, `prompting`, `subagent`, `skill`, `jobs`, `orchestrat`,
   `review-process`, `release`). A `process`/`docs` source never reaches
   clause extraction at all — excluded, and reported with its reason under
   `excludedSources`.
3. Splits each remaining rule document into clauses with
   `extractReferenceClauses` (the same deterministic splitter `review
   conform` uses), drops authoring-template scaffolding
   (`isPlaceholderClauseText`: an unfilled `[x] <criterion> — verified by
   <test>` checklist line, text dominated by `<...>` placeholders, or a bare
   code-fence line — never a real clause, dropped BEFORE tagging so it costs
   nothing), then TAGS every remaining clause `state_kind:
   "pr"|"report"|"hunk"` + `checkable` by REUSING `review conform`'s own
   `applyClauseTags`/`buildClauseTagQuestions`/`clauseTagFromChoice` — an
   explicit `[state:hunk]`/`[not-checkable: ...]` marker on the clause text
   when the rule author wrote one, else one Jev `choice` call per doc's
   untagged clauses (never per clause), cached by the doc's content hash at
   `.metaproject/data/review-jev-rules/clause-tags.json` (a jev-rules-
   specific cache file — `review conform` and `review-jev-rules` never race
   on the same one). Only a clause tagged `state_kind: "hunk"` and
   `checkable` is ever paired against a hunk; anything else is dropped and
   reported under `droppedClauses`.
4. Decides, per `(rule, changed file)` pair, whether an applicable clause
   applies — by declared path globs (`metadata.paths`) and/or
   `metadata.stack_requires`, failing toward inclusion exactly like `keryx
   review stack`/`scope.ts` already do, THEN by file kind: a docs hunk
   (`.md`/`.mdx`/`.txt`) pairs only with a `docs`-categorised source or a
   clause explicitly tagged `[docs-applicable]`; a code source never pairs
   with a docs hunk, and vice versa (`clauseFileKindApplicability`).
5. Takes every changed hunk from `keryx review scope` (mechanical bulk
   already dropped) and asks Jev, per applicable `(hunk, hunk-checkable
   clause)` pair, **one question**: "does this hunk VIOLATE this clause?" —
   batched under the vendor's 64k token budget, capped at `--max-calls`
   (default 150). The budget is spread FAIRLY: hunks are ranked code, then
   tests, then docs, and pairs are allocated round-robin across hunks rather
   than draining the cap on the first hunk in diff order — every selection,
   every drop, and per-hunk coverage (`selection.hunkCoverage`, how many
   hunks were reached vs. never reached) is reported, never silent.
6. Synthesizes findings deterministically: `problem` quotes the clause,
   `impact` is the rule's own stated rationale (if it has a `## Rationale`/
   `## Why` section) or a fixed template, `suggested_fix` names the clause to
   bring the hunk in line with, `evidence` is the hunk location(s) + Jev's
   probability. Severity is capped at `minor` unless the rule itself declares
   a higher one (`[severity: major]` on the clause). One finding per
   `(clause, file)`, deduped across every hunk of that file with a hunk list.

**Why steps 2-5's filters exist:** a live check of this repository's own
41-doc `.metaproject/rules/**` corpus against a merged PR hand-labelled ~1/10
findings correct. Two causes, both fixed here: (a) process/agent-behaviour
rules (commit-message formatting, TDD workflow, an agent's own prompting
standard) paired against a code hunk they were never meant to describe,
because the corpus declares no `metadata.paths`/`stack_requires` and
applicability fails open to "applies everywhere" — the category and
file-kind filters (steps 2 and 4); (b) a re-measurement then found the
`--rules` bypass defeating the category filter for an entire directory, and
the whole `--max-calls` budget landing on a single docs hunk while no code
hunk was ever scored — the scoped bypass and fair round-robin budget (steps
1 and 5). All four are cheap, deterministic, and applied BEFORE any
violation-scoring Jev call, so they cut cost as well as noise. See
`.metaproject/flows/330-*/journal.md` for the full before/after numbers.

---

## Input Contract

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

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

`review-orchestrator` passes `--scope <scope.json>` — the same `keryx review
scope --json` file every other reviewer's dispatch already reads — so this
reviewer checks exactly the same hunks, with the same mechanical-bulk drops,
as everyone else in the round.

---

## Opt-in and privacy

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

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

Every hunk, every rule-clause sent for violation scoring, and every clause
sent for tagging is redacted first through `src/security/service.ts` — the
same floor `review conform` and `review ci-triage` already apply. No cache or
output file stores a credential. Two caches, both gitignored and mode `0600`
under `.metaproject/data/review-jev-rules/`:

- `violation-cache.json`, keyed on the clause text and hunk location, so a
  re-run over unchanged hunks and unchanged rules costs zero additional Jev
  calls.
- `clause-tags.json`, keyed on the rule doc's own content hash — REUSING
  `review conform`'s own clause-tagging cache module
  (`src/review/conform-tag-cache.ts`) at this jev-rules-specific path, so a
  re-run against a DIFFERENT diff but the SAME rule corpus costs zero
  additional tagging calls even when the hunks (and so the violation cache)
  miss.

---

## Output Contract

Emits a `REVIEW_RESULT`-shaped object matching
`.metaproject/skills/gdskills/review/review-orchestrator/reviewer-finding.schema.json`
— `status`, `reviewer: "review-jev-rules"`, `summary`, `findings`, `stats`,
plus `tokens` (with `taggingCalls`/`violationCalls` counted separately),
`selection` (`droppedClauses`'s count, and `hunkCoverage` — one
`{path, applicablePairs, selectedPairs}` per hunk with something to check,
plus `hunksWithPairs`/`hunksReached`/`hunksNeverReached`), `ruleSources`
(each with its `category`), `excludedSources` (category-filtered sources
with their reason), `droppedClauses` (tag-filtered `(ruleId, clauseId)`
pairs with their reason), and `droppedPlaceholderClauses`
(authoring-template clauses dropped before tagging, with their reason) —
under `--json`. `summary` names how many hunks the budget never reached in
plain text. Its findings merge into the consolidated array exactly like any
other reviewer's: same Quality Gate, same dedup, same Wave C verification.

---

## 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 `review-style`, the convention
  reviewers, or any other pass. A rule clause this reviewer flags may also be
  the exact concern a domain reviewer raises independently; the dedup pass
  (by `dedupe_key`/`(file, quote, problem)`) merges the two rather than
  double-counting.

---

### 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.

This reviewer already satisfies all three by construction: `evidence` always
names the hunk and quotes it (never an unreproducible claim), a finding is
only synthesized when the hunk itself is checked against the clause (never a
theoretical pattern), and `synthesizeFindingsFromViolations` dedupes by
`(clause, file)` with every hunk listed, never one finding per hunk.

---

## Red Flags

| Rationalization | Why it is wrong |
|---|---|
| "Jev said 0.9, so this is definitely a violation" | A `noul` score is a probability, not a verdict — severity stays capped at `minor` unless the rule itself declares higher, precisely because Jev alone is not authoritative |
| "This rule clause doesn't really describe code, but the pair matched anyway" | Applicability defaults to "applies everywhere" when a rule declares no path/stack restriction — the clause-kind filter (step 3), the category filter (step 2), and the file-kind gate (step 4) catch most of this before scoring, but a `state_kind: "hunk"` clause on an off-topic rule can still pass through; that is a property of the rule corpus, not a defect in this reviewer |
| "No findings means the diff is clean" | `--max-calls` bounds how many pairs are checked; a capped run reports `selection.droppedPairs`/`hunksNeverReached` for exactly this reason — read the selection stats before treating silence as clean |
| "A rule wasn't checked and I don't know why" | Read `excludedSources` (category filter, at discovery), `droppedClauses` (tag filter, per clause), and `droppedPlaceholderClauses` (template scaffolding, per clause) before assuming a rule was silently skipped — each names the exact reason |
| "I passed `--rules` at a whole rule directory, so every file in it was checked" | Only a `--rules` entry naming ONE file bypasses the category filter; a directory's files are filtered exactly like auto-discovery — check `excludedSources` |
| "I'll skip the opt-in check since I trust this project" | The opt-in and credential gates exist because hunk and rule-clause text leaves the machine; skipping them is skipping consent, not a shortcut |

---

## Verification

Before trusting a run's findings:

1. Read `selection.droppedPairs`/`selection.notApplicable`/
   `selection.droppedClauses`/`selection.hunkCoverage` in the `--json`
   output — a capped, narrowly-applicable, or tag-filtered run covered less
   than "every changed hunk against every applicable clause", and
   `hunksNeverReached` says exactly how many hunks the budget never got to.
2. Read `excludedSources` — a process/meta rule doc excluded by the category
   filter is reported by name and reason, never silently absent from
   `ruleSources`.
3. Spot-check a handful of findings against the actual hunk: does the quoted
   line and the cited clause text support the claim? Jev's probability is not
   evidence a human can inspect; the quote and the clause text are.
4. Confirm every finding carries `reviewer: "review-jev-rules"` and a
   `dedupe_key` — both are required for the orchestrator's Quality Gate and
   Wave C verification to route it correctly.

---

## Scope Boundaries

| Concern | This skill | Use instead |
|---------|------------|-------------|
| A hunk contradicts a documented project rule clause | YES | — |
| Logic bugs, architecture, security, performance not named by any rule | NO | the matching domain reviewer |
| Judging whether a reported finding is real | NO | `review-verifier` |
| Writing or maintaining the rules themselves | NO | a human, or `rules/core/*.mdc` directly |
