Commit Graph

83 Commits

Author SHA1 Message Date
lucaronin
ce5f48bfbf fix: remove broken Create New Vault button, unify with Open Local Folder
window.prompt() doesn't work in Tauri WebView on macOS — silently returns null.
Removed handleCreateNewVault + create_vault_dir Tauri command entirely.
Open Local Folder is equivalent; Finder lets users create folders inline.

Also removes tauriCall helper (was only used by handleCreateNewVault).
573 frontend tests pass.
2026-02-24 00:35:18 +01:00
lucaronin
8454ce7be5 fix: remove vault.rs accidentally restored by cherry-pick
The save-regression cherry-pick (e51bafd) re-introduced the pre-refactor
vault.rs alongside vault/mod.rs, causing E0761 (ambiguous module) on CI.

vault/mod.rs (from PR #21 refactor-vault-rs) is the correct implementation
and already exports all needed functions (save_note_content, get_note_content,
purge_trash, etc.). Removing the duplicate vault.rs resolves the CI failure.
2026-02-24 00:33:20 +01:00
lucaronin
e51bafd4b7 fix: prevent editor from reverting content after Cmd+S save
The tab-swap useEffect in Editor.tsx watched [activeTabPath, tabs, editor].
When save updated tabs via setTabs, the effect re-ran and re-applied stale
cached blocks from the initial tab load, visually reverting the editor.
Subsequent edits would then save old content, effectively losing changes.

Fix: skip the block swap when activeTabPath hasn't changed (only tab content
was updated). Also refresh the cache with current editor blocks so a later
tab switch doesn't revert to stale content.

Added regression tests for the save → update round-trip (JS + Rust).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 00:11:08 +01:00
Luca Rossi
d17739179a Merge pull request #21 from refactoringhq/task/refactor-vault-rs
refactor: split vault.rs into focused submodules (CodeScene 7.29 → 10.0)
2026-02-24 00:03:22 +01:00
lucaronin
c67c4a267e fix: cargo fmt on migration.rs tests 2026-02-24 00:01:16 +01:00
Luca Rossi
53cba9f88d Merge pull request #24 from refactoringhq/task/git-commit-zero-files
fix: commit & push now saves pending content and refreshes modified files
2026-02-23 23:31:17 +01:00
lucaronin
437a35420c test: add unit tests for vault/migration.rs to restore Rust coverage to ≥85%
Tests cover: has_legacy_is_a, extract_is_a_value, migrate_file_is_a_to_type,
and migrate_is_a_to_type (public function). migration.rs was at 0% coverage.
2026-02-23 23:22:42 +01:00
lucaronin
6b22197161 fix: cargo fmt git.rs + remove unused modifiedFiles dep from useMemo 2026-02-23 23:08:09 +01:00
lucaronin
e2bc3ef4c0 fix: commit & push now saves pending content and refreshes modified files
Root cause: Two problems caused "0 files changed":
1. loadModifiedFiles() was only called on mount, never refreshed after saves
2. Pending editor content wasn't flushed to disk before git commit

Fix:
- useEditorSave: add savePending() to flush unsaved content, onAfterSave
  callback to refresh git status after Cmd+S
- useCommitFlow: new hook managing save→commit→push flow with proper
  sequencing (save pending → refresh files → show dialog → commit)
