bvandeusen
95056d5be7
fix: rename Note.metadata → entity_meta (reserved by SQLAlchemy Declarative API)
...
SQLAlchemy reserves 'metadata' as a class attribute on declarative models.
Renamed to 'entity_meta' with explicit column name 'metadata' so the DB
column is unchanged but the Python attribute no longer conflicts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 18:13:47 -04:00
bvandeusen
80f30b705d
feat: Knowledge view + entity types (People, Places, Lists)
...
Data model:
- Migration 0036: adds note_type TEXT (default 'note') and metadata JSONB
to the notes table; index on note_type
- Note model: entity_type property, note_type/metadata in to_dict()
- create_note() accepts note_type and metadata params
Backend:
- /api/knowledge — unified paginated endpoint: type/tag/sort/q filters,
semantic search via embeddings, excludes tasks
- /api/knowledge/tags — distinct tags across knowledge objects
- New LLM tools: create_person, create_place, create_list, add_to_list,
clear_checked_items — all wired into execute_tool()
- People and places auto-injected as compact summary into LLM system prompt
Frontend:
- KnowledgeView replaces HomeView at /; left filter panel (type+tag),
toolbar (search, sort, graph toggle), card grid with type-aware cards
(indigo=note, emerald=person, amber=place, sky=list), load-more pagination
- Today bar: upcoming events, overdue task count, Briefing/Chat links
- Floating mini-chat sticky to bottom: creates/continues a conversation
inline, message history expands upward, close button ends session
- Graph panel: toggles as a 420px right panel at full viewport width
- AppHeader: Knowledge, Chat, Briefing, Calendar, Tasks, Projects
- Router: / → KnowledgeView; /knowledge redirect; HomeView import removed
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 18:01:03 -04:00
bvandeusen
c271f1b41f
feat: add recurrence_rule and recurrence_next_spawn_at columns to notes
2026-03-27 22:49:59 -04:00
bvandeusen
1125c8e107
feat: add started_at/completed_at columns to notes
2026-03-27 22:37:55 -04:00
bvandeusen
7a12cba4d5
feat: add 'cancelled' task status; fix 500 on invalid status/priority
...
TaskStatus enum was missing 'cancelled' — the LLM tried to use it and
hit TaskStatus("cancelled") raising ValueError → 500. Added the value,
a migration to extend the task_status Postgres enum, and proper 400
validation guards on both create and update task routes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-27 09:18:16 -04:00
bvandeusen
16ecd6bbeb
DRY refactoring pass: shared mixins, route helpers, composables, CSS
...
Backend:
- models/base.py: TimestampMixin + CreatedAtMixin; applied to all 10+ models
- routes/utils.py: not_found() + parse_iso_date() helpers; used across all route files
- routes/milestones.py: _milestone_dict() helper replaces 5 repeated to_dict + progress blocks
Frontend:
- 5 new composables: useAutoSave, useEditorGuards, useTagSuggestions,
useFloatingAssist, useListKeyboardNavigation
- ConfirmDialog.vue: reusable confirm modal replacing inline <teleport> blocks
- editor-shared.css: sidebar CSS consolidated from both editor views
- viewer-shared.css: context-bar/breadcrumb CSS consolidated from both viewer views
- NoteEditorView + TaskEditorView: ~120 lines each replaced with composable calls;
duplicate scoped sidebar CSS removed
- NotesListView + TasksListView: inline keyboard-nav replaced with composable
- NoteViewerView + TaskViewerView: duplicate context-bar CSS removed
No behaviour changes. Net: -634 lines, +237 lines across 31 files.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-06 15:26:34 -05:00
bvandeusen
012eb1d46b
Add Projects, Milestones, RAG auto-inject, push notifications, PWA, tag normalisation
...
## Projects & Milestones (Phases A + G)
- New models: Project, Milestone (Project → Milestone → Task hierarchy)
- notes table: project_id + milestone_id FKs; parent_id FK constraint activated
- Migrations: 0017 (projects), 0018 (push_subscriptions), 0019 (events), 0020 (milestones)
- Services: projects.py, milestones.py (CRUD + progress tracking)
- Routes: /api/projects + /api/projects/<id>/milestones
- LLM tools: create/list/get/update project; create/list milestone; project + milestone + parent_task params on note/task tools
- Frontend: ProjectListView (stacked milestone bars), ProjectView (milestone-grouped kanban), ProjectSelector, MilestoneSelector, NoteEditorView + TaskEditorView updated
## RAG Auto-injection (Phase B)
- Notes ≥0.60 cosine similarity auto-injected into system prompt (max 3, 800 chars each)
- excluded_note_ids param; ChatView "Auto-included" sidebar section
## Summarisation improvements (Phase C)
- Threshold 20→30, keep-recent 6→8, max_tokens 200→400
- Two-pass summarisation for histories >50 messages
## Browser push notifications (Phase E)
- PushSubscription model + migration; pywebpush dependency
- /api/push routes; VAPID config; fire-and-forget on generation complete
- Frontend: sw.js, push store, Settings toggle
## PWA manifest (Phase F)
- manifest.json, Apple meta tags, service worker registration in main.ts
## Tag normalisation
- All tags lowercased + deduplicated at backend (create_note/update_note) and frontend (TagInput sanitize)
- Note/Task types gain project_id + milestone_id fields; store signatures updated
## CalDAV
- Radicale embedded server reverted; back to user-configured external CalDAV
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-02 20:52:21 -05:00
bvandeusen
cbfdf5289e
Add multi-user auth, background generation, and chat UX improvements
...
Phase 5: Multi-user authentication with session cookies, bcrypt passwords,
first-user-is-admin pattern, per-user data isolation, backup/restore,
Docker Swarm production stack with secrets and network isolation.
Phase 5.1: Chat UX improvements:
- Background generation architecture (GenerationBuffer + asyncio task)
with SSE fan-out, reconnect support, and periodic DB flushes
- LLM-generated conversation titles (first exchange + every 10th message)
- Stop generation button with cancel_event and partial content preservation
- Relative timestamps in sidebar (5m ago, 3h ago, then dates)
- Empty chat auto-cleanup on navigation away
- Save-as-note uses LLM for title generation, tags notes with "chat"
- Summarize-as-note also tags with "chat"
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-11 14:36:30 -05:00
bvandeusen
db01106714
Backend efficiency & consistency pass
...
- Rewrite get_all_tags() with SQL unnest instead of loading all notes
- Consolidate convert_note_to_task/convert_task_to_note to single-session ops
- Add search_notes_for_context() with single OR-keyword query for build_context()
- Drop selectinload from list_conversations(), use correlated subquery for message_count
- Add set_settings_batch() for single-transaction multi-setting upserts
- Extract get_installed_models() shared helper into services/llm.py
- Delete services/tasks.py pass-through wrapper; routes/tasks.py imports from services.notes
- Add B-tree indexes on notes.title and conversations.updated_at (migration 0007)
- Add logging to services/notes.py, services/chat.py, services/settings.py
- Safe Conversation.to_dict() when messages relationship is not loaded
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-11 08:27:11 -05:00
bvandeusen
807cde30be
Merge tasks into notes: a task is just a note with task attributes
...
A task is now a note with status/priority/due_date columns set (status IS NOT NULL).
This eliminates the separate tasks table, companion note system, cascade deletes,
bidirectional title sync, and _skip_cascade flags.
Migration (0004):
- Add status, priority, due_date columns to notes table
- Migrate task data from companion notes and orphan tasks
- Drop tasks table and old enum types
Backend:
- models/note.py: Add TaskStatus/TaskPriority enums, task columns, is_task property
- models/task.py: Deleted (merged into note.py)
- models/__init__.py: Re-export enums from note.py, remove Task import
- services/notes.py: Remove companion/cascade logic, add is_task filter,
convert_note_to_task, convert_task_to_note, simplified backlinks
- services/tasks.py: Rewritten as thin wrappers around notes service
- routes/notes.py: Add is_task filter (default false), task fields in CRUD,
convert-to-note endpoint
- routes/tasks.py: description→body (with fallback), remove note_id filter
Frontend:
- types/note.ts: Add TaskStatus, TaskPriority, task fields to Note interface
- types/task.ts: Task is now a re-export alias for Note
- stores/notes.ts: Simplify convertToTask, add convertToNote
- stores/tasks.ts: description→body in createTask/updateTask
- TaskEditorView: description→body, remove companion note UI
- TaskViewerView: description→body, remove companion note link, add Convert to Note
- NoteViewerView: Remove companion task UI, simplify convert-to-task
- TaskCard: description→body, non-null assertions for status/priority
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-10 17:56:12 -05:00
bvandeusen
22a3a3c1d1
Initial commit: note-taking/task-tracking app with LLM integration scaffold
...
Vue 3 + TypeScript frontend with Pinia stores, markdown rendering (marked + DOMPurify),
wikilink/tag linkification, and autocomplete. Quart async backend with SQLAlchemy 2.0,
PostgreSQL ARRAY columns, task-note companion linking, backlinks, and note-to-task
conversion. Docker Compose setup with PostgreSQL 16 and Ollama.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-09 23:35:44 -05:00