Renumber spec 001 decision placeholders to D-040–D-051; record the Danish publication

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas WintherandClaude Opus 5.5 committed 2026-10-30 01:47:27 +01:00
1 parent 30969e86b7
commit 0632f7843b
71 files changed
+244 -236

No files matched your search

+2 -2
View File
@@ -77,7 +77,7 @@ describe("BrowserEngine", () => {
expect("modelId" in message).toBe(false);
});
test("forwards the vocabulary hint as `prompt`, and omits an empty one (D-WS2a)", () => {
test("forwards the vocabulary hint as `prompt`, and omits an empty one (D-048)", () => {
const worker = new FakeWorker();
const engine = new BrowserEngine(worker);
void engine.transcribe(new Float32Array(4), { prompt: "Maxwell\nVoid" });
@@ -88,7 +88,7 @@ describe("BrowserEngine", () => {
expect("prompt" in worker.posted[2]!.message).toBe(false);
});
test("forwards the long-form request only when set (D-WS3a)", () => {
test("forwards the long-form request only when set (D-049)", () => {
const worker = new FakeWorker();
const engine = new BrowserEngine(worker);
void engine.transcribe(new Float32Array(4), { longForm: true });
+1 -1
View File
@@ -99,7 +99,7 @@ describe("classifyError", () => {
});
});
describe("classifyError — transcript translation (D-WS4b)", () => {
describe("classifyError — transcript translation (D-045)", () => {
test("out of memory while translating suggests closing tabs, not a smaller Whisper model", () => {
const classified = classifyError("RangeError: Out of memory", { stage: "translate" });
expect(classified.kind).toBe("out-of-memory");
+1 -1
View File
@@ -1,7 +1,7 @@
"""faster_whisper stand-in that reports how server-py/sidecar.py called it.
Lets tests/transcribe.test.ts check the real sidecar's request routing
(D-WS5a: file → BatchedInferencePipeline + VAD, live → sequential) without
(D-047: file → BatchedInferencePipeline + VAD, live → sequential) without
CTranslate2 or model weights. Every segment's text describes the call:
" seq model=<name> loads=<n> <sorted kwargs>" WhisperModel.transcribe
+1 -1
View File
@@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test";
import { join } from "node:path";
import { fitHintToBudget, normalizeHint, PROMPT_TOKEN_BUDGET } from "../src/lib/hint";
// D-WS2a: the server engine truncates the hint in Python (server-py/sidecar.py,
// D-048: the server engine truncates the hint in Python (server-py/sidecar.py,
// with faster-whisper's tokenizer) and the browser engine in TypeScript
// (src/lib/hint.ts, with the Transformers.js tokenizer). Both must apply the
// same rule; with the same deterministic fake tokenizer they must agree
+2 -2
View File
@@ -67,13 +67,13 @@ describe("hint storage", () => {
});
});
describe("fitHintToBudget (D-WS2a truncation rule)", () => {
describe("fitHintToBudget (D-048 truncation rule)", () => {
test("empty hint means no prompt", () => {
expect(fitHintToBudget(" \n", charEncode)).toEqual([]);
});
test("a hint within budget is encoded as a space-led sentence ending in a full stop", () => {
// Measured (D-WS2a): an unterminated list prompt suppresses punctuation
// Measured (D-048): an unterminated list prompt suppresses punctuation
// and triggers repetition loops on smaller models; a full stop does not.
expect(fitHintToBudget("Maxwell\nVoices of the Void", charEncode)).toEqual(
charEncode(" Maxwell, Voices of the Void."),
+4 -4
View File
@@ -329,7 +329,7 @@ describe("live pipeline accuracy (real model, real recordings)", () => {
});
// ---------------------------------------------------------------------------
// Vocabulary hint (D-WS2a): the worker's real prompt code on real weights
// Vocabulary hint (D-048): the worker's real prompt code on real weights
// ---------------------------------------------------------------------------
const HINT = "Maxwell, Voices of the Void, Slenderman, RuneScape, UFO";
@@ -372,7 +372,7 @@ async function transcribeWithHint(
return single.text ?? "";
}
describe("vocabulary hint (real model, D-WS2a)", () => {
describe("vocabulary hint (real model, D-048)", () => {
test.skipIf(!available)(
"a hint keeps the transcript intact, keeps the hinted names, and never leaks into the text",
async () => {
@@ -429,7 +429,7 @@ describe("vocabulary hint (real model, D-WS2a)", () => {
});
// ---------------------------------------------------------------------------
// File-mode accuracy of the long-form pipeline (D-WS3a): Silero VAD chunks,
// File-mode accuracy of the long-form pipeline (D-049): Silero VAD chunks,
// one decode per ≤ 30 s chunk — the path behind "Skip silence". Same
// per-clip bars as the live and chunked file paths above.
// ---------------------------------------------------------------------------
@@ -462,7 +462,7 @@ describe("long-form file pipeline accuracy (real model, real recordings)", () =>
if (clip.language !== "en") {
// "Auto-detect" in the UI: the chunked path forces English here
// (Transformers.js 4.2 has no detection); long-form detects once
// on the first speech chunk and pins it (D-WS3a).
// on the first speech chunk and pins it (D-049).
// Detection must not cost an extra encoder pass: the first
// chunk's decode reuses the encoder output detection computed.
const model = asr.model as unknown as Record<string, unknown>;
+1 -1
View File
@@ -18,7 +18,7 @@ function memoryStorage(initial: Record<string, string> = {}) {
};
}
describe("long-form setting persistence (D-WS3a)", () => {
describe("long-form setting persistence (D-049)", () => {
test("defaults when nothing is stored or storage is unavailable", () => {
expect(loadLongFormChoice(memoryStorage())).toBe(LONG_FORM_DEFAULT);
expect(loadLongFormChoice(null)).toBe(LONG_FORM_DEFAULT);
+1 -1
View File
@@ -75,7 +75,7 @@ describe.skipIf(!available)("Silero VAD on the Transformers.js runtime (real mod
});
});
describe("createWhisperDeps decode with the names-and-terms hint (D-WS2a × D-WS3a)", () => {
describe("createWhisperDeps decode with the names-and-terms hint (D-048 × D-049)", () => {
/** A fake ASR pipeline that records the generate options of each call. */
function fakeAsr() {
const calls: Record<string, unknown>[] = [];
+1 -1
View File
@@ -106,7 +106,7 @@ describe("shouldWarnBeforeLoad", () => {
});
});
describe("desktop-only models (D-WS7a)", () => {
describe("desktop-only models (D-051)", () => {
const parakeet = MODELS.find((model) => model.id === PARAKEET_MODEL_ID)!;
const phone = { userAgent: ANDROID_UA, maxTouchPoints: 5, deviceMemoryGB: 8 };
const ipad = { userAgent: IPAD_DESKTOP_UA, maxTouchPoints: 5, deviceMemoryGB: undefined };
+1 -1
View File
@@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test";
import { fetchModelFile, type ModelFileCacheStorage } from "../src/worker/modelFiles";
import type { LoadProgressMessage } from "../src/worker/protocol";
// Cache-API-backed weight download for the Parakeet path (D-WS7a, D-005).
// Cache-API-backed weight download for the Parakeet path (D-051, D-005).
const URL_A = "https://huggingface.co/org/model/resolve/rev/encoder.onnx";
+8 -8
View File
@@ -39,7 +39,7 @@ describe("MODELS catalog", () => {
"onnx-community/whisper-medium-ONNX",
"onnx-community/whisper-large-v3-turbo",
`${DANISH_MODELS_HF_OWNER}/whisper-small-danish-ONNX`,
// Not Whisper: the D-WS7a Parakeet engine path, last so it never
// Not Whisper: the D-051 Parakeet engine path, last so it never
// becomes anyone's accidental default.
"ysdede/parakeet-tdt-0.6b-v3-onnx",
]);
@@ -80,7 +80,7 @@ describe("MODELS catalog", () => {
});
test("every Whisper model maps to a faster-whisper name for the server engine (D-013)", () => {
// The Danish conversions (D-WS6a) have no faster-whisper alias; their
// The Danish conversions (D-046) have no faster-whisper alias; their
// server-engine name is a Hub repo id — covered by the Danish suite below.
for (const model of WHISPER_MODELS.filter((m) => !m.id.startsWith(`${DANISH_MODELS_HF_OWNER}/`))) {
// The onnx-community ids and faster-whisper's aliases share the same
@@ -98,7 +98,7 @@ describe("MODELS catalog", () => {
});
});
describe("Danish fine-tune conversions (D-WS6a)", () => {
describe("Danish fine-tune conversions (D-046)", () => {
const owner = `${DANISH_MODELS_HF_OWNER}/`;
const danish = MODELS.filter((model) => model.id.startsWith(owner));
@@ -131,7 +131,7 @@ describe("Danish fine-tune conversions (D-WS6a)", () => {
expect(smallDa!.decoderParamsM).toBe(small.decoderParamsM);
});
test("default to the dtypes measured on the converted files (D-WS6a)", () => {
test("default to the dtypes measured on the converted files (D-046)", () => {
// da_festuge on onnxruntime-node: q4 matched or beat q8 and was faster for
// all three, small included; fp16 encoders did not overflow (D-022 check).
for (const model of danish) {
@@ -141,7 +141,7 @@ describe("Danish fine-tune conversions (D-WS6a)", () => {
decoder_model_merged: "q4",
});
expect(resolveDefaultDtype(model.id, "webnn")).toBe("fp16");
expect(model.defaults.wasm.note).toContain("D-WS6a");
expect(model.defaults.wasm.note).toContain("D-046");
}
});
});
@@ -270,7 +270,7 @@ describe("WHISPER_LANGUAGES", () => {
});
});
describe("canTranslate (D-WS4a)", () => {
describe("canTranslate (D-044)", () => {
test("Whisper translate is offered only where OpenAI trained it", () => {
const translating = MODELS.filter((model) => model.canTranslate).map((model) => model.id);
// large-v3-turbo was not trained for translation (OpenAI model card);
@@ -290,7 +290,7 @@ describe("canTranslate (D-WS4a)", () => {
});
});
describe("taskForModel (D-WS4a)", () => {
describe("taskForModel (D-044)", () => {
test("a stale translate resets to transcribe on a model that cannot translate", () => {
expect(taskForModel("onnx-community/whisper-large-v3-turbo", "translate")).toBe("transcribe");
expect(taskForModel("onnx-community/whisper-small.en", "translate")).toBe("transcribe");
@@ -306,7 +306,7 @@ describe("taskForModel (D-WS4a)", () => {
});
});
describe("Parakeet catalog entry (D-WS7a)", () => {
describe("Parakeet catalog entry (D-051)", () => {
const parakeet = getModel(PARAKEET_MODEL_ID)!;
test("family defaults to whisper when absent", () => {
+3 -3
View File
@@ -69,7 +69,7 @@ The worker now caps WASM sessions at `graphOptimizationLevel: "basic"`
outside the browser. **Re-run this step with Backend = WASM to confirm in a
real browser.**
**Update (2026-10-30, D-WS1c):** the Transformers.js 4.3.2 bump brings an
**Update (2026-10-30, D-043):** the Transformers.js 4.3.2 bump brings an
onnxruntime-web build without that bug, so the cap is gone and WASM sessions
run at the default level again. Re-run this step with Backend = WASM (Whisper
Tiny and Tiny.en) to confirm the session still loads in a real browser.
@@ -111,7 +111,7 @@ Result: Works.
Result: Works
## 5. Transcript translation offline (D-WS4b)
## 5. Transcript translation offline (D-045)
1. Online: transcribe anything, open **Translate transcript…**, pick a
direction, click **Translate**. The hint said "Downloads a translation
@@ -129,7 +129,7 @@ Result: Works
Result: _pending (needs a real browser)_
## 6. "Skip silence" (long-form pipeline, D-WS3a/D-WS3b)
## 6. "Skip silence" (long-form pipeline, D-049/D-050)
1. Online, open **Advanced**, tick **Skip silence in uploaded files**, and
transcribe a file. DevTools → Network shows one request for
+1 -1
View File
@@ -15,7 +15,7 @@ import {
import { wordErrorRate } from "./dsp";
/**
* Real-model accuracy of the Parakeet engine path (D-WS7a), opt-in:
* Real-model accuracy of the Parakeet engine path (D-051), opt-in:
*
* PARAKEET_REAL=1 bun test tests/parakeet-real-model.test.ts
*
+1 -1
View File
@@ -12,7 +12,7 @@ import {
} from "../src/lib/parakeet";
import { transcriptToSrt, transcriptToTimestampedTxt } from "../src/lib/export";
// Pure Parakeet engine logic (D-WS7a) — no model, no runtime.
// Pure Parakeet engine logic (D-051) — no model, no runtime.
const RATE = 16_000;
+2 -2
View File
@@ -35,7 +35,7 @@ function tokens(output: unknown): number[] {
return (output as Tensor).tolist()[0]!.map(Number);
}
describe("installPromptSupport (D-WS2a)", () => {
describe("installPromptSupport (D-048)", () => {
test("without a prompt kwarg, generate is called exactly as before", async () => {
const model = fakeModel([50258, 50259, 50360]);
installPromptSupport(model);
@@ -117,7 +117,7 @@ describe("buildPromptPrefix", () => {
]);
});
test("a huge hint stays within the 120-token budget (D-WS2a)", () => {
test("a huge hint stays within the 120-token budget (D-048)", () => {
const prefix = buildPromptPrefix(tokenizer, "Maxwell, ".repeat(500));
expect(prefix.length).toBeLessThanOrEqual(121);
});
+3 -3
View File
@@ -83,7 +83,7 @@ describe("isUiToWorkerMessage", () => {
});
});
describe("choosePipeline (D-WS3a/D-WS3b)", () => {
describe("choosePipeline (D-049/D-050)", () => {
test("long-form only when asked for and the VAD model loaded", () => {
expect(choosePipeline({ longForm: true, vadReady: true })).toBe("longform");
// Offline / never downloaded: the old path, never an error (Review Focus 3).
@@ -248,7 +248,7 @@ describe("deviceAttempts (D-004, D-017)", () => {
});
});
describe("parakeetDeviceAttempts (D-WS7a)", () => {
describe("parakeetDeviceAttempts (D-051)", () => {
const everything = { webnn: true, webgpu: true, webgpuF16: true };
test("auto never picks an accelerator for Parakeet", () => {
@@ -322,7 +322,7 @@ describe("TranscribeProgressTracker", () => {
expect(tracker.finalizeWindow()).toBeNull(); // 20 clamps to 8, not an advance
});
describe("forWindows (variable-length VAD chunks, D-WS3a)", () => {
describe("forWindows (variable-length VAD chunks, D-049)", () => {
// Two speech chunks with a skipped 15 s silence between them: [0–20 s]
// and [35–60 s] of a 70 s file.
const windows = [
+3 -3
View File
@@ -22,7 +22,7 @@ FW_INTEGRATION=1 bun test tests/transcribe.test.ts
Runs the real sidecar end to end (spawn → ready handshake → `tiny.en` load →
transcribe → done), then the first 60 s of `tests/audio_files/en_alien.opus`
(needs `ffmpeg`) in both decoding modes (D-WS5a): `file` (faster-whisper's
(needs `ffmpeg`) in both decoding modes (D-047): `file` (faster-whisper's
`BatchedInferencePipeline` + Silero VAD, what `POST /api/transcribe` uses) and
`live` (sequential, what server-live passes use). First run downloads ~75 MB
of weights from the Hub. Point `SIDECAR_PYTHON` at a virtualenv's python if
@@ -52,11 +52,11 @@ burst, segments in bursts — and cancels a batched run after its first burst.
5. Transcribe the same clip through the server engine.
- [ ] Segments stream in as JSON lines (not one blob at the end). With the
batched pipeline (D-WS5a) they arrive in bursts — one burst per 8
batched pipeline (D-047) they arrive in bursts — one burst per 8
speech chunks (≈ up to 4 min of audio) — with blank heartbeat lines
every 5 s in between; on a clip under ~30 s of speech, everything
arrives as a single segment at the end. Each segment covers one VAD
speech chunk (up to 30 s), not one sentence — expected (D-WS5a).
speech chunk (up to 30 s), not one sentence — expected (D-047).
- [ ] Cancelling a long server transcription (abort / page refresh) stops
the sidecar within one burst; the next request then starts normally.
- [ ] Both transcripts agree in content (minor punctuation/casing drift
+2 -2
View File
@@ -125,7 +125,7 @@ describe("createLiveWebSocket", () => {
// wait for the payload itself, or a loaded machine races past it.
await waitFor(() => sidecar.audioPayloads.length > 0);
expect(sidecar.requests[0]).toEqual(
// Live passes are short: sequential decoding, no batching/VAD (D-WS5a).
// Live passes are short: sequential decoding, no batching/VAD (D-047).
expect.objectContaining({ model: "base", language: "da", task: "translate", mode: "live" }),
);
// The bytes written to the temp file are exactly the committed segment's
@@ -142,7 +142,7 @@ describe("createLiveWebSocket", () => {
await waitFor(async () => (await readdir(tempDir)).length === 0);
});
test("every pass of a session carries the session's vocabulary hint (D-WS2a)", async () => {
test("every pass of a session carries the session's vocabulary hint (D-048)", async () => {
const tempDir = await makeTempDir();
const sidecar = fakeSidecar();
const handler = createLiveWebSocket({ sidecar });
+12 -12
View File
@@ -168,7 +168,7 @@ describe("parseLanguageAndTask", () => {
});
});
describe("parseLanguageAndTask: vocabulary hint (D-WS2a)", () => {
describe("parseLanguageAndTask: vocabulary hint (D-048)", () => {
const parse = (query: string) => parseLanguageAndTask(new URL(`http://localhost/x${query}`));
test("normalizes the hint like the worker does", () => {
@@ -357,7 +357,7 @@ describe("POST /api/transcribe", () => {
});
test("heartbeat blank lines keep a quiet stream alive before the first segment (D-021)", async () => {
// The batched pipeline (D-WS5a) runs VAD over the whole file and decodes a
// The batched pipeline (D-047) runs VAD over the whole file and decodes a
// full batch before its first segment, so the quiet stretch is longer.
const handlers = createTranscribeHandlers({
sidecar: fakeSidecar({ delayMs: 200 }),
@@ -375,7 +375,7 @@ describe("POST /api/transcribe", () => {
expect(text).toContain('"type":"result"');
});
test("passes the vocabulary hint to the sidecar; 400 for an over-long one (D-WS2a)", async () => {
test("passes the vocabulary hint to the sidecar; 400 for an over-long one (D-048)", async () => {
const sidecar = fakeSidecar();
const handlers = createTranscribeHandlers({
sidecar,
@@ -477,7 +477,7 @@ describe("createSidecar (fake python sidecar)", () => {
expect(segments[1]!.text).toContain("model=ok bytes=12 lang=da task=translate");
expect(segments[1]!.text).not.toContain("prompt=");
// The vocabulary hint crosses the JSON-lines protocol intact (D-WS2a).
// The vocabulary hint crosses the JSON-lines protocol intact (D-048).
const prompted: SidecarSegment[] = [];
await sidecar.transcribe(
{ model: "ok", audioPath, prompt: "Århus, Voices of the Void" },
@@ -554,11 +554,11 @@ describe("createSidecar (degradation, D-013)", () => {
// ---------------------------------------------------------------------------
// The real server-py/sidecar.py against a stubbed faster_whisper/numpy
// (tests/fixtures/stub_fw): request routing, model cache, cancel (D-WS5a).
// (tests/fixtures/stub_fw): request routing, model cache, cancel (D-047).
// `-S` keeps real site-packages out, so this runs the same everywhere.
// ---------------------------------------------------------------------------
describe("server-py/sidecar.py (stubbed faster-whisper, D-WS5a)", () => {
describe("server-py/sidecar.py (stubbed faster-whisper, D-047)", () => {
const STUB_DIR = join(import.meta.dir, "fixtures/stub_fw");
const stubbedSidecar = () =>
createSidecar(["env", `PYTHONPATH=${STUB_DIR}`, "python3", "-S", REAL_SIDECAR]);
@@ -590,7 +590,7 @@ describe("server-py/sidecar.py (stubbed faster-whisper, D-WS5a)", () => {
expect(explicit.texts[0]).toContain("batched model=m1");
expect(explicit.texts[0]).toContain("vad_filter=True");
expect(explicit.texts[0]).toContain("batch_size=8");
// Tuned Silero VAD: the default (0.5 / 400 ms) dropped quiet speech (D-WS5a).
// Tuned Silero VAD: the default (0.5 / 400 ms) dropped quiet speech (D-047).
expect(explicit.texts[0]).toContain("vad_parameters={'threshold': 0.2, 'speech_pad_ms': 800}");
expect(explicit.texts[0]).toContain("language=da");
expect(explicit.texts[0]).toContain("task=transcribe");
@@ -599,7 +599,7 @@ describe("server-py/sidecar.py (stubbed faster-whisper, D-WS5a)", () => {
expect(implicit.texts[0]).toContain("batched model=m1");
});
test("the vocabulary hint reaches the batched pipeline as text, and live passes as ids (D-WS2a, D-WS5a)", async () => {
test("the vocabulary hint reaches the batched pipeline as text, and live passes as ids (D-048, D-047)", async () => {
const sidecar = stubbedSidecar();
const file = await run(sidecar, { model: "m1", mode: "file", prompt: "Maxwell, Voices of the Void" });
expect(file.texts).toHaveLength(1);
@@ -611,7 +611,7 @@ describe("server-py/sidecar.py (stubbed faster-whisper, D-WS5a)", () => {
expect(live.texts[0]).toContain("initial_prompt=[32, 77, 97, 120, 119, 101, 108, 108, 46]");
});
test("live mode stays sequential without VAD (short passes, D-WS5a)", async () => {
test("live mode stays sequential without VAD (short passes, D-047)", async () => {
const sidecar = stubbedSidecar();
const { texts } = await run(sidecar, { model: "m1", mode: "live", task: "translate" });
expect(texts[0]).toContain("seq model=m1");
@@ -681,7 +681,7 @@ describe.skipIf(!process.env.FW_INTEGRATION)("real faster-whisper sidecar", () =
);
test(
"file mode (batched + VAD) and live mode both transcribe real speech (D-WS5a)",
"file mode (batched + VAD) and live mode both transcribe real speech (D-047)",
async () => {
const sidecar = createSidecar();
// First 60 s of en_alien as raw float32 16 kHz mono — what the browser uploads.
@@ -718,7 +718,7 @@ describe.skipIf(!process.env.FW_INTEGRATION)("real faster-whisper sidecar", () =
}
test(
"a long file streams in bursts behind heartbeats over HTTP (D-021, D-WS5a)",
"a long file streams in bursts behind heartbeats over HTTP (D-021, D-047)",
async () => {
const handlers = createTranscribeHandlers({
sidecar: createSidecar(),
@@ -756,7 +756,7 @@ describe.skipIf(!process.env.FW_INTEGRATION)("real faster-whisper sidecar", () =
expect(segmentLines.at(-1)!.at - segmentLines[0]!.at).toBeGreaterThan(100);
expect(lines.at(-1)!.line).toContain('"type":"result"');
console.log(
"[D-WS5a] segment arrival (ms):",
"[D-047] segment arrival (ms):",
segmentLines.map(({ at }) => Math.round(at)).join(" "),
);
},
+1 -1
View File
@@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test";
import { renderToStaticMarkup } from "react-dom/server";
import { TranscriptionOptions } from "../src/components/TranscriptionOptions";
// D-WS4a: Whisper's own "Translate to English" only where the model can do it.
// D-044: Whisper's own "Translate to English" only where the model can do it.
function render(canTranslate: boolean): string {
return renderToStaticMarkup(
<TranscriptionOptions
+5 -5
View File
@@ -3,7 +3,7 @@ import { existsSync, readFileSync } from "node:fs";
import { join } from "node:path";
/**
* Tripwires for the patched, pinned Transformers.js runtime (D-WS1a).
* Tripwires for the patched, pinned Transformers.js runtime (D-040).
* `@huggingface/transformers` carries a `bun patch` (D-027/D-028) keyed by
* its exact version; a bump that forgets to regenerate the patch would leave
* the app working but silently bring back the mobile OOM. These checks fail
@@ -48,22 +48,22 @@ describe("@huggingface/transformers runtime", () => {
expect(body).toContain("for (const name of Object.keys(names))");
});
test("Whisper generate still takes the seek loop when max_new_tokens is unset (D-021, D-WS1b)", () => {
test("Whisper generate still takes the seek loop when max_new_tokens is unset (D-021, D-042)", () => {
// The worker's `max_new_tokens: 440` exists only to dodge this branch.
// If upstream changes the condition, re-measure D-021 before touching it.
const source = read(join(PKG_DIR, "src/models/whisper/modeling_whisper.js"));
expect(source).toContain("if (generation_config.return_timestamps && !kwargs.max_new_tokens)");
});
test("onnxruntime-web is the build D-WS1c re-tested 8-bit decoders on at the default optimization level", () => {
test("onnxruntime-web is the build D-043 re-tested 8-bit decoders on at the default optimization level", () => {
// D-014's "basic" cap was dropped because this build loads the q8 merged
// decoders at every graphOptimizationLevel. A different build needs the
// D-WS1c session-creation check re-run before it ships.
// D-043 session-creation check re-run before it ships.
const ortWeb = JSON.parse(read(join(ROOT, "node_modules/onnxruntime-web/package.json"))).version;
expect(ortWeb).toBe("1.31.0-dev.20260914-8d85527a0");
});
test("worker leaves WASM sessions at the default graph optimization level (D-WS1c)", () => {
test("worker leaves WASM sessions at the default graph optimization level (D-043)", () => {
const worker = read(join(ROOT, "src/worker/inference.worker.ts"));
expect(worker).not.toContain("graphOptimizationLevel");
});
+1 -1
View File
@@ -9,7 +9,7 @@ import {
import { loadOpusMt, type OpusMtTranslator } from "../src/worker/opusMt";
/**
* Real Opus-MT translation on onnxruntime-node (D-WS4b), opt-in:
* Real Opus-MT translation on onnxruntime-node (D-045), opt-in:
*
* MT_INTEGRATION=1 flock /tmp/whisper-heavy.lock bun test tests/translate-real-model.test.ts
*
+1 -1
View File
@@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test";
import { renderToStaticMarkup } from "react-dom/server";
import { TranslatePanel, translateStatusText } from "../src/components/TranslatePanel";
// D-WS4b: the panel's copy, before any worker exists (static render).
// D-045: the panel's copy, before any worker exists (static render).
const danish = { text: "Det er ikke noget med at vi skal på ferie.", chunks: [] };
function render(downloaded: string[] = [], hint?: string) {
+1 -1
View File
@@ -12,7 +12,7 @@ import {
} from "../src/lib/translation";
import type { TranscriptChunk } from "../src/worker/protocol";
// Pure planning for transcript translation (D-WS4b) — no model, no network.
// Pure planning for transcript translation (D-045) — no model, no network.
describe("translateUnits", () => {
test("translates every piece in order, batched, and rejoins per unit", async () => {
+1 -1
View File
@@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test";
import { join } from "node:path";
import { ortAliasPlugin } from "../scripts/ortAlias";
// D-WS7a: the Parakeet path must not bring a second onnxruntime into the
// D-051: the Parakeet path must not bring a second onnxruntime into the
// inference worker. parakeet.js depends on its own onnxruntime-web (1.24.1);
// the app runs the one Transformers.js pins. Unminified bundles carry a
// `// node_modules/<path>` comment per bundled module, so count runtimes.