diff --git a/HANDOVER-2026-04-19.md b/HANDOVER-2026-04-19.md new file mode 100644 index 0000000..5759210 --- /dev/null +++ b/HANDOVER-2026-04-19.md @@ -0,0 +1,97 @@ +--- +name: handover-2026-04-19 +type: reference +tags: [handover, session, kon] +description: Session handover — 2026/04/19 dogfood polish + cross-platform window chrome +--- + +# Kon Handover — 2026/04/19 + +Second dogfood sprint. Four phases: (1) fix bugs surfaced on first real use, (2) redesign History for cognitive-load hygiene, (3) resolve broken window resize/drag on Linux Wayland, (4) clean up microphone picker. + +## What shipped this session + +### Cross-window preferences sync +- `preferences.svelte.js` emits `kon:preferences-changed` Tauri event on update. +- Main / viewer / float layouts listen and call `applyExternalPreferences` without re-emit, so theme and font changes propagate live across sibling windows. +- Echo suppressed via source window label check. + +### Hotkey recorder +- Root cause of "can't change hotkey": button-level `onkeydown` relied on post-click keyboard focus, which webkit2gtk on Linux does not guarantee. +- Fix: `document.addEventListener("keydown", ..., { capture: true })` inside a `$effect` gated by `recording`. Beats any descendant handler. Escape now cancels. + +### History page redesign (research-backed) +- Compact row now shows the **title** (or "Untitled"), not body-preview text — metadata already lives in the row columns (date, duration, source icon). +- Expanded row gets an inline title input (replaces the old Rename prompt modal). +- **Edit** button opens the viewer window in `edit` mode (editable textarea, debounced save to localStorage + storage-event sync back to main history). +- **Export .md** copies a full YAML-frontmatter markdown document to the clipboard — paste into Obsidian. +- **Tags**: `$lib/utils/frontmatter.js` exposes `deriveAutoTags` (currently returns `[]`), `buildFrontmatter`, `serialiseFrontmatter`, `buildMarkdown`. Manual tags stored as `item.manualTags`, rendered as removable chips in the expanded row with `+ add tag` input. +- Header tag chip bar (cap 7, click to filter, × to clear), plus `tag:xyz` search syntax. +- Global **Starred** filter toggle in the History header. +- Research memo found all five previous auto-tag families redundant with existing row UI — kept the derivation hook for the post-Task-7 `topic:*` content tag from kon-llm. +- Duplicate-transcript render fix: expanded `

