Skip to content

Commit ccf0cb4

Browse files
committed
prm: don't attempt remote branch deletion where the proxy blocks it
Close-out step 5 assumed every environment could delete a remote ref, so a proxied web session (Claude Code on the web) burned turns on pushes that can never land: the egress proxy returns HTTP 403 on the git-receive-pack POST carrying a ref deletion, and the GitHub MCP surface exposes no delete verb. Add a one-shot environment probe before the close-out, skip the remote half of step 5 outright when it answers, and defer those branches to /repo_cleanup (its Bucket B enumerates origin branches, so a local sweep picks them up). Also correct the remote-environment note, which claimed step 5 ran "as usual" over gh, and record deferred branches in the ledger alongside deleted ones. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DHmxnBNwDGedeUoRJk9iFz
1 parent f94d216 commit ccf0cb4

2 files changed

Lines changed: 59 additions & 8 deletions

File tree

skills/prm/prm.md

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,16 @@ checkout required. Detect which you are in:
3737
- **Remote (mobile/codex)** — no multi-repo checkout. Resolve the PR from the
3838
argument or by listing candidates (below), and **skip the local-only cleanup**
3939
with a one-line note. Never `cd` into a repo that isn't there.
40+
- **Proxied web session (Claude Code on the web)** — remote as above, **plus it
41+
cannot delete remote branches at all**: the egress proxy refuses ref deletions.
42+
Probe once, before the close-out, and remember the answer for the whole run:
43+
44+
```bash
45+
curl -sf "$HTTPS_PROXY/__agentproxy/status" >/dev/null && echo "ref deletes blocked"
46+
```
47+
48+
An answer means every `git push origin --delete` in this run will fail. Do not
49+
attempt one — see step 5.
4050

4151
## The routine
4252

@@ -119,14 +129,19 @@ step 6. Order is forced by the tooling, so do not reorder:
119129
registered in `active.md` — which is exactly why step 3 comes first.
120130
5. **Branches** — delete the remote `feature/<task>` per proven-merged repo, plus
121131
any local branch left in the canonical checkout. Never delete a branch whose
122-
merge you did not prove in sub-step 1.
132+
merge you did not prove in sub-step 1. **If the environment cannot delete
133+
remote refs** (proxied web session, above), skip the remote half outright and
134+
list those branches in the ledger as deferred to `/repo_cleanup` — never spend
135+
turns on a push the proxy has already refused.
123136
6. **Report the ledger** — PRs merged, issue closed, record path, `active.md`
124-
released, worktree removed, branches deleted, and anything skipped.
137+
released, worktree removed, branches deleted **or deferred**, and anything
138+
skipped.
125139

126-
**Remote (mobile/codex):** sub-steps 1, 2 and 5 run over `gh`/`git ls-remote` as
140+
**Remote (mobile/codex):** sub-steps 1 and 2 run over `gh`/`git ls-remote` as
127141
usual. Mind (3) works if PyAutoMind is checked out; otherwise say the record is
128142
pending. The worktree (4) is local-only — name it as outstanding rather than
129-
implying it ran.
143+
implying it ran. Branches (5) delete normally from mobile and Codex, but **not**
144+
from a proxied web session — there they are deferred, not attempted.
130145

131146
### 6. The only guards that stop you
132147

skills/prm/reference.md

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,40 @@ directory listing is the only way to find it.
189189

190190
### 5. Branches
191191

192-
Local branches go with the worktree; the remote ones do not:
192+
Local branches go with the worktree; the remote ones do not. **First establish
193+
whether this environment may delete remote refs at all** — one probe, once per
194+
run, before any repo:
195+
196+
```bash
197+
curl -sf "$HTTPS_PROXY/__agentproxy/status" >/dev/null && echo "ref deletes blocked"
198+
```
199+
200+
An answer means a proxied web session (Claude Code on the web). There, a ref
201+
deletion dies on the `git-receive-pack` POST:
202+
203+
```
204+
error: RPC failed; HTTP 403 curl 22 The requested URL returned error: 403
205+
send-pack: unexpected disconnect while reading sideband packet
206+
```
207+
208+
That 403 is generated in front of GitHub — the ref advertisement to the same host
209+
seconds earlier returns 200 with an `X-Github-Request-Id`, the 403 carries none —
210+
so credentials, `gh` scopes and branch protection are **not** the cause, and no
211+
retry, repo, or token changes it. The GitHub MCP surface has no delete verb
212+
either (`create_branch` exists; nothing deletes a ref). So in that environment:
213+
delete the local branches if a checkout exists, **skip the remote half entirely**,
214+
and put one line per branch in the ledger:
215+
216+
```
217+
branches: deferred — PyAutoMind claude/<task> (merged, proxy blocks remote delete) → /repo_cleanup
218+
```
219+
220+
`/repo_cleanup` is the destination: its Bucket B enumerates origin branches
221+
directly, so a deferred branch is picked up by the next local sweep. Repo-side,
222+
"Automatically delete head branches" (Settings → General → Pull Requests) removes
223+
the need for the step at all.
224+
225+
Otherwise — local CLI, mobile, Codex — delete as usual:
193226

194227
```bash
195228
git -C <repo> push origin --delete feature/<task>
@@ -198,11 +231,14 @@ git -C <repo> fetch --prune
198231
```
199232

200233
Only branches proven merged in step 1. `git ls-remote --heads origin feature/<task>`
201-
is the ground truth that the delete landed.
234+
is the ground truth that the delete landed. If a delete 403s where you expected it
235+
to work, treat it as the proxied case from that point on: **stop after the first
236+
refusal**, do not repeat it per repo, and defer the rest.
202237

203238
### 6. The ledger
204239

205240
Report, per line: PR(s) merged (URL + `MERGED`), issue closed (number + state),
206241
record path under `complete/<YYYY>/<MM>/`, `active.md` claim released, worktree
207-
removed, branches deleted, and **anything skipped** with the reason. A close-out
208-
that quietly skipped a step reads exactly like one that finished.
242+
removed, branches deleted **or deferred** (with the destination), and **anything
243+
skipped** with the reason. A close-out that quietly skipped a step reads exactly
244+
like one that finished.

0 commit comments

Comments
 (0)