#!/usr/bin/env bash
# gate-w2.sh — doyle's W2 gate at f3c8495b, run SEQUENTIALLY in todlando's released pool
# (.worktrees/ws272-w2/target) from the gate worktree (dir named gate-w2-401a19ad, checked out
# DETACHED at f3c8495b — identity is the ref, never the dir name; ir57).
# Shape = W1's corrected gate-w1d.sh: exit FILES per leg, Summary/panic counts per leg in the
# driver log, disk floor per leg, identity trio + SPT_HOME + hatch scrubbed for every child.
# Legs: claim (ONE hatch-wrapped pool-claim, hatch env set inline for that leg only) · treqs ·
# prebuild fixture bins (cold-pool trap) · check · xtask check · clippy -D warnings · nextest LIST
# with the battery filter (assert the wanted cell NAMES are selected, not a floor) · nextest libs+bins
# --no-fail-fast · the three W2 e2e binaries --no-capture (witness lines print only uncaptured) ·
# mutation arms A / B1 / B2 / C (apply → targeted cells → revert → dirty==0) · local twohost pair
# baseline · cross-box twohost pair baseline (kitsubito clone at f3c8495b, role B owner).
set -u
GW=/c/Users/decid/Documents/projects/spt-core/.worktrees/gate-w2-401a19ad
POOL='C:\Users\decid\Documents\projects\spt-core\.worktrees\ws272-w2\target'
OUT=$GW/.spt/gate-doyle; PAIR=$GW/.spt/twohost-web; mkdir -p "$OUT"; cd "$GW" || exit 9
if ! mkdir "$OUT/lock" 2>/dev/null; then echo "REFUSED: $OUT/lock exists — another battery owns this output dir" >&2; exit 9; fi
trap 'rmdir "$OUT/lock" 2>/dev/null' EXIT
export CARGO_TARGET_DIR="$POOL"
unset OWL_SESSION_ID SPT_AGENT_ID SPT_ENDPOINT_ID SPT_HOME SPT_POOL_UNCHECKED
LOG=$OUT/driver.log
leg() { local n=$1; shift; echo "[$(date -u +%H:%M:%SZ)] LEG $n START" >> "$LOG"; "$@" > "$OUT/$n.raw" 2>&1; local e=$?; echo "$e" > "$OUT/$n.exit"; echo "[$(date -u +%H:%M:%SZ)] LEG $n EXIT $e summaries=$(grep -c 'Summary \[' "$OUT/$n.raw") panics=$(grep -c 'panicked at' "$OUT/$n.raw") free_gb=$(df -BG --output=avail /c 2>/dev/null | tail -1 | tr -dc 0-9)" >> "$LOG"; }
pair_ok() { [ "$(cat "$PAIR/$1/a.exit" 2>/dev/null)" = "0" ] && [ "$(cat "$PAIR/$1/b.exit" 2>/dev/null)" = "0" ]; }
mut() { local arm=$1; shift; python .spt/mutate.py apply "$arm" > "$OUT/mut-$arm.apply" 2>&1 || { echo "[$(date -u +%H:%M:%SZ)] MUTATION $arm REFUSED (see mut-$arm.apply)" >> "$LOG"; return; }
        grep -q 'MUTATION LANDED' "$OUT/mut-$arm.apply" || { echo "[$(date -u +%H:%M:%SZ)] MUTATION $arm did not land" >> "$LOG"; return; }
        "$@"
        python .spt/mutate.py revert "$arm" > "$OUT/mut-$arm.revert" 2>&1; echo "[$(date -u +%H:%M:%SZ)] MUTATION $arm reverted: $(tail -1 "$OUT/mut-$arm.revert")" >> "$LOG"; }

echo "gate-w2 at $(git rev-parse HEAD) dirty_tracked=$(git status --short -uno | wc -l) $(date -u +%FT%TZ) treqs=$(traceable-reqs --version) pool=$POOL" > "$LOG"
echo "procs-before: cargo=$(tasklist | grep -ci '^cargo') nextest=$(tasklist | grep -ci nextest) rustc=$(tasklist | grep -ci '^rustc') env-leak: OWL=${OWL_SESSION_ID:-unset} AGENT=${SPT_AGENT_ID:-unset} EP=${SPT_ENDPOINT_ID:-unset} HATCH=${SPT_POOL_UNCHECKED:-unset}" >> "$LOG"

# (0) ONE hatch-wrapped claim; the hatch is inline to this leg only. Judge by the verdict token up top, never the tail.
leg 0-claim env SPT_POOL_UNCHECKED=1 cargo run -p xtask -- pool-claim --foreign-pool --pool "$POOL" --label gate-w2-f3c8495b
echo "claim verdict: $(grep -m1 -E 'CLAIM|claim|TAKEOVER|REFUS|POOL' "$OUT/0-claim.raw" | head -1)" >> "$LOG"

