bvandeusen
eb41e772cd
feat(trash): exclude trashed rows from events/projects/milestones/rulebooks/embeddings reads + filtering tests
2026-05-28 20:33:40 -04:00
bvandeusen
e7f214fc80
feat(trash): exclude trashed rows from notes + knowledge read paths
2026-05-28 20:30:23 -04:00
bvandeusen
f80c327ecf
feat(trash): restore/list_trash/purge/purge_expired + alive() helper
2026-05-28 20:02:21 -04:00
bvandeusen
ce47ebc7de
feat(trash): services/trash.py — delete() + cascade-stamp by batch
2026-05-28 20:01:35 -04:00
bvandeusen
7f0d99d383
feat(trash): SoftDeleteMixin applied to the 7 soft-deletable models
2026-05-28 19:54:01 -04:00
bvandeusen
84b75f7a73
feat(trash): migration 0057 — deleted_at + deleted_batch_id on 7 tables
2026-05-28 19:53:19 -04:00
bvandeusen
30fbf7b117
docs(mcp): add conceptual primer (what each entity is for) to MCP instructions
2026-05-28 18:25:38 -04:00
bvandeusen
d04b6f4bba
style(rulebook): narrow the Topics column in /rules
2026-05-28 11:42:08 -04:00
bvandeusen
311322fdc8
fix(plan): export startPlanning from tasks store (type-check)
2026-05-28 11:20:44 -04:00
bvandeusen
dc93675470
feat(plan): KnowledgeView Plans facet + plan badge (knowledge endpoints + UI)
2026-05-28 11:12:59 -04:00
bvandeusen
2f5ef9124a
feat(plan): Start planning button on project view
2026-05-28 10:44:40 -04:00
bvandeusen
b30cf06096
fix(plan): move Applicable Rules panel to TaskEditorView (the routed task surface)
2026-05-28 10:43:41 -04:00
bvandeusen
75d3d40038
feat(plan): plan-task viewer shows Applicable Rules panel
2026-05-28 10:42:03 -04:00
bvandeusen
1d5f49fe3b
feat(plan): frontend startPlanning API + store action + task_kind type
2026-05-28 10:41:24 -04:00
bvandeusen
b250141e15
feat(plan): REST /api/tasks/planning endpoint
2026-05-28 10:17:38 -04:00
bvandeusen
4609abacd8
feat(plan): start_planning MCP tool + get_task rules augmentation + instructions
2026-05-28 10:17:20 -04:00
bvandeusen
e269ac9d5c
feat(plan): services/planning — start_planning aggregator
2026-05-28 10:16:36 -04:00
bvandeusen
737467f996
feat(plan): REST task routes — kind on create + list
2026-05-28 08:22:54 -04:00
bvandeusen
fc4a1627b5
feat(plan): MCP task tools — kind on create_task + list_tasks
2026-05-28 08:22:31 -04:00
bvandeusen
50d2a0e9c0
feat(plan): services/notes — task_kind create param + list filter
2026-05-28 08:21:59 -04:00
bvandeusen
8754b1c94d
feat(plan): task_kind on Note model + to_dict
2026-05-28 08:15:29 -04:00
bvandeusen
ac462d1203
feat(plan): migration 0056 — task_kind column on notes
2026-05-28 08:15:13 -04:00
bvandeusen
5f3da7c004
feat(rulebook): port script — parse FabledRulebook .md → Scribe DB
2026-05-27 22:39:50 -04:00
bvandeusen
9658e9a35c
feat(rulebook): Project Rules tab — applicable rules + subscription chips
2026-05-27 22:20:19 -04:00
bvandeusen
f2afb2a8bf
feat(rulebook): /rules route, nav entry, g+r shortcut
2026-05-27 22:01:54 -04:00
bvandeusen
447adf816c
feat(rulebook): subscription panel — toggle projects per rulebook
2026-05-27 22:01:03 -04:00
bvandeusen
75d8e7ab49
feat(rulebook): RulesView three-pane shell + child panes + rule editor
2026-05-27 22:00:32 -04:00
bvandeusen
605dd0a13a
feat(rulebook): frontend API client + Pinia store
2026-05-27 21:59:23 -04:00
bvandeusen
eab5c5a026
feat(rulebook): augment get_project with applicable_rules + MCP instructions
2026-05-27 21:52:18 -04:00
bvandeusen
a1a6c5e47e
feat(rulebook): MCP tools — 16 tools for rulebook/topic/rule/subscription
2026-05-27 21:51:39 -04:00
bvandeusen
bbbd6b2f28
feat(rulebook): REST routes — rules, subscriptions, applicable rules
2026-05-27 21:34:53 -04:00
bvandeusen
0219c673c1
feat(rulebook): REST routes — rulebook + topic endpoints
2026-05-27 21:34:25 -04:00
bvandeusen
45fe198d54
feat(rulebook): service layer — subscriptions + get_applicable_rules
2026-05-27 21:19:14 -04:00
bvandeusen
d3833ba5a4
feat(rulebook): service layer — Rule CRUD with multi-filter list_rules
2026-05-27 21:18:35 -04:00
bvandeusen
38e4220015
feat(rulebook): service layer — Topic CRUD
2026-05-27 21:17:54 -04:00
bvandeusen
cfd801d181
feat(rulebook): service layer — Rulebook CRUD + find_rulebook_by_title
2026-05-27 21:17:21 -04:00
bvandeusen
45c2197cdf
feat(rulebook): SQLAlchemy models for rulebooks, topics, rules
2026-05-27 21:16:49 -04:00
bvandeusen
05e379263a
feat(rulebook): migration 0055 — rulebooks, topics, rules, subscriptions
2026-05-27 21:16:24 -04:00
bvandeusen
4806c34a3c
refactor: Phase 10 — Ollama service, image cache, config, frontend orphans
...
Final cleanup phase of the MCP-first pivot.
docker-compose:
- docker-compose.yml: drop ollama service + OLLAMA_URL/MODEL env vars +
IMAGE_CACHE / VAPID env comments
- docker-compose.prod.yml: drop ollama service + Ollama env + GPU
reservation
- docker-compose.quickstart.yml: drop ollama service + Ollama env +
GPU-reservation comment; quickstart instructions now point at the
MCP Access tab instead of model-pull
Config:
- Drop OLLAMA_URL, OLLAMA_MODEL, OLLAMA_BACKGROUND_MODEL,
OLLAMA_KEEP_ALIVE_*, OLLAMA_NUM_CTX, EMBEDDING_MODEL (fastembed
is hard-coded inside services/embeddings.py)
- Drop IMAGE_CACHE_DIR, IMAGE_MAX_BYTES (image cache subsystem
deleted)
- Drop VAPID_PRIVATE_KEY, VAPID_PUBLIC_KEY, VAPID_CLAIMS_SUB (push
deleted in phase 8)
- Drop VOICE_ENABLED, STT_BACKEND, STT_MODEL, TTS_BACKEND (voice
deleted in phase 8)
- Drop Config.validate() rules for those keys
Image cache deletion:
- services/images.py, routes/images.py, models/image_cache.py
- models/__init__.py: drop ImageCache import
- app.py: drop images_bp registration
- alembic/versions/0054_drop_image_cache.py: DROP TABLE image_cache
Frontend client.ts orphan exports stripped:
- getVoiceStatus, getVoiceList, getVoiceLibrary, installVoice,
uninstallVoice, transcribeAudio, synthesiseSpeech,
VoiceStatusResult / VoiceEntry / VoiceLibraryEntry types
- getJournalConfig, saveJournalConfig, getJournalToday/Day/Days,
triggerJournalPrep, runJournalCurator, listPendingActions,
approvePendingAction, rejectPendingAction, listJournalMoments,
updateJournalMoment, deleteJournalMoment, geocodeAddress
- JournalConfig / JournalLocation / JournalConversation /
JournalMessage / JournalDayPayload / JournalMoment /
CuratorRunResult / PendingCuratorAction types
- consolidateProfile, clearProfileObservations, listProfileObservations
- ProfileObservationEntry, learned_summary/observations_* fields on
UserProfile
- consolidateTask (cascading update to TaskEditorView)
- getFableMcpInfo, getNewsItems, GetNewsItemsParams, NewsItem import
TaskEditorView:
- Drop the auto-summary banner + Re-consolidate button
- Drop isBodyAutoMaintained gate (editor is always user-controlled now)
- Drop reconsolidate function + reconsolidating ref
SettingsView:
- profile ref no longer initialises learned_summary /
observations_count / observations_updated_at (those fields are
gone from UserProfile type)
Surviving frontend composables/components flagged for likely future
cleanup but not deleted in this commit (no compile errors, just
unreferenced after Phase 7-8):
- useAssist, useFloatingAssist, useTagSuggestions, useVad,
useListenMode, useOnnxPreloader (composables)
- WorkspaceNoteEditor, WorkspaceTaskPanel, WeatherCard, InlineAssistPanel
(components)
- api/client.ts still references /api/notes/assist/* and
/api/notes/suggest-tags via useAssist + useTagSuggestions — those
endpoints 404 now but no caller hits them; dead at runtime, harmless.
Compose stack collapses to two services: `app` + `db`. No Ollama, no
voice models, no fable-mcp wheel build. First-boot install reduces to:
docker compose up -d
→ visit web UI → register → Settings → MCP Access → copy snippet
→ claude mcp add … → done.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-27 19:10:25 -04:00
bvandeusen
b3fca3ced4
migration: drop chat/journal/push/curator/weather tables (Phase 9)
...
Phase 8 deleted the Python models for these tables; this migration
drops the orphan SQL.
Dropped tables (CASCADE-safe):
conversations, messages, generation_tool_log,
moments + moment_embeddings + moment_people/places/tasks/notes,
pending_curator_actions, push_subscriptions, weather_cache,
rss_item_embeddings (legacy pre-pivot experiment)
Dropped per-user settings: every voice_*, journal_*, briefing_*,
curator_* key, plus default_model, background_model, assistant_name,
auto_consolidate_tasks, chat_retention_days, think_enabled,
rag_default_scope.
Hard cutover — no downgrade. Existing data in these tables is lost;
the spec explicitly accepted this in exchange for a clean schema.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-27 18:16:18 -04:00
bvandeusen
8d73f553ca
test: drop test_tools_calendar_always_available
...
Tested that services/tools/_registry exposed event tools to the LLM
tool layer. That layer was removed in Phase 8 commit 91bafb6; event
CRUD is now covered via the MCP tools in test_mcp_tool_events.py.
2026-05-27 18:10:06 -04:00
bvandeusen
42861142db
chore: remove benchmark notes that were accidentally committed
...
The bench-*.md files got swept into the Phase 8 mega-commit by
`git add -A`. They were local working-tree notes the user never
intended to track.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-27 18:09:32 -04:00
bvandeusen
91bafb641f
refactor: Phase 8 — backend deletion (chat / voice / push / journal / curator)
...
Mega-commit. Strips all server-side LLM machinery now that Phase 7 has
removed the corresponding UI surfaces and the MCP HTTP endpoint is the
sole assistant interface.
Deleted (services/):
chat, generation_buffer, generation_log, generation_task, llm, tools/
(entire package), stt, tts, voice_config, voice_library, push,
journal_closeout, journal_pipeline, journal_prep, journal_scheduler,
journal_search, curator, curator_scheduler, consolidation,
tag_suggestions, research, weather, article_fetcher, pending_actions,
moments, assist, wikipedia.
Deleted (routes/):
chat, voice, push, journal, quick_capture, fable_mcp_dist.
Deleted (models/):
conversation, generation_tool_log, push_subscription,
pending_curator_action, moment, weather_cache.
Deleted (tests/):
test_generation_log, test_journal_*, test_consolidation, test_lookup_tool,
test_notes_consolidation_trigger, test_record_moment_guards,
test_research_pipeline, test_tools_*, test_tool_use_fixes,
test_voice_library, test_weather_service, test_calendar_tool_tz,
test_wikipedia.
Deleted (top-level):
fable-mcp/ (legacy standalone stdio package — wheel-build pipeline
also removed from Dockerfile).
app.py:
- blueprint registrations for the 6 deleted routes
- startup hook trimmed: no more Ollama warmup, KV-cache priming,
journal/curator schedulers, voice model loading
- shutdown hook simplified
- httpx import dropped (was for Ollama calls)
pyproject.toml:
- removed deps: pywebpush, feedparser, html2text, trafilatura
- removed [voice] extras entirely
- description updated for the MCP-first architecture
Dockerfile:
- removed faster-whisper / piper-tts install steps
- removed bundled piper voice download stage
- removed fable-mcp wheel build stage
Surviving-file edits:
- services/auth.py: drop Conversation table claim on first-user setup
- services/backup.py: drop conversation / push-subscription export+restore;
v1/v2 restore now silently skip pre-pivot conversation data
- services/notes.py: drop maybe_consolidate trigger on task done/cancelled;
drop _maybe_trigger_project_summary (LLM auto-summary)
- services/projects.py: drop generate_project_summary + backfill_project_summaries
(both LLM-driven)
- services/user_profile.py: drop append_observations / consolidate /
clear_learned_data (curator-tied) and build_profile_context
(was LLM system-prompt builder)
- services/notifications.py: stub out _fire_push_notif (was send_push_notification)
- services/event_scheduler.py: drop event-reminder push + chat-retention
cleanup job; keep CalDAV pull-sync + reminders job (in-app)
- services/diagnostics.py: _curator_busy() always False
- routes/notes.py: drop /assist, /assist/stream, /suggest-tags endpoints
- routes/tasks.py: drop /<id>/consolidate endpoint
- routes/settings.py: drop /models, KV-cache-prime-on-save, journal-schedule
timezone hook, and the SearXNG search-test endpoint; inline _is_private_url
(was in services/llm.py)
- routes/admin.py: drop /voice, /voice/reload endpoints
- routes/profile.py: drop /consolidate, /observations (GET, DELETE)
- models/__init__.py: drop the 6 dead model imports
Frontend cascade:
- stores/push.ts: deleted entirely (no callers after Phase 7)
- stores/settings.ts: drop checkVoiceStatus + voice-status state
- views/SettingsView.vue: drop Locations section + journalConfig state
(was tied to /api/journal/config); drop JournalConfig + journal/voice
api/client imports
- frontend/api/client.ts: orphaned voice/journal/profile-observation/
fable-mcp-dist exports are left as dead but harmless (call them and
they 404; type-check is clean).
Pre-existing v1 backups that contained conversations/messages still
restore — those tables are silently dropped from the import path.
Anyone pulling the new image with a populated database will need the
Phase 9 migration to drop the dead tables (coming next).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-27 17:47:18 -04:00
bvandeusen
8bec68abc0
fix(ui): restore missing </div> closing the Notifications tab
...
The earlier sed-delete of the Push/ChatHistory/About sections from
the Notifications tab also clipped the tab's outer </div>. Vue's
type-checker happily accepted the unbalanced structure (templates
type-check on script bindings, not tag pairing) but Vite's Vue
compiler failed at build time:
Element is missing end tag.
file: src/views/SettingsView.vue:1062:5
(The reported line 1062 was the outermost .settings-content div —
Vue's parser blames the outermost open tag when an inner sibling
goes unclosed.)
Confirmed by counting: 115 open <div, 116 </div> before — and now
116/116 after restoring the closing tag between the Email Notifications
section and the Integrations tab.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-27 15:38:06 -04:00
bvandeusen
ba6f2c7614
refactor(ui): purge SettingsView dead JS left over from Phase 7
...
The Phase 7 template strip left script-level state, functions, and
imports that no template ever referenced. TypeScript strict mode
(noUnusedLocals + noUnusedParameters) caught all of them on CI.
Removed from the script:
- chat retention: chatRetentionDays, savingRetention, saveRetention
- VAPID/push: vapidResetting/Msg/Error, resetVapidKeys, usePushStore,
pushStore.checkSubscription() call in onMounted
- admin voice block: adminVoiceEnabled, adminVoiceSttModel,
savingAdminVoice, adminVoiceSaved, voiceLoadingModels,
saveAdminVoice, reloadVoiceModels (plus the matching admin
template block — that was still present and referenced these)
- user voice block: voiceStatus, voiceStatusLoading, availableVoices,
voiceTtsVoice, voiceTtsSpeed, voiceSpeechStyle, savingVoice,
voiceSaved, voiceTabLoaded, the whole voice library
(voiceLibrary, voiceLibraryLoading/Error/Filter/Expanded,
installingVoiceIds, uninstallingVoiceIds, filteredVoiceLibrary,
formatVoiceSize, loadVoiceLibrary, refreshInstalledVoices,
installLibraryVoice, uninstallLibraryVoice, loadVoiceTab,
voicePreviewing, previewVoice, saveVoiceSettings)
- observations / consolidation: consolidating, clearingObs,
observations, observationsExpanded/Loading/Loaded,
toggleObservations, onToggleCloseout, runConsolidate,
clearObservations
- assistant / model management: assistantName, defaultModel,
backgroundModel, installedModels, defaultChatModel, OllamaModel
interface, ollamaModels, pullModelName, pullProgress, pulling,
deletingModel, formatBytes, loadOllamaModels, pullModel,
deleteModel, saveAssistant, saving, saved
- api/client imports: getVoiceStatus, getVoiceList, getVoiceLibrary,
installVoice, uninstallVoice, synthesiseSpeech, consolidateProfile,
clearProfileObservations, listProfileObservations,
VoiceStatusResult, VoiceEntry, VoiceLibraryEntry,
ProfileObservationEntry
Surviving: journalConfig + locations editor + temp_unit selector
(Profile→Locations section still uses these to manage home/work
addresses for any future feature; the journal-specific prep/closeout
fields on the same object are dead but harmless as object members).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-27 15:26:51 -04:00
bvandeusen
18eb1e7ab2
refactor(ui): Phase 7 — strip chat/voice/journal/workspace/home surfaces
...
Frontend deletion phase of the MCP-first pivot. All in-app
conversational surfaces are gone — Claude/MCP is the assistant now.
Deleted views:
ChatView, JournalView, WorkspaceView, HomeView
Deleted components:
ChatPanel, ChatInputBar, ChatMessage, ChatStreamingBubble,
ToolCallCard, ToolConfirmCard, WorkspaceChatWidget
Deleted composables + store:
useVoiceRecorder, useVoiceAudio, useStreamingTts, stores/chat
Router changes:
- / now redirects to /knowledge (was /journal)
- dropped /chat, /chat/:id, /journal, /workspace/:projectId
- /tasks still redirects to / (→ /knowledge)
- /notes still redirects to /knowledge
KnowledgeView:
- removed ChatPanel + ChatInputBar embeds
- removed minichat floating widget + state + handlers
- removed Chat link from today bar
- removed `chatStore` driven auto-refresh-on-tool-call watch
App.vue:
- removed useChatStore + startStatusPolling/stopStatusPolling
- removed VAD ONNX preloader (voice subsystem dead)
- removed visibilitychange listener (only did voice status re-check)
- removed `c` single-key shortcut (focus chat / goto chat)
- removed `g+c` two-key sequence (goto chat)
- removed Chat section from shortcuts overlay
- removed `.chat-page` / `.workspace-root` CSS overflow rule
AppHeader.vue:
- removed useChatStore + status indicator (Ollama model status)
- removed Chat / Journal nav links (desktop + mobile)
SettingsView.vue (4598 → 4079 lines):
- removed Voice tab entirely
- Notifications tab: dropped Push Notifications + Chat History
+ About sections (kept Email Notifications)
- General tab: dropped Assistant (name + model pickers) +
Model Management sections (kept Tasks + Timezone)
- Profile tab: dropped Journal + Observations sections
- VALID_TABS + tab list array no longer include "voice"
- removed `loadVoiceTab()` activation trigger
Service worker (frontend/public/sw.js):
- dropped push and notificationclick handlers (push subsystem
only fired on internal generation completion, which is gone)
- kept empty fetch handler as PWA installability shell
Script-level dead code (state refs, helper functions referencing
removed APIs) remains in SettingsView and stores/push.ts and
stores/settings.ts for now — Phase 8 backend deletion will clean
those up alongside the matching backend route removals.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-27 15:14:00 -04:00
bvandeusen
05b0bf97d7
fix(mcp): list_events tz-aware UTC range + end-of-day inclusive
...
Phase 6 smoke caught:
Error executing tool list_events:
can't compare offset-naive and offset-aware datetimes
Event.start_dt is stored timezone-aware; the wrapper was passing naive
datetimes built from datetime.fromisoformat("YYYY-MM-DD"), so the SQL
comparison crashed. Also: the docstring promises "date_to inclusive at
end-of-day" but the code was using midnight-of-date_to, which would
silently miss same-day events after midnight.
Extracted the range math into _day_range_utc() so create/update_event's
_combine() can stay as-is (it stays naive — the service localizes
create/update inputs against the user's tz, that path didn't crash).
Test updated to match: assert tz-aware UTC datetimes and the +24h
bump for end-of-day-inclusive semantics.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-27 14:57:38 -04:00
bvandeusen
02fe500d61
fix(mcp): disable DNS-rebinding protection on FastMCP
...
FastMCP defaults to an allow-list of localhost variants for the Host
header (DNS-rebinding protection). Any deployment behind a reverse
proxy hitting a non-localhost hostname (e.g. devassistant.traefik.internal)
gets 421 Misdirected Request with:
WARNING mcp.server.transport_security: Invalid Host header: <name>
The protection exists to stop a malicious browser page from rebinding
DNS to attack a localhost MCP server. Our deployment is HTTP transport
behind a reverse proxy with bearer-token auth, which already gates
every request — so the rebinding threat doesn't apply. Disabling
the check lets any Host through; auth still rejects unauthorized
requests at 401.
This also makes the integration test pass without test-only host
hackery — every realistic Host header (Traefik internal hostname,
CDN domain, custom DNS) now reaches FastMCP cleanly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-27 14:16:47 -04:00
bvandeusen
06a532b0e6
test(mcp): include Host header in raw-ASGI test scope
...
FastMCP's transport_security module enforces a Host header as DNS-
rebinding protection. Raw-ASGI scope construction doesn't fill it in
automatically (real HTTP clients always send one), so the test
request was getting 421 Misdirected Request with a log warning:
Missing Host header in request
Production is unaffected — real curl, Claude Code, and any real
client send a Host header.
2026-05-27 13:11:39 -04:00
bvandeusen
65d3711a11
fix(mcp): start FastMCP session manager via Quart serving lifecycle
...
After fixing the /mcp path forwarding in 1fd303a , requests now reach
FastMCP — but its StreamableHTTPSessionManager raises:
RuntimeError: Task group is not initialized. Make sure to use run().
The session manager owns a task group that must be running before it
can handle requests. In a stand-alone Starlette app this happens via
the `lifespan` parameter (lifespan = session_manager.run). Hosted
inside Quart, my dispatch wrapper only forwards HTTP events, not
lifespan, so the manager never got its startup signal.
Fix: hook session_manager.run() (an async context manager) into
Quart's @app.before_serving and @app.after_serving so the task group
is alive across the serving window.
The CI integration test was hitting the same crash because it drives
app.asgi_app raw without going through Quart's serving lifecycle —
@before_serving never fires. Updated the test to manually enter
session_manager.run() around the request.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-27 12:59:29 -04:00