Files
Lumotia/docs/superpowers/plans/2026-05-14-phase-b-dogfood-plan.md
Jake e993786700 agent: lumotia — Phase B dogfood plan + B.1 audit trail
Captures the 15-item Phase B plan (code-atomiser-fix wave verification) at
docs/superpowers/plans/2026-05-14-phase-b-dogfood-plan.md so the per-item
methodology, status, and findings survive across sessions.

B.1 already done (commit 6c212a0) — full audit trail in the Done items
section: 8 existing unit tests inventory, the misleading start_live
lifecycle comment that was the only real residual, and the documented
pass on the Race-B end-to-end gap per the existing SAFETY annotation.

B.2-B.15 listed with commit references + pending status. Same methodology
per item: orient on commit, survey existing coverage, identify real
residuals, surgical fix or pass, commit. Anti-patterns section captures
the decisions made on B.1 so future me does not re-litigate them.
2026-05-14 19:11:41 +01:00

84 lines
7.4 KiB
Markdown
Raw 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.
---
name: 2026-05-14-phase-b-dogfood-plan
type: plan
tags: [phase-b, dogfood, code-atomiser-fix, verification, lumotia]
description: "Plan for Phase B of the post-rebrand dogfood pass — verify the 25+ code-atomiser-fix commits (race conditions, lifecycle, trust-boundary, time bombs, observability) against gaps the original commits did not close. Per-item methodology: orient on the commit, survey existing coverage, identify real residuals, surgical fix or documented pass, commit. Phase A (rebrand-migration verification) shipped six commits including a real silent-data-loss bug fix surfaced by the dogfood drill."
---
# Phase B dogfood plan — code-atomiser-fix wave
**Started:** 2026/05/14
**Owner:** Wren (with Jake oversight)
**Status:** In progress. B.1 done. B.2B.15 pending.
---
## Context
Phase A (rebrand-migration verification) shipped six commits including a real silent-data-loss bug fix surfaced by `scripts/dogfood-rebrand-drill.sh`. Phase B applies the same methodology to the 25+ code-atomiser-fix commits that landed between the rebrand cascade and the supply-chain pre-flight: examine each, confirm what the commit claims to fix, identify gaps the original test+fix pass missed, write tests or fix residuals where real, and commit per-item so the audit trail stays surgical.
**Phase A baseline gates carried into Phase B:**
- `cargo test --workspace` — 409 pass / 0 fail
- `cargo fmt --check` — clean
- `cargo clippy --workspace --all-targets -- -D warnings` — clean
- `npm run test` — 12 / 12
- `npm run check` — 0 / 0
- `scripts/dogfood-rebrand-drill.sh` — 8 / 8 probes
- Rust toolchain pinned to 1.94.1 stable
- npm dev deps pinned exact
Each B.x commit must keep all of the above green.
## Methodology per item
For each B.x:
1. **Orient.** Read the commit metadata (subject, body, files changed) and the relevant code in its current state.
2. **Survey.** Catalogue existing test coverage and identify what is *not* tested.
3. **Decide.** Real residual found? Surgical fix or test. No residual? Document the verdict and move on. Hard-to-fixture gap acknowledged in code? Honour the original author's SAFETY annotation and document the pass.
4. **Verify.** Run the per-crate or per-area test gate plus workspace clippy + fmt before committing.
5. **Commit.** Format: `agent: lumotia — Phase B.x <one-line description>`. Include findings + verdict + verification gates in the body.
## Items
| # | Surface | Commit(s) | Status | Outcome |
|---|---|---|---|---|
| **B.1** | Cancellable Whisper inference + bounded drain + lock-over-await | `5725836` | **Done** (`6c212a0`) | 8 existing unit tests cover the atomiser-targetable surface. Race-B end-to-end test acknowledged as hard-to-fixture in the SAFETY comment and left as-is. One real residual fixed: misleading comment on `start_live_transcription_session` claiming lifecycle is "Released explicitly before the RunningLiveSession is installed" — the code does the safer opposite (install-while-locked, drop after). Future reader would have trusted the comment and "fixed" the code into a regression. |
| **B.2** | Hotkey supervisor rearchitecture | `1068ad9` (Race-1, Race-2, TOCTOU) | Pending | — |
| **B.3** | Atomic model download + manifest | `9f67ab2` (Rev-1, Rev-5) | Pending | — |
| **B.4** | Soft-delete + trash + restore | `15b74db`, `87e6248`, `50d0715`, `99f4ecd` (Rev-2, Rev-3) | Pending | — |
| **B.5** | `write_text_file_cmd` path scoping + `transcribe_file` extension allowlist + size cap | `a2b47db`, `a48653c`, `b3da58c` (Trust-1) + `9653e25` (Trust-5) + `ed449cc` (Trust-2) | Pending | — |
| **B.6** | Main-window guards on clipboard / extract-tags / file-write | `12b413d`, `f7af7b0` (Trust-4), `7aee534` (Trust-3, Trust-6) | Pending | — |
| **B.7** | LlmEngine critical-section narrowing + drop-old-model-first | `cde985d` (Race-3, Lifecycle-1) | Pending | — |
| **B.8** | Span propagation across live + model-load spawns; `lumotia.log` writer + EnvFilter coverage; drop `lumotia_live` literal target | `65abfa2` (Obs-3), `8becb1a` (Obs-4, Obs-5), `d1391b3` (Obs-1, Obs-2) | Pending | — |
| **B.9** | JSON-envelope LLM extractor (GBNF removal) | `1d71e8e` | Pending | — |
| **B.10** | `focusTimer` rehydrate `startTick` invariant | `5ba761a` (Race-10) | Pending | — |
| **B.11** | `FirstRunPage` unlisten on all exits | `6aa6a43` (Race-9) | Pending | — |
| **B.12** | `Transcriber::transcribe_sync_with_abort` required | `e0e9a6e` (Lifecycle-2) | Pending | — |
| **B.13** | `drain_inference` deadline from `task.duration_secs` | `07f6755` (Time-bomb-1) | Pending | — |
| **B.14** | Surface capture-thread drops + bypass validation requeue cap | `094b533` | Pending | — |
| **B.15** | `test_llm_model` respects caller GPU preference | `afbd33d` (Race-8) | Pending | — |
## Anti-patterns to avoid
- **Over-refactoring for testability.** B.1 had a legitimate Race-B gap that would require restructuring `LiveSessionRuntime` to test in isolation. The original author flagged the trade-off and chose to keep the production shape simple. We honour that — invasive refactor for one test risks introducing the bug the test would have caught.
- **Re-running the dogfood drill mid-Phase-B.** The drill is in place for Phase A's domain (rebrand migration). Phase B touches different surfaces. Adding new drills is in scope if a real residual demands one (per B.1 — none did).
- **Batch-survey-then-fix.** One-at-a-time per Jake's "utmost care" instruction. Each item gets a focused commit; future reviewer can stop at any boundary without untangling a multi-item changeset.
## Done items
### B.1 — start_live lifecycle comment fix (`6c212a0`)
**Surface:** `src-tauri/src/commands/live.rs`. The `start_live_transcription_session` function's upper comment (lines 705-711) claimed `Released explicitly before the RunningLiveSession is installed in live_state.running`. The actual code installs RunningLiveSession on lines 801-806 and only drops `lifecycle` on line 811. The safer ordering — install-while-locked, then release — was already in place; only the comment was wrong.
**Why it matters:** A future reader auditing the locking discipline would have trusted the comment over the code and "fixed" the code to match the buggier description — reintroducing the half-initialised window where a concurrent `stop_live` could observe `running == None` while a `start_live` is mid-install.
**Other findings (no fix needed):**
* 8 existing unit tests cover the atomiser-targetable surface (`dropping_inference_task_sets_abort_flag`, `drain_timeout_scales_with_inflight_chunk_duration_secs`, `drain_timeout_honours_floor_for_short_chunks`, `drain_timeout_uses_floor_when_no_inflight_task`, `drain_timeout_rejects_non_finite_duration`, `result_listener_loss_is_warned_once_and_not_treated_as_inference_failure`, `dead_result_and_status_channels_self_assert_stop_flag`, `no_lumotia_live_literal_target_in_live_rs`).
* The Race-B drain-timeout end-to-end test gap is genuine but acknowledged in the SAFETY comment inside `drain_inference`. Closing it requires either extracting the inner logic into a pure function with explicit dependencies (refactor of working production code) or constructing a full synthetic `LiveSessionRuntime` (impractical — needs a real engine + model + audio device). Honour the original author's call.
* `stop_live_transcription_session` comments + code consistent. No fix needed.
**Verification:** `cargo test -p lumotia --lib commands::live` 17 / 17 (unchanged, comment-only edit); clippy + fmt clean.