Commit Graph

318 Commits

Author SHA1 Message Date
Test
af147c4cf0 style: fix rustfmt blank line in menu.rs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 17:29:09 +01:00
Test
c4136d69b4 refactor: remove tab bar — single note open at a time
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>
2026-03-24 17:24:49 +01:00
Test
2fdc122d73 style: rustfmt search.rs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:21:29 +01:00
Test
60d3b48ea6 fix: resolve clippy single-element-loop in build.rs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:20:23 +01:00
Test
ecbb94ae83 refactor: remove QMD semantic indexing — keep keyword search only
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>
2026-03-24 16:18:05 +01:00
Test
845181d002 refactor: move vault UI config from ui.config.md to localStorage
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>
2026-03-23 21:07:38 +01:00
Test
35c62583d9 style: rustfmt use statement
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 20:01:15 +01:00
Test
a6b2454184 refactor: remove theming system entirely
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>
2026-03-23 19:57:58 +01:00
Test
33ae00a558 style: apply rustfmt to vault_config.rs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 21:04:05 +01:00
Test
ac02de88e6 fix: store ui.config.md at vault root instead of config/ directory
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>
2026-03-20 21:00:19 +01:00
Test
07522e984c fix: eliminate UI freeze on app focus by moving git commands off main thread
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>
2026-03-20 19:05:23 +01:00
Test
d52365882c style: rustfmt formatting for mod_tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 03:28:36 +01:00
Test
135fe62d21 fix: note list shows incomplete relationships when opening from sidebar
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>
2026-03-20 03:26:52 +01:00
Test
4e88cf71b1 style: rustfmt import formatting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 09:53:42 +01:00
Test
05dca72ef3 feat: handle git divergence, conflicts, and manual pull from within Laputa
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>
2026-03-19 09:51:06 +01:00
Test
7c16ebd065 feat: open note in new window (Cmd+Shift+Click / Cmd+Shift+O)
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>
2026-03-19 08:47:25 +01:00
Test
bc55231baa feat: add Inbox sidebar section showing unlinked notes
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>
2026-03-19 06:41:40 +01:00
Test
e8ace69bb0 style: rustfmt formatting for rename.rs assertions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 15:44:34 +01:00
Test
8cfe7de66a fix: decouple H1 from title sync + non-blocking TitleField rename
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>
2026-03-18 15:42:48 +01:00
Test
c559188f5a fix: remove legacy _themes/ dir creation, seed type defs at vault root
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>
2026-03-18 12:39:37 +01:00
Test
ecd941c54e fix: sync title on reopen of already-open tabs (desync detection)
handleSelectNote skipped syncNoteTitle for tabs already open (early
return). Moved sync call into handleSelectNoteWithSync so it always
runs, even when switching to an existing tab via Cmd+P. Also removes
H1 fallback from extract_title — title now comes from frontmatter or
filename only, per the title/filename contract.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 02:37:29 +01:00
Test
e1c545220f fix: read owner/cadence from properties in ai-context
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 02:01:05 +01:00
Test
e6b3278fea refactor: remove owner/cadence from Frontmatter, source created_at from filesystem
Remove owner, cadence, created_at, and created_time as hardcoded fields from
the Frontmatter struct — they don't drive app logic and belong in generic
properties. Owner and cadence values now flow through to the properties map
(including single-element array unwrapping). Creation date is sourced from
filesystem metadata (birthtime on macOS) instead of frontmatter.

Also fixes title extraction: add H1 heading extraction to extract_title()
(priority: frontmatter title → H1 → filename slug). Previously titles fell
back directly to filename when no frontmatter title was set.

StringOrList is retained for scalar Frontmatter fields as a defensive measure:
YAML values can arrive as single-element arrays (e.g. Status: [Active]) which
would cause entire deserialization to fail without it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 01:56:33 +01:00
Test
414cb12c7d style: rustfmt formatting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 17:14:35 +01:00
Test
3a24178759 fix: remove unused import and dead code from title sync refactor
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 17:08:07 +01:00
Test
a1688f8488 feat: title/filename sync on note open + always write title in rename
- New sync_title_on_open function: detects desync between title frontmatter
  and filename, corrects it (filename wins as source of truth)
