Gates and the acceptance list
How a run stops at a human gate; approve, send back or reject, what the next pass reruns, how the acceptance list is graded and edited, and how a conductor proposes it.
A human gate holds a run until the operator decides. The operator approves (which lands the work), sends it back with a reason, or rejects it. Review grades the run's acceptance list, and the operator can edit that list at the gate. File:line citations are in parentheses; "not checked" means the code was not read for that fact.
01the shipped gate#
The ticket template's gate is human_gate (internal/harness/ticket-completion.yaml:378-385) with this config:
| key | value |
|---|---|
prompt |
approve this evidence-bearing ticket completion or redirect it |
approve_label |
approve & land |
approved_outlet |
approved, cord to land (yaml:495) |
rejected_outlet |
revise, cord to work (yaml:494) |
decision_field |
human_decision |
The shipped gate sets none of the optional show, title or step keys. What each config key does is on nodes. Cords into the gate include second-off (yaml:486), second-gate and revise-human; a spent loop arrives with loop_exhausted (feedback loops).
02approve, send back and reject#
- Approve: the baton goes to
land(yaml:495,yaml:381). An approve is refused while an area that holds the gate has files the operator has not ticked as looked at; a send back never waits. - Send back: the operator must give a reason (error
service.ErrGateReason). The reason is written intodecision_field, so the next pass reads it ashuman_decision. The run goes on with a fresh revise count (feedback loops). - Reject: the run ends as
rejectedwith nothing landed, and its tickets go back to todo with the reason as a comment. A reason is required, and any scope edit sent with a reject is ignored (; the card text is). - Rebase first: a send back can first move the run's workspace onto main. A path changed by main that the run also changed refuses the send back and nothing is touched.
- Who can press: the window's gate card, the Discord buttons and autopilot all decide a gate. Only the window's press can carry a scope edit.
The statuses and journal events for these are gate.requested, gate.resolved and gate.rejected on runs. run_gates lists a run's pending gates with their payload and the decisions made. gate_summary gives one run's gate in about 2 KB: the prompt, accepted, needs_human, each acceptance item met or not, each check, the worker's doubts and the start of review_feedback.
03the acceptance list#
The planner returns review_acceptance_checks and operator_checks (yaml:105-150).
review_acceptance_checksis what review grades.operator_checksare things only the operator can check, and review skips them (yaml:117-118,yaml:266).- Review returns
item_verdicts: one entry per review_acceptance_check, in order, with its 1-based item number, met true or false, and a note (yaml:272-275).
04scope edits#
At the gate the operator edits the list item by item as part of the decision.
| action | effect |
|---|---|
| keep | the item stays; with as it is reworded |
| drop | the item leaves the list |
| move | the item goes to another ticket; a new ticket is filed in the run ticket's phase, an existing one gets a comment. Nothing is written until the operator presses |
| add | the operator's own item joins the list |
| drop a batch ticket | the ticket leaves the run whole and goes back to todo; at least one ticket stays |
- Operator checks are edited the same way, after the graded items.
- The edit must match the list the gate holds, and at least one item must remain for review to grade.
- The gate writes the edited list into the baton as
review_acceptance_checks, so review grades only it from then on. The planner's original list stays in the journal. - Review is told the change as counts only, so the text of an item that left the list never reaches the model grading it (; reviewer prompt
yaml:264-265). - Prose at the gate does not change the list. Only a scope edit does.
05can propose_send_back carry a scope edit#
No. propose_send_back takes the run, a why and a reason, and nothing else. Pressing its card sends the reason and an optional rebase only, and the desk decides the gate with the reason alone (DecideRunGate with no scope). The proposal press has no scope field for a gate (; its scope is only a permission card's "session").
A scope edit is taken from one place, the window's gate card route /api/desk/gate/decide (to), and only when the press source is the window. Discord and autopilot presses carry none.
No propose_ card or desk tool proposes a scope edit. A conductor can only say in words which items to keep, drop or move, so the operator makes the edit on the gate card.
06what the next pass reruns after a send back#
- The send back cord goes from
human_gaterevisetowork, delivered aslatest(yaml:494). The only other cord out of the gate goes toland(yaml:495). The planner is not re-run and the list is not re-planned. Work resumes withhuman_decisionamong its inputs (yaml:177). - What runs after
workis the template's normal path (checks, then review). The cords after work were not read for this page, so the exact nodes are not checked. - Review reads the reason as outstanding requirements and will not accept while any is unmet (
yaml:259-263). - But
item_verdictshave one entry perreview_acceptance_check(yaml:272-273). A send back reason therefore never becomes a new graded item. It is read as prose next to the list, not added to it. - Only a scope edit at the gate changes what review grades. An item added there (
add) becomes a graded item.
07when you're the conductor#
- A new requirement given only as send back prose is not graded as an acceptance item unless it is added to the list at the gate. If you want it graded, tell the operator to add it on the gate card.
- You cannot attach a scope edit to
propose_send_back. Propose the send back for the reason, and say in your why which items to keep, drop or move on the gate card. - The ticket's rule: at a first gate with under half its items met, propose a scope move rather than a full send back. The code only supports the direction (: "if it's scope, edit the list on the gate rather than explaining it: review grades the list"); the half threshold itself is not checked in code.
- Check the gate with
gate_summarybefore reacting, and read the acceptance items in full when the news line was cut. - Use
propose_rejectonly for work that should not land at all. It ends the run and puts the ticket back to todo.