# Napkin

## Corrections
| Date | Source | What Went Wrong | What To Do Instead |
|------|--------|----------------|-------------------|
| 2026-04-22 | self | After the `audio` tmux session collapsed to a single pane, I still treated it like the old pane-1/pane-2 layout and accidentally sent the docs-audit prompt into the surviving pane instead of the intended recipient | Before sending work to a tmux pane in this repo, re-run `tmux list-panes` and target the actual live pane/session rather than assuming the old layout still exists |
| 2026-04-23 | self | While verifying `minutes-7tmf`, I reintroduced the exact Cargo lock contention the napkin already warned about by launching `minutes-core` and `minutes-app` test commands in parallel | In this repo, keep Rust verification strictly single-lane, even for “small” targeted test slices; let one command fully exit before starting the next |
| 2026-04-23 | self | While beginning `minutes-qjaq` verification on the shared main worktree, I launched two targeted `cargo test -p minutes-core --lib ...` commands in parallel and immediately recreated the same package/artifact lock contention | In this repo, even tiny targeted Rust verification during ongoing feature work must stay single-lane; do not fan out tests just because they look short |
| 2026-04-22 | self | While verifying the standalone follow-up branch split from PR #172, I again started multiple Rust commands together (`minutes-core` tests plus `minutes-app` check) and recreated shared Cargo package/artifact lock contention | Even when validating a small split branch here, run Rust tests/checks strictly one at a time; the shared caches and build dirs make parallel verification counterproductive |
| 2026-04-22 | self | While validating PR #172 in a temp worktree, I launched two `cargo test -p minutes-core --lib ...` commands in parallel and immediately hit the repo's shared Cargo package/artifact lock contention again | In this repo, keep Rust verification strictly single-lane even in throwaway worktrees; shared Cargo caches still serialize and parallel launches only add noise |
| 2026-04-22 | self | While tightening Apple speech gating and split benchmark reporting, I again launched multiple Cargo checks in parallel (`minutes-core`, `minutes-cli`, `minutes-app`) and immediately created build-directory/package-cache lock contention instead of signal | In this repo, keep every Rust verification step single-lane, even when the targets feel independent; shared Cargo locks make parallel checks slower and noisier |
| 2026-04-22 | self | While closing GitHub issue #170 from the shell, I put backticks and angle-bracket examples directly inside the `gh issue close --comment` argument, and zsh treated them as command substitution / redirection, mangling the posted comment | When posting GitHub comments from the shell in this repo, avoid inline backticks and `<...>` placeholders inside quoted CLI args; use a body file or `printf ... | gh issue comment --body-file -` so the text reaches GitHub literally |
| 2026-04-20 | self | A public-facing eval/docs pass reused local-only bead IDs (`minutes-n5vj`) in repo docs and described artifacts as "committed/auditable" while the new `docs/eval/` and `tests/eval/` files were still untracked in the working tree | In this repo, never expose local bd IDs as if they were public tracker links, and don't claim docs/results are committed, auditable, or shipped until `git status` confirms the files are actually tracked or committed |
| 2026-04-20 | self | While verifying the Recall workspace skill sync fix, I started two `cargo test -p minutes-app ...` runs in parallel and immediately hit the repo’s known Cargo package/artifact lock contention pattern | In this repo, keep Rust verification strictly sequential, even for small targeted `minutes-app` tests; parallel Cargo runs add noise and slow the signal |
| 2026-04-15 | self | While searching for calendar tests, I repeated an old repo-specific mistake and pointed `rg` at `crates/core/tests`, which does not exist here, adding avoidable noise right in the middle of the investigation | In this repo, use `rg --files crates/core` or search only known existing roots before naming subpaths; `minutes-core` tests live inline under `crates/core/src/` plus the shared top-level `tests/` tree |
| 2026-04-14 | self | During sidecar lifecycle verification I ignored the repo's Cargo sequencing rule and launched `minutes-core` and `minutes-cli` test commands in parallel, which only produced lock contention and a noisier signal | In this repo, keep Cargo verification strictly sequential, including cross-package targeted tests; shared package and artifact locks make parallel runs slower and less trustworthy |
| 2026-04-14 | self | I kept validating Parakeet sweep Rust work with `cargo check` and targeted tests, which missed the repo’s exact `cargo clippy --all --no-default-features -- -D warnings` gate and left main red across several commits | After any non-trivial Rust change in this repo, run the exact Rust gate before pushing: `cargo fmt --all -- --check` and `cargo clippy --all --no-default-features -- -D warnings`. Treat `cargo check` and focused tests as supplementary, not substitutes |
| 2026-04-15 | self | While trying to produce an isolated CLI graph trace, I first wrote the sample meeting under `$HOME/.minutes/meetings` after overriding `HOME`, and `minutes people --rebuild` failed because the CLI reads meetings from `$HOME/meetings` while still writing the graph DB to `$HOME/.minutes/graph.db` | For temp-home CLI repros in this repo, put markdown fixtures in `$HOME/meetings`, expect the SQLite graph at `$HOME/.minutes/graph.db`, and pin `CARGO_HOME` separately if you want to avoid a cold cargo download/build |
| 2026-04-14 | self | While adding LLM title refinement, the existing `write_agent_prompt_file` helper collided on `create_new` under test load because its temp filename generator could still hit an already-existing path | For prompt-file helpers under `~/.minutes/tmp`, use a retry-on-`AlreadyExists` loop around `create_new` instead of assuming timestamp-based names are collision-free |
| 2026-04-14 | self | I initially paired recovered `~/.minutes/jobs` WAVs to meeting markdown files by the job's processing timestamp, which mismatched the actual calls and produced bogus WER comparisons | For recovered job artifacts here, use `recording_started_at` plus a spot-transcribed sample to map the WAV back to the right meeting markdown; `started_at` can just reflect when recovery processing ran |
| 2026-04-13 | user | I treated a pushed commit as effectively done before the latest GitHub Actions run had actually finished green | In this repo, a commit is not done until the newest CI run for that head SHA is green; keep watching/fixing until the latest run completes successfully |
| 2026-04-13 | self | While filing bd issues from a review run, I put backticks inside the shell-quoted `bd create --description` text, and zsh treated them as command substitution before bd ever saw the string | For bd issue descriptions and close reasons here, keep shell-passed text plain or escape backticks first; otherwise the shell mangles the payload before beads records it |
| 2026-04-12 | self | While verifying the OpenCode integration, I kicked off `cargo test -p minutes-core --no-default-features` and a Tauri `cargo check` in parallel, immediately hitting Cargo package/build locks again | In this repo, keep Rust verification strictly sequential, even when the commands target different packages; shared Cargo caches and build dirs make parallel runs noisy and slower |
| 2026-04-09 | user | I started steering toward commit/push because of the repo's generic session-close instructions before confirming whether this helper workflow was meant to stay local-only | For local dev tooling in this repo, confirm the landing expectation before optimizing for commit/push; some helper flows are intentionally repo-local and should stop at verified local changes |
| 2026-04-08 | self | I tried to fan out multiple `bd create` writes in parallel, which triggered Dolt serialization conflicts and also made my assumed child IDs drift from creation order | For bead planning here, create issues sequentially when later items depend on earlier IDs; add dependency edges only after verifying the created IDs |
| 2026-04-08 | self | The native call desktop-control repro looked like a stop/finalization failure in the helper, but the real drop was `minutes stop` sending `SIGTERM` to the desktop app PID from `recording.pid`, killing Tauri before it could enqueue the captured `.mov` | For desktop-managed recordings in Minutes, treat the stop sentinel as authoritative and skip `SIGTERM` when the PID matches a fresh desktop-control heartbeat |
| 2026-04-08 | self | I repeated the repo’s old Cargo habit and passed two positional test filters to `cargo test`, which Cargo treats as an unexpected extra argument | For targeted Rust verification here, run one test filter per `cargo test` invocation (or use a single shared substring) |
| 2026-04-09 | self | I also kicked off multiple `cargo test` runs in parallel for the same package, which mostly just contended on Cargo package/artifact locks and slowed verification down | For focused Rust verification here, run package-level test filters sequentially unless the commands touch disjoint targets/workspaces |
| 2026-04-08 | self | While searching the Minutes repo, I reflexively ran `rg` across generic top-level paths like `src`/`app`/`packages` that do not exist here, which added noisy "No such file or directory" errors right at the start of the investigation | In this repo, scope searches to the actual Rust/Tauri roots (`crates/`, `tauri/`, `docs/`) or use `rg --files` first before naming paths |
| 2026-04-08 | self | While reviewing the main Tauri surface, I almost treated the top processing bar in isolation and would have missed a state-specific regression that was obvious in the Jobs Center | For Minutes UI reviews, compare duplicate state surfaces (top status bars vs Jobs/Recovery center) before calling a behavior intentional; mismatches often reveal real regressions |
| 2026-04-09 | self | The recording/live states hid the entire desktop footer, which silently removed the only in-window path to the Recall panel right when users needed it | For desktop UI state changes here, verify that hiding a container does not strand companion surfaces like Recall; prefer compact/disabled states over removing the only affordance |
| 2026-04-05 | self | While reviewing the Tauri auto-updater wiring, I almost treated a darwin-only `latest.json` as harmless even though the plugin is now enabled globally | For updater changes, inspect the manifest targets against every enabled desktop platform; `tauri-plugin-updater` errors with `TargetsNotFound` when the current OS/arch is missing |
| 2026-03-18 | self | Updated `start_recording` signature for processing-state wiring but missed the tray menu call site in `tauri/src-tauri/src/main.rs` | After widening Tauri command/helper signatures, run `rg` for all call sites before testing so the state plumbing stays consistent |
| 2026-03-19 | self | The Tauri live-recording path was still injecting timestamp titles, which quietly bypassed the smart-title pipeline we had already shipped | When adding UX polish around recording labels, verify we are not overriding downstream title generation or artifact heuristics by accident |
| 2026-03-19 | self | Tried a direct `cargo run -p minutes-cli` sanity check without the repo's usual macOS `CXXFLAGS`, which failed in `whisper-rs-sys` even though the targeted tests had already passed | On this machine, use the `CXXFLAGS=\"-I$(xcrun --show-sdk-path)/usr/include/c++/v1\"` prefix for any Rust command that may build `whisper-rs`, not just tests |
| 2026-03-19 | self | Used backticks inside a shell `rg` argument during verification, and `zsh` treated them as command substitution | When grepping for literal backtick-delimited strings in shell commands, wrap the whole pattern safely or avoid backticks in the query altogether |
| 2026-03-19 | self | Assumed parsed `Frontmatter` carried the runtime-style `content_type` field and wired a consistency heuristic to a field that does not exist | When adding report features on top of markdown frontmatter, re-open the actual `Frontmatter` struct and map from `r#type` explicitly instead of assuming it mirrors downstream write results |
| 2026-03-19 | self | Probed `qmd collection add` assuming the old plan syntax and accidentally created a real collection while trying to discover the interface | For external CLIs, inspect the shipped help or source before probing mutating subcommands; for QMD specifically, `collection add` takes `<path> --name <name>` and `collection list` does not include paths, so pair it with `collection show` |
| 2026-03-19 | self | Guessed the Tauri crate package name for `cargo check` instead of reading `tauri/src-tauri/Cargo.toml` first | When verifying a workspace member, read the manifest or use `--manifest-path` before assuming the package name |
| 2026-03-23 | self | Reused browser `keyCode` values for the dictation hotkey picker even though the native macOS monitor expects virtual keycodes, so many custom keys could never trigger | For browser-captured shortcuts that feed native macOS APIs, map from `KeyboardEvent.code` to macOS virtual keycodes explicitly instead of persisting DOM keycodes |
| 2026-03-23 | self | Moving the dictation hotkey startup off the UI thread still left a race where stale monitor callbacks could overwrite the newest runtime state | When a background monitor can be restarted quickly, track a generation/token in shared state and ignore lifecycle updates from older workers |
| 2026-03-23 | self | Reached for `apply_patch` and `python` out of habit while fixing `crates/core/src/pid.rs`; `apply_patch` kept timing out on this file and this shell only has `python3` | If a targeted edit tool is flaky here, switch promptly to `python3` and verify the rewritten file immediately before continuing |
| 2026-03-24 | self | Moved `tauri::AppHandle` into the dictation hotkey closure and then tried to reuse it for later status emission, which broke `cargo test` with a borrow-of-moved-value compile error | When a Tauri callback needs the same app handle in multiple async/closure paths, clone named handles up front (`app_for_events`, `app_for_status`, etc.) before wiring the monitor |
| 2026-03-24 | self | Trusted `Contents/MacOS/minutes-app --diagnose-hotkey` as a faithful TCC check, but the same probe only reflected granted permissions when the app was launched through LaunchServices | For macOS permission debugging, test the installed app through `open -a` or the repo helper instead of directly executing the bundle binary from the shell |
| 2026-03-24 | self | Read a Windows cross-target `can't find crate for core` failure as if it were a repo portability bug before checking which local Rust toolchain actually owned the installed target | When testing cross-platform builds on this machine, verify `which cargo`, `which rustc`, and `rustup target list --toolchain ... --installed` before trusting the failure as a code issue |
| 2026-03-24 | self | Reached for stale mental-model paths like `tauri/src/app.js` and `crates/mcp/src/reader.ts` before checking the live tree, even though the repo has moved those surfaces to `tauri/src/index.html` and `crates/sdk/src/reader.ts` | When reviewing fast-moving product repos, verify the current file layout with `rg --files` before quoting architecture docs or assuming entry points |
| 2026-03-28 | self | Took "made updates" as likely code changes before checking the worktree; the actual changes were new untracked planning docs | For review requests, start with `git status --short` and inspect untracked docs too, not just tracked diffs |
| 2026-03-28 | self | Almost trusted the shell to demonstrate literal `${HOME}` path handling, but zsh expanded it before Node saw the string | When validating env-var expansion bugs in JS/TS code, use a single-quoted heredoc or equivalent so the runtime receives the literal `${HOME}` / `$HOME` string |
| 2026-03-28 | self | v0.8.2 and v0.7.2 GitHub releases shipped with empty bodies because CI (softprops/action-gh-release) created the release before `gh release create` ran with notes | Create the release with notes FIRST via `gh release create --target main`, which also creates the tag. CI then uploads assets to the existing release. Never `git tag` + `git push --tags` before the release exists. |
| 2026-03-29 | self | Passed two positional test filters to `cargo test`, which Rust interprets as an invalid command rather than "run both sets" | For Rust verification, use one filter per `cargo test` invocation or run the broader target once instead of stacking multiple test names |
| 2026-03-29 | self | Tried to run new dictation unit tests without enabling the `streaming` feature, so the `dictation` module wasn't present in the test binary and the tests silently appeared missing | When verifying dictation/live-transcript behavior in `minutes-core`, use `cargo test -p minutes-core --features streaming ...` or inspect `cargo test -- --list` first if tests don't appear |
| 2026-03-30 | self | Started decoupling recording from processing without first accounting for `~/.minutes/current.wav` being a fixed shared path, which would let the next recording overwrite the previous job's audio | For any async/background recording pipeline in this repo, move the finished capture and its screen-context directory to a job-owned path before releasing the live recording lock |
| 2026-03-30 | self | Used backticks inside a `bd create --description` shell string and zsh tried to execute `minutes jobs` instead of treating it as literal text | When passing issue descriptions through the shell, avoid backticks in double-quoted strings or use single-quoted/heredoc input so command substitution cannot fire |
| 2026-03-31 | self | Added a hashed dedupe key for meeting insights without checking whether `InsightKind` itself derived `Hash`, which broke the first compile pass | When introducing `HashSet` / map keys around existing enums, confirm the enum derives `Hash` or normalize to a primitive key before kicking off verification |
| 2026-03-31 | self | While reviewing the blank-transcript investigation, I initially treated raw-audio loss as mostly a timeout-side effect; the code actually treats `NoSpeech` as a successful pipeline result and cleans up the capture on success | For transcript-loss investigations in this repo, separate "processing failed" from "processing succeeded with `NoSpeech`" before reasoning about why the WAV disappeared |
| 2026-03-31 | self | The MCP layer still auto-downloads `tiny` even though core config defaults to `small`, so "default model" claims are easy to overstate | When reasoning about Minutes model behavior, inspect both core defaults and the MCP bootstrap path instead of assuming they match |
| 2026-03-31 | self | While adding native call capture, I initially let the shared call preflight block before the desktop-native backend had a chance to satisfy `call` intent | When a platform-specific backend can satisfy a generic preflight requirement, compute backend availability before enforcing the block or pass that capability into the decision function explicitly |
| 2026-03-31 | self | The first native call-capture helper wrote `.mov`, but the transcription loader only accepted a narrower extension set, so the happy path would have failed after capture looked successful | For new capture backends in Minutes, verify the emitted container extension is accepted by `load_audio_samples` before treating the path as end-to-end complete |
| 2026-03-31 | self | The first desktop-control handshake acknowledged success as soon as a background thread was spawned, which made MCP think recording had started before the app had actually acquired PID/state | For cross-process control channels in this repo, ack on observed state transition, not on request acceptance alone |
| 2026-03-31 | self | While reviewing the new desktop-control mailbox, I almost called the duplicate-processing race without first checking whether the Tauri app enforced a single-instance lock | For filesystem request/response bridges, verify whether the consumer is single-instance before deciding if read-then-delete polling is safe; if not, require an atomic claim/rename or lock |
| 2026-03-31 | self | Tried searching for the literal pattern `--device` with `rg` without separating patterns from flags, so ripgrep treated it as an option instead of a query | When a search pattern begins with `-`/`--`, pass it via `rg -e \"--pattern\"` (or `--`) before the paths so the shell/tooling can't reinterpret it |
| 2026-04-01 | self | The desktop transcription-language fix looked straightforward until I checked the underlying config type and saw `transcription.language` is `Option<String>`, so a plain select would have silently removed the existing auto-detect state | When mirroring CLI/config settings into the Tauri UI, re-open the config field type first and preserve nullable/`None` semantics explicitly in the control and save path |
| 2026-04-01 | self | Browser-based call detection looked like a narrow Google Meet feature until I checked it against the recent product stance and macOS Automation rules; default-on browser polling would have reopened the same false-positive trust problem we just removed | For call detection in Minutes, treat browser integrations as lower-confidence and opt-in until proven in dogfood, especially when they rely on Apple Events / browser tab inspection |
| 2026-04-01 | self | While backfilling regression tests for community PRs, I repeated the exact Rust CLI mistake the napkin already warned about and passed two positional filters to `cargo test` | For targeted Rust verification in this repo, use one filter per `cargo test` invocation or a single broader substring filter instead of stacking multiple test names |
| 2026-04-02 | self | Trusted `$CODEX_HOME` from the automation prompt and tried to write automation memory before confirming the shell exported it; in this app session it was empty and resolved to `/automations` | For automation-memory writes, verify the env var first and fall back to the concrete `~/.codex` path when `CODEX_HOME` is unset |
| 2026-04-07 | self | While reviewing the new live-transcript status path, I almost accepted `recording.pid` as proof that the sidecar transcript was healthy | For status/reporting changes, verify the actual producer heartbeat or artifact lifecycle; a parent recording process can stay alive long after its sidecar has failed |
| 2026-04-07 | self | While inspecting a sibling Next.js repo from this workspace, I tried to read route-group/dynamic-segment files without quoting the path and zsh treated `(authenticated)` / `[memberId]` as globs | When opening Next.js app-router files from the shell, wrap absolute paths containing `()` or `[]` in single quotes before passing them to `sed`, `nl`, or similar tools |
| 2026-04-07 | self | While validating an old review note, it would have been easy to assume every cited issue was still current because three nearby findings still reproduced | For stale-review verification in this repo, re-open each exact file and version string independently; release links and line references drift faster than adjacent bugs |
| 2026-04-07 | self | While investigating the native macOS call-capture helper, I almost blamed ScreenCaptureKit delivery before checking whether the SIGTERM dispatch source still existed long enough to let the helper finalize its files | For media-capture bugs in this repo, verify signal-source lifetime and output finalization before blaming the capture API; forced termination can look exactly like missing samples |
| 2026-04-08 | self | I initially treated `/site`'s Next 15 banner as if Cathryn's upgrade had been missed, but the committed manifest and lockfile were already on Next 16 and only local `node_modules` was stale | When reported versions disagree in this repo, compare `package.json`, the lockfile, and the installed package tree separately before blaming branch history; `npm ci` may be the only missing step |
| 2026-04-09 | self | During an adversarial strategy review, it would have been easy to repeat older comparison claims about hosted meeting tools lacking MCP support or having older pricing | For Minutes market/comparison work, re-verify competitor MCP availability and pricing from live official docs every pass; this category is moving fast enough that a one-month-old framing can already be wrong |
| 2026-04-09 | user | I committed and pushed private internal strategy docs into this open-source repo by following the generic "always push" workflow without checking whether the material was meant to stay private | In this repo, never commit or push private/internal strategy, monetization, or planning docs without explicit user approval first, even if AGENTS instructions say to push session work by default |
| 2026-04-09 | self | While verifying the title/attribution fix, I kicked off two `cargo test` runs for `minutes-core` in parallel and just made one wait on Cargo's lock | In this repo, run focused Rust verification sequentially even for different test filters; parallel package tests only add lock contention and noise |
| 2026-04-09 | user | I committed internal strategy docs under `.claude/` into this public open-source repo and pushed them to GitHub before removing them | In this repo, treat internal strategy, monetization, GTM, operating-plan, and value-capture docs as private by default. Never commit or push them. If a `.claude/` doc looks like strategy or internal planning, stop and verify it belongs in a public repo before any commit |
| 2026-04-09 | self | The public README currently states that Minutes MCP tools are automatically available in Cowork/Dispatch, while `docs/COWORK-RESEARCH.md` explicitly says that assumption is still unverified and plugin packaging may be required | For strategy or integration writeups in this repo, cross-check the public README against the deeper research note before repeating Cowork/Dispatch claims; treat the plugin-oriented path as the higher-confidence framing until verified |
| 2026-04-09 | self | While threading the new activation cache through `spawn_processing_worker`, I updated most call sites but missed the startup recovery path in `tauri/src-tauri/src/main.rs`, which the first `cargo test -p minutes-app` compile immediately caught | After widening shared Tauri helper signatures here, run `rg` for every call site before compiling; startup/setup-only call sites are easy to miss because they sit outside the main command flow |
| 2026-04-09 | self | I repeated the Cargo lock-contention mistake during activation work by kicking off three focused `cargo test -p minutes-app <filter>` commands in parallel, which just blocked on the package/artifact locks | In this repo, even tiny targeted Rust test filters should be run sequentially once compilation is shared; parallelizing them wastes time and adds noise |
| 2026-04-09 | self | I used backticks inside a shell-quoted `bd close --reason` string, which triggered command substitution and mangled the recorded close reason text for `minutes-ylql.5.2` | Never include raw backticks inside shell-quoted issue reasons or notes here; use plain text or escape them before passing through the shell |
| 2026-04-09 | self | I kicked off `npm --prefix site run build` and `./scripts/check_dojo.sh` at the same time, and Next.js refused the second build with \"Another next build process is already running\" | Treat Next site builds like Cargo tests here: run them sequentially, especially when a smoke script also shells out to `next build` |
| 2026-04-20 | self | The Recall panel stores one shared `assistant.agent_args` list across all CLIs, so switching from Claude/Codex to OpenCode can keep `--dangerously-skip-permissions` around and make `opencode` print its help screen instead of starting normally | When debugging Recall agent launches here, inspect both `assistant.agent` and `assistant.agent_args`; unsupported carryover flags can be the whole bug |
| 2026-04-20 | self | `./scripts/install-dev-app.sh` failed during Developer ID signing because the Tauri `--no-sign` bundle left nested helpers like `Contents/MacOS/mic_check` ad-hoc signed, and the later deep app sign rejected the missing timestamp on that subcomponent | For signed `Minutes Dev.app` installs here, pre-sign nested executables in `Contents/MacOS/` with `--options runtime --timestamp` before signing the app bundle itself |
| 2026-04-12 | self | While diagnosing Parakeet, I confirmed the 110M model transcribes correctly only when detokenized with the NeMo `tokenizer.vocab`; the extracted `*_vocab.txt` produces garbled text, and the 600M v2 conversion still fails even with the tokenizer swapped | For Minutes Parakeet work, verify the exact tokenizer artifact from the `.nemo` before blaming `parakeet.cpp`; `tokenizer.vocab` and `*_vocab.txt` are not interchangeable, and the 600M v2 conversion path needs separate validation |
| 2026-04-12 | self | In the final verification pass I repeated two old Cargo mistakes: launching Rust checks in parallel and trying to pass multiple positional test filters to one `cargo test` | Keep Rust verification sequential in this repo, and when filtering tests use one shared substring (for example `cargo test ... parakeet`) or separate invocations rather than multiple positional filters |

