Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit 45a37f16b987efe990b0ab460a84ff0ab1039931
parent 7ab623f66af7d496eaccb8bfcba6d0365aee1bb6
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Sun, 20 Sep 2026 22:58:07 -0400

report fetch: the cached check must clamp at 0, because the fetch does

`--fetch-only --pad P` is [start-P, end+P] measured from the clip, and both
fetchers take Math.max(0, start - padBefore) — a recording has no seconds
before its first. The route's cache check did not, so for any clip within `pad`
seconds of the beginning it asked whether a window holds a NEGATIVE start,
which no file can ever hold. The check could not fire there, and those are
exactly the clips a sweep starts on: the route queued a job whose only finding
was that the bytes were already on the disk.

Found by the new reuse case, which is g01 at 5–25 s and g02 at 10–15 s: g02's
padded ask is [-10, 35] unclamped and [0, 35] clamped, and 0.00–45.00 holds the
second and not the first.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Diffstat:
Mplans/FACTS.md | 9+++++++++
Mumtool/app/api/report/fetch/route.ts | 12+++++++++++-
2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/plans/FACTS.md b/plans/FACTS.md @@ -4221,6 +4221,15 @@ umtool asks the editor for a clip window instead of running yt-dlp through libvpx-vp9 (27 s to cut a 5 s clip, measured) and writes `.webm`. The two copies must stay byte-identical or a window one side fetched is invisible to the other. +- **`/api/report/fetch`'s "already cached" check must CLAMP its wanted start at + 0**, because the fetch does. `build-video.mjs`'s `fetchClip` and + `fetch-via-editor.mjs` both take `Math.max(0, start - padBefore)` — a + recording has no seconds before its first — so asking whether a window holds + a NEGATIVE start asks for something no file can hold. Unclamped, the check + could never fire for a clip within `pad` seconds of the beginning, which is + exactly where a sweep starts; the route queued a job whose only finding was + that the bytes were already there. Pinned by the reuse case in + `umtool/e2e/report-fetch-via-editor.spec.ts`. - **`WIN_EPS = 0.02` and 2 dp naming are a cross-repo contract.** `common/lib/clipWindow.ts` and `umtool/report-to-video/build-video.mjs` both declare them. A request that rounds differently addresses a different file and diff --git a/umtool/app/api/report/fetch/route.ts b/umtool/app/api/report/fetch/route.ts @@ -56,7 +56,17 @@ export async function POST(request: Request) { r.clip, await projectCache(r.project, r.manifest), )) as { from: number; to: number }[]; - const want = { from: Number(r.clip.start) - padBefore, to: Number(r.clip.end) + padAfter }; + // CLAMPED AT 0, because the FETCH clamps at 0 — build-video.mjs's fetchClip + // and fetch-via-editor.mjs both do `Math.max(0, start - padBefore)`, since a + // recording has no seconds before its first. Asking here whether a window + // holds a NEGATIVE start asks for something no file can ever hold, so this + // check could never fire for a clip within `pad` seconds of the beginning — + // and those are exactly the clips a sweep starts on. The route then queued a + // job whose only finding was that the bytes were already there. + const want = { + from: Math.max(0, Number(r.clip.start) - padBefore), + to: Number(r.clip.end) + padAfter, + }; const holds = windows.find((w) => w.from <= want.from + WIN_EPS && w.to >= want.to - WIN_EPS); if (holds) { // What is already there, PER SIDE, in the pads the bench speaks in.