Project Instructions
Problems with a kendex-owned skill go through kendex report; check ownership in the file first.
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.
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 § 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
# 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.
# 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:
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.
3. Decide and repair
Keys a repo decides: 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.
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.
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:
- A non-author review object accepted by the configured trust and state rules.
- A trusted clean-analysis check-run or commit status that proves analysis ran.
- A trusted comment-form pass bound to this head's SHA.
- 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 § Predicate evidence and trust.
Scripts
scripts/validate.sh: validate a consumer installation.--helpscripts/validate-workflow.sh: compare the adopted workflow with the template.--helpscripts/review-predicate.sh: evaluate one head or validate config.--helpscripts/review-writer.sh:workflow_dispatchandscheduleevaluate and converge every open PR;merge_groupposts one queue success, whileWRITER_READ_ONLY=1is 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). Re-vendor PRs: references/vendored-paths.md.