## User Preferences
- For coding/debugging/testing/review tasks, prioritize technical implementation detail and concrete verification.
- For repo reviews, findings should be the primary output, ordered by severity with file/line references.
- Never commit or push private internal strategy/planning material in this open-source repo without explicit approval.
- Never commit internal strategy documents to GitHub in this open-source Minutes repo.

## Patterns That Work
- Start by checking repo instructions plus `bd` workflow, then inspect both the Rust crates and the MCP/Tauri surfaces before making claims about app behavior.
- For roadmap/status checks here, compare `TODOS.md` against the live code, recent commits, GitHub issues, and `bd`; the todo file can lag behind shipped work and blocker changes.
- Keep local-only `bd` IDs out of public repo docs like `TODOS.md`; use those files for human-readable roadmap/status, and keep execution tracking in beads.
- On macOS 26+, Rust tests that compile `whisper-rs` need `CXXFLAGS="-I$(xcrun --show-sdk-path)/usr/include/c++/v1"`; core tests pass once that is set.
- For native macOS hotkeys in Tauri, keep startup non-blocking and report lifecycle changes back to the webview with explicit `starting/active/failed` status events.
- For releases: create the GitHub release with notes BEFORE pushing the tag (use `gh release create` which creates both). CI workflows only upload assets to an existing release. Never let CI create the release — it produces empty bodies that show up blank in followers' feeds.
- For time-window adversarial reviews here, anchor the window with `git rev-list --before='24 hours ago'` and inspect `BASE..HEAD`; raw `git diff --since` stats can make the review surface look much larger than the actual code delta.
- When a tiny community wrapper references Minutes, check current Minutes warnings/docs before dismissing it; wrappers like `meetmix` can encode a real platform-specific gap rather than redundant hobby glue.

