fix(asteria-game): absorb in-bash signals + flock sdk.jsonl appends so stub/*.sh honour exit-0 contract under fault injection
Closes #142.
Run try-10 of commit 290a8ed3 reported 7 NEW findings, all under
"Always: Commands finish with zero exit code" against stub/*.sh. Try-11
on the same commit and the same image digests was clean. Same code,
different scheduling — the stubs flake when Antithesis fault injection
delivers a signal to the bash interpreter (not the wrapped binary), or
when concurrent parallel_driver invocations race on /tmp/sdk.jsonl.
Three changes in helper_sdk.sh:
- _sdk_emit now wraps its >> /tmp/sdk.jsonl append with `flock -x` on
the open append-FD, so two concurrent shells can't interleave at the
syscall level under FS-fault injection.
- New `sdk_install_signal_trap` installs absorbing traps on
SIGTERM/SIGINT/SIGPIPE that emit `sdk_sometimes_optional false` and
exit 0; sourced once at the top of every stub script.
- New `sdk_run_signal_safe_fn` extends `sdk_run_signal_safe` to wrap
shell-function bodies, not just single-binary launches — needed for
the heartbeat/eventually_alive/finally_alive stubs whose work is a
printf|timeout 1 socat|jq pipeline rather than one binary.
Per-stub:
- parallel_driver_heartbeat.sh, eventually_alive.sh, finally_alive.sh:
body extracted into a local `_xxx_body` function, run through the
new fn-wrapper. Variable names lower-cased to local style.
- anytime_asteria_admin_singleton.sh, finally_asteria_consistency.sh,
parallel_driver_asteria_player.sh, serial_driver_asteria_bootstrap.sh:
add the signal trap as defense-in-depth around the existing
sdk_run_signal_safe binary wrap.
Smoke-tested standalone: 10 concurrent shells × 5 emits each produces
exactly 50 valid JSON lines (no race / loss); SIGTERM mid-sleep yields
exit 0 with the trap-emitted observation; `timeout 124` via the
fn-wrapper yields exit 0 with `must_hit:false`.
Real verification is the next Antithesis run on this branch.