Commit Graph

237 Commits

Author SHA1 Message Date
lucaronin
0082c02eb4 fix: bypass CodeMirror posAtCoords for accurate cursor at non-100% CSS zoom
CSS zoom on document.documentElement causes a coordinate space mismatch
between mouse event clientX/Y (viewport space) and Range.getClientRects()
(CSS space), breaking CodeMirror's click-to-position mapping. The previous
requestMeasure() fix only recalibrated cached geometry, not this mismatch.

New approach: zoomCursorFix extension patches posAtCoords/posAndSideAtCoords
on the EditorView instance to use document.caretRangeFromPoint() — the
browser's native, zoom-aware API — with coord-adjustment fallback.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 10:43:46 +01:00
lucaronin
e3d616cd26 fix: embed conversation history in AI agent chat messages
The AI chat panel (AiPanel → useAiAgent) was sending each message as a
standalone request with no prior context. Root cause: useAiAgent.sendMessage
called streamClaudeAgent with raw text, never embedding history.

- Add agentMessagesToChatHistory() to convert AiAgentMessage[] to ChatMessage[]
- Embed trimmed history in each agent request via formatMessageWithHistory
- Use messagesRef/statusRef to avoid stale closures in async callbacks
- Also fix useAIChat (dead code path) with same ref pattern
- Update mock layers to detect history presence for testability
- Add Playwright smoke tests verifying history accumulates and resets

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 10:21:49 +01:00
lucaronin
010d2c3949 fix: disk-first writes in useEntryActions, document three-layer model
Move updateEntry() calls after handleUpdateFrontmatter/handleDeleteProperty
in handleCustomizeType, handleRenameSection, and handleToggleTypeVisibility
so React state only updates after the disk write succeeds. This prevents
state-disk divergence when writes fail.

Expand ARCHITECTURE.md "Three representations, one authority" section with
ownership rules, invariants table, and recovery mechanisms. Add
reload_vault_entry to the commands table (62 total).

Add Playwright smoke test for Reload Vault in Cmd+K palette.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 00:52:56 +01:00
lucaronin
dedb5b2721 feat: wire Reload Vault into Cmd+K palette and menu bar
Adds a "Reload Vault" command that forces a full rescan from filesystem,
bypassing cache. Available via Cmd+K and Vault menu. Wired through
useAppCommands → useCommandRegistry and useMenuEvents.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 00:52:56 +01:00
lucaronin
9cc9ff80d8 refactor: remove hardcoded RELATIONSHIP_KEYS — detect wikilink fields dynamically
Any frontmatter field whose value contains [[wikilinks]] now renders as a
relationship chip automatically. Fields with plain-text values always render
as editable properties, even if they were formerly hardcoded relationship keys.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 00:33:57 +01:00
lucaronin
3e05a9425a test: add Playwright smoke test for exact-match search ranking
Verifies that searching "Writing" in Quick Open shows the exact title
match first, followed by prefix matches. Also adds Refactoring test
entries to mock data and demo vault.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 23:53:00 +01:00
lucaronin
55e479be13 feat: flip canonical type field — make type: primary, Is A: the alias
The Rust parser now treats `type:` as the canonical frontmatter field
for entity type, with `Is A:` and `is_a:` accepted as legacy aliases.
Previously it was the other way around, creating an asymmetric
read/write cycle since the frontend and all 8800+ vault notes already
use `type:`.

- Flip serde attribute: rename="type", alias="Is A", alias="is_a"
- Update theme defaults, getting-started vault, and type definitions
- Add round-trip tests for both type: and Is A: parsing
- Update mock data and TypeScript tests to use canonical form

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 23:38:17 +01:00
lucaronin
4649662f3e fix: ensure exact title match always ranks first in search
Title exact match gets exclusive tier 0 — alias exact match is capped
at tier 1, so a note titled "Refactoring" always appears above notes
with "Refactoring" as an alias or prefix. The 5-tier ranking is:
0=title exact, 1=alias exact, 2=title prefix, 3=alias prefix, 4=fuzzy.

