Commit Graph

121 Commits

Author SHA1 Message Date
Julien Calixte
e967773bd6 feat(editor): add v0.5 file palette (Cmd-P) with fuzzy match
Cmd-P opens a modal transient palette over the writing column: a bare
fuzzy-search input, the ranked file list, and the selected row in reverse
video. A pure host-testable fuzzy_score (subsequence + word-boundary and
consecutive-run bonuses) ranks results; an in-core MRU floats recently
opened files first and is shared with :e (both route through open_path).
The host feeds the file list once at boot (enumerate_files over /sd/repo
and /sd/local). Ctrl-n/Ctrl-p navigate the list; Enter opens via the same
park/evict path as :e; Esc closes.

Ctrl-n/Ctrl-p also become down/up line motions in Normal and View (vim
CTRL-N/CTRL-P, count-aware), which is why the palette opener is Cmd-P
alone. No `>` prefix on the file input — `>` is reserved for the command
palette (slice 4).

112 editor + 28 keymap tests; the no-git firmware binary builds clean.
2026-07-12 00:11:33 +02:00
Julien Calixte
2215da939d feat: add multi-file buffer foundation (v0.5 slice 1)
Rework the single Effect return into a drained effect queue
(Save{path,scope,contents} / Load / Publish / Pull) so one action can
ask the host for several ordered steps: opening a non-resident file
queues a Save of the outgoing dirty buffer then a Load of the target.

Keep the active buffer's fields inline on Editor and park inactive
buffers in a small LRU (<=3 resident = active + 2); switching back to a
resident buffer restores its caret/scroll/undo without touching the SD.
A dirty parked buffer is saved before eviction, so nothing leaves RAM
unsaved. `:e <path>` opens by prefix (/sd/repo -> Tracked, /sd/local ->
Local); `:sync` is refused in-core for a Local buffer.

Firmware drains the queue to empty each batch (a Load can cascade an
eviction Save) and persistence generalises the atomic save off the
hard-coded notes.md into load_path/save_path.

Also bump the side panel to FONT_9X15 and the `:` command line to
FONT_10X20 for legibility, word-wrapping the snackbar so a long notice
keeps its actionable tail.
2026-07-11 22:26:37 +02:00
Julien Calixte
fa0ea56e1a feat(editor): add Visual mode (v/V) with y/d/c, move View to gr
Charwise `v` and linewise `V` selection with yank/delete/change on the
span; motions and counts extend it. Read-only View moves off v/V to
`gr` (go-read). Selection renders reverse-video on the 1-bit panel.
Normal motions factored into a shared move_by. Firmware -> 0.4.0.
2026-07-11 20:50:16 +02:00
Julien Calixte
470a9d25d0 docs(macroplan): note v0.3 on-device smoke-test and paste-scroll fix 2026-07-11 20:26:15 +02:00
Julien Calixte
884c8f2e48 docs(postmortems): record the SPI-DMA OOM editor freeze
Root cause, shipped safety net, and the specced eradication (a
persistent internal DMA scratch buffer in Epd so paints never allocate
mid-sync). Tracks hardware re-test and the eradication as follow-ups.
2026-07-11 20:21:49 +02:00
Julien Calixte
f950abdc4a docs(macroplan): mark v0.3 editing complete
Records v0.3 as delivered in core (host-tested, on-device smoke-test pending)
and notes the known dot-repeat limits. Also reorders the plan so the Status
block follows the macroplan source.
2026-07-11 20:03:59 +02:00
Julien Calixte
229c259e7c docs: mark v0.2 complete and align delivered-release bookkeeping
Spike 13 (line-number gutter) verified on the panel closes the last v0.2
gate. Record v0.2 as delivered, and give v0.2.5 a delivered date + learning
note to match v0.1/v0.2 (its source-block entry still read on-track).
2026-07-11 19:41:17 +02:00
Julien Calixte
5d9591e5ea docs: rename roadmap.md to macroplan.md and refresh the plan
The file is the macroplan (plus per-version scope), so rename it to match and
retitle to "Macroplan"; update all inbound links and friendly labels across the
docs. Refresh the plan while here: v0.2 gutter built, :gl pull recorded (v0.7),
command-line editing (v0.4), and the format_on_save pref (v0.5).
2026-07-11 19:27:27 +02:00
Julien Calixte
97216db0c0 docs: record line-number gutter and v0.5 line_numbers pref
Mark the v0.2 gutter built + host-tested (Spike 13 bench check still pending),
add the v0.5 .typoena.toml line_numbers toggle, and update CONTEXT.md screen
regions for the rebalanced 63-col writing region / 25-col side panel.
2026-07-11 18:59:52 +02:00
Julien Calixte
fc83306a81 feat(keymap,editor): add Ctrl-d/u half-page scroll
Decode Ctrl+D/Ctrl+U as HalfPageDown/HalfPageUp intents (matching the existing
DeleteWord/DeleteLine chord pattern, so the editor stays ignorant of Ctrl).
They step display (soft-wrapped) rows, not logical lines, so half a page is
half the visible window regardless of how prose wraps: Normal moves the caret
and the viewport follows, View scrolls the viewport, Insert/Command are no-ops.
2026-07-11 18:32:05 +02:00
Julien Calixte
491dc57144 docs: drop relative line numbering from the v0.2 gutter
Relative numbering renumbers the whole gutter on every j/k, a tall partial
refresh per cursor move that eats the e-ink ghosting budget for no
proportionate gain. Gutter is now absolute-only; Spike 13 downgrades from a
genuine e-ink risk to a layout decision.
2026-07-11 18:31:33 +02:00
Julien Calixte
a817229ae1 docs(qfd): rebase perception and H1 targets on measured v0.1
Update the House now that v0.1 is delivered and hardware-verified:

