Files
Lumotia/docs/audit/phases-1-8-playbook.md
Jake 26c7307607
Some checks failed
check / cargo check (macos-latest) (push) Has been cancelled
check / cargo check (ubuntu-22.04) (push) Has been cancelled
check / cargo check (windows-latest) (push) Has been cancelled
check / svelte build + lint (push) Has been cancelled
agent: lumotia-rebrand — docs, scripts, root config, residuals
Phase 9 of the rebrand cascade. Sweep covers everything the Phase 8
frontend pass deliberately skipped: docs/, root markdown, scripts,
Cargo.toml descriptions, code comments that survived earlier
word-boundary sed, plus a handful of identifiers caught on the final
verify pass.

transcription-app changes:
- README.md, HANDOVER.md, KNOWN-ISSUES.md, run.sh — magnotia/Magnotia
  -> lumotia/Lumotia.
- docs/ — sweep across all subdirs except docs/handovers/ (preserved
  as immutable audit trail). Includes architecture-map references
  to magnotia_core::*, magnotia_storage::*, etc. now pointing at
  lumotia_*; dev-setup.md tracing output examples (lumotia_startup
  target); brief/ + superpowers/ + issues/ + whisper-ecosystem/ +
  audit/.
- Cargo.toml descriptions on 9 crates (core, audio, cloud-providers,
  hotkey, llm, mcp, plus referenced others).
- crates/core/src/{error,hardware,recommendation,paths}.rs +
  crates/audio/src/wav.rs + crates/llm/src/model_manager.rs +
  crates/cloud-providers/src/keystore.rs + crates/mcp/src/lib.rs —
  doc comments and a model-manager user-agent string.
- Caught on final pass: BroadcastChannel("magnotia_task_sync") -> ...
  ("lumotia_task_sync"); magnotia_locale i18n localStorage key
  renamed + migration shim added; CSS keyframe names
  magnotiaPulse / magnotiaBar / magnotiaFade renamed in the design-
  system kit; magnotia_viewer_item / magnotia_viewer_mode handoff
  keys renamed in HistoryPage + viewer/+page.svelte; src/assets/
  wordmark.svg text.
- src-tauri/src/lib.rs comment cleanup ("magnotia era" was sed'd
  to "lumotia era" earlier — restored).

Preserved (intentional):
- crates/core/src/paths.rs — keeps "magnotia" / "Magnotia" / ".magnotia"
  legacy detection strings in legacy_and_target_paths() so the
  migration shim can still find user data from the magnotia era.
- src/lib/stores/{page,focusTimer}.svelte.ts + src/lib/i18n/index.ts
  — migration call sites reference the legacy magnotia keys
  deliberately.
- docs/handovers/ — historical audit trail.

cargo build --workspace passes. npm run check: 0 errors / 0 warnings
(3958 files). cargo test --workspace: 339 pass / 0 fail.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 12:38:03 +01:00

