TaskEditorView:
- Back button standardized to "← Tasks"
- Toolbar now on same row as Write/Preview tabs (flex-direction row)
- Save button and title input inherit gradient/Fraunces from editor-shared.css
TaskViewerView:
- Shimmer skeleton loader replaces plain "Loading..." text
- Task title uses Fraunces font at 2rem
- Edit button becomes primary gradient CTA
- Meta timestamps show clock/pencil SVG icons
- Backlinks section: card grid with colored type badges (note=indigo, task=amber)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- WorkspaceNoteEditor: replace toggling list/editor views with always-visible
left rail (155px) showing note list alongside editor pane; persist last-open
note per project in localStorage (workspace_note_{projectId})
- WorkspaceTaskPanel: add priority dot + due date on task rows; replace full
overlay detail with bottom-split (44% list / 56% detail); close button
replaces back nav; active row highlighted; fade transition
- WorkspaceView: show project goal in header instead of 'Workspace'; non-equal
panel widths (0.8fr / 1.1fr / 1.1fr); empty chat quick-action chips (Project
status / New note / Add tasks); prefill() helper
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces the flat sorted list with date-aware sections that surface what
needs attention first. Completed tasks go into a collapsed section at the
bottom. Grouped-by-project mode is preserved as the second toggle option.
TaskCard compact restored to card hover/lift style.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- NotesListView: skeleton shimmer for grid and list modes; grid columns change from fixed 3 to auto-fill(260px)
- NoteCard compact: flat border-bottom row style instead of stacked mini-cards; gradient fade mask on grid preview text
- TaskCard compact: flat border-bottom row style; show up to 2 tags
- TasksListView: gradient + shadow on New Task button (matches NotesListView)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Ports UserManagementView logic (users list, invitations, registration
toggle) directly into SettingsView as a lazy-loaded 'users' admin tab.
Adds loadLogsPanel stub for Task 4. Adds apiDelete import and User type
import at script top.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove the gear dropdown menu from AppHeader; cog icon is now a plain
router-link to /settings. Admin-only /admin/users and /admin/logs routes
are replaced with redirects to /settings. Mobile menu admin links removed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Hero card: last-active project (by most recent note/task updated_at),
prominent 'Open Workspace' button, milestone bars, 5 recent items,
highest-priority next-up todo task
- Projects grid: all other active projects with small workspace button,
urgency badges (in progress / todo count), milestone bars, hover lift
- Inbox section: collapsible strip of orphaned tasks + notes (no project)
- Skeleton shimmer replaces plain 'Loading...' text
- Chat widget + quick actions unchanged at top
Backend additions used: ?no_project=true on both /api/notes and
/api/tasks; ?project_id= on /api/tasks (committed separately)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
TaskViewerView:
- Add '→ In Progress' / '→ Done' advance button in toolbar (forward-only,
hidden when status is already done)
- Styled with primary indigo gradient to distinguish from secondary actions
TaskEditorView:
- showPreview now defaults false; set to true after load only when body
has content — empty tasks open directly in Write mode
- Save on an existing task now calls window.location.reload() so the
preview/edit mode re-evaluates from the freshly persisted body
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Nav padding: 0.5rem → 0.75rem vertical, 1.25rem → 1.5rem horizontal
- AppLogo size: 24px → 34px so the book detail is legible
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously the empty-conversation cleanup only fired when switching
between chats (convId watcher). Navigating to /notes, /tasks, etc.
left orphaned untitled empty conversations. onUnmounted now runs the
same check, deleting the current conversation if message_count === 0.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- theme.css: darken user bubble text (#3a3a4a light / #b0b0c8 dark) for better readability
- AppHeader: highlight Chat nav link when on any /chat/* route (was only active on exact /chat)
- summary.md: document workspace, graph, queue persistence, ToolCallCard direct-API, dedup scoping
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Matches the ChatView.vue update from the UI polish pass — queued bubbles
use linear-gradient(135deg, #6366f1, #4f46e5) and 18px border-radius
consistent with the Illuminated Transcript design language.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
.logo-book fill was var(--color-text) which renders black in light mode.
Changed to var(--color-primary) so it matches the brand indigo in both
modes. Stroke updated to match at 70% opacity.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Design direction: "Illuminated Transcript" — the AI response is the
primary artifact; user prompts are subordinate margin notes.
ChatMessage.vue:
- User bubble: ghosted background (rgba 3-4% opacity), muted text,
thin near-invisible border. De-emphasized, recessed.
- Assistant bubble: left indigo accent border (2px), elevated shadow
via --color-bubble-asst-shadow. Commands attention.
- Assistant role label: indigo (var(--color-primary)); user label muted.
- Removed old white-override content rules (no longer on dark bg).
- Thinking block: full border → left-only indigo accent bar (35% opacity),
removed inner top border.
ChatView.vue:
- Streaming bubble: same left accent + shadow as assistant bubbles.
- Streaming role label: indigo to match ChatMessage.
- Thinking block in streaming: same treatment as ChatMessage.
theme.css:
- Added --color-bubble-user-bg/border/text for light + dark.
- Added --color-bubble-asst-shadow for light + dark.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The role-user justify-content and message-bubble shape styles are scoped
to ChatMessage.vue and don't reach the inline queued bubbles. Add them
directly in ChatView and WorkspaceView: right-aligned row, 16px border
radius with 4px bottom-right corner, same padding and font as user bubbles.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Queued message bubbles now match user bubble style (primary colour,
right-aligned, opacity 0.45) in both ChatView and WorkspaceView
- Queue persisted to localStorage (fa_conv_queue_<id>); survives page
refresh, restored on fetchConversation, cleared on delete
- ToolCallCard confirm/deny: buttons now inline in header row; "Create
anyway" calls POST /api/notes or /api/tasks directly (no LLM round-trip);
shows "✓ Created" / "Skipped" state; removed chatStore dependency
- POST /api/notes and POST /api/tasks now accept project (name string) and
resolve to project_id server-side, matching tools.py behaviour
- Remove semantic similarity duplicate check from create_note and
create_task — 0.87 threshold was too aggressive for topically-related
notes; title-based exact/fuzzy checks are sufficient
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Dashboard chat: allow typing/sending during streaming (queued in store)
placeholder updates to "Type to queue…" during generation
- ChatView/WorkspaceView: replace queued chip with actual pending message
bubbles — light grey, dashed border, "Queued" badge above content; clear
button below the stack
- ToolCallCard: when tool returns requires_confirmation=True, show
"Similar content found" label (not "Error"), link to the similar note,
and "Create Anyway" / "Don't Create" buttons that auto-send the reply
- tools.py: fuzzy title match now returns requires_confirmation=True with
similar_note data instead of a hard error, so numbered-series notes
(Lore: X 0, Lore: X 1) can be created with one button click; semantic
match responses also include similar_note for the link
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces the single long scrolling page with a tab bar. Active tab
persists to localStorage across navigation. Admin tab only visible to
admins. Push notifications description clarified to mention HTTPS requirement.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- sw.js: suppress notification when the target chat tab is already focused
(clients.matchAll visibility check before showNotification)
- generation_task.py: provide meaningful body for tool-only responses
(lists tool names instead of sending an empty string that browsers discard);
promote scheduling failure from debug to warning
- push.py: promote send errors from warning to error with exc_info;
log successful sends at INFO so they're visible in normal operation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Chat store: when sendMessage() is called while streaming, push to a
per-conversation queue and return. When the stream ends the next queued
message fires automatically via setTimeout(0) to keep the call stack
clean. clearQueue() and queuedCount exposed for UI consumption.
Queue is cleaned up on conversation delete.
ChatView/WorkspaceView: remove the streaming guard from the local
sendMessage() functions and the :disabled on the textarea so users can
type and submit freely while streaming. Input placeholder changes to
"Type to queue next message…" during streaming. A small "⏳ N queued ×"
chip appears below the streaming bubble showing queue depth with a
cancel button.
DashboardChatInput: disable input, attach button, and send button
during streaming. The dashboard creates a fresh conversation per
message so in-conversation queuing doesn't apply — locking the input
is the correct UX here. Placeholder updates to "Generating response…"
during streaming.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Panel state is saved to localStorage as workspace_panels_{projectId} on
every toggle and restored on mount. Each project remembers its own layout
independently. Fallback guard ensures at least one panel is always open
after restore.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Conversations are bucketed into: Today, Yesterday, This week, This month,
and older entries sub-grouped by calendar month (e.g. "February 2026").
Group labels are sticky so they stay visible while scrolling. Older
buckets use month+year sub-grouping rather than a single "Older" catch-all.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Completed (success) tool calls render collapsed: label + inline summary + ▶ chevron
- Clicking the header expands the detail section (result list, links, tags)
- Error cards start expanded so failures are immediately visible
- Running (in-progress) cards start expanded for live progress visibility
- Auto-collapses when a running call completes during streaming
- Suggested-tag pills remain accessible in both collapsed (via separate row) and expanded states
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
TiptapEditor.vue (central — applies to all three editors):
- Escape inside editor blurs it and emits 'escape' event to parent
TagInput.vue (central — applies everywhere tags are used):
- ArrowUp/ArrowDown navigate autocomplete suggestion list with visual highlight
- Enter confirms the keyboard-selected suggestion instead of typed text
NoteEditorView, TaskEditorView, WorkspaceNoteEditor (per-editor wiring):
- @escape on TiptapEditor returns focus to the title input (ref="titleRef")
- Ctrl+E from title input or editor main column jumps focus into editor body
- Ctrl+S on title input saves (was already on editor area; now consistent)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add MarkdownToolbar to the workspace note editor (was missing entirely)
- Add [[ button to MarkdownToolbar so wikilinks are discoverable in all editors;
clicking inserts [[ which immediately triggers the WikilinkSuggestion dropdown
- Add link suggestions strip: polls /api/notes/link-suggestions 2.5s after edit,
shows unlinked note-title mentions as clickable chips to wrap in [[...]], plus
"All" button to apply everything at once — directly addresses the heading→wikilink
workflow (note title appearing as heading text gets detected and offered for linking)
- Add Ctrl+S keyboard shortcut on title input and editor area to save
- Replace ✕ delete icon on note list items with trash can SVG (consistency with task panel)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- WorkspaceTaskPanel: add milestone <select> in task detail (PATCH /api/notes/:id),
replace delete ✕ with trash can SVG icon
- WorkspaceView: scroll to bottom when streaming ends so final message is visible
without a page refresh
- ToolCallCard: fix search_notes result count (was reading data.total; tool returns
data.count), so results no longer show "0 found"
- push.py: switch from deprecated WebPusher().send(vapid_private_key=...) to
webpush() function (pywebpush 2.x API compatibility)
- app.py: downgrade /api/health, /api/chat/status, and static asset requests from
INFO to DEBUG in after_request logger to reduce log noise at default log level
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New /graph route with D3 force simulation (GraphView.vue)
- Tag nodes as first-class graph nodes (string IDs "tag:name") — clicking
navigates to /notes?tags=name; tags shown by default
- Invisible project hub nodes attract project members into clusters
- Physics panel with live sliders: repulsion, link distance, link strength,
project pull, gravity (forceX/forceY, not forceCenter)
- Wikilink edges retain directed arrowheads; tag edges are thin, no arrowhead
- Graph nav link in AppHeader; `g` shortcut in App.vue
- Backend: build_note_graph() emits tag nodes + note→tag edges instead of
O(n²) note→note shared-tag mesh
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
NoteEditorView: two-column sidebar layout (project/milestone/tags/assist
always visible), removed assist toggle button, InlineAssistPanel removed.
Writing assist: whole_doc mode rewrites entire document; DiffView.vue
replaces editor during review showing full-document diff. Scope dropdown
in sidebar switches between whole-document and section modes.
Persistent drafts: migration 0022 adds note_drafts (UNIQUE per note+user)
and note_versions (max 20, auto-pruned) tables. Draft saved after generation
completes, restored on editor mount, cleared on accept/reject. Version
snapshot created automatically whenever note body changes on save.
HistoryPanel.vue: version list + DiffView modal, restore button writes
body back to editor.
Config: OLLAMA_NUM_CTX default raised to 65536; assist num_predict now
tracks Config.OLLAMA_NUM_CTX instead of a hardcoded 4096.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
stores/chat.ts:
- Replace 7 global stream refs with convStreams: Record<number, ConvStreamState>
- Each conversation tracks its own stream state; 7 names become computed getters
- Add isStreamingConv(id) public helper
- Increment message_count +2 immediately after POST 202 (not at done) so the
cleanup watcher never deletes a mid-generation conversation
- SSE reconnect retries now run for background conversations regardless of
which conv is currently viewed
- error toasts only shown when the erroring conv is currently viewed
- deleteConversation cleans up orphaned stream state
ChatView.vue:
- Remove invalid write to store.lastContextMeta (now a read-only computed)
- Add !store.isStreamingConv(newId) guard to watch(convId) fetch so navigating
back to a generating conversation shows accumulated content without stale refetch
- Add startNewConversation() helper; opening /chat with no ID auto-creates a
new conversation and redirects to it (on mount and on navigation)
- Deleting a conversation also auto-creates a new one
Also committing previous-session changes (keyboard nav + task routing):
- App.vue: e shortcut only on note-view (not task-view, which is removed)
- TaskCard.vue: route directly to /tasks/:id (viewer), remove View buttons
- router/index.ts: remove task-view route; /tasks/:id now maps to TaskEditorView
- TasksListView.vue: Enter key pushes to /tasks/:id
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- App.vue: e → edit on viewer pages; / → focus search (custom event); c → focus
chat on home or navigate to /chat; update shortcuts panel with Lists + Chat sections
- theme.css: add a:focus-visible to focus-ring rules (router-link cards now show
visible keyboard focus outline)
- SearchBar.vue: expose focus() via defineExpose for cross-component focus dispatch
- NotesListView / TasksListView: j/k vim-style navigation with kb-active-item
highlight; listen for shortcut:focus-search; cleanup on unmount
- HomeView.vue: listen for shortcut:focus-chat, call chatInputRef.focus()
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
First Escape blurs the active input (reaching neutral state where
shortcuts work), second Escape navigates home. Allows full keyboard
navigation without touching the mouse to leave a focused field.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Prevents content from escaping max-width boundaries across notes,
tasks, projects list, and project detail views.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>