- Perception zone: Typoena column moves from v0.1 target to measured.
  W6 3->4 (1 h soak attested), W1 4->2 (type latency measured ~630 ms,
  a visible lag). Typoena total 52->51, lead over Pomera down to one.
- H1 target: v0.1 relaxed 200->400 ms and v1.0 150->300 ms; ~630 ms
  still exceeds 400 ms, recorded as the open latency gap, not a pass.
- Fix pre-existing drift: TikZ W14 disagreed with the table/totals
  (Pomera/Smart 2/5 vs 5/1); "thirteen rows" -> "fourteen".
- Hoist the House diagram above section 1 so the picture leads.
- Trim AI writing tells and thin em-dash density in the new prose.
2026-07-11 17:58:38 +02:00
Julien Calixte
17b6631310 docs(qfd): annotate H7 Publish latency with measured :sync data
Adds a ‡ footnote on H7 (mirroring the H4 boot-latency †): cold :sync ~16 s /
warm ~10 s measured 2026-07-11 — within the ≤30 s v0.1 target, marginal against
the ≤10 s v1.0 target (cold's one-time Wi-Fi+SNTP push it over). Links the
breakdown in notes/sync-latency.md.
2026-07-11 17:21:26 +02:00
Julien Calixte
fe544ccdd3 refactor(docs): merge quality-house into qfd §3
quality-house.md mirrored qfd.md's §1/§2 catalogues in a separate file,
which silently drifted (H3 cadence read 20 there vs 64 in qfd). Fold the
House diagram, perception scores, and regen notes into qfd.md §3 with no
section renumbering, so inbound #3/#6/#7 anchors still resolve. Delete
quality-house.md; re-point quality-house-empty.md and the docs index.
2026-07-11 17:17:18 +02:00
Julien Calixte
a700412773 docs: record :sync latency budget from hardware measurement
New docs/notes/sync-latency.md breaks down the measured ~16 s cold :sync
(Wi-Fi + SNTP + one TLS push), explains the optimistic-retry handshake saving,
the reconcile/last-writer-wins semantics, and why the rest is near the protocol
floor. Linked from the notes index, the docs index, and the Git row of the root
README.
2026-07-11 17:04:02 +02:00
Julien Calixte
92068f1cce docs(quality-house): sync H3 target to 1:64 after qfd change 2026-07-11 17:00:45 +02:00
Julien Calixte
9d6daf7afd docs(qfd): sync boot latency and refresh cadence to measured values 2026-07-11 16:47:12 +02:00
Julien Calixte
c206fc28e4 docs: record verified 4258 ms cold boot after refresh fix 2026-07-11 16:46:56 +02:00
Julien Calixte
ad023843e9 docs: add e-ink refresh-latency curve and boot-time budget notes 2026-07-11 16:46:50 +02:00
Julien Calixte
8dc6ee362f feat(firmware): wire SD persistence + git publish into the editor
Land the v0.1 editor integration: the git_sync module (libgit2 on the SD
/sd/repo, dedicated 96KB git thread, lazy Wi-Fi, :sync push with
synced/up-to-date/failed snackbars), the boot splash (Spike 9) plus its bin
and justfile recipes, and a power-on→cursor boot-timing log. Also re-syncs
the roadmap/spikes/v0.1-product status and adds the SD hardware reference
photo.
2026-07-11 15:30:43 +02:00
Julien Calixte
98a9d1dffe docs: flag that v0.1 keeps wifi up, link git_sync.rs
Ground the off-between-syncs assumption in the code: the shipped firmware
runs the stay-associated strategy the section argues against. Link
run_git_service so the claim is verifiable and mark teardown as v0.8 work.
2026-07-11 15:25:33 +02:00
Julien Calixte
2673a3377a docs: note wifi is off (not modem-sleep) between syncs
Make explicit that the per-sync burst assumes a full radio de-init between
pushes, and that staying associated to skip handshakes loses on energy until
~150 syncs/hr — a regime a writing appliance never reaches.
2026-07-11 15:19:18 +02:00
Julien Calixte
f4af38d8ef docs: add .typoena.toml config and auto-sync energy tradeoff
Record the git-tracked .typoena.toml preferences file (save_on_idle,
auto_sync) and the palette `>` command mode that edits it in the v0.5
roadmap. Add a tradeoff-curves note deriving Wi-Fi sync energy as a 1/T
curve, which sets auto_sync's default to 10m (opportunistic, min-clamped)
rather than a 5m wall-clock timer.
2026-07-11 14:38:07 +02:00
Julien Calixte
14967a06c6 docs: retire resolved SD risk, re-sync v0.1 status
Spike 3 (SD) is resolved (genuine 32 GB card mounts, verified on its own
SPI3 host per ADR-012) and the mount/save path is now wired into main.rs.

- README: move the SD/CMD59 open question to the retired-risks line; drop
  the stale "blocked on SD (waiting on a compatible card)" from the status
  blurb. Remaining v0.1 gate is the boot splash + wiring git publish.
- roadmap: flip the boot-load and save-to-SD v0.1 items to done, re-sync
  the status blurb and macroplan note, re-point the config-at-boot TODO
  from the (landed) SD wiring to the git-publish wiring.
2026-07-11 14:14:08 +02:00
Julien Calixte
18ed6aa599 docs(roadmap): record the panel snackbar and fix panel status
The side-panel split (writing column + panel) is already built in the
editor crate; correct the stale "not built yet" note and add the
snackbar under v0.1.
2026-07-11 14:01:02 +02:00
Julien Calixte
81d5f818cc docs(persistence): note boot-load and :w/:sync save are wired 2026-07-11 12:17:58 +02:00
Julien Calixte
7a1f25f5d1 docs(persistence): document module and refine FAT recovery to two cases
Record that persistence is now implemented and hardware-verified, and correct
the crash-recovery rule everywhere it appeared as "just promote the tmp": a
crash during the tmp write leaves a partial tmp, so recovery keeps the
committed target when both files are present and only promotes the tmp when
the target was already unlinked. Also fix the stale README heading that still
said the SD was on shared SPI2.
2026-07-11 12:02:30 +02:00
Julien Calixte
5540f901de docs(sd): mark SD-on-SPI3 verified on hardware
Re-ran the spike on the dedicated SPI3 wiring (CLK 14 / MOSI 15) with
the same clean mount + atomic round-trip result. Flip the docs from
"pending a re-run" to verified.
2026-07-11 11:43:34 +02:00
Julien Calixte
4bc9236bd7 docs(adr): record ADR-012 — SD on its own SPI3 host
Document the shared-bus arbitration decision: rather than rework the
proven EPD SPI layer and add a cross-thread mutex on the save path, the
SD moves to a dedicated SPI3. Update the boot sequence, risk table,
Spike 3 postmortem follow-up, hardware overview, and firmware README.
2026-07-11 11:28:22 +02:00
Julien Calixte
5335751323 docs(sd): record Spike 3 hardware verification and findings
Mark Spike 3 resolved (genuine 32 GB SDHC mounts, round-trips clean on the
shared SPI2 bus; the 133 GB SDXC's CMD59 rejection was the sole fault).
Capture the FatFS f_rename caveat and the ≤32 GB card-compatibility note in
ADR-007, the resolution in the postmortem, and the verified writeup in the
firmware README.
2026-07-11 11:14:31 +02:00
Julien Calixte
757dd492b9 docs: trim AI writing tells from READMEs and docs prose
Drop magic adverbs (silently, arguably), a stakes-inflation flourish,
and the bold-first Snippets bullets; de-duplicate the "usable artifact,
not a checkpoint" line shared by the README and roadmap.
2026-07-11 09:19:58 +02:00
Julien Calixte
314fefc9b6 docs: link the enclosure to its README, not the folder 2026-07-11 09:08:40 +02:00
Julien Calixte
704fd743a0 docs: link the enclosure concept from README and hardware.md 2026-07-11 02:31:50 +02:00
Julien Calixte
13d49930cc docs: document the SD card provisioning recipes
Record init/load/provision in the roadmap (the config-on-SD migration
and the firmware env!()->file read TODO) and in the git-sync note as the
implementation of the pre-seed-from-a-computer decision.
2026-07-11 01:44:44 +02:00
Julien Calixte
e6498cdcb3 docs(roadmap): mark v0.2.5 + the v0.2 UTF-8 buffer done
International input is hardware-verified (dead-key composer, UTF-8-correct
editor, physical Esc -> backtick/tilde). Records the editor's extraction
into host-testable crates and the deliberately-dropped side-panel accent
marker.
2026-07-11 00:54:55 +02:00
Julien Calixte
371b542d44 docs(roadmap): plan Markdown snippets for v0.6
Trigger-driven expansion (no popup — e-ink refresh + distraction-free),
numbered empty tab stops + $0, no placeholder text, no dynamic values,
pause-triggered panel indicator. Records the why so scope isn't relitigated.
2026-07-08 22:44:33 +02:00
Julien Calixte
ad047cc717 docs: reconcile screen-layout docs with the panel changes
Mode now sits at the side panel's bottom-left (not its top), and the
words-this-session field is gone. Update the CONTEXT.md field list and
the product-doc mock + prose to match; note the keyboard flag renders
as NO KBD (Latin-9 has no glyph for the mock's symbols).
2026-07-08 21:48:32 +02:00
Julien Calixte
d6b9e46ec1 docs: add index READMEs for docs/ and docs/notes/
Give the two linked-but-unindexed folders a browsable entry point so
directory links land on a real index instead of a bare listing.
2026-07-08 14:45:58 +02:00
Julien Calixte
dbe7720a27 docs: point directory links at their folder's README
Bare-folder links (e.g. docs/postmortems/) only resolve on GitHub's
auto-render; retarget them to the folder's README.md so they open a
real file in any markdown viewer.
2026-07-08 14:45:52 +02:00
Julien Calixte
fcf5815468 docs(roadmap): track the writing column + side panel split in v0.1
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.
2026-07-08 11:02:41 +02:00
Julien Calixte
aa068147ab docs(roadmap): replace the mermaid Gantt with Macroplan TOML
The macroplan app parses this source directly; the baseline originals
stay fixed and v0.1's slip is expressed as an at-risk status instead of
a re-drawn bar.
2026-07-08 00:19:28 +02:00
Julien Calixte
c82130a616 docs(roadmap): move the macro-plan Gantt in from the README
Kept as the original June 2026 baseline with a note pointing to the
Status block for actuals.
2026-07-08 00:04:32 +02:00
Julien Calixte
571c5ed825 docs(hardware): add part table, rationale, and bench status page
Extracted from the README so it can slim down to a summary + link.
2026-07-08 00:04:25 +02:00
Julien Calixte
77768cc85f 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.
2026-07-07 23:44:46 +02:00
Julien Calixte
2aa4032e1f docs(notes): record why the notes repo stays full-size (pre-seed the SD)
The 150 MB of images are remanso's image CDN (it reads image bytes straight
out of git as blobs), not offloadable bloat — LFS/filter-repo/git-rm all
break remanso. libgit2 also lacks blobless partial clone. Decision: leave
the repo untouched and pre-seed the SD with a full clone from a computer, so
the device only ever takes the open + incremental fetch/push path. Also
notes the increment-C constraint: stage specific paths (not add_all) so a
media-excluding sparse checkout is safe.
2026-07-07 22:55:59 +02:00
Julien Calixte
ef755bac81 docs(postmortems): correct the FATFS delete finding (std, not read-only)
The read-only-attribute theory (and the predicted AM_RDO unlink shim) was
wrong. A diagnostic recursive walk showed every entry writable (ro=false)
and succeeded via path-based deletion, so the real blocker was
std::fs::remove_dir_all's openat/unlinkat/fdopendir usage against esp-idf's
path-based FATFS VFS. Update the increment-A/B checklist accordingly.
2026-07-07 22:49:18 +02:00
Julien Calixte
4153cae9c4 docs(postmortems): record milestone #2A verified, FAT read-only-delete finding
Increment A (persistent-clone publish cycle) is hardware-verified: clone +
persistent open + fast-forward push. Mark the follow-up checklist: git module
fold is in progress (A done; B = divergence + AM_RDO unlink shim; C = editor
wiring), tech-doc revision done, PAT-in-flash tracked as open ADR-011. Note
the FAT read-only-delete limitation and the real-notes-repo sizing caveat.
2026-07-07 08:35:11 +02:00
Julien Calixte
cce62bf9f7 docs(adr): add ADR-011 for credential provisioning (open)
The PAT-in-flash shortcut (ADR-005 v0.1) is safe for the dev's bench unit
but not for a shipped one: it's plaintext in flash, the same token on every
unit, and rotation needs a reflash. ADR-005 decided the auth model but left
provisioning mechanics open.

Capture that as ADR-011 (Proposed/Open): the options (build-time bake →
on-device paste → eFuse-encrypted NVS, per-device fine-grained PAT, GitHub
App) and the likely shape, deferred beyond v0.1. It gates the first non-dev
distribution. Point the Spike 7 postmortem's shortcut entry at it.
2026-07-07 00:03:55 +02:00
Julien Calixte
2f2f1227ec docs(technical): rewrite git module section for libgit2
The v0.1 technical doc still described the gitoxide/gix plan with an
undecided transport and a 32 KB git_task stack. Bring it in line with
what spike 7 proved:

- gix → libgit2 via the git2 crate (ADR-004 kill-switch fired: no gix push)
- transport settled: HTTPS + PAT over esp-idf mbedTLS, no custom transport
  or reqwest/rustls layer needed
- fail-closed cert verification (embedded GitHub roots + PASSTHROUGH)
- git_task stack 32 KB → 96 KB (measured ~67 KB depth); dedicated thread
- persistent-clone + fast-forward is the product flow (spike used a fresh
  per-boot throwaway branch); add --all stages deletions
- PAT via libgit2 credential callback, never logged/persisted

Also mark the Spike 7 entry done in the spikes list.
2026-07-06 23:52:02 +02:00
Julien Calixte
d397b31ca4 docs(postmortems): mark dedicated git task done
Git now runs on its own 96 KB std::thread and the main-task stack is back
to 12 KB — hardware-verified off-main. Update the follow-up checklist and
the "three bugs" caveat to reflect the completed move.
2026-07-06 23:46:55 +02:00