0078 — The reviewer labels the risk: ROOT with low or med merges with no person; high, or silence, pages both founders
- Status: Accepted 2026-10-31. Written while the slices are in flight, as ADR-0004 requires. The policy is live on a seat once that seat runs agent-harness main with parts 1, 2 and 4 merged.
- Date: 2026-10-31
- Deciders:
- The rule is Gera's, spoken 2026-10-31: "low/med should be okay high is @ us … the non-driver, so the reviewer should label the risk."
- The scope is the lane's, settled through fable-decide receipt
fa99cac73(RESOLVED, high in both orders). The whole tier goes, including the decider's LOW self-merge, because "the driver never grades its own risk". Keeping §5's self-tiering would leave two release triggers for one hold.
- Systems: team-protocol (agent-harness
cross_review,slack_socket._handle_sibling) and the PR drive's merge gate (agent-harnessactivities/merge_gate,workflows/pr_drive), plus the alert decider's prompt (alert_remediation_prompt§5). - Relation: amends ADR-0071 decision 7. That decision made cross-review advisory: a BANDAGE verdict did not stop a merge. Under this ADR the reviewer's verdict and risk label decide whether the PR merges without a person. ADR-0003 is respected: the seats integrate by a marked Slack post and a GitHub label, never by a call.
1. The decision
- The non-driver labels the risk. The
CROSS-REVIEW REQUESTthe driver's runtime posts, and the critique brief the reviewer's runtime attaches, both ask forRisk: low|med|highwith a one-line reason, next to the one-word verdict (ROOT, BANDAGE or UNSURE). The rubric is one constant,cross_review.RISK_ASK. HIGH covers prod data or migrations, Clara's outward behaviour, auth/tokens/secrets, deletes of live routes or guards, payment or PMS writes, external comms, the AppFolio robot's scripts, and a second loosening of the same alarm within 14 days. When the reviewer is unsure, it is high. The mirror case is the same code: when Trinity drives, Smith's runtime attaches the brief, and Smith answers with a risk label too. - The label is read in code, not from a model's memory.
cross_review.record_verdictsparses the reviewer's reply when it arrives as a sibling message, before the sibling budget can drop it. It reads only a verdict the reply OPENS with: at the start, or right after a requested PR's number. It stores one row per PR, and the latest reply wins. - Every PR sent for cross-review is held for its reviewer. The request also puts
hold-for-reviewon the PR (the driver's hold). The alert decider opens every fix PR with that label already on. No merger lands the PR before the reviewer answers: not the PR drive, not propflowai's merge-hold status, not auto-queue. - The PR drive's merge gate applies the label (
merge_gate._reviewer_risk_arm, asked after the constitution §11 path hold and before the fix contract):- ROOT, risk low or med, recorded after the head commit → the driver's hold is lifted (the label is removed) and the ordinary gate decides: checks green and the bot's 🟢.
- anything else the reviewer said (high, BANDAGE, UNSURE, no readable risk) → held. The drive pages both founders once. If the PR is still held when the drive expires (its 36 h lifetime), the expiry opens a
pr-drive-expiredowed item (ADR-0080), which pages once more at its 6 h bound, about 42 h after the drive started. That second page is ADR-0080's rule for a drive that stopped looking, not a repeat of the first. - no verdict yet → a wait. The drive's own stall window is the reviewer's window. When it runs out, the drive pages both founders and reads the silence as high (fail closed).
- The driver never grades its own risk and never merges. The alert decider's §5 tier (LOW self-merge, HIGH → person) is gone. The decider judges only its confidence and stops at
Mergeable:. - What stays person-only, whatever the label: constitution §11 paths (
HUMAN_REVIEW_PATHS), and anyhold-for-reviewa person or a fence bot put on. Who applied a label is read from the PR's events, never assumed. The driver's hold is a label by the App's bot, or by the PR's author within 30 s of opening (gh pr create --label) or of the request's recorded hold. Any other label since the last removal is a person's. An events read that fails is NOT read as a person's hold: the PR stays held, recoverably, and the gate re-checks on its next poll, so a GitHub blip never pages anyone. - A formatting-only hold is not a risk. A
smith-fix/*PR missing its## Prior attempts and why they didn't holdsection is held without a label. The driver is told to add the section to its own body. The hold lifts once a non-empty section is there.
2. Why this shape
- Why the actor alone could not tell Smith's hold from Gera's. On 2026-10-31, propflowai #24116 and #24092 were each opened by
gera-propflowand labelled bygera-propflowone second later. That was Smith's at-open label, running as the shared user account after the App fallback. A rule of "a human account's label is a person's" would have read Smith's own hold as Gera's and kept it person-only. Event shape (author plus the moment of opening) is what separates them. - Why the label is removed, not skipped. In propflowai the
reviewstatus is held red whilehold-for-reviewis on (dangerous-diff-fence.yml, the merge-hold job). Skipping the label in Smith's gate alone would never merge the PR. Removing it firesunlabeled, which re-runs that job. - Why lifting is safe where the old contract latched. The latch existed because "removing the label hands the PR to the drive, which merges anything pushed after the review." The lift happens only when the reviewer's label is newer than the head commit. Every later head still needs the bot's fresh 🟢, like any PR.
- Why the section hold stopped latching. It never proved the section was true. A regex can see that a heading exists, not that its content is honest, and latching on it turned a formatting gap into a page for a person.
3. Consequences
- Smith's alert fixes that used to self-merge in minutes now wait one reviewer cycle. A Trinity outage pages both founders once per held PR, and once more if the hold outlives the drive (see §1). Both failure modes are latency and noise, never a wrong merge.
- Sequencing: the gate must not require labels before the reviewer is asked for them. Part 1 (the ask and the record) lands first, and part 4 (every fix PR opens held) lands only after part 2 (the gate that lifts the hold).
- Stated gaps:
- Hop cap. A request at the last hop below
AGENT_SIBLING_MAX_HOPSgets an unstamped reply. Off the bridge that reply never reaches_handle_sibling, so the follow-up PR reads as high. - Lift timing. A verdict recorded before a later push does not lift the hold. If the head moves before the lift, the PR waits and then pages.
- Unrequested PRs. A PR opened where no request can be posted (a DM, a cron turn, no sibling) is not held by this rule.
- The 30-second window. A real person who labels a PR within 30 s of its opening, as the author, is indistinguishable from the driver's at-open label, and the reviewer's ROOT + low/med would lift it. Rare (a person labels a PR they opened in the same second, then a reviewer clears it), and stated rather than closed.
- Trinity's seat. Trinity's seat needs Fede's machine to pull main before her requests carry the ask or her gate reads Smith's labels. Until then, Smith's requests still ask her for the label in the posted text.
- Hop cap. A request at the last hop below
- ADR-0056 decision 5 ("by the decider's §5, the robot's scripts are HIGH … a human merges") is amended here. The robot's scripts are on the reviewer's HIGH list, so such a PR is still held for a person, but now on the reviewer's label rather than Smith's own tier. The ✅ it names was retired on 2026-09-12; the drive's page to both founders replaces it.
4. Slices
| Part | What | Repo |
|---|---|---|
| 1 | the request and brief ask for Risk:; the reply is recorded in code |
agent-harness #1769 |
| 2 | the gate: lift on ROOT + low/med, hold and page both founders otherwise; the hold put on with the request | agent-harness #1772 |
| 3 | a missing prior-attempts section is the driver's to fix, never a person's hold | agent-harness #1770, #1773 |
| 4 | the decider's §5: no tier, no self-merge, every fix PR opens held | agent-harness #1771 |