Build Tactiq

YESreplaces $12/mosaves $144/yrback to the verdict

0%0 of 20 items done

Saved on this device only. Tick prerequisites first, then work the phases in order · do not start one until the checks above it pass.

A browser extension that reads the meeting platform's own live captions, a local store that cleans and speaker-labels the transcript, notes generated on demand with every claim citing a moment, and an import path for recordings when captions were not available.

estimated effort multi-daythe files for this build are in the project pack

CaptureA browser extension observing the caption region of the meeting pageRuntimeTypeScript with a local application and SQLiteFallbackwhisper.cpp for imported recordingsSpeakersLabels from the platform where it provides them, corrected by handNotesGenerated on demand with segment citations

Before step 1

Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.

  1. installfree

    Why Runs the local application and builds the extension.

    Get it nodejs.org, or nvm install 22. open ↗

    Verify node --version prints v22 or higher

  2. decidefree to read; an hour of advice if this is for work

    Why The rules apply to the recording rather than the mechanism, and several jurisdictions require every participant to agree. Capturing invisibly does not change that.

    Get it Identify where participants typically join from, take the strictest applicable rule, and record what you concluded and when.

    Verify A written note names the jurisdictions and the rule applied

  3. have readyfree with an existing account

    Why The extension reads that platform's caption region specifically, and every platform renders them differently.

    Get it Whichever you actually meet on. Turn captions on and observe how the region updates before writing any code.

    Verify Captions appear and you can identify their elements in the page

  4. have readyfree

    Why Caption revision, interleaved speakers and platform quirks only appear in real conversation with several people.

    Get it Ask colleagues, explain what you are testing, and disclose as you would in normal use.

    Verify Three captured meetings exist with disclosure records

  5. installfree, but transcription takes real machine time

    Why Phase 5 only, for recordings where captions were unavailable.

    Get it Build whisper.cpp and download a model sized for your machine. open ↗

    Verify It transcribes a short recording with word timings

Data model

Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.

- meetings(id, platform, title, started_at, ended_at, disclosed_at, capture_method) · capture_method is captions or recording
- lines(id, meeting_id, ordinal, at_ms, speaker, text, source) · source is platform_caption or transcription
- segments(id, meeting_id, start_ms, end_ms, speaker, text) · cleaned and merged from lines
- notes(id, meeting_id, kind, body, cited_segment_ids_json, validated, generated_at)
- corrections(id, meeting_id, segment_id, field, before, after, at) · speaker and text fixes, kept so a regeneration uses them
- A meeting has a disclosure timestamp or it does not, and one without is visibly marked as undisclosed rather than treated the same.

Environment variables

These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.

VariableNeededExampleWhere the value comes from
DB_PATHrequired~/.local/share/meetings/meetings.dbTranscripts and notes. Contains colleagues' words, so treat backups accordingly.
DISCLOSURE_TEXTrequired./config/disclosure.mdSuggested wording offered at capture start. Configuration so it fits your context.
TRANSCRIPT_RETENTION_DAYSrequired180How long transcripts are kept, per your written policy.
DISCLOSURE_RETENTION_DAYSrequired1825Longer than the transcript, because it is the evidence the capture was disclosed.
NOTES_MODELrequiredlocalWhich model generates notes. Local means transcripts never leave the machine.

The build, in order

  1. Reading captions as they appear

    Live captions from a real meeting arrive in your store as they are spoken.

    1. Watching for changes rather than polling, and identifying the caption elements the platform uses.

      Files extension/observe.ts

    2. Once it stops changing. Every intermediate version is the naive failure.

      Files extension/dedupe.ts

    3. Meetings get reloaded. Losing the transcript at that point loses the meeting.

      Files extension/persist.ts

    done when · tick each as it passes
    watch out
    • Meeting platforms revise a caption line in place as the speech recogniser improves its guess, so naive capture records every intermediate version and produces a transcript full of half-sentences. Track each caption element and store its final text when it stops changing rather than every update.
  2. Disclosure as part of starting

    You cannot start a capture without being prompted to tell the room.

    1. Every capture, not a one-time preference. This is the whole control.

      Files extension/start.ts

    2. One sentence to paste in the chat. Making it easy is what makes it happen.

      Files config/disclosure.md

    3. In the list and on any output. Not identical to a disclosed one.

      Files src/meetings.ts

    done when · tick each as it passes
    watch out
    • A disclosure setting that defaults to off, or a reminder you can dismiss permanently, becomes a capture nobody knows about within a week. Put the prompt in the start flow, record what happened, and make an undisclosed meeting visibly different rather than identical to a disclosed one.
  3. Cleaning a caption transcript

    The transcript reads as speech rather than as caption fragments.

    1. Consecutive lines from one speaker within a short gap become one segment.

      Files src/clean.ts

    2. Caption revision leaves duplicated fragments. Detect and drop them.

      Files src/clean.ts

    3. So a better cleaner improves your existing meetings rather than only future ones.

      Files src/segments.ts

    done when · tick each as it passes
    watch out
    • Cleaning in place destroys the raw capture, and caption cleaning rules always need improving, at which point the meetings you already have cannot benefit. Keep the raw lines and derive segments, so a better cleaner can be re-run over everything you have.
  4. Notes that cite the transcript

    Every line of the summary points at a moment in the meeting.

    1. Structured output, so parsing is not a regular expression.

      Files src/notes.ts

    2. A pure function, unit tested with a crafted bad citation.

      Files src/validate.tssrc/validate.test.ts

    3. In the cited segment, or the action stays unassigned.

      Files src/actions.ts

    done when · tick each as it passes
    watch out
    • Caption transcripts are noisier than audio transcription, with dropped words and misrecognitions, which makes a model more likely to smooth over a gap by inventing what fits. Requiring citations and validating them matters more here than with a clean transcript, not less.
  5. Recordings, when captions were not available

    A meeting without captions can still be processed, from a recording you were entitled to make.

    1. With word timings, using the same segment model as captions.

      Files src/import.ts

    2. Refuse the import without one. A recording is a stronger artefact, not a weaker one.

      Files src/import.ts

    3. One cleaning and notes path for both sources.

      Files src/segments.ts

    done when · tick each as it passes
    watch out
    • Treating an imported recording as needing less disclosure than a live capture is backwards: a recording is a stronger artefact than a transcript and the consent question is the same or greater. Require the same record, and refuse to process an import without one.
what this build does not replace
after v1, if you want it

Need the files? The project pack on the verdict page hands your agent the whole brief · more meeting notes.