docs: document manual_notes.json (Granola-style live notes redesign)

This commit is contained in:
iamdoubz committed 2026-07-11 00:11:52 -05:00
1 parent 45ddc2bd3e
commit 94eafd4fae
1 file changed
+38 -4
+38 -4
View File
@@ -16,7 +16,8 @@ Default root: `%LOCALAPPDATA%\WhispAssist\` (user-configurable, FR-STORE-2).
└── <meeting_id>\ # one folder per meeting (uuid)
├── audio.wav # canonical recording — present ONLY if "Record" was on (ADR-0009)
├── transcript.json # canonical transcript (segments+speakers+timings)
├── notes.md # user-editable Markdown notes
├── manual_notes.json # raw user-authored notes captured live during recording
├── notes.md # the final notes document: manual notes + transcript, merged at finalize
├── summary.json # LLM summary, decisions, action items (if generated)
└── briefs/ # feature briefs distilled from this meeting (ADR-0011), if any
└── <brief_id>.json # agent-ready spec served via the MCP `get_feature_brief` tool
@@ -24,9 +25,42 @@ Default root: `%LOCALAPPDATA%\WhispAssist\` (user-configurable, FR-STORE-2).
Rule: while a meeting is in progress a working WAV is the source of truth for crash recovery. On
finalize, it is **kept** as `audio.wav` if "Record this meeting" was on, or **deleted** if not
(FR-REC-1/4) — deletion happens only after `transcript.json` is finalized. `transcript.json`,
`notes.md`, and `summary.json` are **derived** and regenerable (regenerable only while the audio
still exists — i.e. for recorded meetings).
(FR-REC-1/4) — deletion happens only after `transcript.json` is finalized. `transcript.json` and
`summary.json` are **derived** and regenerable (regenerable only while the audio still exists —
i.e. for recorded meetings).
`notes.md` is **generated once, at finalize**, by merging `manual_notes.json` (freeform notes
typed live during the recording, plus any per-moment annotations — see below) with the rendered,
speaker-tagged transcript (`notes::MarkdownNotes::merge`). After that it is the user's own
document, freely editable via `update_notes` exactly like before this changed — nothing
re-renders or overwrites it afterward. In particular, renaming or merging a speaker after finalize
updates the `speakers` table and the live UI display, but does **not** retroactively rewrite text
already baked into `notes.md` (same as any other manual edit isn't retroactively touched either —
this was a pre-existing clobber bug this redesign also fixes: renaming a speaker used to silently
overwrite the whole file). A crash-recovery finalize (T2.8) and a post-finalize batch
re-transcription (T3.8) both re-render `notes.md` from scratch and so both re-read
`manual_notes.json` from disk to fold the same manual notes back in.
### `manual_notes.json`
```jsonc
{
"schema": 1,
"freeform_md": "string — the user's running notes, typed live in the Notes pane while recording",
"segment_notes": [
{ "anchor_ms": 12345, "text": "string", "created_at": 1735000000, "updated_at": 1735000010 }
]
}
```
`segment_notes[].anchor_ms` is a timestamp into the recording (a clicked transcript segment's
`start_ms`), not a segment id — a later batch re-transcription can renumber/regenerate segment
ids, but never moves the moment in time a note was attached to. At merge time, each note is placed
right after whichever transcript paragraph's time span contains its `anchor_ms`; a note whose
anchor doesn't land inside any paragraph surfaces under an "Other notes" section instead of being
silently dropped. Written to disk on every edit via `update_live_notes`/`set_segment_note`
(`04-api-contracts.md`) — live-session only, same write-through-for-crash-safety spirit as
`transcript.json` accumulating during recording.
## SQLite schema (`wa.db`)