## Patterns That Don't Work
- Assuming this repo is only a CLI tool misses the Tauri desktop app and MCP integration surfaces that need review too.
- Trusting `path.resolve(...).startsWith(...)` in Node is not a safe allowlist check here; it misses sibling-prefix and symlink cases.
- In `crates/core/src/pid.rs`, reopening a PID file after taking an `fs2` exclusive lock is not portable; Windows can fail with `os error 33` even though the same flow appears fine on Unix.
- Treating `cargo test --workspace` failures in `pid::tests::sentinel_lifecycle` as proof of a fresh regression is misleading; that test still uses the real `~/.minutes/recording.stop` path instead of an isolated temp home, so verify attribution before blaming today's queue/PID changes.

## Domain Notes
- `minutes` is a local-first meeting capture app with Rust core/CLI, a Tauri desktop app, and a TypeScript MCP server.
- The worktree may already contain user changes; review around them carefully and do not revert unrelated edits.
- The desktop app mixes in-memory recording state with PID-file-based status, so app restarts and cross-surface recording flows are easy places for desync bugs.
- Apple speech work currently overloads `transcription.engine` for a live-only experimental path, so Tauri settings/status code is already compensating around a missing dedicated live-backend config model.
- In the Tauri Apple-speech status surface, `supported` means runtime support exists, while `selectable` means `SpeechTranscriber` is actually available; UI availability copy should key off `selectable`, not `supported`.
- After a remote PR merge on this repo, a dirty local worktree can leave overlapping files in an older pre-merge state; compare against `origin/main` before assuming dirty Apple/live files contain unique local work.
- Live coaching is intentionally split across surfaces: the Tauri UI is the on/off control plus lightweight live status, while the actual coaching/advice is meant to happen in Claude Desktop/Code or another agent reading the live transcript context.
- Early public traction is strongest on the agent-facing distribution surfaces: as of 2026-04-08 the repo has 964 GitHub stars / 95 forks while `minutes-mcp` and `minutes-sdk` each show ~2.6k-2.9k npm downloads over the last month, so strategy discussions should treat "conversation memory for agents" as at least as important as the standalone recorder wedge.
