Three frames: empty state with grouped actions, search results
with fuzzy filtering, and no-results state.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New notes created in-session show a green dot; existing notes with
uncommitted git changes show an orange dot. Saving a new note clears
the green dot; git commit clears the orange dot.
Introduces NoteStatus type ('new' | 'modified' | 'clean'), extracts
useNewNoteTracker hook and resolveNoteStatus pure function, and adds
onNoteSaved callback to useEditorSave for clearing new-note tracking.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Frame 1: Full grid view with 8 color swatches and scrollable icon grid
- Frame 2: Search filtered state (searching "book")
- Frame 3: Empty state (no matching icons)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Property values (dates, URLs, text) were inheriting the 14px root font
size instead of using the 12px size already applied in InfoRow and other
inspector sections. Standardize all property value and editing input
text to 12px for visual consistency.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Default, hover (underline + pointer), and edit mode states
for URL properties in the Inspector panel.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Type field in the Properties panel was read-only. Now it uses a
Radix Select dropdown that lists all vault types (entries where
isA === "Type"), plus a "None" option to clear the type. Wired to
the existing onUpdateProperty('type', ...) flow.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.
E2E tests cover:
- Drag & drop image into editor inserts image block with data URL
- Drop zone overlay appears during image drag
- Non-image file drops are correctly ignored
Design file shows three states: idle, drag-over (dashed border +
overlay label), and after-drop (image block inserted inline).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shows all five type colors (red, yellow, green, purple, blue) with
matching dotted underlines — demonstrating the currentColor fix.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Frames showing the fixed Commit & Push behavior:
- Button enabled state with correct badge count (3 files)
- Button with no changes (badge hidden)
- Commit dialog with correct file count after save+refresh
- Success toast after commit
- Error toast when commit fails
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copied from ui-design.pen — includes existing Settings Panel frame.
New OAuth states (login button, waiting, connected) are reflected in
the implementation. Pencil editor not available for adding new frames.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3 frames showing the dirty indicator UI states:
- NoteList: orange dot before title for modified/added notes
- TabBar: orange dot between title and close button
- StatusBar: "N pending" counter with CircleDot icon
Design decision: used accent-orange (--accent-orange) for the
indicator to differentiate from type-colored icons and provide
a warm "uncommitted changes" signal without being alarming.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
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>
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>
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>
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>
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>
- E2E test now verifies Cmd+S shortcut shows a save toast
- Added design/editor-save-bug.pen wireframe
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two frames showing the visual distinction between editable properties
and read-only Info section:
- Frame 1: Full inspector with editable properties (hover states,
cursor pointer) and Info section (muted, non-interactive)
- Frame 2: Side-by-side comparison of editable vs read-only styling
Product decisions:
- Separate "Info" section for derived metadata (Modified, Created,
Words, Size)
- Info uses --text-muted color, no hover/click states
- Editable properties keep interactive styling (hover bg, pointer)
- Type row stays at top of Properties section as identity element
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* 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>
Four frames showing collapse states:
1. All panels visible (default with collapse button)
2. Sidebar collapsed (note list + editor)
3. Editor only (⌥1)
4. Editor + notes (⌥2)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shows sort dropdown with direction arrows (↑/↓) per option,
active state highlighting, and header button reflecting current direction.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copied from ui-design.pen as template. Contains existing 4-panel layout
frames showing sidebar, note list, editor, and inspector — the areas
where property sync and wikilink updates are now reflected immediately.
Note: Pencil app not available for interactive editing. Two logical
frames to call out:
1. Property sync: Inspector change → immediate sidebar/notelist update
2. Wikilink sync: rename → open tabs show updated wikilinks
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Four frames covering the GitHub vault modal flow:
1. Modal empty state — initial view with Clone/Create tabs
2. Clone repo list — browsing user repos with search
3. Create new repo — name input, visibility toggle, local path
4. Clone in progress — spinner, progress bar, status text
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Settings modal with header, 3 API key input fields (Anthropic, OpenAI,
Google AI), masked key display with clear button, and footer with
Cmd+, hint and Save button.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The macOS window frame (transparent title bar, 38px) and the sidebar
share the same background color (#F7F6F3), making them visually
indistinguishable. Replace the sidebar's paddingTop: 38 with a
dedicated spacer div that has a bottom border (1px solid var(--border)),
matching the border style used between all other panels. The spacer
also serves as a drag region for window movement.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two frames added to design/git-history.pen:
- "Git History — Commit List": shows inspector panel with clickable
hashes (primary color, underlined), relative dates, commit messages,
and author name (muted, small) on each commit row
- "Git History — Diff Open": shows diff view with breadcrumb bar
displaying file path and commit badge, plus colored diff lines
(red for removed, green for added)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two frames added:
- "Note Creation — Before (dialog)" — old flow with CreateNoteDialog
- "Note Creation — After (immediate)" — new flow with instant Untitled note
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Three frames showing the tab rename interaction:
1. Normal tab state (double-click hint)
2. Editing mode (inline input with ring border, text selected)
3. Saved state (new title, file renamed, wiki links updated)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>