commit d6cc4835975303576070a7530aa49a046dc3095f
parent d35e8b52ba7193518ab541914ccf339574180f68
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Sat, 12 Sep 2026 12:14:58 -0400
common+editor: `held` gets a default, because the field it deferred to is gone
one-core-phase-1.md:1218-1222 makes this part of the deletion rather than a
tidy: `sanitizePolicy` refused to default `held` only because an absent key had
somewhere else to ask, and asking was the whole point — a default would have
read a paused corpus as running. With the four retired fields deleted there is
nothing to ask, so the key is filled in, and `defaultHeldFor` is exactly the
reading those fields gave a file that named no gate: free for transcription,
download and digest (all three defaulted false), HELD for backfill, whose
`backfill.enabled` defaulted false and was read INVERTED. The lane has shipped
held since it existed and still does — unarmed and held, which is gate B kept as
two deliberate acts.
Without this, deleting the fields would have silently opened the backfill lane's
gate on every settings.json and every fixture that never named one — the one
reading the deletion could change, and the one the phase-1 note calls out.
Five e2e fixtures said "the backfill lane runs" by spelling `backfill.enabled:
true` — the inverted field, where true meant NOT held. They say it on the lane
now (`autoQueue.backfill.held: false`), including the two lane-runner policies
and the one backfill test whose own `autoQueue` literal replaces the helper's.
channel-line's follows its `enabled` parameter, as the old field did.
common tests 1074: the four pause-migration cases are gone with the function they
covered, and one is added for the lane that ships held.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat:
10 files changed, 133 insertions(+), 52 deletions(-)
diff --git a/common/controller/operationBatch.test.ts b/common/controller/operationBatch.test.ts
@@ -61,11 +61,13 @@ test("the shipped default is off, and holds no disk", () => {
// until an operator says so, and nothing re-downloads media without an
// explicit opt-in.
//
- // "Off" is now the LANE'S ARM, `autoQueue.backfill.enabled`. The
- // `backfill.enabled` this line used to read was the lane's inverted pause
- // field, which slice 1.4 moved to `autoQueue.backfill.held` and S0-pause
- // deleted; an unarmed lane dispatches nothing whatever its gate says.
+ // "Off" is now TWO keys on the lane, and both ship off: the arm
+ // (`autoQueue.backfill.enabled`) and the gate (`autoQueue.backfill.held`,
+ // which `defaultHeldFor` shuts because the `backfill.enabled` this line used
+ // to read was inverted and defaulted false). S0-pause deleted that field; it
+ // did not change what a fresh install does.
assert.equal(defaultSiteSettings().autoQueue.backfill.enabled, false);
+ assert.equal(defaultSiteSettings().autoQueue.backfill.held, true);
const d = defaultBackfill();
assert.equal(d.allowRedownload, false);
assert.equal(d.concurrency, 1);
@@ -275,10 +277,15 @@ test("the backfill lane holds when its gate is shut, and says so", () => {
});
test("an enabled backfill lane with no GPU-bound operation runs at its slots", () => {
+ // Released explicitly: the backfill lane's gate DEFAULTS shut
+ // (`defaultHeldFor`), which is the reading its inverted `backfill.enabled`
+ // always gave a file that named no gate.
const verdict = laneLimit(
- settingsWith({
- backfill: { ...defaultBackfill(), concurrency: 3 },
- }),
+ withGateHeld(
+ settingsWith({ backfill: { ...defaultBackfill(), concurrency: 3 } }),
+ "backfill",
+ false,
+ ),
{
lane: "backfill",
operations: [],
@@ -301,9 +308,11 @@ test("the GPU carve-out is keyed on contendsFor, not on laneFor existing", () =>
// run. Now the declaration itself answers, so an operation with a fixed
// `lane: { contendsFor: "gpu" }` and NO laneFor is caught, and one with a
// laneFor resolving to CPU is not.
- const settings = settingsWith({
- backfill: { ...defaultBackfill(), concurrency: 4 },
- });
+ const settings = withGateHeld(
+ settingsWith({ backfill: { ...defaultBackfill(), concurrency: 4 } }),
+ "backfill",
+ false,
+ );
const cpuOnly = laneLimit(settings, {
lane: "backfill",
operations: [fakeOperation("cpu-op", "cpu")],
@@ -328,9 +337,11 @@ test("the GPU carve-out is keyed on contendsFor, not on laneFor existing", () =>
// two engines allocate the same 8 GB card.
assert.equal(gpuBound.limit, 4, "idle: nothing is transcribing in this process");
const weightless = laneLimit(
- settingsWith({
- backfill: { ...defaultBackfill(), concurrency: 4 },
- }),
+ withGateHeld(
+ settingsWith({ backfill: { ...defaultBackfill(), concurrency: 4 } }),
+ "backfill",
+ false,
+ ),
{
lane: "backfill",
operations: [fakeOperation("gpu-op", "gpu")],
diff --git a/common/jobs/autoQueuePolicy.ts b/common/jobs/autoQueuePolicy.ts
@@ -668,6 +668,23 @@ function defaultOrderFor(lane: AutoQueueKind): AutoQueueOrder {
return lane === "digest" ? "cheapest" : "listed";
}
+// THE DEFAULT GATE FOR A LANE, and only one lane ships held.
+//
+// It is not a new policy — it is the reading the four retired pause fields gave
+// a file that named no gate, preserved. `transcriptionsPaused`,
+// `downloadsPaused` and `digest.digestsPaused` all defaulted false (free);
+// `backfill.enabled` defaulted FALSE and was INVERTED, so the backfill lane has
+// shipped HELD since it existed. S0-pause deleted the fields, which is what
+// makes defaulting this key correct — and required, because until slice 1.4 an
+// absent `held` had somewhere else to ask and now it has not.
+//
+// The backfill lane is therefore off twice over on a fresh install: unarmed
+// (`enabled: false`) and held. That is gate B — never enable the backfill lane
+// against ~66,540 missingInput videos by accident — kept as two deliberate acts.
+function defaultHeldFor(lane: AutoQueueKind): boolean {
+ return lane === "backfill";
+}
+
export function defaultAutoQueuePolicy(
lane: AutoQueueKind = "transcription",
): AutoQueuePolicy {
@@ -677,6 +694,7 @@ export function defaultAutoQueuePolicy(
replaceAutoSubs: false,
order: defaultOrderFor(lane),
snoozeUntil: null,
+ held: defaultHeldFor(lane),
root: defaultRootFor(lane),
};
}
@@ -721,13 +739,14 @@ function sanitizePolicy(value: unknown, lane: AutoQueueKind): AutoQueuePolicy {
? defaultOrderFor(lane)
: sanitizeAutoQueueOrder(r.order),
snoozeUntil: sanitizeSnooze(r.snoozeUntil),
- // A BOOLEAN OR NOTHING. `held` is the lane's pause gate
- // (AutoQueuePolicy.held) and the only spelling of one since S0-pause
- // deleted the four legacy fields it migrated from. Not defaulted: an
- // absent key reads as not held anyway, and `undefined` never reaches the
- // file (JSON.stringify drops it), so a lane nobody has paused stays absent
- // rather than gaining a `"held": false` the operator did not write.
- held: typeof r.held === "boolean" ? r.held : undefined,
+ // THE LANE'S PAUSE GATE, and the only spelling of one since S0-pause deleted
+ // the four legacy fields it migrated from. DEFAULTED, which it deliberately
+ // was not while those fields existed: an absent key used to mean "ask the
+ // retired field", so filling it in here would have read a paused corpus as
+ // running. There is nothing left to ask, and `defaultHeldFor` is the
+ // reading those fields gave a file that named no gate — free everywhere
+ // except backfill, whose field was inverted and defaulted to held.
+ held: typeof r.held === "boolean" ? r.held : defaultHeldFor(lane),
root:
r.root === undefined
? defaultRootFor(lane)
diff --git a/common/lib/autoQueueTypes.ts b/common/lib/autoQueueTypes.ts
@@ -114,17 +114,19 @@ export type AutoQueuePolicy = {
// lib/pauseGates.ts, whose limit()/guard returns 0 so runPool idle-waits. A
// hold, never a stop — see that file's header.
//
- // OPTIONAL, and absent now means NOT HELD. Until slice 1.4 four separate
+ // OPTIONAL IN THE TYPE, FILLED BY THE SANITIZER. Until slice 1.4 four separate
// settings fields carried this — `transcriptionsPaused`, `downloadsPaused`,
// `digest.digestsPaused` and (inverted) `backfill.enabled` — so `undefined`
- // meant "ask the legacy field" and the sanitizer deliberately refused to
- // default it. S0-pause deleted those four, on the precondition that the live
- // settings.json already carried every `held` key, so there is nothing left to
- // ask: `isGateHeld` reads this and only this.
+ // meant "ask the legacy field" and `sanitizePolicy` deliberately refused to
+ // default it: a default would have read a paused corpus as running. S0-pause
+ // deleted those four, on the precondition that the live settings.json already
+ // carried every `held` key, and the default came in with them
+ // (`defaultHeldFor` — free everywhere except backfill, whose field was
+ // inverted and shipped held).
//
- // STILL NOT DEFAULTED, for a smaller reason: `undefined` never reaches the
- // file (JSON.stringify drops it), so a lane that has never been paused stays
- // absent rather than gaining a `"held": false` the operator did not write.
+ // It stays optional because a reader may be handed a PARTIAL settings object
+ // (laneGuards.test.ts casts one), and `isGateHeld` answers `false` for a lane
+ // that carries no key at all rather than throwing.
held?: boolean;
root: AutoQueueGroup;
};
diff --git a/common/lib/pauseGates.test.ts b/common/lib/pauseGates.test.ts
@@ -61,34 +61,39 @@ test("a settings.json still spelling a retired pause field cannot hold a lane",
// four fields — `transcriptionsPaused`, `downloadsPaused`,
// `digest.digestsPaused` and the INVERTED `backfill.enabled`. They are gone
// from SiteSettings, so a hand-edited or long-unwritten file that still
- // carries them is read past: absent is not held, and there is no second
- // opinion left to disagree with the key.
+ // carries them is read past entirely.
//
- // The precondition that made this safe is recorded in one-core-phase-2.md
- // §S0-pause: the live settings.json carried all four `held` keys before the
- // fields went, so nothing that was paused could come back running.
+ // EVERY VALUE BELOW IS THE OPPOSITE OF THE ANSWER, which is what makes this a
+ // test rather than a coincidence: under the old fallback these four said
+ // held/held/held/free, and what comes out is the lane defaults —
+ // free/free/free/held. A reader that still consulted them fails on all four.
+ //
+ // The precondition that made the deletion safe is recorded in
+ // one-core-phase-2.md §S0-pause: the live settings.json carried all four
+ // `held` keys before the fields went, so nothing paused came back running.
const base = defaultSiteSettings();
- for (const lane of LANES) {
- assert.equal(base.autoQueue[lane].held, undefined, `${lane} defaults held`);
- }
const stale = {
...base,
transcriptionsPaused: true,
downloadsPaused: true,
digest: { ...base.digest, digestsPaused: true },
- // `false` was HELD under the old inversion, which is the value most likely
- // to be misread by anything that kept looking.
- backfill: { ...base.backfill, enabled: false },
+ backfill: { ...base.backfill, enabled: true },
} as unknown as SiteSettings;
- for (const lane of LANES) {
- assert.equal(isGateHeld(stale, lane), false, `${lane} read a retired field`);
- }
- // And the key still answers on the same object: the stale fields are inert,
+ assert.deepEqual(
+ LANES.map((lane) => isGateHeld(stale, lane)),
+ [false, false, false, true],
+ );
+ // The lane defaults are where those answers come from, not the stale object.
+ assert.deepEqual(
+ LANES.map((lane) => isGateHeld(base, lane)),
+ [false, false, false, true],
+ );
+ // And the key still answers on the same object: the retired fields are inert,
// not consulted-and-outranked.
assert.equal(isGateHeld(withGateHeld(stale, "digest", true), "digest"), true);
assert.equal(
- isGateHeld(withGateHeld(stale, "backfill", true), "backfill"),
- true,
+ isGateHeld(withGateHeld(stale, "backfill", false), "backfill"),
+ false,
);
});
@@ -113,6 +118,20 @@ test("no sanitizer carries a retired pause field back onto disk", () => {
assert.equal("downloadsPaused" in base, false);
});
+test("the backfill lane ships held, as its inverted field always made it", () => {
+ // The one lane whose default gate is shut, and the reason is continuity: the
+ // retired `backfill.enabled` defaulted FALSE and `isGateHeld` read it
+ // inverted, so every settings.json that never named a gate has read this lane
+ // as held since it existed. `defaultHeldFor` is that reading, kept.
+ const base = defaultSiteSettings();
+ assert.equal(base.autoQueue.backfill.held, true);
+ assert.equal(base.autoQueue.backfill.enabled, false, "and unarmed as well");
+ for (const lane of LANES) {
+ if (lane === "backfill") continue;
+ assert.equal(base.autoQueue[lane].held, false, `${lane} ships free`);
+ }
+});
+
test("holding a lane leaves the rest of its policy alone", () => {
// The bug this forbids: a rebuilt literal instead of a spread would drop the
// lane's other settings on a pause click. It used to guard the sweep's
diff --git a/common/lib/pauseGates.ts b/common/lib/pauseGates.ts
@@ -82,14 +82,15 @@ export function pauseLaneFor(operationId: string): PauseLane | null {
// its pause was the one per-lane switch living somewhere else, in four fields
// with three polarities.
//
-// ABSENT IS NOT HELD, and that is now the whole rule. Slice 1.4 read an absent
+// ONE FIELD ANSWERS, and that is now the whole rule. Slice 1.4 read an absent
// key through the four retired pause fields and `getSettings` copied the answer
// onto the lane; S0-pause deleted both, on the precondition that the live
// settings.json already carried all four `held` keys (it did — the migration
-// had persisted them on its first write). So a file that predates the key, or
-// a hand-written one, reads as NOT held: there is no longer another field that
-// could say otherwise, and inventing a default of `true` would hold four lanes
-// on every fixture that never mentioned a pause.
+// had persisted them on its first write). A file that names no gate is not read
+// past in silence either: `sanitizePolicy` fills the key with `defaultHeldFor`,
+// which is the reading the retired fields gave such a file — free everywhere
+// except backfill, whose field was inverted and shipped held. So this is a
+// `=== true` on a key the sanitizer has already settled.
//
// `autoQueue` is read defensively: laneGuards.test.ts casts a partial object to
// SiteSettings, and this must answer for it the way it always has.
diff --git a/editor/e2e/attribution.spec.ts b/editor/e2e/attribution.spec.ts
@@ -119,6 +119,12 @@ function attributionSettings(over: {
concurrency: 1,
allowRedownload: false,
},
+ // THE LANE'S GATE, SPELLED. It used to be spelled by `backfill.enabled:
+ // true` in the block above — the inverted retired field, where `true` meant
+ // NOT held. S0-pause deleted it, and the lane's gate defaults SHUT
+ // (`defaultHeldFor`), so a fixture that wants the lane to run says so on
+ // the lane.
+ autoQueue: { backfill: { held: false } },
attribution: {
enabled: true,
appId: "ollama-direct",
diff --git a/editor/e2e/backfill.spec.ts b/editor/e2e/backfill.spec.ts
@@ -88,6 +88,12 @@ function backfillSettings(over: {
allowRedownload: false,
...over.backfill,
},
+ // THE LANE'S GATE, SPELLED. It used to be spelled by `backfill.enabled:
+ // true` in the block above — the inverted retired field, where `true` meant
+ // NOT held. S0-pause deleted it, and the lane's gate defaults SHUT
+ // (`defaultHeldFor`), so a fixture that wants the lane to run says so on
+ // the lane.
+ autoQueue: { backfill: { held: false } },
};
}
@@ -1034,6 +1040,9 @@ test("re-acquired audio is handed to auto-transcribe when the policy would repla
await writeSettings({
...backfillSettings({ backfill: { allowRedownload: true } }),
autoQueue: {
+ // Named here because this literal REPLACES backfillSettings' autoQueue,
+ // and the lane's gate defaults shut.
+ backfill: { held: false },
transcription: {
enabled: true,
maxWorkers: 1,
diff --git a/editor/e2e/channel-line.spec.ts b/editor/e2e/channel-line.spec.ts
@@ -57,6 +57,10 @@ function laneSettings(enabled: boolean) {
concurrency: 1,
allowRedownload: false,
},
+ // The lane's gate followed its `enabled` flag when that flag was the
+ // inverted `backfill.enabled`; S0-pause deleted the field, so the same
+ // thing is said on the lane.
+ autoQueue: { backfill: { held: !enabled } },
};
}
diff --git a/editor/e2e/lane-runner.spec.ts b/editor/e2e/lane-runner.spec.ts
@@ -315,7 +315,12 @@ test("the backfill lane runner diarizes, then attributes from that diarization",
await writeFile(resolvePath(dataRel(VIDEO, "audio.mp3")), "fake audio\n");
await writeSettings(
laneSettings({
- autoQueue: { backfill: { enabled: true, maxWorkers: 1, root: CATCH_ALL } },
+ autoQueue: {
+ // `held: false` because the backfill lane's gate defaults SHUT — the
+ // reading its inverted `backfill.enabled` always gave a file that named
+ // no gate, kept when S0-pause deleted the field.
+ backfill: { enabled: true, held: false, maxWorkers: 1, root: CATCH_ALL },
+ },
}),
);
await generateReport(page, CHANNEL);
@@ -374,7 +379,7 @@ test("the digest and backfill lanes dispatch at the same time", async ({
laneSettings({
autoQueue: {
digest: { enabled: true, maxWorkers: 1, root: CATCH_ALL },
- backfill: { enabled: true, maxWorkers: 1, root: CATCH_ALL },
+ backfill: { enabled: true, held: false, maxWorkers: 1, root: CATCH_ALL },
},
}),
);
diff --git a/editor/e2e/widget.spec.ts b/editor/e2e/widget.spec.ts
@@ -78,6 +78,11 @@ const BACKFILL_SETTINGS = {
concurrency: 1,
allowRedownload: false,
},
+ // THE LANE'S GATE, SPELLED — the lane's pause has to start OPEN for the
+ // widget's control to hold it. It used to be spelled by `backfill.enabled:
+ // true` above (the inverted retired field, deleted by S0-pause), and the
+ // gate now defaults shut.
+ autoQueue: { backfill: { held: false } },
};
const TWO_WORKERS = {