# Petal — Build Plan & Progress Multi-session build. **Source of truth for what's done and what's next.** Update the checkboxes as work completes. `petal-spec.md` is the design spec; this file tracks execution. ## Decisions locked in (see also memory: petal-design-north-star) - **Auth deferred** — no Authentik yet. Seed a single hardcoded local user (`id = "local"`); keep the `user_id` column so auth drops in later without a schema migration. - **Copyleaks deferred** — needs a public webhook; skip Tier-2 plagiarism until there's a public endpoint. Tier-1 voice-consistency (local) is in scope. - **Traefik/deploy deferred** — local dev first. - **LLM**: Qwen 3.5 (256K context) on 64GB dual-GPU. Grammar checkpoint cap ~10K tokens (latency guard); voice pass sends whole document. - **Suggestion anchoring**: resolve by `original` string in ProseMirror coords at render time; stored `from_pos`/`to_pos` are plaintext offsets for server-side use only. (Spec Note #6.) - **Aesthetic is an acceptance criterion**: pretty, warm, Chinese-woman-friendly; CJK fonts first-class. ## Phases ### Phase 0 — Foundation / scaffold ✅ - [x] `git init`, `.gitignore`, remote → gitea.parodia.dev/drwily/petal - [x] Go module (`go.mod`), directory skeleton per spec - [x] `internal/config` env loading (local-dev defaults; auth/copyleaks fields kept for later) - [x] Vite + React 19 + TS + Tailwind v4 scaffold in `web/` (design tokens in `@theme`, Google fonts) - [x] Frontend embedded via `web/embed.go` (`go:embed all:dist`) + SPA handler in `cmd/server/main.go` - [x] Dev workflow documented in README; `.env.example` added - [x] Verified end-to-end: binary serves `/api/health` + embedded SPA + SPA fallback ### Phase 1 — Data layer ✅ - [x] SQLite (modernc) init + migrations (`internal/db/db.go`) — versioned `schema_migrations` runner, WAL + foreign keys, single writer conn - [x] Models: User, Document, Suggestion (`internal/db/models.go`) — + type/status constants - [x] Seed hardcoded `local` user (idempotent on startup) - [x] Schema includes `voice` in suggestions type CHECK (full spec schema incl. plagiarism_reports, to avoid a later migration) - [x] `db.Open` wired into `cmd/server/main.go`; `db_test.go` covers migrate/seed idempotency, CHECK constraint, FK cascade ### Phase 2 — Document CRUD + auto-save ← first "it works" milestone - [ ] Doc handlers: list/create/get/update/delete (`internal/docs/handlers.go`) - [ ] Frontend DocList sidebar (create/rename/delete) - [ ] Tiptap EditorCore (StarterKit, Underline, TextAlign, Placeholder, CharacterCount) - [ ] `useAutoSave` (1.5s debounce) → PUT /api/docs/:id - [ ] StatusBar: word count + save status - [ ] Keep `content` (Tiptap JSON) and `content_text` (plain) in sync on save ### Phase 3 — LLM grammar checkpoint - [ ] `LLMClient` interface + factory (`internal/llm/client.go`) - [ ] `vllm.go` (OpenAI-compat), `ollama.go` (native) — both behind interface - [ ] `checkpoint.go` (30s/doc rate limit), `prompts.go` - [ ] `POST /api/docs/:id/check` - [ ] `useCheckpoint` (4s debounce) + checkpoint indicator - [ ] SuggestionMark + SuggestionCard (accept/dismiss); **string-anchoring**, not stored pos - [ ] Suggestion colors: grammar=mint, phrasing=peach, idiom=lavender, clarity=sky ### Phase 4 — Ask Petal (conversational follow-up) - [ ] `POST /api/suggestions/:id/chat` SSE streaming; server-side context injection - [ ] AskPetal component, token-by-token render, no persistence - [ ] CJK font fallbacks on chat bubbles (spec Note #17) ### Phase 5 — Voice consistency pass (Tier 1) - [ ] `POST /api/docs/:id/voice`, whole-document, slow cadence / explicit action - [ ] `voice` suggestion type, honey decoration (`--color-honey`) ### Phase 6 — Design system & polish - [ ] Full pastel tokens, Nunito + Lora + JetBrains Mono - [ ] Shape language, shadows, transitions - [ ] Signature animations (suggestion fade-float, accept confetti, breathing checkpoint dot) - [ ] Distraction-free mode ### Phase 7 — Spell check - [ ] nspell browser-side (en-US), vendor dictionaries ### Deferred (post-v1-local) - [ ] Authentik OIDC auth + session middleware - [ ] Copyleaks Tier-2 + webhook HMAC - [ ] Dockerfile, docker-compose, Traefik, deploy to write.parodia.dev ## Session log - 2026-06-25: Spec reviewed & amended (voice/grammar decoupled, ctx cap, routes, voice DB type, honey color, string-anchoring). Build plan created. - 2026-06-25: **Phase 0 complete.** Go module + chi server, config loader, React/Vite/Tailwind-v4 scaffold with full design tokens, frontend embedded & served by the binary, verified end-to-end. Toolchain: Go 1.24.4, Node 22, npm 10. Next: **Phase 1 (data layer)** — SQLite via modernc, models, seed `local` user. - 2026-06-25: **Phase 1 complete.** `internal/db` package: modernc.org/sqlite (pulled go toolchain → 1.25), `Open()` does mkdir + WAL/foreign-keys DSN + versioned migration runner + idempotent local-user seed. Models with type/status constants. Wired into `main.go`; tests pass (migrate/seed idempotency, CHECK reject, FK cascade). Verified server boots and writes `petal.db`. Next: **Phase 2 (document CRUD + auto-save)** — first "it works" milestone.