docs: backfill ADRs 0016–0020 (historical decisions)
0016: Vault repair and auto-bootstrap 0017: Auto-save with 500ms debounce 0018: In-app git divergence and conflict resolution 0019: MCP server for AI integration 0020: AI dual architecture (chat + agent) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
31
docs/adr/0016-vault-repair-auto-bootstrap.md
Normal file
31
docs/adr/0016-vault-repair-auto-bootstrap.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
type: ADR
|
||||
id: "0016"
|
||||
title: "Vault repair and auto-bootstrap"
|
||||
status: active
|
||||
date: 2026-03-16
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
As Laputa evolved (flat vault migration, frontmatter format changes, theme seeding, config folder structure), existing vaults could end up in inconsistent states. Users shouldn't need to manually fix their vault structure after app updates. New features that depend on vault files (type definitions, config files, themes) need those files to exist.
|
||||
|
||||
## Decision
|
||||
|
||||
**Every feature that depends on vault files must auto-bootstrap: check if the file/folder exists on vault open, create with defaults if missing (silent, idempotent). A central `Cmd+K → "Repair Vault"` command runs all repairs at once.**
|
||||
|
||||
## Options considered
|
||||
|
||||
- **Option A** (chosen): Auto-bootstrap + central repair command — pros: self-healing, idempotent, no manual intervention, progressive vault upgrades / cons: startup has repair overhead (mitigated by fast checks), silent creation may surprise users
|
||||
- **Option B**: Migration scripts run once per version — pros: explicit, one-time cost / cons: users who skip versions miss migrations, requires version tracking in vault
|
||||
- **Option C**: Require manual vault setup — pros: user is in full control / cons: terrible UX, support burden, breaks on every structural change
|
||||
|
||||
## Consequences
|
||||
|
||||
- `repair_vault` Tauri command: flattens stray files, migrates legacy frontmatter (`Is A:` → `type:`), restores themes and config files
|
||||
- `vault_health_check` detects stray files in non-protected subfolders and filename-title mismatches
|
||||
- On vault load, a migration banner offers to flatten stray files to the root
|
||||
- `run_startup_tasks()` in `lib.rs`: purges trash, seeds themes, registers MCP — all idempotent
|
||||
- Config seeding (`config_seed.rs`): creates `config/` folder, migrates `AGENTS.md`, repairs missing config files
|
||||
- All new features must register their bootstrap logic with the repair command
|
||||
- Re-evaluate if startup repair overhead becomes noticeable on large vaults
|
||||
30
docs/adr/0017-auto-save-debounce.md
Normal file
30
docs/adr/0017-auto-save-debounce.md
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
type: ADR
|
||||
id: "0017"
|
||||
title: "Auto-save with 500ms debounce"
|
||||
status: active
|
||||
date: 2026-03-19
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
Manual save (Cmd+S) was the only way to persist note changes. Users could lose work if the app crashed or they navigated away. However, saving on every keystroke would cause excessive disk I/O and vault reloads, especially with the wikilink extraction and frontmatter parsing that happens on save.
|
||||
|
||||
## Decision
|
||||
|
||||
**Auto-save note content 500ms after the last keystroke via a debounced `useEditorSave` hook. No manual save required, though Cmd+S still works as an immediate save.**
|
||||
|
||||
## Options considered
|
||||
|
||||
- **Option A** (chosen): 500ms debounce auto-save — pros: no data loss, natural save rhythm, low disk overhead, same save pipeline as manual save / cons: very rapid typing may delay save, 500ms window for potential data loss on crash
|
||||
- **Option B**: Save on blur/navigate only — pros: fewer writes / cons: data loss on crash during editing, unexpected for users who leave the editor open
|
||||
- **Option C**: Periodic save (every N seconds) — pros: predictable write pattern / cons: either too frequent (wasteful) or too infrequent (data loss risk)
|
||||
|
||||
## Consequences
|
||||
|
||||
- `useEditorSave` hook debounces content changes at 500ms
|
||||
- Same save pipeline: `blocksToMarkdownLossy → postProcessWikilinks → prepend frontmatter → disk write`
|
||||
- Tab status indicator shows unsaved state during debounce window
|
||||
- Multi-window: each window has its own independent auto-save via `useEditorSaveWithLinks`
|
||||
- Cmd+S still available for immediate save (bypasses debounce)
|
||||
- Re-evaluate if 500ms proves too aggressive for low-powered devices or too slow for data safety
|
||||
32
docs/adr/0018-git-divergence-conflict-resolution.md
Normal file
32
docs/adr/0018-git-divergence-conflict-resolution.md
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
type: ADR
|
||||
id: "0018"
|
||||
title: "In-app git divergence and conflict resolution"
|
||||
status: active
|
||||
date: 2026-03-19
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
Laputa uses git for vault sync (via GitHub). When multiple devices edit the same vault, divergence (push rejected) and merge conflicts are inevitable. Previously, users had to resolve these outside the app using command-line git, which broke the self-contained experience and was error-prone for non-technical users.
|
||||
|
||||
## Decision
|
||||
|
||||
**Handle git divergence, push rejection, and merge conflicts entirely within Laputa's UI: sync status indicators, automatic pull-before-push recovery, a conflict resolver modal, and per-note conflict banners.**
|
||||
|
||||
## Options considered
|
||||
|
||||
- **Option A** (chosen): Full in-app conflict resolution — pros: self-contained, non-technical users can resolve conflicts, visual diff for each file, Keep mine / Keep theirs per note / cons: complex implementation, must handle all git edge cases
|
||||
- **Option B**: External tool delegation (open terminal or VS Code) — pros: simpler to implement, leverages existing tools / cons: breaks the flow, assumes user has git knowledge, poor UX
|
||||
- **Option C**: Conflict-free sync (CRDT-based) — pros: no conflicts by design / cons: fundamentally different architecture, incompatible with standard git, massive rewrite
|
||||
|
||||
## Consequences
|
||||
|
||||
- `useAutoSync` hook: configurable pull interval, detects divergence, sets `pull_required` status
|
||||
- `ConflictResolverModal`: shows conflicted files with resolution options (Keep mine / Keep theirs / Manual)
|
||||
- `ConflictNoteBanner`: inline banner in editor for conflicted notes
|
||||
- `pullAndPush()`: recovery flow for divergence — pull then auto-push
|
||||
- Git status popup: shows branch name, ahead/behind counts, Pull button
|
||||
- Sync states: idle, syncing, pull_required, conflict, error — shown in StatusBar
|
||||
- All git operations shell out to the `git` CLI (not libgit2) for reliability
|
||||
- Re-evaluate if CRDT-based sync becomes viable for markdown files
|
||||
31
docs/adr/0019-mcp-server.md
Normal file
31
docs/adr/0019-mcp-server.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
type: ADR
|
||||
id: "0019"
|
||||
title: "MCP server for AI integration"
|
||||
status: active
|
||||
date: 2026-03-01
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
AI assistants (Claude Code, Cursor) are increasingly part of the development and knowledge management workflow. To make the vault accessible to these tools, Laputa needed to expose vault operations as a standardized tool interface. The Model Context Protocol (MCP) provides exactly this — a standard way for AI clients to discover and call tools.
|
||||
|
||||
## Decision
|
||||
|
||||
**Ship an MCP server (`mcp-server/`) as a Node.js process that exposes 14 vault tools via stdio transport, with a WebSocket bridge for live UI integration. Auto-register in Claude Code and Cursor configs on startup.**
|
||||
|
||||
## Options considered
|
||||
|
||||
- **Option A** (chosen): MCP server with stdio + WebSocket — pros: standard protocol, works with Claude Code and Cursor out of the box, WebSocket bridge enables live UI actions from AI, auto-registration is frictionless / cons: Node.js dependency alongside Rust backend, two transport layers to maintain
|
||||
- **Option B**: REST API — pros: simpler, widely understood / cons: not a standard AI tool protocol, would need custom integration per AI client
|
||||
- **Option C**: Expose tools only via Claude CLI MCP config — pros: no separate server / cons: no WebSocket bridge, no live UI actions, limited to Claude CLI
|
||||
|
||||
## Consequences
|
||||
|
||||
- 14 tools: vault CRUD, search, frontmatter editing, note linking, UI actions (open note, highlight, set filter)
|
||||
- Two transports: stdio (Claude Code/Cursor) and WebSocket (port 9710 for tools, 9711 for UI actions)
|
||||
- Auto-registration in `~/.claude/mcp.json` and `~/.cursor/mcp.json` — non-destructive upsert
|
||||
- `mcp.rs` manages lifecycle: spawn on startup, kill on exit
|
||||
- `useMcpBridge` and `useAiActivity` hooks connect frontend to WebSocket bridge
|
||||
- MCP server reads/writes vault files directly — Tauri backend not involved in MCP tool execution
|
||||
- Re-evaluate if MCP protocol evolves to support binary transport or if vault operations need Tauri backend involvement
|
||||
32
docs/adr/0020-ai-dual-architecture.md
Normal file
32
docs/adr/0020-ai-dual-architecture.md
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
type: ADR
|
||||
id: "0020"
|
||||
title: "AI dual architecture (chat + agent)"
|
||||
status: active
|
||||
date: 2026-02-14
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
Users need AI assistance in two distinct modes: quick questions about their notes (lightweight chat) and complex multi-step operations on the vault (agent with tool access). A single AI interface cannot serve both use cases well — chat needs to be fast and cheap, while agent mode needs full tool execution and reasoning.
|
||||
|
||||
## Decision
|
||||
|
||||
**Provide two AI interfaces: AI Chat (direct Anthropic API, no tools, streaming text) and AI Agent (Claude CLI subprocess with MCP tools, NDJSON streaming, reasoning blocks, and tool action cards).**
|
||||
|
||||
## Options considered
|
||||
|
||||
- **Option A** (chosen): Dual interface (Chat + Agent) — pros: right tool for each job, chat is fast/cheap (Haiku default), agent has full tool access via MCP, clear UX separation / cons: two codepaths to maintain, two UIs in the inspector panel
|
||||
- **Option B**: Agent-only (always use Claude CLI) — pros: one interface / cons: overkill for simple questions, slower startup, higher cost, requires Claude CLI installation
|
||||
- **Option C**: Chat-only (API with function calling) — pros: simpler / cons: no file editing, no vault-wide operations, limited by API context window
|
||||
|
||||
## Consequences
|
||||
|
||||
- AI Chat: `AIChatPanel` + `useAIChat` — Anthropic API via Vite proxy (dev) or Rust `ai_chat` command (Tauri)
|
||||
- AI Agent: `AiPanel` + `useAiAgent` — spawns Claude CLI as subprocess, streams NDJSON events
|
||||
- Agent gets MCP vault tools via `--mcp-config` flag — search, read, edit, create notes
|
||||
- Context building: `ai-context.ts` builds structured snapshot (active note, linked notes, open tabs, vault metadata)
|
||||
- Three model options for chat: Haiku 3.5 (default), Sonnet 4, Opus 4
|
||||
- Agent mode detects file operations from tool inputs and triggers vault reload
|
||||
- Toggle between Inspector, Chat, and Agent via breadcrumb bar sparkle icon
|
||||
- Re-evaluate if function calling in the Anthropic API matures enough to replace the CLI subprocess approach
|
||||
@@ -71,3 +71,8 @@ proposed → active → superseded
|
||||
| [0013](0013-blocknote-editor.md) | BlockNote as the rich text editor | active |
|
||||
| [0014](0014-wikilink-relationships.md) | Wikilink-based relationship model | active |
|
||||
| [0015](0015-note-type-system.md) | Note type system (types as files) | active |
|
||||
| [0016](0016-vault-repair-auto-bootstrap.md) | Vault repair and auto-bootstrap | active |
|
||||
| [0017](0017-auto-save-debounce.md) | Auto-save with 500ms debounce | active |
|
||||
| [0018](0018-git-divergence-conflict-resolution.md) | In-app git divergence and conflict resolution | active |
|
||||
| [0019](0019-mcp-server.md) | MCP server for AI integration | active |
|
||||
| [0020](0020-ai-dual-architecture.md) | AI dual architecture (chat + agent) | active |
|
||||
|
||||
Reference in New Issue
Block a user