- Registered sync_note_title Tauri command
- rename_note now always writes title to frontmatter (not just when present)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 16:45:30 +01:00
Test
56b923c650 refactor: extract_title reads from frontmatter title, not H1
Title is now sourced from the `title` frontmatter field with filename-
derived fallback (slug_to_title). H1 headings are treated as body content.
Added `title` to Frontmatter struct and SKIP_KEYS. Made title_to_slug
pub(super) for reuse across vault submodules.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 16:41:49 +01:00
Test
dc6edd74af fix: rustfmt formatting in mod_tests.rs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 15:10:06 +01:00
Test
50dec4bcf3 refactor: extract vault/mod.rs into submodules — fix CodeScene hotspot health
vault/mod.rs was 1820 lines with duplicated code already extracted to
entry.rs, frontmatter.rs, file.rs but never wired up. Slim mod.rs to
delegate to submodules. Score: 7.85 → 10.0.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 15:07:29 +01:00
Test
a808880e32 style: rustfmt repair_vault tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 14:32:17 +01:00
Test
1e3ddb231c fix: repair vault now flattens type folders and migrates legacy frontmatter
Repair Vault command now runs flatten_vault() and migrate_is_a_to_type()
before restoring themes and config, ensuring vaults adopt flat structure.
Also fixes config.md type definition to use `type: Type` instead of
legacy `Is A: Type`.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 14:32:17 +01:00
Test
08493f8217 style: rustfmt seed.rs and getting_started.rs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 12:09:28 +01:00
Test
6dc6b5e515 refactor: improve code health for vault/mod.rs and Editor.tsx — fix CodeScene hotspot score
Extract scan_vault helpers (is_md_file, try_parse_md, scan_root_md_files, scan_protected_folders)
to eliminate deep nesting and reduce cyclomatic complexity. Break up large assertion blocks in tests.
Extract useEditorSetup and useRawModeWithFlush hooks from Editor component to reduce complexity.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 12:07:33 +01:00
Test
beb49b6e40 fix: update Repair Vault for flat vault structure — no theme/ or config/ dirs
Theme vault notes now live at root as default-theme.md, dark-theme.md,
minimal-theme.md instead of in theme/ subdirectory. AGENTS.md holds full
content at root instead of stub+config/agents.md pattern. Adds migration
for legacy theme/ and config/ directories on startup and repair.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 12:06:09 +01:00
Test
fa49251459 feat: persist editor mode (raw/preview) across note switches
Editor mode is now stored as a global preference in VaultConfig instead of
being tracked per-tab. Toggling raw mode persists across tab switches and
app restarts via the editor_mode field in config/ui.config.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 11:41:35 +01:00
Test
67dbda8f24 style: rustfmt vault mod.rs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 10:38:47 +01:00
Test
17f94647b7 fix: uniform StringOrList normalization for all frontmatter string fields
Replace per-field Option<String> with Option<StringOrList> for all string
fields in the Frontmatter struct (owner, cadence, status, icon, color,
sidebar_label, template, sort, view, trashed_at, created_at, created_time).

Previously, fields like Owner stored as YAML arrays (e.g. `Owner: [Luca]`)
caused serde to fail the entire Frontmatter deserialization, defaulting all
fields to None — including is_a, which broke the type badge display.

Now all string fields use StringOrList with into_scalar() normalization:
- Single-element array → unwrap to scalar
- Multi-element array → take first element
- Scalar → unchanged
- Empty array → None
- Absent → None

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 10:37:16 +01:00
Test
2f028404b1 style: rustfmt vault mod.rs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 20:29:39 +01:00
Test
1550c02e4a fix: add missing VaultEntry fields (belongs_to, status, owner, cadence)
The vault module split left the mod.rs VaultEntry struct missing fields
that were added in entry.rs but never wired in. Adds the missing fields,
populates them from frontmatter, adds status/owner/cadence to SKIP_KEYS,
and fixes conflicting test expectations from the incomplete merge.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 20:20:58 +01:00
Test
19d53da8fb fix: use contains() instead of iter().any() for clippy manual_contains
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 19:45:57 +01:00
Test
15a747094b Resolve merge conflict: keep split vault module from origin/main 2026-03-16 19:25:49 +01:00
Test
d1bbacafb3 style: apply rustfmt to mod_tests.rs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 19:03:14 +01:00
Test
7b6d8773d4 fix: resolve clippy warnings from vault module split
Remove unused HashMap import from mod.rs, use contains() instead of
iter().any() in frontmatter.rs, add HashMap import to test module.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 19:03:14 +01:00
Test
4c6b0430f4 refactor: split vault/mod.rs monolith into entry, frontmatter, file modules
Extract VaultEntry struct to entry.rs (64 lines), YAML parsing to
frontmatter.rs (323 lines), and file I/O helpers to file.rs (59 lines).
Tests moved to mod_tests.rs. mod.rs reduced from 1679 to 189 lines,
now purely orchestration (parse_md_file, reload_entry, scan_vault).

All 612 tests pass, public API unchanged.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 19:03:14 +01:00
Test
7a341c2a5e fix: clippy manual_contains lint in vault frontmatter filter
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 18:33:13 +01:00
Test
85fa0b8680 fix: frontmatter parsing fails when unknown fields have list values
The Frontmatter struct deserialization failed completely when any unknown
field had a list value (e.g. Owner: [Luca], Cadence: [Weekly]) because
serde expected a string but got an array. This caused unwrap_or_default()
to return all-None, losing type/status/archived for ~7000+ notes.

Two fixes:
1. Filter parse_frontmatter input to only known keys, preventing unknown
   fields from causing deserialization failures
2. Change Owner and Cadence to StringOrList to handle both formats
2026-03-16 17:12:58 +01:00
Test
08668854b9 fix: flat vault type resolution — remove type/ prefix from links and protected folders
- Type relationship links: [[type/essay]] → [[essay]] (matches flat vault structure)
- PROTECTED_FOLDERS / KEEP_FOLDERS: only attachments, _themes, assets
- TypeSelector navigation: type/slug → slug
- Updated all 14 affected test files
- All 612 Rust tests + 2151 frontend tests pass
2026-03-16 16:19:24 +01:00
Test
fa74009877 feat: ensure .DS_Store in .gitignore for all new vaults
Extract ensure_gitignore from init_repo so it can be reused by
clone_repo (GitHub "Create New" flow) and repair_vault. New vaults
created via any path now get .DS_Store excluded by default.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 05:36:45 +01:00
Test
f89b199b79 fix: cargo fmt formatting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 05:06:24 +01:00
Test
a88c9fc2d0 feat: add vault_health_check command
Detects two classes of vault issues:
1. Stray files in non-protected subfolders (won't be scanned)
2. Filename-title mismatches (filename ≠ slugify(title))

Returns a VaultHealthReport with stray_files and title_mismatches.
Registered as a Tauri command for frontend use.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 05:06:24 +01:00