116 lines
4.9 KiB
Markdown
116 lines
4.9 KiB
Markdown
# CLAUDE.md — Laputa App
|
||
|
||
## ⛔ BEFORE EVERY COMMIT — Non-negotiable checklist
|
||
|
||
Run all of these. If any fails, fix before committing. No exceptions.
|
||
|
||
```bash
|
||
pnpm lint && npx tsc --noEmit # lint + types
|
||
pnpm test # unit tests
|
||
pnpm test:coverage # frontend ≥70% coverage
|
||
cargo test # Rust tests
|
||
cargo llvm-cov --manifest-path src-tauri/Cargo.toml --fail-under-lines 85
|
||
pre_commit_code_health_safeguard # CodeScene ≥9.2 — if it fails, fix structurally (see below)
|
||
```
|
||
|
||
**CI is a safety net, not a discovery tool.** If CI catches something you didn't catch locally, that's a process failure. All these tools are available locally — use them while you code, not just at the end.
|
||
|
||
## ⛔ BEFORE FIRING laputa-task-done — QA on real vault
|
||
|
||
1. Acquire lockfile: `echo $$ > /tmp/laputa-qa.lock && trap "rm -f /tmp/laputa-qa.lock" EXIT`
|
||
2. Kill other instances: `pkill -x laputa 2>/dev/null || true; sleep 1`
|
||
3. Start app: `pnpm tauri dev` from worktree
|
||
4. Switch vault to `~/Laputa` (not demo)
|
||
5. Test the feature/fix with real mouse clicks (`cliclick`) on real notes
|
||
6. If task touches file save: verify `git -C ~/Laputa diff` shows changes
|
||
7. If QA fails → fix and re-run. Do NOT fire the signal until it passes.
|
||
|
||
Fire done signal only after QA passes:
|
||
```bash
|
||
rm -f /tmp/laputa-qa.lock
|
||
openclaw system event --text "laputa-task-done:<task_id>:<slug>" --mode now
|
||
```
|
||
|
||
## ⛔ CODE HEALTH — No shortcuts
|
||
|
||
If `pre_commit_code_health_safeguard` flags a file:
|
||
- **Understand why** — use `code_health_review` via CodeScene MCP
|
||
- Fix the structural problem (extract hooks, split components, reduce complexity)
|
||
- **Never** add a JSDoc comment, `#[allow(...)]`, `// eslint-disable`, or `as any` just to pass the gate
|
||
- It's fine to take longer. False quality is worse than no quality.
|
||
|
||
---
|
||
|
||
## Project
|
||
|
||
Tauri v2 + React + TypeScript desktop app. Reads a vault of markdown files with YAML frontmatter.
|
||
|
||
- **Spec**: `docs/PROJECT-SPEC.md`
|
||
- **Architecture**: `docs/ARCHITECTURE.md`
|
||
- **Abstractions**: `docs/ABSTRACTIONS.md`
|
||
- **Wireframes**: `ui-design.pen`
|
||
- **Luca's vault**: `~/Laputa/` (~9200 markdown files)
|
||
|
||
## Tech Stack
|
||
|
||
- Desktop: Tauri v2 (Rust backend)
|
||
- Frontend: React 18 + TypeScript + BlockNote editor
|
||
- Tests: Vitest (unit), Playwright (E2E), `cargo test` (Rust)
|
||
- Package manager: pnpm
|
||
|
||
## Architecture
|
||
|
||
- `src-tauri/src/` — Rust backend (file I/O, git, frontmatter parsing)
|
||
- `src/` — React frontend
|
||
- `src/mock-tauri.ts` — Mock layer for browser/test env (silently swallows Tauri calls — **not a substitute for native app testing**)
|
||
- `src/types.ts` — Shared TypeScript types
|
||
|
||
## How to Work
|
||
|
||
- **Never develop on `main`** — always on `task/<slug>` branch
|
||
- **Commit every 20–30 min** — atomic commits, one concern per commit (`feat:`, `fix:`, `refactor:`, `test:`, `docs:`)
|
||
- **Update docs/** when changing architecture, abstractions, or significant design
|
||
- **Test as you go** — write tests alongside code, not after
|
||
|
||
## Testing
|
||
|
||
- Unit tests must cover real business logic, not "component renders"
|
||
- Every bug fixed manually → add a regression test
|
||
- Every new feature → new tests for new behavior paths
|
||
- `pnpm test:coverage` and `cargo llvm-cov` must pass before committing
|
||
|
||
## Design File (every UI task)
|
||
|
||
Every task with UI changes needs a design file. Follow this process:
|
||
|
||
1. **Open `ui-design.pen` first** — study existing frames to understand the visual language, spacing, and component style before designing anything new.
|
||
2. **Design in light mode** — all existing designs use light mode. New frames must match. Never use dark mode for designs.
|
||
3. **Create `design/<slug>.pen`** for the new feature — additive only, NOT a copy of ui-design.pen.
|
||
4. **When merging to main** — merge your frames into `ui-design.pen` with proper layout:
|
||
- Place frames in a logical area (group by feature area, not stacked on top of each other)
|
||
- Leave at least 100px spacing between frames
|
||
- **Delete `design/<slug>.pen`** after merging — the frames now live in `ui-design.pen`
|
||
|
||
```bash
|
||
mkdir -p design
|
||
# Study schema first:
|
||
node -e "const f=JSON.parse(require('fs').readFileSync('ui-design.pen','utf8')); console.log(JSON.stringify(f.children[0],null,2))"
|
||
# Start fresh:
|
||
echo '{"children":[],"variables":{}}' > design/<slug>.pen
|
||
```
|
||
|
||
## macOS / Tauri Gotchas
|
||
|
||
- `Option+N` on macOS → special chars (`¡`, `™`), not `key:'N'`. Use `e.code` or `Cmd+N`.
|
||
- Tauri menu accelerators: use `MenuItemBuilder::new(label).accelerator("CmdOrCtrl+1")` — decorative text in labels doesn't register shortcuts.
|
||
- `app.set_menu()` replaces the ENTIRE menu bar — include all submenus.
|
||
|
||
## QA Scripts
|
||
|
||
```bash
|
||
bash ~/.openclaw/skills/laputa-qa/scripts/focus-app.sh laputa
|
||
bash ~/.openclaw/skills/laputa-qa/scripts/screenshot.sh /tmp/out.png
|
||
bash ~/.openclaw/skills/laputa-qa/scripts/shortcut.sh "command" "s"
|
||
bash ~/.openclaw/skills/laputa-qa/scripts/click.sh 400 300 # logical coords
|
||
```
|