Fetch missing source notes from the HTTP backend before the git refs fetch#1975
Fetch missing source notes from the HTTP backend before the git refs fetch#1975scouredimage wants to merge 3 commits into
Conversation
When a rewrite needs source notes that are not in the local notes-db cache, fetch_missing_notes_for_commits only tried a git refs fetch of refs/notes/ai from each remote. On the HTTP notes backend that fetch is the wrong tool: the server — not refs — is the source of truth, and the fetch requires SSH auth that is not available in every daemon environment. In production this stranded authorship notes at scale: restacks failed translation with 'failed to fetch authorship notes for source commits [...]: Permission denied (publickey)' even though the backend held every source note. Add warm_cache_for_commits, which batch-fetches specific SHAs from the HTTP backend into notes-db as synced rows (sharing the fetch/cache core with warm_cache_for_remote), and call it for the missing sources before falling back to the refs fetch. The refs fetch and the missing-note error contract are unchanged for the git-notes backend. Co-Authored-By: Claude Fable 5 <[email protected]>
|
One clarification that strengthens the motivation here: on an HTTP-backend deployment the git refs fetch in |
Problem
When a rewrite (rebase/restack/cherry-pick) needs source notes that are not in the local notes-db cache,
fetch_missing_notes_for_commitshas exactly one recovery path: a git refs fetch ofrefs/notes/aifrom each remote. On the HTTP notes backend that is the wrong tool twice over:refs/notes/ai— is the source of truth, so the refs fetch often has nothing to offer even when the backend holds every note;git fetchmay not see the user's SSH agent).Observed at scale in a large deployment: dozens of restacked PRs permanently lost AI attribution because translation aborted with
…while the HTTP backend held every single source note. #1887/#1888 made the presence check backend-aware (cached sources skip the network), but sources missing from the local cache still funnel into the SSH-only fetch.
Fix
notes_api::warm_cache_for_commits(shas): batch-fetches specific SHAs from the HTTP backend into notes-db as already-synced rows. Shares the fetch/cache core (fetch_and_cache_notes) and the cached-SHA filter withwarm_cache_for_remote, whose behavior and logging are unchanged.fetch_missing_notes_for_commits: when the HTTP backend is enabled, pull the missing sources from it first; if that covers everything, done — no refs fetch, no SSH. Otherwise fall through to the existing refs fetch and the existing still-missing error contract (unchanged for the git-notes backend).Constant git cost: zero new git spawns — the backend fetch is one HTTP call per 100 SHAs and a notes-db write.
Tests
fetch_missing_notes_pulls_sources_from_http_backend_when_refs_fetch_fails— repo with a remote whose fetch always fails (stand-in for broken SSH auth), note available only on a mock backend server: previously returned the stranding error, now succeeds and caches the note as synced. Red without the fix (verified by disabling the new path), green with it.fetch_missing_notes_still_errors_when_backend_lacks_note— when neither the backend nor any remote has the note, the loud failure with the missing SHAs is preserved.warm_cache_for_remote_*and notes_api cache tests pass unchanged.Related: #1961 replays rebases that completed while no daemon was observing; its replay funnels through this same fetch, so the two fixes compose — #1961 finds the missed rewrite, this PR lets its note translation succeed without SSH.
🤖 Generated with Claude Code