diff --git a/.claude/memory/MEMORY.md b/.claude/memory/MEMORY.md index 9f678d0..f776d9f 100644 --- a/.claude/memory/MEMORY.md +++ b/.claude/memory/MEMORY.md @@ -8,6 +8,7 @@ Keep this file under 200 lines — anything longer is content bloat, not memory. - [learnings/vercel-blocks-unknown-author-email](learnings/2026-05-26-vercel-blocks-unknown-author-email.md) — Vercel preview deploys block when commit author email has no GitHub account; use the noreply alias - [learnings/sandbox-cant-clone-private-repo](learnings/2026-05-26-sandbox-cant-clone-private-repo.md) — Don't `git clone` from sandbox bash; the `github_repository` resource is auth'd, raw `git clone` is not - [learnings/github-mcp-strips-html-comments](learnings/2026-05-26-github-mcp-strips-html-comments.md) — `update_pull_request` silently strips `` from PR bodies; session-id marker can't be set by agent (ENG-25) +- [learnings/recheck-open-prs-at-pr-open](learnings/2026-05-26-recheck-open-prs-at-pr-open.md) — session-start grep is insufficient; re-grep `list_pull_requests` right before `create_pull_request` to catch parallel-session races (PR #18 vs #20 ENG-25) ## Decisions - [decisions/mcp-for-small-writes-checkout-for-big](decisions/2026-05-26-mcp-for-small-writes-checkout-for-big.md) — Single-file writes go through GitHub MCP; multi-file or test-needing changes use the mounted checkout + `git push` diff --git a/.claude/memory/learnings/2026-05-26-recheck-open-prs-at-pr-open.md b/.claude/memory/learnings/2026-05-26-recheck-open-prs-at-pr-open.md new file mode 100644 index 0000000..12b25bb --- /dev/null +++ b/.claude/memory/learnings/2026-05-26-recheck-open-prs-at-pr-open.md @@ -0,0 +1 @@ +The `check-open-pr-before-ticket-pickup` convention (one `list_pull_requests` + grep before `git checkout -b`) is **not sufficient** when two sessions wake up for the same ticket within the same wall-clock minute. Today PR #18 (10:04:47Z, `sesn_01EhZHPuoB16G5mANW6B6b7U`) and PR #20 (10:07:21Z, `sesn_012j21sUvdmnhx3baX6ivYLW`) both shipped ENG-25 with ~2.5 min between PR-open events. The second session's session-start grep ran before #18 was indexed/visible, so the check passed and the dup got opened anyway — same root cause as the PR #15 vs #16 ENG-26 race that prompted the original convention. Mitigation: **re-grep `list_pull_requests` immediately before calling `create_pull_request`**, not just at session start. If a dup appeared mid-session, the later session aborts with a "closing as race-loser, see PR #X" Linear comment and stops, even if local code is already written. The cost is one extra MCP call per ticket pickup; the upside is preventing another ENG-27-style cleanup ticket every time two sessions race. Upstream fix (only spawn one session per ticket) belongs in the orchestration layer, not this codebase.