Archilyzer · Source

archilyzer

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

commit 0d9116019a8baae2aa813146a9f04314df379641
parent 5bd1d69241df58fa9a80e1a8089c70e16b910c5a
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Fri,  2 Oct 2026 01:09:32 -0400

common, editor: the re-point names migrate-tier for a legacy channel; the reconcile spec's changed file differs in length

A legacy channel on a location is refused by the re-point preflight with the
migrate-tier sentence (it has no media link to rewrite). The reconcile case's
changed live chat now differs in size too: rsync's quick check compares size
and a one-second mtime.

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

Diffstat:
Mcommon/controller/storageLocations.test.ts | 24++++++++++++++++++++++++
Mcommon/controller/storageLocations.ts | 10++++++++++
Meditor/e2e/channel-storage.spec.ts | 5++++-
3 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/common/controller/storageLocations.test.ts b/common/controller/storageLocations.test.ts @@ -187,6 +187,30 @@ test("channelsOnLocation buckets ok / unreachable / moving and ignores channels }); }); +test("re-point refuses a legacy channel on the location, naming migrate-tier", async () => { + await withTmp(async (h) => { + const oldTarget = path.join(h.rootA, "old", "data"); + await mkdir(oldTarget, { recursive: true }); + await mkdir(path.join(h.rootB, "old", "data"), { recursive: true }); + const oldDir = path.join(h.paths.channelsDir, "old"); + await mkdir(oldDir, { recursive: true }); + await writeFile( + path.join(oldDir, "config.json"), + JSON.stringify({ handling: "transcribe", url: "https://x/o", dataDir: oldTarget }) + "\n", + ); + await symlink(oldTarget, path.join(oldDir, "data")); + await setLocations(h, [loc("a", h.rootA)]); + const pre = await preflightRepoint({ + paths: h.paths, + locationId: "a", + newRoot: h.rootB, + io: h.io, + }); + assert.equal(pre.ok, false); + assert.match(pre.problems.join("\n"), /old: .*archilyzer storage migrate-tier old/); + }); +}); + // THE RETIRED LAYOUT (release 17): a channel whose whole `data/` was moved // before the media tier is still ON its location (by its retired `dataDir`), // counted unreachable — its text and media are held until migrate-tier — and diff --git a/common/controller/storageLocations.ts b/common/controller/storageLocations.ts @@ -613,6 +613,16 @@ export async function preflightRepoint(opts: { slug, relocatedMediaDir(newRoot, slug), ); + // THE RETIRED LAYOUT (release 17) is migrated, never re-pointed: its + // `data` link is not the media link a re-point rewrites. + if (media.status === "legacy") { + base.problems.push( + `${slug}: ${media.detail ?? "its media layout is the retired whole-directory one"}. ` + + `A re-point rewrites the media link, which this channel does not ` + + `have until it is migrated.`, + ); + continue; + } if (!resumable && media.status !== "ok" && media.status !== "unreachable") { base.problems.push( `${slug}: its media reads as ${media.status} — ` + diff --git a/editor/e2e/channel-storage.spec.ts b/editor/e2e/channel-storage.spec.ts @@ -1010,9 +1010,12 @@ test("Reconcile and resume settles an extra and a changed file on the destinatio const scratch = join(target, VIDEO, ".audio.mp3.parakeet"); await mkdir(scratch, { recursive: true }); await writeFile(join(scratch, "meta.json"), "{}"); + // A different LENGTH as well as different words: rsync's quick check + // compares size and a one-second mtime, and both files were written within + // the same second. await writeFile( join(target, VIDEO, "transcript.live_chat.json"), - '[{"stale":true}]', + '[{"stale":true,"from":"an older copy"}]', ); await writeFile( resolvePath(`test-transcripts/channels/${SLUG}/.relocating.json`),