docs(qfd): align with v0.1 refresh, ADR-010, and CONTEXT.md

- Re-anchor W1..W4 source links to the renumbered v0.1 user stories
  (story 1 "First run" was deleted in the v0.1 refresh).
- W2 now points at ADR-010 and CONTEXT.md as well as the product spec.
- W4 reframed from "first-run setup" to "one-shot provisioning, never
  repeated mid-session" so it covers both the v0.1 build-time path and
  the v0.9 on-device path.
- ADR-005 tradeoff row rewritten: "captive-portal form" was wrong after
  the v0.1 refresh; replaced with the binary-as-secret-store framing.
- New ADR-010 row in the tradeoffs table.
- Read-across notes flag that C12 owns ADR-010's implementation but not
  its UX contract, and that C11 LittleFS is unused in v0.1.
- Section 8 picks up three new cross-doc inconsistencies that were
  spotted and fixed during the refresh (commit-message format mismatch,
  captive-portal vs. solo target user, vocabulary leak resolved by
  CONTEXT.md).
This commit is contained in:
Julien Calixte
2026-05-14 20:40:30 +02:00
parent 7055d01e9d
commit 22aeb449e3

View File

@@ -9,7 +9,9 @@ Scope: v0.1 MVP — see
[`v0.1-mvp-product.md`](v0.1-mvp-product.md) for user-facing scope and
[`v0.1-mvp-technical.md`](v0.1-mvp-technical.md) for implementation —
with the v0.2v1.0 trajectory ([README](../README.md),
[roadmap](roadmap.md)) in mind so we don't paint into a corner.
[roadmap](roadmap.md)) in mind so we don't paint into a corner. Terminology
(e.g. **Tracked**, **Local**, **Save**, **Publish**) follows the project
glossary at [`../CONTEXT.md`](../CONTEXT.md).
Format inspired by the classic House of Quality, kept compact. Strength
weights: **9** strong, **3** medium, **1** weak, blank none.
@@ -23,10 +25,10 @@ What a user (= me) values about the device, with importance weights on a
| ID | Requirement | Weight | Source |
| --- | ------------------------------------------------------- | :----: | ------------------------------------------------------------------------------------------------------------------ |
| W1 | Sub-second visible response to typing | 10 | [product → story 2](v0.1-mvp-product.md#user-stories), [README → UX](../README.md#ux-boundaries-set-by-the-medium) |
| W2 | `Ctrl-G` reliably lands a commit on GitHub | 9 | [product → story 4](v0.1-mvp-product.md#user-stories) |
| W3 | Pulling power never corrupts the file | 10 | [product → story 5](v0.1-mvp-product.md#user-stories), [acceptance](v0.1-mvp-product.md#acceptance-criteria) |
| W4 | One-shot first-run setup, never repeated | 7 | [product → story 1](v0.1-mvp-product.md#user-stories) |
| W1 | Sub-second visible response to typing | 10 | [product → Write](v0.1-mvp-product.md#user-stories), [README → UX](../README.md#ux-boundaries-set-by-the-medium) |
| W2 | `Ctrl-G` reliably **Publishes** to the remote | 9 | [product → Publish](v0.1-mvp-product.md#user-stories), [ADR-010](adr.md#adr-010-publish-ux--atomic-ctrl-g-auto-timestamp-commit-message-no-user-prompt), [CONTEXT → Publish](../CONTEXT.md#user-facing-actions) |
| W3 | Pulling power never corrupts the file | 10 | [product → Recover](v0.1-mvp-product.md#user-stories), [acceptance](v0.1-mvp-product.md#acceptance-criteria) |
| W4 | One-shot provisioning, never repeated mid-session | 7 | [product → Provisioning](v0.1-mvp-product.md#provisioning-build-time-dev-only), [roadmap → v0.9](roadmap.md#v09--robustness--) |
| W5 | Quick boot to a writing cursor | 6 | [product → acceptance](v0.1-mvp-product.md#acceptance-criteria) (≤ 5 s) |
| W6 | Long sessions without crash / lag / drift | 9 | [product → acceptance](v0.1-mvp-product.md#acceptance-criteria) (1 h soak) |
| W7 | Distraction-free, single-purpose surface | 8 | [README → vision](../README.md#vision) |
@@ -218,6 +220,15 @@ Function-to-component matrix (9 strong / 3 medium / 1 weak):
touch it. That's why ADR-004 includes a kill-switch (fall back to
`libgit2-sys` if spike 7 fails). It's also why H9 sits in the top three
priorities — `gitoxide`'s memory profile is the unknown.
[ADR-010](adr.md#adr-010-publish-ux--atomic-ctrl-g-auto-timestamp-commit-message-no-user-prompt)
pins the *shape* of the publish sequence (the `gct` flow); C12 is just the
library that implements it. Changing ADR-010 doesn't change C12's column,
but changing C12 (the kill-switch) does not change ADR-010's user
contract.
- **C11** (LittleFS) is unused in v0.1 — config is build-time. Its non-zero
cells in the matrix describe the v0.9+ shape per
[ADR-007](adr.md#adr-007-storage-split--fat-on-sd-for-working-copy-littlefs-on-flash-for-config),
not v0.1 reality.
- **C2** (std runtime) sits underneath almost everything, but it's the
_enabler_ (H4 boot, H10 binary, H12 Wi-Fi) rather than the bottleneck.
Reversing ADR-001 would force re-deciding ADR-004, ADR-005, ADR-006,
@@ -258,11 +269,12 @@ Plain-language summary of what we accepted in exchange for what.
| Custom widget layer over Ratatui | Dirty-rects aligned to e-ink regions; 200 KB binary back | 500 LoC we own and maintain | ADR-002 |
| 5.79" strip panel over 7.5" page or 10.3" reader | 27 KB framebuffer, fast partial refresh, "Freewrite" UX | Only ~11 visible lines | ADR-003 |
| `gitoxide` over `libgit2-sys` | Pure Rust, modular, no FFI cross-compile pain | Smart-HTTP path is newer; PSRAM profile unproven (spike 7) | ADR-004 |
| HTTPS + PAT over OAuth device-flow or SSH | First-run UX fits in a captive-portal form | Long-lived secret on device; manual rotation in v0.1 | ADR-005 |
| HTTPS + PAT over OAuth device-flow or SSH | Simplest auth that `gitoxide` smart-HTTP already supports | Long-lived secret on device; in v0.1 the PAT is compiled into the binary (dev-only target user makes this acceptable); v0.9 moves it to encrypted NVS | ADR-005 |
| `std::thread` over `embassy` or `tokio` | Boring, debuggable, real stack traces; no exec to tune | ~76 KB total stack across 5 tasks | ADR-006 |
| FAT-on-SD + LittleFS-on-flash split | Desktop can read SD; config survives SD reformat | Two filesystems to manage; FAT's power-loss weakness mitigated by atomic-rename | ADR-007 |
| Wall power for v0.1, battery deferred | Measure real draw before sizing the cell | Tethered MVP; not the final aesthetic | ADR-008 |
| USB host (TinyUSB) over BLE-HID | No radio contention with Wi-Fi during push; keyboard powered from the device | One more USB connector on enclosure | ADR-009 |
| Atomic `Ctrl-G` + auto-timestamp commit message | One key, one outcome; matches the user's existing `gct` workflow; no modal prompt to slow H1 latency | Commit history is timestamp noise; the device may author merge commits the user never sees; reversal would break muscle memory | ADR-010 |
### Conflicts left explicitly _unresolved_ by v0.1
@@ -290,12 +302,31 @@ These are the live tensions we are watching, not deciding harder:
cross-reference the tech doc. The 76 KB figure still fits comfortably
in the ESP32-S3's 512 KB internal SRAM, so no design change — just
documentation accuracy.
- **Commit-message format triple-mismatch.** README said `git commit -m
"wip"`, the v0.1 product doc said `"wip <timestamp>"`, and the user's
actual shell alias (`gct` / `git-commit-timestamp`) uses a pure ISO-8601
timestamp with no `wip` prefix. Resolved by aligning all docs on `gct`
and recording the decision as
[ADR-010](adr.md#adr-010-publish-ux--atomic-ctrl-g-auto-timestamp-commit-message-no-user-prompt).
Pulled the v0.7 roadmap item "Commit message prompt instead of hard-coded
`wip`" — it's now contradicted by ADR-010 and removed.
- **First-run flow vs. target user.** The v0.1 product doc described a
captive-portal first-run, but the same doc names the v0.1 target user as
the dev themselves ("Me. Solo."). Provisioning a solo-dev device through
a captive portal is ceremony without a user. Resolved by switching v0.1
to build-time env-var config (no NVS, no LittleFS, no AP mode); on-device
provisioning is the v0.9 release that introduces non-dev users. Touches
ADR-005, ADR-007, the v0.1 product + technical docs, and the v0.9
roadmap entry.
- **Vocabulary leak.** Earlier docs used "commit" and "push" as if they
were distinct user actions; the gct/ADR-010 model collapses them into a
single user-facing **Publish**. Resolved by introducing
[`CONTEXT.md`](../CONTEXT.md) as the canonical glossary; user-facing text
now uses **Save** and **Publish** only.
No other cross-doc contradictions found between `adr.md`, README, and the
v0.1 product/technical docs at the time of writing. The minor variance
between README's "~12 lines" and product/ADR-003's "~11 lines" of edit
area is within rounding for a 14 px glyph in a 240 px tall edit region
and is not load-bearing.
The minor variance between README's "~12 lines" and product/ADR-003's
"~11 lines" of edit area is within rounding for a 14 px glyph in a 240 px
tall edit region and is not load-bearing.
---