47e248d9ac
- README.md: reduced to overview + quick start + links to docs/ - docs/architecture.md: stack, design decisions, data models, key services - docs/configuration.md: all env vars, docker-compose setup, production + security - docs/development.md: dev workflow, CI/CD, migrations, release process - docs/features.md: detailed feature breakdown + keyboard shortcuts - docs/api-keys-and-mcp.md: API key management + Fable MCP install guide - docs/sso-oauth.md: OAuth/OIDC setup (replaces docs/oauth-setup.md) - docs/changelog.md: development history from summary.md - Remove summary.md (content distributed across docs/) - Remove docs/oauth-setup.md (superseded by docs/sso-oauth.md) - .gitignore: add .mcp.json Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
10 KiB
10 KiB
Changelog
Development history — most recent first.
2026-03-24 — fable-mcp serve, admin log tool, Settings MCP install UI
- Dockerfile — builds
fable-mcpwheel into/app/dist/at image build time routes/fable_mcp_dist.py—GET /api/fable-mcp/info(availability check) andGET /api/fable-mcp/download(wheel download)fable_mcp/tools/admin.py—get_app_logs()calling/api/admin/logsfable_mcp/server.py—fable_get_app_logsMCP tool- SettingsView — "Fable MCP" section in API Keys tab: wheel download button and install instructions
- ci.yml —
fable-mcp/**added to trigger paths
2026-03-23 — fable-mcp scaffold + all tools
fable-mcp/Python package scaffolded (pyproject.toml,hatchlingbuild)FableClient— async httpx wrapper withFABLE_URL+FABLE_API_KEYauth- Tool modules:
notes,tasks,projects,milestones,search,chat,admin server.py— FastMCP stdio transport; all tools registered- Settings UI — API Keys tab with create/revoke,
.envdownload, Claude config download routes/api_keys.py—POST /api/api-keys,GET /api/api-keys,DELETE /api/api-keys/:id
2026-03-23 — Model management UI, RSS category/refresh, weather city search
- SettingsView — Model Management section: list installed models (size, loaded state), pull by name (SSE progress), delete unused
routes/chat.pylist_models_route— also hits/api/psin parallel; returnsloaded: boolandmodified_atper model- RSS feeds — category badge, last-fetched age, manual refresh button, category input on add
routes/briefing.py—POST /api/briefing/feeds/refreshtriggers immediate re-fetchget_weathertool — now accepts any city name (geocodes via Nominatim + fetches Open-Meteo); not limited to pre-configured locations
2026-03-22 — Briefing scheduler fix, quick capture fix, task back navigation
- Briefing scheduler — fixed deadlock:
start_briefing_schedulermade async; replacedrun_coroutine_threadsafe(...).result()withawait(was blocking the event loop thread) - Briefing pipeline — added early return when both LLM synthesis lanes produce empty strings (was always prepending "Good morning" on failure)
- Quick capture — fixed: was always creating notes. Two causes fixed: (1) now uses user's
default_modelsetting instead ofConfig.OLLAMA_MODEL; (2) removedcreate_projectfrom classifier prompt (tool not offered, causing fallback to note) - TaskViewerView — back button navigates to task's project when
project_idis set; Esc handler registered in capture phase to prevent conflict with App.vue global handler
2026-03-21 — Briefing RSS + project kanban advance buttons
- ProjectView kanban — status-advance buttons on task cards (→ todo→in_progress, ✓ in_progress→done), hidden until hover
- Briefing UI — RSS feeds section: add URL + category, list feeds with last-fetched age badge, delete, manual refresh
2026-03-16 — Fuzzy project resolution, create_project guard, task embedding fix
services/tools.py—_resolve_projectrewritten with 4-step lookup: (1) exact DB match, (2)query in titlesubstring, (3)title in queryreverse substring, (4) SequenceMatcher ≥ 0.55. Partial names now reliably resolve without creating duplicates.services/tools.py—create_projecthandler: similar-project checks (threshold 0.55) run before theconfirmedgate, soconfirmed=truecannot bypass them.routes/tasks.py— fire-and-forgetupsert_note_embeddingadded to create and update routes (tasks weren't getting embeddings via REST API).services/briefing_pipeline.py—await is_caldav_configured()fix (was called without await — latent bug since the function became async).services/notes.py— removed erroneous duplicatecount_query.where(Note.parent_id == parent_id)that was applied inside theno_projectbranch.
2026-03-12 — CI release process update
.forgejo/workflows/ci.yml— removedmainfrombranchespush trigger. CI fires only ondevpushes,v*tags. Production release: create release via Forgejo UI onmainwith av*tag → tag push fires CI → build job pushes:latest+:<version>.
2026-03-11 — Daily Briefing (full feature)
Backend:
- Migration
0026_add_briefing_tables.py:rss_feeds,rss_items,weather_cache; addedconversation_typeandbriefing_datetoconversations. services/weather.py: geocoding via Nominatim, forecast via Open-Meteo, per-user DB cache.services/rss.py: feedparser-based fetch, per-feed DB cache prune-to-100.services/briefing_pipeline.py: two-lane parallel gather (weather, RSS, tasks, calendar) → LLM synthesis → GenerationBuffer SSE stream.services/briefing_scheduler.py(APScheduler): slots morning/midday/evening/night with catch-up logic.routes/briefing.py: RSS CRUD at/api/briefing/feeds, weather config, briefing config,POST /api/briefing/trigger.
Frontend:
BriefingView.vue: primary briefing page; digest card + conversation thread + reply bar.BriefingSetupWizard.vue: 4-step setup wizard shown on first visit.- SettingsView: Briefing tab (enable toggle, location geocoding, office days, time slot toggles, RSS CRUD).
- AppHeader: "Briefing" nav link added.
2026-03-11 — Version footer, task history, note version retention
- CalVer build-time version tracking:
DockerfileinjectsBUILD_VERSIONARG; displayed in Settings footer. - Task history moved to collapsible right sidebar (previously modal overlay).
- Note version retention: configurable max versions per note (default 20) enforced at write time.
- Content deduplication in
build_context()— same note cannot appear in multiple context blocks.
2026-03-11 — Multi-user sharing, notifications, groups, backup rewrite
- Migration
0025_add_sharing_and_notifications.py:groups,group_memberships,project_shares,note_shares,notifications. services/access.py:PERMISSION_RANKdict;get_project_permission/get_note_permission— check ownership, direct share, group-based share, note→project inheritance.- Share dialog (
ShareDialog.vue): user tab (search + permission select), group tab, current shares list with inline change/remove. SharedWithMeView.vue:/sharedroute — shared projects and notes.- In-app notification bell with 60s polling; push generated on share/group events.
- Backup rewrite (version 2): includes all tables;
restore_full_backupbuilds ID maps, two-pass note restore forparent_idpatching.
2026-03-10 — Project Workspace, Graph View, settings tabs, message queue persistence
WorkspaceView.vue: 3-panel layout (tasks/chat/notes), collapse toggles, SSE watcher auto-loads notes and refreshes tasks.WorkspaceTaskPanel.vue: milestone-grouped task list, detail slide-over with status cycle + log.WorkspaceNoteEditor.vue: list ↔ TipTap editor, autosave.GraphView.vue: D3 force-directed graph, tag nodes, project hub nodes, physics panel, peek panel.- SettingsView fully rewritten with tabbed layout (General, Account, Notifications, Integrations, Data, Admin).
- Message queue: persisted to localStorage; queued bubbles shown in chat with opacity + "QUEUED" label.
- ToolCallCard: confirm/deny inline; "Create anyway" posts directly to API (no LLM round-trip).
- Duplicate detection: scoped to same
is_tasktype; semantic threshold raised 0.87 → 0.90.
2026-03-10 — "Illuminated Transcript" design language
- Fraunces font for headings; assistant bubbles elevated with left indigo accent + shadow; user bubbles ghosted (transparent bg, muted text).
- Dark palette shifted to slate-indigo (
#111113).--radius-lg12→18px. - Cards: shadow depth replaces borders. Send buttons: indigo gradient + glow.
2026-03-10 — CI/CD infrastructure
infra/Dockerfile.runner-base: Ubuntu 24.04 + Python 3.12 + Node 22 LTS custom runner image.- All CI jobs use
py3.12-node22runner; pip caching added; Node bumped to 22.
2026-03-06 — Session invalidation on credential change
users.session_versioncolumn; incremented on password change/reset; checked in_check_auth; mismatch evicts all other sessions.
2026-03-06 — DRY refactoring (backend + frontend)
models/base.py:TimestampMixin+CreatedAtMixinapplied to all models (~60 lines removed).routes/utils.py:not_found()+parse_iso_date()helpers.- Frontend composables:
useAutoSave,useEditorGuards,useTagSuggestions,useFloatingAssist,useListKeyboardNavigation. - Shared CSS:
editor-shared.css,viewer-shared.css. Net: −634 lines, +237 lines.
2026-03-06 — Project-aware writing assist, link suggestions, project-scoped RAG
- Writing assist:
context_notesparam injects project notes;definition-tagged notes prioritised. - Link suggestions: detects note titles as plain text in body; one-click wikilink conversion.
- Project-scoped RAG:
rag_project_idparam restricts semantic + keyword search to a project. search_notestool: upgraded to hybrid semantic + keyword;relevancefield in results.- SSRF protection:
_is_private_url()blocks private/loopback addresses;follow_redirects=False. - Config validation:
Config.validate()at startup.
2026-03-05 — Note editor sidebar, full-document writing assist, drafts, version history
- NoteEditorView: two-column layout; writing assistant always visible in sidebar.
whole_docmode: assistant outputs complete revised document (not just selected section).DiffView.vue: standalone diff component with equal-line collapsing (git-style context).- Persistent drafts:
note_draftstable; draft auto-saved after assist generation; restored on load. note_versionstable: auto-snapshot on body change; version browser with diff + restore.
2026-03-05 — Task work log, task editor overhaul
task_logstable;TaskLogSection.vuewith timestamps, duration badges, inline edit.- TaskEditorView: two-column layout with collapsible sidebar; sub-tasks section.
log_workLLM tool added to_CORE_TOOLS.
2026-03-04 — Per-conversation streaming, SSE reconnection, keyboard navigation
- Per-conversation streaming state; auto-new chat on open.
- SSE reconnection: chat
reconnectIfGenerating()on mount + navigation; assist retry loop withLast-Event-ID. - Model load timeout raised 90s → 180s.
- Writing assist retry loop (3 attempts, exponential backoff).