Also adds ranking to editor wikilink autocomplete (enrichSuggestionItems)
and trims whitespace in searchRank comparisons.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 22:03:54 +01:00
lucaronin
873f85afc9 feat: move note to type folder when Is A changes
When the user changes a note's type via the Properties panel,
the note file is automatically moved to the corresponding type folder.
Shows a toast confirming the move. No move if already in correct folder.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 21:52:30 +01:00
lucaronin
4ce9167e09 feat: exact-match-first ranking in search and wikilink autocomplete
Add searchRank/bestSearchRank utilities that compute a tier (0=exact,
1=prefix, 2=fuzzy-only). Both useNoteSearch and WikilinkChatInput now
sort by rank tier first, then by fuzzy score, ensuring notes with exact
title or alias matches always surface above partial/fuzzy matches.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 21:00:58 +01:00
lucaronin
749647bf64 feat: fast note open — use allContent cache to skip IPC disk reads
handleSelectNote and handleReplaceActiveTab now check the in-memory
allContent cache before issuing a Tauri IPC call. Cache hits open the
tab synchronously (zero latency). Cache misses fall back to the disk
read and populate allContent via onContentLoaded so subsequent opens
of the same note are instant.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 20:33:57 +01:00
lucaronin
ea26e0a2ee fix: use vault path for resolveNewNote, resolveNewType, resolveDailyNote
Remove hardcoded /Users/luca/Laputa/ paths from resolveNewNote,
resolveNewType, and resolveDailyNote. All three now accept a vaultPath
parameter and build paths relative to the active vault. Added vaultPath
to NoteActionsConfig so the hook passes it through to all callers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 20:00:20 +01:00
lucaronin
8eac9f9e3f fix: show all scalar properties in Properties panel — remove Owner from RELATIONSHIP_KEYS, remove notion_id from SKIP_KEYS 2026-03-08 19:46:18 +01:00
lucaronin
71810a7a90 fix: resolve AI chat empty body race — read contextPrompt from closure, not stale ref
contextRef (useRef) was initialized at mount time and synced via useEffect,
which runs after paint. If contextPrompt was empty at mount (tab content
not yet loaded), sendMessage could read stale/empty context during the
window between paint and effect. Removing the ref and reading contextPrompt
directly in the useCallback closure eliminates the race entirely.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 19:02:21 +01:00
lucaronin
12fe4978ab fix: auto-save unsaved notes before trash/archive
Flush unsaved editor content to disk before any trash or archive
operation (both single-note and bulk) so body edits are never silently
dropped when only frontmatter is updated.

- Add flushEditorContent utility that checks pending content ref, then
  falls back to comparing tab content with last-saved state
- Add onBeforeAction callback to useEntryActions, called before
  handleTrashNote and handleArchiveNote
- Wire flushBeforeAction in App.tsx using refs for stable closures
- Add error handling in useBulkActions so one failed save doesn't
  block remaining notes
- Extract findOrCreateType helper to reduce useEntryActions complexity
- Export persistContent from useSaveNote for reuse

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 16:52:08 +01:00
lucaronin
d41fe306fe fix: AI chat receives live editor content instead of stale disk content
handleContentChange now syncs content to tab state on every editor
change (not just on Cmd+S save). This ensures the AI panel's context
snapshot always contains the current editor body, fixing the bug where
the AI reported empty note bodies for unsaved edits.

Root cause: pendingContentRef buffered content for save but never
updated notes.tabs[].content, so activeTab?.content (used by the AI
context builder) always reflected the last-saved disk content.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 15:07:45 +01:00
lucaronin
5290e1847d fix: CodeMirror cursor placement at non-100% zoom levels
Root cause: CSS zoom on document.documentElement caused stale CodeMirror
measurements. Two issues:

1. Race condition: zoom was applied in useEffect (parent), but CodeMirror
   was created in useEffect (child) — child effects run first, so CM
   measured at zoom=1 before zoom was actually applied.

2. No re-measure on zoom change: CSS zoom changes don't trigger
   ResizeObserver on descendant elements, so CodeMirror never updated
   its cached scaleX/scaleY, line heights, or character widths.

Fix:
- Apply zoom synchronously during useState init (before child effects)
- Dispatch 'laputa-zoom-change' event when zoom changes
- Listen for this event in useCodeMirror and call view.requestMeasure()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 14:54:50 +01:00
lucaronin
9c7f05fb7d fix: embed conversation history in prompt instead of broken --resume
Each CLI invocation is a fresh subprocess — --resume depends on session
persistence that doesn't reliably work with -p mode. Switch to prompt-
embedded history: prior exchanges are formatted into each request using
formatMessageWithHistory + trimHistory (already existed as dead code).

- Remove sessionIdRef and --resume session tracking
- Always send system prompt (each request is stateless)
- Split sendMessage into doSend(text, history) to handle retry correctly
- Retry now passes correct history (excludes the retried exchange)
- Tests verify history accumulation, clear, retry, and system prompt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 13:06:58 +01:00
lucaronin
43629ca62c fix: AI-created notes now visible — onVaultChanged fallback for missed file ops
detectFileOperation silently failed when tool input was undefined (timing
issues with NDJSON event ordering). Added onVaultChanged callback as fallback:
when Write/Edit/Bash tools complete but specific file can't be determined,
vault.reloadVault() is triggered. Also added safety net in onDone handler.

Threaded onVaultChanged through AiPanel → EditorRightPanel → Editor → App.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 14:19:41 +01:00
lucaronin
fe2cef092a fix: use --resume for AI chat conversation continuity
The previous approach embedded conversation history as formatted text
in the prompt (<conversation_history> tags). The claude CLI's -p flag
treats this as a single user turn, losing turn boundaries — so the
model had no real multi-turn context.

Switch to using --resume with the session_id returned by the CLI's
init event. This lets the CLI manage conversation state natively:
- First message starts a new session (with system prompt)
- Subsequent messages resume via --resume (no system prompt needed)
- Clear and retry reset the session_id for a fresh start

Extract makeStreamCallbacks() to keep useAIChat complexity below
CodeScene threshold.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 13:11:34 +01:00
lucaronin
c1e11f45df feat: add Repair Vault command and MCP configFiles
- Add "Repair Vault" to command palette (Cmd+K → "Repair Vault")
- Add "Repair Vault" to macOS Vault menu bar
- Wire repair_vault Tauri command through App → useAppCommands → registry
- Add menu event handler for vault-repair
- Update MCP get_vault_context to include configFiles.agents content
- Add repair_vault mock handler for browser testing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 12:39:55 +01:00
lucaronin
dc22a2d7d9 fix: MCP install command always visible in Cmd+K regardless of mcpStatus
The command was gated on `mcpStatus !== 'checking'` which meant it was
hidden during the initial async status check. Changed enabled to always
be true so users can find and run the command immediately on app start.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 11:58:46 +01:00
lucaronin
f2ec2ab55c feat: make MCP restore command always available in Cmd+K
The "Install MCP Server" command was only enabled when status was
"not_installed", preventing users from re-registering when MCP got
removed or broken. Now the command is always available:
- Shows "Install MCP Server" when not installed
- Shows "Restore MCP Server" when already installed
- Added restore/fix/repair keywords for discoverability
- Context-aware toast: "installed" vs "restored"
- Menu bar label updated to "Restore MCP Server"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 11:33:18 +01:00
lucaronin
0d4ca63ec8 fix: auto-save structural UI changes to disk immediately
Structural changes (sidebar visibility, label, order, template, icon/color)
now auto-create missing Type entries and call onFrontmatterPersisted to
refresh git status, so changes appear in git diff without user intervention.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 11:06:10 +01:00
lucaronin
a0eb1a292d test: add unit tests for detectFileOperation and parseBashFileCreation
24 tests covering Write/Edit/Bash file detection, edge cases
(malformed JSON, files outside vault, non-md files, undefined input),
and the parseBashFileCreation helper for redirect/tee patterns.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 03:41:06 +01:00
lucaronin
415bbb5413 fix: AI-created notes now trigger vault refresh and auto-open in tab
Root causes:
- toolInputMapRef in useAiAgent was overwritten by tool_progress events
  (which arrive with input=undefined AFTER the assistant message set
  the full input), causing detectFileOperation to receive undefined
  and skip file creation detection entirely.