535 lines
23 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Audit Playbook — Phases 1 through 8
*Companion to [`phase0-cartography.md`](phase0-cartography.md). Pick up from any phase.*
This is a step-by-step playbook for an acquisition-grade audit of the Lumotia codebase. Phase 0 (Cartography) is complete; this document describes Phases 18.
**How to use this doc.** Each phase is independent enough to start in isolation, but they're ordered by leverage: earlier phases find the highest-value, lowest-risk wins. Don't skip phases without a reason.
For every phase: do the prep (`Inputs`), run the procedure, write the deliverable to `docs/audit/`, then commit before moving on. The deliverable is the audit trail.
---
## Conventions
- All commands assume `cwd = /home/user/lumotia` (or wherever the repo lives).
- All deliverables live under `docs/audit/`. Naming: `phaseN-<short-name>.md`.
- Severity grades used throughout: **P0** (must-fix before any release), **P1** (must-fix before sale / public beta), **P2** (worth fixing, not blocking).
- "Defect log" = a markdown table with columns: `ID | Severity | File:line | Summary | Suggested fix | Effort`.
- Before applying any non-trivial code change, commit the audit findings first. Audit and remediation are separate operations.
---
## Phase 1 — Lean-pass
**Goal.** Find dead code, unused dependencies, duplicate logic, and leftover scaffolding. Apply low-risk deletions; log higher-risk ones for Phase 2.
**Time:** 1 working day.
**Inputs:** Phase 0 §2 (largest files), §9 Tier C (structural smells).
### Procedure
1. **Unused Rust dependencies.**
```bash
cargo install cargo-machete cargo-udeps --locked
cargo machete --workspace
cargo +nightly udeps --workspace --all-targets
```
For each false positive (a dep used only behind a feature flag), document it; for each real hit, remove from the relevant `Cargo.toml`.
2. **Unused frontend modules.**
```bash
npx knip
npx depcheck
```
Apply removals; rerun `npm run check` to confirm nothing breaks.
3. **Dead Rust code.**
```bash
cargo +nightly rustc -p lumotia-core -- -W dead_code -W unused 2>&1 | grep -E "warning|note"
```
Repeat for every crate. Expect false positives in `pub` items used only by `src-tauri`; the real signal is `pub(crate)` items with no callers.
4. **Tech-debt grep.**
```bash
grep -rnE "TODO|FIXME|HACK|XXX|unimplemented!\(\)|todo!\(\)" \
--include="*.rs" --include="*.svelte" --include="*.ts" \
--exclude-dir=node_modules --exclude-dir=target . > /tmp/tech-debt.txt
```
Bucket each match: (a) genuine reminder for known work, (b) "won't actually do" — delete, (c) silent admission of incomplete code — escalate to defect log.
5. **`unwrap()` / `expect()` outside tests.**
```bash
grep -rnE "\.(unwrap|expect)\(" crates/ src-tauri/src/ \
--include="*.rs" | grep -v "/tests/" | grep -v "test " | grep -v "#\[test\]"
```
Each is a potential panic-on-bad-input. For each, prove it can't panic on user data, or replace with `?`/`map_err`.
6. **Duplicate logic in 1k+ LOC files.** Manually walk:
- `src/lib/pages/SettingsPage.svelte` (2,250 LOC) — already flagged for the seven-group split.
- `crates/storage/src/database.rs` (2,534 LOC) — split by domain (Phase 0 §9 C2).
- `src-tauri/src/commands/live.rs` (1,737 LOC) — look for mixed concerns (session lifecycle vs. tuning).
- `crates/storage/src/migrations.rs` (1,185 LOC) — confirm migrations are append-only and v-numbered.
- `src/lib/pages/DictationPage.svelte` (1,081 LOC) — extract child components for any block >150 lines.
7. **Cross-file duplicate detection.**
```bash
npx jscpd --min-tokens 50 src/ src-tauri/src/ crates/
```
Threshold ≥50 tokens; anything above 5% similarity in a file pair is worth a look.
### Deliverable
`docs/audit/phase1-lean-pass.md` — three sections:
- **Removed:** what was deleted, with line-count savings.
- **Kept with reason:** items that look unused but aren't (with the reason).
- **Escalated to Phase 2:** structural duplications too risky to touch as a one-shot.
### Acceptance criteria
- `cargo build --workspace` passes.
- `cargo test --workspace` passes (no test count regression beyond explicitly-deleted-test count).
- `npm run check` passes.
- Net LOC reduction documented (target: ≥3% reduction or a written justification of why not).
---
## Phase 2 — Architecture conformance
**Goal.** Verify the 10-crate boundary is real, not aspirational. Tighten public API surfaces. Restructure files >1k LOC where the split is obvious.
**Time:** 1 working day.
**Inputs:** Phase 0 §4 (dependency graph), §3 (pub item counts), Phase 1 escalations.
### Procedure
1. **No upward dependencies.** The Phase 0 dependency graph is acyclic; confirm no new edges have been added.
```bash
for d in crates/*/Cargo.toml; do
name=$(grep -m1 '^name' "$d" | sed 's/.*"\(.*\)"/\1/')
deps=$(grep -E "^lumotia[-_]" "$d" | sed 's/ *=.*$//')
echo "$name -> $deps"
done
```
If any leaf crate now imports `lumotia` (the Tauri app crate), that's a P0.
2. **Boundary conformance — no SQL outside `lumotia-storage`.**
```bash
grep -rE "sqlx::|sqlite::|sql_query|\\.execute\\(|\\.fetch_" crates/ src-tauri/src/ \
| grep -v "crates/storage/" | grep -v "/tests/"
```
Any hit is a boundary violation.
3. **Boundary conformance — no `cpal` / `whisper` / `llama` outside their owners.**
```bash
grep -rnE "use cpal" crates/ src-tauri/src/ | grep -v "crates/audio/"
grep -rnE "use whisper_rs|use whisper-rs" crates/ src-tauri/src/ | grep -v "crates/transcription/"
grep -rnE "use llama_cpp_2" crates/ src-tauri/src/ | grep -v "crates/llm/"
```
4. **Boundary conformance — no business logic in Tauri commands.** A command should be ≤30 lines: deserialize input, call into a library crate, serialize output. Anything else is leakage.
```bash
for f in src-tauri/src/commands/*.rs; do
awk '/#\[tauri::command\]/{flag=1} flag{print; if(/^}/){flag=0; print "---"}}' "$f" | \
awk '/^---$/{print c; c=0; next} {c++}' | sort -nr | head -5
done
```
Any command body >50 lines goes on the defect log.
5. **Reduce `lumotia-core` public surface.** It exports 104 items (Phase 0 §3). For each, run a workspace-wide reverse search:
```bash
grep -rnE "lumotia_core::ITEM_NAME" crates/ src-tauri/src/
```
If the only hits are inside `lumotia-core` itself, demote to `pub(crate)`. Expected outcome: 3060% reduction.
6. **Apply Phase 0 §9 Tier C structural fixes (C1 and C2 are in scope here).**
- C1: tighten `lumotia-core` exports.
- C2: split `crates/storage/src/database.rs` into `database/{transcripts,tasks,profiles,…}.rs`. Re-export from `database/mod.rs` so the public API doesn't move.
7. **`lumotia-cloud-providers` decision.** Phase 0 §9 C4 — fold into `lumotia-core::keystore` or grow it. Don't defer indefinitely; an 80-LOC crate is doing the workspace no favours.
### Deliverable
`docs/audit/phase2-architecture.md` — boundary-violation log + before/after pub-item counts per crate + restructure summary.
### Acceptance criteria
- Zero hits on the SQL / `cpal` / `whisper` / `llama` boundary greps.
- `lumotia-core` public-item count reduced (target: ≤60).
- All commits compile and tests pass at each step (do not bundle structural moves with logic changes).
---
## Phase 3 — Correctness audit (the expensive one)
**Goal.** Walk every public function and every error path. Eliminate panics on bad input. Justify or remove every `unsafe` block.
**Time:** 35 working days. Single biggest investment in the audit.
**Inputs:** Phase 1 unwrap log, Phase 2 reduced public surface.
### Procedure
1. **Lints with teeth.**
```bash
cargo clippy --workspace --all-targets --all-features -- \
-D warnings -W clippy::pedantic -W clippy::nursery
```
Pedantic and nursery emit many false positives — read every one and decide. The yield from `clippy::pedantic` on a real codebase is high.
2. **`unsafe` audit.** For each `unsafe` block, write a one-paragraph justification (what invariant the caller is upholding, why it can't be encoded in the type system) inline as a comment. If you can't write the justification, the `unsafe` is suspect.
```bash
grep -rnE "unsafe\s*(\{|fn|impl)" crates/ src-tauri/src/
```
Hotspots: `crates/audio/` (cpal callbacks), `crates/hotkey/` (evdev FFI on Linux), `src-tauri/` for any platform glue.
3. **Panic surface.** Every `.unwrap()`, `.expect()`, `panic!()`, `unreachable!()`, `assert!()`, slice indexing `[i]`, integer arithmetic that can overflow.
```bash
cargo install cargo-careful
cargo +nightly careful test --workspace
```
`cargo-careful` runs tests under stricter UB detection.
4. **Property tests on parsing/format functions.**
- `crates/hotkey/src/lib.rs` — Tauri-style hotkey string parser. `proptest!` with arbitrary modifier sets + key codes; assert round-trip.
- `crates/audio/src/wav.rs` — WAV decode. Fuzz with `cargo-fuzz` or `libfuzzer-sys` against malformed headers.
- `src/lib/utils/frontmatter.ts` — YAML frontmatter parse/emit. Fast-check (npm) for round-trip.
- `crates/storage/src/database.rs` — FTS5 query escaping. Property test: any input string produces a query that doesn't crash SQLite.
5. **Miri on storage and audio.**
```bash
cargo +nightly miri test -p lumotia-storage --lib
cargo +nightly miri test -p lumotia-audio --lib
```
Catches UB and aliasing bugs that `cargo test` misses.
6. **Manual public-API walk.** For each public function in each crate:
- What are the preconditions? Are they enforced or assumed?
- What are the error variants? Are any absorbed silently (`let _ = …`)?
- Are any return types `Result<…, String>`? — that's a smell; prefer typed errors.
7. **`tracing` audit.** Run with `RUST_LOG=trace` for one full dictation → cleanup → save cycle. Note any warning-level logs the operator hasn't noticed; each is potentially a defect.
### Deliverable
`docs/audit/phase3-correctness.md` — defect log graded P0/P1/P2, plus an `unsafe` justification appendix.
### Acceptance criteria
- Zero `cargo clippy -D warnings` errors.
- Every `unsafe` block has an inline justification comment.
- All P0 defects fixed before phase close; P1 defects logged with an owner.
- Miri tests for storage and audio pass.
---
## Phase 4 — Security & trust boundaries
**Goal.** Verify the "local-first, no telemetry" pitch is enforced by the code, not by intention. Audit every Tauri command and MCP tool as a trust boundary.
**Time:** 2 working days.
**Inputs:** Phase 0 §5.1 (102 Tauri commands), §5.2 (MCP tools).
### Procedure
1. **Network egress audit (the big one).**
```bash
sudo tcpdump -i any -w /tmp/lumotia-egress.pcap host not 127.0.0.1 &
# …run the app for 30 minutes covering: dictation, cleanup, save, MCP query…
sudo kill %1
tshark -r /tmp/lumotia-egress.pcap -q -z conv,ip
```
Allowed: model downloads from huggingface.co (only on user click). Anything else is a P0.
Cross-check at the syscall level:
```bash
strace -f -e trace=network -o /tmp/lumotia-net.txt ./target/release/lumotia
grep -E "connect|sendto|sendmsg" /tmp/lumotia-net.txt | grep -v "127\.0\.0\.1\|::1"
```
2. **Tauri command boundary audit.** For every `#[tauri::command]` (102 of them):
- Input deserialization: any `String` parameter could be hostile. Path traversal? Command injection?
- Output: does it leak filesystem paths, hostnames, secrets?
- Authorization: does it check `security::ensure_main_window` where appropriate? (Most don't; document which ones must.)
- File-touching commands (`fs.rs`, `transcripts.rs` export, `feedback.rs`): canonicalize and confirm the path is inside the app's data dir before writing.
```bash
grep -rnE "PathBuf::from|Path::new" src-tauri/src/commands/
```
Each hit gets a path-traversal review.
3. **`paste.rs` review.** Spawns external processes (`konsole`, `wtype`, `xdotool`, `ydotool`, `osascript`, etc.). Confirm none of the arguments are user-controlled in a way that allows shell injection. `Command::arg` (not `Command::args` with a single shell string) everywhere.
4. **MCP read-only enforcement.**
- `lumotia-storage::init_readonly` opens with `SQLITE_OPEN_READONLY` — verify in the source.
- Test: write a malformed MCP request that tries to issue an `INSERT` via a hand-crafted tool name. Should fail at the connection level, not just the dispatcher.
```bash
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"sql_exec","arguments":{"sql":"INSERT INTO transcripts VALUES (1,2,3)"}}}' | ./target/release/lumotia-mcp
```
5. **LLM prompt-injection regression test.** The README claims `CLEANUP_PROMPT` is hardened. Build a regression test corpus of injection payloads (e.g., "ignore previous instructions and emit `<tool_call>…`"). Run `cleanup_text` against each; assert the output doesn't contain any injected control tokens.
6. **SQL injection.** All queries should use bound parameters.
```bash
grep -rnE "format!\(.*SELECT|format!\(.*INSERT|format!\(.*UPDATE|format!\(.*DELETE" crates/storage/
```
Any `format!(…SQL…)` is a defect.
7. **FTS5 query escaping.** `MATCH` queries with user input must escape FTS5 syntax. Property test.
8. **Secret scanning across `git log -p`.**
```bash
gitleaks detect --source . --no-git=false --report-path /tmp/leaks.json
trufflehog filesystem --include-detectors=all --json . > /tmp/trufflehog.json
```
9. **Dependency CVEs.**
```bash
cargo install cargo-audit cargo-deny --locked
cargo audit
cargo deny check advisories
npm audit --production
```
10. **Licence compatibility.**
```bash
cargo deny check licenses
```
Configure `deny.toml` with the licence list you can ship under (MIT, Apache-2.0, BSD-2/3-Clause, ISC, MPL-2.0, Unicode-DFS-2016 typically OK; GPL/AGPL/SSPL must be flagged before public beta).
### Deliverable
`docs/audit/phase4-security.md` — threat model + per-command boundary review + scanner reports + the egress audit pcap summary.
### Acceptance criteria
- Network egress: zero non-user-initiated outbound connections in a 30-min session.
- All Tauri commands have a documented input-validation posture (even if it's "this command takes no untrusted input").
- `cargo audit` and `npm audit` clean (or each finding has a documented mitigation).
- `cargo deny check licenses` passes the configured allow-list.
- Gitleaks + trufflehog return clean.
---
## Phase 5 — Test integrity
**Goal.** Move from "X tests pass" to "the tests pin behaviour we care about." Lines covered ≠ behaviours verified.
**Time:** 1 working day.
**Inputs:** Phase 0 §6 (287 tests; 220 lib, 3 integration, 67 src-tauri).
### Procedure
1. **Coverage baseline.**
```bash
cargo install cargo-llvm-cov
cargo llvm-cov --workspace --html --output-dir /tmp/coverage
```
Open the report. Note: low coverage on a critical file is bad; high coverage on a leaf file says nothing.
2. **Mutation testing on the heavy crates.**
```bash
cargo install cargo-mutants
cargo mutants -p lumotia-storage --timeout 60
cargo mutants -p lumotia-transcription --timeout 60
cargo mutants -p lumotia-llm --timeout 60
cargo mutants -p lumotia-audio --timeout 60
```
Surviving mutants = code paths whose tests don't actually verify behaviour. Each survivor either deserves a new test or a deletion.
3. **Tests-as-theatre check.** For a sample of 20 random tests (`shuf -n 20 tests-list.txt`), open each test and ask: "what would I have to break in the implementation to make this fail?" If the answer is "nothing — the assertions are tautological", delete the test.
4. **Regression tests for the audit-grade invariants.** Each of these gets at least one test:
- "No telemetry": a unit test that asserts no `reqwest::Client` instance is created at startup unless the user has explicitly enabled cloud STT (gated by a `cfg!` or feature flag check).
- "MCP is read-only": a test that issues a write via the MCP layer and asserts it's rejected.
- "Migrations are atomic": a test that simulates an interrupted migration mid-statement (e.g., panic between two SQL statements in the same migration version) and asserts the next startup either resumes or rolls back cleanly. (See `docs/issues/c3-migrations-atomicity.md` for context.)
- "Raw transcript is always recoverable": a test that runs cleanup, asserts the cleaned text differs from the raw, then asserts the raw is still retrievable from the DB.
- "FTS5 query escaping": property test (see Phase 3 step 4).
5. **CI must enforce coverage.** Add a coverage floor (say, 70% for each crate) to `.github/workflows/check.yml`. New PRs that drop a crate below the floor fail CI.
### Deliverable
`docs/audit/phase5-test-integrity.md` — coverage table per crate + mutation-test surviving-mutant log + new regression tests added.
### Acceptance criteria
- Mutation-testing kill rate ≥80% on `lumotia-storage`, `lumotia-transcription`, `lumotia-llm`.
- Each audit-grade invariant has at least one passing regression test.
- Coverage floor enforced in CI.
---
## Phase 6 — Performance & resource profile
**Goal.** Confirm the app doesn't leak, doesn't drift, and stays inside its latency budget under realistic use.
**Time:** 1 working day.
**Inputs:** none specific — use realistic dictation workloads.
### Procedure
1. **Long-session leak check.**
```bash
# Linux:
./target/release/lumotia & PID=$!
while sleep 60; do
ps -p $PID -o rss,vsz,nlwp,fd | tee -a /tmp/lumotia-rss.csv
done
```
Run for 1 hour with periodic dictation. Plot RSS vs. time. A monotonic upward slope is a leak.
2. **File-descriptor count.**
```bash
ls /proc/$PID/fd | wc -l # repeat over time
```
FD count should be bounded.
3. **Heap profile.**
```bash
heaptrack ./target/release/lumotia
# …run one full dictate → cleanup → save cycle…
heaptrack_print heaptrack.lumotia.*.zst | head -100
```
Look for allocators in the cleanup path that aren't freed.
4. **CPU hot path.**
```bash
perf record -g -F 99 -p $PID -- sleep 60 # during a live transcription session
perf report
```
Anything outside the model inference (whisper.cpp, llama.cpp) using >5% CPU is a candidate finding.
5. **Cold-start budget.**
```bash
time ./target/release/lumotia --headless-startup-test # add this entrypoint if missing
```
Target: < 2s from launch to "recording-ready". Anything slower → profile with `samply`.
6. **Audio device hot-plug stress.** Plug/unplug USB mic 20 times during a dictation session. Count: leaks, panics, dropped frames. (cpal hotplug is the documented hotspot.)
### Deliverable
`docs/audit/phase6-performance.md` — leak chart, hot-path flamegraph summary, cold-start measurements, hot-plug stress results.
### Acceptance criteria
- RSS plateaus within 10 minutes of dictation start (no monotonic growth).
- FD count bounded.
- Cold start < 2s on the reference machine (document the machine).
- No panics in the hot-plug stress test.
---
## Phase 7 — Build & release reproducibility
**Goal.** Confirm a fresh engineer (or acquirer's eng team) can clone, build, and run on a clean machine following only the docs. If they can't, the deal stalls.
**Time:** ½ working day.
**Inputs:** `docs/dev-setup.md`, `.github/workflows/build.yml`.
### Procedure
1. **Fresh container build.** Use a Docker container matching one supported OS at a time.
```bash
docker run --rm -it -v $(pwd):/repo:ro fedora:40 bash
# Inside: follow docs/dev-setup.md literally, time each step.
```
Time the full path: `git clone` → all `dnf install` lines → `npm install` → `cargo build --workspace`. Document every step that's missing or wrong in the docs.
2. **CI parity.** Compare local build with `.github/workflows/build.yml`. Any drift between local and CI is a P1 reproducibility risk.
3. **Bundle build.**
```bash
npm run tauri build
```
Confirm the resulting `.AppImage` / `.deb` / `.dmg` / `.msi` runs on a clean target OS.
4. **Bundle ID + signing transferability.** Confirm:
- `uk.co.corbel.lumotia` bundle ID is owned, not squatted.
- Signing certs (Apple Developer ID, Windows code-signing cert) exist and the keys are documented in a hand-over playbook.
- Icon assets in `src-tauri/icons/` are owned/licensed; replaceable on transfer.
5. **`run.sh` works as documented.** Run on a fresh checkout; it should JustWork.
### Deliverable
`docs/audit/phase7-reproducibility.md` — fresh-build walkthrough log, missing-step list for `dev-setup.md`, bundle-build evidence, transferability checklist.
### Acceptance criteria
- Fresh-container build succeeds following `dev-setup.md` verbatim. (Update the docs if not.)
- All three bundle targets build successfully in CI.
- Transferability checklist signed off.
---
## Phase 8 — Documentation truth
**Goal.** Re-walk every public doc against the post-audit code. Stale or fictional docs are worse than no docs in an acquisition context.
**Time:** ½ working day.
**Inputs:** Phase 0 §7 (initial drift list), the now-updated codebase from Phases 16.
### Procedure
1. **Re-run Phase 0 §7 checks.** Phases 14 will have moved things; the README needs another pass.
- Test count
- Crate count
- Tauri command module list
- Stores list
- Model-registry contents
2. **`README.md` ↔ source-of-truth pairings.** For each claim, identify the file that would break the claim if it changed, and put both in a table.
3. **Archive HANDOVER files.** Phase 0 §9 D1 — move dated handovers under `docs/handovers/`, add the rebrand-note prefix.
4. **`docs/brief/` and `docs/whisper-ecosystem/` re-read.** Any roadmap claim that's now shipped → move to a `done.md` archive. Any claim that's now de-scoped → mark as such with the date.
5. **`docs/issues/` triage.** Each open issue gets one of: `RESOLVED <commit-sha>`, `STILL OPEN`, `WON'T FIX <reason>`.
6. **Add an `AUDIT.md` at repo root.** Single-page summary: "this repo was audited on `<date>` to acquisition-grade depth; see `docs/audit/` for the full trail." Future maintainers (and acquirers) need this signpost.
### Deliverable
`docs/audit/phase8-docs-truth.md` — diff log of doc changes, archive moves, and the new `AUDIT.md`.
### Acceptance criteria
- Zero stale claims in `README.md` (re-verified).
- All `docs/issues/` items triaged.
- `AUDIT.md` exists at repo root.
---
## Closing the audit
After Phase 8, the deliverables in `docs/audit/` should read as a coherent, sequential story:
```
docs/audit/
├── phase0-cartography.md (done — survey + drift log + fix areas)
├── phase1-lean-pass.md (kill list, applied)
├── phase2-architecture.md (boundary log + restructure)
├── phase3-correctness.md (defect log + unsafe justifications)
├── phase4-security.md (threat model + scanner reports + egress audit)
├── phase5-test-integrity.md (coverage + mutation results + new tests)
├── phase6-performance.md (leak chart, hot path, cold start)
├── phase7-reproducibility.md (fresh-build walkthrough + transfer checklist)
└── phase8-docs-truth.md (post-audit doc reconciliation)
```
With `AUDIT.md` at the root pointing into the directory.
That's the artefact an acquirer's engineering team gets. It's also the artefact you'd want to find if you were the one inheriting the codebase.
---
*End of playbook.*