docs(bf-1yr1w): record --ble opt-in (SIM_BLE=1) in run-sim-local + re-verify matcher PASS

bf-1yr1w criterion 3: the --ble opt-in must be recorded in the canonical
runtime script (not a fork). scripts/run-sim-local.sh now carries an
opt-in env passthrough:

  SIM_BLE=1 ./scripts/run-sim-local.sh   # appends --ble to the sim invocation
  ./scripts/run-sim-local.sh             # default: --ble OFF, CSI->blob path unchanged

Default-off preserves the script's existing gate (CSI->blob). The --ble +
fixture + matcher gate remains scripts/run-sim-ble-match.sh; only the
opt-in itself is added here. A matching "--ble opt-in (SIM_BLE=1)"
subsection is added to notes/hardware-free-runtime.md so the recipe is
recorded there, not only in the fixture note.

Also chmod +x scripts/run-sim-ble-match.sh: it was committed non-executable
(mode 100644), so its documented invocation (./scripts/run-sim-ble-match.sh)
failed with EACCES. Now 100755 like the other run-sim-*.sh scripts.

Re-verified PASS (fresh run, 2026-07-08): bash scripts/run-sim-ble-match.sh
-> exit 0, GetMatch() returns "Alice" for blob_id=7 (confidence=0.714,
is_ble_only=false) via /api/ble/matches; 0 rejects, no panic. This is the
evidence for criteria 1+2: the bf-21v71 wire fix (GetMatch() copied onto
the served slice) fires for the sim fixture and resolves the seeded person
onto a live CSI blob.

Hygiene (change is shell+md+mode only, zero Go source): go vet ./... clean;
go test ./internal/... ./cmd/... all ok. The containerized integration
packages (test/acceptance, tests/e2e) are unaffected and tests/e2e remains
deliberately RED per notes/hardware-free-runtime.md (gated on bf-4q5w /
bf-5jeo), not a regression of this shell+md change.

Co-Authored-By: Claude <noreply@anthropic.com>
Bead-Id: bf-1yr1w
This commit is contained in:
jedarden 2026-07-08 14:28:58 -04:00
parent c42989e608
commit 58faa9ac4a
3 changed files with 33 additions and 11 deletions

View file

@ -186,6 +186,22 @@ chain. The first link (register a person + bind the sim's advertised device) is
link to it, do not duplicate it. The matcher script reuses that exact REST sequence
internally.
### `--ble` opt-in in `run-sim-local.sh` (`SIM_BLE=1`)
The canonical script now carries the `--ble` opt-in itself (bf-1yr1w), so you don't
have to fork it to exercise BLE ingestion:
```bash
SIM_BLE=1 ./scripts/run-sim-local.sh # appends --ble to the sim invocation
./scripts/run-sim-local.sh # default: --ble OFF, canonical CSI→blob path unchanged
```
Default-off — `run-sim-local.sh`'s gate is still the CSI→blob path. Re-verified green
both ways at HEAD `c42989e` (2026-07-08): default `peak=2` and `SIM_BLE=1` `peak=2`,
both with `[SIM] PASS: 2 blobs detected for 2 walkers` / `sim --verify PASSED`. The
opt-in only turns on BLE advertisement ingestion; it does **not** seed a person or
assert identity. The fixture + matcher gate is `scripts/run-sim-ble-match.sh` below.
### The recipe
```bash
@ -234,7 +250,7 @@ match — `blob_id != -1` AND `person_name == "Alice"` AND `confidence >= 0.6`:
"confidence":0.714,"is_ble_only":false}
```
### PASS evidence (HEAD `7757149`, 2026-07-08)
### PASS evidence (HEAD `7757149`; re-verified `c42989e`, 2026-07-08)
```
[match] peak_blobs (via /api/blobs): 2

0
scripts/run-sim-ble-match.sh Normal file → Executable file
View file

View file

@ -18,7 +18,7 @@
#
# Usage: ./scripts/run-sim-local.sh
# Env: SIM_NODES, SIM_WALKERS, SIM_RATE, SIM_DURATION, SIM_SEED, SIM_PORT,
# SIM_SPACE (override defaults; see below)
# SIM_SPACE, SIM_BLE (override defaults; see below)
# Exit: 0 if >=1 blob is observed via /api/blobs, 1 otherwise.
#
# Requires: go, curl, jq.
@ -44,6 +44,11 @@ SIM_RATE="${SIM_RATE:-30}"
SIM_DURATION="${SIM_DURATION:-25}"
SIM_SEED="${SIM_SEED:-42}"
SIM_SPACE="${SIM_SPACE:-5x5x2.5}"
# SIM_BLE=1 opts in to synthetic BLE advertisements (--ble). Default off: this
# script's gate is the CSI->blob path, NOT identity. The --ble + fixture + matcher
# gate lives in scripts/run-sim-ble-match.sh (bf-1yr1w, notes/hardware-free-runtime.md
# "BLE identity matcher (--ble)"). Opting in here only exercises BLE ingestion.
SIM_BLE="${SIM_BLE:-0}"
log() { printf '[run-sim] %s\n' "$*"; }
die() { printf '[run-sim] ERROR: %s\n' "$*" >&2; exit 1; }
@ -87,7 +92,7 @@ trap cleanup EXIT INT TERM
log "mothership: $MS"
log "sim: $SIM"
log "params: nodes=$SIM_NODES walkers=$SIM_WALKERS rate=$SIM_RATE duration=${SIM_DURATION}s seed=$SIM_SEED space=$SIM_SPACE port=$PORT"
log "params: nodes=$SIM_NODES walkers=$SIM_WALKERS rate=$SIM_RATE duration=${SIM_DURATION}s seed=$SIM_SEED space=$SIM_SPACE port=$PORT ble=$SIM_BLE"
# --- Start mothership on an ephemeral data dir ---------------------------------
# SPAXEL_MDNS_ENABLED=false: loopback reproduce, no multicast needed (the sim
@ -114,15 +119,16 @@ log "mothership healthy"
# --- Start sim with --verify (canonical acceptance cross-check) ----------------
# The sim streams for $SIM_DURATION, then its verifyBlobs polls /api/blobs
# (2s settle + 12x500ms) and asserts blob_count == walkers ±1.
"$SIM" \
--mothership "ws://localhost:$PORT/ws/node" \
--nodes "$SIM_NODES" --walkers "$SIM_WALKERS" --rate "$SIM_RATE" \
--space "$SIM_SPACE" \
--duration "$SIM_DURATION" --seed "$SIM_SEED" --verify \
> "$DATA_DIR/sim.log" 2>&1 &
# (2s settle + 12x500ms) and asserts blob_count == walkers ±1. SIM_BLE=1 appends
# --ble (synthetic BLE advertisements); default off keeps the canonical path green.
sim_args=(--mothership "ws://localhost:$PORT/ws/node"
--nodes "$SIM_NODES" --walkers "$SIM_WALKERS" --rate "$SIM_RATE"
--space "$SIM_SPACE"
--duration "$SIM_DURATION" --seed "$SIM_SEED" --verify)
[ "$SIM_BLE" = "1" ] && sim_args+=(--ble)
"$SIM" "${sim_args[@]}" > "$DATA_DIR/sim.log" 2>&1 &
SIM_PID=$!
log "sim started (pid $SIM_PID, --verify enabled)"
log "sim started (pid $SIM_PID, --verify enabled, ble=$SIM_BLE)"
# --- Independent /api/blobs poller over the streaming window (authoritative) ---
# A node is online when went_offline_at is the Go zero timestamp (0001-01-01T00:00:00Z)