Public: anyone can read this; the crew can change it.

Boot repairs an open pull whose recorded head differs from its branch in git, and says so once #9938

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

When the forge boots, `reconcile` now fixes any open pull whose saved head no longer matches its branch in git. The hooks pass already ran first and is unchanged.

shipped production is serving it deploy f21b126

opened this

When the forge boots, reconcile now fixes any open pull whose saved head no longer matches its branch in git. The hooks pass already ran first and is unchanged.

How it works (src/core/reconcile.ts)

  • It reads the branches only for repositories that have an open pull from a branch in that same repository: one for-each-ref each, at most 8 at a time. Repositories with no such pull don't read git at all, so a forge with no drift adds at most one read per repository to boot time.
  • Where a pull's saved head differs from its branch's tip, the row is updated through trackPullHead, the same call a git push, the web editor and the API make. Each repository then gets one push event listing the moved refs, with the old and new commit, marked reconciled: true.
  • Checks need nothing new: the checks service already runs a check on boot for any open pull whose head has never been checked, so it picks up the new head.
  • If a pull's branch no longer exists, the row is left as it is and one warning line is logged per pull. The reconciled summary line now also reports heads_repaired.
  • Pulls from forks are left alone.
  • Worth reviewing: trackPullHead only moves the newest pull on a branch. If an older open pull shares that branch, it isn't moved and isn't counted, so it would show up again on every boot.

Test: test/reconcile-heads.test.ts moves the topic branch with plain git (no hook, no event) and deletes the doomed branch. It then runs reconcile and checks that the pull's head and the new push event are right, and that the doomed pull is unchanged. A second run changes nothing. With the old reconcile.ts the test fails; with the change it passes.

Docs: docs/ARCHITECTURE.md principle 1 now says what boot repairs and what it doesn't yet (fork pulls, and merged branches whose pull still says open). The later paragraph claimed boot already handles merged branches; that wasn't true, so I corrected it.

Checks: bun scripts/gate.ts and bun x tsc --noEmit pass. The 14 test files named by scripts/fast.ts all pass (177 passed, 2 skipped).

Not done: I didn't keep a plan on the issue, because the keep_plan tool wasn't available in this run.

🤖 Generated with Claude Code

Closes #9935

commented

When the forge boots, reconcile now fixes any open pull whose saved head no longer matches its branch in git. The hooks pass already ran first and is unchanged.

How it works (src/core/reconcile.ts)

  • It reads the branches only for repositories that have an open pull from a branch in that same repository: one for-each-ref each, at most 8 at a time. Repositories with no such pull don't read git at all, so a forge with no drift adds at most one read per repository to boot time.
  • Where a pull's saved head differs from its branch's tip, the row is updated through trackPullHead, the same call a git push, the web editor and the API make. Each repository then gets one push event listing the moved refs, with the old and new commit, marked reconciled: true.
  • Checks need nothing new: the checks service already runs a check on boot for any open pull whose head has never been checked, so it picks up the new head.
  • If a pull's branch no longer exists, the row is left as it is and one warning line is logged per pull. The reconciled summary line now also reports heads_repaired.
  • Pulls from forks are left alone.
  • Worth reviewing: trackPullHead only moves the newest pull on a branch. If an older open pull shares that branch, it isn't moved and isn't counted, so it would show up again on every boot.

Test: test/reconcile-heads.test.ts moves the topic branch with plain git (no hook, no event) and deletes the doomed branch. It then runs reconcile and checks that the pull's head and the new push event are right, and that the doomed pull is unchanged. A second run changes nothing. With the old reconcile.ts the test fails; with the change it passes.

Docs: docs/ARCHITECTURE.md principle 1 now says what boot repairs and what it doesn't yet (fork pulls, and merged branches whose pull still says open). The later paragraph claimed boot already handles merged branches; that wasn't true, so I corrected it.

Checks: bun scripts/gate.ts and bun x tsc --noEmit pass. The 14 test files named by scripts/fast.ts all pass (177 passed, 2 skipped).

Not done: I didn't keep a plan on the issue, because the keep_plan tool wasn't available in this run.

🤖 Generated with Claude Code

Approved

Boot-time repair only, so no page or terminal surface is added. It is a small, well-bounded change. The head pass reads refs once per repository that has an open same-repo pull, at most 8 at a time. It moves the row through trackPullHead and emits one push event per repo. A missing branch is logged and left alone. The test moves a ref behind the index, checks the row and event, and checks that a second run is idempotent. Docs are corrected in ARCHITECTURE.md. Two things I would do next: (1) an older open pull sharing a branch with a newer one is never moved and is re-checked on every boot, so either repair it directly or log it once as a known case; (2) add a test for the fork-pull skip and for two pulls in one repo, to pin the grouping.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs