live: heartbeat sync 2026-10-19T15:24:41-07:00 (Refs #11)

This commit is contained in:
Frank committed 2026-10-19 15:24:41 -07:00
1 parent 6e3e5594eb
commit c14c64d6c0
12 files changed
+452 -129

No files matched your search

@@ -0,0 +1,56 @@
---
name: dankvoice-bundle-swap-red-proof
description: "Prove a dankvoice behavior test is red-before/green-after by pointing DV_EXT at the previously committed dist bundle, with a pinned scratch fixture dir."
---
Use when a new black-box `tests/behavior.bats` assertion in dankvoice must be shown to be red-capable (fails on the pre-change code) without `git stash`/worktree juggling, or when the old bundle must be compared to the new one.
## Why
The bats suite drives `dist/index.js` only (nothing imports `src/`), and the bundle is self-contained. So the *previous commit's* behavior is one `git show` away: write it to a file, point `DV_EXT` at it, run the same driver, and read the same `PLAYS n` / `CALL` / `NOTIFY` lines the test asserts.
## Procedure
1. Build the new bundle and export the old one:
```bash
cd ~/Projects/<dankvoice-checkout>
bun run build >/dev/null 2>&1
git show HEAD:dist/index.js > /tmp/old-dist.js
```
2. Stand up the fixtures in a **pinned** scratch dir — never `$(ls -dt /tmp/tmp.* | head -1)`: other live sessions on the box create `tmp.*` dirs continuously, and a glob picks *theirs*, which is how a red-proof silently becomes "Module not found" and then a false `PLAYS 0`.
```bash
W=/tmp/dv-redproof; rm -rf "$W"; mkdir -p "$W/bin"
```
3. Copy the **real** player stub, not a simplification. The driver counts plays from the stub log; a stub that only `sleep`s records nothing and reports `PLAYS 0` for every build, red and green alike. Mirror `setup()` in `tests/behavior.bats`:
```bash
cat > "$W/player.sh" <<'SH'
#!/usr/bin/env bash
printf '%s\n' "$*" >> "$DV_STUB_LOG"
for arg in "$@"; do case "$arg" in *.wav) cp "$arg" "$DV_COPY" ;; esac; done
sleep "${DV_HOLD:-0.1}"
SH
chmod +x "$W/player.sh"
ln -s "$W/player.sh" "$W/bin/pw-play" # PATH fallback player
printf '#!/usr/bin/env bash\nprintf "116\\talsa_output.usb-KT.0\\taudio/sink\\t*\\n"\n' > "$W/bin/wpctl"
chmod +x "$W/bin/wpctl"
sed -n '86,408p' tests/behavior.bats > "$W/driver.ts" # the inline heredoc driver
```
(Re-check those line bounds against the current file; the driver lives inside `setup()`.)
4. Export the env the driver expects and run old vs new against the SAME scenario:
```bash
export DV_STUB="$W/player.sh" DV_STUB_LOG="$W/player.log" DV_COPY="$W/played.wav" \
DV_OMPCONFIG=/dev/null DANKVOICE_CONFIG="$W/settings.json" DV_MODELS="$W/models.yml" DV_WPCTL=x
for ext in /tmp/old-dist.js "$PWD/dist/index.js"; do
rm -f "$W/player.log"
DV_EXT="$ext" DV_PLAYER_BIN="$W/no-such-player" bun "$W/driver.ts" speak | grep -E '^PLAYS|^NOTIFY'
done
```
The driver sets its own fixture server URL and prepends `dirname "$DV_STUB")/bin` to `PATH` (see its `DANKVOICE_*` block), so the discovered-player fallback has somewhere real to land.
5. Add a **control**: same scenario with a valid player path. Old-vs-new differences that the control also shows are harness bugs, not behavior changes.
## Reading the result
- old `PLAYS 0` + new `PLAYS 1` + control `PLAYS 1` → the assertion is red-capable and the fix is real.
- identical results old vs new → the harness is lying (stub too thin, wrong scratch dir, or the scenario never reaches the changed path). Fix the harness before believing any green.
- File-mode assertions: pre-seed the file with the *old* mode (`printf … > file; chmod 644 file`) — a fresh write with `mode:` in `writeFileSync` only applies at creation, so a fresh file can look green while the old code is equally green.
## Gotchas
- Never poll the bats suite while doing this; `setup()` runs `bun run build`, so a concurrent `src/` edit gets compiled into someone else's run (see `dankvoice-bats-serialization`).
- `bun run build` does not typecheck; a stale identifier reference survives bundling and only fails at runtime — the suite, not the build, is the gate.