Review & QA gates
hlix has two gates, and they are not the same thing. Automated QA judges work after it exists. An approval gate stops work before it starts. Every cycle passes the first; the second is a project policy you opt into — plus a set of risk lanes that demand it whether you opted in or not.
When this matters to you
Section titled “When this matters to you”- You want to know what happens between an agent finishing and you seeing the result.
- A cycle failed and you want to know whether it will retry on its own.
- You need a person in the loop before agents touch a production-adjacent project.
- A cycle parked for approval on a project where the gate is switched off.
Gate one: automated QA
Section titled “Gate one: automated QA”Work moves from build through automated QA to an evaluator verdict; a retryable failure loops back to build carrying the evaluator’s feedback, and the human approval gate — off by default — sits between approval and deploy.
Every cycle runs it. No configuration, no opt-out.
intake ──▶ planner ──▶ execute ──▶ QA evaluator ▲ │ │ ├── approved ──▶ deploy │ │ └── optimize ─┤ (retryable) │ └── terminal ──▶ failThe evaluator judges the completed tasks against the plan and the quality criteria and returns a verdict. A retryable problem loops through the optimizer and back into evaluation — the task does not just fail, it gets another pass with the failure as input. A terminal problem fails the cycle with a recorded reason rather than looping forever.
The evaluator’s verdict is visible on the task’s evidence document, alongside the diff it judged:
{"evaluator": {"verdict": "approved", "summary": "…", "headSha": "9f2c1b0…", "stale": false}}stale: true means the branch moved after the evaluator looked. The verdict is still shown — it is just no longer about the current commit. See Reviewing output.
Gate two: human approval
Section titled “Gate two: human approval”Off by default. Setting requiresApproval on a project makes the orchestrator open a blocking deployment_approval request before launching a gated cycle, then park the run until someone decides. Approving resumes dispatch; denying fails that cycle.
With the flag off, an autonomous run is unchanged — the gate adds nothing to a project that has not asked for it. Approvals covers the request queue and how to resolve one.
Lanes that demand a human
Section titled “Lanes that demand a human”Some work is risky enough that a person signs off first, no matter what the project asked for.
Every cycle is classified at Triage into a lane, derived from how well understood the change is and how costly a wrong answer would be. Four of those lanes open the same blocking approval request the project flag would, on their own:
| Lane | The classification behind it |
|---|---|
stop |
Simple but high-risk — a human should plan this before code starts |
design-review |
Ambiguous and high-risk — a senior owner should look at it first |
architecture-review |
Ambiguous and medium-risk — the shape should be agreed before code |
manual-lane |
Systemic and high-risk — there is no automated lane for this |
The lane check runs per cycle, and it ORs with the project setting: whichever says “gate” wins. So a project with approvals off still parks a manual-lane cycle, and a project with approvals on gates everything regardless of lane. The request that opens carries the lane in its context, so the queue tells you why this particular cycle stopped.
The other five lanes — auto, fast-review, plan-gate, experiment, split-work — do not gate. They are recorded classification you can read, filter, and audit on; plan-gate in particular is already satisfied by the planning pass every cycle makes before it executes.
Sending work back yourself
Section titled “Sending work back yourself”Neither gate replaces your judgement. When you read a diff and disagree with it, request-revision folds your unresolved line comments into the task’s feedback and re-enters the cycle, so the worker gets your notes as instructions rather than as a rejection. That is the third loop, and it is the one you drive.
What gets recorded
Section titled “What gets recorded”Three planes carry different promises, and the difference is the point:
| Plane | Answers | Delivery |
|---|---|---|
| Audit log | Who did what, to what, when, from where, with what outcome | Guaranteed and immutable |
| Events | What is happening right now | Best-effort |
| Agent runs and logs | Why a run cost or failed what it did | Best-effort |
The audit log is the one that carries a promise. It is append-only at the database level, partitioned by month, and chained per organization with a row hash, so a tampered or missing row is detectable rather than merely unlikely. GET /v1/api/audit-log/verify checks that chain. Where a mutation is compliance-critical, the state change and its audit row commit in one database transaction — the record cannot exist without the change, or the change without the record.
Reading the audit log requires the workspace owner or admin role.
Where to go next
Section titled “Where to go next”| If you want to… | Read |
|---|---|
| Turn the approval gate on | Approvals |
| See how a cycle gets its lane | Triage |
| Read the diff a gate judged | Reviewing output |
| See what a cycle run does end to end | Cycles |