Tasks 4-7 on the Boss-Repaired plan, completing the M1 iteration: - Task 4: check-side export-signature gate — CheckError variants ExportNonScalarSignature / ExportHasEffects (codes export-non-scalar-signature / export-has-effects), code() arms, check_fn gate (params->ret->effects, first-violation-wins, unconditional on f.export.is_some()). The clause-3 discriminator in code: effectful/non-scalar exports fail to typecheck. 6/6. - Task 5: codegen Target::StaticLib — Target enum, threaded param, @main/MissingEntryMain gated behind Target::Executable, one external @<sym> forwarder per export to @ail_<module>_<fn> (fn_scalar_sig/llvm_scalar). In-source missing_entry_main_is_error byte-unchanged. Lowering pin 2/2. - Task 6: CLI ail build --emit=staticlib — clap field, Cmd::Build branch, build_staticlib (verbatim build_to prefix + has_export guard + two-archive clang -c/ar rcs tail) + run_cmd. CLI pin 2/2. - Task 7: C-host E2E coherent-stop proof (cc links libembed_backtest_step.a + libailang_rt.a, backtest_step(0,3)=9 / (9,4)=25, s==25, exit 0) + DESIGN.md §"Embedding ABI (M1)" (scalar C ABI, provisional until M3). E2E pin 1/1. Independent Boss verification: E2E 1/1, gate 6/6, full workspace 0 failures, roundtrip_cli + design_schema_drift + spec_drift green, Invariant 1 holds (no new dep in core/codegen/runtime). 3 behaviour- neutral plan pseudo-vs-reality concerns in the journal. Default-exe codegen/runtime path byte-unchanged (check.py firing = tracked-P2 known-noise, audit-adjudicated). INDEX line added. Completes the M1 iteration (impl). Milestone-close audit + fieldtest (surface-touching) are the next pipeline steps.
26 KiB
iter embedding-abi-m1.1 — Embedding ABI M1: linkable artifact + scalar C entrypoint
Date: 2026-05-18
Started from: b0bd7efeaf
(Tasks 1–3 committed at 818177d; Tasks 4–7 re-dispatched from 818177d)
Status: DONE — all 7 tasks complete. Tasks 1–3 committed
(818177d); Tasks 4–7 implemented on the corrected plan and sit
unstaged in the working tree. The E2E coherent-stop proof
(embed_e2e.rs: cc link + run, s == 25, exit 0) is GREEN.
Tasks completed: 7 of 7 (Tasks 1–3 DONE + committed; Task 4
initially BLOCKED on a Boss plan-defect — fixture module≠stem —
resolved by Boss plan Repair [Design-decision 6] + re-dispatch;
Tasks 4–7 then completed cleanly on the corrected plan)
Summary
The Embedding-ABI M1 iter is complete across all 5 pipeline
layers. Tasks 1–3 landed in the first dispatch and were committed
(818177d) as a verified known-good subset: the CLI build-path
MissingEntryMain baseline pin (Task 1), the additive
FnDef.export: Option<String> schema field threaded across the
whole workspace via compile-driven enumeration with a hash-stability
golden pin (Task 2), and the Form-A (export "<sym>") surface
modifier with full parse/print/grammar lockstep and a byte-identical
round-trip (Task 3).
Task 4 was BLOCKED in the first dispatch on a Boss plan-defect
(fixtures declared module ≠ file-stem; the loader hard-enforces
module == file-stem at workspace.rs:438). The Boss Repaired the
plan (Design-decision 6: fixture (module …) == file stem; the
C symbol stays backtest_step via (export …), demonstrating spec
Decision 2's mangling-decoupling) and re-dispatched Tasks 4–7. On
the corrected plan all four landed cleanly: the check-side
scalar-only + effect-free export gate with two new CheckError
variants (export-non-scalar-signature / export-has-effects, the
clause-3 discriminator in code, Task 4); the codegen
Target::StaticLib mode suppressing @main/MissingEntryMain and
emitting one external @<sym> forwarder per export to
@ail_<module>_<fn> (Task 5); the CLI ail build --emit=staticlib
two-archive emit (libembed_backtest_step.a + libailang_rt.a,
Task 6); and the C-host E2E coherent-stop proof — cc links both
archives, calls backtest_step(0,3)=9, backtest_step(9,4)=25,
the s == 25 assertion holds, exit 0 (Task 7), plus the DESIGN.md
§"Embedding ABI (M1)" current-state subsection. Full workspace
green (0 failures); roundtrip_cli green; compile_check.py /
cross_lang.py exit 0; check.py fires only the tracked P2
*.bump_s / *.max_us known-noise envelope (plan Step 6: audit-
adjudicated, not a plan-level gate — the default-executable
codegen/runtime path is byte-unchanged). No clean-core dependency
added (Invariant 1).
Per-task notes
- iter embedding-abi-m1.1.1: CLI build-path
MissingEntryMainbaseline pin. Createdexamples/embed_noentry_baseline.ail(main-free module) +crates/ail/tests/embed_missing_main_baseline.rs(triple-assertion: non-zero exit + verbatimhas no \main` defDisplay substring [codegen lib.rs:129] + absent binary). GREEN on write; not-a-no-op confirmed;roundtrip_cli` green with the new fixture. DONE. - iter embedding-abi-m1.1.2: additive
FnDef.exportschema field + workspace-wide threading. Added the field toFnDefafterdoc(verbatim plan doc-comment,#[serde(default, skip_serializing_if = "Option::is_none")]). Compile-driven enumeration viacargo build --workspace --all-targets --keep-goingover two dependency-ordered waves threadedexport: Noneinto ~85FnDef/AstFnDefliterals across 18 files incl. all named blind-spot sites (codegen lib.rs:3320missing_entry_main_is_error, design_schema_drift.rs:278, spec_drift.rs:256, hash_pin.rs, the in-source#[cfg(test)] mod testsliterals, themono.rsAstFnDefalias, theparse.rs/print.rsliterals).cargo build --workspaceexits 0 (planner self-review item 7 gate met). DESIGN.md fn-JSON"export"line + drift test green (Recon Q2 confirmed: no nested-struct-key anchor forced). Hash pin green (goldenb4662aa70839f60b). Full workspace test gate: 611/0. DONE_WITH_CONCERNS. - iter embedding-abi-m1.1.3: Form-A
(export "<sym>")surface modifier.parse_exporthelper (faithfulparse_docmirror);parse_fnthreaded (let mut export,Some("export")arm with duplicate-clause guard, unknown-attr string updated,Ok(FnDef{…})uses parsedexport);write_fn_defexport emission block (doc → export → suppress → type order); form_a.md production +(export STRING)?+ prose paragraph. RED verified (unknown fn attribute \export``), then GREEN: round-trip gate byte-identical, surface crate 72/0, ailang-core 111/0. DONE. - iter embedding-abi-m1.1.4 (FIRST dispatch — BLOCKED, audit
trail): wrote the five plan fixtures + the verbatim gate pin; ran
it → RED for the WRONG reason (a
ModuleNameMismatchload failure, not the absence of the gate). BLOCKED — see Blocked detail + Boss resolution. No gate production code written; the WIP fixtures + RED test were discarded by the Boss for the re-dispatch. - iter embedding-abi-m1.1.4 (RE-dispatch — DONE): check-side
export-signature gate on the corrected plan (Design-decision 6,
module==stem). Recreated the five fixtures (module == file stem;
embed_export_float_ok.ailuses(app * a b)— no*.head)- the verbatim gate pin
crates/ailang-check/tests/embed_export_gate.rs. RED verified for the RIGHT reason (fixtures load cleanly, 4*_rejectedfail because no gate exists, 2 positives already pass). Added twoCheckErrorError variants (ExportNonScalarSignature(String,&'static str,String)/ExportHasEffects(String,Vec<String>)) afterConstHasEffects, their twocode()arms, and the gate incheck_fnafter the param/ret well-formedness checks (gate order params→ret→effects, first-violation-wins, unconditional onf.export.is_some()). GREEN 6/6; combined fixture fails signature-first. Round-trip + full workspace green. DONE.
- the verbatim gate pin
- iter embedding-abi-m1.1.5: codegen
Target::StaticLib. Added theTargetenum next toAllocStrategy; threadedtargetthroughlower_workspace_inner;lower_workspace_with_alloc/lower_workspacepinTarget::Executable; new publiclower_workspace_staticlib_with_alloc. Gated theMissingEntryMainshape-check + the@maintrampoline behindTarget::Executable; theStaticLibarm emits one externaldefine {cret} @<sym>(...)per(export …)fn forwarding to@ail_<module>_<fn>via the newfn_scalar_sig/llvm_scalarhelpers. RED→GREEN IR-shape pin (no@main, has@backtest_step, forwards to@ail_embed_backtest_step_step; exe target stillMissingEntryMain). In-sourcemissing_entry_main_is_errorpin byte-unchanged; codegen crate 0 failures. DONE_WITH_CONCERNS (theemit_ir-routes-via-lower_workspaceplan note). - iter embedding-abi-m1.1.6: CLI
ail build --emit=staticlib. Added the--emitclap field (value_parser = ["exe", "staticlib"], defaultexe) afteralloc; branchedCmd::Build(emit == "staticlib"→build_staticlib); addedbuild_staticlib(verbatimbuild_to:2239–2294shared prefix +has_exportguard +lower_workspace_staticlib_with_alloc+ two-archiveclang -c/ar rcstail) and the new sharedrun_cmdhelper (confirmed no pre-existing equivalent). RED→GREEN CLI pin (libembed_backtest_step.a+libailang_rt.aproduced; export-less module rejected with the zero-export error). Default-exe regression (floats E2E + Task-1 baseline) green. DONE. - iter embedding-abi-m1.1.7: E2E host harness + DESIGN.md
§"Embedding ABI (M1)". Wrote
crates/ail/tests/embed/host.c(spec headline host, verbatim) +crates/ail/tests/embed_e2e.rs. E2E GREEN —cclinkslibembed_backtest_step.a+libailang_rt.a, runs the host,backtest_step(0,3)=9/backtest_step(9,4)=25,s == 25assertion holds, exit 0 (the milestone coherent stop). Added the DESIGN.md §"Embedding ABI (M1)" subsection (verbatim prose, at##level for consistency with §"Mangling scheme"). Drift tests 8/8 + 8/8; full workspace 0 failures; bench trio per plan Step 6. DONE_WITH_CONCERNS (the dead-Path-import correction + the###-vs-##heading-level resolution).
Concerns
- iter embedding-abi-m1.1.2: the plan's RED-pin symbol
ailang_core::hash::content_hash_fn(&FnDef)does not exist. The real entry point isdef_hash(&Def) -> String(the onecrates/ailang-core/tests/hash_pin.rsuses). Resolved by mirroringhash_pin.rsexactly (wrap theFnDefinDef::Fn(...), calldef_hash) — this is explicitly authorised by the plan's own Step-1 NOTE ("the implementer mirrors the exact hashing entry point thathash_pin.rsuses if the name differs"). Property and shape unchanged; recorded because the plan's literal symbol was wrong (planner pseudo-vs-reality class — thefeedback_specs_need_concrete_code/feedback_plan_pseudo_vs_realityfamily). - iter embedding-abi-m1.1.4: the plan fixture
embed_export_float_ok.ailuses(app *. a b). There is no*.Float-multiply head in AILang — Float arithmetic uses the same typeclass-generic head as Int (examples/floats.ail/examples/mut_sum_floats.ailboth use(app + …); codegen lowers tofadd/fmul doubleby type). Per the plan NOTE ("if the Float-multiply surface differs, use the same head that example uses"), the fixture as written uses(app * a b). The fixture's role ("scalar+pure Float export passes the gate") is preserved. Recorded; not yet exercised (Task 4 BLOCKED before the gate ran). - INFRA (not iter-authored):
docs/roadmap.mdbecame dirty in the working tree during this run (a ~98-line P2 "DESIGN.md → design/ role-split" milestone proposal, mtime mid-session). Phase 0'sgit status --porcelainwas empty (clean start). Nothing in this iter writesroadmap.md; it was modified by an external/concurrent writer. It is path-disjoint from every iter file. Left untouched (roadmap.md is Boss-owned per CLAUDE.md; main HEAD sacrosanct). The Boss must decide independently whether to keep or discard it; it is NOT part of this iter's commit. (RESOLVED at Boss re-dispatch: committed separately as Boss roadmap maintenance — see Boss resolution. Not part of the Tasks 4–7 working tree.) - iter embedding-abi-m1.1.5 (plan pseudo-vs-reality, behaviour-
neutral): plan Task-5 Step 3(b) third bullet says "
emit_ir(line 197): its internallower_workspace_innercall passesTarget::Executable". Reality:emit_irdoes NOT calllower_workspace_innerdirectly — it callslower_workspace(codegen lib.rs:214), which now passeslower_workspace_inner(ws, AllocStrategy::Gc, Target::Executable). The plan's intent (the in-sourcemissing_entry_main_is_errorpin, which callsemit_ir, stays byte-unchanged) is delivered transitively and verified GREEN at Task-5 Step 7. Recorded because the plan's literal call-chain description was inaccurate (planner pseudo-vs-reality family); no behavioural deviation. - iter embedding-abi-m1.1.7 (plan-verbatim transcription defect,
corrected): the plan's verbatim Task-7
embed_e2e.rsimportsstd::path::{Path, PathBuf}but the test body uses onlyPathBuf— a transcribed unused import that raisesunused_importson every build. Implementer-mindset judgement: a verbatim copy that introduces a compiler warning is not the plan's intent; reduced touse std::path::PathBuf;. Test behaviour byte-identical (E2E still GREEN). Recorded as a deviation from plan-literal text in service of plan intent. - iter embedding-abi-m1.1.7 (plan code-block vs plan prose, design
consistency): plan Task-7 Step 4's code block shows the new
section as
### Embedding ABI (M1), but the same step's prose instruction says "at the same heading level as §"Mangling scheme"" — §"Mangling scheme" is##(level-2) in DESIGN.md. Used## Embedding ABI (M1)for structural consistency with the surrounding §"Mangling scheme" / §"Data model" level-2 sections, following the plan's explicit prose directive over its illustrative code-block#-count. Section content byte-verbatim. - iter embedding-abi-m1.1 (cross-checks, plan-confirming, no
deviation): the six named implementer-judgement cross-checks were
executed. (a)
Type::Conhas exactly{name: String, args: Vec<Type>}— no mode field; the plan'smatches!guard is correct. (b)declared_effsis alreadyVec<String>(perlib.rsdeclared_effs.into_iter().collect()), so the plan's conditional.into_iter().collect()conversion did NOT apply —.clone()matchesExportHasEffects(_, Vec<String>)exactly. (c)synth::llvm_typelowersInt→"i64",Float→"double"(synth.rs:17,21) — the plan'sllvm_scalaris an exact mirror for the 2-scalar M1 subset; forwardercalltypes match@ail_<module>_<fn>'s emitted signature (also proven by the Task-7 E2E realcclink + run). (d) no pre-existingrun_cmdhelper inmain.rs(only inlineCommand::newblocks) — adding it was correct per the plan. (e)ailang_core::Defis crate-root re-exported (ailang-core lib.rs:76) —ailang_core::Def::Fnvalid inmain.rs. (f)ailang_surface::load_workspace+ailang_check::check_workspace+Diagnostic.code: Stringare the exactmain.rs:580–581public symbols. All confirmations of plan assumptions, not contradictions.
Known debt
- None blocking. The M1 ABI is deliberately scalar-only and
provisional until M3 (no
Bool/Str/ADT/record marshalling, no per-thread context lifecycle API); this is reserved-unimplemented scope, labelled in DESIGN.md §"Embedding ABI (M1)", not debt. check.pyfires the tracked P2*.bump_s/*.max_usknown-noise envelope (3 regressed / 2 improved beyond tolerance / 58 stable; e.g.throughput.bench_list_sum.bump_s+13.95%,latency.explicit_at_rc.max_us+60.61%). This iter touched only check-side gating, a codegenTargetenum (every existing path pinnedExecutable), and CLI dispatch — none on the runtime hot path these metrics measure; the default-executable codegen/runtime path is byte-unchanged (Task-5 Step 7/8 + Task-6 Step 6 confirm). Per plan Step 6 this is milestone-close-audit-adjudicated, NOT a plan-level gate.compile_check.py/cross_lang.pyexit 0.bench/architect_sweeps.shexits 1 both with and without the DESIGN.md edit (pre-existing advisory residue, established carry-on adjudicated at milestone-closeaudit); the new §"Embedding ABI (M1)" introduced no new Wunschdenken / post- mortem phrasing (the "provisional until M3" / "M2 will change" clauses are labelled reserved-unimplemented, which the DESIGN.md honesty rule explicitly permits).
Blocked detail
RESOLVED (2026-05-18, re-dispatch). This block was a first-dispatch event; it was resolved by the Boss plan Repair (see "## Boss resolution" below — Design-decision 6, Option 2, module==stem) and the Tasks 4–7 re-dispatch completed all four tasks cleanly. The detail below is preserved verbatim as the iter's audit trail and is no longer an open block. Iter status is DONE.
Task: 4 (check-side export-signature gate)
Reason: spec-ambiguous (a spec-internal contradiction that
rippling-binds Tasks 4–7, surfaced as unclear per the per-task
sub-status table → BLOCKED to Boss).
Worker says: The plan's Task-4 gate pin
(crates/ailang-check/tests/embed_export_gate.rs) is verbatim and
correct Rust; it calls ailang_surface::load_workspace(&path) on
each fixture (the exact call shape crates/ail/src/main.rs:580–581
uses). load_workspace →
ailang_core::workspace::load_modules_with →
module_name_from_path (workspace.rs:1566) hard-enforces
in-file module name == file stem, returning
WorkspaceLoadError::ModuleNameMismatch (workspace.rs:182)
otherwise. The plan's verbatim fixtures deliberately violate this:
examples/embed_backtest_step.ailhas(module backtest …)— spec-mandated, because the entry module namebacktestis what produceslibbacktest.a(Task 6),@ail_backtest_stepand the exported C symbolbacktest_step(Tasks 5/7, the spec headline hosthost.cdeclaresextern int64_t backtest_step(...)). Stem isembed_backtest_step⇒ModuleNameMismatch.embed_export_str_param_rejected.ail→ modulebad_str_param;embed_export_io_rejected.ail→bad_io;embed_export_effectful_rejected.ail→bad;embed_export_adt_ret_rejected.ail→bad_adt_ret;embed_export_float_ok.ail→embed_float_ok. All stem-mismatched ⇒ everycheck_codes()call panics on load before the gate is ever consulted.
These three plan facts cannot all hold simultaneously: (a) fixture
files named examples/embed_* (every Task 4/5/6/7 path cites these
exact names), (b) the spec-headline module/C-symbol naming
(backtest → libbacktest.a / backtest_step), (c) a
load_workspace-based check-side gate pin. roundtrip_cli (Task 1/3)
sidesteps this only because it drives ail parse (single-file, no
workspace stem-match). The contradiction is therefore invisible until
the first load_workspace-based fixture test — exactly Task 4.
This is not one of the six named implementer-judgement cross-checks
(Float *. head, public-symbol confirmation, Type::Con field set,
declared_effs element type, run_cmd pre-existence, llvm_scalar
callee-ABI). It is a structural spec/plan defect requiring a
Boss/spec decision among at least:
- Rename each fixture file to its module stem
(
examples/backtest.ail,examples/bad_str_param.ail, …) and update every Task 4/5/6/7 path citation accordingly (preserves the spec headline module/C-symbol naming; ripples ~12 plan path references + the Task-6/7libbacktest.amath still holds since module staysbacktest). - Rename each fixture module to its filename stem
(
(module embed_backtest_step …), …) and re-derive the spec's C-symbol /lib<entry>.astory fromembed_backtest_step(changes the spec headline;libembed_backtest_step.a,@ail_embed_backtest_step_step— almost certainly not what the spec wants). - Change the Task-4 gate pin to a loader that does not
stem-enforce (e.g. parse the single file directly), which
diverges from the plan's verbatim
load_workspace-based test and from howail checkactually loads (main.rs:580).
Option 1 is the most spec-faithful (it keeps the headline module
backtest and only moves files), but it is a cross-task plan edit
(≥12 path citations) and therefore the planner's / Boss's call, not
an inline implementer substitution. I did NOT silently pick one
(reverted my own speculative fixture-module renames so the Boss sees
the contradiction unobscured); no gate production code was written.
Suggested next step: Boss adopts Option 1 — re-issue the plan
for Tasks 4–7 with fixture files renamed to their module stems
(examples/backtest.ail etc.) and the ~12 path citations updated;
keep module backtest so the spec's libbacktest.a /
backtest_step headline is preserved — then re-dispatch this iter
with task_range: [4, 7] (Tasks 1–3 are clean and can be committed
now or carried).
Boss resolution (2026-05-18)
The BLOCK was verified accurate against source:
crates/ailang-core/src/workspace.rs:438 (entry_module.name != module_name_from_path(entry_path) → ModuleNameMismatch, no
exception) — module name MUST equal file stem. The defect is a
Boss plan-write error: the plan's headline + gate fixtures
declared (module backtest) / (module bad) / … in embed_*.ail
files, malformed under that invariant. The orchestrator correctly
stopped at the Iron Law instead of guessing. Recon maps file
structure, not fixture-content invariants; the Boss source-
verification focused on code-edit anchors, not cross-checking each
fixture's module name against its filename against the loader —
this is the feedback_specs_need_concrete_code /
feedback_plan_pseudo_vs_reality family (the fixture as written
would not load), now also a fixture-well-formedness lesson.
Decision: Option 2, overriding the orchestrator-recommended
Option 1. (Agent recommendations are not directives — own
judgement formed first.) Keep the descriptive embed_* filenames;
rename the fixture modules to their file stems
(embed_backtest_step, embed_export_str_param_rejected, …).
Rationale from semantics, not effort:
- The spec's load-bearing contract (Decision 2, spec lines
52–59 / 167–169) is that the exported C symbol is author-chosen
and decoupled from
ail_<module>mangling —(export "backtest_step")is the contract;host.casserts onbacktest_step, which is invariant under module rename. So spec-faithfulness does not discriminate between the options;libbacktest.a/@ail_backtest_stepare illustrative (build-output filename + internal mangling — the latter is exactly what the spec decouples from), not frozen-ABI contracts. The orchestrator's "Option 1 most spec-faithful" over-weighted the illustrativelibbacktest.astring. examples/is a flat shared corpus auto-enrolled in whole-corpus tests (roundtrip_cli); Option 1'sexamples/bad.ail/backtest.ail/bad_io.ailpollute it with collision-prone, non-self-describing names. Option 2 keeps the self-describing groupedembed_*set — a real maintainability argument in a ~100-file flat dir read by future LLM authors.- Option 2 (module = stem, C symbol stays
backtest_stepvia the(export …)string) is a concrete demonstration of the spec's own Decision-2 decoupling thesis — the first fixture proving module-name ≠ C-symbol — not a violation of it. The spec's(module backtest)/(module bad)blocks are shape- illustrative (planner contract: spec owns shape, not bytes).
Consequence: entry module embed_backtest_step ⇒ archive
libembed_backtest_step.a, internal symbol
@ail_embed_backtest_step_step; the external C symbol
backtest_step and host.c are UNCHANGED (the actual coherent-
stop contract). Architect-at-close note recorded in the plan
(Design-decision 6): a fixture module name differing from the
spec's illustrative block is expected under module==stem +
Decision 2, not drift.
Actions taken: (1) plan docs/plans/embedding-abi-m1.1.md fixed —
Design-decision 6 added, Task-4 fixtures → module==stem, Task-5/6/7
dependent strings updated (libembed_backtest_step.a,
@ail_embed_backtest_step_step; C symbol @backtest_step
unchanged), the two iter-1 concerns folded (no *. Float head →
(app * a b); content_hash_fn → def_hash(&Def)); (2) the
already-created headline examples/embed_backtest_step.ail
corrected to (module embed_backtest_step); (3) the 5 blocked-
Task-4 fixtures + the RED embed_export_gate.rs discarded
(untracked WIP — recreated correctly by the re-dispatch from the
fixed plan); (4) Tasks 1–3 committed as a verified known-good
partial subset (cargo build --workspace exit 0, full workspace
green with zero FAILED after the WIP discard, roundtrip_cli
green); (5) orchestrator re-dispatched with task_range: [4, 7]
on the clean tree + corrected plan. The user's path-disjoint
roadmap addition (P2 "DESIGN.md → design/ role-split") was
committed separately as Boss roadmap maintenance, not bundled
into this iter.
Files touched
Committed at 818177d (Tasks 1–3, first dispatch)
Schema / canonical docs:
- crates/ailang-core/src/ast.rs (FnDef.export field)
- docs/DESIGN.md (fn-JSON "export" line)
- crates/ailang-core/specs/form_a.md (grammar production + prose)
Workspace-wide compile-gate threading (~85 export: None, literals):
- crates/ailang-core/src/desugar.rs, pretty.rs
- crates/ailang-core/tests/{design_schema_drift,hash_pin,spec_drift}.rs
- crates/ailang-check/src/{lib,lift,linearity,mono,reuse_shape,suppress_filter,uniqueness}.rs
- crates/ailang-check/tests/workspace.rs
- crates/ailang-codegen/src/lib.rs
- crates/ailang-prose/src/lib.rs
Surface modifier (Task 3):
- crates/ailang-surface/src/parse.rs (parse_export + parse_fn thread)
- crates/ailang-surface/src/print.rs (write_fn_def export block)
New files committed at 818177d:
- examples/embed_noentry_baseline.ail
- examples/embed_backtest_step.ail (corrected to
(module embed_backtest_step)) - crates/ail/tests/embed_missing_main_baseline.rs
- crates/ailang-core/tests/embed_export_hash_stable.rs
Tasks 4–7 re-dispatch working tree (UNCOMMITTED — this hand-off)
Modified (4 source/doc files):
- crates/ailang-check/src/lib.rs (2 CheckError variants + 2 code() arms + check_fn gate; +51)
- crates/ailang-codegen/src/lib.rs (Target enum + threaded target + forwarder loop + fn_scalar_sig/llvm_scalar; +130/-22)
- crates/ail/src/main.rs (--emit clap field + Cmd::Build branch + build_staticlib + run_cmd; +123)
- docs/DESIGN.md (new §"Embedding ABI (M1)" subsection; +24)
New files (untracked, this re-dispatch):
- examples/embed_export_str_param_rejected.ail
- examples/embed_export_adt_ret_rejected.ail
- examples/embed_export_io_rejected.ail
- examples/embed_export_effectful_rejected.ail
- examples/embed_export_float_ok.ail
- crates/ailang-check/tests/embed_export_gate.rs (GREEN 6/6)
- crates/ailang-codegen/tests/embed_staticlib_lowering.rs (GREEN 2/2)
- crates/ail/tests/embed_staticlib_cli.rs (GREEN 2/2)
- crates/ail/tests/embed/host.c
- crates/ail/tests/embed_e2e.rs (GREEN 1/1 — coherent-stop proof)
(docs/roadmap.md is NOT in this iter's working tree — the
first-dispatch external modification was Boss-committed separately
as roadmap maintenance, per the Boss resolution.)
Stats
bench/orchestrator-stats/2026-05-18-iter-embedding-abi-m1.1.json