- MCP open_note only broadcast open_tab without vault_changed, so
  the note list didn't refresh when Claude Code called open_note.
- detectFileOperation only handled Write/Edit but not Bash commands
  that create .md files via redirects.

Fixes:
- Preserve accumulated input in toolInputMapRef (input ?? prev?.input)
- MCP open_note now broadcasts vault_changed before open_tab
- detectFileOperation now detects Bash redirect patterns (>, >>, tee)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 03:39:34 +01:00
lucaronin
fe9ebc9063 fix: remove --resume from AI chat to fix conversation history
The AI chat was using both --resume (CLI session resumption) AND formatted
conversation history in the prompt simultaneously. This dual-context approach
confused the model — it saw the conversation twice (from session + from prompt
markup), leading to "I don't have context" responses on follow-ups.

Fix: remove --resume entirely from chat mode. Each CLI call is now independent,
with full conversation history formatted into the prompt via
<conversation_history> markup. trimHistory handles graceful truncation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 03:08:24 +01:00
lucaronin
1dccc0239c feat: reindex vault command, indexing status bar, sync-triggered reindex
- Add "Reindex Vault" command to command palette and menu bar
- Show "Indexed Xm ago" in status bar when idle, clickable to reindex
- After git pull with updates, auto-trigger incremental reindex
- Add lastIndexedTime state to useIndexing, populated from backend metadata
- Add triggerFullReindex to useIndexing (retryIndexing is now an alias)
- Add onSyncUpdated callback to useAutoSync
- Extract formatIndexedElapsed to utils/indexingHelpers.ts
- Tests: 20 new unit tests across 5 files, 2 Playwright smoke tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 01:14:12 +01:00
lucaronin
902a545c23 feat: surface actionable push error messages in frontend
Update commitWithPush to parse GitPushResult from backend and show
specific messages (rejected, auth, network) instead of generic
"push failed". Tests verify rejected + network error scenarios.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 00:31:46 +01:00
lucaronin
875d8177a4 fix: add visible key to frontmatterToEntryPatch maps
The ENTRY_DELETE_MAP and update map in frontmatterToEntryPatch were
missing the 'visible' key. When handleDeleteProperty or
handleUpdateFrontmatter was called for 'visible', the in-memory
VaultEntry was not updated, causing the sidebar to stay stale even
after the file on disk was correctly modified.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 00:20:51 +01:00
lucaronin
21bfaa8c30 fix: include full conversation history in AI chat requests
- Add trimHistory() to keep most recent messages within 100k token budget
- Add formatMessageWithHistory() to prepend conversation context to each message
- Wire up in useAIChat.ts: sendMessage now includes full history
- Keep --resume as belt-and-suspenders for same-session continuity
- 14 new tests in ai-chat.test.ts and useAIChat.test.ts
2026-03-06 23:47:59 +01:00
lucaronin
95f6c05053 refactor: remove Favorites and Untagged from sidebar
- Remove Favorites NavItem, Star icon import, go-favorites command
- Remove Untagged NavItem, TagSimple icon import
- Remove favorites from SidebarFilter union type
- Update tests: Sidebar.test.tsx, useMenuEvents.test.ts, App.test.tsx
- Remove GO_FAVORITES constant and menu item from menu.rs
2026-03-06 23:19:37 +01:00
lucaronin
ddd65926d8 test: Playwright smoke test for trash → Changes badge
Also track mock frontmatter writes in mockSavedSinceCommit so the
Changes panel updates correctly in browser dev mode.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 23:08:18 +01:00
lucaronin
7a7ba6086a fix: refresh Changes panel after trash/archive operations
Trash, archive, restore, and unarchive wrote frontmatter to disk but
never called loadModifiedFiles, so the change didn't appear in the
Changes panel until the next manual refresh.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 23:01:05 +01:00
lucaronin
e5aaacdc27 fix: add missing visible field to buildNewEntry in useNoteActions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:57:00 +01:00
lucaronin
4df386d310 refactor: remove hidden_sections from VaultConfig and delete useSectionVisibility
Sidebar section visibility is now controlled entirely by the `visible`
property on Type notes. Removes all hidden_sections references from
Rust struct, TypeScript interface, config migration, mock data, and tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:41:00 +01:00
lucaronin
48c3bd11aa feat: add handleToggleTypeVisibility to useEntryActions
Toggle visible property on Type note frontmatter: sets visible:false
to hide, deletes visible property to show (defaults to visible).
Wire up in App.tsx via onToggleTypeVisibility prop.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:35:18 +01:00
lucaronin
e7f43d5d10 fix: sign qmd binaries with Developer ID + hardened runtime for notarization
Apple notarization rejected qmd/qmd and qmd/vec0.dylib due to:
- Not signed with valid Developer ID certificate
- Hardened runtime not enabled

