docs: refresh v0.1 spec for gct publish flow and dev-only build-time config
Two coupled changes that emerged from one /deep-design session, both touching
the same v0.1 paragraphs:
(1) Align Ctrl-G with the user's existing gct shell alias: git add . ->
short-circuit if nothing staged -> commit with an ISO-8601 timestamp (no
wip prefix) -> push -> on push failure, git pull --no-edit then retry.
Atomic from the user's view. Recorded as ADR-010. The previously-planned
v0.7 commit-message-prompt item is removed; it contradicts the
gct/timestamp model.
(2) Replace the v0.1 captive-portal first-run with build-time env-var
config: build.rs reads TW_* env vars and embeds them as constants. No
NVS read, no LittleFS mount, no AP mode, no HTTP server. The v0.1
target user is the dev themselves; the first release usable by non-dev
users is v0.9, and the v0.9 settings entry is reframed accordingly.
ADR-005 updated to describe the build-time path and the v0.9 migration.
The two changes share files because the v0.1 spec is one interlocked
document; splitting further would require line-level surgery without
improving auditability.
This commit is contained in:
@@ -146,7 +146,7 @@ gantt
|
||||
| [v0.4](docs/roadmap.md#v04--visual-mode--ex-commands--) | Visual + ex | `v V`, `:w :q :e`, status line. |
|
||||
| [v0.5](docs/roadmap.md#v05--file-palette--multi-file--) | Files | `Ctrl-P` over `/repo` + `/local`, buffers. |
|
||||
| [v0.6](docs/roadmap.md#v06--markdown-affordances--) | Markdown | Headings, list continuation, soft-wrap. |
|
||||
| [v0.7](docs/roadmap.md#v07--search--better-git--) | Search + git | `/`, `:Gpull`, `:Gbranch`, commit msg. |
|
||||
| [v0.7](docs/roadmap.md#v07--search--better-git--) | Search + git | `/`, `:Gpull`, `:Gbranch`. |
|
||||
| [v0.8](docs/roadmap.md#v08--power-battery--sleep--) | Power | 18650 + sleep + lid switch. |
|
||||
| [v0.9](docs/roadmap.md#v09--robustness--) | Robustness | Crash-safe writes, reconnect, settings. |
|
||||
| [v1.0](docs/roadmap.md#v10--polish--) | Polish | Boot ≤ 3 s, fonts, enclosure, guide. |
|
||||
|
||||
61
docs/adr.md
61
docs/adr.md
@@ -211,14 +211,17 @@ on-device, and reasonably secure for a personal appliance.
|
||||
|
||||
### Decision
|
||||
|
||||
**HTTPS + PAT.** Stored in internal LittleFS, encrypted with a key derived
|
||||
from the chip's eFuse so a stolen SD card alone is not enough. Captive
|
||||
portal accepts the PAT during first-run setup.
|
||||
**HTTPS + PAT.** In v0.1 the PAT (and all other config) is compiled into the
|
||||
firmware binary via build-time env vars — the dev's-only-user model makes the
|
||||
binary-as-secret-store acceptable. From v0.9 onward, the PAT moves to
|
||||
encrypted LittleFS with a key derived from the chip's eFuse, so a stolen SD
|
||||
card alone is not enough.
|
||||
|
||||
### Consequences
|
||||
|
||||
- The user must generate a PAT with `repo` scope. Documented in
|
||||
[v0.1 product → first-run flow](v0.1-mvp-product.md#first-run-provisioning-flow).
|
||||
- The user (= dev, in v0.1) must generate a PAT with `repo` scope and supply
|
||||
it as a build-time env var. Provisioning is build-time only — see
|
||||
[v0.1 product → provisioning](v0.1-mvp-product.md#provisioning-build-time-dev-only).
|
||||
- PAT is never logged. Validated in code review.
|
||||
- Rotation in v0.1 = wipe NVS and re-run setup. Proper rotation UI is v0.9
|
||||
— see [roadmap → v0.9](roadmap.md#v09--robustness--).
|
||||
@@ -371,6 +374,54 @@ if TinyUSB host turns out unstable
|
||||
|
||||
---
|
||||
|
||||
## ADR-010: Publish UX — atomic `Ctrl-G`, auto-timestamp commit message, no user prompt
|
||||
|
||||
**Status:** Accepted — 2026-05-14
|
||||
**Scope:** Whole project, all releases.
|
||||
|
||||
### Context
|
||||
|
||||
The device needs an action that ships writing to the git remote. Most
|
||||
git-using tools expose `commit` and `push` as distinct user gestures, often
|
||||
with a commit-message prompt. The device's actual user (= the author of this
|
||||
firmware) already uses the [`gct` shell alias](../CONTEXT.md#user-facing-actions)
|
||||
for their own writing: `git add . && git commit -m "<timestamp>" && git push`,
|
||||
with a `git pull --no-edit` fallback when the push fails non-fast-forward.
|
||||
`gct` is the established workflow; the typewriter mirrors it.
|
||||
|
||||
### Options considered
|
||||
|
||||
| Option | Pros | Cons |
|
||||
| ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Three separate gestures** (save / commit / push) | Maximally git-native; user has fine control. | Three keys to remember, three failure modes to surface, three concepts in the user's head. Wrong shape for an appliance whose job is to remove ceremony. |
|
||||
| **One gesture, prompt for message** (`Ctrl-G` → modal asking for message → commit → push) | Conventional "publish" pattern; each commit is named. | A modal prompt on e-ink is hostile (latency, full refresh); the user's actual workflow (`gct`) explicitly avoids authoring messages; messages would be noise (`"updated notes"` × 1000). |
|
||||
| **One gesture, auto-timestamp message** (`Ctrl-G` mirrors `gct`) | Matches the user's real workflow; one key, one outcome; no prompts, no modes, no decisions in the writing path. | Commit history is timestamp-noise (useless for code archaeology); a future reader will wonder where the commit messages went; locks in a UX assumption that's hard to undo without breaking muscle memory. |
|
||||
|
||||
### Decision
|
||||
|
||||
**One gesture, auto-timestamp message, atomic from the user's view.** `Ctrl-G`
|
||||
runs the full `gct` sequence (stage all → short-circuit if nothing staged →
|
||||
commit with ISO-8601 timestamp → push → on push failure, `pull --no-edit` then
|
||||
retry). Failure surfaces as a single retry-able outcome in the status line.
|
||||
|
||||
### Consequences
|
||||
|
||||
- The user's vocabulary collapses to **Save** and **Publish**;
|
||||
[`CONTEXT.md`](../CONTEXT.md#user-facing-actions) pins this — *commit* is
|
||||
not a user-facing term.
|
||||
- Commit history is a stream of timestamps. The device is a writing tool, not
|
||||
a code repository — the history is here for recoverability, not narrative.
|
||||
- The pull-merge-retry path means the device may author merge commits on the
|
||||
user's behalf, with git's default merge message. Acceptable: the user
|
||||
doesn't read commit history from the device anyway.
|
||||
- The previously-planned "commit message prompt" item in v0.7 has been
|
||||
removed from the roadmap.
|
||||
- Reversing this later (introducing message prompts) would change the
|
||||
semantics of `Ctrl-G` and break the user's muscle memory. Hard-to-reverse
|
||||
by design.
|
||||
|
||||
---
|
||||
|
||||
## How to add a new ADR
|
||||
|
||||
1. Append a new `## ADR-NNN: <title>` section to this file.
|
||||
|
||||
@@ -17,9 +17,11 @@ The minimum thing that justifies the hardware existing. Full design:
|
||||
- [ ] Insert-only editing (no modes yet), backspace, enter, arrow keys
|
||||
- [ ] Line wrap, no line numbers yet
|
||||
- [ ] Save on `Ctrl-S` → SD
|
||||
- [ ] Wi-Fi credentials via captive portal on first boot, stored in NVS
|
||||
- [ ] `Ctrl-G` runs: `git add notes.md && git commit -m "wip" && git push` to a
|
||||
pre-configured remote, using a PAT entered during setup
|
||||
- [ ] 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 →
|
||||
`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
|
||||
|
||||
Out of scope: Vim, palette, multiple files, branches, conflict handling.
|
||||
@@ -52,6 +54,9 @@ Out of scope: Vim, palette, multiple files, branches, conflict handling.
|
||||
- [ ] `:e` and palette share the same recent-files list
|
||||
- [ ] `:enew` creates a new file — prompts for scope (tracked vs local)
|
||||
- [ ] `Ctrl-G` is disabled / hidden when the current buffer is local-scope
|
||||
- [ ] Status line briefly shows file count on `Ctrl-G` when 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 — [ ]
|
||||
|
||||
@@ -65,7 +70,6 @@ Out of scope: Vim, palette, multiple files, branches, conflict handling.
|
||||
- [ ] `/` forward search, `n N`
|
||||
- [ ] `:Gpull` (fetch + fast-forward only; refuse on conflict and surface it)
|
||||
- [ ] `:Gbranch` to switch branches; refuse with dirty tree
|
||||
- [ ] Commit message prompt instead of hard-coded `"wip"`
|
||||
|
||||
## v0.8 — Power: battery + sleep — [ ]
|
||||
|
||||
@@ -81,7 +85,9 @@ Out of scope: Vim, palette, multiple files, branches, conflict handling.
|
||||
- [ ] Recover from interrupted push (re-attempt on next save)
|
||||
- [ ] SD card removal / reinsert handling
|
||||
- [ ] Wi-Fi reconnect with backoff
|
||||
- [ ] Settings screen: SSID, PAT rotation, default remote, commit author
|
||||
- [ ] 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 — [ ]
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
## One-line summary
|
||||
|
||||
Boot the device, type into one file, hit `Ctrl-S` to save, hit `Ctrl-G` to
|
||||
push it to GitHub. That's the entire product surface.
|
||||
publish it to GitHub. That's the entire product surface.
|
||||
|
||||
## Target user
|
||||
|
||||
@@ -22,62 +22,49 @@ the loop closes end to end.
|
||||
|
||||
## User stories
|
||||
|
||||
1. **First run.** I plug in the device for the first time. It walks me through
|
||||
Wi-Fi setup, asks for a GitHub Personal Access Token and a repository URL,
|
||||
and stores them. I never want to do this step twice.
|
||||
|
||||
2. **Write.** I open the lid (= plug in power). Within a few seconds the
|
||||
1. **Write.** I open the lid (= plug in power). Within a few seconds the
|
||||
screen shows my `notes.md` file. I start typing. What I type appears on
|
||||
screen with sub-second latency.
|
||||
|
||||
3. **Save.** I hit `Ctrl-S`. The file on SD is updated. A short status flash
|
||||
2. **Save.** I hit `Ctrl-S`. The file on SD is updated. A short status flash
|
||||
confirms it.
|
||||
|
||||
4. **Push.** I hit `Ctrl-G`. The device commits and pushes to GitHub. The
|
||||
status line shows progress; if it succeeds, the commit hash is briefly
|
||||
shown. If it fails, I see why.
|
||||
3. **Publish.** I hit `Ctrl-G`. The device ships my latest changes to GitHub
|
||||
atomically — if the remote has moved on, it merges in (no-edit) and pushes
|
||||
again, so I only see one outcome. If it succeeds, a short hash is briefly
|
||||
shown. If it fails, I see why and I can retry.
|
||||
|
||||
5. **Recover.** Power gets pulled mid-edit. I plug it back in. My file is at
|
||||
4. **Recover.** Power gets pulled mid-edit. I plug it back in. My file is at
|
||||
the last saved state — I lose unsaved changes, but the file isn't
|
||||
corrupted.
|
||||
|
||||
That's it. No other stories ship in v0.1.
|
||||
|
||||
## First-run provisioning flow
|
||||
## Provisioning (build-time, dev-only)
|
||||
|
||||
```
|
||||
[POWER ON, no config in NVS]
|
||||
│
|
||||
▼
|
||||
Splash: "typewriter v0.1 — first-run setup"
|
||||
│
|
||||
▼
|
||||
Wi-Fi: device starts AP "typewriter-setup"
|
||||
Screen shows: SSID, password, http://192.168.4.1
|
||||
│
|
||||
▼
|
||||
User connects from phone/laptop, enters:
|
||||
• home Wi-Fi SSID + password
|
||||
• git remote URL (HTTPS)
|
||||
• GitHub username
|
||||
• GitHub PAT (with `repo` scope)
|
||||
• commit author name + email
|
||||
│
|
||||
▼
|
||||
Device validates: connects to Wi-Fi, clones the repo into /sd/repo
|
||||
│
|
||||
▼
|
||||
Screen: "ready. opening notes.md"
|
||||
│
|
||||
▼
|
||||
[STEADY STATE]
|
||||
```
|
||||
v0.1 has **no on-device provisioning** — no captive portal, no in-editor
|
||||
wizard, no NVS config file, no LittleFS config. The device is the dev's own
|
||||
machine (see [Target user](#target-user)); config is baked into the firmware
|
||||
at build time:
|
||||
|
||||
If the clone fails (bad PAT, no `notes.md` in the repo, etc.), the screen
|
||||
shows the error and offers retry. The repo is expected to already exist on
|
||||
GitHub and contain (or be willing to contain) `notes.md` — v0.1 does not
|
||||
create remote repos. Auth model rationale:
|
||||
[ADR-005](adr.md#adr-005-auth--https--github-personal-access-token).
|
||||
- Wi-Fi SSID + password, git remote URL, GitHub username, PAT, and commit
|
||||
author name + email are read by `build.rs` from environment variables (or
|
||||
a `.env` file gitignored locally) and embedded as `const &'static str`s in
|
||||
the binary.
|
||||
- The dev clones the git working copy onto the SD card from their laptop
|
||||
(`git clone` directly onto the mounted SD), so `/sd/repo/notes.md` is
|
||||
present at first boot.
|
||||
- Re-configuring = re-build + re-flash. For a single-dev MVP, that's fine.
|
||||
|
||||
If the firmware boots and finds no `/sd/repo` or no `/sd/repo/notes.md`, it
|
||||
shows a one-line error on the splash and stops. No recovery flow ships in
|
||||
v0.1 — the dev re-mounts the SD and reboots.
|
||||
|
||||
On-device provisioning UI (Wi-Fi captive portal, PAT rotation, settings
|
||||
screen) lands in v0.9 when the first non-dev user becomes a concern; at that
|
||||
point the constants migrate to NVS-on-LittleFS per
|
||||
[ADR-007](adr.md#adr-007-storage-split--fat-on-sd-for-working-copy-littlefs-on-flash-for-config).
|
||||
Auth model rationale: [ADR-005](adr.md#adr-005-auth--https--github-personal-access-token).
|
||||
|
||||
## Steady-state flow
|
||||
|
||||
@@ -96,10 +83,12 @@ create remote repos. Auth model rationale:
|
||||
├── Ctrl-S → write file, full refresh, status: "saved 14:02"
|
||||
│
|
||||
└── Ctrl-G → save if dirty, then:
|
||||
git add notes.md
|
||||
git commit -m "wip <timestamp>"
|
||||
git add .
|
||||
(if nothing staged: status "nothing to publish", stop)
|
||||
git commit -m "<ISO-8601 timestamp>"
|
||||
git push
|
||||
status: "pushed abc1234" or "push failed: <reason>"
|
||||
└─ on failure: git pull --no-edit, retry push
|
||||
status: "published abc1234" or "publish failed: <reason>"
|
||||
```
|
||||
|
||||
## Screen layout
|
||||
@@ -150,9 +139,10 @@ don't fight it.
|
||||
| Failure | What the user sees |
|
||||
| ----------------------------------------------------- | ------------------------------------------------------------------------ |
|
||||
| No SD card on boot | "no SD card — insert one and reboot" |
|
||||
| SD card mounted but `/sd/repo` missing | drop back into first-run setup |
|
||||
| SD card mounted but `/sd/repo` missing | "missing /sd/repo — re-provision and reboot" (dev re-clones onto SD) |
|
||||
| Wi-Fi credentials wrong (build-time env vars) | status shows `Wi-Fi ✗`; dev rebuilds with correct env vars and re-flashes |
|
||||
| Wi-Fi won't connect | status shows `Wi-Fi ✗`; editing still works; `Ctrl-G` shows "no network" |
|
||||
| `Ctrl-G` push rejected (auth, non-fast-forward, etc.) | status shows reason; commit stays local; user can retry |
|
||||
| `Ctrl-G` publish fails (auth, network, merge conflict)| status shows reason; local commit is preserved; user can retry — non-fast-forward auto-recovers via pull-then-push and is not surfaced as a failure unless the pull itself conflicts |
|
||||
| File write fails | status flashes "save failed"; buffer stays dirty |
|
||||
| Keyboard disconnects | header shows `⌨ ✗`; editing pauses; reconnects automatically |
|
||||
|
||||
@@ -169,11 +159,13 @@ Explicitly **not** in this release, to keep it shippable:
|
||||
- Branches. Always on whatever branch was cloned (default).
|
||||
- `git pull`. Manual recovery if the remote diverges.
|
||||
- Conflict handling.
|
||||
- Commit message editing — always `"wip <timestamp>"`.
|
||||
- Commit message editing — always an ISO-8601 timestamp, no user prompt ever
|
||||
(see [`gct`](../CONTEXT.md#user-facing-actions)).
|
||||
- Battery. Wall power only.
|
||||
- Sleep / lid-close behaviour.
|
||||
- Font selection.
|
||||
- Settings UI after first-run (re-flash or wipe NVS to reconfigure).
|
||||
- On-device provisioning UI (captive portal, wizard, settings screen). v0.1 is
|
||||
provisioned out-of-band from the dev's laptop; users are a v0.9 concern.
|
||||
- Markdown rendering (headings, bold, etc.) — plain text rendering of MD.
|
||||
- Search.
|
||||
|
||||
@@ -184,14 +176,14 @@ to an engineering function with a measured target in
|
||||
[qfd.md §6](qfd.md#6-critical-performance-budget); that's the
|
||||
place to check before declaring an item done.
|
||||
|
||||
- [ ] First-run setup completes in under 5 minutes including typing in a PAT.
|
||||
- [ ] After a cold boot with valid config, cursor is ready in ≤ 5 s.
|
||||
- [ ] After a cold boot with valid pre-flashed config, cursor is ready in ≤ 5 s.
|
||||
- [ ] Typing a 1000-word paragraph never drops a keystroke and never lags
|
||||
more than 300 ms behind the keyboard.
|
||||
- [ ] `Ctrl-S` durably writes the file (verified by power-cycling immediately
|
||||
after the status confirms save — file is intact).
|
||||
- [ ] `Ctrl-G` produces a commit visible on github.com within 30 s on a
|
||||
typical home Wi-Fi.
|
||||
typical home Wi-Fi (including the pull-then-retry path when the remote
|
||||
has moved on since the last publish).
|
||||
- [ ] Pulling power during typing never corrupts the file; the previous saved
|
||||
state is recoverable.
|
||||
- [ ] One hour of continuous typing without crash, freeze, or memory
|
||||
|
||||
@@ -45,7 +45,7 @@ blocked by I/O.
|
||||
| Task | Core | Stack | Responsibility |
|
||||
| ------------- | ---- | ----- | -------------------------------------------------------- |
|
||||
| `usb_task` | 0 | 8 KB | TinyUSB host loop, decode HID reports, post `KeyEvent`s |
|
||||
| `wifi_task` | 0 | 8 KB | Provisioning AP or station mode; expose status |
|
||||
| `wifi_task` | 0 | 8 KB | Station mode only (no provisioning AP); expose status |
|
||||
| `ui_task` | 1 | 16 KB | Consume `KeyEvent`s, mutate editor state, enqueue render |
|
||||
| `render_task` | 1 | 12 KB | Drain render queue, do partial/full refresh on EPD |
|
||||
| `git_task` | 1 | 32 KB | Triggered by `Ctrl-G`; runs gitoxide commit + push |
|
||||
@@ -60,11 +60,10 @@ read snapshot (render diff).
|
||||
```
|
||||
1. ROM → bootloader → app_main
|
||||
2. Init PSRAM allocator, set as default for large alloc
|
||||
3. Mount LittleFS on internal flash → read /nvs/config.toml
|
||||
├─ no config → enter PROVISIONING mode
|
||||
└─ config OK → continue
|
||||
4. Mount FAT on SD → verify /sd/repo exists
|
||||
├─ missing → enter PROVISIONING mode (clone)
|
||||
3. Config is compiled into the binary (`build.rs` reads env vars) — no
|
||||
filesystem read needed for it. LittleFS is unused in v0.1.
|
||||
4. Mount FAT on SD → verify /sd/repo and /sd/repo/notes.md exist
|
||||
├─ missing → fatal: "missing /sd/repo — re-mount SD and reboot"
|
||||
└─ present → continue
|
||||
5. Init SPI bus (shared: EPD + SD on different CS)
|
||||
6. Init EPD, full refresh: splash + boot log
|
||||
@@ -125,7 +124,7 @@ stack decision (e.g. fall back to libgit2; switch to a separate SD SPI bus).
|
||||
| `←` `→` `↑` `↓` | move cursor (visual lines for ↑↓) |
|
||||
| `Home` `End` | line start / end |
|
||||
| `Ctrl-S` | save |
|
||||
| `Ctrl-G` | save (if dirty) + commit + push |
|
||||
| `Ctrl-G` | publish (save → stage → commit → push, with pull-and-retry on remote divergence) |
|
||||
|
||||
Anything else is ignored in v0.1.
|
||||
|
||||
@@ -178,21 +177,44 @@ PSRAM heap during push is a top-3 watched metric — see
|
||||
- `gix` with the smart-HTTP transport backed by `esp-idf` mbedtls (via a
|
||||
custom transport impl, or `gix-transport` with `reqwest`+`rustls-mbedtls`
|
||||
if that path is cleaner — decided in spike 7).
|
||||
- Operations needed in v0.1:
|
||||
- Operations needed in v0.1 (the [`gct` shell function](../CONTEXT.md#user-facing-actions) is the reference):
|
||||
- `gix::open` the existing working copy at `/sd/repo`
|
||||
- stage `notes.md` (`gix::index` add)
|
||||
- commit with author from config, message `"wip <ISO-8601 timestamp>"`
|
||||
- stage everything under the working copy (`git add .` equivalent)
|
||||
- short-circuit return if nothing is staged — status: "nothing to publish"
|
||||
- commit with author from config, message `"<ISO-8601 timestamp>"` (no `wip`
|
||||
prefix; the timestamp *is* the message)
|
||||
- push HEAD to `origin/<current branch>`
|
||||
- on push failure: `git pull --no-edit` (merge), then retry the push once.
|
||||
Only surface failure to the status line if the pull conflicts or the
|
||||
second push also fails.
|
||||
- The PAT is loaded into the Authorization header per request; never logged.
|
||||
- Push errors propagate as a string back to the status line.
|
||||
- The whole sequence is atomic from the user's view — see
|
||||
[`CONTEXT.md` → Publish](../CONTEXT.md#user-facing-actions).
|
||||
|
||||
### `provisioning` — first-run wizard
|
||||
### Provisioning — build-time only (no module on device)
|
||||
|
||||
- Triggered when `config.toml` is absent OR `/sd/repo` is absent.
|
||||
- Captive portal posts a JSON blob; device validates by:
|
||||
1. Connecting to the supplied Wi-Fi credentials.
|
||||
2. Cloning the supplied repo URL into `/sd/repo` using the supplied PAT.
|
||||
- Only on both successes does it persist config and reboot into steady state.
|
||||
v0.1 has **no provisioning module, no NVS config, no LittleFS mount**. All
|
||||
config (Wi-Fi creds, remote URL, GitHub user, PAT, commit author) is supplied
|
||||
as environment variables at build time:
|
||||
|
||||
```sh
|
||||
export TW_WIFI_SSID=... TW_WIFI_PASS=...
|
||||
export TW_REMOTE_URL=... TW_GH_USER=... TW_PAT=...
|
||||
export TW_AUTHOR_NAME=... TW_AUTHOR_EMAIL=...
|
||||
cargo espflash --release
|
||||
```
|
||||
|
||||
`build.rs` reads these (or fails the build) and emits constants the runtime
|
||||
references directly. The `.env` file used to source these is gitignored.
|
||||
|
||||
The git working copy is set up out-of-band: the dev clones the remote onto
|
||||
the mounted SD card from their laptop. There is no "first clone on device"
|
||||
in v0.1.
|
||||
|
||||
Net savings vs. an on-device wizard: ~300–500 LoC of firmware (HTTP server,
|
||||
captive AP, form parsing, validation state machine, NVS read/write, TOML
|
||||
parser). On-device provisioning + NVS-backed config land in v0.9 when
|
||||
non-dev users enter the picture.
|
||||
|
||||
## Memory plan
|
||||
|
||||
|
||||
Reference in New Issue
Block a user