Proves add -> commit -> push over HTTPS+PAT via libgit2 (git2), the ADR-004 fallback after gitoxide was found to lack HTTP(S) push. Host crate on stable, kept out of the xtensa firmware tree.
Spike 7 — git push (desktop half)
Bring-up spike 7 in
../../docs/v0.1-mvp-technical.md. Decision context: ADR-004 (git impl) and ADR-005 (auth). Full write-up:../../docs/postmortems/2026-07-05-spike7-gix-https-push.md.
Spike 7 proves the add → commit → push sequence the on-device git module
will run. Per the technical doc it's desktop-Rust first, then on device —
this crate is the desktop half. It is a host program (plain stable
toolchain), deliberately kept out of the xtensa-pinned firmware/ crate.
Headline finding: the ADR-004 kill-switch fired
Spike 7 is the documented kill-switch for ADR-004: "if
[gix smart-HTTP push] fails on the device, we fall back to libgit2-sys."
It fires at the library level, before any device work: gitoxide's own
crate-status doc states gix supports push only over file:// and ssh:// —
push over HTTP(S) is not implemented (only clone/fetch are). Since
ADR-005 fixes auth as HTTPS + PAT, gix cannot satisfy the
push path today. So this spike uses the fallback the risk table names:
libgit2 via the git2 crate.
What it does
Mirrors the v0.1 git module contract:
- open the working copy
- stage with
git add --allsemantics (deletions propagate — needed for v0.5 file-delete) - short-circuit when nothing is staged → "nothing to publish"
- commit; author from config, message = an ISO-8601 timestamp (the time is the message)
- push
HEADtoorigin/<branch>over HTTPS, PAT in the credential callback (never logged) - on push rejection (remote moved): fetch +
pull --no-edit(fast-forward or a clean merge), then retry the push once; merge conflicts are fatal (surfaced, never auto-resolved)
Verified (2026-07-05)
Run live against a local file:// bare remote (no credentials):
-
first commit + push from an unborn
HEAD→ lands in origin ✅ -
nothing to publish short-circuits when the index matches
HEAD✅ -
divergence: a second clone advances origin → push rejected →
pull --no-editmerges cleanly → retry push succeeds, origin gets a two-parent merge commit ✅ -
real HTTPS + PAT push to github.com — confirmed 2026-07-05 against
jcalixte/typoena-test:committed → push accepted by remote, the commit landed on GitHub. Thegit2build linksopenssl-sysfor the TLS transport.
Still not exercised: a non-fast-forward rejection over HTTPS (the
push_update_reference callback path) — the local file:// transport surfaced
rejection as a push() error instead, and the GitHub push above was a clean
fast-forward. The callback path is coded for but unproven live.
Not proven here (the next gate)
The risk moved with the kill-switch: can libgit2 cross-compile to
xtensa-esp32s3-espidf against esp-idf's mbedtls? — the exact C cross-compile
pain gix was chosen to avoid. That is the next on-device spike, and it also
needs PSRAM (CONFIG_SPIRAM) enabled and a working SD card (Spike 3) for the
/sd/repo working copy. This desktop pass de-risks the API + git mechanics
only.
Run
Local remote — proves the mechanics, no secrets:
mkdir -p /tmp/s7 && cd /tmp/s7
git init -q --bare origin.git && git clone -q origin.git work
echo hi > work/notes.md
cargo run --manifest-path <this-crate>/Cargo.toml -- "$PWD/work"
Real GitHub repo — proves HTTPS + PAT (use a throwaway repo + a repo-scoped
fine-grained PAT):
cp .env.example .env # fill TW_GH_USER / TW_PAT / TW_REPO_PATH
set -a; . ./.env; set +a
cargo run -- "$TW_REPO_PATH"
TW_REPO_PATH must be a clone whose origin is the HTTPS URL (or set
TW_REMOTE_URL to point origin there). The PAT is passed to libgit2's
credential callback and never printed.