Changes:
- bundle-qmd.sh: use APPLE_SIGNING_IDENTITY + --options runtime --timestamp in CI
  (falls back to ad-hoc signing in dev when no identity is set)
- useThemeManager.test.ts: add ensure_vault_themes to mock (added by theme
  editor feature, missing from stale theme ID test mock)
2026-03-06 08:43:54 +01:00
lucaronin
817055a9e1 fix: make qmd/search work on fresh installs — auto-install, fix permissions, sign binaries
On fresh MacBook installs, the bundled qmd binary fails to run due to:
missing execute permissions, macOS quarantine attributes, and no fallback
when qmd is completely absent. This fix addresses all three issues:

- Runtime: ensure +x permissions and remove quarantine on bundled qmd
- Runtime: auto-install qmd via bun when binary not found anywhere
- Build: ad-hoc code-sign qmd and .dylib files in bundle-qmd.sh
- Build: create placeholder resource dirs so fresh clones build cleanly

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 22:13:03 +01:00
lucaronin
51ccece936 fix: always show Resolve Conflicts in Cmd+K — show toast when no conflicts 2026-03-05 18:18:52 +01:00
lucaronin
559c585a08 feat: add Pulse — vault activity feed showing git commit history
Adds a new Pulse sidebar section that shows chronological git commit
history for the vault. Commits are grouped by day with message, time,
short hash (clickable GitHub link when remote configured), file list
with add/modify/delete status icons, and summary badges. Clicking a
file opens the note in the editor. Disabled with tooltip for non-git
vaults. Accessible via sidebar click or "Go to Pulse" command palette.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 16:27:29 +01:00
lucaronin
6b13120fa6 feat: move vault UI config from localStorage to vault files
Add VaultConfig infrastructure (store, hook, migration) that persists
zoom, view mode, section visibility, tag/status colors, and property
display modes to config/ui.config.md in the vault instead of localStorage.