` only if compact preview actually truncated. + +### Viewer / editor popout +- `/viewer` route now reads `kon_viewer_mode` from localStorage ("view" | "edit"). +- Edit mode renders a plain textarea bound to `item.text`; 400ms debounced save flushes on input, final flush on `onDestroy`. Segment-specific controls (Compact, Starred) hidden in edit mode. +- Native title: **"Kon - Transcription Editor"**. + +### Platform-aware window chrome (Linux fix) +**Root cause:** Tauri v2 frameless `decorations: false` on KDE Wayland + webkit2gtk does not honour diagonal corner resize (collapses `NorthEast` etc. to a single axis via GTK's `gtk_window_begin_resize_drag`), and `data-tauri-drag-region` adds noticeable drag latency. Setting `setPointerCapture` ahead of `startResizeDragging` does not help once the compositor has taken over the pointer grab. Verified via Context7 docs + Codex diagnosis — Linux frameless is a known-fragile path. + +**Fix:** +- Linux uses **native KWin/Mutter decorations**. `src-tauri/tauri.linux.conf.json` overlays `decorations: true` + full main window config (title, sizes) — overlays **replace** the windows array, so every field must be present, not just the delta. `src-tauri/src/commands/windows.rs` uses `cfg!(target_os = "linux")` to set decorations per window. +- macOS / Windows keep custom chrome. `src/lib/utils/osInfo.js` `isLinux()` gates `` and `` via `useCustomChrome = $state(false)`; flips to `!isLinux()` after `loadOsInfo()` resolves. +- Dueling drag-region handlers removed across Titlebar, float page, viewer page — everywhere a manual `startDragging()` lives, the `data-tauri-drag-region` attribute was deleted (they're alternatives per Tauri docs, not combinable). +- `ResizeHandles` kept for macOS/Windows frameless: 12 px edges / 20 px corners via CSS vars (`--kon-resize-edge`, `--kon-resize-corner`), `pointerdown` + `setPointerCapture`, corners with explicit higher z-index. Handles rendered as siblings of the animated layout div so `position: fixed` is viewport-relative rather than captured by the transform containing block. + +### Window minimum sizes (evidence-backed) +Research pass cited GNOME HIG (1024×600 desktop / 360×294 mobile floors), WCAG 2.2 SC 1.4.10 Reflow (320 CSS px), Raycast 750×474 as a reference for single-pane working width, and consistent A11y principle that nothing should clip in the default configuration. + +| Window | Was | Now | Rationale | +|---|---|---|---| +| Main | 1020×540 | **960×600** | Fits 210 px sidebar + ~750 px content; GNOME vertical floor. | +| Float | 400×400 | **360×480** | 360 = GNOME mobile floor; 480 fits pills + quick-add + sort + ~6 task rows without scroll. | +| Transcript editor | 450×500 | **560×520** | Exceeds WCAG reflow floor; ~60-70 char measure for editing. | + +### Microphone picker cleanup +- ALSA enumeration was leaking `hw:`, `plughw:`, `front:`, `sysdefault:`, `null` et al into the dropdown. +- `SettingsPage.svelte` now renders only sentinel devices (`default`, `pipewire`, `pulse`) + one entry per unique sound card, keyed off the `sysdefault:CARD=X` alias. +- `crates/audio/src/capture.rs` reads `/proc/asound/cards` and populates a new `description` field on `DeviceInfo` with the card's full product string (e.g. "Blue Microphones" for Jake's Yeti). Frontend prefers description → CARD=X short name → raw name. + +### GPU reporting +- `commands/models.rs::get_runtime_capabilities` was hardcoded to `accelerators: vec!["cpu"]` and `supports_gpu: false` for whisper. Updated to `["cpu", "vulkan"]` and whisper `supports_gpu: true`, reflecting that `crates/transcription/Cargo.toml` links transcribe-rs with the `whisper-vulkan` feature unconditionally. +- Settings now shows the Vulkan option instead of the "This build is CPU-only" notice. + +### Desktop shortcut +- `~/Desktop/Kon.desktop` launcher with the 128×128 icon, `Terminal=true` so logs are visible and Ctrl+C cleanly stops the run.sh wrapper. + +## What's deferred + +- **Transparent windows (`transparent: true`)** — Tauri issue #13270 reports this smooths drag/resize further on Linux, but it's moot now that Linux uses native decorations. +- **File-system export (.md save dialog)** — currently clipboard-only. Needs a Rust `write_text_file` command for plugin-less file writes. +- **Bulk select + bulk export** in History. +- **LLM-powered content tags** (`topic:*`, `intent:*`) — slots into Task 7 `kon-llm` stub once Phase 3 wires real llama-cpp-2. +- **Settings UX overhaul** — Jake flagged that current settings feel overwhelming. Proposed: bunch high-traffic settings, hide advanced behind a toggle. Brainstorm + plan deferred to a dedicated session. +- **Task 7 (MicroSteps end-to-end)** — storage + Tauri CRUD + kon-llm stub + frontend dual-write all landed in an earlier commit chain. The MicroSteps UI was written as the final task 7 step but not yet dogfooded against the stub LLM. Needs manual walkthrough. + +## Gotchas discovered today + +| Issue | Fix | +|---|---| +| `tauri.linux.conf.json` stripped title and min sizes from main window | Overlay **replaces** the windows array — include every field, not just the delta | +| `data-tauri-drag-region` + manual `startDragging()` on the same node caused drag latency | Pick one — we use manual `startDragging` for the button/input early-return logic | +| Corner resize collapsed to single axis on KWin Wayland | Native decorations on Linux side-step the whole frameless path | +| `animate-float-enter` on the viewer/float layout root created a containing block that broke `position: fixed` on ResizeHandles children | Render ResizeHandles as a sibling of the animated div, not a descendant | +| Kon binary auto-respawned on file-save while a second run.sh was also launching → two visible instances sharing one Vite server | Do not script `./run.sh` while the user has already launched via the desktop icon; rely on HMR | +| `run.sh` leaves `"beforeDevCommand": ""` in tauri.conf.json if its cleanup trap is bypassed (e.g. SIGKILL) | Cleanup trap restores `"npm run dev"` on graceful exit; SIGTERM (not SIGKILL) is the right kill signal | +| `/proc/asound/cards` header lines have leading whitespace for 2-digit card ID alignment | Parser trims leading whitespace before checking for leading digit | + +## How to resume + +``` +Picking up Kon dogfooding from 2026/04/19. +HANDOVER is at HANDOVER.md in the project root. +Active priorities: (1) confirm resize/drag/mic cleanup, (2) Task 7 MicroSteps +dogfood with kon-llm stub, (3) Settings UX brainstorm. +``` diff --git a/HANDOVER.md b/HANDOVER.md index 5759210..652641b 100644 --- a/HANDOVER.md +++ b/HANDOVER.md @@ -1,97 +1,83 @@ --- -name: handover-2026-04-19 +name: handover-2026-04-23 type: reference -tags: [handover, session, kon] -description: Session handover — 2026/04/19 dogfood polish + cross-platform window chrome +tags: [handover, session, kon, consolidation] +description: Session handover — 2026/04/23 branch consolidation + main-in-its-best-state pass --- -# Kon Handover — 2026/04/19 +# Kon Handover — 2026/04/23 -Second dogfood sprint. Four phases: (1) fix bugs surfaced on first real use, (2) redesign History for cognitive-load hygiene, (3) resolve broken window resize/drag on Linux Wayland, (4) clean up microphone picker. +Consolidation session. Jake asked for "all branches to main and the repo in its best state" ahead of Corbie rebrand. This session brought outstanding Dependabot PRs into `main`, cleaned workspace lints, recovered an orphan stash onto a dedicated branch, and established a clean baseline for the post-rebrand push. + +## Rebrand note + +The product is in the process of being renamed **Kon → Corbie**. As of 2026/04/23 the canonical product name in any new copy (grant applications, landing pages) is **Corbie** (sentence case). The GitHub repo `jakejars/kon` and the Gitea repo `jake/kon` both still carry the `kon` name, intentionally — repo rename is pending Jake's own hand and is not blocking the rebrand copy-wise. Code paths (`crates/`, `src-tauri/`, package name `kon@0.1.0`) remain as-is until the repo rename lands; renaming the codebase identifiers is a separate coordinated sweep. See `memory/project_corbie_rebrand.md` in CORBEL-Main for the full rebrand state. ## What shipped this session -### Cross-window preferences sync -- `preferences.svelte.js` emits `kon:preferences-changed` Tauri event on update. -- Main / viewer / float layouts listen and call `applyExternalPreferences` without re-emit, so theme and font changes propagate live across sibling windows. -- Echo suppressed via source window label check. +### Baseline validation +- Fresh `cargo build`, `cargo test --workspace`, `cargo fmt --check`, `npm run check`, `npm run build` run against the pre-consolidation tip (`9b0067b`, tagged as `pre-consolidation-2026-04-23` for recovery). +- `npm run build` initially failed with a missing-dependency error for `@chenglou/pretext`. Root cause: stale partial `node_modules` install dated 2026-04-21 07:45 — the directory for the package existed but was empty. `npm install` recovered it; package is present in lockfile and needed by `src/lib/utils/textMeasure.ts`. +- `cargo clippy -- -D warnings` initially failed with 3 errors in `crates/storage/src/file_storage.rs` (two doc-list overindentations, one needless return). These were trivial style issues that clippy had never enforced at CI strictness. -### Hotkey recorder -- Root cause of "can't change hotkey": button-level `onkeydown` relied on post-click keyboard focus, which webkit2gtk on Linux does not guarantee. -- Fix: `document.addEventListener("keydown", ..., { capture: true })` inside a `$effect` gated by `recording`. Beats any descendant handler. Escape now cancels. +### Workspace clippy cleanup (commit `fe61661`) +- Applied `cargo clippy --fix` across 11 files: `crates/audio`, `crates/hotkey`, `crates/storage`, `crates/transcription`, `src-tauri`. +- Net -2 lines. No behavioural changes — pure lint cleanup (needless returns, unnecessary casts, `iter().any()` → `contains()`, `repeat().take()` → `repeat_n`, lifetime elision, `map_or` simplification, reference-immediately-dereferenced). +- One remaining warning left untouched: `needless_range_loop` at `src-tauri/src/commands/live.rs:1089` — clippy's suggested iterator rewrite would make it less readable. Earmarked for a focused refactor session. +- Build + 245 workspace tests remain green post-fix. -### History page redesign (research-backed) -- Compact row now shows the **title** (or "Untitled"), not body-preview text — metadata already lives in the row columns (date, duration, source icon). -- Expanded row gets an inline title input (replaces the old Rename prompt modal). -- **Edit** button opens the viewer window in `edit` mode (editable textarea, debounced save to localStorage + storage-event sync back to main history). -- **Export .md** copies a full YAML-frontmatter markdown document to the clipboard — paste into Obsidian. -- **Tags**: `$lib/utils/frontmatter.js` exposes `deriveAutoTags` (currently returns `[]`), `buildFrontmatter`, `serialiseFrontmatter`, `buildMarkdown`. Manual tags stored as `item.manualTags`, rendered as removable chips in the expanded row with `+ add tag` input. -- Header tag chip bar (cap 7, click to filter, × to clear), plus `tag:xyz` search syntax. -- Global **Starred** filter toggle in the History header. -- Research memo found all five previous auto-tag families redundant with existing row UI — kept the derivation hook for the post-Task-7 `topic:*` content tag from kon-llm. -- Duplicate-transcript render fix: expanded `

