You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Found by the v0.41.0 consumer bump: ouroboros's AOT runtime (aot_rt.h) links the EigenScript runtime directly and drives observer slots without ever running compile_ast — so nothing arms obs_needed, the linked bookkeeping returns early at eigs_obs_gate_open(), and every predicate silently answers from an empty window (t27_observer: VM impr=1, AOT all-zeros). This is the silent-wrong shape the gate's header forbids, on the seam the #1034 loop's OBS_BUILTINS-rejection reasoning named ("a C embedder running an assembled chunk with no name in any pool") — now demonstrated by a real consumer rather than hypothesized.
The eigs_eval_string/eigs_eval_file paths are safe (they force the gate — verified in round 16 of the loop). The hole is embedders that BYPASS eval and drive runtime internals directly.
Fixed on the consumer side in ouroboros (one eigs_obs_enable() in aot_boot). What this issue asks for upstream:
docs/EMBEDDING.md: add the contract line — an embedder that executes code through any path other than eigs_eval_* must call eigs_obs_enable() (or accept a dead observer). It is the one sanctioned arming path and is already exported (eigenscript.h:1094).
Optional hardening to evaluate: an eigs_open()-level default-armed mode, disarmed only by the compile-time verdict — which would make the closed gate opt-in-by-evidence for every entry path instead ofdefault-closed for paths that never compile. That inverts today's conservative direction for embedders and deserves its own design pass, not a drive-by.
Repro: build any observer-using program with ouroboros aot/build.sh at pin >= v0.41.0 without the aot_boot fix; compare against the VM arm.
Found by the v0.41.0 consumer bump: ouroboros's AOT runtime (
aot_rt.h) links the EigenScript runtime directly and drives observer slots without ever runningcompile_ast— so nothing armsobs_needed, the linked bookkeeping returns early ateigs_obs_gate_open(), and every predicate silently answers from an empty window (t27_observer: VMimpr=1, AOT all-zeros). This is the silent-wrong shape the gate's header forbids, on the seam the #1034 loop's OBS_BUILTINS-rejection reasoning named ("a C embedder running an assembled chunk with no name in any pool") — now demonstrated by a real consumer rather than hypothesized.The
eigs_eval_string/eigs_eval_filepaths are safe (they force the gate — verified in round 16 of the loop). The hole is embedders that BYPASS eval and drive runtime internals directly.Fixed on the consumer side in ouroboros (one
eigs_obs_enable()inaot_boot). What this issue asks for upstream:eigs_eval_*must calleigs_obs_enable()(or accept a dead observer). It is the one sanctioned arming path and is already exported (eigenscript.h:1094).eigs_open()-level default-armed mode, disarmed only by the compile-time verdict — which would make the closed gate opt-in-by-evidence for every entry path instead ofdefault-closed for paths that never compile. That inverts today's conservative direction for embedders and deserves its own design pass, not a drive-by.Repro: build any observer-using program with ouroboros
aot/build.shat pin >= v0.41.0 without the aot_boot fix; compare against the VM arm.