docs(external-contrib): v3 — locked Phase 2 decisions, verbose merge msg (Ship Msg 3)

Cleanup pass on the design doc per Ship's Msg 3 review. Two changes, no architecture shifts:

1. Merge commit message updated to locked verbose form:
     "Merge external GitHub PR #{N}: {branch_slug}"
   N derived from gh-pr-{N}/ regex; branch_slug = post-prefix portion. Embeds
   the GitHub PR number explicitly so `git log --merges --grep "#90"` surfaces
   the merge from PR number alone. Drops the v2 "{branch}"-only form.

2. "Open questions for Ship" section collapsed to "Locked decisions" —
   the three Phase 2 items (backout flag, rebase-after-fix scope, merge commit
   message format) were locked in Ship's reply on Msg 2 but the v2 doc still
   framed them as open. Now restated as decisions so Ganymede doesn't re-debate
   resolved items at line-level review.

Diffs reviewable against v2 (commit fa6cceb).
This commit is contained in:
m3taversal 2026-04-28 13:04:09 +01:00
parent fa6cceb9cd
commit 537cfd5ed7

View file

@ -3,11 +3,12 @@
**Author:** Epimetheus **Author:** Epimetheus
**Architecture review:** Ship (owns merge.py, sync-mirror.sh) **Architecture review:** Ship (owns merge.py, sync-mirror.sh)
**Code review:** Ganymede (line-level, post-design-approval) **Code review:** Ganymede (line-level, post-design-approval)
**Status:** Phase 1 sweep-only scope locked (Ship Msg 2/2). Awaiting code review. **Status:** Phase 1 sweep-only scope locked. Phase 2 architecture decisions locked (Ship Msg 3). Awaiting Phase 1 line-level code review.
## Revision log ## Revision log
- **v2 (this revision):** Phase 1 simplified per Ship's Msg 2 — backfill script dropped (sweep IS the backfill), sweep placement specified explicitly as the very first action after initial fetch (ahead of branch-mirror loop AND auto-create-PR block at line ~250). Phase 2 architecture unchanged. - **v3 (this revision):** Cleanup pass per Ship Msg 3 — merge commit message updated to locked verbose form (`"Merge external GitHub PR #{N}: {branch_slug}"`), open-questions section collapsed to "Locked Phase 2 decisions" restating the three resolved outcomes (no longer questions).
- **v2:** Phase 1 simplified per Ship's Msg 2 — backfill script dropped (sweep IS the backfill), sweep placement specified explicitly as the very first action after initial fetch (ahead of branch-mirror loop AND auto-create-PR block at line ~250). Phase 2 architecture unchanged.
- **v1:** Initial draft. - **v1:** Initial draft.
## Problem statement ## Problem statement
@ -90,9 +91,12 @@ async def _merge_no_ff_external(branch: str) -> tuple[bool, str]:
Mechanics: Mechanics:
1. Fetch latest origin/main and origin/{branch} 1. Fetch latest origin/main and origin/{branch}
2. Create scratch worktree at HEAD of origin/main 2. Create scratch worktree at HEAD of origin/main
3. git merge --no-ff origin/{branch} -m "Merge PR: {branch}" 3. Derive: gh_pr_num = re.match(r"gh-pr-(\d+)/", branch).group(1)
4. git push origin HEAD:main branch_slug = branch[len(f"gh-pr-{gh_pr_num}/"):]
5. Cleanup worktree 4. git merge --no-ff origin/{branch} \
-m f"Merge external GitHub PR #{gh_pr_num}: {branch_slug}"
5. git push origin HEAD:main
6. Cleanup worktree
Conflict handling: Conflict handling:
- Entity conflicts: same auto-resolve pattern as cherry-pick - Entity conflicts: same auto-resolve pattern as cherry-pick
@ -108,9 +112,12 @@ async def _merge_no_ff_external(branch: str) -> tuple[bool, str]:
""" """
``` ```
The merge commit message uses the branch name (which contains the GitHub PR The merge commit message format `"Merge external GitHub PR #{N}: {branch_slug}"`
number via the `gh-pr-{N}/...` convention) so post-merge processing can embeds the GitHub PR number explicitly so `git log --merges --grep "#90"`
correlate back to the GitHub PR if needed. surfaces the merge from PR number alone (no branch-name guessing). Branch slug
is the post-`gh-pr-{N}/` portion of the branch (e.g.,
`contributor/arcium-confidential-computing-challenge`) — already in scope at
merge time, no claim-file read needed.
### Bug #2 fix: self-healing sweep at top of sync-mirror cycle ### Bug #2 fix: self-healing sweep at top of sync-mirror cycle
@ -340,29 +347,29 @@ next merge action.
us contributor comments on closed-via-cherry-pick PRs (already partially solves us contributor comments on closed-via-cherry-pick PRs (already partially solves
the UX). Phase 2 adds the "merged" badge. Phase 3 is post-Phase-1 cleanup. the UX). Phase 2 adds the "merged" badge. Phase 3 is post-Phase-1 cleanup.
## Open questions for Ship ## Locked decisions
**Resolved in Msg 2:** **Phase 1 (resolved in Msg 2):**
- ~~`.fork-pr-map` file location~~ → moot, sweep replaces map approach - `.fork-pr-map` file location → moot, sweep replaces map approach
- ~~Phase 1 vs Phase 2 sequencing~~ → separate deploys, sweep-only Phase 1 confirmed - Phase 1 vs Phase 2 sequencing → separate deploys, sweep-only Phase 1
- ~~One-shot backfill script~~ → dropped, sweep IS the backfill - One-shot backfill script → dropped, sweep IS the backfill
- ~~Sweep placement~~ → confirmed: first action after initial fetch, before - Sweep placement → first action after initial fetch, before branch-mirror loop
branch-mirror loop AND auto-create-PR block AND auto-create-PR block
**Still open (Phase 2 architecture):** **Phase 2 (resolved in Msg 2 / Ship reply):**
1. **Backout flag necessary?** I'm including `EXTERNAL_PR_NO_FF_MERGE` config 1. **Backout flag:** `EXTERNAL_PR_NO_FF_MERGE` config flag included, default
flag for fast cutout. Overkill given low-traffic external-PR path? Or `True` after deploy. One config branch in dispatch is cheap insurance with
prudent given Accelerate Solana pressure? hackathon timing risk one week out.
2. **Test plan #5 (rebase-after-fix) scope.** Documenting the silent-ignore as 2. **Rebase-after-fix scope:** silent-ignore as documented in §"Edge case".
acceptable for now. Sufficient for hackathon, or do you want me to add the Eval-reset semantics already handle the recovery path — no structured
structured-alert path before May 5? alert in this scope. Re-evaluate after first 5-10 external contributors.
3. **`merge --no-ff` commit message format.** I have `"Merge PR: {branch}"`. 3. **Merge commit message format:** verbose with PR number —
Better signal to derive the GitHub PR number from the branch and write `"Merge external GitHub PR #{N}: {branch_slug}"`. Branch slug derived from
`"Merge external GitHub PR #{N}: {claim_title_or_branch_slug}"`? Trades the `gh-pr-{N}/` prefix strip; already in scope at merge time, no claim-file
verbosity for searchability in `git log --merges`. read needed. Searchability via `git log --merges --grep "#90"` is the value.
Sending revised doc directly via Pentagon. Ganymede gets line-level review of Ganymede gets line-level review of the Phase 1 sweep code on
the Phase 1 code once Ship signs off on the revised design. `epimetheus/sync-mirror-self-heal` once Ship signs off on this revision.