Commit Graph

193 Commits

Author SHA1 Message Date
lucaronin
df64d45152 design: keyboard navigation wireframes
Two frames showing tab switching shortcuts (Cmd+Opt+Left/Right in Tauri,
Cmd+Shift+Left/Right in browser) and note list navigation (Cmd+Opt+Up/Down
replaces current tab).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 10:44:17 +01:00
lucaronin
5f2a6495db feat: AI chat panel 2026-02-21 10:38:41 +01:00
lucaronin
4b843f94f6 feat: Allow to create new types 2026-02-21 10:32:36 +01:00
lucaronin
001b52c00f feat: update app icon 2026-02-21 10:21:30 +01:00
lucaronin
d94236c482 fix: editor min width — width 100% on .bn-container and .bn-editor 2026-02-21 09:52:05 +01:00
lucaronin
333df92bc9 test: add E2E tests for create new type feature
6 Playwright tests covering the full flow:
- Create Type dialog opens from + button on Types section
- Create button disabled when name is empty
- Creating a type adds it to sidebar and opens it in editor
- Custom types appear in Create Note dialog type selector
- Can create instances of custom types
- Cancel closes dialog without side effects

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 09:46:02 +01:00
lucaronin
5ec9af98c5 test: add tests for create type dialog and dynamic sidebar sections
- CreateTypeDialog: 8 tests covering open/close, validation, submit, cancel
- Sidebar dynamic sections: 5 tests covering custom type rendering,
  instance display, + button behavior, and built-in type deduplication

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 09:42:45 +01:00
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
4e4cffe6a3 fix: ensure editor has full width regardless of title/content length
The BlockNote editor container (.bn-container) had no explicit width,
so it sized based on content. With short or empty document titles,
the editor collapsed to a very small width.

Fix: set width: 100% on .bn-container and .bn-editor so the editor
always fills available space. Added margin: 0 auto on .bn-editor to
keep the 760px text column centered.

Also adds an E2E test verifying editor width stays above 300px.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 09:39:37 +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
bca6b3c8e8 docs: AI chat architecture + fix pre-existing build errors
Update docs/ARCHITECTURE.md with:
- AI Chat system architecture (context picker, streaming, MCP)
- WebSocket bridge protocol
- New files listing and data flow diagrams
- Updated tech stack table

Update mock-tauri.ts with richer AI chat mock responses
(context-aware summarize, expand, grammar responses).

Fix pre-existing TypeScript build errors:
- Add missing snippet/relationships to test VaultEntry fixtures
- Fix string|null → string type mismatches in Sidebar, NoteList, Inspector
- Remove unused imports (cn in Editor, AIChatPanel in App)
- Fix tryParseMarkdownToBlocks Promise cast

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 23:07:10 +01:00
lucaronin
7d235d723f feat(ai-chat): WebSocket bridge for MCP vault ops
Add WebSocket bridge connecting MCP server tools to the frontend:
- mcp-server/ws-bridge.js: WebSocket server exposing vault tools
  (read_note, create_note, search_notes, append_to_note)
- src/hooks/useMcpBridge.ts: React hook for typed tool invocations
  with lazy connection, request/response correlation, timeouts
- Vite MCP bridge info endpoint (/api/mcp/info)

Protocol: client sends {id, tool, args}, server responds {id, result}
Default port: 9710 (configurable via WS_PORT env var)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 22:59:00 +01:00
lucaronin
b61d29edd1 feat(mcp-server): vault operation tools
Add Node.js MCP server with 5 vault tools:
- open_note / read_note: read markdown file content
- create_note: create new note with frontmatter and title
- search_notes: search by title or content substring
- append_to_note: append text to existing note

Uses @modelcontextprotocol/sdk with stdio transport.
VAULT_PATH env var configures the vault directory.
10 passing tests covering all operations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 22:57:39 +01:00
lucaronin
261d2f986c feat(ai-chat): Rust ai_chat command
Add Tauri command for AI chat via reqwest:
- ai_chat module with send_chat() using Anthropic Messages API
- ANTHROPIC_API_KEY from environment variable
- Proper error handling for missing key, API errors, parse failures
- Unit tests for request building and response extraction
- Mock handler added to mock-tauri.ts for browser testing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 22:55:49 +01:00
lucaronin
f4ca64f229 feat(ai-chat): context picker + Anthropic API
Rewrite AIChatPanel with:
- Context picker: current note auto-added, search to add more notes,
  removable context pills, token estimation badge
- Real Anthropic API integration via Vite dev server proxy (SSE streaming)
- API key stored in localStorage, configurable via dialog
- Model selector: Haiku 3.5, Sonnet 4, Opus 4
- Mock fallback when no API key is configured
- Extracted useAIChat hook and ai-chat utilities for clean separation

Decision: Using Vite middleware proxy for dev mode to avoid CORS issues
with direct browser-to-Anthropic calls. Phase 2 will add Rust backend.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 22:52:56 +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