audit + close: intrinsic-bodies — honest prelude docs + lockstep table + stale-model fix (refs #9)

Milestone close for intrinsic-bodies (.1 mechanism 52ff873 + .2
migration/lock caa3618). Architect drift review over c42034b^..caa3618
plus the regression scripts. Both gates assessed; four drift items
resolved (3 fixed inline here, 1 filed to backlog).

Regression: both scripts exit 0.
  bench/check.py        → 34 metrics, 0 regressed, 2 improved beyond
                          tolerance (bench_hof_pipeline.bump_s -10.76%,
                          bench_list_sum_explicit.bump_s -12.27%), 32 stable.
  bench/compile_check.py → 24 metrics, 0 regressed, 24 stable.
  The milestone is behaviour-preserving; the two throughput improvements
  are noise within the bench's run-to-run band, not a milestone effect.

Drift items (architect):

1. [FIXED] examples/prelude.ail — the 13 migrated defs' doc strings
   still said "Body is placeholder for round-trip stability" and named
   `try_emit_primitive_instance_body` (the pre-raw-buf.1 dispatch fn).
   Post-migration the body IS an honest (intrinsic) marker, not a
   placeholder, and dispatch is `intercepts::lookup`. The docs lied
   about the very artefact the milestone exists to de-lie — an active
   honesty-rule infraction on main. Rewritten to present-tense
   "compiler-supplied (intrinsic) body; codegen emits <IR> via the
   intercept registry" across all 13 (7 Eq/Ord instance methods +
   6 float_* fns).

2. [FIXED] design/models/0007-kernel-extensions.md — claimed the
   `try_emit_primitive_instance_body` hardcoded list is "not yet
   migrated into a plugin registry ... deferred to the Series
   milestone". Stale since raw-buf.1 (the registry shipped) and
   intrinsic-bodies (the (intrinsic) marker + bijection pin). Rewritten
   to the present state: the registry exists, (intrinsic) declares
   membership, the bijection pin locks marker<->entry, and the
   optimisation-only class is named.

3. [FIXED] CLAUDE.md "Lockstep-invariant pairs" — added the third pair:
   INTERCEPTS entries <-> (intrinsic) markers, guarded by
   intercepts_bijection_with_intrinsic_markers, with the
   optimisation-only allowlist carve-out. Same class as the two existing
   tabled pairs; ships silently broken if one side moves without the
   other.

4. [BACKLOG #41, label idea] INTERCEPTS conflates two concepts —
   intrinsic-backed (compiler-supplied body) vs optimisation-of-a-
   real-body (the 5 *__Int icmp family). The .2 bijection pin contains
   it with a hardcoded OPTIMISATION_ONLY allowlist + a stale-allowlist
   guard; a structural split (an Intercept kind field) is the
   forward direction but is its own focused change, out of scope here.

What holds (architect confirmed): data-model contract matches the
shipped Term::Intrinsic (design_schema_drift gates it); no INDEX row
needed (data-model addition, not a new contract); both existing
lockstep pairs untouched (answer lowers via the ordinary qualified-fn
path, no new lower_app arm; no Pattern::Lit reject); 0007-honesty-rule
correctly needed no edit (general rule, never named the dummies).

RATIFY — baseline move: the prelude module hash pin
(crates/ailang-surface/tests/prelude_module_hash_pin.rs) moves
2ea61ef21ebc1913 -> b1373a2c69e70a3f. Cause: this tidy's 13 doc-string
rewrites (item 1). doc is part of the canonical JSON, so the module
hash shifts; behaviour is unchanged. The 6 mono eq/compare def-hashes
do NOT move (synthesise_mono_fn sets doc: None, so instance-method docs
never reach the synthesised symbol). Full workspace test green
post-rebaseline.

Milestone intrinsic-bodies is closed. It unblocks the raw-buf.2 redo
(the polymorphic kernel-tier fns RawBuf needs now have an honest body
form). raw-buf (#7) remains parked; resuming it is a fresh decision.
This commit is contained in:
2026-05-29 17:56:10 +02:00
parent caa3618c3e
commit 6ccc756c0f
4 changed files with 37 additions and 26 deletions
+15 -12
View File
@@ -568,18 +568,21 @@ Concrete state after the mechanisms milestone closed (2026-05-28):
regression pin); the code path no longer hardcodes any module
name as special.
- Codegen intercepts: the pre-existing `try_emit_primitive_instance_body`
hardcoded list is **not yet** migrated into a plugin registry
that migration is deferred to the Series milestone, when there
is the first real external consumer and the mechanism can
graduate from "hardcoded for one case" to "registry for many
cases". Single-consumer registries are premature mechanism.
The reason migration cost is not a decision driver: there is
nothing to break externally, and rewrites inside the workspace
are cheap. Choosing the right design now is the priority; cost
of refactoring tests and fixtures is the project's own problem
and is amortised over zero external consumers.
- Codegen intercepts: the compiler-supplied implementations of the
prelude's primitive Eq/Ord/Float operations live in a registry,
`crates/ailang-codegen/src/intercepts.rs::INTERCEPTS`. A
kernel-tier or prelude definition whose body is the `(intrinsic)`
marker (`Term::Intrinsic`) declares membership in that registry;
codegen routes it through `intercepts::lookup` on its mangled
name. The pairing is locked by
`intercepts_bijection_with_intrinsic_markers`: every intrinsic
marker reachable in the loaded workspace resolves to a registry
entry, and every registry entry not on the optimisation-only
allowlist has a marker. The registry also carries an
optimisation-only class — entries that intercept the
monomorphised `__Int` specialisation of a real-bodied polymorphic
free fn (`lt/le/gt/ge/ne`) for a faster direct `icmp`; those have
a real source body and no marker.
## Coexistence with existing mechanisms