Conversation
License compliance — cleanNo new dependency license findings in this PR. Warn-only (shadow) mode — this check does not block merges yet. Updated automatically by the canonical license compliance workflow. NOTICE presence (advisory)Missing NOTICE (advisory, does not block):
|
The base branch was changed.
31b4a40 to
908a20f
Compare
Review StatusCurrent Status: ❌ PENDING Pending reviews: Needs 1 Management or Team Lead, and 1 more from Management, Team Lead, or Member. |
… 0.9.1 Audit of what bci-whispercpp 0.9.1 offers against what the SDK exposes. The addon is already pinned ^0.9.1, so this is parity work only. Streaming segments lost windowStartTimestep. lib/stream.js attaches it to every segment emitted in `emit: 'delta'` mode, and it is the only thing that maps a segment's window-local timestamps onto the stream timeline — without it a delta consumer cannot place its own output. Stats were diffed against BCIModel.cpp rather than against the SDK's own expectations. The native model emits 15 fields; six never reached callers: processCalls, totalTime, totalWallMs, whisperSampleMs, whisperBatchdMs and whisperPromptMs. Five more were declared and mapped that the model never emits at all — audioDurationMs, realTimeFactor, encoderMs, decoderMs and melSpecMs belong to the asr-ggml engines, so the op was promising a shape that could not arrive. Both directions are corrected. Backend diagnostics now ride the batch terminal frame, reusing the mapping added for asr-ggml. The streaming path is deliberately left alone: the addon does not populate response.stats for streams, so there is nothing to derive a verdict from. detect_language was documented as "not supported natively (rejected by the addon)". It is in the addon's own validWhisperParams; the description was inherited from the asr-ggml schema. Load config and per-call stream options were already at full parity — whisperConfig 16/16, contextParams 4/4, miscConfig 1/1, bciConfig 1/1, and windowTimesteps/hopTimesteps/emit — and are unchanged.
…ep reaches callers The batch terminal frame carried diagnostics on the wire but never attached the profiling symbol, so event.backend stayed empty for bciTranscribe. Attach it the same way the ASR handlers do. bci-reachability.test.ts drives the real handlers: the batch terminal must feed buildOperationEvent's backend, and delta-mode segments must keep windowStartTimestep through the handler output. Both fail against the previous handler and mapper respectively. Also document windowStartTimestep on the streaming session JSDoc.
908a20f to
e3a2dff
Compare
The BCI streaming terminal frame carried no modelExecutionMs, unlike every sibling duplex handler: the stream op measured nothing and returned void. It now times the model work and returns it, and the handler iterates by hand so that return value reaches the terminal frame. Neither BCI operation had a metrics config registered, so the timing and the stats this branch maps were dropped before reaching an event — only the backend diagnostics survived, because those are read unconditionally. Both ops now register one. The new tests fail without either half: one assertion without the timing attach, five without the configs.
The segment type, its mapper and the backend-diagnostics helper are shared with @qvac/bci-whispercpp since this branch, and the stats grouping comment called the whisper.cpp stage timings whisper-only while BCI maps them too. Renames the reachability test to the two names the ASR side established: profiling-backend for the diagnostics, metadata-handlers for the segment.
QVAC E2E — base run in progressRunning: run 35544949877 · suite The |
QVAC E2E — tests changed by this PRThis smoke run additionally covers 2 test(s) that are not tagged Catalog: 526 tests · smoke: 108 · touched by this PR: 3 (1 already in smoke)
2 added test id(s) |
QVAC E2E —
|
QVAC E2E —
|
QVAC E2E —
|
QVAC E2E —
|
QVAC E2E —
|
🎯 What problem does this PR solve?
Gap audit of
@qvac/bci-whispercpp0.9.1 against the SDK surface. Already pinned^0.9.1, so parity work only — no version bump.windowStartTimestep.lib/stream.js:148attaches it to every segment emitted inemit: 'delta'mode, and the addon documents exactly why: a segment's own timestamps are window-local, so this is the only thing that maps them onto the stream timeline. It appeared nowhere in the SDK, leaving delta-mode output unplaceable.processCalls,totalTime,totalWallMs,whisperSampleMs,whisperBatchdMs,whisperPromptMs.audioDurationMs,realTimeFactor,encoderMs,decoderMs,melSpecMswere declared onBciAddonResponseand conditionally spread, butBCIModel.cppemits none of them — they belong to the asr-ggml engines. Harmless at runtime, but the interface promised a shape that cannot arrive.detect_languagewas documented as rejected by the addon. It is in the addon's ownvalidWhisperParams; the wording was inherited from the asr-ggml schema.📝 How does it solve it?
windowStartTimestepis carried on the shared segment shape, and only when the engine sent it — batch segments do not gain a key that would be meaningless.BCIModel.cppactually emits, and all six missing fields are mapped. The five phantom fields are gone.buildAsrBackendDiagnosticsmapping from QVAC-24486 feat[api]: close the SDK gaps against @qvac/asr-ggml 0.5.3 #4564, and the frame attaches the profiling symbol so they land on the profiling event'sbackend. The streaming path is deliberately untouched: the addon does not populateresponse.statsfor streams, so there is no verdict to derive.detect_language's description now matches the validator.Where the stats and diagnostics reach. They are on the batch
bciTranscribeterminal frame, so RPC consumers see them (Python'sbci_transcribeyields that frame) and profiling picks up the diagnostics. The JS convenience functions do not surface them:bciTranscribe()resolves to text or segments only, and neither BCI stream session (JS or Python) has astatsfield. Exposing them there changes the public return shapes, so it is left as a follow-up rather than done here.Verified already at parity and left unchanged:
whisperConfig16/16,contextParams4/4,miscConfig1/1,bciConfig1/1 (day_idx), and the per-call stream optionswindowTimesteps/hopTimesteps/emit(including thehop < windowrefine that mirrors the addon's own check).🧪 How was it tested?
lunteon both packages: clean.contract:export --checkandsdk-python generate.py --check: both exit 0, with both zod copies pinned to the version CI resolves.bci-schemas.test.ts:windowStartTimestepsurvives the mapper and is absent on batch segments; the terminal frame accepts a diagnostics payload; the full emitted stats surface round-trips.bci-reachability.test.tsdrives the real handlers rather than the schemas: the batch terminal frame feedsbuildOperationEvent'sbackend, and delta-mode segments keepwindowStartTimestepthrough the handler output. Each test fails against the code it guards (the handler without the symbol attach, and the mapper without the field).🔌 API Changes
📋 Follow-ups
bciTranscribe()drops the batch terminal frame's stats and diagnostics. Surfacing them means widening its return type, which is an API decision of its own. The stream sessions have nothing to surface until the addon reports stats for streams.computeWERis exported by the addon and surfaced nowhere. Left out on purpose: it is a scoring helper rather than part of the inference path, so exposing it is an API-design call rather than a parity fix.reload()is not a BCI gap. It exists onBCIInterface— the native binding wrapper exposed as theaddonescape hatch — but the publicBCIWhispercppclass has none, and the SDK's reload path callsmodel.reload(...). Widening the whisper-only reload union would not reach BCI.