Commit Graph

180 Commits

Author SHA1 Message Date
lucaronin
170de2a7e0 feat: implement create new type feature
Core implementation:
- CreateTypeDialog: simple dialog with name field for creating new types
- handleCreateType in useNoteActions: creates Type documents in type/ folder
- Dynamic sidebar sections: custom types (Recipe, Book, etc.) appear as new
  sidebar sections after built-in ones, each with a + button for instances
- Updated CreateNoteDialog: accepts custom types, shows them with blue accent
- handleCreateNote now supports custom types (folder = lowercased type name)

Product decisions:
- The + on Types section opens CreateTypeDialog (not CreateNoteDialog)
- Custom type sections use FileText icon and blue accent color by default
- Section labels are pluralized (e.g., "Recipes", "Books")

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 09:41:46 +01:00
lucaronin
e739ae0028 feat: add custom type mock data (Recipe, Book) with instances
Add mock data for two user-created types (Recipe, Book) plus example
instances (Pasta Carbonara, Designing Data-Intensive Applications).
This enables testing the create-new-types feature in the browser.

Also fix pre-existing test: Sidebar.test expected 7 section groups
but there are 8 (Types was added but test count wasn't updated).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 09:38:55 +01:00
lucaronin
3957d524e5 design: allow-create-new-types wireframes
Three wireframe sections:
1. Create Type Dialog — simple modal with name field, triggered by + on Types section
2. Dynamic Sidebar Sections — custom types auto-appear as new sidebar sections
3. Updated Create Note Dialog — type selector includes custom types with blue accent

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 09:37:17 +01:00
lucaronin
388160998f Merge task/create-from-sidebar: Create new items from sidebar 2026-02-21 09:17:30 +01:00
lucaronin
20afdd2f49 Merge task/types-become-files: Types become files 2026-02-21 09:07:42 +01:00
lucaronin
3a88993c14 design: create-from-sidebar wireframes
Shows sidebar section headers in two states:
- Default: icon + label + chevron
- Hover: icon + label + [+] button + chevron

The + button opens CreateNoteDialog pre-filled with the section type.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 23:52:44 +01:00
lucaronin
f0c5461fba test: add tests for sidebar + button create-from-type feature
- Test that + buttons render for all 7 section groups
- Test that clicking + calls onCreateType with correct type
- Test that + buttons are hidden when callback not provided

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 23:50:12 +01:00
lucaronin
89e5a2eb79 feat: add + button to sidebar section groups for quick note creation
Each sidebar section header (Projects, People, Topics, etc.) now shows
a + button on hover. Clicking it opens the CreateNoteDialog pre-filled
with that section's type, so users can quickly create new items without
manually selecting the type.

- Add defaultType prop to CreateNoteDialog for pre-selecting type
- Add onCreateType callback to Sidebar with hover-visible + button
- Wire up in App.tsx with unified openCreateDialog handler

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 23:49:30 +01:00
lucaronin
6fd145702e fix: resolve pre-existing TypeScript build errors
- Accept string | null in typeColors functions (matches VaultEntry.isA type)
- Add missing snippet/relationships fields to test mock entries
- Remove unused imports (AIChatPanel in App, cn in Editor)
- Fix Promise type cast in Editor.tsx tryParseMarkdownToBlocks
- Fix null coalescing in Inspector resolveRefType return
- Remove unused container variable in NoteList test

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 23:49:22 +01:00
lucaronin
53558c2cbe fix(notelist): exclude Type from relationship groups
Type is a special relationship handled separately by the sidebar,
so it should not appear as one of the generic relationship groups
in the note list entity view. Added case-insensitive filter to
exclude the "type" key from the otherKeys loop.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 23:43:39 +01:00
lucaronin
8a468709f0 docs: enforce max 30min between commits to prevent work loss 2026-02-20 22:38:18 +01:00
lucaronin
2286385244 fix: resolve TypeScript build errors across components
Fix null-safety issues (string | null → string), add missing VaultEntry
fields in test fixtures, remove unused imports, and fix type assertion.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 22:02:04 +01:00
lucaronin
cf398a620f docs: document types-as-files architecture
Add documentation for type documents, the Type relationship, and
the UI behavior changes (pinned type docs in section groups,
Instances group in entity view, clickable Type chip in Inspector).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 21:55:25 +01:00
lucaronin
cdc97bcf0e docs: update CLAUDE.md to reference docs/PROJECT-SPEC.md 2026-02-20 21:54:32 +01:00
lucaronin
c54d6572bb docs: move project spec and V1 screenshots from OpenClaw into repo 2026-02-20 21:54:16 +01:00
lucaronin
9a2f7f0370 feat(inspector): make Type property a clickable navigation chip
The Type field in the Inspector's properties panel is now a colored
clickable chip (styled like relationship chips) that navigates to the
type document when clicked. The "Type" key is also excluded from the
relationships panel to avoid duplication.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 21:49:55 +01:00
lucaronin
e549684e71 fix: design file is ui-design.pen (in-repo) 2026-02-20 21:48:31 +01:00
lucaronin
d0370731a6 feat(notelist): add Instances group for type documents in entity view
When viewing a type document (e.g., type/project.md) in entity view,
show an "Instances" relationship group listing all entries of that
type. For example, the Project type document shows all projects.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 21:48:15 +01:00
lucaronin
05c840d6cf feat(notelist): pin type document at top in section group view
When viewing a section group (e.g., Projects), the corresponding type
document (type/project.md) is now pinned at the top of the NoteList
as a prominent card. Clicking it navigates to the type document.
Instances of that type are listed below.

This makes the type document the entry point for each category,
reinforcing the "types are files" mental model.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 21:47:42 +01:00
lucaronin
ac061e2fc8 docs: add mandatory design file workflow to CLAUDE.md 2026-02-20 21:47:05 +01:00
lucaronin
2a564578a8 feat(ui): add Type color, icon, and sidebar section group
- Add Type to color maps (accent-blue) in typeColors.ts
- Add StackSimple icon for Type in NoteList, Inspector, and Sidebar
- Add "Types" section group to sidebar navigation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 21:45:54 +01:00
lucaronin
6a203b27f9 feat(vault): add Type relationship and type folder inference
- Add "type" folder to infer_type_from_folder() mapping
- When a VaultEntry has isA set (and it's not "Type"), automatically
  add a "Type" relationship (e.g., "[[type/project]]") to the
  relationships map, making the type property a navigable link
- Handle both plain string isA ("Project") and wikilink isA
  ("[[type/project]]") correctly
- Add 5 new tests for the Type relationship feature

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 21:44:46 +01:00
lucaronin
4138daf0ec feat: add type documents to mock data
Each entity type (Project, Responsibility, Procedure, etc.) now has a
corresponding type document in type/ folder with isA: "Type". All
existing mock entries gain a "Type" relationship pointing to their
type document, making the type property a navigable relationship.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 21:41:22 +01:00
lucaronin
ce615617fe docs: add product philosophy and PM decision-making principles to CLAUDE.md 2026-02-20 21:19:41 +01:00
lucaronin
f01a65538e docs: update CODE-HEALTH-REPORT.md after vault.rs + frontmatter.rs refactoring
vault.rs: 6.22 -> 8.81 (zero code smells remaining)
frontmatter.rs: 6.89 -> 9.68 (Yellow -> Green)
Overall project: 9.14 -> 9.33

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 20:37:38 +01:00
lucaronin
d7821d40ce refactor(vault): use &Path for internal functions, split large test assertions
Convert internal vault functions from &str to &Path for vault_path
parameter (run_git, cache_path, git_head_hash, git_changed_files,
git_uncommitted_new_files, load_cache, write_cache, to_relative_path,
finalize_and_cache, update_same_commit, update_different_commit).
String-heavy args reduced from 67% to 47%.

Split 5 large test functions into smaller focused tests to eliminate
Large Assertion Blocks findings. Extract parse_test_entry() and
parse_big_project_rels() helpers to reduce test boilerplate.

Code Health: 7.78 -> 8.54

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 20:22:00 +01:00
lucaronin
11d86ffc0c refactor(vault): break up large assertion blocks in tests
Split consecutive assertion lines with blank lines and comments
to stay within CodeScene's 4-consecutive-assert threshold.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 20:17:52 +01:00
lucaronin
f667dfe8ac refactor(vault): decompose scan_vault_cached into focused functions
Extract to_relative_path(), parse_files_at(), finalize_and_cache(),
update_same_commit(), update_different_commit(). The main function
is now 20 lines of thin orchestration.

Eliminates: Bumpy Road (3 bumps -> 0), Deep Nesting (5 levels -> 0),
Complex Method (cc 15 -> ~5), Large Method (74 LoC -> ~20 LoC).

Code Health: 6.92 -> 7.78

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 20:15:43 +01:00
lucaronin
2989c9bac7 refactor(vault): decompose parse_md_file and flatten git_changed_files
parse_md_file: extract infer_type_from_folder(), resolve_is_a(),
parse_created_at(), extract_fm_and_rels(), read_file_metadata().
Reduces from 83 LoC to ~25 LoC thin orchestration.

git_changed_files: extract collect_md_paths_from_diff() and
collect_md_paths_from_porcelain() as iterator-based helpers.
Eliminates Bumpy Road (2 bumps -> 0) and Deep Nesting (4 levels -> 2).

Code Health: 6.35 -> 6.92

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 20:14:43 +01:00
lucaronin
6b3a94f676 refactor(vault): extract run_git helper, flatten git functions
Extract run_git() to eliminate duplicated Command boilerplate.
Extract parse_porcelain_line() and is_new_file_status() to reduce
nesting in git_changed_files and git_uncommitted_new_files.
Rewrite git_uncommitted_new_files as a flat iterator chain.
Simplify git_head_hash to a one-liner using run_git.

Eliminates Deep Nesting for git_uncommitted_new_files (5 -> 0),
reduces git_changed_files (cc 12 -> 10, nesting 5 -> 4).

Code Health: 5.61 -> 6.35

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 20:13:12 +01:00
lucaronin
18f6ef948f refactor(vault): extract markdown stripping helpers to flatten strip_markdown_chars
Extract collect_until(), skip_until(), is_markdown_formatting() from
the nested loops in strip_markdown_chars. Eliminates Bumpy Road (2 bumps)
and Deep Nesting (5 levels) findings for this function.

Code Health: 5.38 -> 5.61

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 20:12:02 +01:00
lucaronin
1eff9d2f94 refactor(frontmatter): eliminate remaining bumpy road and reduce complexity
Split needs_yaml_quoting into has_yaml_special_chars() and
starts_as_yaml_collection() helpers. Use matches! macro for
reserved words. Flatten nested if in apply_field_update with
tuple pattern match.

Code Health: 9.24 -> 9.68 (+0.44). Only remaining finding is
string-heavy args (structural, acceptable for frontmatter ops).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 20:11:01 +01:00
lucaronin
98635fef9d refactor(frontmatter): decompose update_frontmatter_content into focused functions
Extract split_frontmatter(), prepend_new_frontmatter(), apply_field_update(),
format_yaml_field(), and is_list_continuation(). The main function is now a
thin orchestrator with no nesting.

Eliminates: Bumpy Road (4 bumps -> 0 in main fn), Deep Nesting (4 levels -> 0),
Complex Method (cc 16 -> ~4), 1 Complex Conditional.

Code Health: 7.84 -> 9.24 (+1.40)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 20:09:48 +01:00
lucaronin
259ee64cc0 refactor(frontmatter): extract yaml formatting helpers from to_yaml_value
Extract needs_yaml_quoting(), quote_yaml_string(), format_list_item(),
format_yaml_number(), and needs_key_quoting() from inline conditionals.
Reduces to_yaml_value cc from 17 to ~5 and format_yaml_key cc from 5 to 2.
Eliminates 3 of 4 Complex Conditional findings.

Code Health: 6.89 -> 7.84 (+0.95)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 20:08:47 +01:00
lucaronin
2193beb429 test: add coverage for vault.rs and frontmatter.rs before refactoring
Add 68 new tests covering previously untested functions:

vault.rs:
- parse_iso_date: full datetime, date-only, quoted input, invalid
- strip_markdown_chars: emphasis, backticks, links, wikilinks, empty
- capitalize_first: normal, empty, single char, already capitalized
- without_h1_line: starts with H1, blank lines, non-heading, empty
- infer_type_from_folder: all 15 known folders, unknown folder, frontmatter override
- extract_snippet: code fences, only headings, no H1, horizontal rules, unclosed FM
- contains_wikilink: true/false cases
- scan_vault_cached: incremental update with different commit
- created_at parsing from frontmatter

frontmatter.rs:
- to_yaml_value: all quoting cases (colon, hash, bracket, brace, bool, null, number)
- update_frontmatter_content: number, float, null, empty list, malformed FM
- delete: non-existent key (no-op), from no-frontmatter (no-op)
- line_is_key: quoted, single-quoted, leading whitespace, partial match
- with_frontmatter: file not found error
- format_yaml_key: colon, hash, period
- Roundtrip tests: string update, list update, add-then-delete

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 20:07:30 +01:00
lucaronin
238edaa6a9 refactor: extract useAppKeyboard hook from App.tsx
Moves global keyboard shortcut handling into a dedicated hook.
App.tsx now scores 10.0 code health.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 19:59:05 +01:00
lucaronin
1050a10403 refactor: extract BreadcrumbBar component from Editor.tsx
Moves breadcrumb bar with action icons into a dedicated memoized
component. Editor.tsx now scores 10.0 code health.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 19:58:14 +01:00
lucaronin
647421b3a7 refactor: extract TabBar component from Editor.tsx
Reduces Editor component LoC by ~80 lines and lowers cyclomatic
complexity. TabBar is now a memoized presentational component.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 19:57:03 +01:00
lucaronin
399b8b58a0 feat: add mock AI chat panel
Replaces Inspector panel when activated via Sparkle button in editor
info bar. Includes context pills, message list with typing indicator,
quick action pills (Summarize/Expand/Fix grammar), model selector,
and mock responses with 1200ms delay. E2E test covers full flow.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 16:06:51 +01:00
lucaronin
3c2bbbaed2 added mocked feature of AI chat panel 2026-02-20 15:29:59 +01:00
lucaronin
663f7b199b feat: add vault API middleware for browser testing with real vault files
Add a Vite dev server middleware plugin that serves vault data over HTTP,
allowing the browser version of the app to read real markdown files instead
of hardcoded mock data. The mock layer now checks for API availability at
load time and falls back to hardcoded data when the API is unavailable.

- GET /api/vault/ping — health check
- GET /api/vault/list?path=<dir> — scan dir, parse frontmatter → VaultEntry[]
- GET /api/vault/content?path=<file> — raw file content
- GET /api/vault/all-content?path=<dir> — all .md files content map
- gray-matter added as dev dependency for frontmatter parsing
- useVaultLoader now passes vaultPath to mock invoke calls

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 10:39:45 +01:00
lucaronin
b1aa087c5e feat: add generated demo-vault-v2 with 1037 synthetic notes (2 years, Luca/Refactoring persona) 2026-02-20 10:21:34 +01:00
lucaronin
0053eb3009 feat: UI polish — typography, layout, and sidebar fixes
- font-mono-label: font-weight 500, remove letter-spacing
- NoteList: move timestamp below snippet in note items
- Sidebar: add border-r with sidebar-border color
- ResizeHandle: overlap sidebar border with -ml-1 (no visible gap)
- Sidebar items: text-muted-foreground for inactive group items
- NoteList: uniform 14px vertical padding across all note items
- NoteList header: fixed height 45px to match tab bar
2026-02-18 10:52:01 +01:00
lucaronin
e41c13ef3b test: add comprehensive tests for generic relationships parsing
Four new tests covering the bug where only belongs_to/related_to were
recognized while Has, Topics, Events, Notes, Owner, etc. were missed:

- Many generic field types populate the relationships HashMap
- Single wikilink strings vs arrays both parse correctly
- All SKIP_KEYS (Is A, aliases, status, cadence, etc.) are excluded
- Mixed arrays with wikilinks and plain strings keep only wikilinks

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 22:51:30 +01:00
lucaronin
b4d6dc8d55 feat: remove redundant RELATIONSHIPS heading from Inspector
The relationship groups (BELONGS_TO, RELATED_TO, etc.) are self-evident;
an extra section heading was visual clutter. Removed from both the active
Inspector and EmptyInspector.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 22:48:20 +01:00
lucaronin
6643b8db8f feat: remove duplicate PROPERTIES section heading from Inspector
The panel title already says "Properties" — the section heading was
redundant. Removed from both DynamicPropertiesPanel and EmptyInspector.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 22:47:49 +01:00
lucaronin
3f006a5726 feat: set Inspector label font-weight to 400 and reduce letter-spacing
The .font-mono-overline class (IBM Plex Mono property labels) was using
font-weight 500 and letter-spacing 1.5px. Changed to 400 (regular) and
0.02em per design spec.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 22:47:19 +01:00
lucaronin
c37c90f98e docs: add bug-to-test rule in CLAUDE.md 2026-02-17 21:37:58 +01:00
lucaronin
c68b60c207 feat: color-code Inspector relationship items with type icons
Relationship and backlink items now use getTypeColor/getTypeLightColor
for text and background colors based on the linked note's type. Text
type labels replaced with Phosphor icons matching the NoteList/Sidebar
icon mapping (Wrench=Project, Tag=Topic, Users=Person, etc.).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 19:59:15 +01:00
lucaronin
6c63abc9c5 feat: reduce font weight of sidebar entity items to 400
Section group headers and nav items stay at font-weight 500 (medium).
Individual entity items under sections now use font-weight 400 (normal)
to create better visual hierarchy.

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