From 77768cc85f913171b734c33370be86954725b64c Mon Sep 17 00:00:00 2001 From: Julien Calixte Date: Tue, 7 Jul 2026 23:44:46 +0200 Subject: [PATCH] docs(roadmap): sync marks to actual core progress The editor core runs 2-3 versions ahead of shippable device releases (no release has shipped; v0.1's hardware gate is still open). Mark done/partial items across v0.1-v0.7 with [x]/[~], record what landed early (View mode, d/c operators + text objects, :fmt), and the v0.4 decision to move View off v/V so Visual can take them. --- docs/roadmap.md | 100 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 74 insertions(+), 26 deletions(-) diff --git a/docs/roadmap.md b/docs/roadmap.md index ba7c8b3..264c689 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -5,36 +5,57 @@ The macro-plan (Gantt) lives in the [README](../README.md#roadmap); this file holds the per-version scope. The user-facing requirements and engineering targets each release feeds into are tracked in [`qfd.md`](qfd.md). +## Status — synced 2026-07-07 + +The editor **core** (`firmware/src/editor.rs`) has been built 2–3 versions +ahead of the device **releases**. No release has shipped: v0.1's hardware gate +(SD, splash, wiring the git/save path into the app binary) is still open, even +though v0.2 navigation and most of v0.6 Markdown already run. Version numbers +are unchanged — they track shippable device releases, not core progress. + +Marks: `[x]` done in core · `[~]` partially done · `[ ]` not started. An +inline `(✓)` marks the done half of a split item. + --- -## v0.1 — MVP: "it writes, it pushes" — [ ] +## v0.1 — MVP: "it writes, it pushes" — [~] The minimum thing that justifies the hardware existing. Full design: [product](v0.1-mvp-product.md) · [technical](v0.1-mvp-technical.md). -- [ ] ESP32-S3 boots, e-ink shows Typoena splash + boot log -- [ ] USB host enumerates the Nuphy, key events reach the editor -- [ ] One hard-coded file (`/sd/repo/notes.md`) opens on boot -- [ ] Insert-only editing (no modes yet), backspace, enter, arrow keys -- [ ] Line wrap, no line numbers yet -- [ ] Save on `Ctrl-S` → SD -- [ ] Wi-Fi credentials + remote URL + PAT + author baked into the binary at +**Status:** core editing + partial refresh run on device. **Blocked** on three +integration items: SD (Spike 3 — awaiting a compatible ≤32 GB card), the boot +splash (Spike 9), and wiring the git/save path into the app binary — today it +lives in the `git_sync` / `sd_fat` spike bins, not `main.rs`. + +- [~] ESP32-S3 boots (✓); e-ink shows Typoena splash + boot log — splash pending Spike 9 +- [x] USB host enumerates the Nuphy, key events reach the editor (Spike 4) +- [ ] One hard-coded file (`/sd/repo/notes.md`) opens on boot — SD spike-only, not in `main.rs` +- [x] Insert-only editing, backspace, enter, arrow keys — modal editor overshot this early (see v0.2) +- [x] Line wrap, no line numbers yet — soft-wrap done early (see v0.6) +- [ ] Save on `Ctrl-S` → SD — SD blocked, not wired to `main.rs` +- [x] Wi-Fi credentials + remote URL + PAT + author baked into the binary at build time via env vars (no NVS, no on-device provisioning UI in v0.1) -- [ ] `Ctrl-G` runs: `git add .` → commit with an ISO-8601 timestamp message → +- [~] `Ctrl-G` runs: `git add .` → commit with an ISO-8601 timestamp message → `git push`; on push failure, `git pull --no-edit` then retry the push - (no-op short-circuit when nothing is staged). PAT from first-run setup. -- [ ] Partial refresh on edits; full refresh on save + (no-op short-circuit when nothing is staged). Proven on device in the + `git_sync` spike (✓); not yet wired to the editor. +- [~] Partial refresh on edits (✓ Spike 5); full refresh on save — save not wired yet Out of scope: Vim, palette, multiple files, branches, conflict handling. -## v0.2 — Vim navigation — [ ] +## v0.2 — Vim navigation — [~] -- [ ] Mode state machine (Normal / Insert), mode indicator in the side panel -- [ ] Movement: `h j k l`, `w b e`, `0 $`, `gg G`, `Ctrl-d Ctrl-u` -- [ ] `i a o O A` to enter Insert -- [ ] `Esc` returns to Normal +**Status:** navigation done in core; remaining = `Ctrl-d/u`, the line-number +gutter, and the UTF-8 buffer. Shipped early beyond scope: a read-only **View** +mode and the full `d`/`c` operator + text-object grammar (see v0.3 / v0.4). + +- [x] Mode state machine (Normal / Insert / View), mode indicator in the status strip +- [~] Movement: `h j k l`, `w b e`, `0 $`, `gg G` (✓); `Ctrl-d Ctrl-u` remain +- [x] `i a o O A` to enter Insert +- [x] `Esc` returns to Normal - [ ] Line numbers in the left gutter: relative in Normal mode (current line - shown as its absolute number), absolute in Insert mode + shown as its absolute number), absolute in Insert mode — Spike 13 first - [ ] Groundwork — UTF-8-correct buffer: caret motions and edits step by character, not byte (drop the ASCII == byte-offset assumption in `editor.rs`), so every motion added here and later stays correct once @@ -44,6 +65,8 @@ Out of scope: Vim, palette, multiple files, branches, conflict handling. ## v0.2.5 — International input — [ ] +**Status:** not started (depends on the v0.2 UTF-8-correct buffer). + A small focused release between navigation and editing. US-International dead-key accent composition, resolved in the keyboard layer (`usb_kbd.rs`) so the editor still receives a single `Key::Char`. Builds on the v0.2 @@ -58,19 +81,40 @@ UTF-8-correct buffer and the ISO-8859-15 render font. accent as its literal first - [ ] Pending-accent indicator in the side-panel status strip -## v0.3 — Vim editing — [ ] +## v0.3 — Vim editing — [~] -- [ ] `x dd yy p P`, `dw dd d$`, repeat with `.` +**Status:** deletes and counts done; **yank/paste, undo/redo, and `.` repeat +remain** — there is no register or recorded-op mechanism yet. The `d`/`c` +operator grammar and text objects landed here ahead of schedule (the roadmap +had scheduled only `dd`/`dw`/`d$`). + +- [~] `x dd`, `dw dd d$` (✓); `yy p P` and repeat with `.` remain (need a register / recorded op) - [ ] Undo / redo (`u`, `Ctrl-r`) — bounded history in PSRAM -- [ ] Numeric prefixes (`3dd`, `5j`) +- [x] Numeric prefixes (`3dd`, `5j`) +- [x] Ahead of schedule: `c` change operator + text objects + (`ciw`, `di(`, `ca"`, … — inner/around, nesting-aware) -## v0.4 — Visual mode + ex commands — [ ] +## v0.4 — Visual mode + ex commands — [~] + +**Status:** the `:` command-line mechanism is built (Command mode + status-strip +echo), but only `:fmt` exists — `:w :q :wq :e` remain. Visual mode is not +started. + +**DECISION (2026-07-07):** `v`/`V` = **Visual** selection (vim-standard). The +read-only **View** (reading/scroll) mode currently bound to `v`/`V` moves off +those keys and gets its own trigger (exact key TBD when Visual lands). View mode +stays — it just frees `v`/`V` for Visual. - [ ] Visual char (`v`) and line (`V`) modes, `y d c` on selections -- [ ] `:` command line: `:w :q :wq :e ` +- [~] `:` command line: `:w :q :wq :e ` (mechanism ✓; these commands remain) +- [x] Ahead of schedule / unscheduled: `:fmt` Markdown formatter + (table alignment, blank-line collapse, trailing-whitespace strip) ## v0.5 — File palette + multi-file — [ ] +**Status:** not started (Spikes 11 + 14 retire the panel-mechanism and +buffer-lifecycle risk first). + - [ ] `Ctrl-P` opens fuzzy file palette over **both** `/sd/repo/` and `/sd/local/`, with a scope marker (e.g. `[git]` / `[local]`) per result - [ ] Open, switch, close buffers (keep ≤ 3 in memory) @@ -84,15 +128,19 @@ UTF-8-correct buffer and the ISO-8859-15 render font. more than one dirty Tracked file (e.g. `"publishing 3 files: abc1234"`), so workspace-scoped behaviour stays visible to the user -## v0.6 — Markdown affordances — [ ] +## v0.6 — Markdown affordances — [~] -- [ ] Heading lines bolded in render -- [ ] List continuation on Enter inside `- ` / `1. ` -- [ ] Soft-wrap at word boundaries +**Status:** done early — only the 80-col ruler remains. + +- [x] Heading lines bolded in render (faux-bold double-strike) +- [x] List continuation on Enter inside `- ` / `1. ` (with empty-item exit) +- [x] Soft-wrap at word boundaries - [ ] Optional column ruler at 80 ## v0.7 — Search + better git — [ ] +**Status:** not started. + - [ ] `/` forward search, `n N` - [ ] `:Gpull` (fetch + fast-forward only; refuse on conflict and surface it)