chore: remove stale docs and assets (PROJECT-SPEC, ROADMAP, VISION, Design System Proposal, iPad Prototype, screenshots, untitled notes, prompt.txt, ui-design.pen)

This commit is contained in:
lucaronin
2026-04-06 19:18:15 +02:00
parent ceda8abe5d
commit 89f655cc04
29 changed files with 0 additions and 16351 deletions

10
adr.md
View File

@@ -1,10 +0,0 @@
---
type: Type
"sidebar label": ADRs
icon: article
color: red
title: Adr
---
# ADR

View File

@@ -1,5 +0,0 @@
---
title: Custom views as .yml files with client-side filter engine
type: Note
status: Active
---

View File

@@ -1,352 +0,0 @@
# Design System Proposal for Laputa
## Current State Assessment
### What exists today
- **53 top-level frames** scattered across a ~6800x11400px canvas with no spatial logic
- **0 reusable components** (every frame is ad-hoc)
- **~40 design variables** with light/dark theme support (colors, radii, fonts)
- **2 foundation frames**: Color Palette and Typography & Spacing Specs
- **1 full-app layout** frame (light mode only)
- **4 sidebar-collapse variations** showing different panel states
### Recurring patterns that should be components (but aren't)
By analyzing the 53 frames, these patterns are duplicated 3-10x each:
| Pattern | Where it appears | Times duplicated |
|---------|-----------------|-----------------|
| Inspector section header (label + action icon) | rbF01-03, reF01-03, pi01 | 7x |
| Note list item (title + snippet + date + dot) | dp01-04, mni01-04, trNL1 | ~10x |
| Tab bar tab (label + close + dot indicator) | dp10, mni10, full layout | 3x |
| Sidebar filter item (icon + label + count) | trSB1, full layout sidebar | 4x |
| Sidebar section group (chevron + icon + label) | full layout, drag frames | 4x |
| Breadcrumb bar (icon + path + badges) | dp20, archBtnNorm/Arc, full layout | 4x |
| Modal shell (header + body + footer) | ghv01-04, iogBH (settings) | 5x |
| Property row (label + value) | urlDefault/Hover/Edit, pi01 | 4x |
| Relationship pill (icon + label + X) | trRI1, reF01-03, rbF01-03 | 6x |
| Status badge (colored dot/pill) | dp01, dp10, dp20, dp30 | 4x |
| Status bar (version + branch + sync) | mni20, full layout | 2x |
| Search bar (dark themed) | 3aG9b, K1O2x, nrIcZ | 3x |
| Warning/info banner | trW30 | 1x (but will recur) |
Every time a new feature is designed, these get rebuilt from scratch.
---
## Proposed Structure
### Single file: `ui-design.pen`
Multiple files creates friction (can't reference components cross-file, harder to maintain). Keep one file, organized into logical **sections** using large container frames as visual grouping. Each section is a horizontal band across the canvas.
### Canvas Layout (top to bottom)
```
y ≈ 0 ┌─────────────────────────────────────────────┐
│ 0. COVER │
│ App name, version, last updated, TOC │
└─────────────────────────────────────────────┘
y ≈ 200 ┌─────────────────────────────────────────────┐
│ 1. FOUNDATIONS │
│ Color palette, Typography scale, Spacing, │
│ Border radius, Shadows, Iconography │
└─────────────────────────────────────────────┘
y ≈ 1800 ┌─────────────────────────────────────────────┐
│ 2. COMPONENTS (Reusable) │
│ Atoms → Molecules → Organisms │
│ Each component: default + states side by side│
└─────────────────────────────────────────────┘
y ≈ 5000 ┌─────────────────────────────────────────────┐
│ 3. PATTERNS / COMPOSITIONS │
│ Panel Inspector, Panel NoteList, Panel Editor│
│ Modal shell, Popover/dropdown shell │
└─────────────────────────────────────────────┘
y ≈ 7000 ┌─────────────────────────────────────────────┐
│ 4. FULL LAYOUTS │
│ Default state, Sidebar collapsed, Editor │
│ only, etc. (full 1440x900 frames) │
└─────────────────────────────────────────────┘
y ≈ 12000 ┌─────────────────────────────────────────────┐
│ 5. FEATURE SPECS │
│ Grouped by feature area — all current 53 │
│ frames reorganized here │
└─────────────────────────────────────────────┘
```
Each section starts with a **section label frame** (large text, description, horizontal rule). Within each section, frames flow **left to right, wrapping down**, with 100px spacing.
---
## Section 1: Foundations
### What to keep
- **Color Palette** (frame `mOf4J`) — already good. Move to top of file.
- **Typography & Spacing** (frame `HZonq`) — already good. Place next to color palette.
### What to add
- **Spacing Scale** — explicit 4px grid reference (4, 8, 12, 16, 20, 24, 32, 40, 48, 64) with visual boxes
- **Shadow Tokens** — overlay shadow, dialog shadow, dropdown shadow (currently only documented in CSS, not in the design file)
- **Icon Reference** — small grid showing common Lucide + Phosphor icons used in the app, at 14px and 16px sizes
### Variables to add
The .pen file already has `--radius-sm/md/lg` but is missing spacing variables. Add:
| Variable | Value | Usage |
|----------|-------|-------|
| `--space-xs` | 4 | Tight gaps (icon-to-label) |
| `--space-sm` | 8 | Standard gap |
| `--space-md` | 12 | Section padding |
| `--space-lg` | 16 | Panel padding |
| `--space-xl` | 24 | Large section gaps |
| `--space-2xl` | 32 | Page padding |
| `--space-3xl` | 48 | Section dividers |
---
## Section 2: Component Library
### Atomic Design Hierarchy
#### Atoms (smallest building blocks)
| Component | Variants/States | ID Prefix |
|-----------|----------------|-----------|
| **Button/Primary** | default, hover, active, disabled | `c/btn-pri` |
| **Button/Secondary** | default, hover, active, disabled | `c/btn-sec` |
| **Button/Ghost** | default, hover, active | `c/btn-ghost` |
| **Button/Destructive** | default, hover, disabled | `c/btn-dest` |
| **Button/Icon** | default, hover (icon-only button, e.g. close, settings) | `c/btn-icon` |
| **Input/Text** | empty, filled, focused, error, disabled | `c/input` |
| **Input/Search** | empty, with query, with clear button | `c/input-search` |
| **Badge** | default, secondary, outline, destructive, status colors (green/orange/red/blue/purple) | `c/badge` |
| **Status Dot** | green (new), orange (modified), none (clean) | `c/status-dot` |
| **Checkbox** | unchecked, checked, indeterminate | `c/checkbox` |
| **Toggle** | off, on | `c/toggle` |
| **Icon** | 14px, 16px, 20px wrapper with Lucide/Phosphor | `c/icon` |
| **Separator** | horizontal, vertical | `c/sep` |
| **Avatar/Initial** | letter avatar for Person entities | `c/avatar` |
| **Tooltip** | top, bottom (container with pointer) | `c/tooltip` |
#### Molecules (composed from atoms)
| Component | Composition | States | ID Prefix |
|-----------|------------|--------|-----------|
| **Sidebar/FilterItem** | icon + label + count badge | default, active, hover | `c/sb-filter` |
| **Sidebar/SectionHeader** | chevron + icon + label + add button | collapsed, expanded, hover, dragging | `c/sb-section` |
| **Sidebar/SectionItem** | indent + label | default, active, hover | `c/sb-item` |
| **Sidebar/TopicItem** | hash + label | default, active, hover | `c/sb-topic` |
| **NoteList/Item** | status dot + title + snippet + date + type pill | default, selected, hover, modified, new | `c/nl-item` |
| **NoteList/Header** | title + count + sort button | — | `c/nl-header` |
| **Tab** | label + close btn + modified dot | default, active, hover, modified | `c/tab` |
| **BreadcrumbBar** | path segments + word count + status badge | new, modified, clean | `c/breadcrumb` |
| **Property/Row** | label + value | default, hover, editing | `c/prop-row` |
| **Property/URLRow** | label + link + copy/edit icons | default, hover, editing | `c/prop-url` |
| **Relationship/Pill** | icon + label + (X remove on hover) | default, hover, trashed, archived | `c/rel-pill` |
| **Relationship/AddInput** | search input with autocomplete | empty, typing, results | `c/rel-add` |
| **Inspector/SectionHeader** | label + action button | default, hover | `c/insp-header` |
| **Git/CommitItem** | hash + message + author + date (timeline style) | — | `c/git-commit` |
| **Search/ResultItem** | title + path + highlighted snippet | default, selected | `c/search-result` |
| **Sort/DropdownItem** | label + direction arrow + checkmark | default, selected | `c/sort-item` |
| **Banner/Warning** | icon + message + optional action | info, warning, error | `c/banner` |
| **Wikilink** | colored link text (varies by entity type) | 8 type colors | `c/wikilink` |
#### Organisms (panel-level compositions)
| Component | Content | ID Prefix |
|-----------|---------|-----------|
| **Panel/Sidebar** | title bar + filters + sections + commit area | `c/panel-sidebar` |
| **Panel/NoteList** | header + type pills + item list | `c/panel-notelist` |
| **Panel/Editor** | tab bar + breadcrumb + content area | `c/panel-editor` |
| **Panel/Inspector** | properties section + relations + backlinks + history | `c/panel-inspector` |
| **Modal/Shell** | header + tab bar (opt) + body + footer | `c/modal` |
| **Popover/Dropdown** | list of items + separator + annotation | `c/popover` |
| **StatusBar** | left info + right info | `c/statusbar` |
| **TitleBar** | traffic lights (macOS) | `c/titlebar` |
---
## Section 3: Patterns / Compositions
These are **non-reusable** reference frames showing how components compose into real UI sections. Think of them as "component playgrounds" — they use component instances to build real UI, but they're documentation, not building blocks.
- **Inspector states**: Properties expanded, Relations with pills, Referenced By with/without entries, Backlinks, Git history
- **NoteList states**: All Notes view, filtered by section, empty state, search results
- **Sidebar states**: All sections expanded, one collapsed, dragging reorder, after reorder
- **Editor states**: Single tab, multiple tabs, modified tabs, diff view
- **Modal patterns**: GitHub Vault flow (4 states), Settings, Create Note, Commit Dialog
---
## Section 4: Full Layouts
| Frame | Description |
|-------|-------------|
| **Default — All Panels** | 1440x900, sidebar + notelist + editor + inspector |
| **Sidebar Collapsed** | Editor area wider, collapse button visible |
| **Editor + NoteList Only** | No sidebar or inspector |
| **Editor Only** | Focused writing mode |
| **AI Chat Open** | Inspector replaced with AI Chat panel |
| **Quick Open Modal** | Cmd+P overlay on default layout |
Keep the existing 5 layout frames (qHhaj + SC_all/nosb/edonly/ednl). Add AI Chat and Quick Open.
---
## Section 5: Feature Specs
Reorganize existing 53 frames into feature groups. Each group gets a **feature label** frame above it:
| Group | Frames to include |
|-------|-------------------|
| **Note Status & Indicators** | dp01, dp10, dp20, dp30, mni01, mni10, mni20 |
| **Trash & Archive** | trSB1, trNL1, trRI1, trW30, archBtnNorm, archBtnArc |
| **Inspector & Properties** | pi01, pi50, rbF01-03, reF01-03, urlDefault/Hover/Edit |
| **Sidebar** | dsg01a-04j, csB01, csA01 |
| **GitHub Vault** | ghv01-04, ghv03 |
| **Git History** | ghCL1, ghDO1, vc001, vc100, vc200 |
| **Sort & Search** | srtDD, srtBN, 3aG9b, K1O2x, nrIcZ |
| **Editor & Wikilinks** | wlc01 |
| **Settings** | iogBH |
| **Virtual List** | vl001 |
---
## Naming Convention
### Frames
```
Section-level: "== FOUNDATIONS =="
"== COMPONENTS =="
"== FULL LAYOUTS =="
Feature groups: "Feature: Trash & Archive"
"Feature: Note Status"
```
### Reusable Components
```
component/<category>/<name>
Examples:
component/button/primary
component/button/ghost
component/sidebar/filter-item
component/notelist/item
component/inspector/section-header
component/modal/shell
```
### States (within a component frame)
```
<component-name> — <state>
Examples:
Button/Primary — Default
Button/Primary — Hover
NoteList/Item — Selected
NoteList/Item — Modified
```
### Feature Spec Frames
```
<Feature> — <Specific View>
Examples:
Trash — Note List View
Trash — 30-Day Warning
Git History — Commit List
Git History — Diff Open
```
---
## Implementation Priority
### Phase 1: Foundation Cleanup (2-3 hours)
1. Add spacing variables to the .pen file
2. Move Color Palette and Typography frames to top of canvas (y ≈ 200)
3. Add section label frames as visual dividers
4. Reorganize existing 53 frames into the feature-spec section (y ≈ 12000+)
5. Create cover frame at y ≈ 0
**Impact**: Clean canvas, easy to navigate. Zero component work yet.
### Phase 2: Core Atoms (3-4 hours)
1. **Button** — 4 variants x 3 states = ~12 sub-frames, all as `reusable: true`
2. **Badge** — 6 color variants + 4 style variants
3. **Status Dot** — green, orange, red, none
4. **Input** — text + search variants
5. **Separator** — horizontal + vertical
6. **Icon Button** — close, settings, chevron, etc.
**Impact**: Building blocks exist. Future features can pull from them.
### Phase 3: Core Molecules (4-5 hours)
1. **Sidebar/FilterItem** — most reused sidebar pattern
2. **Sidebar/SectionHeader** — with chevron and add button
3. **NoteList/Item** — the most duplicated pattern in the file
4. **Tab** — with modified indicator states
5. **Property/Row** — default/hover/edit states
6. **Relationship/Pill** — normal/trashed/archived states
7. **Inspector/SectionHeader** — label + collapse/action
**Impact**: Feature specs can be rebuilt from instances. Consistency guaranteed.
### Phase 4: Organisms (3-4 hours)
1. **Modal/Shell** — replace 5 ad-hoc modals with instances of one shell
2. **Panel/Sidebar** — full sidebar composition
3. **Panel/NoteList** — full notelist composition
4. **StatusBar** — standardize
5. **Popover/Dropdown** — for sort, autocomplete, etc.
**Impact**: Full layouts can be composed from panel organisms.
### Phase 5: Rebuild Full Layouts (2-3 hours)
1. Rebuild "Laputa App — Full Layout (Light)" using component instances
2. Create remaining layout variants (AI Chat, Quick Open)
3. Ensure all layouts use the same component instances for consistency
**Impact**: Single source of truth. Change a button component, all layouts update.
### Phase 6: Feature Spec Cleanup (2-3 hours)
1. Rebuild key feature specs using component instances where possible
2. Remove frames that are now redundant (covered by component states)
3. Add any missing feature-specific variations
**Impact**: Clean, maintainable feature documentation.
---
## Estimated Total Effort
| Phase | Effort | Cumulative |
|-------|--------|-----------|
| 1. Foundation Cleanup | 2-3h | 2-3h |
| 2. Core Atoms | 3-4h | 5-7h |
| 3. Core Molecules | 4-5h | 9-12h |
| 4. Organisms | 3-4h | 12-16h |
| 5. Full Layouts | 2-3h | 14-19h |
| 6. Feature Cleanup | 2-3h | 16-22h |
**Recommendation**: Do phases 1-3 first (9-12h). This covers 80% of the value — clean organization + the most reused components. Phases 4-6 can happen incrementally as features are designed.
---
## What "World Class" Looks Like
After this work, `ui-design.pen` will:
1. **Open to a cover page** with app identity and section navigation
2. **Have ~30 reusable components** that match the real implementation 1:1
3. **Use variables everywhere** — no hardcoded colors, spacing, or radii
4. **Show every component state** — no guessing what hover/active/disabled looks like
5. **Compose layouts from instances** — change a component, all layouts update
6. **Group features logically** — find any feature spec in seconds
7. **Grow naturally** — new features just add instances of existing components + new feature-specific frames
The key shift: **from "collection of screenshots" to "living system of composable parts"**.

View File

@@ -1,332 +0,0 @@
# Laputa App — Personal Knowledge & Life Management App
## Status: V1 Complete! 🎉
## Vision
Custom desktop + mobile app to manage Luca's life — projects, responsibilities, knowledge, people, events. Built around a specific ontology that no existing app gets right. The current Laputa vault (Obsidian, 9200+ markdown files) is the data layer and predecessor — the app gives it a proper UI.
## Tech Stack
- **Desktop**: Tauri (Rust shell + system webview)
- **Frontend**: React + TypeScript
- **Editor**: CodeMirror 6 — live preview with reveal-on-focus (Obsidian/Bear style)
- **Mobile**: Capacitor (wraps same web UI for iOS/Android) — later phase
- **Data**: plain markdown files on disk with YAML frontmatter, git-versioned
- **Core logic**: Rust (file parsing, git ops, indexing) via Tauri commands
---
## Ontology
### Core Entities
#### Year
- Top-level time container
- Has: Quarters, Targets
- Naming convention: `2026` (Laputa legacy: Chinese zodiac names like `2022-tiger`)
#### Quarter
- Time container within a Year
- Has: Projects, Targets
- Natural planning/review cycle
#### Responsibility
- Long-running duty, possibly indefinite
- Has clear and measurable KPIs (via Measures)
- Has an owner (Person)
- Has: Projects, Procedures, Tasks, Measures
- Examples: "Grow newsletter", "Manage sponsorships", "Stay healthy"
#### Measure
- A trackable metric tied to one or more Responsibilities
- Quantitative and observable
- Examples: "Resting heart rate", "Newsletter subscribers", "Monthly revenue", "Sponsorship close rate"
#### Target
- A time-bound goal for a Measure
- Typically quarterly
- Examples: "Resting HR < 55 by Q1 2026", "Reach 100k subscribers by Q2 2026"
- Belongs to: a Quarter (or Year), references a Measure
#### Project
- Has a beginning and an end
- Can't be completed in one sitting
- Has success criteria (key results, described informally in the project page)
- Has a timeline — at minimum a deadline (default: end of quarter)
- Advances one or more Responsibilities
- Has an owner (Person)
- Belongs to: Quarter (primary), Responsibility
- Has: Tasks, Notes
#### Experiment
- Like an unplanned baby project — exploring something promising without expectation of success
- Can't be completed in one sitting
- No strict success criteria or deadline
- Has an owner (Person)
- Examples: "Vibe-coding a stock screener", "Testing a new content format"
#### Procedure
- Recurring piece of work, completable in one sitting
- Has a cadence (daily, weekly, monthly, etc.)
- Belongs to: a Responsibility (usually) or a Project (less common)
- Has an owner (Person)
- Examples: "Weekly sponsorship report", "Morning briefing", "Monthly review"
#### Task
- One-off piece of work, completable in one sitting
- Belongs to: a Responsibility or a Project
- Has an owner (Person)
#### Topic
- An area of interest — no performance expectations
- Things link to Topics for categorization/discovery
- Examples: "AI/ML", "Trading", "Fitness", "Frontend"
#### Note
- A document, tool, resource, or any material helpful to advance work
- Can belong to: Procedures, Responsibilities, Projects (one or many)
- Can be related to: Topics (one or many)
- Examples: evergreen notes, reference docs, templates, bookmarks
#### Person
- A real-world person or an AI agent
- Owner of Projects, Responsibilities, Procedures, Tasks
- Related to Events
#### Event
- Something that happened on a given day, stored in long-term memory
- Examples: conversations, meetings, achievements, personal milestones
- Can be related to: any entity above
- Date-based: one specific day
---
## Relationships Summary
```
Year
└── Quarter
└── Project ──→ Responsibility (advances)
└── Target ──→ Measure ──→ Responsibility
Responsibility
├── Project
├── Procedure (recurring)
├── Task (one-off)
└── Measure → Target
Project
├── Task
└── Note
Procedure
└── Note
Note ──→ Topic (categorization)
Event ──→ anything (loose association)
Person = owner of Project, Responsibility, Procedure, Task
```
### Relationship Types
- **Belongs to**: hierarchical parent (Project→Quarter, Task→Project, Procedure→Responsibility)
- **Advances**: Project→Responsibility (why this project exists)
- **Related to**: loose association (Event→anything, Note→Topic)
- **Owner**: Person who is accountable (single owner per entity)
---
## Laputa Legacy Mapping
| Laputa Concept | Life OS Equivalent |
|---|---|
| Year | Year |
| Quarter | Quarter |
| Goal | Target + Measure |
| Project | Project |
| Key Result | Informal in Project page |
| Responsibility | Responsibility |
| Procedure | Procedure |
| Topic | Topic |
| Person | Person |
| Event | Event |
| Evergreen | Note |
| Note (reading notes) | Note |
| Readings | Note |
| Essay | Note (belongs to a Responsibility/Project) |
| Monday Ideas | Note |
| Area | Folded into Responsibility or Topic |
| Month | Removed (Quarter is the planning unit) |
| Journal | Removed or becomes a Note |
| Movie/Restaurant/Hotel | Out of scope (or Topic-linked Notes) |
| Vital | Measure |
| Video/Buckets | Note (belongs to Project/Responsibility) |
---
## UI Design
### Design Reference
- Wireframes: `/Users/luca/OpenClaw/Laputa-app-design.pen`
- Inspiration: Bear Notes, Obsidian
### Core Principle: Type-Agnostic UI
Minimize custom UI behavior per entity type. Everything is a file, everything gets the same treatment. Type only determines which sidebar section an entity appears under (and maybe an icon/color hint). The editor, right panel, and note list behave identically regardless of type.
### Layout: Four Panels
#### 1. Left Sidebar — Navigation
**Filters** (flat, switch the note list view):
- All Notes
- Untagged
- Favorites
- People
- Events
**Section Groups** (expandable, show entity list):
- PROJECTS +
- EXPERIMENTS +
- RESPONSIBILITIES +
- PROCEDURES +
**Topics** (flat list, not nested):
- work
- strategy
- ideas
- research
- drafts
- archive
#### 2. Note List — Middle Panel
- Contextual to sidebar selection
- Title, preview snippet, date, tags as colored pills
- Status/type indicators
- Search bar + create button
- Default sort: last edited (descending)
- Quick type filter pills: `All | Notes | Events | People | ...`
- When viewing a section group entity (e.g. a Project): its own page is **pinned at top**, children listed below
#### 3. Editor — Main Panel
- CodeMirror 6 with live preview (reveal markdown syntax on active line)
- **Tab bar** at top: multiple open notes, closeable, shows parent context
- Title + content only — NO properties/frontmatter shown in editor
- Tags shown as clickable pills below title
- Created/last edited dates below title
- Wikilinks rendered as clickable in-app navigation links
- Frontmatter exists in the file but is hidden from the editor view
#### 4. Right Panel — Inspector
- **Status** pills (Active, Draft, etc.)
- **Properties**: Created, Modified, Author, Word Count, custom properties. Editable — writes to YAML frontmatter.
- **Relationships**: all "belongs to", "related to", "advances" links. Editable.
- **Backlinks**: notes that reference this note
- **Revision History**: git commits for this file — hash, message, author, timestamp. "View all revisions" link.
### Key UI Decisions
- **Editor is sacred** — all metadata/relationships live in the right panel, not above the content. Avoids the Obsidian/Notion problem of properties pushing content down.
- **Everything is a file** — a Project, Responsibility, Topic are all just notes with a type. Clicking one in the sidebar shows its page pinned at top of note list, children below.
- **Topics are flat** — no nesting for v1
- **Saved views / smart filters** — future feature. Saved queries that live under any entity in the sidebar (e.g. "Evergreen 60+ days" under a Procedure). Not in v1.
- **Tasks stay on Todoist** — no task management in v1
## Design Decisions
- **Month/Week are NOT entities** — they're time-based views/filters, not containers. Monthly reviews are a Procedure.
- **Essays, Monday Ideas, Videos, Readings** = Notes (belonging to Responsibility/Project)
- **Movies, Restaurants, Hotels** = Notes attached to Topics
- **Key Results** = informal, embedded in Project pages (not a separate entity)
- **Owner** = single Person per entity (no multi-owner for now)
- **Type-agnostic UI** — minimize type-specific behavior, keep everything consistent
- **Metadata in right panel, not in editor** — frontmatter is hidden from the editor, rendered as editable UI in the inspector
## Dev Workflow
> Full process documented in **`dev-workflow` skill** (`~/.openclaw/skills/dev-workflow/SKILL.md`).
> Below: Laputa-specific details only.
- **Repo**: `~/Workspace/laputa-app/` + GitHub `LucaRonin/laputa-app`
- **Design file**: `~/OpenClaw/projects/Laputa-app-design.pen`
- **Mock layer**: `src/mock-tauri.ts` (realistic test data for browser/Playwright testing without Tauri)
### Laputa-Specific MCPs (for Claude Code)
- **Context7** — up-to-date docs for Tauri v2, CodeMirror 6, React
- **Pencil MCP** — reads the .pen design file
### Key Lesson from M1
M1 passed all tests but showed 0 notes — vault path wrong, error silently swallowed. This drove the mandatory verification workflow now captured in the dev-workflow skill.
---
## V1 Milestones
### M1: Scaffold & Shell ✅ COMPLETE
**Goal:** Empty Tauri + React app that opens a window, reads a vault path, and lists files.
- [x] Init repo at `~/Workspace/laputa-app/`
- [x] Tauri v2 + React 19 + TypeScript + Vite 7 project setup
- [x] Configure Vitest (7 tests), Playwright (2 E2E tests), Rust tests (10 tests)
- [x] Rust backend: `list_vault` command — scans directory, parses YAML frontmatter via `gray_matter` crate
- [x] Rust backend: extracts type (Is A), aliases, Belongs to, Related to, Status, Owner, Cadence, title from H1
- [x] React: four-panel layout (Sidebar 250px, NoteList 300px, Editor flex, Inspector 280px), all resizable
- [x] Tauri mock layer for browser testing (`src/mock-tauri.ts`)
- [x] Screenshot verification via Playwright (`e2e/screenshot.spec.ts`)
- [ ] Push to GitHub (not yet done)
**Git log (5 commits):**
```
e72d66a Add Tauri mock layer for browser testing and visual verification workflow
bc75647 Remove unused Vite scaffold files
7d5c48c Add unit and E2E tests for all panel components
57083ad Add four-panel layout shell with vault scanning on load
6b53cf8 Initialize Tauri v2 + React + TypeScript project with vault scanner
```
### M2: Sidebar & Note List
**Goal:** Navigate the vault via sidebar, see filtered note lists.
- [ ] Sidebar: Filters section (All Notes, Favorites)
- [ ] Sidebar: Section Groups (Projects, Experiments, Responsibilities, Procedures) — populated from frontmatter `type:`
- [ ] Sidebar: Topics — flat list, populated from `Related to` topic links
- [ ] Note list: show title, preview snippet, date, type indicator
- [ ] Note list: sort by last modified (descending)
- [ ] Note list: search (full-text across vault)
- [ ] Note list: type filter pills (All | Notes | Events | People | ...)
- [ ] Clicking a section group entity: pin its page at top, show children below
- [ ] Filesystem watching: live reload when files change externally
### M3: Editor
**Goal:** Open and edit markdown files with CodeMirror 6 live preview.
- [ ] CodeMirror 6 integration with React
- [ ] Live preview: hide markdown syntax, reveal on active line (Obsidian/Bear style)
- [ ] Frontmatter hidden from editor view
- [ ] Tab bar: open multiple notes, close tabs, show parent context
- [ ] Wikilinks rendered as clickable links → navigate in-app
- [ ] Save: write markdown + YAML frontmatter to disk
- [ ] Auto-save (debounced)
- [ ] Basic markdown features: headings, bold/italic, lists, code blocks, links, images
### M4: Right Panel — Inspector
**Goal:** View and edit metadata, relationships, and git history.
- [ ] Properties panel: Created, Modified, Author, Word Count, Status, custom fields
- [ ] Properties editable → writes to YAML frontmatter
- [ ] Relationships panel: Belongs to, Related to, Advances — rendered as clickable links
- [ ] Relationships editable (add/remove)
- [ ] Backlinks: auto-computed from wikilinks across vault
- [ ] Git revision history: show commits for current file (hash, message, author, date)
- [ ] "View all revisions" link
### M5: File Operations & Polish
**Goal:** Create, rename, delete files. Polish for daily-driver use.
- [ ] Create new note (with type selector → sets `type:` in frontmatter, created at vault root)
- [ ] Rename file (updates filename + title)
- [ ] Delete → permanent delete with confirm dialog
- [ ] Keyboard shortcuts (Cmd+N new, Cmd+S save, Cmd+P quick open/search)
- [ ] Quick open palette (Cmd+P) — fuzzy search across all files
- [ ] People and Events filters in sidebar
- [ ] Visual polish: match Bear-inspired design from .pen wireframes
- [ ] E2E tests with Playwright for core flows
---
## Open Questions
- [ ] Migration path from current Laputa vault (legacy cleanup, schema normalization)
- [ ] Multi-user or just Luca + AI agents?
- [ ] How does Brian (and other agents) interact with the data?
- [ ] Mobile: when to start the Capacitor layer?
- [ ] Year/Quarter navigation in sidebar — dedicated section or time-based filter?
- [ ] Home/dashboard view — what does it show?

View File

@@ -1,113 +0,0 @@
---
title: ROADMAP
---
# Laputa — Product Roadmap
*Strategic directions, not implementation tasks. Each item here represents a direction that will be broken down into many smaller tasks when the time comes.*
*Updated: March 2026.*
---
## Consolidation sprint (current priority)
Before building new features, the architectural foundations must be solid. Key structural fixes underway:
- Move vault cache outside the vault directory (→ `~/.laputa/cache/`) with atomic writes
- Flip `type:` to canonical field in Rust parser (`Is A:` becomes alias)
- Remove `allContent` from the architecture — derive backlinks from open tabs only
- ~~Remove hardcoded `RELATIONSHIP_KEYS` — detect wikilink fields dynamically~~ ✅ Done
- Fix hardcoded vault path in `resolveNewNote` / `resolveNewType` / `resolveDailyNote`
- Define and enforce the three-source-of-truth contract (filesystem → cache → React state)
These are not features — they are the foundation everything else is built on.
---
## Strategic directions
### 1. Semantic properties
**What:** Conventional frontmatter field names (`status:`, `url:`, `start_date:`, `end_date:`, `goal:`, `result:`) trigger rich UI rendering beyond the Properties panel — chips in the note list, progress indicators in the editor header, date range badges.
**Why:** Notes are not just documents. A Project has a start and end. A Responsibility has KPIs. A Procedure has an owner and a cadence. The app should surface this structure visually, not just store it as plain text.
**Convention over configuration:** the rendering rules ship as sensible defaults. Users can override via `config/semantic-properties.md` in the vault — a plain markdown file, editable from within the app.
**Draft tasks:** created in Todoist. To be prioritized after consolidation sprint.
---
### 2. Default relationships in Properties panel
**What:** The Properties panel shows a set of relationship fields by default — even when empty — guiding the user toward a connected knowledge graph. Defaults include: Belongs to, Related to, Events, People (Type is already shown).
**Why:** A new note starts with a completely empty Properties panel today. There's no guidance on how to connect it. Laputa is opinionated — it should show you the connections that matter.
**Convention over configuration:** the default list is built in, but can be overridden via `config/relations.md` in the vault.
**Draft tasks:** created in Todoist. Needs design discussion (per-type overrides?) before implementation.
---
### 3. Global workspace filter
**What:** A top-level workspace switcher (below the traffic lights) that filters the entire app — sidebar, note list, search — to show only notes belonging to the selected workspace, plus shared notes (those without a Workspace field).
**Why:** A single vault often contains both personal and work content. A workspace filter lets you focus on one context at a time without cognitive overhead.
**How:** Notes opt into a workspace via `Workspace: [[workspace/refactoring]]` frontmatter. Workspace notes are auto-detected from the `workspace/` folder. No setup required.
**Future trajectory:** Workspaces are the seed of a multi-vault, multi-user access control model. In the future, workspaces may map to separate Git repositories — each with their own access permissions. Different people see different workspaces (vaults). Git provides the audit trail. This enables Laputa to grow from a personal tool to a small-team knowledge base without rebuilding the product.
**Draft tasks:** created in Todoist. Lower priority than semantic properties and default relationships.
---
### 4. Inbox and capture pipeline
**What:** An Inbox section that surfaces all unorganized notes — those with no outgoing relationships. Replaces "All Notes" as the primary landing section. Capture integrations (Chrome extension, iPhone share sheet, Readwise sync) feed into the inbox automatically.
**Why:** Capture and organize are fundamentally different activities and should be treated separately. Today Laputa has no concept of an unorganized note — everything lands in the same pool. The inbox makes the unorganized state visible and actionable, creating a discipline: Inbox Zero, reached weekly.
**The inbox as a smart filter:** not a folder. Any note without `Belongs to:`, `Related to:`, or other meaningful relationship is automatically in the inbox. Connecting a note to something removes it from the inbox, automatically.
**Capture integrations (future, each a separate feature):**
- Chrome extension → saves URL/clip as a note to the vault via Git
- iPhone share sheet → quick capture from any app
- Readwise / Kindle highlights → synced via Git automation
- Voice memo → transcribed and dropped into inbox
**Priority:** The Inbox UI is high-value and can be implemented without the capture integrations. Integrations come after.
---
### 5. Mobile apps
**What:** Native apps for iPhone and iPad — not ports of the desktop app, but purpose-built for each form factor.
**iPhone:** Optimized for fast capture. Quick note creation, voice memos, brief thoughts. The primary use case is getting something into the vault quickly while away from the desk. Minimal reading and editing.
**iPad:** A more capable mirror of the desktop experience — reading, editing, navigating the vault. Not a full four-panel layout, but enough to work on notes meaningfully. Think "laptop replacement for light work sessions."
**Why it matters:** Laputa's value as a personal knowledge system depends on being able to capture things wherever you are. Without mobile capture, important notes get lost or end up scattered in other apps.
**Sync:** Git-based, same as desktop. The vault is a Git repo — mobile apps commit and pull like any other client.
**Priority:** After the desktop experience is solid. Not before.
---
## Principles for this roadmap
- **Foundations before features** — a shaky architecture multiplies the cost of every feature built on top of it
- **Convention over configuration** — ship strong defaults, allow customization via vault files
- **File-first** — every strategic direction must be achievable without breaking the markdown-files-on-disk model
- **AI-readable by design** — conventions that humans find intuitive should also be legible to AI agents navigating the vault
---
*For active tasks and bugs, see the Todoist board (Laputa App project).*
*For architectural decisions and design principles, see [ARCHITECTURE.md](./ARCHITECTURE.md) and [VISION.md](./VISION.md).*
<!-- QA test edit Wed Apr 1 16:17:01 CEST 2026 -->

View File

@@ -1,195 +0,0 @@
# Laputa — Product Vision
*Written by Brian based on conversations with Luca Rossi, FebMar 2026.*
*This is a living document — update it as the vision evolves.*
---
## Why this, why now, why us
Before the what and how: the why.
The best projects are built by people who have an unusually strong answer to "why are you the right person to build this?" This is that answer.
**Luca Rossi** is a startup founder and former generalist CTO — someone who can build a product end-to-end across code, design, scope, and product. And for the last five years, full-time, he has run Refactoring: a technical newsletter with nearly 200,000 subscribers, for which he has written over 300 original articles. In word count, that's roughly two *Lord of the Rings* novels.
Personal knowledge management has been an obsession since university. But over the last five years it stopped being a hobby and became *table stakes* — the system that makes writing 300 articles possible. Laputa is an attempt to bottle that system.
The credibility is real: if you wonder whether this person knows how to organize knowledge for sustained output, the output speaks for itself. The method inside Laputa is not theorized — it's been battle-tested for years at scale.
**The distribution is built in.** Refactoring reaches ~200,000 engineers, managers, and technical leaders — exactly the people most receptive to a tool like this. The audience already trusts the author on this topic, because they've been reading his writing about knowledge management and learning for years.
This is not a product looking for a market. It's a tool built by its first power user, for an audience that already knows and trusts him.
**Why Laputa, in the context of Refactoring.**
Refactoring is a newsletter about how software is built, how teams work, and how digital products are developed — written from Luca's experience and conversations with other tech leaders. A natural question follows: what is the author's own current experience building software with AI?
Laputa answers that question directly and publicly. If it works — if it becomes a real product used by real people — it validates the author's capabilities and authority to write about these topics. Not as theory, but as demonstrated practice. Anyone can look at the GitHub repository, see 100 commits a day, and verify: this person actually does this.
This is why Laputa is **free and open source**: success becomes a reputation and acquisition channel for Refactoring. The attention and trust earned through a well-executed open source project converts — through sponsorships, paid subscriptions, and brand authority — into the business that Refactoring runs on.
The strategy is coherent: build the tool you describe, make the work visible, let the product speak for the author.
---
## The problem
Most people who want to work effectively with AI face a version of the same problem: **they don't have their knowledge organized in a way that AI can actually use.**
They have notes scattered across Notion, Apple Notes, browser bookmarks, and email. Some of it is structured, most of it isn't. Even the people who do maintain a knowledge base discover that AI tools — ChatGPT, Notion AI, others — struggle to navigate it meaningfully. The knowledge is there, but it's not *accessible*.
The problem has two distinct layers:
1. **Architectural**: most knowledge tools store data in proprietary formats on remote servers. AI tools can't read them efficiently, can't commit changes back, can't reason over the full structure. The format itself creates a ceiling.
2. **Methodological**: even with the right tool, most people don't know *how* to organize knowledge so it becomes useful over time — what to capture, how to connect things, how to turn raw notes into a system that works with you instead of against you.
Laputa addresses both layers, together. That's what makes it different.
---
## The insight: tool and method, together
Most PKM tools give you a blank canvas and leave the rest to you. They solve the first problem (somewhere to put things) but not the second (how to organize them). The result is that sophisticated users build complex custom systems, while everyone else gives up.
Laputa's position is different: **we ship the method alongside the tool.**
The method is opinionated but not rigid. It tells you: here's how to think about your work, here's where different kinds of notes belong, here's how to connect them. If it fits your needs — great, start immediately. If your situation is different — customize it. The types, the relationships, the structure can all be changed. But you don't have to figure it out from scratch.
This combination — an opinionated method on top of a technically excellent foundation — is what makes Laputa genuinely useful to people who are stuck, not just people who already know what they're doing.
---
## The method: a framework for knowledge work
### The knowledge ontology
Laputa organizes work around two axes:
| | **One-time** | **Recurring** |
|---|---|---|
| **Multi-session** | **Project** (has a start and end) | **Responsibility** (no end, measured by KPIs) |
| **Single-session** | *Task* (lives in a task manager) | **Procedure** (checklist, routine) |
Everything else is context:
- **Notes** — the atomic unit. Any note connects to one or more of the above.
- **Topics** — areas of interest with no performance expectation. A knowledge repository.
- **Events** — things that happened, anchored to a date.
- **People** — contacts and their history.
Relations between notes are first-class citizens — not just wiki-links, but typed, bidirectional connections that make the knowledge graph navigable.
This ontology is not arbitrary. It maps cleanly to how both individuals and organizations actually structure their work: companies have projects, responsibilities, procedures, and people. So do independent creators. So do individuals managing their lives.
### Knowledge has a purpose
A principle that underlies everything in Laputa: **notes exist to get things done.** Not to be stored for some abstract future use. Not to show how organized you are. To do something.
This is the difference between a knowledge system that works over years and one that collapses after a few weeks. Without a real purpose, the maintenance cost of taking notes is never justified, and people stop. With a purpose — writing regularly, building things, making decisions — the system pays for itself.
What you *do* with organized knowledge depends on who you are:
- **Writers and content creators** — the output is articles, essays, posts. Captures become highlights, highlights become **evergreen notes** (small, atomic, timeless ideas), evergreen notes become building blocks for articles. Evergreen notes are a middle layer: not the raw input, not the final output, but the refined reusable units that make writing easier and faster.
- **Builders and project-driven people** — the output is shipped work. Captures feed projects, decisions, and procedures. Evergreen notes matter less; the project knowledge graph matters more.
- **Operators and managers** — the output is better systems and decisions. Captures feed responsibilities (KPIs, workflows) and procedures (how we do things). The value accumulates in the recurring structure, not in individual notes.
The framework is flexible enough to fit all three — and most people are a mix. What stays constant is the flow: **capture → organize → express**. The *what* of expressing changes; the discipline doesn't.
### The two-phase workflow: capture and organize
Notes move through two distinct phases, and the transition between them is intentional.
**Capture** — fast, frictionless, available everywhere. A thought, a saved article, a Kindle highlight, a voice memo. The cardinal rule: never let friction during capture cause a good idea to be lost. Captured notes land in the vault unconnected — no relationships, no organization. That's fine. That's the point.
**Organize** — a deliberate, periodic activity (weekly is the natural cadence). You ask: *what is this useful for?* Many things that seemed important when captured won't survive this question — deleting >50% of captures is normal and healthy. For the things that survive: connect them. Link to a Project, a Responsibility, a Topic. Every note should eventually connect to at least one actionable container. If you can't connect something to anything, that's a signal worth paying attention to.
**The Inbox** is the UI expression of this split: a smart section that shows all unorganized notes — those with no outgoing relationships. The goal is Inbox Zero, reached periodically (weekly). The inbox is not a folder; it's a derived state. Connecting a note to something removes it automatically.
### Convention over configuration
The method lives in the app as *conventions*: standard field names and folder structures that have well-defined meanings and trigger specific behavior.
`status:` shows a colored chip. `Workspace: [[workspace/refactoring]]` assigns a note to a context. `Belongs to:` connects it to its parent. `start_date:` and `end_date:` show a duration badge. The app recognizes these by convention, without any setup.
Users who want more can override the defaults: `config/relations.md` changes which relationship fields appear by default; `config/semantic-properties.md` controls how fields are rendered. But the defaults work immediately, for everyone.
This is convention *over* configuration — not convention *instead of* it.
---
## The foundation: architecture that earns trust
The method is only as good as the system it runs on. Laputa's architecture is built around a single principle: **your knowledge is yours, permanently and unconditionally.**
### Local files, version-controlled with Git
Every note is a plain Markdown file on your disk. There is no database, no proprietary format, no sync lock-in. The files are readable by any tool that can open a text file — today and in twenty years.
Git provides version control: every change is tracked, diffable, reversible. You have a full audit trail of what changed, when, and why. Collaboration happens via Git — the same way software teams have collaborated for decades, without any proprietary cloud in between.
### AI-native by design
A vault of plain Markdown files, version-controlled with Git, is dramatically more AI-friendly than any SaaS-based system.
An AI agent working on a local vault can read thousands of notes in seconds, understand their structure, write new ones, connect existing ones, and commit the changes back — all with full comprehension. Notion's AI can't do this. No SaaS-based AI can do this, because the architecture doesn't allow it.
More importantly: the more a vault follows Laputa's conventions, the *less configuration an AI needs* to navigate it. Shared conventions make knowledge legible to both humans and AI without bespoke instructions for every setup. The method and the AI-native architecture reinforce each other.
### Open and exit-friendly
The trust between Laputa and the user is earned daily, not enforced by format. If something better comes along, you take your Markdown files and leave. The exit door is always open.
---
## Why not Obsidian?
Obsidian is the obvious comparison. The difference is philosophy:
- **Obsidian** is a blank canvas. Infinitely configurable via plugins and community extensions. Powerful for users who want to build their own system — and who have the time and patience to do so.
- **Laputa** is opinionated. It ships with a complete point of view: a knowledge framework, semantic conventions, and defaults that work immediately. No plugin hunting. No configuration required to get started.
Obsidian also treats Git as an afterthought — its business model is built around proprietary sync. In Laputa, Git is a first-class citizen: the natural, obvious way to sync, collaborate, and maintain history.
---
## Who it's for, and where it's going
### Three stages of adoption
Laputa is designed to grow through three natural stages — not pivots, but extensions of the same foundation:
**Stage 1: Personal PKM + AI context** *(current)*
A single person manages their knowledge, life, and work in a local vault. The primary collaborator is AI. The vault gives structure to one person's context, making it legible to an AI that can assist meaningfully across all areas of work and life. The method helps structure the knowledge; the AI helps use it.
**Stage 2: Independent knowledge workers**
Content creators, freelancers, consultants. People with maximum incentive *and* maximum agency to build a real system. They have projects, clients, responsibilities — and they work alone or in very small teams. The same ontology applies: a newsletter creator has editorial projects, a subscriber-growth responsibility, and a publishing procedure. AI collaboration deepens: the AI can see not just personal notes but client commitments, content pipelines, recurring workflows.
**Stage 3: Small teams**
The ontology scales to organizations. Companies have projects, responsibilities, procedures, and people — the same categories, at a larger scale. The access model changes: different people see different subsets of the vault, via workspace filtering and Git-based access control. Version history gives teams a full audit trail. AI agents become shared collaborators on team knowledge, not just personal assistants.
**What makes this trajectory coherent:** the foundational model — local files, Git-versioned, structured by conventions — doesn't need to be rebuilt at each stage. It extends naturally.
### The right early adopters
The first users who will get the most from Laputa are technically-minded individuals who:
- Are frustrated with Notion's performance, complexity, or lock-in
- Understand or are comfortable with Git
- Want a system that's AI-native by design, not by bolted-on features
- Value owning their data
Broader audiences will follow as the onboarding experience matures and the conventions become easier to adopt.
---
## Design principles
1. **Opinionated but not rigid** — ship the method and the defaults; allow customization where it matters
2. **Convention over configuration** — standard field names trigger rich behavior automatically; users can override via vault config files
3. **Git-first** — sync, history, collaboration, and audit trail via Git; no proprietary cloud
4. **AI-native architecture** — local files, open formats, structured by conventions legible to both humans and AI
5. **Zero lock-in** — earn trust daily; the exit door is always open
6. **Capture and organize are separate** — the inbox makes unorganized notes visible; Inbox Zero is the discipline
7. **Relations as first-class citizens** — connections between notes are as important as the notes themselves
8. **Filesystem as the single source of truth** — the app never owns the data; cache and UI state are always derived and reconstructible
9. **Convention over system config files** — app configuration and preferences that belong to a note (e.g. type-level UI preferences) are stored in that note's frontmatter using the `_field` underscore convention, not in separate config files or localStorage. Everything that matters lives in the vault as plain text.

View File

@@ -1,124 +0,0 @@
# iPad Prototype — Tauri v2 iOS Feasibility Report
**Date:** 2026-03-27\
\
**Status:** VERIFIED — App builds, installs, and renders React UI on iPad Pro 13" simulator (iOS 18.3.1)
## Summary
Laputa can be ported to iPad using Tauri v2 iOS (beta) with **minimal code changes**. The React frontend stays identical. The Rust backend compiles for iOS with conditional compilation to gate desktop-only features (git CLI, menu bar, MCP, Claude CLI). Vault read/write operations work without changes.
**Key result:** `tauri ios build --target aarch64-sim` succeeds. The app launches on iPad simulator and the React UI renders correctly (telemetry consent dialog, welcome screen, all styled correctly).
## What Works
| Feature | Status | Notes |
| ------------------------------ | ---------------- | --------------------------------------------------------------------- |
| Rust backend cross-compilation | VERIFIED | Zero errors, zero warnings for `aarch64-apple-ios-sim` |
| Desktop build (no regressions) | VERIFIED | 581 Rust tests pass, 2201 frontend tests pass, CodeScene gates pass |
| Tauri iOS project generation | VERIFIED | `tauri ios init` generates Xcode project successfully |
| Xcode build for simulator | VERIFIED | `tauri ios build --target aarch64-sim`**BUILD SUCCEEDED** |
| App launch on iPad simulator | VERIFIED | Installs and launches on iPad Pro 13" (M4), PID assigned |
| React UI in WebView | VERIFIED | Telemetry consent dialog renders with correct styling, fonts, buttons |
| Vault file read/write | Expected to work | Pure filesystem operations, no process spawning |
| AI chat (Anthropic API) | Expected to work | Uses `reqwest` HTTP, no CLI dependency |
| Search | Expected to work | Pure Rust in-memory search |
| Settings persistence | Expected to work | JSON file read/write |
## What Doesn't Work (Yet)
| Feature | Blocker | Recommended Solution |
| ---------------------- | ---------------------------- | --------------------------------------------------------------------------------------- |
| Git operations | No `git` binary on iOS | **Option B (Working Copy)** for prototype; **Option A (isomorphic-git)** for production |
| GitHub clone/push/pull | Depends on git CLI | Same as above |
| Claude CLI streaming | No `claude` binary on iOS | Use Anthropic API directly (requires new implementation) |
| MCP server / WS bridge | Spawns Node.js child process | Skip for mobile; explore in-process MCP later |
| macOS menu bar | Desktop-only API | Touch-native navigation (already handled by React) |
| Updater plugin | Desktop-only | Use TestFlight for updates |
| File open dialog | Different on iOS | `tauri-plugin-dialog` supports iOS — needs testing |
## Changes Made
### `src-tauri/src/lib.rs`
* Gated `WsBridgeChild`, `run_startup_tasks`, `spawn_ws_bridge`, `log_startup_result` behind `#[cfg(desktop)]`
* Mobile build skips MCP registration, WS bridge, and vault migrations at startup
* Run event handler gated for desktop (child process cleanup)
### `src-tauri/src/commands.rs`
* Git commands: desktop implementations remain unchanged; mobile stubs return graceful errors or empty results
* GitHub commands: desktop-only; mobile stubs return errors
* Claude CLI commands: desktop-only; mobile stubs return `installed: false`
* MCP commands: desktop-only; mobile stubs return `NotInstalled`
* Menu commands: desktop-only; mobile stub is a no-op
* Vault, frontmatter, search, AI chat, settings: **unchanged** (work on both platforms)
### `src-tauri/src/lib.rs`
* `pub mod menu` gated behind `#[cfg(desktop)]`
### `src-tauri/capabilities/`
* `default.json`: scoped to desktop platforms (`linux`, `macOS`, `windows`)
* `mobile.json`: new file with iOS/Android permissions (core, dialog)
### `src-tauri/gen/apple/`
* Full Xcode project generated by `tauri ios init`
* iPad support: all orientations enabled, arm64 architecture
## Architecture: How Mobile Stubs Work
```text
Frontend (React) ──invoke──> Tauri Commands ──> Rust Backend
┌──────────┴──────────┐
#[cfg(desktop)] #[cfg(mobile)]
│ │
Real impl Stub (error/empty)
(git CLI, (graceful degradation)
menu, MCP)
```
The frontend code doesn't change at all. Commands that aren't available on mobile return errors that the UI can handle gracefully (e.g., hiding the git sync panel, disabling commit buttons).
## Git Strategy for iPad
### Phase 1: Working Copy (Recommended for prototype)
* User manages vault with [Working Copy](https://workingcopy.app/) (git client for iPad)
* Laputa opens the vault via iOS Files API / FileProvider
* Zero git code needed in Laputa — Working Copy handles sync
* **Pro:** Works immediately, robust git implementation
* **Con:** Requires separate app, split UX for sync
### Phase 2: isomorphic-git (Production)
* Pure JS git implementation running in the WebView
* Replace `invoke("git_commit")` etc. with JS-side git operations
* **Pro:** Integrated UX, no external dependency
* **Con:** Slower on large vaults (~9200 files), limited advanced git features
### Phase 3: git2-rs / gitoxide (Future)
* Pure Rust git library compiled into the Tauri binary
* Best performance, no JS bridge overhead
* **Con:** Larger binary size, more integration work
## Next Steps
1. **Install iOS simulator runtime**`xcodebuild -downloadPlatform iOS` (downloading ~7GB)
2. **Full Xcode build**`npx tauri ios build --target aarch64-sim`
3. **Launch on iPad simulator**`npx tauri ios dev`
4. **Test vault read/write** — open a vault, read/edit a note
5. **Test AI chat** — verify Anthropic API calls work from iOS WebView
6. **Evaluate touch UX** — identify layout issues on iPad screen size
7. **File Provider integration** — test opening vaults from Working Copy via iOS Files
## Prerequisites Installed
* Rust iOS targets: `aarch64-apple-ios`, `aarch64-apple-ios-sim`, `x86_64-apple-ios`
* Xcode 16.2 with iOS 18.3.1 simulator runtime (downloading)
* CocoaPods 1.16.2, xcodegen 2.45.3, libimobiledevice 1.4.0
* Tauri CLI 2.10.0 with iOS support

View File

@@ -1,61 +0,0 @@
Title/filename sync: derive title from filename, keep in sync via frontmatter
## Goal
Every note has a `title` field in frontmatter that stores the human-readable title with original casing and spacing. The filename is always the slug of the title. The two are kept in sync at all times within Laputa.
## Current state
`extract_title` reads the first H1 heading as the display title, with filename as fallback. This approach is fragile: H1 can diverge from the filename, and using filename directly loses casing information.
## Expected behavior
### Title/filename contract
- `title` frontmatter = human-readable title (e.g. `Career Tracks Depend on Company Shape`)
- filename = slug of title (e.g. `career-tracks-depend-on-company-shape.md`)
- The two are always kept in sync within Laputa
### On note open (sync check)
When Laputa opens a note, it checks for desync:
- If `title` frontmatter is absent → derive title from filename (hyphens → spaces), write it to frontmatter
- If `title` frontmatter is present but its slug doesn't match the filename → **filename wins**: overwrite `title` with the filename-derived value
- If both are in sync → no-op
This means: edits made outside Laputa that change only the filename or only the title frontmatter are auto-corrected on next open. **Filename is the source of truth.**
### On title edit (inside Laputa)
When the user renames a note inside Laputa:
- Update `title` frontmatter to the new value
- Rename the file to the new slug
- Update all wikilinks in the vault (existing rename flow)
### Title display
`extract_title` should read `title` from frontmatter (never from H1). H1 in the body is just content.
## Keyboard access
- No new keyboard interactions — title editing is part of the existing rename flow
- QA: Cmd+P → open note → verify title in header matches frontmatter `title` field
## Edge cases
1. Note has no `title` frontmatter → derive from filename on open (silent, idempotent)
2. `title` frontmatter desync from filename (edited outside Laputa) → filename wins, title overwritten
3. Filename has hyphens that are actual content (e.g. `e2e-test.md`) → becomes `E2e Test` — acceptable tradeoff
4. Fresh note created in Laputa → title set immediately from user input, filename = slug
5. Note renamed outside Laputa (filename changed, title not) → title updated to match new filename on next open
## Acceptance criteria
- [ ] Every note has `title` in frontmatter after being opened in Laputa
- [ ] Filename = slug of `title` at all times within Laputa
- [ ] On open: desync is detected and resolved (filename wins)
- [ ] `extract_title` reads from frontmatter `title`, never H1
- [ ] Rename flow updates both `title` frontmatter and filename atomically
- [ ] **Keyboard access:** open note → rename via title field → file renamed + wikilinks updated
- [ ] No regressions (`pnpm test` + `cargo test` pass)
- [ ] **Native app QA (keyboard only):** Open note → edit title → confirm filename changed + wikilinks updated; then manually desync title in a file → reopen in Laputa → confirm title auto-corrected
---
CONTEXT:
- Worktree: /Users/luca/Workspace/laputa-worktrees/title-filename-sync
- Dev port: 5393 (use --port 5393 when running pnpm dev)
- Run pnpm test before finishing
- Push directly to main when done: git push origin HEAD:main — NEVER open PRs, NEVER --no-verify
- Finish signal: openclaw system event --text 'laputa-task-done:6g9hCFpjP7qRRhqv:title-filename-sync' --mode now
- See CLAUDE.md for all coding guidelines

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +0,0 @@
---
title: Untitled key result
type: Key Result
status: Active
---
# Untitled key result

View File

@@ -1,6 +0,0 @@
---
title: Untitled note 134
type: Note
status: Active
---
# Untitled note 130

View File

@@ -1,6 +0,0 @@
---
title: Untitled note 134
type: Note
status: Active
---
# This is a very long title that should wrap onto multiple lines in the editor

View File

@@ -1,8 +0,0 @@
---
title: Untitled note 134
type: Note
status: Active
---
# Untitled note 130

View File

@@ -1,8 +0,0 @@
---
title: Untitled note 134
type: Note
status: Active
---
# Untitled note 130

View File

@@ -1,5 +0,0 @@
---
title: Untitled note 213
type: Note
status: Active
---

View File

@@ -1,5 +0,0 @@
---
title: Untitled note 215
type: Note
status: Active
---

View File

@@ -1,8 +0,0 @@
---
title: Untitled note 23
type: Note
status: Active
---
# Untitled note 23

View File

@@ -1,8 +0,0 @@
---
title: Untitled note 4
type: Note
status: Active
---
# Untitled note 18

View File

@@ -1,8 +0,0 @@
---
title: Untitled note 4
type: Note
status: Active
---
# Untitled note 4

View File

@@ -1,18 +0,0 @@
---
title: Untitled project 10
type: Project
status: Active
---
# Untitled project 10
## Objective
## Key Results
## Notes

View File

@@ -1,18 +0,0 @@
---
title: Untitled project 11
type: Project
status: Active
---
# Untitled project 11
## Objective
## Key Results
## Notes

View File

@@ -1,18 +0,0 @@
---
title: Untitled project 14
type: Project
status: Active
---
# Untitled project 15
## Objective
## Key Results
## Notes

View File

@@ -1,18 +0,0 @@
---
title: Untitled project 14
type: Project
status: Active
---
# Untitled project 14
## Objective
## Key Results
## Notes

View File

@@ -1,18 +0,0 @@
---
title: Untitled project 3
type: Project
status: Active
---
# Untitled project 3
## Objective
## Key Results
## Notes

View File

@@ -1,18 +0,0 @@
---
title: Untitled project 7
type: Project
status: Active
---
# Untitled project 7
## Objective
## Key Results
## Notes

View File

@@ -1,18 +0,0 @@
---
title: Untitled project 8
type: Project
status: Active
---
# Untitled project 8
## Objective
## Key Results
## Notes

View File

@@ -1,18 +0,0 @@
---
title: Untitled project 9
type: Project
status: Active
---
# Untitled project 9
## Objective
## Key Results
## Notes

View File

@@ -1,18 +0,0 @@
---
title: Untitled video
type: Project
status: Active
---
# Untitled project 13
## Objective
## Key Results
## Notes

View File

@@ -1,8 +0,0 @@
---
title: Untitled video
type: Video
status: Active
---
# Untitled video