#!/usr/bin/env bash # Chained after the 4B rung: generate its voice arms so the rung is readable the # moment it lands, rather than needing a second round trip to become informative. # # Two arms, because the base control is what earns the claim: at 1.7B the adapter # took curly quotes from 0/18 to 15/18 and that number only means something because # the 0/18 came from the SAME carrier. Same nine prompts, same two seeds, same # sampler as both earlier rungs, plus the operator's own Abernathy frame prompt. # # ⚠ Gated on the 4B run having actually produced an adapter -- a chain that fires on # failure turns one lost run into two. set -uo pipefail PREV=/home/infra-ops/r49-runs/h02-4b-1ep OUT=/home/infra-ops/r49-runs/voice-test-4b V=/home/infra-ops/ml/.venv/bin/python exec >> /home/infra-ops/r49-runs/chain-4b-voicetest.log 2>&1 echo "=== $(date -Is) armed, waiting on $PREV" while [ -f "$PREV/run.pid" ] && kill -0 "$(cat "$PREV/run.pid")" 2>/dev/null; do sleep 60; done echo "=== $(date -Is) 4B run finished" [ -f "$PREV/adapter/adapter_model.safetensors" ] || { echo "=== REFUSING: no adapter, the 4B run did not succeed"; exit 1; } cd /home/infra-ops/r49-prep for spec in "4b-base::" "4b-tuned::--adapter $PREV/adapter"; do arm="${spec%%::*}"; extra="${spec##*::}" for pf in voice_prompts.json abernathy.json; do tag=$([ "$pf" = "abernathy.json" ] && echo "-abernathy" || echo "") $V gen_voice_test.py --base /home/infra-ops/carriers/Qwen3-4B-Base $extra \ --arm "$arm" --prompts "$pf" --out "$OUT/${arm}${tag}.jsonl" done done echo "=== $(date -Is) voice arms written to $OUT"