← All features

Verify and reviewAvailable in v0.3.0

Gates

A gate turns “done” into a check with recorded evidence: one checkable result, the command that proves it and the output it must produce. oah gates check runs the CHECK lines through unlazy after you approve them, ticks passing gates with evidence and binds them to their inputs. oah finish refuses unmet gates.

When you need it

An agent saying “done” proves nothing. Without recorded checks you cannot tell what passed, and a later change can quietly break a result that once worked.

How it works

  1. oah gates new <task> writes .oah/tasks/<task>/GATES.md from a template; oah gates lint <task> judges whether each gate can fail.
  2. oah gates check <task> shows the CHECK commands on the first run and waits for your approval (--approve).
  3. unlazy, at the commit oah is tested with, runs the checks. Passing gates are ticked with evidence and bound to their inputs, so a later change to an input makes the gate run again.
  4. GATES.summary.md, written by gates check, is the committed, path-free record; the ledger itself stays out of git.
  5. oah finish refuses unmet gates (OAH_GATES_UNMET). A truly impossible gate is written as ABANDON: G<n> <reason> and handed to you, never deleted.

Example

One gate in a ledger (from Concepts).

- [ ] G1: `python hello.py Ada` prints `Hello, Ada!`
  CHECK: python hello.py Ada
  EXPECT: Hello, Ada!
  EVIDENCE: pending

Requirements

  • unlazy, the gate checker, installed with oah init --with-unlazy; it needs Node.js 16 or newer.
  • CHECK lines must run the same in cmd.exe and sh: call python, node or oah check (for example oah check contains FILE TEXT), not grep or pipes.

Limits and recovery

  • A gate's inputs are tracked files, untracked files that are not ignored, and the run environment. A change to an external service or an ignored untracked file does not make a gate run again, so check those separately.
  • Without unlazy, gate commands refuse (OAH_UNLAZY_MISSING); oah finish --allow-structural finishes on ticked boxes alone and is recorded as unverified.
  • The opt-in Stop hook keeps a Claude Code session from ending while gates are unmet. Limiting it with [gates] stop_agents moves the check to oah finish; it is not lost.
  • A summary that no longer matches gives OAH_GATES_SUMMARY_STALE: run oah gates check <task> and commit the rewritten summary.

Original documents

Related