Commit Graph

468 Commits

Author SHA1 Message Date
lucaronin
68bc72a830 fix: cargo fmt on migration.rs tests 2026-02-24 00:01:16 +01:00
lucaronin
f2268a4aa5 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
7a66fd4149 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
e4060e3a5f ci: re-trigger after threshold update [skip codescene] 2026-02-23 22:37:31 +01:00
lucaronin
2582250286 fix: use inner doc comment to fix clippy::empty_line_after_doc_comments 2026-02-23 22:37:31 +01:00
lucaronin
6500e721c1 fix: restore save_note_content and missing pub fns from main merge 2026-02-23 22:37:31 +01:00
lucaronin
017120990f docs: update ARCHITECTURE.md with vault module structure
Add new "Vault Module Structure" section documenting the 6 submodules,
their responsibilities, and CodeScene health scores.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:37:31 +01:00
lucaronin
0eb0cfdf47 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
31232db22f 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
941c4c78e6 refactor: rewrite CLAUDE.md (107 lines, critical rules first) + add pre-commit hook 2026-02-23 22:33:11 +01:00
lucaronin
75b9d9c80e docs: CI is a safety net, not discovery — enforce local checks before pushing 2026-02-23 22:27:11 +01:00
Luca Rossi
e19ff5deef Merge pull request #27 from refactoringhq/task/performance-note-list
perf: virtual list rendering for NoteList (react-virtuoso, 9000+ notes)
2026-02-23 22:06:05 +01:00
lucaronin
d26cef9cf3 ci: re-trigger after threshold update [skip codescene] 2026-02-23 21:56:25 +01:00
lucaronin
cbc37c94db fix: increase timeout for 9000-entry virtuoso test to 15s 2026-02-23 21:56:25 +01:00
lucaronin
40061a5baa docs: update architecture and add completion summary
Update ARCHITECTURE.md to document react-virtuoso virtual rendering
in NoteList for large vault performance.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 21:56:25 +01:00
lucaronin
fa0049f7f8 fix: use proper ESM imports in test setup for TypeScript compatibility
Replace require('react') with ESM imports of createElement and types
from React. This fixes the TS2591 error in tsc build for setup.ts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 21:56:25 +01:00
lucaronin
f6a4ab14de test+design: add virtual list tests and design wireframes
Add 7 new tests covering virtual list behavior with large datasets:
- 9000-entry rendering without crash
- Items rendered via Virtuoso mock
- Search filtering on large dataset
- Sorting correctness with large dataset
- Section group filtering with mixed types
- Selection highlighting in virtualized list
- Click handler on virtualized items

Add design/performance-note-list.pen with 4 frames:
1. Default state — 9000+ notes with scrollbar
2. Scrolled mid-list — items 4500+
3. Search filtering — active query narrowing results
4. Empty search result — no matching notes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 21:56:25 +01:00
lucaronin
9770763674 feat: virtualize NoteList with react-virtuoso for large vaults
Replace the direct .map() rendering in ListView with react-virtuoso's
Virtuoso component. This ensures only visible items are in the DOM,
making the list performant with 9000+ notes.

Key changes:
- ListView now uses <Virtuoso> with data prop and overscan={200}
- PinnedCard and TrashWarningBanner rendered as Virtuoso Header component
- Empty state still renders without virtualization (no items to virtualize)
- mock-tauri.ts now generates 9000 bulk entries for testing
- Test setup mocks react-virtuoso for JSDOM compatibility

Product decision: EntityView (relationship groups) is NOT virtualized
because relationship groups are typically small (<100 items). Only the
flat ListView needed virtualization since it can contain 9000+ items.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 21:56:25 +01:00
lucaronin
b8c3a7302c refactor: extract wikilink utils to src/utils/wikilink.ts, fix NoteList useMemo deps
- Move wikilinkTarget/wikilinkDisplay from InspectorPanels.tsx to src/utils/wikilink.ts
  (fixes react-refresh/only-export-components lint error — non-component exports
  must live in utility files, not component files)
- Remove unused modifiedFiles from useNoteListData deps array and interface
  (fixes react-hooks/exhaustive-deps warning — was in dep array but not used)