# (1) statics
leg 1-treqs    traceable-reqs check
leg 2-prebuild cargo build -p spt -p mock-adapter --bins
leg 3-check    cargo check --workspace --all-targets
leg 4-xtask    cargo run -p xtask -- check
leg 5-clippy   cargo clippy --workspace --all-targets -- -D warnings

# (2) the filter is asserted by NAME before it is run (a population floor proves only that it selected SOMETHING)
FILTER='((package(spt-msg) | package(spt-store) | package(spt-daemon)) & kind(lib)) | (package(spt) & (kind(bin) | binary(io_events_undriven_kinds_e2e) | binary(webserve_attachment_e2e) | binary(webserve_cross_node_e2e)))'
leg 6-list cargo nextest list -E "$FILTER"
for want in a_reap_shaped_pass_cannot_clobber_a_concurrent_add a_msg_envelope_is_excerpted_by_its_text_and_other_envelopes_are_untouched \
            a_typed_msg_envelope_still_carries_the_recipients_monic a_typed_user_msg_envelope_is_still_verbatim_and_monicless \
            a_typed_msg_envelope_carries_the_trust_warning a_senders_own_monic_and_warning_are_stripped_before_ours_are_attached \
            the_one_short_id_names_the_message_on_both_edges an_attachment_is_snapshot_served_fetched_back_and_named_by_its_message \
            a_scoped_entry_is_still_served_on_loopback; do
  echo "list-has $want: $(grep -c "$want" "$OUT/6-list.raw")" >> "$LOG"
done
echo "list-has xnode binary: $(grep -c 'webserve_cross_node_e2e' "$OUT/6-list.raw")" >> "$LOG"

# (3) libs + bins in one --no-fail-fast leg (T3 is NOT here — it lives in the ioedges binary); e2e binaries uncaptured, one per leg
leg 7-libsbins cargo nextest run --no-fail-fast -E '((package(spt-msg) | package(spt-store) | package(spt-daemon)) & kind(lib)) | (package(spt) & kind(bin))'
leg 8-ioedges  cargo nextest run --no-fail-fast -p spt --test io_events_undriven_kinds_e2e --no-capture
leg 9-attach   cargo nextest run --no-fail-fast -p spt --test webserve_attachment_e2e --no-capture
leg 10-xnode   cargo nextest run --no-fail-fast -p spt --test webserve_cross_node_e2e --no-capture
for w in 'W2_ARM=one-short-id' 'W2_ARM=fetch-exit3' 'F1_ARM='; do echo "witness $w: ioedges=$(grep -c "$w" "$OUT/8-ioedges.raw") attach=$(grep -c "$w" "$OUT/9-attach.raw") xnode=$(grep -c "$w" "$OUT/10-xnode.raw")" >> "$LOG"; done

# (4) mutation arms — each: LANDED (printed) → targeted cells → revert → dirty_tracked==0
mut A  leg mA-msglib   cargo nextest run --no-fail-fast -p spt-msg --lib
mut B1 leg mB1-store   cargo nextest run --no-fail-fast -p spt-store --lib -E 'test(/excerpt/)'
mut B1 leg mB1-ioedges cargo nextest run --no-fail-fast -p spt --test io_events_undriven_kinds_e2e --no-capture
mut B2 leg mB2-store   cargo nextest run --no-fail-fast -p spt-store --lib -E 'test(/excerpt/)'
mut B2 leg mB2-ioedges cargo nextest run --no-fail-fast -p spt --test io_events_undriven_kinds_e2e --no-capture
mut C  leg mC-daemon   cargo nextest run --no-fail-fast -p spt-daemon --lib -E 'test(/reap_shaped/)'
mut C  leg mC-attach   cargo nextest run --no-fail-fast -p spt --test webserve_attachment_e2e --no-capture
echo "[$(date -u +%H:%M:%SZ)] post-mutation dirty_tracked=$(git status --short -uno | wc -l) HEAD=$(git rev-parse --short HEAD)" >> "$LOG"

# (5) twohost pair: local baseline, then cross-box baseline on the real hosts (owner = kitsubito clone at f3c8495b)
leg 11-pair-none bash .spt/rig/twohost-web-local.sh "$GW" none none
if ! pair_ok none; then echo "[$(date -u +%H:%M:%SZ)] local pair baseline NOT green: a.exit=$(cat "$PAIR/none/a.exit" 2>/dev/null) b.exit=$(cat "$PAIR/none/b.exit" 2>/dev/null)" >> "$LOG"; fi
WAIT=600 leg 12-xbox-none bash .spt/twohost-web-xbox.sh "$GW" /home/reavus/spt-core-gate-w2 w2-f3c8495b none
echo "[$(date -u +%H:%M:%SZ)] GATE DONE dirty_tracked=$(git status --short -uno | wc -l)" >> "$LOG"
echo "procs-after: cargo=$(tasklist | grep -ci '^cargo') nextest=$(tasklist | grep -ci nextest) spt_from_pool=$(wmic process where "ExecutablePath like '%ws272-w2%'" get ProcessId 2>/dev/null | grep -c '[0-9]')" >> "$LOG"