` only if compact preview actually truncated. +### Dependabot merges (commits `6579c5f`, `0b1c492`, `509b983`) +Three dev-dep bumps landed as `--no-ff` merge commits: -### Viewer / editor popout -- `/viewer` route now reads `kon_viewer_mode` from localStorage ("view" | "edit"). -- Edit mode renders a plain textarea bound to `item.text`; 400ms debounced save flushes on input, final flush on `onDestroy`. Segment-specific controls (Compact, Starred) hidden in edit mode. -- Native title: **"Kon - Transcription Editor"**. +| # | Package | File changes | +|---|---|---| +| 1 | `picomatch` | `package-lock.json` only | +| 2 | `@sveltejs/kit` | `package.json` + `package-lock.json` | +| 3 | `vite` (npm_and_yarn group) | `package.json` + `package-lock.json` | -### Platform-aware window chrome (Linux fix) -**Root cause:** Tauri v2 frameless `decorations: false` on KDE Wayland + webkit2gtk does not honour diagonal corner resize (collapses `NorthEast` etc. to a single axis via GTK's `gtk_window_begin_resize_drag`), and `data-tauri-drag-region` adds noticeable drag latency. Setting `setPointerCapture` ahead of `startResizeDragging` does not help once the compositor has taken over the pointer grab. Verified via Context7 docs + Codex diagnosis — Linux frameless is a known-fragile path. +After the three merges: `npm install` clean, `npm run build` green, `npm run check` 0 errors / 0 warnings. Vulnerability count went from 6 (1 low / 2 moderate / 3 high) to 5 (3 low / 2 moderate) — the three highs cleared. -**Fix:** -- Linux uses **native KWin/Mutter decorations**. `src-tauri/tauri.linux.conf.json` overlays `decorations: true` + full main window config (title, sizes) — overlays **replace** the windows array, so every field must be present, not just the delta. `src-tauri/src/commands/windows.rs` uses `cfg!(target_os = "linux")` to set decorations per window. -- macOS / Windows keep custom chrome. `src/lib/utils/osInfo.js` `isLinux()` gates `` and `` via `useCustomChrome = $state(false)`; flips to `!isLinux()` after `loadOsInfo()` resolves. -- Dueling drag-region handlers removed across Titlebar, float page, viewer page — everywhere a manual `startDragging()` lives, the `data-tauri-drag-region` attribute was deleted (they're alternatives per Tauri docs, not combinable). -- `ResizeHandles` kept for macOS/Windows frameless: 12 px edges / 20 px corners via CSS vars (`--kon-resize-edge`, `--kon-resize-corner`), `pointerdown` + `setPointerCapture`, corners with explicit higher z-index. Handles rendered as siblings of the animated layout div so `position: fixed` is viewport-relative rather than captured by the transform containing block. +### Orphan-stash recovery (branch `feat/design-system-recover`, commit `8855db8`) +- A WIP stash sat on `stash@{0}`, pinned to parent commit `1296173` — the tip of the deleted `feat/design-system` branch. ~1000 LOC across 24 files: `ai-formatting/rule_based.rs` rewrite, `transcription/local_engine.rs`, core `hardware.rs` + `recommendation.rs`, `audio/resample.rs`, and a sweep across Svelte UI (`TaskSidebar`, `FilesPage`, `TasksPage`, `WipTaskList`, `ModelDownloader`, `Titlebar`, `viewer`, `float`). +- Recovered using `git stash branch`, which creates a branch from the stash's parent commit and applies the stash content. Parent commit still existed in the reflog even though no branch referenced it. +- Committed the full recovery as `wip(design-system): recover orphan stash` on the new branch. **Not merged to main.** Needs a focused rebase session: heavy conflicts expected in `TasksPage`, `FilesPage`, `ai-formatting/rule_based.rs`, and `transcription/local_engine.rs` against current main since those all saw release-blocker fixes after the stash was taken. Also missing the 2026-04-23 clippy cleanup. +- Branch pushed to `github` for remote preservation. -### Window minimum sizes (evidence-backed) -Research pass cited GNOME HIG (1024×600 desktop / 360×294 mobile floors), WCAG 2.2 SC 1.4.10 Reflow (320 CSS px), Raycast 750×474 as a reference for single-pane working width, and consistent A11y principle that nothing should clip in the default configuration. +## Release-blocker state (unchanged this session) -| Window | Was | Now | Rationale | -|---|---|---|---| -| Main | 1020×540 | **960×600** | Fits 210 px sidebar + ~750 px content; GNOME vertical floor. | -| Float | 400×400 | **360×480** | 360 = GNOME mobile floor; 480 fits pills + quick-add + sort + ~6 task rows without scroll. | -| Transcript editor | 450×500 | **560×520** | Exceeds WCAG reflow floor; ~60-70 char measure for editing. | +From `docs/issues/README.md`: -### Microphone picker cleanup -- ALSA enumeration was leaking `hw:`, `plughw:`, `front:`, `sysdefault:`, `null` et al into the dropdown. -- `SettingsPage.svelte` now renders only sentinel devices (`default`, `pipewire`, `pulse`) + one entry per unique sound card, keyed off the `sysdefault:CARD=X` alias. -- `crates/audio/src/capture.rs` reads `/proc/asound/cards` and populates a new `description` field on `DeviceInfo` with the card's full product string (e.g. "Blue Microphones" for Jake's Yeti). Frontend prefers description → CARD=X short name → raw name. +- **0 open CRITICAL** +- **1 open MAJOR** — RB-08 `power-assertion-macos-objc2` (awaits manual runtime verification on a real macOS machine: `pmset -g assertions` during a background live-session) +- **11 RBs resolved** +- **11 CR items resolved** from the 2026-04-22 code review -### GPU reporting -- `commands/models.rs::get_runtime_capabilities` was hardcoded to `accelerators: vec!["cpu"]` and `supports_gpu: false` for whisper. Updated to `["cpu", "vulkan"]` and whisper `supports_gpu: true`, reflecting that `crates/transcription/Cargo.toml` links transcribe-rs with the `whisper-vulkan` feature unconditionally. -- Settings now shows the Vulkan option instead of the "This build is CPU-only" notice. +RB-08 continues to gate v0.1 tagging. -### Desktop shortcut -- `~/Desktop/Kon.desktop` launcher with the 128×128 icon, `Terminal=true` so logs are visible and Ctrl+C cleanly stops the run.sh wrapper. +## Deferred (unchanged from 2026/04/19 handover unless noted) -## What's deferred +- **RB-08 verification** — needs macOS hardware access +- **Design-system work** — parked on `feat/design-system-recover`; revisit in a dedicated session +- **`live.rs:1089` needless_range_loop refactor** — clippy suggestion is ugly, deserves a real rewrite +- **Kon → Corbie codebase rename** — package name, crate prefixes, repo name on Gitea + GitHub. Coordinated sweep, not yet scheduled +- **Transparent windows**, **file-system export**, **bulk select/export**, **LLM content tags**, **Settings UX overhaul**, **Task 7 walk-through** — all carried over from 2026-04-19 handover +- **CI clippy enforcement** — 1 warning remains on main; turning on `-D warnings` in CI means either fixing it or explicit `#[allow]` -- **Transparent windows (`transparent: true`)** — Tauri issue #13270 reports this smooths drag/resize further on Linux, but it's moot now that Linux uses native decorations. -- **File-system export (.md save dialog)** — currently clipboard-only. Needs a Rust `write_text_file` command for plugin-less file writes. -- **Bulk select + bulk export** in History. -- **LLM-powered content tags** (`topic:*`, `intent:*`) — slots into Task 7 `kon-llm` stub once Phase 3 wires real llama-cpp-2. -- **Settings UX overhaul** — Jake flagged that current settings feel overwhelming. Proposed: bunch high-traffic settings, hide advanced behind a toggle. Brainstorm + plan deferred to a dedicated session. -- **Task 7 (MicroSteps end-to-end)** — storage + Tauri CRUD + kon-llm stub + frontend dual-write all landed in an earlier commit chain. The MicroSteps UI was written as the final task 7 step but not yet dogfooded against the stub LLM. Needs manual walkthrough. +## Repo state at session end -## Gotchas discovered today +- `main` at `509b983` — 7 commits ahead of origin at session start (1 clippy + 3 dependabot original commits + 3 merge commits) +- `feat/design-system-recover` at `8855db8` — WIP recovery, pushed to `github` only +- Tags: `pre-consolidation-2026-04-23` points at `9b0067b` (restore anchor) +- Stashes: none +- Dependabot branches: still present locally; can be pruned now that merges landed -| Issue | Fix | -|---|---| -| `tauri.linux.conf.json` stripped title and min sizes from main window | Overlay **replaces** the windows array — include every field, not just the delta | -| `data-tauri-drag-region` + manual `startDragging()` on the same node caused drag latency | Pick one — we use manual `startDragging` for the button/input early-return logic | -| Corner resize collapsed to single axis on KWin Wayland | Native decorations on Linux side-step the whole frameless path | -| `animate-float-enter` on the viewer/float layout root created a containing block that broke `position: fixed` on ResizeHandles children | Render ResizeHandles as a sibling of the animated div, not a descendant | -| Kon binary auto-respawned on file-save while a second run.sh was also launching → two visible instances sharing one Vite server | Do not script `./run.sh` while the user has already launched via the desktop icon; rely on HMR | -| `run.sh` leaves `"beforeDevCommand": ""` in tauri.conf.json if its cleanup trap is bypassed (e.g. SIGKILL) | Cleanup trap restores `"npm run dev"` on graceful exit; SIGTERM (not SIGKILL) is the right kill signal | -| `/proc/asound/cards` header lines have leading whitespace for 2-digit card ID alignment | Parser trims leading whitespace before checking for leading digit | +## Full pre-push verification (Phase 5) -## How to resume +Run at end of session — see commit log after `509b983` for the verification commit, and `outputs/` for the full log. -``` -Picking up Kon dogfooding from 2026/04/19. -HANDOVER is at HANDOVER.md in the project root. -Active priorities: (1) confirm resize/drag/mic cleanup, (2) Task 7 MicroSteps -dogfood with kon-llm stub, (3) Settings UX brainstorm. -``` +## Anchors + +- Previous handover: [HANDOVER-2026-04-19.md](HANDOVER-2026-04-19.md) +- Release-blocker index: [docs/issues/README.md](docs/issues/README.md) +- Rebrand memory: `~/.claude/projects/-home-jake-Documents-CORBEL-Main/memory/project_corbie_rebrand.md` +- Active-focus upstream: `context/active-focus.md` in CORBEL-Main