agent: lumotia — v0.1 release-completion run
Closes the code-side v0.1 ship gate. All quality gates green: cargo fmt/clippy/test (~327 tests), npm check (0/0), vitest 13/13, scripts/dogfood-rebrand-drill.sh 8/8. Phase F — first-run onboarding promoted to v0.1 - FirstRunPage with skip-to-main + failure recovery + event recording - Six onboarding commands (record/list/has-completed + lumotia_events) - Storage migration v17 (onboarding_events + lumotia_events tables) UI hardening (in-scope items from v0.1-ui-hardening.md) - StatusPill + PostCaptureCard components, 21st preview entry - Sidebar recording-as-sacred-state (opacity + aria-disabled, reduced-motion) - Settings 6-section regroup + Help section + Activation log + Privacy toggle - Error-state copy sweep (DictationPage + SettingsPage, plain-language) - Global :focus-visible rule, textarea outlines restored - Ctrl+K / Ctrl+, / Escape bindings in +layout LLM resilience - rule_based_extract_tasks (regex-free imperative-verb extractor) + extract_tasks_with_fallback wrapper — task extraction never returns zero - tokio::time::timeout(120s) wraps cleanup/tags/tasks commands Release artefacts - LICENSE (canonical AGPL-3.0), CHANGELOG (Keep-a-Changelog format) - v0.1-release-notes, privacy-and-ai-use, install-warnings, tester-onboarding-kit, tester-acceptance-runbook, code-signing-setup, apple-silicon-rb08-runbook, virtual-audio-setup, v0.1-contrast-audit - Workspace versioning + AGPL spdx; npm exact-pin (10 ranges removed) - AppImage SHA-256 sidecar in build.yml - README v0.1 section + Reporting-issues; canonical repo slug Closure pass — items moved from human-required to code-complete - KI-02 Linux idle inhibit: zbus 5 → org.freedesktop.login1.Manager.Inhibit - KI-03 Windows sleep prevention: SetThreadExecutionState(ES_CONTINUOUS|...) - acquire/release_idle_inhibit Tauri commands, wired in DictationPage - Diagnostic-bundle frontend wire-up (Settings → Help button) - WCAG-AA contrast fix via .btn-filled-text utility (no token changes) - 8 destructive-action sites wrapped in plain-language confirm() guards - KNOWN-ISSUES.md + v0.1-known-limitations.md updated (KI-02/03 fixed) Scripts - pre-tag-verify.sh, tag-day.sh, smoke-linux + driver - parse-diagnostic-bundle.sh, parse-activation-log.py Per-item audit trail: docs/release/v0.1-completion-status.md Remaining: W-01…W-08 (signing certs, hardware probes, smoke matrix, tester recruitment) — see docs/release/v0.1-known-limitations.md.
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
import FocusTimer from "$lib/components/FocusTimer.svelte";
|
||||
import MorningTriageModal from "$lib/components/MorningTriageModal.svelte";
|
||||
import { hasTauriRuntime } from "$lib/utils/runtime.js";
|
||||
import { loadOsInfo, isLinux } from "$lib/utils/osInfo.js";
|
||||
import { loadOsInfo, isLinux, isMac } from "$lib/utils/osInfo.js";
|
||||
import { page, settings, saveSettings } from "$lib/stores/page.svelte.js";
|
||||
import {
|
||||
getPreferences,
|
||||
@@ -225,13 +225,50 @@
|
||||
}
|
||||
|
||||
function handleKeydown(e) {
|
||||
if (e.key === "Escape" && page.taskSidebarOpen) {
|
||||
page.taskSidebarOpen = false;
|
||||
return;
|
||||
}
|
||||
if (e.key === "[" && !isInputFocused(e)) {
|
||||
settings.sidebarCollapsed = !settings.sidebarCollapsed;
|
||||
saveSettings();
|
||||
try {
|
||||
// Escape: close task sidebar first, then broadcast for any open modal.
|
||||
if (e.key === "Escape") {
|
||||
if (page.taskSidebarOpen) {
|
||||
page.taskSidebarOpen = false;
|
||||
return;
|
||||
}
|
||||
// Let each modal own its close logic — dispatch and let them listen.
|
||||
window.dispatchEvent(new CustomEvent("lumotia:escape"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Modifier key shortcuts — skip when focus is in a text field.
|
||||
const modKey = isMac() ? e.metaKey : e.ctrlKey;
|
||||
|
||||
// Ctrl+K / ⌘+K — jump to History and focus the search input.
|
||||
if (modKey && e.key === "k" && !isInputFocused(e)) {
|
||||
e.preventDefault();
|
||||
if (page.current === "history") {
|
||||
window.dispatchEvent(new CustomEvent("lumotia:focus-search"));
|
||||
} else {
|
||||
page.current = "history";
|
||||
// After the page renders, ask the search input to take focus.
|
||||
// rAF gives Svelte one tick to mount the History page.
|
||||
requestAnimationFrame(() => {
|
||||
window.dispatchEvent(new CustomEvent("lumotia:focus-search"));
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Ctrl+, / ⌘+, — open Settings.
|
||||
if (modKey && e.key === "," && !isInputFocused(e)) {
|
||||
e.preventDefault();
|
||||
page.current = "settings";
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.key === "[" && !isInputFocused(e)) {
|
||||
settings.sidebarCollapsed = !settings.sidebarCollapsed;
|
||||
saveSettings();
|
||||
}
|
||||
} catch {
|
||||
// A keydown error must never silence the listener — swallow silently.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,9 +380,16 @@
|
||||
await profilesStore.load();
|
||||
|
||||
try {
|
||||
const completed: boolean = await invoke("has_completed_onboarding");
|
||||
const whisper = await invoke("list_models");
|
||||
const parakeet = await invoke("list_parakeet_models");
|
||||
if (whisper.length === 0 && parakeet.length === 0) {
|
||||
const noModels = whisper.length === 0 && parakeet.length === 0;
|
||||
const replayRequested = sessionStorage.getItem("lumotia:replay-tutorial") === "1";
|
||||
|
||||
if (replayRequested) {
|
||||
sessionStorage.removeItem("lumotia:replay-tutorial");
|
||||
page.current = "first-run";
|
||||
} else if (!completed && noModels) {
|
||||
page.current = "first-run";
|
||||
}
|
||||
} catch {
|
||||
|
||||
Reference in New Issue
Block a user