Files
command-center/agent/managed-skills/dankvoice-bundle-swap-red-proof/SKILL.md
T

3.9 KiB

name, description
name description
dankvoice-bundle-swap-red-proof Prove a dankvoice behavior test is red against the pre-change bundle by pointing DV_EXT at git show HEAD:dist/index.js, with the driver extracted from the bats heredoc into a pinned scratch directory. Use before claiming a new bats assertion is red-capable.

Prove a new tests/behavior.bats assertion is red-capable — that it fails against the previous build, not just passes against the new one — without stashing, branching, or editing src/.

Why

tests/behavior.bats is a black-box suite: the plugin bundle is loaded through DV_EXT, so a different bundle is the red side. Stashing the fix would break the dist byte-identity pin test and the shared worktree.

Working recipe

cd ~/Projects/dankvoice                      # or the feature worktree: ~/Projects/wt-dv-*
bun run build                                 # current src = the green side
git show HEAD:dist/index.js > /tmp/old-dist.js # the red side (pre-change bundle)

W=/tmp/dv-redproof                            # PINNED name; see traps below
rm -rf "$W" && mkdir -p "$W/bin"
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"
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"
# The driver lives inside the bats file as a heredoc: extract it verbatim.
end=$(grep -n '^TS$' tests/behavior.bats | cut -d: -f1)
sed -n "86,$((end - 1))p" tests/behavior.bats > "$W/driver.ts"

export DV_EXT="$PWD/dist/index.js" 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 DV_SELECT=""
for ext in /tmp/old-dist.js "$PWD/dist/index.js"; do
  rm -f "$W/player.log" "$DANKVOICE_CONFIG"
  DV_EXT="$ext" bun "$W/driver.ts" <scenario> 2>&1 | grep -E '^PLAYS|^CALLS|^NOTIFY|^SETTINGS'
done

The scenario name is the driver's third argv (speak, auto, repeat, humanizecycle, badurl, …); the bats -f test body's env (DV_PLAYER_BIN, DV_SETTINGS_JSON, DANKVOICE_VERBOSITY, …) is passed the same way. DV_SELECT holds the menu answers, |-separated, consumed in order.

Traps, each one cost a turn

  • The scratch directory must be pinned by name. ls -dt /tmp/tmp.* picks up other sessions' temp dirs, and then player.sh and driver.ts live in different directories — the run silently does the wrong thing.
  • The stub must append to $DV_STUB_LOG. The driver counts player invocations from that file; a stub that only sleeps reports PLAYS 0 for both bundles and the whole proof reads as "fix does nothing".
  • DV_EXT is required. Missing it yields Cannot find package 'undefined' from the driver, which looks like a broken driver, not a missing env var.
  • DV_SETTINGS_JSON supports __PORT__ (the driver substitutes the fixture port), so a preseed can name a prefixed route — needed whenever the test is about which endpoint got resolved.
  • Never run this while a bats run is in flight in the same repo: setup() runs bun run build, so two runs clobber dist/ and the pin test.

Reading the result

Red side must show the defect (PLAYS 0, 644, a chat CALL with the wrong prefix, Invalid URL), green side the fix — assert on printed markers only (PLAYS, CALLS, CALL <url>, NOTIFY, SETTINGS). CALLS counts /audio/speech calls only; the rewrite call appears as its own CALL /…/chat/completions … sys=<full system prompt> line, which is how prompt-level knobs (verbosity, heckle) are observed.

Prefer this over a synthetic leak: if the check already caught a real leftover/failure once, that event is the sensitivity proof — say so in the commit message instead of faking one.