Skip to content

Commit 47634af

Browse files
docs/lessons.md: stacked-PR base-deletion trap + relay branch-name collision; CLAUDE.md: relay convention now specifies unique per-session suffix
1 parent fdc29e1 commit 47634af

2 files changed

Lines changed: 44 additions & 0 deletions

File tree

CLAUDE.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,15 @@ partial work reports in the same structure ("WHAT SHIPPED: nothing —
8787
blocked at step N because X"). Applies to every hold point, completion,
8888
status update, and blocker report.
8989

90+
For any report longer than ~10 lines, or whenever normal message
91+
delivery has been unreliable: commit the fenced block to a
92+
`docs/reports/<date>-<topic>.md` file on a short-lived, **per-session
93+
uniquely-suffixed** branch (never the bare `report-relay` — it's
94+
retired; two independent sessions collided on it with no push
95+
conflict to warn either one), push, and reply with only the branch
96+
name, file path, and one header line. See [[docs/lessons.md]] for the
97+
collision this prevents.
98+
9099
## docs/ index
91100

92101
This is a flat working index for Claude Code sessions. For an

docs/lessons.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,3 +406,38 @@ method that actually worked after `page.on(console/pageerror)` came up empty: ad
406406
calls at the very top of each component in the suspect render tree (starting from the root) to
407407
binary-search how far the tree actually renders before going silent - the last log line reached
408408
pinpoints the synchronous throw's rough location even when nothing else in the stack reports it.
409+
410+
## A stacked PR's base branch gets deleted out from under it when the parent merges (squash-and-delete)
411+
412+
If PR B is opened against PR A's branch (a stack) and PR A is later squash-merged with
413+
`--delete-branch`, GitHub does NOT retarget B to the repo's default branch - it auto-CLOSES B
414+
instead, the moment A's branch disappears (confirmed via `gh pr view`: `state: CLOSED`,
415+
`mergeStateStatus: DIRTY`, immediately after A's merge, not something B's author did). Worse:
416+
the GitHub API then refuses to reopen a PR whose base branch was deleted at all - a direct
417+
`state cannot be changed` 422, not a `gh` CLI limitation, not something worth retrying a
418+
different way. Confirmed live (`claude/e2-bleed-prior-batch-resolution`, PR #69, stacked on PR
419+
#66's branch): #66 merged, #69 auto-closed, reopen attempts 422'd twice (once for `state=open`
420+
alone, once combined with `base=master`). Recovery: the _head_ branch survives (only the base
421+
branch was deleted) - preserve the closed PR's title/body, open a brand-new PR from the same
422+
head branch against `master` directly (became #72), then resolve whatever real merge conflict
423+
appears (git sees the parent's squash commit as unrelated history to what the child branch was
424+
built on, even though the content is logically the same - expect at least one real conflict, not
425+
a fast-forward). **Prevention, the actual fix**: retarget the child PR to `master` (`gh pr edit --base master` / a REST `PATCH .../pulls/N -f base=master`) BEFORE merging+deleting the parent's
426+
branch, while the retarget API call still works normally - not after.
427+
428+
## Cross-session branch-name collisions on a "standing convention" name
429+
430+
Once a delivery pattern (e.g. "commit reports to a `report-relay` branch, relay the URL") gets
431+
adopted as a _standing_ convention rather than a one-off, multiple independent sessions on this
432+
box will reach for the exact same bare branch name for their own unrelated work - confirmed live:
433+
a second, unrelated session pushed 5 more commits (upstream-ladder CI, federation-v1 doc updates)
434+
on top of this session's own single report commit on a bare `report-relay` branch, with no
435+
warning or conflict at push time (git branches don't lock; two sessions can both fast-forward the
436+
same ref from their own local history without either one noticing the other's commits landed
437+
first, as long as neither force-pushes). Confirmed via `git log <branch> --oneline`: the last
438+
commit either session recognizes, followed by commits from a different narrative it never wrote.
439+
**Fix**: every session's first relay push must use a branch name unique to that session, not the
440+
convention's bare name - a numeric/date/session-id suffix, chosen so two concurrent sessions
441+
adopting the same convention independently can't collide (a fixed default like a bare
442+
`report-relay` is exactly the thing every session will reach for identically). The bare
443+
`report-relay` name itself is now retired for this reason - always suffix.

0 commit comments

Comments
 (0)