What is built in v0.3.2
The first MVP: Phase 0's recorder plus most of Phase 1's queue. This page is the reality file: if something is not listed here as built, it does not exist yet, whatever brief v2.0 says.
Tested in Chromium with a fake audio device and a local server replaying OpenRouter responses. Not yet tried on a real Google Meet call or with a real OpenRouter key. The replayed responses are shaped from OpenRouter's documented examples, not recorded. The first real run should record some to replace them (
tests/fixtures/openrouter/README.md).
Built
| Brief v2.0 | What | Where | Tested |
|---|---|---|---|
| 4.1 | Tab capture: stream ID from the side panel's Start click, redeemed in an offscreen document, played back so you keep hearing the meeting, on the output device you chose (setSinkId) | sidepanel.js, offscreen.js | built in Chromium with a fake device standing in for the tab; spike S1, S8 on a real call |
| 4.2 | Microphone: opt-in per meeting, granted once on the options page, separate mute in the panel and on Alt+Shift+M, the "separate from Meet's mute" sentence | options.js, offscreen.js, service-worker.js | built A8: no mic segments when off, none while muted |
| 4.3 | AudioWorklet taps in a 16 kHz context (resampled in JS if Chrome refuses the rate); one sample clock per channel | worklet.js, offscreen.js | built |
| 4.4 | Cuts at pauses: energy against an adaptive floor, 8 s minimum, 600 ms pause, 2 s idle close, 30 s forced cut, silence dropped | lib/vad.js | built 8 unit tests on audio with a known shape |
| 4.5 | Each segment is checked by its bytes before sending; one that fails is kept as invalid, never sent | lib/wav.js, lib/queue.js | built unit and Chromium |
| 5.1 to 5.4 | The request (verbose_json, provider.zdr), fallback to json remembered per model, the errors table, backoff with jitter and Retry-After, the key check on a network-shaped error, leases | lib/openrouter.js, lib/queue.js, lib/db.js | built A4 (no double send under two drains), A7, retry, fallback |
| 6 | Lines from model output kept as returned; gaps shown; You and Meeting by channel; probable-echo and suspect flags; ≈ for times that are a segment's start | lib/transcript.js | built |
| 8 | IndexedDB without a library: meetings, segments, audio apart, lines; unlimitedStorage; retention of transcribed audio; delete a meeting; delete all | lib/db.js | built A12 |
| 9 | The manifest exactly as specified; the validator refuses any other | manifest.json, admin/build/validate.mjs | built |
| 10 | Side panel, options (key test, microphone grant, devices, live model list, retention, provenance), meetings page (play the audio a line came from, retry, export TXT, Markdown, JSON, delete) | sidepanel.*, options.*, meetings.* | built pages load without errors |
| 7 | The debrief: voicedebrief.ai's summary prompt made for a meeting (Key points, Decisions, Actions, Open questions, In one sentence, each point timed), in voicedebrief.ai's four locales' language and tone, google/gemini-3.5-flash by default; probable echoes left out of what the model reads; stored apart from the transcript, which it never changes; rendered as text, never HTML; in the Markdown and JSON exports | lib/prompts.js, lib/debrief.js, meetings.js | built unit and Chromium |
| - | VoiceDebrief alignment: its colour schemes (vendored, five, chosen on the options page, allowlisted), brand and BETA mark, routingHonest and modelCaveat sentences, key guidance. The details | vd-tokens.css, lib/theme.js, every page | built Chromium; the gate refuses a colour outside vd-tokens.css |
| 14 | Session states, stop on tab close, an interrupted capture marked after a restart, the queue resumed by an alarm | service-worker.js | built in part: restart recovery is not yet tested |
Not built yet
- Translation of the transcript as a separate artefact, the declared workflow, and the infographic (brief v2.0, section 7; voicedebrief.ai has all three).
- Edits as a revision layer (6.3). The transcript is read-only.
- A per-meeting budget, and enabling the icon only on Meet pages through
declarativeContent. It is not in the manifest, because a permission nothing uses is a permission too many. - A release zip and the Chrome Web Store.
What the first real call and the v0.3.1 review corrected
v0.3.2 fixes 13 of the review's 18 findings and part of 4 more, and leaves 1 open; Reviews has the status of each, with its test. The first real call answered spike S1: opening the side panel straight from the icon does not let Chrome capture the tab. The icon click is now handled by MeetScribe, which opens the panel and remembers the tab (route b).
What building it corrected
These go into the brief's next version.
- An offscreen document has
chrome.runtimeand nothing else. Brief v2.0 has the offscreen document drain the queue, and the queue reads its settings fromchrome.storage, which does not exist there. The first Chromium run showed segments stuck insending: the error came after the lease was taken. Now the offscreen document asks the service worker for settings, and an unexpected error gives the lease back at once instead of stranding the segment for 90 seconds. - A drain needs a way to hand back a lease on any error, not only on the ones it expects. This was the same incident;
processOnenow wraps the whole send. - The test runner read Node's output, and Node changed it. The first CI run on
devpassed all 38 tests and still failed. GitHub's runner has Node 24, whose default test reporter printsℹ tests 12where Node 22 printed# tests 12when piped, so the runner counted zero tests. It refused, as it was written to: a file that runs no tests is a failure. It now asks for the TAP reporter by name. - The repository's
.gitignorehid the code. GitHub's Python template ignoreslib/andbuild/, soextension/lib/andadmin/build/were left out of the first commits without a word. It was found by checking a fresh clone before the first push of the extension, and replaced. - The microphone's clock starts later than the tab's.
getUserMediatakes time, so the microphone channel's first sample is set from the capture context's current time, not zero. Otherwise a You line would sort before the Meeting line it answers.