@@ -123,6 +123,45 @@ non-negotiables, each with a test:
123123
124124---
125125
126+ ## Shipped in v0.10.0
127+
128+ Responsiveness, honesty about hardware, and a text-import that actually works —
129+ plus a way for people to send feedback.
130+
131+ - ** The Companion no longer freezes the app.** ` companion_chat ` was a synchronous
132+ command, so a turn — including the tens-of-seconds cold model load on the first
133+ message — ran on the UI thread and locked the whole window until it returned,
134+ which read as a crash. It's now async and runs off the UI thread (like the phone
135+ portal already did). The same fix landed on ** text import** (` parse_experience ` ),
136+ which had the identical problem.
137+ - ** The model pre-warms.** When the Companion comes into view the app quietly loads
138+ the model into memory (` ollama::warm ` → ` companion_warm ` ), so the first real
139+ message arrives at warm speed instead of paying a cold multi-second load.
140+ - ** Compute watcher** (` compute.rs ` ) — local LLMs are memory-bound, so before
141+ someone leans on the Companion the app reads the machine (` sysinfo ` ) and gives a
142+ plain verdict: * ample / tight / insufficient* . It weighs available RAM against the
143+ model's footprint (using Ollama's ` /api/ps ` real resident size when the model is
144+ loaded, and flagging a GPU→CPU spill), preflights a model ** before** the multi-GB
145+ download in setup, and folds in the ** measured tokens/sec** of the last reply so a
146+ machine that fits the model but runs it too slowly is caught honestly. Read-only,
147+ advisory, never a gate.
148+ - ** Import from text, fixed.** It was unreliable and opaque — on the default model
149+ (qwen3:8b) the parse ran with * thinking on* , took minutes (looked hung), and still
150+ under-extracted, so people saw "No doses were detected." Now it runs with
151+ ` think: false ` (a full trip report went from timing out to ~ 30 s with every dose
152+ found), grammar-constrains the reply to a ** JSON schema** for a guaranteed shape,
153+ and uses the substance's standard name so the interaction checker recognises it
154+ (acid→LSD, shrooms→psilocybin, xanax→alprazolam). The UI says what to paste and
155+ what works best, shows the extracted intention/setting/notes (not just doses), and
156+ explains the no-dose case. When no real date was found, fabricated-but-spaced dose
157+ times are rebased onto the start you confirm.
158+ - ** First-run Companion opt-in.** The disclaimer splash on a fresh install now asks
159+ whether to enable the Companion, once (it's optional, on-device, and the safety
160+ layers work either way).
161+ - ** Send feedback → GitHub.** A Settings card opens a prefilled bug report or feature
162+ request as a GitHub issue in the browser. No backend, no telemetry — nothing leaves
163+ the journal; GitHub handles identity and the reports collect in one place.
164+
126165## Shipped in v0.9.1
127166
128167A round of Companion and Settings polish on top of v0.9.0, mostly driven by
@@ -360,6 +399,18 @@ using the model switch and reading the screens as a first-timer would.
360399
361400</details >
362401
402+ 0 . ** Backend timestamp normalization for imports.** Shipped in v0.10.0, text import
403+ rebases fabricated dose/timeline times onto the confirmed start ** in the frontend**
404+ (` rebaseTimestamps ` in ` +page.svelte ` ), because that's where the ` t+ ` date math
405+ already lives and the backend has no date library. That's solid for the common case
406+ but leaves the invariant split across two layers. A cleaner home is the backend: give
407+ ` import_experience ` (` commands.rs ` ) real timestamp parsing (add ` chrono ` , or the
408+ ` time ` crate) so it owns normalization — parse each ` taken_at ` /` at ` , drop the ones it
409+ can't, and when no absolute ` started_at ` was extracted, shift the parseable ones so the
410+ earliest lands on the chosen start while preserving spacing. Then the phone portal's
411+ import path (if it ever gains one) and the desktop share one rule. Small, self-contained,
412+ worth a test that a T+ report rebases correctly and a real-dated one is left untouched.
413+
3634141 . ** Phone portal — log from your phone over Tailscale.** *** Entirely optional; off by
364415 default.*** Field Notes stays a ** fully offline, on-device app as it ships** — this
365416 adds an opt-in way to reach the journal from a phone during a session (the desktop is
0 commit comments