# Review Gate

> Load to wire, adopt, tune, or debug a repo's review gate or its REVIEW_GATE_* settings.

- Skill: `vanillagreencom/review-gate-2` (Agent Skill, multi-file: 69 files)
- Install (CLI): `npx skillmds@latest add vanillagreencom/review-gate-2`
- Raw SKILL.md: https://api.skillmd.com/api/skills/vanillagreencom/review-gate-2/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: MIT
- Author: vanillagreencom (https://skillmd.com/u/vanillagreencom)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/vanillagreencom/review-gate-2

---


<!-- kendex:project-instructions:start -->
## Project Instructions

<!-- kendex:shared-instructions:start -->
Problems with a kendex-owned skill go through `kendex report`; check ownership in the file first.
<!-- kendex:shared-instructions:end -->
<!-- kendex:project-instructions:end -->

# Review Gate

The gate answers ONE question: **has this exact PR head been reviewed?** It posts that answer as a commit status the repo's branch rules require. It does not check CI, re-run anything, or reason about jobs.

Two greens do NOT mean a review happened. Under `REVIEW_GATE_MODE = "off"` the predicate evaluates no evidence and attests only that the repo disabled the gate; and merge-group statuses never read the mode, posting green as "merge-queue entry: post-approval by construction". Both: [`REVIEW_GATE_MODE` in the settings table](references/settings.md).

## Decision table

| Verdict | Status | Meaning |
|---|---|---|
| `approved` | `success` | Evidence exists for this head, the whole diff sits under `REVIEW_GATE_RENDER_PATHS`, or `REVIEW_GATE_DOCS_ONLY = "none"` and the shared CI classifier accepts the diff as docs-only; no standing objection; no unresolved threads. Under `REVIEW_GATE_MODE = "off"` the predicate evaluates NO term. Success there means only "gate disabled", stated in the status description. |
| `awaiting` | `pending` | No review evidence for this head yet. |
| `threads-open` | `pending` | Evidence exists, but review threads are unresolved. |
| `changes-requested` | `failure` | A reviewer objects. Red means objection, never a build failure. |
| `untracked-claim` | `failure` | A disposition reply that claims tracking and names no issue fails the gate. |
| `unreasoned-decline` | `failure` | A decline whose reason strips to nothing against the label vocabulary fails the gate. |
| `suppressed-findings` | `failure` | A review body at the commit the gate relies on — the head, or the carry base once carry supplies the evidence — carries a `Suppressed comments (N)` or `Previously missed (N)` block: findings that never became threads. Either title counts, written as a markdown heading or as a `<details>` summary. The status names the count and the file:line list. It has no dedicated settings key, and while enforcement is on nothing disables it; `REVIEW_GATE_MODE = "off"` reaches it only by disabling the whole gate. An entry clears when the PR author answers it in an issue comment carrying a line `Dispositions at <sha>` that names this head, plus a line per entry opening with the entry's own `file:line` token — bare as the status prints it, or bold or backticked as the review body does — followed by `Fixed in <sha>`, `Declined: <reason>` or `Tracked: <ID>`. That marker is the only thing that binds the comment to the head. The whole term clears when that commit carries no such block. |
| (exit 2, no verdict) | *unchanged* | A read failed or config is invalid. Take NO action; retry next pass. |

Pending text names the head; which sources open the gate is [references/settings.md](references/settings.md) § Reading the pending status. How the reply-parsing failure verdicts read a reply is `DEVELOPMENT.md` § Tracking-claim parsing and § Decline parsing, and how `suppressed-findings` reads a body is § Suppressed-finding parsing; what to write instead is orch's `references/finding-disposition.md`.

# Working in a consumer repo

## 1. Read the current state before changing anything

```bash
# Is the engine vendored and committed?
git ls-files .agents/skills/review-gate/scripts/ | head

# Is anything wired to write the gate?
git ls-files '.github/workflows/*.yml' '.github/workflows/*.yaml' \
  | xargs grep -l 'review-writer\.sh' 2>/dev/null

# What does the repo say about itself?
.agents/skills/review-gate/scripts/validate.sh; echo "exit $?"
```

`validate.sh` prints one verdict record per check: `ok` or `FAIL`, then `check=CODE value=VALUE`. Indented lines explain the result and the repair. Exit 0 = clean, 1 = findings, 2 = the check could not run at all (bad arguments, not a git repository, a missing file it derives checks from). Fix that first; a 2 is never a pass. Run it after every step below.

## 2. Adopt, when nothing is wired

The precondition comes first: the repo needs **a merge queue** whose required contexts include the test aggregate, or **no held-back jobs**. Held-back jobs report `skipped`, which GitHub counts as satisfied, and a reviewed PR would merge untested. Confirm which one holds before wiring anything.

```bash
# 1. vendor the engine as TRACKED files (CI checks out nothing else)
kendex refresh
git add .agents/skills/review-gate

# 2. copy the writer VERBATIM — it carries no per-repo values
cp .agents/skills/review-gate/templates/review-gate-writer.yml \
   .github/workflows/review-gate-writer.yml

# 3. assign the handful of values this repo actually decides (table
#    below); an install writes none of them, since each has a default
$EDITOR kendex.settings.toml

# 4. prove the install answers for itself
.agents/skills/review-gate/scripts/validate.sh
```

Then add the validate step to the repo's CI as its own job, with no `needs`, no path filter, no gate condition:

```yaml
  review-gate-validate:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@<pinned-sha>
        with:
          persist-credentials: false
      - run: .agents/skills/review-gate/scripts/validate.sh
```

Finish with the repo-side wiring of ruleset, merge queue, and bypass actor, and delete the local machinery the writer supersedes, in the same PR: [references/adoption.md](references/adoption.md).

## 3. Decide and repair

Keys a repo decides: [references/adoption.md](references/adoption.md) § Keys a repo decides. Repair by verdict line: the same reference's § Repair by verdict line.

## 4. Operations

**Watching one or many PRs without stalling.** Never key a hand-rolled monitor on gate-state transitions. Run `.agents/skills/review-gate/scripts/pr-watch.sh` (optionally `--heal`) on the harness's wake-up mechanism: silence + exit 0 means nothing needs you; attention lines name exactly what does. See [Watching PRs as an agent](references/adoption.md#watching-prs-as-an-agent-pr-watch).

**A pull request drew no automatic review.** The automatic reviewer is armed by a branch ruleset, and a base outside that ruleset's target set never draws one. Request the review by hand with `gh pr edit <PR#> --add-reviewer @copilot`. The target set, the ruleset parameters, and the fallbacks when the manual request draws nothing: [references/automatic-review.md](references/automatic-review.md).

**Reviewers are down / nothing is reviewing.** Run the internal review loop: fix findings, resolve every thread, then post the override status with a real reason. It cannot bypass an objection or an open thread.

**A PR that repairs the gate itself.** The writer always runs the merged engine. Merge the repair PR with the ruleset's bypass actor and say so in the commit message.

**A settings-change PR** is judged by the OLD config. A PR adding a trusted login cannot have its own gate honor it. Merge via normal review or the bypass actor.

# The engine

Evidence for the CURRENT head is any of:

1. A non-author review object accepted by the configured trust and state rules.
2. A trusted clean-analysis check-run or commit status that proves analysis ran.
3. A trusted comment-form pass bound to this head's SHA.
4. A trusted operator override with a reason, for missing evidence only.

Carry-forward never creates evidence or bypasses a fail-closed term. Objections and unresolved threads fail closed; an evidence-read failure exits 2 with no verdict. Evidence, trust, relay, and writer mechanics: [DEVELOPMENT.md](DEVELOPMENT.md) § Predicate evidence and trust.

## Scripts

- `scripts/validate.sh`: validate a consumer installation. `--help`
- `scripts/validate-workflow.sh`: compare the adopted workflow with the template. `--help`
- `scripts/review-predicate.sh`: evaluate one head or validate config. `--help`
- `scripts/review-writer.sh`: `workflow_dispatch` and `schedule` evaluate and converge every open PR; `merge_group` posts one queue success, while `WRITER_READ_ONLY=1` is a no-op. Its header documents the workflow-only contract.
- `scripts/pr-watch.sh`: reduce open PRs to attention lines. `--help`

Engine selftests run in kendex CI ([DEVELOPMENT.md](DEVELOPMENT.md)). Re-vendor PRs: [references/vendored-paths.md](references/vendored-paths.md).

