• bvandeusen released this 2026-04-29 16:04:58 -04:00 | 670 commits to main since this release

    Closes the 4/29 dentist-appointment investigation. Two complementary structural fixes plus the held-back EventSlideOver UX refactor.

    Event-store data integrity

    #160 — Duration replaces end_dt at the storage layer. Schema migration 0043 adds duration_minutes (with >= 0 CHECK constraint) and drops end_dt. Wire format unchanged — end_dt is now a derived @property. End-before-start is structurally inexpressible. The corrupt prod row that triggered this work backfills to duration_minutes=NULL automatically.

    Behavioral upgrade: moving an event's start now slides the effective end forward (preserving duration), instead of corrupting or hard-rejecting.

    #161 — Tool layer disambiguates multi-match. When update_event or delete_event get a query that matches 2+ events, the tool returns success: false with a candidates array. The model picks one by passing event_id on the next call. Pre-fix: both tools silently took matches[0], which is exactly how the dentist event got applied to the wrong row.

    Calendar UX

    EventSlideOver redesigned as a centered modal. Auto-save on close (X / Esc / backdrop click / Enter in form). Trash icon in the header (edit mode only). Invalid form in edit mode → toast + discard; in create mode → silent discard. Removes the right-edge floor band where the destructive Delete button was visually invisible.

    Reverted in-flight

    94b169f (A+B hotfix) is reverted by b7e7073 — superseded by #160. The hotfix made bad data filterable; #160 makes it inexpressible.


    46 calendar/events tests pass. Ruff clean. Schema migration runs automatically on container restart. Tag push triggers the build.

    Downloads
  • bvandeusen released this 2026-04-29 12:11:12 -04:00 | 676 commits to main since this release

    Hotfix-style follow-up to v26.04.29.1.

    Anti-placeholder rule on create_event

    The model was creating events with stand-in titles ("Appointment") and "details TBD" descriptions when the user mentioned a future event without concrete specifics, instead of asking for the missing pieces first. The placeholder title then never got updated when the user supplied real details.

    The create_event tool description now names the failure mode explicitly and instructs: record a moment, ask for the missing pieces, and call create_event once with the actual title, time, and location. Pairs with the capture-first persona changes from v26.04.29.1.

    Pure prompt change. 18 calendar-tool tests pass; ruff clean. No schema or migration.

    Downloads
  • bvandeusen released this 2026-04-29 10:38:03 -04:00 | 678 commits to main since this release

    Calendar tool — date/time handling made model-agnostic

    A "schedule for this Friday at 8am" request landed on Thursday. Two distinct fault lines fixed:

    • Split start into start_date + start_time — a YYYY-MM-DD string carries no TZ for the model to mis-tag, so the calendar day cannot drift across the local→UTC boundary. Strict regex rejects TZ suffixes on either field. Legacy combined start/end kept as backcompat.
    • Today's weekday anchored in system prompts; expected_weekday validator on create_event/update_event. Prompts now read "Today is Wednesday, 2026-04-29" instead of forcing the model to derive the weekday. The validator rejects mismatches with a self-correcting error and respects the user's local TZ (Tokyo Friday 23:00 stays Friday).

    Journal — three rough edges from real usage

    • Persona tuning — capture-first; helpdesk-style follow-ups banned; emoji ban; first-person moment phrasing required (no more "The user mentioned…").
    • record_moment data hygiene — server-side keyword-overlap guard drops moment→task links that share no meaningful keyword; placeholder filter drops generic single-word place names (work, home, office).
    • Prep filtering — tasks bucketed into due-today / upcoming / overdue (overdue items surface with staleness duration, not as "due today"); events use a TZ-aware day window + proximity filter, fixing recurring events surfacing 5 months out.

    fable-mcp 0.3.0

    Briefing tools removed, journal tools shipped. Reinstall with pipx install --force after deploy.


    53 backend tests pass; ruff clean. No schema or migration changes — deploy-only.

    Downloads
  • bvandeusen released this 2026-04-28 09:13:40 -04:00 | 686 commits to main since this release

    Day after the journal/Scribe rebrand, the design system shipped end-to-end and several adjacent issues surfaced during verification got resolved.

    Headline

    • Design system applied across the whole app — dusty violet #5B4A8A accent replaces indigo; warm parchment light mode (#F5F1E8 page, #FBF8F0 cards) replaces white-and-cool-blue; Obsidian/Iron/Pewter dark mode replaces cool grey; Inter loaded for body, JetBrains Mono for code, Fraunces still for headings ≥18px. The Hybrid accent rule is enforced — Save buttons are Moss green, Cancel is Bronze, Delete is Oxblood with a Trash icon, brand-moment CTAs (chat send, journal send, "Open Workspace") keep the dusty-violet gradient.
    • 60 hand-inlined SVGs replaced with Lucide across 15 files. Every chrome icon is now 16 or 24px. Emoji-as-icons (, , 🎤, 📎, , , ×, /) swept.
    • Journal config returned to Settings inside the Profile tab. Locations (home/work geocode), temperature unit, prep schedule (auto-generate toggle, prep time, day rollover hour) — the data the deleted Briefing tab used to set is editable again.
    • Weather + events fixes/api/journal/weather now serves cached weather regardless of age (matches the prep's behavior) and auto-refreshes stale rows in the background. Events window widened from "now → +14 days" to "today 00:00 → +14 days" so events earlier today still surface in the right rail.
    • Long-form reading line-height (1.7) on .prose — Note viewer, Task viewer, chat assistant bubbles, journal prep all read like considered prose instead of UI snippets.
    • Italic stripped from chrome — 42 declarations across 24 files. Italic now means "emphasis" only; markdown content emphasis (<em>/<i>) is preserved via browser default.

    Fixes

    • ProjectView Tasks tab counter no longer shows NaN when a status bucket is empty (services/projects.py initialises task_counts with all three lifecycle keys at 0)
    • TaskEditor preview body no longer overflows on top of the WorkLog section (preview pane + work log no longer flex-shrink in the column)
    • Calendar Month/Year title renders Inter, not Fraunces (FullCalendar uses an <h2> element which got caught by the global Fraunces rule)
    • Header status dots brightened so "Ready" reads as a vital green (#4ade80), not muted Moss
    • KnowledgeView filter labels and NoteEditor entity-field labels enlarged to readable size

    Migrations

    None required. Settings already had journal_config from the prior release; today's changes only add UI for fields that already existed.

    Documentation

    • docs/design-system.md updated with the per-PR ship table and explicit "Out of scope — deferred indefinitely" subsection
    • docs/architecture.md, docs/features.md, docs/api-reference.md cleared of stale briefing references; current state describes the journal system

    Deploy notes

    • Pull the new image; no manual migration step
    • After deploy, configure Settings → Profile → Locations to populate the journal's right-rail weather (the auto-refresh kicks in on the next page load once locations are set)

    What's deferred

    • Lucide stroke-weight overrides (1.5/1 vs current 2)
    • Filled-as-active icon state
    • New-user onboarding wizard (tracked as Fable task #155)
    • Flutter app surface phase (foundation port shipped today; surface phase tracked as #156)
    Downloads
  • bvandeusen released this 2026-04-27 08:12:56 -04:00 | 708 commits to main since this release

    A substantial release. Five days of work bundled together.

    Headline

    • Rebrand: Fabled Assistant → Fabled Scribe (user-visible strings, repo, image path; internal package + DB unchanged)
    • Briefing → Journal: day-anchored conversational surface where you record your day. Daily LLM-generated prep at the top, conversational chat below, silent record_moment extractions in the background.
    • RSS retired end-to-end (services, models, tools, NewsView, article-discuss flow, DB tables). The URL-generic read_article tool survives.
    • Routing: / now lands on /journal; Knowledge moved to /knowledge as its own route.
    • Design system doc captures the FabledSword baseline + Scribe's iteration decisions. UI polish pass deferred.

    Migrations (apply on container start)

    • 0040 — rename conversations.briefing_dateday_date; delete all briefing conversations + briefing_config settings
    • 0041 — add moments + 4 junction tables + moment_embeddings
    • 0042 — drop RSS tables; clear rss_enabled / briefing_*_topics settings

    Breaking

    • All prior briefing conversations and briefing_config user settings are deleted by migration 0040. By design, no recovery.
    • All RSS feeds, items, reactions, and embeddings are dropped by 0042. By design, no recovery.

    Deploy notes

    • Pull the new image; migrations run on startup
    • Force-regenerate today's prep via mcp__fable__fable_trigger_journal_prep to pick up the latest prompt-tuning
    • Flutter app's matching journal-replaces-briefing migration was pushed to FabledApp dev and will land in its next APK release

    What's deferred

    • Polish pass applying the design system to existing UI
    • End-of-day moment synthesis
    • Native Android journal UX (the Flutter app currently has the migrated screen but isn't yet the polished journal experience the web side is iterating toward)
    Downloads
  • bvandeusen released this 2026-04-22 15:11:24 -04:00 | 732 commits to main since this release

    Highlights

    Project workspace (/workspace/:projectId) redesigned around tasks + notes as the main surface. Chat is now a bottom-anchored floating widget modeled on the Knowledge view's mini-chat.

    Layout

    • Two-column grid: tasks (0.85fr) | notes (2.15fr) — down from three equal-ish columns.
    • Chat header toggle removed; only Tasks | Notes remain.

    Chat widget

    • Bottom-anchored dock, centered within --page-max-width, rounded top corners.
    • Collapsed = input-only. Expanded = full ChatPanel above the input (500px tall).
    • Pinned per-project conversation survives page reloads; delete-if-empty-and-new on unmount.
    • Restart ↻ — detaches current conversation and starts fresh; old conversation remains discoverable.
    • History ▾ — dropdown lists conversations where rag_project_id === projectId.
    • Widget owns the SSE streamingToolCalls watcher; emits note-changed and task-changed events to the view.

    Notes panel polish

    • Notes-picker rail widens from 155px → 200px and gains --color-bg-card so it no longer visually merges with the tasks panel.
    • Active-note indicator moved from the left edge to the right edge (pointing at the editor).
    • Dropped horizontal dividers between title / tags / toolbar / body — the chrome reads as one unified field.
    • Note title bumped to 1.4rem Fraunces serif with generous row padding.
    Downloads
  • bvandeusen released this 2026-04-17 23:34:20 -04:00 | 741 commits to main since this release

    Highlights

    • Unified lookup toollookup replaces search_web. Runs Wikipedia summary + SearXNG search in parallel. Current events no longer get masked by generic role articles.
    • Wikipedia thumbnails inline — when the summary includes an image, it's cached via the existing /api/images/ pipeline and embedded in the reply.
    • Wikipedia in research pipeline — added alongside SearXNG as a source for deep-research notes.
    • Weather card UX — hourly precipitation summaries, peak-hour column, manual refresh button.
    • Briefing events widget — next 2 weeks of events grouped by day below the weather card.

    Fixes

    • Article extraction in lookup serialized to avoid a libxml2 double-free crash.
    • Several test-patching fixes.
    Downloads
  • bvandeusen released this 2026-04-17 07:16:41 -04:00 | 757 commits to main since this release

    Allow Fraunces Google Font by adding fonts.googleapis.com to CSP style-src and fonts.gstatic.com to font-src.

    Downloads
  • bvandeusen released this 2026-04-16 20:24:07 -04:00 | 759 commits to main since this release

    Hotfix: add wasm-unsafe-eval to CSP script-src so onnxruntime-web can compile the Silero VAD WASM binary. Also surfaces VAD init errors as a UI toast.

    Downloads
  • bvandeusen released this 2026-04-16 19:37:14 -04:00 | 761 commits to main since this release

    Highlights

    • Silero VAD voice detection — Replace amplitude-based silence detection with Silero VAD v5 ONNX for robust speech-vs-noise classification on web
    • Briefing 2-column layout — Weather + news in a single sidebar with tabbed locations and table-based forecast
    • UI polish — Remove chat input bar border divider, container-query scaling for forecast icons
    • CI fix — Switch node_modules cache to npm download cache
    Downloads