docs(agent-team): close B1 — deploy-before-merge is a committed hard gate, not a manual fallback

Round-3 re-review resolved B2-B6 but flagged B1 still-open: the prior wording left
a 'enforced by hand until the check exists' escape hatch. Reframe B1 as a REQUIRED
Phase-1 build deliverable that blocks the flip (no manual fallback), with the
required-status-check + admin-bypass-disabled branch protection, and a dry-run
faithfulness note (same workflow file/jobs as live, only the privileged if: differs).
This commit is contained in:
Adam Moussa 2026-06-22 17:25:02 -04:00
parent 1bad2d5a76
commit 877739dece

View file

@ -150,14 +150,22 @@ workflow (Phase 3), not only the inert version** (see Phase 3).
- [ ] **Memory/doc update when denylist vectors change** (FIX): adding a denylist vector (here
or later) updates `project_r720_agent_team` memory + the Confluence host page in the SAME
change — the denied set is operational/security-critical, not tribal knowledge.
- [ ] **Deploy-before-merge enforcement — CONCRETE, CI-enforced (B1).** "Deploy" of this change
= the privileged path is *proven on the live box before the workflow PR merges*. Mechanism:
(a) the box exercises a **dispatch dry-run** of the apply/verify workflow (privileged steps
still `if:${{ false }}`) that emits a signed "exercised-on-box" artifact / status; (b) a
**required status check** on the workflow-file PR consumes that proof so the PR is
un-mergeable until the box has run it; (c) NO `--admin` bypass. This makes deploy-then-merge
a gate, not prose. (Until that check exists, deploy-before-merge is enforced by hand +
recorded in the PR — but the gate is the target.)
- [ ] **Deploy-before-merge enforcement — CONCRETE, CI-enforced (B1). REQUIRED Phase-1
deliverable; the flip does not proceed without it (no manual fallback).** "Deploy" of this
change = the privileged path is *proven on the live box before the workflow PR merges*.
Build, in this phase:
- (a) the box exercises a **dispatch dry-run** of the apply/verify workflow (privileged steps
still `if:${{ false }}`) that emits a signed "exercised-on-box" artifact/status. **Dry-run
faithfulness (NIT):** it runs the SAME workflow file and the SAME untrusted build/verify +
pure-code-gate jobs as the live path — ONLY the privileged `if:` differs — so the dry-run
is a faithful proof of the path, not a separate mock.
- (b) a **required status check** on the workflow-file PR consumes that proof, so the PR is
un-mergeable until the box has run it.
- (c) branch-protection set so the required checks **cannot be bypassed by admins** ("do not
allow bypassing the above settings" / include-administrators) — **no `--admin` merge of the
privileged flip** (NIT). This setting is applied in Phase 2 with the rest of the env/protection.
This is the gate; until it is built+green, the flip is blocked. (Owner: 🤖 build; verified in
the Phase-1 `/sh-security-review` + cross-review hard stop.)
- [ ] **Concrete "no write token on the box" audit (B-QUESTION → a real check):** a
test/script asserting the box env + coordinator config hold no `pull-requests:write` /
contents-write token (grep the live env names + assert the App token is only an Actions