The side panel was referenced from v0.2.5/v0.5/v0.8 but never defined or scheduled. Add it as a v0.1 build item, mark it unbuilt, and link the CONTEXT.md and product-design definitions.
11 KiB
Roadmap — version details
Frequent releases. Each version is a usable artifact, not a checkpoint.
This file holds the macro-plan (Macroplan block below) and the per-version
scope. The user-facing requirements and engineering targets each release feeds
into are tracked in 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.
Macro-plan
Macroplan source — paste into the macroplan app to render the week-by-week
view. original dates are the June 2026 baseline and never move; slips get
appended as reestimates, per-item actuals live in the Status block above.
title = "Typoena — macro plan"
[[feature]]
name = "v0.1 it writes, it pushes"
start = 2026-06-01
original = 2026-06-29
status = "at-risk"
note = "Overdue — core editing + on-device git push proven in spikes, but blocked on SD (compatible ≤32 GB card), boot splash, and wiring save/publish into main.rs."
[[feature]]
name = "v0.2 navigation"
start = 2026-06-29
original = 2026-07-20
status = "on-track"
note = "Core work landed early: motions and modes already run; gutter, Ctrl-d/u, UTF-8 buffer remain."
[[feature]]
name = "v0.2.5 international input"
start = 2026-07-20
original = 2026-08-03
[[feature]]
name = "v0.3 editing"
start = 2026-08-03
original = 2026-08-24
status = "on-track"
note = "Deletes, counts, and operator grammar done early in core; yank/paste, undo/redo remain."
[[feature]]
name = "v0.4 visual + ex"
start = 2026-08-24
original = 2026-09-07
status = "on-track"
note = ": command-line mechanism and :fmt done early; Visual mode not started."
[[feature]]
name = "v0.5 palette + multi-file"
start = 2026-09-07
original = 2026-09-28
[[feature]]
name = "v0.6 markdown"
start = 2026-09-28
original = 2026-10-12
status = "on-track"
note = "Done early in core — only the 80-col ruler remains."
[[feature]]
name = "v0.7 search + git"
start = 2026-10-12
original = 2026-11-02
[[feature]]
name = "v0.8 battery + sleep"
start = 2026-11-02
original = 2026-11-30
[[feature]]
name = "v0.9 robustness"
start = 2026-11-30
original = 2026-12-28
[[feature]]
name = "v1.0 polish"
start = 2026-12-28
original = 2027-01-25
[[milestone]]
name = "MVP ships"
week = 2026-06-29
requires = ["v0.1 it writes, it pushes"]
v0.1 — MVP: "it writes, it pushes" — [~]
The minimum thing that justifies the hardware existing. Full design: product · technical.
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
- 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 inmain.rs - Insert-only editing, backspace, enter, arrow keys — modal editor overshot this early (see v0.2)
- Line wrap, no line numbers yet — soft-wrap done early (see v0.6)
- Save on
Ctrl-S→ SD — SD blocked, not wired tomain.rs - 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-Gruns:git add .→ commit with an ISO-8601 timestamp message →git push; on push failure,git pull --no-editthen retry the push (no-op short-circuit when nothing is staged). Proven on device in thegit_syncspike (✓); not yet wired to the editor. - Split the display into writing column (~60 cols) + side panel
(~20 cols) for all metadata — the surface every later panel feature
writes to. Not built yet:
editor.rsstill renders full-width 79 cols. Defined inCONTEXT.md§ Screen regions and product § Screen layout. - [~] 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 — [~]
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).
- 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-uremain i a o O Ato enter InsertEscreturns to Normal- Line numbers in the left gutter: relative in Normal mode (current line 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 accented input lands. Done early so it isn't retrofitted across the whole motion/text-object surface. Render font is already ISO-8859-15 (Latin-9), so accented glyphs display.
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
UTF-8-correct buffer and the ISO-8859-15 render font.
- Dead keys — grave, acute, circumflex, diaeresis, tilde — compose with
the next letter: à é ê ë ñ, ç (via
'+c), both cases '+space emits a literal apostrophe (the everyday apostrophe path); a dead key followed by a non-composing letter emits the accent then the letter- A non-character event (Enter, Backspace, arrows) flushes any pending accent as its literal first
- Pending-accent indicator in the side-panel status strip
v0.3 — Vim editing — [~]
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 Pand repeat with.remain (need a register / recorded op) - Undo / redo (
u,Ctrl-r) — bounded history in PSRAM - Numeric prefixes (
3dd,5j) - Ahead of schedule:
cchange operator + text objects (ciw,di(,ca", … — inner/around, nesting-aware)
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 con selections - [~]
:command line::w :q :wq :e <path>(mechanism ✓; these commands remain) - Ahead of schedule / unscheduled:
:fmtMarkdown 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-Popens 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)
:eand palette share the same recent-files list:enewcreates a new file — prompts for scope (tracked vs local)- Delete a file — removes it from the SD card; for a Tracked file the
removal reaches the next
Ctrl-GPublish's staged set (git rm/add -Asemantics, not plaingit add .); a Local file is just unlinked Ctrl-Gis disabled / hidden when the current buffer is local-scope- The side panel briefly shows file count on
Ctrl-Gwhen the publish bundles 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 — [~]
Status: done early — only the 80-col ruler remains.
- Heading lines bolded in render (faux-bold double-strike)
- List continuation on Enter inside
-/1.(with empty-item exit) - 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)
v0.8 — Power: battery + sleep — [ ]
- Measure idle / typing / push current draw on bench
- 18650 + IP5306 charge board, soft power switch
- Light sleep on idle > 30 s (keyboard interrupt wakes)
- Deep sleep on lid close (reed switch); restore cursor + buffer
- Battery indicator in the side panel
v0.9 — Robustness — [ ]
- Crash-safe writes (write to
.tmp, fsync, rename) - Recover from interrupted push (re-attempt on next save)
- SD card removal / reinsert handling
- Wi-Fi reconnect with backoff
- On-device provisioning + settings screen: SSID, PAT rotation, default remote, commit author (replaces the v0.1 dev-only NVS-flashing path — first release usable by someone who is not the firmware author)
v1.0 — Polish — [ ]
- Boot time ≤ 3 s to usable cursor
- Font selection (at least one serif + one mono) with adjustable font size, switchable at runtime and persisted across reboots
- Theme: light / dark (inverted e-ink), switchable at runtime and persisted across reboots
- Enclosure design files in
hardware/ - User guide
v1.x — Stretch / nice-to-have
- 10.3" panel upgrade via IT8951
- Multiple remotes / repos
- Stats: words today, streak
- BLE-HID fallback for wireless keyboards