Skip to content

hardening: CodeOfPolicies ABI canary, module vintage stamps, loud jit/GPU/tune failures - and overrides announce themselves - #3687

Merged
borisbat merged 2 commits into
masterfrom
bbatkin/jit-hardening
Aug 11, 2026
Merged

hardening: CodeOfPolicies ABI canary, module vintage stamps, loud jit/GPU/tune failures - and overrides announce themselves#3687
borisbat merged 2 commits into
masterfrom
bbatkin/jit-hardening

Conversation

@borisbat

Copy link
Copy Markdown
Collaborator

The hardening landing from the jit-infra fallout arc (follow-up to #3683): the stale-binary failure class gets code teeth, the remaining silent failures get loud, and the tune mint gets its dev-run escape. Plus a new review rule, applied to both checklists and implemented across the diff: an active override announces itself in the run's output.

1. CodeOfPolicies ABI canary (the night's root cause)

CodeOfPolicies now leads with an abi_stamp field whose default initializer — (DAS_POLICIES_VERSION << 24) | (sizeof(CodeOfPolicies) << 8) — compiles into whatever binary CONSTRUCTS the struct (the host exe), while parseDaScript/compileDaScript check it against libDaScript's own headers. A stale daslang.exe over a fresh DLL now dies with FATAL: CodeOfPolicies ABI stamp mismatch ... relink the host instead of silently reading every policy field (including jit_enabled) at shifted offsets.

  • The stamp's low byte is 0 by design, so a pre-canary libDaScript reading the word as its old leading bools still sees aot == false.
  • Computed by a static constexpr member (NSDMI is complete-class context), one source of truth.
  • Split into a testable predicate (checkCodeOfPoliciesStamp, covered by tests-cpp/small/test_policies_canary.cpp) + the fatal wrapper.

2. Module-vintage stamps

DAS_BUILD_ID only changes at releases, so a shared module rebuilt against DIFFERENT headers of the SAME version passes the existing gate and is silently, subtly wrong. REGISTER_DYN_MODULE now also exports vintage_dyn_<name> returning das_abi_vintage() — an FNV fold of DAS_BUILD_ID plus the sizeof of the core ABI surface (Module, Context, SimNode, Program, TypeDecl, ..., CodeOfPolicies, daScriptEnvironment). The loader compares and WARNS (never refuses) on mismatch or absence.

Field-verified: loading a same-version pre-vintage module (D:/Work/daScript/modules/dasAudio built from the main tree) into this binary prints the warning — and then the process AVs inside the drifted module, which is exactly the disease class; the log now names the culprit right before the crash. An old-VERSION module (DASPKG dasVulkan, 0.6.3) still hits the layer-1 build-id refusal unchanged.

3. Loud-failure trio

  • run_jit ending with ZERO functions to jit now logs a LOG_ERROR (the WHOLE program runs interpreted) instead of silently skipping the pipeline; the dll-mode-on-static-build downgrade is upgraded from a quiet warning to an error naming the stale-stub possibility.
  • lcpp_bench refuses (panics) any row where DASLLAMA_GPU* rails were requested but the GPU tier resolved CPU, distinguishing "no backend module registered" from "registered but did not arm" — and stamps the exec state (exe-native / jit / INTERPRETED) into the config line so a dead jit can never hide behind a normal-looking header.
  • load_model_cached logs a LOG_ERROR when GPU rails are wanted but no backend module ever registered — the require ?vulkan guard previously swallowed a failed shared_module load with zero diagnostics. The message includes the exact dlopen failures via a new das-visible builtin describe_pending_dynamic_modules (registered in das2rst groups, handmade doc included). New SPI predicates gpu_want_any / moe_gpu_backend_registered carry asserts in test_gpu_tier.das.

4. Tune remnants

  • Skip-mint: tune_suppress_mint(reason) is a new runtime seam in llvm_tune — a library [init] can suppress the auto/restart mint so untuned scopes keep fallback stamps (--tune still wins). dasLLAMA wires DASLLAMA_ALLOW_UNTUNED=1 to it: the dev-run escape now skips the minutes-long mint instead of only bypassing the measurement gate. Scope-test arm 13 proves it (no FAKE TUNER, fallback RESULT, no sidecar).
  • Exit-1 hunt, concluded: a controlled scratch-manifest tuner run reproduced it — the gen half completes its races, then the END-of-run noise gate refuses (the bracket must cover the whole window that produced the winners), aborts without writing, and exits 1. That is by-design refusal, previously a bare rc=1 at the log tail. dasllama_tuner now detects the refusal in the relayed output and closes with REFUSED for noise + the full escape ladder (DAS_TUNE_NOISE_CV recalibrates / DAS_TUNE_NOISE_OVERRIDE=1 mints anyway, stamped / DASLLAMA_ALLOW_UNTUNED=1 skips minting).
  • Drive-by: engine_sha()'s 2>/dev/null under cmd.exe redirected to a literal file path and leaked The system cannot find the path specified. into every tuner run — now 2>NUL on windows.

5. The override-announce rule

New CODEREVIEW.md entry in BOTH dasLLVM and dasLLAMA: a knob that changes what a run measures, mints, or emits beyond its defaults prints one line naming itself when set, silent when unset. Implemented for the current family:

  • DAS_TUNE_POLICY — announced at policy resolution (once per app compile).
  • DAS_TUNE_NOISE_CV — noise-gate threshold lines carry (DAS_TUNE_NOISE_CV); tuner banner prints the recalibrated gate (new query tune_noise_threshold_overridden).
  • DAS_TUNE_NOISE_OVERRIDE — announced in the tuner banner when set, not only when it fires.
  • DASLLAMA_ALLOW_UNTUNED — unconditional LOG_WARNING at [init] when set.

Validation

  • tests-cpp-small 81/81 (1.10M assertions) including the new canary case; full tests/ suite green (two apparent fs/lsp reds were artifacts of a relative -dasroot . in the runner invocation, both pass with a proper root); JIT smoke clean.
  • llvm_tune_scope all 13 arms green under -jit; test_gpu_tier green.
  • Lint (CI-exact changed-set form): 13 files, 0 issues — including removing a stale nolint:PERF030 in dasllama_gpu_tier.das that the sweep surfaced. Format clean; --ast-verify -compile-only clean on every changed .das.
  • das2rst: new function grouped, stub filled, no Uncategorized, no untracked generated files.
  • ENVIRONMENT.md regenerated from the widened allow_untuned declaration.

Notes for review: the NOISE GATE string-scan in dasllama_tuner.run_half is a display affordance over the relayed child stream (the structured alternative would be a new @tune event; deliberately not taken here). LLVM_JIT_CODEGEN_VERSION is unbumped on purpose — no IR generation, target-machine, or ABI change in this diff.

🤖 Generated with Claude Code

https://claude.ai/code/session_01H3CQmhA327qR2RyKZCKvj6

… jit/GPU/tune failures - and active overrides announce themselves

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H3CQmhA327qR2RyKZCKvj6
Copilot AI lite review requested due to automatic review settings August 11, 2026 01:18

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens daslang against stale-binary / ABI-drift failure modes by adding an ABI canary for CodeOfPolicies, introducing per-dynamic-module “vintage” stamps, and making previously silent JIT/GPU/tune downgrade paths emit loud, self-diagnosing output (including a new “overrides announce themselves” review rule).

Changes:

  • Add CodeOfPolicies::abi_stamp + verification at parseDaScript/compileDaScript, with a dedicated C++ test.
  • Add dynamic-module ABI “vintage” export via REGISTER_DYN_MODULE and warn on mismatch/missing stamp at load time; expose pending module-load failures to das via describe_pending_dynamic_modules.
  • Make tuning/JIT/GPU rails failures and override knobs explicit in logs, docs, checklists, and tests (including tune mint suppression via tune_suppress_mint).

Reviewed changes

Copilot reviewed 24 out of 24 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests-cpp/small/test_policies_canary.cpp New doctest coverage for the CodeOfPolicies ABI canary predicate.
src/builtin/module_builtin_fio.cpp Warn on dyn-module vintage mismatch; add das-visible describe_pending_dynamic_modules binding.
src/ast/ast_parse.cpp Enforce the CodeOfPolicies ABI stamp at parse/compile entry points.
include/daScript/ast/ast.h Introduce abi_stamp + versioned stamp computation and das_abi_vintage(); export per-module vintage symbol.
doc/source/stdlib/handmade/function-fio-describe_pending_dynamic_modules-0x4bb5b7686cbfbdfb.rst Handmade stdlib doc stub for the new fio function.
doc/reflections/das2rst.das Ensure describe_pending_dynamic_modules is grouped in das2rst output.
modules/dasLLVM/daslib/llvm_jit_run.das Make “dll mode requested but static build” and “0 functions jitted” cases loud errors.
modules/dasLLVM/daslib/llvm_tune.das Add tune_suppress_mint and explicit override announcements for tune policy/noise rails.
modules/dasLLVM/tests/llvm_tune_scope.das Add a new test arm proving tune_suppress_mint prevents minting and keeps fallback stamps.
modules/dasLLVM/tests/llvm_tune_scope_client_suppress.das New client fixture that suppresses mint from a library [init].
skills/llvm_tune.md Document the new runtime mint-suppression seam and its precedence rules.
modules/dasLLVM/CODEREVIEW.md Add the “active overrides announce themselves” checklist rule for dasLLVM.
modules/dasLLAMA/dasllama/dasllama_gpu_tier.das Add gpu_want_any and moe_gpu_backend_registered to disambiguate rail intent and backend absence.
modules/dasLLAMA/tests/test_gpu_tier.das Extend tests for the new GPU-tier intent/registration predicates.
modules/dasLLAMA/dasllama/dasllama_image.das Emit a loud error when GPU rails are requested but no backend module registered; include dlopen failure details.
modules/dasLLAMA/benchmarks/lcpp_bench.das Refuse GPU-flagged benchmark rows when the GPU tier resolved CPU; stamp execution state into config output.
modules/dasLLAMA/harness/tuner_noise.das Tag noise-gate output when DAS_TUNE_NOISE_CV recalibrates; fix Windows stderr redirection.
modules/dasLLAMA/harness/dasllama_tuner.das Detect noise-gate refusal and make the final rc!=0 line self-diagnosing; announce noise overrides up front.
modules/dasLLAMA/dasllama/dasllama_math_gen.das Wire DASLLAMA_ALLOW_UNTUNED=1 to tune_suppress_mint and log the active override.
modules/dasLLAMA/dasllama/dasllama_env.das Update DASLLAMA_ALLOW_UNTUNED docstring to include mint suppression behavior.
modules/dasLLAMA/performance/profile_common.das Clarify allow-untuned behavior in tune summary docs.
modules/dasLLAMA/ENVIRONMENT.md Regenerate env docs reflecting allow-untuned mint suppression.
modules/dasLLAMA/BRINGUP.md Update bring-up guidance to note allow-untuned also suppresses auto-mint.
modules/dasLLAMA/CODEREVIEW.md Add the “active overrides announce themselves” checklist rule for dasLLAMA.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/builtin/module_builtin_fio.cpp
…s, Context::setup canary, the shared gpu_want_arms_tier predicate, metal-world guards, noise-refusal escapes honesty, both checklists rewritten per their own self-review

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H3CQmhA327qR2RyKZCKvj6
Copilot AI review requested due to automatic review settings August 11, 2026 02:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 29 out of 29 changed files in this pull request and generated no new comments.

@borisbat
borisbat merged commit a1628c2 into master Aug 11, 2026
38 checks passed
@borisbat
borisbat requested a lite review from Copilot August 11, 2026 03:25

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 29 out of 29 changed files in this pull request and generated no new comments.

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.

2 participants