From 8c2ef9618451dcdd87082ceffa28e548d5c9e790 Mon Sep 17 00:00:00 2001 From: Dai Ha Date: Wed, 9 Sep 2026 04:08:43 +0700 Subject: [PATCH] charter template: test a refusal, and do not count a transport failure as one Propagated from claude-bridge CLAUDE.md. The step 8 refusal paragraph told a lead what to do when the forge refuses a merge, but not how to establish that it did. Both halves came from the fleet01 lead, measured on akb/kb on 2026-09-08 UTC. First: it re-ran the all-zeroes head_commit_id probe after the operator granted merge rights, and got HTTP 409 'head out of date' where the same request gave 405 'User not allowed to merge PR' on 2026-09-06. A 409 is payload validation, which is only reachable after the permission gate, so the grant took. The lead reports the repository permissions object did not change at all across that flip -- still admin:false, push:true, pull:true. I did not check that object myself; my forge token is a different identity and would read a different one. Merge rights on a protected branch live in branch protection, so a permissions field is wrong in both directions and only the probe tells them apart. Second: the lead's first probe attempt returned HTTP 000, because GITEA_HOST already carries the scheme and a trailing slash and the URL came out as https://https://git.ltms.dev//api/... A transport failure looks exactly like a refusal if the test is 'not 200'. That is the trap worth naming, because the whole point of the probe is to tell a refusal apart from everything else. Sync check in the claude-bridge addendum reports 'in sync: True'. --- 7-Use-Cases.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/7-Use-Cases.md b/7-Use-Cases.md index 7d0ab67..e65b2df 100644 --- a/7-Use-Cases.md +++ b/7-Use-Cases.md @@ -405,6 +405,12 @@ below are the procedure — run them in order, every task, not only the big ones without having read the diff yourself. A refusal is exactly when that shortcut is tempting, because no action is left that forces you to look, and taking it turns this step into forwarding a reviewer's verdict — which is delegating the merge by proxy, two lines above. + **Test a refusal; do not read it off a permissions field.** A protected branch holds its merge + rights separately from the repository permissions, so that field can say yes while the merge is + refused, and still say no after a grant makes it work. Probe instead, with a request that cannot + succeed on its merits, so a rejection can only mean the refusal. Treat a transport failure as a + third answer that proves nothing: a timeout, a DNS error or a bad URL is not a refusal, and + counting it as one makes you sure of something you never measured. **Steps 3 and 4 are separate on purpose** — spawning and sending in one loop is how parallel work silently becomes serial, and it is the most common way this layer is wasted. For the same reason,