diff --git a/docs/brief/research-grounded-design-audit.md b/docs/brief/research-grounded-design-audit.md new file mode 100644 index 0000000..f40ff2f --- /dev/null +++ b/docs/brief/research-grounded-design-audit.md @@ -0,0 +1,234 @@ +--- +title: "Research-Grounded Design Audit" +description: "Point-in-time audit of Kon against the research-grounded cognitive-load, executive-function, and accessibility memo." +last_updated: 2026-04-26 +--- +# Research-Grounded Design Audit — Kon vs. Cognitive-Mercy Research + +> Companion to [research-grounded-design-principles.md](research-grounded-design-principles.md). +> Date: 2026-04-26. Product-code snapshot: `a15167c`. + +## Spine + +Kon's design thesis is cognitive mercy: reduce working-memory load, preserve state, make return painless, avoid shame, avoid forced categorisation, and let users outsource sequencing without feeling broken. This audit judges every recommendation against that spine. Motivational-app patterns — accountability, social presence, partner sharing, streak pressure, or nudges harder than a quiet digest — are out-of-product-scope by design, not deferred. + +## Methodology + +- Source memo: [research-grounded-design-principles.md](research-grounded-design-principles.md), committed as a reference document. +- Code evidence: prior parallel-Explore audit provided in the planning context, then direct source spot-checks against product code at `a15167c`. +- Visual evidence: no screenshots committed. The file:line references below are the durable source of truth. +- Vite/Playwright limitation: backend-dependent flows such as real model loading, live transcription, and transcript history were audited from source only. + +Evidence strength is graded independently from alignment: + +- 🟢 **Strong** — direct Kon-relevant evidence: RCT, large meta-analysis, or established practice standard for at least one actual Kon population. +- 🟡 **Moderate** — convergent evidence: adjacent populations, robust design-pattern evidence, or strong mechanism-grounded inference. +- 🟠 **Weak / emerging** — single-source, small-n, transitive inference only, or active research area without consensus. +- ⚫ **Contested / null** — failed replications, null effects under adequate power, or live methodological debate. + +## Summary Table + +| Feature/challenge | Alignment | Evidence | Gap tier | One-line verdict | +|---|---:|---:|---|---| +| Cognitive-load lens | ✅ | 🟡 | — | Cognitive mercy is the product spine: offload, preserve state, avoid shame. | +| Voice capture | ✅ | 🟢 | — | Local Whisper, low-friction capture, raw transcript remains recoverable. | +| MicroSteps decomposition | ⚠️ | 🟢 | T1 | Aligned except no implementation-intention phrasing. | +| MicroStep step-count fixed at 3-7 | ⚠️ | 🟡 | T2 | Hard-coded range; no user granularity or mastery fade. | +| Buckets | ✅ | 🟢 | — | Inbox/Today/Soon/Later, no numeric priority ladder. | +| Match my energy | ⚠️ | 🟡 | T2 | Three-state sort exists; labels/meaning are system-defined. | +| Local-first / privacy | ✅ | 🟢 | — | Product architecture keeps core flows local. | +| Custom vocabulary / contextual biasing | ✅ | 🟢 | — | Profile terms feed Whisper `initial_prompt` and LLM cleanup. | +| Personal acoustic adaptation | ⚪ | 🟢 | OOS | Distinct from contextual biasing; out of current product boundary. | +| Accessibility fonts | ⚠️ | ⚫ | T1 | Font picker is neutral, but Bionic copy overstates benefit. | +| Letter/line spacing | ✅ | 🟢 | — | Live sliders cover the best-supported reading intervention. | +| Reduce motion | ✅ | 🟢 | — | Three-option in-app control resolves system preference. | +| Post-collapse re-entry | ⚠️ | 🟡 | T2 | Morning triage copy is merciful; no >7-day fresh-start state. | +| Unintrusive dopamine loops | ✅ | 🟢 | — | Fixed completion feedback, no variable-ratio reward layer. | +| Capture-to-action gap | ✅ | 🟢 | — | Raw transcript canonical, no required categorisation at capture. | +| Streaks vs momentum | ✅ | 🟢 | — | Streaks absent; visible progress is soft and optional. | +| Notifications and nudges | ⚠️ | 🟡 | T2 | Opt-in OFF, focus-suppressed, capped; no digest-batched mode. | +| Identity framing | ✅ | 🟢 | — | Onboarding and cleanup copy avoid pathology/training framing. | +| Externalised time | ✅ | 🟢 | — | Running ring is always visible when active. | +| Implementation-intention phrasing | 🔴 | 🟢 | T1 | Strongest single citation in the memo; not in the MicroStep prompt. | +| Transition support / re-orientation | 🔴 | 🟡 | T2 | No explicit "where was I?" return state after interrupted MicroSteps. | +| Body doubling / co-presence | ⚪ | 🟠 | OOS | Outside current solo/local-first product boundary. | +| Coach/partner sharing loop | ⚪ | 🟡 | OOS | Turns Kon toward social accountability; not a backlog item. | +| MicroStep mastery / scaffolding fade | 🔴 | 🟡 | T3 | Requires schema/evaluation work; defer. | +| Honest limitations in product copy | ⚠️ | ⚫ | T1 | Some user-facing copy implies certainty where evidence is contested. | + +## Per-Feature Alignment + +### 0. Cognitive-Load Lens + +- **Doc recommends:** treat working memory, initiation, sequencing, and time perception as variable capacity; design Kon as an external cognitive system rather than a training app. +- **Kon does:** current product framing and this audit's spine are cognitive mercy: offload decisions, preserve state, avoid shame, and allow long-term use without implying the user should graduate from the tool. +- **Visual:** code-only. +- **Verdict:** ✅ aligned, 🟡 moderate evidence, no gap. +- **Notes:** this is the load-bearing interpretation for all feature-specific rows below. + +### 1. Voice Capture + +- **Doc recommends:** one-gesture capture, local processing, support for fragments, and transcript drafts that never block saving. +- **Kon does:** first-run copy says "Press the button. Start talking. That's it." ([FirstRunPage.svelte](../../src/lib/pages/FirstRunPage.svelte#L301-L302)); raw Whisper output is explicitly treated as source of truth and recoverable in preview ([preview/+page.svelte](../../src/routes/preview/+page.svelte#L71-L84), [preview/+page.svelte](../../src/routes/preview/+page.svelte#L221-L234)). +- **Visual:** code-only. +- **Verdict:** ✅ aligned, 🟢 strong evidence, no gap. +- **Notes:** severe expressive aphasia remains an honest limitation in the memo, not a current product claim. + +### 2. MicroSteps + +- **Doc recommends:** 3-7 concrete steps, user edit/reject/override, implementation-intention phrasing, user-controlled granularity, and scaffolding fade. +- **Kon does:** the system prompt requires 3-7 concrete physical micro-steps ([prompts.rs](../../crates/llm/src/prompts.rs#L1-L5)); users can decompose, check off, edit, and give feedback ([MicroSteps.svelte](../../src/lib/components/MicroSteps.svelte#L48-L92), [MicroSteps.svelte](../../src/lib/components/MicroSteps.svelte#L218-L305)). +- **Visual:** code-only. +- **Verdict:** ⚠️ partial gap, 🟢 strong evidence, T1/T2/T3 split. +- **Gap detail:** implementation-intention phrasing is missing from the prompt and is the strongest single Tier 1 opportunity. User-adjustable count is Tier 2; mastery fade is Tier 3. + +### 3. Buckets + +- **Doc recommends:** Inbox/Today/Soon/Later, no numeric priorities, Today as the working surface, and no overdue-shame launch state. +- **Kon does:** the Tasks page defines All/Inbox/Today/Soon/Later and avoids P1-P4 style priorities ([TasksPage.svelte](../../src/lib/pages/TasksPage.svelte#L38-L45)). +- **Visual:** code-only. +- **Verdict:** ✅ aligned, 🟢 strong evidence, no gap. +- **Notes:** the audit did not inspect a rendered drag flow, but the structural bucket model matches the memo. + +### 4. Match My Energy + +- **Doc recommends:** quick high/medium/low energy input, skip without penalty, tasks at or below current energy, and user-defined energy meanings. +- **Kon does:** the Tasks page includes current-energy controls and a Match my energy sort ([TasksPage.svelte](../../src/lib/pages/TasksPage.svelte#L56-L65), [TasksPage.svelte](../../src/lib/pages/TasksPage.svelte#L88-L104), [TasksPage.svelte](../../src/lib/pages/TasksPage.svelte#L319-L360)). Energy labels are fixed as High/Medium/Zero ([EnergyChip.svelte](../../src/lib/components/EnergyChip.svelte#L48-L60)). +- **Visual:** code-only. +- **Verdict:** ⚠️ partial gap, 🟡 moderate evidence, T2. +- **Gap detail:** users cannot redefine what each label means for their body, which weakens the Jason energy-envelope grounding. + +### 5. Local-First / Privacy + +- **Doc recommends:** local-only defaults, no transcript-content telemetry, no required account, and privacy perception surfaced clearly. +- **Kon does:** model and transcription paths are local-first in the current architecture; profile vocabulary is resolved locally before transcription ([transcription.rs](../../src-tauri/src/commands/transcription.rs#L157-L180), [transcription.rs](../../src-tauri/src/commands/transcription.rs#L251-L282)). +- **Visual:** code-only. +- **Verdict:** ✅ aligned, 🟢 strong evidence, no gap. +- **Notes:** the memo correctly labels direct local-first-vs-cloud disclosure evidence as transitive rather than RCT-backed. + +### 6. Custom Vocabulary / Per-Profile Language + +- **Doc recommends:** first-class user vocabulary, low-friction learning, local persistence, and corrections feeding future recognition. +- **Kon does:** profile terms are joined into Whisper `initial_prompt` ([mod.rs](../../src-tauri/src/commands/mod.rs#L26-L62)); Whisper passes that prompt through to `set_initial_prompt` ([whisper_rs_backend.rs](../../crates/transcription/src/whisper_rs_backend.rs#L51-L78)); cleanup appends custom vocabulary spellings ([llm_client.rs](../../crates/ai-formatting/src/llm_client.rs#L51-L65)); the viewer can learn terms from edits ([viewer/+page.svelte](../../src/routes/viewer/+page.svelte#L124-L132)). +- **Visual:** code-only. +- **Verdict:** ✅ aligned for contextual vocabulary, 🟢 strong evidence, no gap. +- **Boundary:** personalised acoustic adaptation is separate from contextual biasing and is explicitly out-of-product-scope research for now. + +### 7. Accessibility: Fonts, Bionic Reading, Spacing, Motion + +- **Doc recommends:** honest framing for OpenDyslexic/Lexend/Bionic, adjustable size/spacing, no italics for extended reading, and `prefers-reduced-motion` plus an in-app control. +- **Kon does:** font picker, font size, letter spacing, line height, transcript size, Bionic toggle, and reduce-motion control are present ([AccessibilityControls.svelte](../../src/lib/components/AccessibilityControls.svelte#L40-L111)); defaults and DOM application include Lexend, Atkinson, OpenDyslexic, 16px, 1.5 line-height, Bionic off, and reduce motion system ([preferences.svelte.ts](../../src/lib/stores/preferences.svelte.ts#L29-L47), [preferences.svelte.ts](../../src/lib/stores/preferences.svelte.ts#L81-L98)). +- **Visual:** code-only. +- **Verdict:** ⚠️ partial gap, ⚫ contested for branded font/Bionic claims, 🟢 strong for spacing/motion, T1 honest-copy fix. +- **Gap detail:** "Bold the first few characters of each word for faster scanning" overstates a contested/null evidence base ([AccessibilityControls.svelte](../../src/lib/components/AccessibilityControls.svelte#L104-L105)). + +## Per-Challenge Alignment + +### A. Post-Collapse Re-Entry + +- **Doc recommends:** a fresh-start state after >7 days away, one-tap backlog bankruptcy, no overdue counts, and no catch-up framing. +- **Kon does:** morning triage is optional, capped at three, and explicitly avoids overdue/failed framing ([MorningTriageModal.svelte](../../src/lib/components/MorningTriageModal.svelte#L1-L15), [MorningTriageModal.svelte](../../src/lib/components/MorningTriageModal.svelte#L120-L170)). Copy says "Yesterday's open items. The rest can wait." ([MorningTriageModal.svelte](../../src/lib/components/MorningTriageModal.svelte#L202-L207)). +- **Visual:** code-only. +- **Verdict:** ⚠️ partial gap, 🟡 moderate evidence, T2. +- **Gap detail:** there is no special >7-day return detection, fresh-start copy, or Inbox bankruptcy action. + +### B. Unintrusive Dopamine Loops + +- **Doc recommends:** fixed-schedule, completion-contingent feedback; no variable-ratio reward, streak pressure, surprise confetti, or forced sound. +- **Kon does:** focus-timer completion is deterministic and brief ([focusTimer.svelte.ts](../../src/lib/stores/focusTimer.svelte.ts#L71-L83), [focusTimer.svelte.ts](../../src/lib/stores/focusTimer.svelte.ts#L150-L178)); task completion dispatches plain state/events rather than a reward loop ([page.svelte.ts](../../src/lib/stores/page.svelte.ts#L503-L514)). +- **Visual:** code-only. +- **Verdict:** ✅ aligned, 🟢 strong evidence, no gap. +- **Notes:** completion sound exists for the focus timer; general sound cues default off in settings ([page.svelte.ts](../../src/lib/stores/page.svelte.ts#L58-L59)). + +### C. Capture-To-Action Gap + +- **Doc recommends:** optimise time-to-first-syllable, allow nameless/untyped thought dumps, preserve in-progress state, and keep original transcript canonical. +- **Kon does:** raw transcript recovery is explicit ([preview/+page.svelte](../../src/routes/preview/+page.svelte#L71-L84)); auto-title prompt treats speech as data, not instructions, and does not invent facts ([prompts.rs](../../crates/llm/src/prompts.rs#L46-L59)); task extraction omits non-commitments rather than forcing categorisation ([prompts.rs](../../crates/llm/src/prompts.rs#L61-L66)). +- **Visual:** code-only. +- **Verdict:** ✅ aligned, 🟢 strong evidence, no gap. +- **Notes:** real hotkey/lock-screen performance was not measured in this docs-only audit. + +### D. Streaks Vs Momentum + +- **Doc recommends:** no streak counters, no streak-loss framing, no leaderboards, and any progress shown over softer ranges. +- **Kon does:** settings define no streak mechanic; momentum sparkline is optional and separate from the "N today" badge ([types/app.ts](../../src/lib/types/app.ts#L125-L130)); defaults keep the sparkline on but not a consecutive-use metric ([page.svelte.ts](../../src/lib/stores/page.svelte.ts#L82-L85)); design docs explicitly prohibit streak-shaming ([design-principles.md](design-principles.md#L28)). +- **Visual:** code-only. +- **Verdict:** ✅ aligned, 🟢 strong evidence, no gap. +- **Notes:** "N today" is same-day completion acknowledgement, not a streak. + +### E. Notifications And Nudges + +- **Doc recommends:** silent, batched, user-controlled notifications; no push by default; compassionate language; OS quiet-hour respect. +- **Kon does:** nudges default off ([page.svelte.ts](../../src/lib/stores/page.svelte.ts#L82-L84)); nudge suppression requires enabled/unmuted, no document focus, and under 3/hour ([nudgeBus.svelte.ts](../../src/lib/stores/nudgeBus.svelte.ts#L12-L21), [nudgeBus.svelte.ts](../../src/lib/stores/nudgeBus.svelte.ts#L94-L128)); morning nudge copy is gentle ([nudgeBus.svelte.ts](../../src/lib/stores/nudgeBus.svelte.ts#L177-L195)). +- **Visual:** code-only. +- **Verdict:** ⚠️ partial gap, 🟡 moderate evidence, T2. +- **Gap detail:** the current bus is immediate-triggered with caps; it does not offer a 1-3 daily digest batching mode. + +### F. Identity Framing + +- **Doc recommends:** capability/scaffolding language, no cure/training framing, no pathology onboarding, and user work visible as mastery evidence. +- **Kon does:** first-run copy is minimal and non-pathologising ([FirstRunPage.svelte](../../src/lib/pages/FirstRunPage.svelte#L301-L302)); cleanup prompt frames AI as translator, not editor, preserving the user's meaning ([llm_client.rs](../../crates/ai-formatting/src/llm_client.rs#L8-L49)); raw transcript remains available as the user's own words ([preview/+page.svelte](../../src/routes/preview/+page.svelte#L71-L84)). +- **Visual:** code-only. +- **Verdict:** ✅ aligned, 🟢 strong evidence, no gap. +- **Notes:** rebrand work is unrelated to this audit. + +### G. Literature-Surfaced Gaps + +- **Externalised time:** Kon has a persistent focus timer that survives window close/reopen ([focusTimer.svelte.ts](../../src/lib/stores/focusTimer.svelte.ts#L1-L13), [focusTimer.svelte.ts](../../src/lib/stores/focusTimer.svelte.ts#L180-L208)) and a visible running ring with controls ([FocusTimer.svelte](../../src/lib/components/FocusTimer.svelte#L102-L193)). Verdict: ✅ aligned, 🟢 strong. +- **Implementation intentions:** MicroStep prompt does not request if-then plans ([prompts.rs](../../crates/llm/src/prompts.rs#L1-L5)). Verdict: 🔴 missing, 🟢 strong, T1. +- **Transition support:** there is no explicit "where was I?" re-orientation on return to an interrupted MicroStep. Verdict: 🔴 missing, 🟡 moderate, T2. +- **Body doubling:** evidence is emerging, but the feature would move Kon away from solo/local-first cognitive mercy. Verdict: ⚪ OOS, 🟠 weak/emerging. +- **Coach/partner loop:** evidence is stronger for severe EF impairment, but the product shape becomes social accountability. Verdict: ⚪ OOS, 🟡 moderate. + +## Corrections From Prior Internal Audit + +1. **Bionic Reading copy overstates the evidence.** `AccessibilityControls.svelte` says "Bold the first few characters of each word for faster scanning" ([AccessibilityControls.svelte](../../src/lib/components/AccessibilityControls.svelte#L104-L105)). The memo treats Bionic Reading evidence as contested/null. The toggle can stay, but the copy should soften. Captured as Tier 1 #2. + +## Minor UX Notes Not Driven By The Memo + +- **MicroStep `Just Start` timer launch hover-reveals.** The running timer ring itself is always visible, so externalised time remains aligned. The launch affordance hides until row hover ([MicroSteps.svelte](../../src/lib/components/MicroSteps.svelte#L297-L305)), which drifts from Kon's internal no-hover-to-reveal rule. This is a small CSS follow-up, not a research-memo gap. + +## Prioritised Gaps + +### Tier 1 — Single-PR Sized + +1. **Implementation intentions in MicroStep prompt** — update [prompts.rs](../../crates/llm/src/prompts.rs#L1-L5) so decomposition includes at least one cue-anchored "when X, then Y" step. This is the strongest evidence-to-effort item in the memo. +2. **Honest accessibility-font + Bionic copy** — soften [AccessibilityControls.svelte](../../src/lib/components/AccessibilityControls.svelte#L104-L105) and add a short note under the font picker that font choices are personal preferences with contested evidence. + +### Tier 2 — Multi-Component + +3. **Re-entry / fresh-start trigger after long absence** — detect >7-day absence in the shell or morning triage flow; switch copy to "Welcome back. This week starts fresh."; offer one-tap Inbox bankruptcy. +4. **Notifications digest mode** — add an opt-in digest mode with 1-3 user-set times alongside the immediate nudge bus. Defaults remain OFF. +5. **User-adjustable MicroStep count** — expose granularity preference and thread it through the decomposition prompt. +6. **"Where was I?" MicroStep re-orientation** — show the just-completed step and next step when returning to an interrupted decomposition. +7. **User-defined energy meaning** — let users edit labels and descriptions for High/Medium/Zero. + +### Tier 3 — Roadmap / Schema Work + +8. **MicroStep mastery / scaffolding fade** — track completion patterns and offer to fold familiar routines back into single tasks. Requires schema work and evaluation. + +### Out-Of-Product-Scope Research Projects + +- **Body doubling / co-presence layer.** Outside Kon's current solo/local-first product boundary; would push the app toward social accountability. +- **Coach / partner sharing loop.** Same product-boundary issue, even where the evidence is stronger for severe EF impairment. +- **Personal acoustic adaptation / per-user model fine-tunes.** Distinct from contextual vocabulary; requires opt-in data, evaluation, and storage design before it could belong in product. + +Out-of-product-scope by design, not deferred. + +## Honest-Copy Items + +- **Bionic Reading:** change "for faster scanning" to preference-based wording. +- **Accessibility font picker:** add one sentence that OpenDyslexic/Lexend/Bionic evidence is contested and the picker is for comfort/preference. +- **Match my energy:** if surfaced in product explanation, ground it in Jason's energy-envelope model; mention spoon theory only as a communication metaphor. + +## Open Questions For Jake + +- Keep this audit docs-only, or eventually surface a short methodology line in an in-app About/Methodology screen? +- Fold Tier 1 into v0.1 work, or queue it immediately after v0.1? + +## Next Actions + +- Tier 1 items each get a focused follow-up plan. +- Tier 2 items get a brief design conversation before plan-writing. +- Tier 3 stays on roadmap. +- Out-of-product-scope items are not picked up unless the product boundary is intentionally reopened.