Replace unreliable filesystem ctime/mtime with git log timestamps.
A single batch `git log` walks the full commit history to extract
created_at (oldest commit) and modified_at (newest commit) for each
.md file. Falls back to filesystem dates for non-git vaults and
uncommitted files. Cache version bumped to 10 for full rescan.
ADR 0039 documents the decision.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds FAVORITES sidebar section backed by _favorite and _favorite_index
frontmatter properties. Star button in breadcrumb bar toggles favorite
state. Drag-to-reorder updates _favorite_index on all affected notes.
Section auto-hides when empty.
ADR 0038 documents the decision to use frontmatter for portability.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cmd+I is the standard italic shortcut in text editors. The AI panel
was overriding it, breaking italic formatting. Reassigned to
Cmd+Option+I (CmdOrCtrl+Alt+I in Tauri menu) which is free.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Files with malformed YAML (e.g. Notion exports containing unescaped
double quotes inside double-quoted strings) caused gray_matter to return
Pod::Null instead of a parsed Hash. This silently reset all frontmatter
fields to defaults, making trashed/archived notes appear in Inbox.
Add a line-by-line fallback parser that extracts simple key:value pairs
when gray_matter fails, so critical fields (Trashed, Archived, type)
are never lost. Bump cache version to 9 to force rescan.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. Folder selection now recursively includes notes from subfolders
2. + button creates a new folder with inline rename (Tauri command + UI)
3. Note list items show full path when note is in a subdirectory
4. Remove flat vault migration banner and all related code (Rust commands,
hook, component, smoke test) — subfolders are now first-class
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Bug 1: Wikilink autocomplete now always inserts the vault-relative path
as the target (e.g. [[docs/adr/0001-tauri-stack|Title]]) instead of
just the filename. This ensures wikilinks are unambiguous and resolve
correctly across subfolders after reload.
Bug 2: unique_dest_path now excludes the source file from collision
checks, preventing false positives where a note's own file is treated
as a naming conflict (causing silent -2 suffix renames).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When the app regains focus, checks git diff for renames (--diff-filter=R).
If renamed .md files are found, shows a non-blocking banner with "Update
wikilinks" and "Ignore" buttons. The update reuses the existing vault-wide
wikilink replacement logic from rename.rs.
New Tauri commands: detect_renames, update_wikilinks_for_renames.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When opening a vault without a .git directory, a blocking modal prevents
app use until the user either creates a repository (git init + add +
commit) or chooses another vault. The check runs via is_git_repo Tauri
command; browser mode fails open.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extend the Rust vault scanner to index .md files in all visible
subdirectories (hidden dirs excluded). Add FolderNode struct and
list_vault_folders Tauri command that returns the directory tree.
On the frontend, add FolderNode type, extend SidebarSelection with
{ kind: 'folder'; path: string }, and add isInFolder() filtering
in noteListHelpers.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tauri's default dragDropEnabled=true intercepts HTML5 DnD events at the
webview level, preventing BlockNote's block handle drag-to-reorder from
receiving dragstart/dragover/drop events. Setting dragDropEnabled=false
lets all drag events flow through standard HTML5 DnD, which BlockNote
expects.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Editor (400px), note list (220px), sidebar (180px), and inspector
(240px) now have CSS min-width constraints. Window minWidth set to
800px in Tauri config. Flex-shrink ratios create cascade order:
editor shrinks first, then note list, then sidebar.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove AIChatPanel, useAIChat hook, Rust ai_chat command, and
anthropic_key from settings. AI is now exclusively via Claude CLI
subprocess (AiPanel). Simplifies codebase and eliminates API key
management for users. ADR-0027 superseded.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Completes the commands/ module split: GitHub commands now live in
github.rs (88 lines) instead of bloating git.rs (318→233). Vault
and frontmatter tests moved from mod.rs to vault.rs where they
belong (mod.rs 254→93 lines, CodeScene 9.24→9.84). Deduplicated
batch_archive/trash test setup with a shared temp_note helper.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Initialize Tauri iOS support with conditional compilation:
- Desktop-only features (git CLI, menu, MCP, Claude CLI) gated behind #[cfg(desktop)]
- Mobile stubs return graceful errors so frontend degrades smoothly
- Vault read/write, AI chat, search, settings work unchanged on both platforms
- Xcode project generated, Rust cross-compiles cleanly to aarch64-apple-ios-sim
- All 581 Rust tests and 2201 frontend tests still pass
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reverts commits 47b5e45, 5c76939, 1eecae0, 660208a, 86a9f65, 259d5b6.
Removes PinnedPropertiesBar, usePinnedProperties hook, Rust backend
for _pinned_properties, and all related tests.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add update_channel setting (stable/canary) to Settings with UI toggle.
Stable channel uses Tauri updater plugin; canary fetches latest-canary.json
and opens GitHub release page for manual download. Add useFeatureFlag()
hook with localStorage overrides and compile-time defaults (no remote
dependencies). Add release-canary.yml CI workflow for canary branch builds.
Update stable workflow to preserve latest-canary.json on GH Pages.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- JS: @sentry/browser + posthog-js with lazy init and path scrubbing
- Rust: sentry crate with beforeSend path scrubber
- useTelemetry hook reactively inits/tears down SDKs on settings change
- reinit_telemetry Tauri command lets frontend trigger Rust-side reinit
- Zero network requests without explicit user consent
- All file paths redacted from error payloads via regex scrubber
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New fields: telemetry_consent, crash_reporting_enabled, analytics_enabled,
anonymous_id. All Option/null by default for backward compatibility with
existing settings.json files.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the multi-tab model with single-note navigation. One note is
open at a time; clicking any note (sidebar, wikilink, relationship)
replaces the current note in the editor. Back/Forward history still
works via Cmd+[/].
Removed: TabBar component, useClosedTabHistory, tab reorder/close/
reopen logic, Cmd+W/Cmd+Shift+T shortcuts, Close Tab and Reopen
Closed Tab menu items, tabLayout utility, and all related tests.
Simplified: useTabManagement (single-note), useAppNavigation (no tab
lookup), useKeyboardNavigation (note nav only), useNoteCreation (no
close-tab cleanup), useDeleteActions (deselect instead of close tab),
Editor (no TabBar render), Rust menu (removed 2 menu items).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove the entire QMD search engine (semantic indexing, hybrid search,
vector embeddings) and replace with a simple walkdir-based keyword
search. QMD never worked reliably in production, added bundle bloat,
and showed "Index failed" in the status bar.
What changed:
- Rust: deleted indexing.rs, rewrote search.rs as pure keyword search
- Frontend: removed useIndexing hook, IndexingBadge, hybrid search
- Menu: removed "Reindex Vault" command from palette and menu bar
- Config: removed qmd from bundle resources and build script
- Deleted tools/qmd/ (QMD CLI tool, MCP server, tests)
- Updated docs (ARCHITECTURE, ABSTRACTIONS, GETTING-STARTED)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the in-vault ui.config.md file with localStorage persistence
keyed by vault path. Vaults now contain only user content — no app
config files. Removes the Rust vault_config module, Tauri commands
(get/save_vault_config), startup migrations, and demo vault config files.
The reactive store (vaultConfigStore) and consumer hooks (useZoom,
useViewMode, useRawMode) are unchanged — only the storage backend moved.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove all theme switching, creation, and management functionality
from the app — backend (Rust theme module, Tauri commands, menu items,
startup tasks, vault seeding), frontend (useThemeManager, ThemePropertyEditor,
themeSchema, command palette Appearance group, settings panel appearance
section, isDarkTheme prop chain), mock data, and all related tests.
Editor styling via theme.json/EditorTheme.css is preserved (not user theming).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Repair Vault was creating config/ui.config.md inside a config/ subdirectory.
All vault config files should live at vault root (flat structure). Changed
config_path() to point to vault root, added migrate_ui_config_to_root() for
legacy migration, and wired it into both startup and repair_vault flows.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sync Tauri commands (git_pull, git_push, git_remote_status, reload_vault)
blocked the runtime thread during network I/O, freezing the UI for 2-3s
on every Cmd+Tab. Converted them to async with tokio::spawn_blocking.
Added 30s cooldown to focus-triggered git pull and theme settings reload
to prevent redundant work on rapid app switching.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Two root causes:
1. noteListHooks used a stale selection.entry to build relationship groups —
now looks up the fresh entry from the entries array so relationship updates
propagate immediately.
2. frontmatterToEntryPatch didn't update entry.relationships — added
RelationshipPatch support so frontmatter changes also update the
relationships map in state.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When push is rejected due to remote having newer commits, the bottom bar
now shows "Pull required" (orange). Clicking it pulls then auto-pushes.
Conflicted notes show an inline banner with "Keep mine" / "Keep theirs"
buttons. A new "Pull from Remote" command is available in Cmd+K and the
Vault menu. Clicking the sync badge opens a popup showing branch name,
ahead/behind counts, and a Pull button.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add multi-window support: notes can be opened in dedicated secondary
Tauri windows with editor-only layout (no sidebar, no note list).
Triggers: Cmd+Shift+Click on notes, Cmd+K → "Open in New Window",
Cmd+Shift+O shortcut, Note → "Open in New Window" menu bar item.
Secondary windows have their own auto-save, theme, and wikilink
navigation. Closing a secondary window does not affect the main window.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Inbox shows notes without valid outgoing relationships (body wikilinks
or frontmatter refs), helping users find captured but unorganized notes.
Includes time-period filter pills (This week/month/quarter/All time),
Cmd+K command, and macOS menu bar entry. Broken wikilinks (targeting
non-existent notes) are not counted as relationships.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
H1 headings are body content, not the title source of truth. Remove
useHeadingTitleSync hook and frontmatter-title-from-H1 logic in the
editor. Rust rename_note no longer modifies H1 in file content — only
updates the frontmatter title: field.
TitleField now uses optimistic UI: the new title displays immediately
after commit while the async file rename runs in background, preventing
UI freezes on slow filesystems or large vaults.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Repair Vault and app startup no longer create or recreate the _themes/
directory (legacy JSON theme store). All config files — theme notes,
theme.md, config.md, AGENTS.md — are seeded exclusively at vault root.
- Remove seed_default_themes() and all _themes/ creation paths
- Add migrate_legacy_themes_dir() to clean up _themes/ with only defaults
- Stop list_themes() from auto-creating _themes/ when absent
- Remove _themes from KEEP_FOLDERS and PROTECTED_FOLDERS (flatten-safe)
- Fix create_theme() to error instead of recreating _themes/
- Remove _themes/ seeding from create_getting_started_vault()
- Update all affected tests (642 Rust + 2253 frontend pass)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>