#\!/usr/bin/env bash
# misc_defer_idle_callback — regression test for issue #26 (deferred cross-callback
# to an IDLE leaf). 2 flat leaves: driver runs main.go -> axis.start and goes idle;
# axis, on the boundary sensor's `pressed`, notifies driver via inner.done — a
# cross-leaf callback to the now-idle driver. The callback is parked (it lives only
# in the cascade's `pending`, not driver's LTS snapshot); the fix seeds it into the
# leaf's component queue so the deferred drain dispatches it natively. ASSERTS the
# fix: the trace renders (no bail) and the deferred callback dispatches from
# driver's OWN queue (`sut.driver.<q>` pair + `sut.driver.inner.done`).
#
# NOTE: golden.simulate.1 is dzn's `simulate --state` output; nucleos currently
# differs only in one per-emit value-timing line (the sensor mirror commits a step
# early) — a SEPARATE issue, so this script asserts the #26 structure, not a byte
# match. (Tighten to a golden diff when value-timing converges.)
set -euo pipefail
here="$(cd "$(dirname "$0")" && pwd)"
nuc="${NUCLEOS:-$here/../../target/release/nucleos}"
dzn="$here/misc_defer_idle_callback.dzn"
t="$here/trace.1"
out="$("$nuc" simulate -m Sys "$dzn" < "$t" 2>&1)"
fail=0
echo "$out" | grep -q 'render bailed'           && { echo "FAIL: still bails"; fail=1; }
echo "$out" | grep -q 'sut.driver.<q>'          || { echo "FAIL: no driver queue dispatch"; fail=1; }
echo "$out" | grep -q 'sut.driver.inner.done'   || { echo "FAIL: no inner.done delivery"; fail=1; }
echo "$out" | grep -q '(trail "sensor.pressed")' || { echo "FAIL: pressed not in trail"; fail=1; }
if [ "$fail" -eq 0 ]; then echo "PASS: #26 deferred cross-callback renders (driver queue dispatch)"; exit 0
else echo "--- output ---"; echo "$out" | tail -8; exit 1; fi
