| … | … | @@ -65,9 +65,23 @@ export async function collectFramesSince ({ getFrame, length, since }) { |
| 65 | 65 | if (!covered && newerFrames.length) { |
| 66 | 66 | const base = newerFrames[0].since |
| 67 | 67 | if (base === null || base === undefined) { |
| 68 | | // Defensive: another producer may genuinely emit a first frame with no prior state. |
| 69 | | covered = true |
| 70 | | anchorRev = null |
| 68 | // ⛔ FROM-GENESIS IS REFUSED, and this is a size argument rather than a correctness one. |
| 69 | // |
| 70 | // The oldest frame we hold declares NO prior state, so the union of every frame is complete and |
| 71 | // walkable on its own — this branch used to serve it. Measured on prod 2026-08-07 (wj62, whose |
| 72 | // firehose genuinely starts with a null `since` after its re-authoring): that answer was |
| 73 | // **202,262 bytes / 719 blocks** against **46,106 bytes / 224 blocks** for the full repo. 4.4x |
| 74 | // LARGER, for the same 168 records. |
| 75 | // |
| 76 | // That is not a fixture artefact, it is structural: the union from genesis contains every block |
| 77 | // the repo has EVER held — every superseded MST node and every deleted record — so it is |
| 78 | // ALWAYS a superset of the current repo. A from-genesis diff can therefore never beat the full |
| 79 | // CAR, and refusing hands the caller the smaller, simpler, complete answer they actually wanted. |
| 80 | // |
| 81 | // Deliberately NOT `covered = true`. My unit fixture never reached this branch (RepoManager.init |
| 82 | // mints an unsequenced genesis commit, so a synthetic repo's first frame carries a real `since`) |
| 83 | // and only a live repo exposed it. See the test named for exactly that. |
| 84 | return { frames: newerFrames, covered: false, anchorRev: null, reason: 'from-genesis' } |
| 71 | 85 | } else if (!newer(base, since)) { |
| 72 | 86 | // The oldest frame we hold builds on a state at or BEFORE what the caller has. There is no commit |
| 73 | 87 | // between the two, so nothing is missing from the middle. |
| … | … | @@ -137,9 +151,15 @@ export async function findCommitBlock ({ getFrame, length, cid, scanLimit = 64 } |
| 137 | 151 | export async function repoDiffSince ({ getFrame, length, since, headCommitCid, headCommitBytes = null, headRev }) { |
| 138 | 152 | if (!since) return { ok: false, reason: 'no since given' } |
| 139 | 153 | if (!length) return { ok: false, reason: 'firehose is empty — no history to diff from' } |
| 140 | | const { frames, covered, anchorRev } = await collectFramesSince({ getFrame, length, since }) |
| 154 | const c = await collectFramesSince({ getFrame, length, since }) |
| 155 | const { frames, covered, anchorRev } = c |
| 141 | 156 | if (!covered) { |
| 142 | | return { ok: false, reason: 'firehose does not reach back to rev ' + since + ' — cannot prove the diff is complete' } |
| 157 | return { |
| 158 | ok: false, |
| 159 | reason: c.reason === 'from-genesis' |
| 160 | ? 'since predates the firehose start — a from-genesis diff is always a superset of the full repo, so the full CAR is smaller and complete' |
| 161 | : 'firehose does not reach back to rev ' + since + ' — cannot prove the diff is complete' |
| 162 | } |
| 143 | 163 | } |
| 144 | 164 | // The head block, located in the firehose rather than supplied. `headCommitBytes` remains accepted so a |
| 145 | 165 | // caller that legitimately holds the bytes (a test, or a producer assembling its own commit) can pass |