diff --git a/scripts/stage-frank-dragoon-eval.sh b/scripts/stage-frank-dragoon-eval.sh new file mode 100755 index 0000000..637f5b9 --- /dev/null +++ b/scripts/stage-frank-dragoon-eval.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash +# stage-frank-dragoon-eval.sh — rebuild the /tmp/halogen-eval staging dir that +# battery-frank-dragoon.py reads. /tmp is tmpfs, so EVERY REBOOT deletes the +# corpus and the probe image (learned the hard way on 2026-10-18, mid A/B). +# +# Run on Dankclaw through a login shell: uv lives in ~/.local/bin, which a +# bare `ssh host script` does not put on PATH. +# ssh dankclaw 'bash -lc "/home/dank/serverAppConfigs/scripts/stage-frank-dragoon-eval.sh"' +# +# The corpus is the wikitext-2 raw test split with blank lines removed and the +# rows joined by single newlines (2,891 lines). battery.py sizes its haystacks +# in CHARACTERS (CPT 4.33), so the byte count IS the identity check across two +# boots: 1287656 B. If that number changes, the two boots are not comparable. +set -euo pipefail +STAGE=/tmp/halogen-eval +mkdir -p "$STAGE" +cd "$STAGE" + +if [ ! -s wikitext-2-raw-test.txt ]; then + uv run --quiet --with pyarrow python3 - <<'PY' +import pathlib, urllib.request +import pyarrow.parquet as pq + +raw = pathlib.Path("test.parquet") +url = ("https://huggingface.co/datasets/wikitext/resolve/main/" + "wikitext-2-raw-v1/test-00000-of-00001.parquet") +if not raw.exists() or raw.stat().st_size < 1_000_000: + urllib.request.urlretrieve(url, raw) + +lines = [] +for text in pq.read_table(raw).column("text").to_pylist(): + lines.extend(ln for ln in text.split("\n") if ln.strip()) +out = pathlib.Path("wikitext-2-raw-test.txt") +out.write_text("\n".join(lines) + "\n") +print("lines", len(lines), "bytes", out.stat().st_size) +PY +fi + +if [ ! -s red512.b64 ]; then + uv run --quiet python3 - <<'PY' +import base64, struct, zlib + +def chunk(tag, data): + body = tag + data + return struct.pack(">I", len(data)) + body + struct.pack(">I", zlib.crc32(body) & 0xFFFFFFFF) + +w = h = 512 +rows = b"\x00" + b"\xdc\x32\x32" * w # filter 0 + solid color per pixel +png = (b"\x89PNG\r\n\x1a\n" + + chunk(b"IHDR", struct.pack(">IIBBBBB", w, h, 8, 2, 0, 0, 0)) + + chunk(b"IDAT", zlib.compress(rows * h, 6)) + + chunk(b"IEND", b"")) +open("red512.b64", "wb").write(base64.b64encode(png)) +print("png bytes", len(png), "b64", len(base64.b64encode(png))) +PY +fi + +# battery.py reads the corpus and the PNG at import time; ship it here so one +# command restores the whole stage. +cp -f "$(dirname "$(readlink -f "$0")")/battery-frank-dragoon.py" battery.py +chmod +x battery.py + +# The 51.2 GB n-gram table is page cache (Pin::None). A reboot leaves it cold, +# and a cold table throttles prefill — warm it before any measurement. +if [ "${WARM:-0}" = 1 ]; then + time cat /home/dank/models/halogen-v2-abliterated/qwen38-flash-next-ngram.hgn >/dev/null +fi + +ls -l "$STAGE" | sed -n '1,8p'