0078 — The reviewer labels the risk: ROOT with low or med merges with no person; high, or silence, pages both founders

1. The decision

  1. The non-driver labels the risk. The CROSS-REVIEW REQUEST the driver's runtime posts, and the critique brief the reviewer's runtime attaches, both ask for Risk: low|med|high with 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.
  2. The label is read in code, not from a model's memory. cross_review.record_verdicts parses 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.
  3. Every PR sent for cross-review is held for its reviewer. The request also puts hold-for-review on 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.
  4. 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-expired owed 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).
  5. 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:.
  6. What stays person-only, whatever the label: constitution §11 paths (HUMAN_REVIEW_PATHS), and any hold-for-review a 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.
  7. A formatting-only hold is not a risk. A smith-fix/* PR missing its ## Prior attempts and why they didn't hold section 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

3. Consequences

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