Skip to content

A file means one thing on every road: file-relative + project-root resolution, import-road for-body scoping, cross-road oracle (#1056) - #1106

Merged
InauguralPhysicist merged 6 commits into
mainfrom
fix-1056
Sep 6, 2026
Merged

A file means one thing on every road: file-relative + project-root resolution, import-road for-body scoping, cross-road oracle (#1056)#1106
InauguralPhysicist merged 6 commits into
mainfrom
fix-1056

Conversation

@InauguralPhysicist

@InauguralPhysicist InauguralPhysicist commented Sep 6, 2026

Copy link
Copy Markdown
Collaborator

Closes #1056 — a file now means one thing regardless of the road it arrived by.

What changed

Resolution is a function of the file, never of the process cwd. load_file and import share one chain: absolute path as-is → the directory of the file that CONTAINS the call (the main program's dir; a module's own dir; a load_filed file's own dir for loads nested inside it; cwd only for code with no file: the piped REPL, or the embed API with no path) → the eigs_modules walk-up → the project root (nearest ancestor containing eigs.json, the marker the eigs_modules walk already used) → the exe-relative stdlib steps → $HOME/.local/lib/eigenscript. The bare cwd try and the one-level <base>/../<path> hack are gone. A failed resolution names what was tried.

A for body's is at a module's top level binds in the module scope on every road. Only the import road dropped it (keys of M lacked from_for); if / loop while / try bodies and the main / load_file roads already bound it.

Top-level return was already one rule ("end the current file, yield its value; the outermost file's value is discarded"); it is now stated in docs/LANGUAGE_CONTRACT.md and pinned by a cross-road fixture.

A cross-road oracle: tools/road_diff.sh runs every tests/roads/*.eigs fixture as the main program, via load_file, and via import, from two working directories each (66 executions over 11 fixtures), and fails on any divergence; --selftest plants a divergent fixture and the empty-population case. In the suite.

Why the project-root rule and not "source-file relative"

The issue suggested resolving relative to the source file. Census across every .eigs in the ecosystem (2026-09-05): 929 literal load_file targets, 821 resolve relative to the containing repo's ROOT, 87 relative to the containing file's own directory, 104 are stdlib paths. Source-relative-only would have broken ~840 sites; the project-root rule covers them with a one-file migration.

Breaking change (CHANGELOG, Unreleased)

Consumers that run root-relative paths from files in subdirectories need an eigs.json at their repo root (six repos already have one; the rest get it at the next pin bump — the consumer preflight sweep will show exactly which). Two in-repo tests that encoded the removed cwd / parent steps were migrated to the new rule.

Measured exception, filed separately

A fresh for binder INSIDE A FUNCTION stays readable after its loop while a module-level one does not — pre-existing on main, identical on all three roads: #1105.

Gates (builder, in the worktree)

release: RESULTS: 4246/4246 passed, 0 failed
asan (detect_leaks=1): RESULTS: 4235/4235 passed, 0 failed
jit_diff: OK (230 programs x {jit, osr} vs the interpreter; 4 arms adjudicated by replay; 0 ledgered)
G2 on c1684bc: road_diff blocks.eigs -> 3 failures (import road: from_for missing); on the branch: 0

Blind-critic rounds: see the commit trail; verdicts and the largest gaps per round are recorded in the PR comments.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Kpzyjv1SaLaqBf45FSFDhB

InauguralPhysicist added a commit that referenced this pull request Sep 6, 2026
…the race (#1107)

The #885 control asserted that a deliberately shared global cross-talks
between two threads within a fixed 200 rounds each. That is a bet on the
scheduler, and it lost on CI for PR #1106 @ 07a0ac3 (2026-09-06):
`control cross-talk: A=0 B=0 over 200 rounds each`, with the file identical
on main and the lane green on the previous push. PR #1034 hit the same shape
before the start barrier was added.

Now each worker runs at least ROUNDS rounds and keeps racing until BOTH sides
have observed at least one mismatch or PLANT_BUDGET (200000) rounds elapse;
the check requires both sides to have seen it. The property is unchanged —
a harness that never interleaves exhausts the budget and FAILS — only the
sample size adapts to the scheduler.

Measured on the dev box: 3/3 runs stop at the 200-round minimum
(A=198/200 B=199/200; 199/198; 188/189). Plant: making the shared global
`__thread` (race impossible) gives `A=0/200000 B=0/200000` and
EMBED_CONCURRENT_FAIL in 0.37 s, so the budget costs nothing on a failing
control either.


Claude-Session: https://claude.ai/code/session_01Kpzyjv1SaLaqBf45FSFDhB

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
InauguralPhysicist and others added 5 commits September 6, 2026 00:16
Resolve import and load_file from the containing file, then eigs_modules,
then the nearest eigs.json project root, then the existing stdlib roots.
Remove bare cwd and one-parent fallback. Retain canonical provenance in
shared source blobs so nested loads and deferred functions use their own
file, including symlink entry points. Keep origin/collision classification.

Bind imported top-level for-body is assignments in the module, preserving
isolated loop binders and outer-binder writes inside nested loops. Keep
the existing fresh-function-binder slot exception; do not change return
semantics. Document all three roads and the breaking eigs.json migration.

Use the same file provenance in the eager observer scan. Its memo key
includes directory identity as well as file identity: hard-linked source
in different directories can reach different observing children.

Add 11 cross-road fixtures (66 executions), exact stdout snapshots and
namespace readback, and an in-suite road_diff gate with positive control,
divergence fault, and empty-population fault. Fixtures include source and
project-root precedence, missing-path diagnostics, nested/deferred loads
and imports, cwd shadows/chdir, symlinks, hardlinks, block binding and return.

Existing tests that encoded the removed cwd/parent steps were migrated:
- test_module_scope and test_import_toplevel_scope now write generated
  modules beside their containing test file, rather than into src/.
- the observer lib/ui probe requests lib/ui.eigs through the stdlib chain.
- the observer cwd-shadow probe now requires the containing-file result.
The missing-import diagnostic retains the established "not found" text.

Baseline c1684bc (built before C edits):
  bash tools/road_diff.sh --fixture blocks
  road_diff: FAIL: blocks.eigs import cwd=. rc=0
  expected ["from_for", 4]; got ["from_for", "<missing>"]
  road_diff: FAIL: blocks.eigs import cwd=__unrelated_cwd rc=0
  road_diff: FAIL: blocks.eigs: roads/cwds diverge
  road_diff: fixtures=1 runs=6 failures=3 seconds=0.05
  shell exit 1
Direct baseline import keys:
  ["from_if", "from_loop", "from_try", "fn", "from_fn"]
  blocks.from_for = null
Main/load baseline values both [2, 2, 3, 4, 1].

Additional actual fault injection:
- restore the eager scan's old main-file base: observer_nested gives
  fixtures=1 runs=6 failures=5; restore fix: failures=0.
- inode-only observer memo: hardlink_observer gives
  fixtures=1 runs=6 failures=5; directory-aware key: failures=0.
- road_diff --selftest: controls=1 plants=2 failures=0.

Measured exception to the brief, preserved as existing semantics:
  define probe() as:
      for z in [7, 8]:
          0
      return z
  print of (probe of [])
prints 8, exit 0, on c1684bc. A fresh function binder remains readable
after the loop. The binders fixture pins it on all three roads, and docs
explicitly retain this previously documented function-slot exception.

Final validation totals: see the appended handoff results below.

Sanitizer ownership regression reproduced and fixed:
  blocks before root lev_names cleanup: fixtures=1 runs=6 failures=6
  each execution: 32-byte LeakSanitizer report, exit 1
  after cleanup: all 11 fixtures / 66 executions and CLI 15/15 pass
  under ASAN_OPTIONS=detect_leaks=1.

Final validation on the unchanged source artifact:
  release: RESULTS: 4246/4246 passed, 0 failed
  asan: RESULTS: 4235/4235 passed, 0 failed
  jit: jit_diff: OK (230 programs x {jit, osr} vs the interpreter; 4 arms adjudicated by replay; 0 ledgered)
  ASan detect_leaks=1: zero LeakSanitizer, AddressSanitizer, UBSan reports.
  G2 branch: fixtures=1 runs=6 failures=0; imported from_for is 4.
  A/B direct shadow probe: both print SCRIPTDIR-COPY, exit 0.
  freestanding-check: both symbol gates passed.

Gate execution caveat: running jit_diff immediately after make asan
uses the ASan binary. Its interpreter exceeded the fixed 180-second
deadline on test_loop_cap_772.eigs (105 million iterations), while
JIT and OSR returned 0. That run reported LEDGER CHANGED (230
programs examined), with only that fixture in JIT and OSR.
After make restored the validated release variant, the unchanged
jit_diff gate passed all 230 programs with zero ledgered divergences.
No timeout, ledger, fixture, or gate rule was relaxed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kpzyjv1SaLaqBf45FSFDhB
Close both round-2 critic findings. Snapshots now encode presence separately:
[name, 1, value] for a present binding and [name, 0] for absence. Values such
as null and the literal "<missing>" cannot impersonate an absent binding.
Migrate 37 snapshot rows in all 11 goldens algebraically; fixture source,
fixture prints and payload expectations are unchanged.

The original sentinel fixture reproduced a false green on the read-only
canonical main binary: fixtures=1 runs=6 failures=0. Selftest now requires a
literal-sentinel positive control, red when its assignment is deleted,
red for a genuinely absent binding where present null is expected, and the
existing cwd-divergence/zero-fixture plants. It checks clean child exits and
the intended mismatches, so a crash or unavailable binary is not accepted.

Actual runtime regression proof (canonical binary only executed, never built):
  bash tools/road_diff.sh --selftest --bad-binary \
    /home/jon/src/InauguralSystems/EigenScriptEcosystem/EigenScript/src/eigenscript
  road_diff selftest: GREEN: literal "<missing>" is present
  road_diff selftest: RED: literal "<missing>" binding dropped (known-bad binary, import only)
  road_diff selftest: RED: genuinely missing binding cannot impersonate present null
  road_diff selftest: controls=2 plants=4 failures=0
The unchanged sentinel fixture exposes missing bindings on both import runs.
The portable default plants the missing assignment without another checkout.
A scratch oracle mutant restoring the ambiguous absence representation was
also rejected: selftest exit 1 even though its sentinel gate falsely said
fixtures=1 runs=6 failures=0. Record the failure and protocol in roads/README.

Correct ARCHITECTURE, PACKAGE_DESIGN, OBSERVER and the additional stale
SYNTAX chain found by auditing all docs/ and README (including docs/llms.txt).
Describe containing-file directory, eigs_modules, nearest eigs.json project
root, then stdlib roots, with absolute paths used as-is. Remove nonexistent
-e/stdin-file roads from the new docs. Executed load_file and import from
both A and B via the piped REPL and fresh embed eval-string states: each
loaded its own cwd's files, rc=0. Confirmed -e and /dev/stdin file invocations
both exit 1 with 'cannot read file', as the critics reported.

Validation:
  bash tools/road_diff.sh
    road_diff: fixtures=11 runs=66 failures=0
  bash tools/road_diff.sh --selftest
    road_diff selftest: controls=2 plants=4 failures=0
  bash tools/doc_drift_check.sh: exit 0
  tools/doc_coupling_hook.sh (compiler-path event): exit 0
  Broad cwd/working-directory audit: no stale resolution claims remain;
    targeted stale-chain grep across docs/ and README is empty.
  git diff --check: clean
  Final release suite (one run): RESULTS: 4246/4246 passed, 0 failed (exit 0)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kpzyjv1SaLaqBf45FSFDhB
Close the three round-3 critic findings without changing runtime semantics.
The driver captures print, has_key, load_file and throw before fixture code
runs on every road, including before the main source splice. Every capture
and temporary uses a fresh private UUID prefix. Snapshot emission calls only
these saved builtins; keys is not a dependency. Existing goldens are unchanged.

Reproduced the old print-rebinding false green against the read-only canonical
main binary: fixtures=1 runs=6 failures=0. The same fixture now reads back its
function on the branch and detects the missing import binding on main. The
membership control invokes the actual shared namespace-snapshot emitter after
rebinding has_key and keys in the same scope; it does not rely on import
isolation to protect the readback. A rebound throw cannot suppress the driver's
return-value check either.

Add independent process-result plants: after successful execution of the real
binary, a bounded Python wrapper changes only rc to 17 or only stderr. Stdout
still matches the golden. Every rc-plant run has the same rc, so cross-road rc
comparison cannot conceal removal of the absolute exit-status check. Selftest
requires the exact roads, statuses and diagnostics of each planted failure.

Before this change, deleting 'result.stderr or' or 'result.returncode or'
left selftest green: controls=2 plants=4 failures=0. Both now fail at their
own new control. Scratch gate mutants reverting print/has_key/throw readback
to rebound names also fail selftest, as does delaying main's captures until
after its source splice. These are executions, not inspection-only claims.

Pin the compiler arm's module-scope choice with importer_scope.eigs and
its eigs_modules/clobber_helper helper. The importer must retain outer=1
while the helper's for-body write creates a module-owned outer binding.

Compiler plant proof, built using plain make in an archived scratch tree
inside this worktree (build/roads_round3/compiler_mutant):
  src/compiler.c, #1056 arm:
    else if (g_compile_import_toplevel)
  changed ONLY there to:
    else if (0 && g_compile_import_toplevel)
The pre-change gate over its archived 11 fixtures remained green:
  road_diff: fixtures=11 runs=66 failures=0
The new fixture, through tools/road_diff.sh --fixture importer_scope --binary
<binary>, is red on the compiler plant and the read-only canonical main binary,
green on the branch:
  plant:  fixtures=1 runs=6 failures=5, exit 1
  main:   fixtures=1 runs=6 failures=6, exit 1
  branch: fixtures=1 runs=6 failures=0, exit 0
The plant's main/load roads fail; its import road remains green. Main fails
all roads. Independent main-program readback (all child rc=0, stderr empty):
  plant:  ["outer", 1, 2] / ["helper_has_outer", 1, 0]
  main:   ["outer", 1, 1] / ["helper_has_outer", 1, 0]
  branch: ["outer", 1, 1] / ["helper_has_outer", 1, 1]
The canonical tree was executed read-only, never built or modified.

Validation:
  bash tools/road_diff.sh
    road_diff: fixtures=12 runs=72 failures=0 seconds=2.11
  bash tools/road_diff.sh --selftest
    road_diff selftest: controls=5 plants=9 failures=0
  bash tools/road_diff.sh --selftest --bad-binary \
    /home/jon/src/InauguralSystems/EigenScriptEcosystem/EigenScript/src/eigenscript
    road_diff selftest: GREEN: rebinding print cannot forge readback
    road_diff selftest: RED: print rebinding: dropped import binding (known-bad binary)
    road_diff selftest: GREEN: rebinding has_key/keys cannot forge readback
    road_diff selftest: RED: has_key/keys rebinding: dropped import binding (known-bad binary)
    road_diff selftest: GREEN: rebinding throw preserves return validation
    road_diff selftest: RED: throw rebinding cannot suppress a return mismatch
    road_diff selftest: RED: nonzero rc with matching stdout
    road_diff selftest: RED: stderr only with matching stdout and rc=0
    road_diff selftest: controls=5 plants=9 failures=0
  Focused doc_drift_check.sh: exit 0
  doc_coupling_hook.sh, compiler-path event: exit 0 (expected advisory)
  git diff --check: clean
  Final release suite, one run: RESULTS: 4246/4246 passed, 0 failed (exit 0)

Record the demonstrated oracle failures and the new controls in
tests/roads/README.md as the distill-lessons outcome for this round.

Final hash verification: all 5 changed/new files match the tested artifact;
HEAD remains fed3782. No runtime source edits and no measurements contradict
this round's brief. Standalone selftest wall time was 1.72s in each mode.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kpzyjv1SaLaqBf45FSFDhB
Round 4 on fix-1056, starting from clean 5e1567f.

Imported entry chunks now tag their module-scope writes. SET_FN_NAME_LOCAL
uses a shared interpreter/JIT lookup that honors nearer loop locals before
the module entry environment; it cannot write through to the importer.
Resolve the target before the inline cache, including when a local appears
between loop iterations. Ordinary function chunks keep their existing rules.
OP_IMPORT restores its compile-only directory override before executing the
module, so runtime eval inherits the executing function's source directory.

Add f29_loop_local (current/enclosing loop locals plus if/while siblings),
f29_loop_local_cache (alternating local/module writes over 80 iterations), and
f30_eval_dir (main, load_file, imported caller, and nested imported caller).
Existing fixture goldens are unchanged. SPEC, COMPARISON, LANGUAGE_CONTRACT,
CHANGELOG, and the oracle README document the fixes and their evidence.

Generated module writers in test_import, test_import_errors, test_module_scope,
and test_import_toplevel_scope now use the canonical EIGS_TEST_DIR supplied
by both suite runners. Installed-layout source symlinks resolve to the real
test directory, not the temporary runner cwd. Audited all tests/ files with
write_text plus import/load_file: the remaining writers use absolute temp
paths or write non-module data. install.sh accepts EIGENSCRIPT_INSTALL_PREFIX
for an isolated installation without changing HOME or the normal installation.

Require a unique terminal driver completion marker, emitted by captured print
AFTER readback. Only that marker is removed before byte-exact comparison.
Malformed road-bind identifiers fail by name before any child runs. Selftest
adds early-exit forgery and invalid-identifier plants; removing either guard
makes selftest fail. The old gate accepted the forged exit at fixtures=1
runs=6 failures=0; invalid metadata instead raised ValueError. Prior capture,
presence, rc-only, stderr-only, divergence, and zero-fixture controls remain.

Reproduction BEFORE the runtime fix (5e1567f, release binary):
  bash tools/road_diff.sh --fixture f29_loop_local
  import stdout (both cwds):
    10
    ["direct", 1, 10]
    ["nested", 1, 20]
    ["from_if", 1, 31]
    ["from_while", 1, 41]
  main/load stdout instead start 11, direct=11, nested=21.
  road_diff: fixtures=1 runs=6 failures=3

  bash tools/road_diff.sh --fixture f30_eval_dir
  wrapper prints WRAPPER-PEER / EVALHELPER-PEER; nested_eval=LEAF-PEER.
  On import, main_eval and loaded_eval also become WRONG-DIR-ERROR.
  Every child exits 0 with empty stderr; expected all EVALHELPER-PEER.
  road_diff: fixtures=1 runs=6 failures=7

AFTER: both fixtures and importer_scope run with default execution, forced
interpreter, and forced OSR: fixtures=1 runs=6 failures=0 for each.
f29_loop_local prints 11 with direct=11, nested=21, from_if=31, from_while=41;
f30_eval_dir's two prints and six bindings all contain EVALHELPER-PEER.
Disabling module_scope_writes and running f29_loop_local_cache makes both
interpreter and forced OSR red (fixtures=1 runs=6 failures=3). Restore the
assignment and both pass. No canonical-tree build or binary mutation.

Installed-layout CI steps from .github/workflows/ci.yml were reproduced using
EIGENSCRIPT_INSTALL_PREFIX=$PWD/build/roads_round4/install ./install.sh,
then ./build.sh to restore the tree binary. Verified the VS Code client wiring,
both executables on PATH, --version, and clean JSON import from / using both
installed and tree interpreters. The subset with the installed interpreter:
  BEFORE writer migration: Installed-layout subset: 6 passed, 2 failed
  AFTER writer migration:  Installed-layout subset: 8 passed, 0 failed
The two red sections were [36] Import System and [59] Import Error Paths.

Validation before the final suites:
  road_diff: fixtures=15 runs=90 failures=0
  road_diff selftest: controls=5 plants=11 failures=0
  Same selftest totals with --bad-binary pointing at the read-only c1684bc
  canonical interpreter; sentinel/capture plants give import-only failures.
  Doc examples: 84 checked, 84 passed, 0 failed, 5 skipped, 0 unreadable fence(s)
  doc_drift_check exit 0; semantics doc-coupling surfaces updated.
  JIT smoke: all cases passed.

Final gates, one at a time, once each on the frozen artifact:
  Release: RESULTS: 4246/4246 passed, 0 failed
  ASan (detect_leaks=1): RESULTS: 4235/4235 passed, 0 failed
  Release jit_diff: jit_diff: OK (230 programs x {jit, osr} vs the interpreter; 4 arms adjudicated by replay; 0 ledgered)

All 32 changed/new files retained their pre-suite SHA-256 hashes throughout
release, ASan, and the final release-binary JIT comparison. No new divergences
were added to the JIT ledger. No measurements contradicted the round-4 brief.

Commit prepared for the orchestrator: git metadata is read-only for the builder.
Changes remain in the fix-1056 worktree; the builder did not commit or push.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kpzyjv1SaLaqBf45FSFDhB
An embedding host executing eigs_eval_file kept its entry directory override
active through execution. A helper's eval then loaded the entry's peer instead
of the helper's. Share eval_source between both embed APIs, set an explicit
file directory only around compile_ast, restore it before vm_execute, and
remove the embed API's script_dir mutation. Deferred helpers keep their own
file, and successive no-file strings keep the host's cwd base.

The imported OP_SET_FN_NAME_LOCAL inline cache could still point at the module
after eval created a nearer local without changing the module's version.
Inline imported stores now require frame.env == frame.fn_env; otherwise the
existing bounded helper finds the nearest binding, stopping at the module.
The existing walk_depth==0 guard still requires the inline target's own slot.
The new compare precedes mutation and uses the existing aligned helper path;
no opcode, layout, helper ABI, builtin, syntax, tape or observer change.

Tests and claims:
- Add src/embed_roads.c and tests/embed_roads: real eigs_eval_file/string,
  deferred helpers, loads/imports, an internal host-callback provenance probe,
  no-file restoration, and execution-time checks of the compile override.
  The callback test does not promise general API reentrancy.
- make embed-roads links the actual CLI object variant, including ASan.
  tools/embed_roads.py gates exit/stderr, check counts and results, with wrong
  peer, missing tree, exit-only, stderr-only and zero-check selftest plants.
  Enroll the target in all three warning-gate lists and the embed gate in [99z].
- Six new native road fixtures run interpreter/default JIT/forced OSR on all
  three roads and both cwds. Every native arm requires compiled>0; stats must
  be present exactly once. ARM64 has no emitter and explicitly runs only the
  interpreter; it is not counted as a successful native arm. Selftest checks
  this policy and rejects forced-off native arms and missing stats.
- Native goldens came from EIGS_JIT_OFF=1 before runtime edits. All 15 existing
  fixture goldens remain unchanged. f29 fixtures stop at LOOP_ENV_CLEAR and
  never tested native stores; correct CHANGELOG and roads README accordingly.
  Update SPEC, COMPARISON, LANGUAGE_CONTRACT and EMBEDDING for embed provenance.
- The warning selftest initially failed before its planted header probe:
  its HEAD archive had the current Makefile/enrollment but lacked the new C
  test. Overlay current tracked/nonignored C/header inputs (and deletions),
  preserving the real generated-header and compiler-flag plants. This is test
  setup repair, not an exemption from the warning gate.

F3 red on 07a0ac3's embed code, green with the fix:
Save the fixed src/eigs_embed.c, replace it with
  git show 07a0ac3:src/eigs_embed.c
then run:
  make embed-roads
  python3 tools/embed_roads.py --binary build/release/embed_roads
The final C harness produced:
  embed_roads: eval_file: MAIN / HELPER
  embed_roads: checks=28 scope_checks=17 failures=14
Restoring the fix and rebuilding produced:
  embed_roads: eval_file: HELPER / HELPER
  embed_roads: eval_string deferred functions: HELPER / HELPER
  embed_roads: eval_file from helper callback: HELPER / HELPER
  embed_roads: eval_string load: HELPER / HELPER
  embed_roads: eval_file import: HELPER / HELPER
  embed_roads: eval_string import: HELPER / HELPER
  embed_roads: checks=31 scope_checks=20 failures=0

All temporary resolve-directory setter sites were execution-probed:
- Delaying load_file's restore/free until after vm_execute: checks=30,
  scope_checks=19, failures=16; execution-override diagnostics name the sites.
- Delaying OP_IMPORT's restore until after vm_execute: checks=30,
  scope_checks=19, failures=5; imported wrapper returns WRAPPER / HELPER.
- The 07a0ac3 embed setter: failures=14 above.
Each plant used make embed-roads and the same C harness. All sources were
restored and rebuilt before final gates. README records the complete audit:
main/state provide entry/no-file bases; lint uses a private traversal context;
bundle rewrites the entry argv; neither lint nor bundle writes a resolver global.

J1 independent plants (plain make, one build/gate at a time):
1. In jit_helper_set_fn_name_local only, replace
     Env *target = fn_name_write_target(chunk, frame, idx);
   with Env *target = frame->fn_env; then make and bash tools/road_diff.sh:
  road_diff: fixtures=21 runs=198 failures=30 seconds=10.20
  native_alternate reference: [7300, 26762400]
  native_alternate import JIT: [24, 3068348]
  native_alternate import OSR: [24, 212400]
2. Disable only the new jit.c condition with if (0 && op ==
   OP_SET_FN_NAME_LOCAL && chunk->module_scope_writes), then make and
   bash tools/road_diff.sh --fixture native_inline:
  road_diff: fixtures=1 runs=18 failures=5 seconds=0.98
  native_inline reference14999, imported JIT/OSR19999; child rc=0.
  Restoring the guard makes every tier14999.
Measured fixed import-road native_inline statistics:
  road_diff: native native_inline.eigs import tier=ref cwd=.: [jit] scanned=0 compiled=0 cache_used=0
  road_diff: native native_inline.eigs import tier=jit cwd=.: [jit] scanned=2 compiled=1 cache_used=19878
  road_diff: native native_inline.eigs import tier=osr cwd=.: [jit] scanned=2 compiled=1 cache_used=19878
A gate-only mutant dropping `or not tier_ok` is also rejected by selftest's
force-off plant. The native checks cannot silently measure zero compilations.
The old direct f29 cache fixture, with EIGS_JIT_STATS=1 EIGS_JIT_STOPS=1
EIGS_JIT_OSR_THRESHOLD=1, reports:
  [jit] scanned=1 compiled=0 cache_used=0
         1  LOOP_ENV_CLEAR         (100.0%)

Final gates (one at a time, unchanged sources, release/ASan suite each ONCE):
[roads-final]
road_diff: fixtures=21 runs=198 failures=0 seconds=10.39
[selftest-final]
road_diff selftest: GREEN: numeric binding
road_diff selftest: RED: planted.eigs: roads/cwds diverge
road_diff selftest: GREEN: literal "<missing>" is present
road_diff selftest: RED: literal "<missing>" binding dropped (assignment deleted)
road_diff selftest: GREEN: rebinding print cannot forge readback
road_diff selftest: RED: print rebinding: forged absence golden
road_diff selftest: GREEN: rebinding has_key/keys cannot forge readback
road_diff selftest: RED: has_key/keys rebinding: forged absence golden
road_diff selftest: GREEN: rebinding throw preserves return validation
road_diff selftest: RED: throw rebinding cannot suppress a return mismatch
road_diff selftest: RED: genuinely missing binding cannot impersonate present null
road_diff selftest: RED: nonzero rc with matching stdout
road_diff selftest: RED: stderr only with matching stdout and rc=0
road_diff selftest: GREEN: three measured tier arms (18 runs)
road_diff selftest: GREEN: ARM64 policy explicitly runs only the interpreter
road_diff selftest: RED: native tiers compiled nothing
road_diff selftest: RED: native mechanism statistics missing
road_diff selftest: RED: exit before readback cannot forge completion
road_diff selftest: RED: invalid binding name is a named failure
road_diff selftest: RED: zero fixtures
road_diff selftest: controls=7 plants=13 failures=0
[selftest-bad-final]
road_diff selftest: controls=7 plants=13 failures=0
[embed-final]
embed_roads selftest: RED: wrong helper peer
embed_roads selftest: RED: missing fixture tree
embed_roads selftest: RED: exit
embed_roads selftest: RED: stderr
embed_roads selftest: RED: zero_checks
embed_roads selftest: controls=1 plants=5 failures=0
[jit-smoke]
JIT smoke: all cases passed.
[jit-diff]
jit_diff: OK (230 programs x {jit, osr} vs the interpreter; 4 arms adjudicated by replay; 0 ledgered)
[release]
  RESULTS: 4246/4246 passed, 0 failed
[asan]
  RESULTS: 4235/4235 passed, 0 failed
[tsan]
  PASS: seeded race detected (23 warnings) — the gate is live
Results: 14 passed, 0 failed
ASan ran with ASAN_OPTIONS=detect_leaks=1; no leak-tally note or sanitizer
error appeared. TSan used the exact CI commands, make tsan followed by
bash tests/test_tsan.sh. make restored src/eigenscript to the release binary.
The serial runner's source hashes match before/after all final gates.

Additional focused checks:
werror warning gate OK: all 456 compile invocations across 28 dry-run targets + 7 script(s) carry: -Werror=switch -Werror=comment -Werror=misleading-indentation
SELFTEST OK: both integration mutations planted and aggregate fault tree rejected, synthetic fault shapes caught (incl. target-batch divergence, two-invocation blocks, switch-enum, zero-line targets, partial per-target coverage loss, unpinned targets), clean shapes pass, floors bite in BOTH directions, unenrolled compile surfaces are caught
doc_drift_check.sh: rc=0
Doc examples: 78 checked, 78 passed, 0 failed, 5 skipped, 0 unreadable fence(s)
Removed-claim audit:
rg -n -i 'applies to JIT writes|including under forced OSR|eigs_eval_file.*updates.*script_dir' CHANGELOG.md tests/roads/README.md docs README.md
Output: empty (rg rc=1).

No measurement contradicts the Round 5 brief. The directly measured inline
14999/19999 divergence additionally confirms the reported fast-path defect.
Git metadata is read-only by the brief: leave these changes in fix-1056's
working tree for the orchestrator to commit. No commit or push was attempted.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kpzyjv1SaLaqBf45FSFDhB
The embed provenance section rejected a standalone build.sh CLI because it
required exactly one inode match in build/*/eigenscript. Reuse a uniquely
identified make variant, but build the dedicated embed harness from the
Makefile SOURCES objects when the match is empty or ambiguous. That fallback
uses release objects, or ASan objects when ASAN_OPTIONS is set. It does not
relink the CLI or infer an unidentified CLI's compiler flags. Four metadata
controls cover standalone, unique, ambiguous, and sanitizer-fallback layouts.
The existing embed-roads target remains enrolled in TARGETS, TARGET_BATCHES,
and TARGET_FLOORS in tools/werror_switch_check.sh (floor 25).

GP1 choice (b): describe the native arms as configurations, not measured
OSR-entry mechanisms. The same compiled chunk is exercised with the OSR
threshold lowered; both native arms compile code and must agree. The current
statistics count compiled chunks and do not establish different entry paths.
Remove the overstated forced-OSR/measured-tier wording from CHANGELOG and
roads documentation, retaining the f29 LOOP_ENV_CLEAR bailout limitation.
A new child-environment control verifies EIGS_JIT_OSR_THRESHOLD=1 reaches the
lowered-threshold arm. Removing the setting must fail even with matching
stdout and successful native compilation. This checks the configuration,
not an unmeasured OSR-entry count.

GP2: plant a compile-directory override only while the registered
host_scope_clean probe executes, after all ordinary embed results are good.
That probe alone must detect it: checks=32 scope_checks=21 failures=1, child
rc=1. Gutting its condition leaves all ordinary HELPER results correct and
checks=32 scope_checks=21 failures=0, which the strengthened selftest rejects.
Add invalid-value and duplicate-header controls for road-native metadata;
each must fail by name before running any fixture. Gutting validation makes
the otherwise valid native fixture green and therefore fails the selftest.
Qualify EMBEDDING.md's no-file eigs_eval_string cwd statement with
"when no script frame is executing".

This round changes only the harnesses and documentation: six files, no
runtime semantics or fixture-golden changes. The build-layout assumption,
unmeasured entry-mechanism claim, and untested probes are now documented in
tests/roads/README.md and covered by concrete controls (distill-lessons pass).

Reproduction and targeted mutation evidence

On the original harness, hiding all build-variant inode matches while
preserving the CLI and restoring the variant names afterward returned rc=1:
embed_roads: FAIL: cannot identify the CLI build variant

All four targeted selftest mutants were exercised before final gates and
restored; the test runner is build/roads_round6/mutations.py:
RED: gutted threshold-setting rejected by selftest
RED: gutted native-header rejected by selftest
RED: gutted layout fallback rejected by selftest
RED: gutted host_scope_clean rejected by selftest
GREEN: restored embed harness

The threshold-assignment mutant reports:
  road_diff selftest: FAIL: lowered-threshold configuration
  road_diff: fixtures=1 runs=18 failures=7
The header-validation mutant reports:
  road_diff selftest: FAIL: native metadata invalid value
  road_diff: fixtures=1 runs=18 failures=0
The layout-fallback mutant reports:
  embed_roads selftest: FAIL: standalone build.sh layout
The scope-probe mutant reports:
  embed_roads selftest: FAIL: execution-scope probe missed planted override
  embed_roads: checks=32 scope_checks=21 failures=0

GP1 measurement on the restored release binary (each rc=0):
  EIGS_JIT_STATS=1 src/eigenscript tests/roads/native_inline.eigs
14999
[jit] scanned=2 compiled=1 cache_used=19878
  EIGS_JIT_STATS=1 EIGS_JIT_OSR_OFF=1 src/eigenscript tests/roads/native_inline.eigs
14999
[jit] scanned=0 compiled=0 cache_used=0
The default native configuration already relies on OSR for this probe.
Requiring the default arm to have zero OSR entries would need different
execution coverage; it is not what the existing measurements establish.

Serial final validation (all rc=0, one heavy job at a time)

bash tools/road_diff.sh
road_diff: fixtures=21 runs=198 failures=0 seconds=10.26

bash tools/road_diff.sh --selftest
road_diff: compared planted.eigs (6 runs)
road_diff: fixtures=1 runs=6 failures=0 seconds=0.04
road_diff selftest: GREEN: numeric binding
road_diff selftest: RED: planted.eigs: roads/cwds diverge
road_diff: compared sentinel.eigs (6 runs)
road_diff: fixtures=1 runs=6 failures=0 seconds=0.04
road_diff selftest: GREEN: literal "<missing>" is present
road_diff selftest: RED: literal "<missing>" binding dropped (assignment deleted)
road_diff: compared rebind_print.eigs (6 runs)
road_diff: fixtures=1 runs=6 failures=0 seconds=0.04
road_diff selftest: GREEN: rebinding print cannot forge readback
road_diff selftest: RED: print rebinding: forged absence golden
road_diff: compared rebind_membership.eigs (6 runs)
road_diff: fixtures=1 runs=6 failures=0 seconds=0.05
road_diff selftest: GREEN: rebinding has_key/keys cannot forge readback
road_diff selftest: RED: has_key/keys rebinding: forged absence golden
road_diff: compared rebind_throw.eigs (6 runs)
road_diff: fixtures=1 runs=6 failures=0 seconds=0.05
road_diff selftest: GREEN: rebinding throw preserves return validation
road_diff selftest: RED: throw rebinding cannot suppress a return mismatch
road_diff selftest: RED: genuinely missing binding cannot impersonate present null
road_diff selftest: RED: nonzero rc with matching stdout
road_diff selftest: RED: stderr only with matching stdout and rc=0
road_diff selftest: GREEN: reference and two native configurations (18 runs)
road_diff selftest: GREEN: ARM64 policy explicitly runs only the interpreter
road_diff selftest: GREEN: lowered OSR threshold reaches the child
road_diff selftest: RED: lowered OSR threshold removed (stdout still matches)
road_diff selftest: RED: native tiers compiled nothing
road_diff selftest: RED: native mechanism statistics missing
road_diff selftest: RED: native metadata invalid value
road_diff selftest: RED: native metadata duplicate header
road_diff selftest: RED: exit before readback cannot forge completion
road_diff selftest: RED: invalid binding name is a named failure
road_diff: FAIL: zero fixtures
road_diff selftest: RED: zero fixtures
road_diff selftest: controls=8 plants=16 failures=0

bash tools/road_diff.sh --selftest --bad-binary   /home/jon/src/InauguralSystems/EigenScriptEcosystem/EigenScript/src/eigenscript
road_diff: compared planted.eigs (6 runs)
road_diff: fixtures=1 runs=6 failures=0 seconds=0.04
road_diff selftest: GREEN: numeric binding
road_diff selftest: RED: planted.eigs: roads/cwds diverge
road_diff: compared sentinel.eigs (6 runs)
road_diff: fixtures=1 runs=6 failures=0 seconds=0.04
road_diff selftest: GREEN: literal "<missing>" is present
road_diff selftest: RED: literal "<missing>" binding dropped (known-bad binary, import only)
road_diff: compared rebind_print.eigs (6 runs)
road_diff: fixtures=1 runs=6 failures=0 seconds=0.04
road_diff selftest: GREEN: rebinding print cannot forge readback
road_diff selftest: RED: print rebinding: dropped import binding (known-bad binary)
road_diff: compared rebind_membership.eigs (6 runs)
road_diff: fixtures=1 runs=6 failures=0 seconds=0.05
road_diff selftest: GREEN: rebinding has_key/keys cannot forge readback
road_diff selftest: RED: has_key/keys rebinding: dropped import binding (known-bad binary)
road_diff: compared rebind_throw.eigs (6 runs)
road_diff: fixtures=1 runs=6 failures=0 seconds=0.05
road_diff selftest: GREEN: rebinding throw preserves return validation
road_diff selftest: RED: throw rebinding cannot suppress a return mismatch
road_diff selftest: RED: genuinely missing binding cannot impersonate present null
road_diff selftest: RED: nonzero rc with matching stdout
road_diff selftest: RED: stderr only with matching stdout and rc=0
road_diff selftest: GREEN: reference and two native configurations (18 runs)
road_diff selftest: GREEN: ARM64 policy explicitly runs only the interpreter
road_diff selftest: GREEN: lowered OSR threshold reaches the child
road_diff selftest: RED: lowered OSR threshold removed (stdout still matches)
road_diff selftest: RED: native tiers compiled nothing
road_diff selftest: RED: native mechanism statistics missing
road_diff selftest: RED: native metadata invalid value
road_diff selftest: RED: native metadata duplicate header
road_diff selftest: RED: exit before readback cannot forge completion
road_diff selftest: RED: invalid binding name is a named failure
road_diff: FAIL: zero fixtures
road_diff selftest: RED: zero fixtures
road_diff selftest: controls=8 plants=16 failures=0

ONE release suite, using the requested cold standalone layout:
  ( rm -f src/eigenscript build/*/eigenscript; ./build.sh; cd tests && bash run_all_tests.sh )
The serial runner used && between build phases so a build failure could not
be hidden. Filtered embed section:
embed_roads: build=release (0 matching CLI variants; dedicated source build)
embed_roads: eval_file: HELPER / HELPER
embed_roads: eval_string deferred functions: HELPER / HELPER
embed_roads: eval_file from helper callback: HELPER / HELPER
embed_roads: eval_string load: HELPER / HELPER
embed_roads: eval_file import: HELPER / HELPER
embed_roads: eval_string import: HELPER / HELPER
embed_roads: checks=31 scope_checks=20 failures=0
embed_roads selftest: GREEN: standalone, unique, ambiguous, sanitizer layouts
embed_roads selftest: RED: execution-scope override
embed_roads selftest: RED: wrong helper peer
embed_roads selftest: RED: missing fixture tree
embed_roads selftest: RED: exit
embed_roads selftest: RED: stderr
embed_roads selftest: RED: zero_checks
embed_roads selftest: controls=5 plants=6 failures=0
  PASS: road differential and planted faults

  RESULTS: 4246/4246 passed, 0 failed

ONE ASan suite:
  make asan
  cd tests && ASAN_OPTIONS=detect_leaks=1 bash run_all_tests.sh
Filtered embed section:
embed_roads: build=asan (1 matching CLI variants; matching objects)
embed_roads: eval_file: HELPER / HELPER
embed_roads: eval_string deferred functions: HELPER / HELPER
embed_roads: eval_file from helper callback: HELPER / HELPER
embed_roads: eval_string load: HELPER / HELPER
embed_roads: eval_file import: HELPER / HELPER
embed_roads: eval_string import: HELPER / HELPER
embed_roads: checks=31 scope_checks=20 failures=0
embed_roads selftest: GREEN: standalone, unique, ambiguous, sanitizer layouts
embed_roads selftest: RED: execution-scope override
embed_roads selftest: RED: wrong helper peer
embed_roads selftest: RED: missing fixture tree
embed_roads selftest: RED: exit
embed_roads selftest: RED: stderr
embed_roads selftest: RED: zero_checks
embed_roads selftest: controls=5 plants=6 failures=0
  PASS: road differential and planted faults

  RESULTS: 4235/4235 passed, 0 failed
No leak-tally note or sanitizer error was reported.

make jit-smoke
  JIT smoke: all cases passed.

make  # restore release after ASan
bash tools/jit_diff.sh
jit_diff: OK (230 programs x {jit, osr} vs the interpreter; 4 arms adjudicated by replay; 0 ledgered)

Additional documentation checks:
  doc_drift: rc=0
  Doc examples: 78 checked, 78 passed, 0 failed, 5 skipped, 0 unreadable fence(s)
  rg -n -i 'forced.?osr|measured.*tier' docs README.md CHANGELOG.md tests/roads/README.md
  output: empty (rg rc=1)

Both full suites also passed the warning audit:
  all 456 compile invocations across 28 dry-run targets + 7 scripts carry
  -Werror=switch -Werror=comment -Werror=misleading-indentation.
The final serial runner verified unchanged source hashes across all final
gates. A subsequent hash check and git diff --check also passed. The CLI is
restored to build/release/eigenscript.

Brief discrepancy: the checked-in .github/workflows/ci.yml at 29532a4 uses
make asan for the ASan full-suite lane (line 500), and make valgrind followed
by tests/valgrind_smoke.sh for Valgrind (lines 610 and 614), rather than
build.sh/full-suite for both. Commands inspected:
  rg -n 'build.sh|make asan|make valgrind|valgrind_smoke' .github/workflows/ci.yml
Relevant output:
  500:        run: make asan
  610:        run: make valgrind
  614:        run: cd tests && bash valgrind_smoke.sh
The standalone-layout defect was independently reproduced and fixed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kpzyjv1SaLaqBf45FSFDhB
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A file's semantics depend on HOW IT WAS REACHED (main / import / load_file) — for-body scoping and top-level return both differ

1 participant