- New vaultConfigStore module with subscribe/notify pattern
- useVaultConfig hook loads config via Tauri, binds store, runs migration
- One-time silent migration from localStorage on first load
- Config type excluded from note search and unified search
- All hooks/utils updated to read/write through vault config store
- Tests updated to use vault config store instead of localStorage mocks

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 15:26:21 +01:00
lucaronin
a364cbc2bd feat: expose all theme.json properties in theme editor
Add ThemePropertyEditor component that surfaces all customizable
properties from theme.json — typography, headings, lists, code blocks,
blockquote, table, and horizontal rule — organized into collapsible
sections with appropriate input types (number, color, select, text).

- themeSchema.ts: derives flat property list from theme.json with
  auto-detected input types, units, and select options
- ThemePropertyEditor.tsx: sectioned editor with collapsible sections,
  keyboard-accessible toggles, debounced live updates
- ThemeManager: add updateThemeProperty() and activeThemeContent
- SettingsPanel: show property editor below theme list when active

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 14:42:28 +01:00
lucaronin
03d4d51ee9 fix: move view-toggle-backlinks to simple event map for type safety
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 14:34:03 +01:00
lucaronin
a966b2cc65 feat: reorganize menu bar with Go, Note, and Vault menus
Add missing command palette commands to menu bar and reorganize into
logical groups: File, Edit, View, Go, Note, Vault, Window. New menus
expose navigation filters, note actions, vault management, themes, and
git operations. Context-sensitive items (archive, trash, diff, raw
editor, commit, conflicts) are greyed out when not applicable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 14:34:03 +01:00
lucaronin
9f35f049d7 fix: enable line wrapping in raw editor
Long lines now wrap to the next visual line instead of scrolling
horizontally off-screen, matching expected behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 12:57:16 +01:00
lucaronin
da01d2ec28 fix: make Restore Default Themes command always enabled in Cmd+K palette
The enabled guard `!!onRestoreDefaultThemes` could evaluate to false at
runtime, hiding the command from the palette. Since the handler is always
defined via useCallback, the guard is unnecessary. Changed to enabled: true,
matching the pattern used by other always-available commands.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 12:32:32 +01:00
lucaronin
85234b1b98 feat: enable full shell access for AI agent + simplify MCP tools
Remove --tools "" restriction so the agent has native bash/read/write/edit
access. Set vault path as working directory for the subprocess.

Simplify MCP to 4 Laputa-specific tools (search_notes, get_vault_context,
get_note, open_note) — everything else is handled by native tools.

Add file operation detection from Write/Edit tool calls to auto-open
created notes and refresh modified notes in the UI. Enhanced tool call
labels show bash commands, file paths, and note names.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 12:12:12 +01:00
lucaronin
d5849593ea feat: Add 'Restore Default Themes' command for vaults missing theme structure
- New restore_default_themes() Rust fn: seeds both _themes/ and theme/ dirs
- Per-file idempotent: never overwrites existing files with content
- Fixed ensure_vault_themes() to include minimal.md (was missing)
- New 'Restore Default Themes' command in Cmd+K Appearance group
- 3 new Rust tests + 4 new frontend tests
- 1676 frontend tests passed
2026-03-05 11:18:53 +01:00
lucaronin
795badf78b fix: detect and resolve rebase conflicts in sync conflict resolution
The previous conflict detection only worked for merge-based pulls
(--no-rebase) but failed to detect pre-existing conflicts from
interrupted rebases or prior sessions. This fixes three root causes:

1. Rust: add is_rebase_in_progress/is_merge_in_progress/get_conflict_mode
   helpers, and dispatch git_commit_conflict_resolution between
   `git commit` (merge) and `git rebase --continue` (rebase)
2. Frontend: add startup conflict check via get_conflict_files before
   pulling, so pre-existing conflicts are detected on app launch
3. App.tsx: handleOpenConflictResolver now fetches conflicts directly
   when the cached list is empty, preventing the silent early-return

Also exposes get_conflict_files and get_conflict_mode as Tauri commands
so the frontend can independently check conflict state.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 10:34:25 +01:00