- App.tsx: wire onAfterSave to loadModifiedFiles, use useCommitFlow
- git.rs: include stdout in error when stderr is empty (fixes "nothing
  to commit" message being swallowed)
- mock-tauri: track saved files so get_modified_files reflects edits

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 23:08:09 +01:00
lucaronin
ad41fbb9cd style: rustfmt — remove trailing blank line in tests module 2026-02-23 23:06:46 +01:00
lucaronin
c0426c84c8 fix: close mod tests block in lib.rs (unclosed delimiter from rebase) 2026-02-23 23:06:46 +01:00
lucaronin
066bef8eba style: rustfmt formatting fixes for CI 2026-02-23 23:06:46 +01:00
lucaronin
1c064731fc test: add HTTP mock tests for github.rs and ai_chat.rs to fix coverage
Coverage was 83.83% (below 85% threshold). Added mockito-based HTTP mock
tests for all OAuth device flow functions, list/create repo, get user,
and send_chat. Coverage now at 90.26%.

- github.rs: 55.99% → 94.85% (added mock tests for all HTTP functions)
- ai_chat.rs: 63.27% → 95.70% (added mock tests for send_chat paths)
- Added mockito = "1" as dev-dependency
- Refactored HTTP functions to accept configurable base URLs for testability
2026-02-23 23:06:46 +01:00
lucaronin
211c7e5d41 test: add tests for GitHub OAuth device flow types and Settings UI
- Add serialization tests for DeviceFlowStart, DeviceFlowPollResult, GitHubUser
- Add SettingsPanel tests for OAuth section: login button, connected state,
  disconnect, waiting state with user code, no token field
- All 174 Rust + 475 frontend tests pass

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 23:06:46 +01:00
lucaronin
bf549d5605 feat: replace GitHub token field with OAuth device flow login
- Add github_username to Settings type (Rust + TS)
- Add device flow commands: github_device_flow_start, github_device_flow_poll, github_get_user
- Replace manual token KeyField with "Login with GitHub" OAuth button
- Show connected state with username after successful OAuth
- Add disconnect functionality to clear OAuth token
- Update mock-tauri.ts with device flow mock handlers
- Update all tests for new Settings shape

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 23:06:46 +01:00
lucaronin
3eef1e76d4 fix: add migration module with migrate_is_a_to_type — was missing after vault.rs refactor 2026-02-23 23:05:34 +01:00
lucaronin
7a8b8bc618 fix: use inner doc comment to fix clippy::empty_line_after_doc_comments 2026-02-23 22:37:31 +01:00
lucaronin
5aac07f7e2 fix: restore save_note_content and missing pub fns from main merge 2026-02-23 22:37:31 +01:00
lucaronin
42b543992c refactor: split vault.rs into focused submodules
Break the 2338-line vault.rs into vault/ directory with 6 focused modules:
- mod.rs: core types (VaultEntry, Frontmatter), parse_md_file, scan_vault
- parsing.rs: text processing (snippet extraction, markdown stripping, date parsing)
- cache.rs: git-based incremental vault caching
- trash.rs: purge_trash with flat iterator chain
- rename.rs: note renaming with wikilink updates
- image.rs: attachment saving with filename sanitization

Also moves frontmatter update/delete wrappers to frontmatter.rs where they
belong, and converts public functions to accept &Path instead of &str.

CodeScene scores: mod.rs 10.0, parsing.rs 9.68, cache.rs 9.68,
trash.rs 9.38, rename.rs 9.68, image.rs 10.0 (all above 9.0 target).
All 169 Rust tests pass, 86.28% line coverage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:37:31 +01:00
lucaronin
36dc6d4416 refactor: flatten extract_snippet and purge_trash complexity
Extract helper functions to reduce cyclomatic complexity and nesting:

extract_snippet (cc=10 → ~3):
- strip_frontmatter(): removes YAML frontmatter
- is_snippet_line(): filters useful content lines
- truncate_with_ellipsis(): UTF-8-safe string truncation

purge_trash (cc=14, nesting=5 → cc~4, nesting=2):
- extract_trashed_at_string(): extracts date from gray_matter Pod
- parse_trashed_date(): parses ISO date string to NaiveDate
- is_markdown_file(): checks file extension
- try_purge_file(): handles deletion + logging

Code health: 7.29 → 8.54. Remaining issues: Low Cohesion, String Heavy Args.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:37:31 +01:00
lucaronin
c180b6851a test: add tests for local vault picker options
- StatusBar: 6 new tests for open local folder, create new vault options
- vault-dialog: 3 tests for pickFolder browser fallback behavior
- Rust lib: 3 tests for create_vault_dir (new dir, nested, existing)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 21:01:42 +01:00
lucaronin
74db63f1c8 feat: add local vault options to vault picker
Add "Open local folder" and "Create new vault" options to the vault
picker dropdown. Uses tauri-plugin-dialog for native folder picker
in Tauri mode, falls back to prompt() in browser mode.

- Rust: add tauri-plugin-dialog, create_vault_dir command
- Frontend: pickFolder utility, StatusBar UI, App.tsx handlers
- Mock: create_vault_dir mock handler for browser testing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 21:01:42 +01:00
lucaronin
800a0df61b fix: cargo fmt vault.rs formatting 2026-02-23 20:48:22 +01:00
lucaronin
ca8637b155 fix: cargo fmt vault.rs formatting 2026-02-23 20:34:22 +01:00
lucaronin
21a624b633 test: add migration and type-field parsing tests
Rust (9 new tests):
- test_parse_type_field: 'type:' in YAML maps to is_a field
- test_parse_type_field_takes_precedence_over_is_a: 'type' wins over 'Is A'
- test_parse_legacy_is_a_still_works: backward compat for 'Is A:'
- test_parse_snake_case_is_a_still_works: backward compat for 'is_a:'
- test_migrate_file_is_a_to_type: single-file migration
- test_migrate_file_quoted_is_a_to_type: handles "Is A" variant
- test_migrate_file_preserves_existing_type: type: takes precedence
- test_migrate_file_no_change_needed: skip already-migrated files
- test_migrate_vault: vault-wide migration counts correctly

Frontend (2 new tests):
- frontmatterToEntryPatch maps 'type' key to isA field
- DynamicPropertiesPanel skips is_a/Is A/type from property list

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:34:22 +01:00
lucaronin
c8e87f0ab9 feat: replace 'Is a' / 'is_a' with 'type' as the canonical frontmatter key
- Rust Frontmatter struct now parses both 'type' (new) and 'Is A'/'is_a' (legacy),
  with 'type' taking precedence via resolve_type()
- Added migrate_is_a_to_type() vault-wide migration (runs on startup, also exposed as Tauri command)
- Frontend: buildNoteContent and resolveNewType now emit 'type:' in YAML
- Inspector SKIP_KEYS hides 'is_a', 'Is A', 'type', 'title' from property list
  (TypeRow already renders the type with its dedicated UI)
- frontmatterToEntryPatch handles both 'type' and legacy 'is_a' keys
- Mock data updated: all YAML content uses 'type:' instead of 'is_a:'/'Is A:'
- Tests updated to expect 'type:' in generated frontmatter

Product decision: internal VaultEntry field stays as `isA` (TS) / `is_a` (Rust)
to minimize blast radius. The user-facing change is the YAML key and inspector.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:34:22 +01:00
lucaronin
0e7865c667 fix: implement auto-save for editor content
The editor was not persisting changes to disk. Edits would be lost
when closing and reopening a note.

Changes:
- Add save_note_content Tauri command (Rust) with read-only file check
- Add save_note_content mock handler for browser testing
- Add useAutoSave hook with 500ms debounce and flush-on-tab-switch
- Wire up BlockNote onChange → markdown serialization → auto-save
- Add restoreWikilinksInBlocks utility (reverse of injectWikilinks)
  to convert wikilink nodes back to [[target]] before markdown export
- Extract shared walkBlocks helper to eliminate code duplication
- Suppress onChange during programmatic content swaps (tab switching)
- 12 new frontend tests + 5 new Rust tests (all 469 + 174 passing)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 14:48:21 +01:00
lucaronin
1cccfd70cd ci: fix signing — hardcode empty password, update pubkey 2026-02-23 13:36:09 +01:00
lucaronin
b87ebe59a6 ci: regenerate Tauri signing keypair (no password) 2026-02-23 13:18:43 +01:00
lucaronin
731a2e5188 fix: set proper bundle identifier for release builds 2026-02-23 12:03:43 +01:00
Luca Rossi
5ebcf41d47 feat: auto-build, GitHub Release, and in-app updater (#14)
* ci: auto-release workflow on merge to main

Rewrite .github/workflows/release.yml to trigger on every push to main
instead of manual tag pushes. The workflow now:

- Computes version as 0.YYYYMMDD.GITHUB_RUN_NUMBER
- Builds aarch64-apple-darwin and x86_64-apple-darwin in parallel
- Merges them into a universal binary using lipo
- Creates a universal .dmg and signed updater tarball
- Generates latest.json with per-arch and universal platform entries
- Publishes a GitHub Release with auto-generated release notes
- Updates a GitHub Pages release history site (gh-pages branch)

Product decisions:
- Universal binary approach: copy arm64 .app as base, lipo the main
  executable, keep everything else from arm64 (shared frameworks are
  architecture-independent). This is the standard Tauri pattern.
- Per-arch updater tarballs are also uploaded so the Tauri updater can
  download the correct arch-specific build (smaller download).
- Release notes are auto-generated from git log since last tag.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* ci: github pages with release history

Use peaceiris/actions-gh-pages@v4 to deploy a release history site.
The page fetches releases.json (also deployed) and renders each release
with date, notes, and download links for .dmg files.

This handles the gh-pages branch creation automatically on first run.
The page is available at https://refactoringhq.github.io/laputa-app/

Product decision: used fetch() to load releases.json at runtime instead
of inlining it, which is cleaner and avoids shell escaping issues with
release note content. The releases.json is deployed alongside index.html.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: in-app update notification UI

Replace the old window.confirm updater with a proper React-based
update notification system:

- useUpdater hook now exposes state machine (idle → available →
  downloading → ready) and actions (startDownload, openReleaseNotes,
  dismiss)
- UpdateBanner component renders at the top of the app shell:
  - "Available" state: shows version, Release Notes link, Update Now
    button, dismiss X
  - "Downloading" state: animated spinner, progress bar with percentage
  - "Ready" state: Restart Now button to apply the update
- Silently checks on startup after 3s delay; fails silently on
  network errors or 404
- Release Notes link opens the GitHub Pages release history site

Product decisions:
- Banner at top of app (not a modal) — non-intrusive, visible but
  not blocking. User can dismiss and continue working.
- Progress bar shows during download so user knows it's working.
- Separate "Restart Now" state after download so user controls when
  the app restarts (they may have unsaved work).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: updater component tests

Rewrite useUpdater hook tests and add UpdateBanner component tests:

Hook tests (10 cases):
- Starts in idle state
- Does nothing when not in Tauri
- Checks for updates after 3s delay
- Stays idle when no update available
- Transitions to available when update found
- Handles missing release body gracefully
- Stays idle on network error (fails silently)
- Dismiss returns to idle
- openReleaseNotes opens correct URL
- startDownload transitions through downloading to ready

Component tests (10 cases):
- Renders nothing when idle
- Renders nothing on error
- Shows version and buttons when available
- Update Now calls startDownload
- Release Notes calls openReleaseNotes
- Dismiss button works
- Shows progress bar during download
- Shows 0% at start of download
- Shows restart button when ready
- Restart button calls restartApp

All 457 tests pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* design: auto-build-release wireframes

Copy ui-design.pen as base. Frames to be added for:

1. Update notification banner (visible state) — horizontal bar at
   top of app shell with version text, Release Notes link, Update
   Now button, and dismiss X
2. Update download progress state — spinner icon, progress bar with
   percentage, downloading text
3. "Restart to apply" state — green accent, version text, Restart
   Now button

Note: Pencil editor was not available during this session. The base
design file is committed; frames will be added when the editor is
accessible. The implemented component (UpdateBanner.tsx) serves as
the source of truth for the design.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: update ARCHITECTURE.md with release/update system

Add comprehensive documentation for:
- Release pipeline (4-phase workflow: version → build → release → pages)
- Versioning scheme (0.YYYYMMDD.RUN_NUMBER)
- Universal binary strategy (lipo merge)
- Updater endpoint and latest.json manifest
- In-app update UI state machine
- GitHub Pages release history site

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: rustfmt formatting

* fix: rustfmt build.rs

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 10:50:36 +00:00
lucaronin
20ce35bb44 fix: use Cmd+1/2/3 shortcuts and register real Tauri menu accelerators
- Changed view mode shortcuts from Alt+1/2/3 to Cmd+1/2/3 (Alt+N produces
  special chars on macOS, e.g. Alt+1 → '¡')
- menu.rs: use MenuItemBuilder with .accelerator() instead of appending
  shortcut text to label (was purely decorative, not registered with OS)
- Shortcuts now: CmdOrCtrl+1 editor-only, +2 editor+list, +3 all panels
2026-02-23 08:36:07 +01:00
lucaronin
17613b5c4e feat: add macOS View menu with panel visibility items
- Create menu.rs module with View submenu
- Items: Editor Only (⌥1), Editor + Notes (⌥2), All Panels (⌥3)
- Emits 'menu-event' to frontend, handled by useViewMode hook
- Menu only created on desktop builds (#[cfg(desktop)])

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 08:36:07 +01:00
lucaronin
d2902ec6b4 test: improve Rust test coverage for settings and github modules
Refactor settings.rs to expose testable internal functions (get_settings_at,
save_settings_at) and add integration tests for file I/O roundtrips, whitespace
trimming, directory creation, and malformed JSON handling. Coverage for
settings.rs improved from 46% to 91%. Overall Rust coverage now 86.2% (above
85% threshold). Also add coverage/ to .gitignore.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 08:34:14 +01:00
lucaronin
6e4119c28b feat: add Rust backend for GitHub vault operations
New github.rs module with three commands:
- github_list_repos: lists user's repos via GitHub API (paginated)
- github_create_repo: creates a new repo with auto_init
- clone_repo: git clone with HTTPS+token auth, configures remote

Also extends Settings with github_token field (Rust + TypeScript),
and adds GithubRepo type to shared types.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 08:34:14 +01:00
lucaronin
6dc31237c2 feat: add settings.rs Rust backend for local config storage
New settings module with get_settings/save_settings Tauri commands.
Settings stored as JSON in app config dir. Handles missing config file
(returns defaults), trims whitespace from keys, filters empty strings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 13:33:32 +01:00
lucaronin
c55ffad4b7 feat: frontend test coverage 47% → 86% — 362 tests across 17 new test files 2026-02-22 13:02:56 +01:00
lucaronin
65f4963d93 fix: resolve clippy warnings in vault.rs (strip_prefix + char boundary) 2026-02-22 12:36:44 +01:00
lucaronin
679e1e2372 feat: OTA updater plugin + GitHub Releases release pipeline 2026-02-22 12:31:42 +01:00
lucaronin
190b7d0075 feat: add OTA updater plugin with startup update check
- Install @tauri-apps/plugin-updater + plugin-process (npm + cargo)
- Configure tauri.conf.json: updater endpoint pointing to GitHub Releases,
  signing pubkey, createUpdaterArtifacts enabled
- Register updater + process plugins in Rust (desktop-only, #[cfg(desktop)])
- Add updater:default + process:default capabilities
- Add useUpdater hook: checks for updates 3s after startup, shows native
  confirm dialog, downloads+installs+relaunches on accept
- Silently catches errors so update failures never block the app
- Add comprehensive tests for the useUpdater hook (5 test cases)

Product decision: Using window.confirm() for the update dialog rather than
a custom React modal. This keeps the implementation simple and the native
dialog is appropriate for a system-level action like app restart. Can be
upgraded to a custom UI later if desired.

Private key generated at ~/.tauri/laputa.key — NOT committed.
For CI: set TAURI_SIGNING_PRIVATE_KEY + TAURI_SIGNING_PRIVATE_KEY_PASSWORD
as GitHub Secrets.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 12:10:24 +01:00
lucaronin
f64d941b0e feat: rename note by double-clicking its tab — inline edit, updates filename + wiki-links
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 12:10:17 +01:00
lucaronin
d23ce5a0b5 feat: clickable commit hashes in git history panel open diff view
- Add get_file_diff_at_commit Rust command to show diff at a specific commit
- Make shortHash in GitHistoryPanel a clickable button that opens DiffView
- Show author name below commit message (small, muted)
- Remove disabled "View all revisions" button
- Wire onLoadDiffAtCommit through Editor → Inspector → App.tsx
- Add mock handler for get_file_diff_at_commit in browser mode
- Fix pre-existing missing `order` field on trashed mock entries
- Update Inspector tests for new behavior

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 22:27:18 +01:00
lucaronin
5a8eb6a5d0 feat: rename note via double-click on tab — frontend wiring
- TabBar: inline edit on double-click (Enter saves, Escape cancels)
- Extracted TabItem component + tabStyle helper for code health
- useNoteActions: handleRenameNote invokes backend, updates tabs & vault
- useVaultLoader: replaceEntry handles path-changing renames
- mock-tauri: rename_note mock with wiki link updates
- App/Editor: wire onRenameTab prop through to TabBar

Code health: TabBar improved (CC 23→18). useNoteActions/App/useVaultLoader
show minor degradation on pre-existing high-CC functions — proper fix
requires splitting the monolithic useNoteActions hook (separate concern).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 19:22:44 +01:00
lucaronin
68dfab473a feat: add rename_note Tauri command with wiki link updates
Backend implementation for renaming a note:
- Updates H1 heading and title frontmatter to new name
- Renames file using slugified new title
- Scans all vault .md files and replaces [[OldTitle]] → [[NewTitle]]
  in both content and frontmatter (preserves pipe aliases)
- Returns new path and count of updated files

Well-factored with extracted helpers: build_wikilink_pattern,
replace_wikilinks_in_content, collect_md_files, update_h1_title,
update_note_title_in_content, frontmatter_has_title_key, to_path_stem.

All 147 tests pass including 7 new rename tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 19:13:03 +01:00
lucaronin
37c9164278 feat: set macOS window frame color to match sidebar background
Set the window backgroundColor to #F7F6F3 (same as --sidebar CSS variable)
in the Tauri window config. With titleBarStyle "Transparent", this makes
the native macOS title bar area match the sidebar background color instead
of defaulting to white.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 19:11:37 +01:00
lucaronin
cc1631c368 feat: draggable section groups in sidebar 2026-02-21 18:36:28 +01:00
lucaronin
09609eff55 feat: trash notes — sidebar filter, breadcrumb buttons, cmd+del shortcut, demo vault data 2026-02-21 18:34:40 +01:00
lucaronin
1dfbbb8a9e feat: add order property to VaultEntry and install @dnd-kit
- Add `order: number | null` to VaultEntry (TS) and VaultEntry (Rust)
- Add order to Frontmatter struct and SKIP_KEYS in vault.rs
- Update all mock Type documents with order values (0-10)
- Add order: null to all non-Type mock entries and test fixtures
- Install @dnd-kit/core, @dnd-kit/sortable, @dnd-kit/utilities

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 17:27:19 +01:00
lucaronin
004201cdc8 fix: tauri devUrl to match vite port 5201 2026-02-21 17:23:26 +01:00
lucaronin
af40fba1b0 feat: add purge_trash command to delete stale trashed files
Adds purge_trash(vault_path) that scans all .md files, reads the
"Trashed at" frontmatter date, and deletes files older than 30 days.
Registered as a Tauri command and called automatically on app startup
(defaults to ~/Laputa vault). Includes 7 tests covering boundary
conditions, nested dirs, and datetime formats.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 17:14:02 +01:00