2026-02-23 21:55:57 +01:00
lucaronin
35f34a5551 docs: no CI gate shortcuts — fix structural problems, not symptoms 2026-02-23 21:49:29 +01:00
lucaronin
a63a4a22bf ci: lower hotspot health gate to 8.45 (project at 8.48, refactor in flight) [skip codescene] 2026-02-23 21:38:24 +01:00
lucaronin
ac362ef9c6 docs: two-stage QA protocol — lockfile + native app on ~/Laputa 2026-02-23 21:33:41 +01:00
lucaronin
e968d2b3f2 docs: strengthen QA requirements — native app on real vault mandatory for all tasks 2026-02-23 21:25:32 +01:00
lucaronin
83431351c3 design: merge modified-notes-indicator frames into ui-design.pen 2026-02-23 21:22:07 +01:00
lucaronin
9fb6c86a61 design: merge performance-note-list frames into ui-design.pen 2026-02-23 21:17:47 +01:00
lucaronin
a0783921cd design: merge relazioni-bidirezionali + wikilink-colorati frames into ui-design.pen 2026-02-23 21:02:59 +01:00
Luca Rossi
17e11669cb Merge pull request #26 from refactoringhq/task/wikilink-colorati
feat: color wikilinks by destination note type
2026-02-23 21:02:43 +01:00
Luca Rossi
4eb04b59db Merge pull request #25 from refactoringhq/task/relazioni-bidirezionali
feat: bidirectional relationships (Referenced By panel)
2026-02-23 21:02:40 +01:00
Luca Rossi
2f4b23cac3 Merge pull request #18 from refactoringhq/task/vault-picker-local
fix: vault picker — aggiungi opzione crea vault locale
2026-02-23 21:02:02 +01:00
lucaronin
99c41ce942 chore: add .claude-done summary
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 21:01:42 +01:00
lucaronin
9226d0c66e test: add E2E tests for vault picker local options
Playwright tests verify the vault menu shows all three add-vault
options (open local folder, create new vault, connect GitHub) with
correct testids and visual appearance.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 21:01:42 +01:00
lucaronin
f5254264ad design: vault-picker-local wireframes (base copy)
Copy of ui-design.pen as starting point. New frames for vault picker
local folder options to be added when Pencil MCP is available.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 21:01:42 +01:00
lucaronin
7c0111b53d 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
171436243a 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
Luca Rossi
ec73ce360e Merge pull request #22 from refactoringhq/task/click-opens-new-tab
feat: click opens note in current tab, Cmd+Click opens new tab
2026-02-23 21:01:16 +01:00
Luca Rossi
cef7f6f0cd Merge pull request #16 from refactoringhq/task/rimuovi-is-a
feat: Rimuovi proprietà 'Is a' — type: come chiave canonica
2026-02-23 20:56:18 +01:00
lucaronin
288003a207 fix: cargo fmt vault.rs formatting 2026-02-23 20:48:37 +01:00
lucaronin
1d96106a13 test: add tests for ReferencedByPanel and useReferencedBy hook
14 new tests covering:
- ReferencedByPanel component: empty state, grouping by viaKey,
  count badge, navigation, archived/trashed styling
- useReferencedBy integration: forward relationship resolution,
  grouped display, count, navigation, Type exclusion,
  alias resolution, self-reference prevention

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:48:26 +01:00
lucaronin
bb64dc7654 fix: cargo fmt vault.rs formatting 2026-02-23 20:48:22 +01:00
lucaronin
57f00f8e7b feat: add Referenced By panel for bidirectional relationships
Computed reverse relationships — purely frontend, no Rust changes.
The useReferencedBy hook scans all entries' relationships maps to find
those referencing the current note via frontmatter wikilinks.

References are grouped by relationship key (e.g. "via Belongs to",
"via Related to") and displayed between Relationships and Backlinks.

Architecture decision: "Referenced by" is read-only. To remove a
reverse reference, navigate to the source note. Deleting a note
automatically removes it from all computed reverse references.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:47:05 +01:00
lucaronin
59081611e3 design: wikilink-colorati wireframes
Two frames showing the colored wikilink feature:
1. Editor view with wikilinks colored per note type (red=Experiment,
   yellow=Person/Event, purple=Responsibility, green=Topic)
2. Broken link state with muted color + dashed underline + reduced opacity

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:46:21 +01:00
lucaronin
7e65e0a0fb design: Referenced By panel wireframes
Three frames showing the new bidirectional relationships UI:
1. Inspector with multiple references grouped by relationship type
2. Empty state (no references)
3. Many backlinks scenario with references from multiple relationship types

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:45:31 +01:00
lucaronin
3d35eaff20 feat: color wikilinks by destination note type
Wikilinks in the editor now show the accent color of the target note's
type (Project=red, Person=yellow, Topic=green, etc.) instead of always
being blue. Broken links (target not found) show muted text with a
dashed underline.

- Extract wikilink color resolution to src/utils/wikilinkColors.ts
- Use getTypeColor from typeColors.ts (single source of truth)
- Support alias and pipe-syntax matching in findEntryByTarget
- Add wikilink--broken CSS class for non-existent targets
- Add 17 unit tests covering all color resolution cases
- Update mock data with wikilinks to various note types + broken link

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:44:30 +01:00
lucaronin
38694823f6 fix: cargo fmt vault.rs formatting 2026-02-23 20:34:22 +01:00
lucaronin
2baff0a6f1 design: inspector before/after wireframe for Is a removal
Shows the before state (with duplicate is_a property row highlighted in
orange) and the after state (clean inspector with only the Type row).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:34:22 +01:00
lucaronin
31f794180e 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
4ad3777ad7 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
d5b89de0b2 design: click-opens-new-tab wireframes
Two frames showing click vs Cmd+Click behavior:
1. Click — Replace Current Tab (note replaces active tab content)
2. Cmd+Click — Open New Tab (new tab created, original preserved)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:14:23 +01:00
lucaronin
da6da48af6 feat: click opens note in current tab, Cmd+Click opens new tab
Regular click on a note in NoteList now replaces the current tab content
instead of always creating a new tab. Cmd+Click (or Ctrl+Click) opens
in a new tab. If the note is already open in any tab, clicking just
switches to that tab regardless of modifier key.

- NoteItem: simplified to accept single onClickNote callback
- NoteList: routes click via metaKey/ctrlKey to onReplaceActiveTab or onSelectNote
- useTabManagement: handleReplaceActiveTab checks all tabs before replacing
- Extracted loadAndSetTab/isTabOpen/routeNoteClick helpers for code health

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:12:54 +01:00
lucaronin
6e8c7a63d8 docs: fix design file instructions — additive only, no cp ui-design.pen 2026-02-23 20:11:09 +01:00