Build Hedy

KINDAreplaces $12.99/mosaves $155.88/yrback to the verdict

0%0 of 17 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 local study companion whose hard problems are producing an end-of-session artefact that actually aids retention rather than one that feels productive, keeping a live panel quiet enough not to cost more attention than it returns, and decoding audio without inventing sentences over silence.

estimated effort weekendthe files for this build are in the project pack

RuntimePython 3.12 with FastAPI and one page over a websocket, no build stepCapturesounddevice at 16 kHz mono, optionally mixing a microphone and a loopback deviceTranscriptionA local speech model with overlapping chunks and voice activity detection in frontStorageSQLite for sessions, segments, cards and attempts, plus a markdown file per sessionAssistanceOne model call per scheduled tick, rate limited above the model rather than below it

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 capture loop, the decoder and the server.

    Get it python.org or your package manager. open ↗

    Verify python3 --version prints 3.12 or higher

  2. installfree, after the download

    Why Everything else in this build assumes the audio never leaves the machine, and a hosted transcription service would make that untrue.

    Get it Install the runtime and download a small English model on first run.

    Verify A one minute recording transcribes faster than real time on your machine

  3. installfree

    Why Without one you capture only your own microphone, which is half a conversation and makes the transcript useless for a call.

    Get it A virtual audio device for your platform, installed and selected as an input.

    Verify It appears in the device list and a played recording produces segments

  4. API keypay per call; the rate cap keeps it small

    Why The panel and the question generation are model calls, and they are the only networked part.

    Get it Create a key with your preferred provider and set a spend limit in their console.

    Verify Ending a test session produces questions that cite real segments

  5. decidefree

    Why Recording a lecture is not only a question between you and the lecturer, and finding out afterwards is the wrong order.

    Get it Read the recording policy where you study and write down what it permits.

    Verify A note in the README states the policy you checked and the date

Data model

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

- sessions(id, kind, started_at, ended_at, brief, consent_note, device, model_id) · kind is lecture, seminar, meeting or call, and it changes the defaults rather than just a label
- segments(id, session_id, t_start, t_end, text, avg_logprob, no_speech_prob) · one per decoded chunk, keeping whatever confidence the decoder reported
- cards(id, session_id, at, kind, text, source_segment_ids_json, shown_at, dismissed_at) · a live prompt, with the transcript it was built from
- questions(id, session_id, text, answer, source_segment_ids_json, created_at) · the artefact that matters, answers stored separately from the question text
- attempts(id, question_id, at, self_rating, next_due_at) · retrieval practice needs a record of the attempt, not a record of the reading
- settings(panel_updates_per_minute, lecture_panel_default_off, audio_retention_days, interval_schedule_json)
- There is no streak table, no score and no notification queue. A study tool that nags is a study tool uninstalled in week three.

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
MODEL_API_KEYsecretoptionalsk-...redactedThe panel and question generation. Absent means local transcription only.
MODEL_IDoptionala text model identifierStored on the session, because questions differ by model.
SPEECH_MODELrequiredsmall.enThe local decoder. Larger is slower and the panel cap assumes it keeps up.
DATABASE_PATHrequired./data/study.dbSessions, segments, questions and attempts. The attempts are the irreplaceable part.
SESSIONS_DIRrequired./sessionsOne markdown file per session. These are meant to outlive the application.
AUDIO_RETENTION_DAYSrequired7How long recordings of other people stay on your disk. Short is the right default.
PANEL_UPDATES_PER_MINUTErequired3Hard cap enforced in the scheduler. Lower it before you raise it.
MONTHLY_COST_CEILINGrequired3.00Assistance stops at this figure and transcription carries on.

The build, in order

  1. Capture, and a transcript that never invents

    Audio is captured from a device you chose and decoded only where somebody is actually speaking.

    1. Capturing the other side of a call is a routing problem, not a code problem.

      Files app/audio.pyREADME.md

    2. Silence in, invented sentences out.

      Files app/vad.pytests/test_vad.py

    3. Otherwise you lose a word every boundary and never notice.

      Files app/transcribe.pytests/test_overlap.py

    done when · tick each as it passes
    watch out
    • Decoding fixed chunks with no overlap chops a word at every boundary, so the panel reasons over a transcript that is missing a word every few seconds and you will blame the model for it. Overlap the chunks by a second and merge on the overlap, and drop non-speech before it reaches the decoder rather than after, because long silences are exactly the input that produces fluent sentences nobody said.
  2. A panel that does as little as possible

    The live assistance costs less attention than it returns, and in a lecture it is closed.

    1. A cap in the renderer is not a cap.

      Files app/assist.pytests/test_rate.py

    2. The session kind is a design decision, not a label.

      Files app/sessions.pyweb/panel.js

    3. A prompt you cannot trace is a prompt you cannot check.

      Files app/assist.py

    done when · tick each as it passes
    watch out
    • Rendering a card whenever the model returns turns the session into the laptop multitasking condition that Sana and colleagues measured a cost for, both for the person with the laptop and for whoever can see the screen, and the cost lands on the lecture you are attending rather than the transcript you will read later. Cap the rate in the scheduler so the cap holds when the model is fast, default the panel closed for lectures, and time how long you actually spend looking at it before deciding the cap is too low.
  3. The session ends in questions

    Finishing a session produces short-answer questions with the answers hidden, and the summary is secondary.

    1. The default view is the design decision here.

      Files web/session_end.jsapp/questions.py

    2. So the interface cannot accidentally show both.

      Files app/db.pytests/test_questions.py

    3. A question about something nobody said is worse than no question.

      Files app/questions.pytests/test_citation.py

    done when · tick each as it passes
    watch out
    • Generating a tidy summary and calling it revision optimises the condition that lost by fourteen points at one week in Roediger and Karpicke, and it will feel like the better product because rereading feels fluent and recall does not. Make the question list the page you land on, keep answers collapsed until an attempt has been recorded, and let the summary exist as the second tab rather than the first.
  4. Bringing them back, without nagging

    Questions come due on a schedule you can read, and nothing chases you.

    1. With the reasoning next to them, not in a commit message.

      Files config/intervals.jsonapp/review.py

    2. A stored queue drifts from the attempts that produced it.

      Files app/review.pytests/test_review.py

    3. The absence of a notification path is the feature.

      Files tests/test_no_notifications.py

    done when · tick each as it passes
    watch out
    • A review queue that sends a notification is the feature that gets a study app deleted in the second week, and an interval schedule hidden in code is one you cannot argue with when it feels wrong. Keep the intervals in a configuration file with the reasoning written beside them, show the next due date after every attempt, and leave the reminding to the person.
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.