Files
AILang/docs/journals/2026-05-18-iter-embedding-abi-m1.1.md
T
Brummel e406d07d81 iter embedding-abi-m1.1 (DONE 7/7): Embedding-ABI M1 — scalar AILang fn callable from C/Rust
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.
2026-05-18 14:50:27 +02:00

26 KiB
Raw Blame History

iter embedding-abi-m1.1 — Embedding ABI M1: linkable artifact + scalar C entrypoint

Date: 2026-05-18 Started from: b0bd7efeaf (Tasks 13 committed at 818177d; Tasks 47 re-dispatched from 818177d) Status: DONE — all 7 tasks complete. Tasks 13 committed (818177d); Tasks 47 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 13 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 47 then completed cleanly on the corrected plan)

Summary

The Embedding-ABI M1 iter is complete across all 5 pipeline layers. Tasks 13 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 47. 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 MissingEntryMain baseline pin. Created examples/embed_noentry_baseline.ail (main-free module) + crates/ail/tests/embed_missing_main_baseline.rs (triple-assertion: non-zero exit + verbatim has 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.export schema field + workspace-wide threading. Added the field to FnDef after doc (verbatim plan doc-comment, #[serde(default, skip_serializing_if = "Option::is_none")]). Compile-driven enumeration via cargo build --workspace --all-targets --keep-going over two dependency-ordered waves threaded export: None into ~85 FnDef/AstFnDef literals across 18 files incl. all named blind-spot sites (codegen lib.rs:3320 missing_entry_main_is_error, design_schema_drift.rs:278, spec_drift.rs:256, hash_pin.rs, the in-source #[cfg(test)] mod tests literals, the mono.rs AstFnDef alias, the parse.rs/print.rs literals). cargo build --workspace exits 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 (golden b4662aa70839f60b). Full workspace test gate: 611/0. DONE_WITH_CONCERNS.
  • iter embedding-abi-m1.1.3: Form-A (export "<sym>") surface modifier. parse_export helper (faithful parse_doc mirror); parse_fn threaded (let mut export, Some("export") arm with duplicate-clause guard, unknown-attr string updated, Ok(FnDef{…}) uses parsed export); write_fn_def export 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 ModuleNameMismatch load 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.ail uses (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 *_rejected fail because no gate exists, 2 positives already pass). Added two CheckError Error variants (ExportNonScalarSignature(String,&'static str,String) / ExportHasEffects(String,Vec<String>)) after ConstHasEffects, their two code() arms, and the gate in check_fn after the param/ret well-formedness checks (gate order params→ret→effects, first-violation-wins, unconditional on f.export.is_some()). GREEN 6/6; combined fixture fails signature-first. Round-trip + full workspace green. DONE.
  • iter embedding-abi-m1.1.5: codegen Target::StaticLib. Added the Target enum next to AllocStrategy; threaded target through lower_workspace_inner; lower_workspace_with_alloc / lower_workspace pin Target::Executable; new public lower_workspace_staticlib_with_alloc. Gated the MissingEntryMain shape-check + the @main trampoline behind Target::Executable; the StaticLib arm emits one external define {cret} @<sym>(...) per (export …) fn forwarding to @ail_<module>_<fn> via the new fn_scalar_sig / llvm_scalar helpers. RED→GREEN IR-shape pin (no @main, has @backtest_step, forwards to @ail_embed_backtest_step_step; exe target still MissingEntryMain). In-source missing_entry_main_is_error pin byte-unchanged; codegen crate 0 failures. DONE_WITH_CONCERNS (the emit_ir-routes-via-lower_workspace plan note).
  • iter embedding-abi-m1.1.6: CLI ail build --emit=staticlib. Added the --emit clap field (value_parser = ["exe", "staticlib"], default exe) after alloc; branched Cmd::Build (emit == "staticlib"build_staticlib); added build_staticlib (verbatim build_to:22392294 shared prefix + has_export guard + lower_workspace_staticlib_with_alloc + two-archive clang -c/ar rcs tail) and the new shared run_cmd helper (confirmed no pre-existing equivalent). RED→GREEN CLI pin (libembed_backtest_step.a + libailang_rt.a produced; 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 — cc links libembed_backtest_step.a + libailang_rt.a, runs the host, backtest_step(0,3)=9 / backtest_step(9,4)=25, s == 25 assertion 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 is def_hash(&Def) -> String (the one crates/ailang-core/tests/hash_pin.rs uses). Resolved by mirroring hash_pin.rs exactly (wrap the FnDef in Def::Fn(...), call def_hash) — this is explicitly authorised by the plan's own Step-1 NOTE ("the implementer mirrors the exact hashing entry point that hash_pin.rs uses if the name differs"). Property and shape unchanged; recorded because the plan's literal symbol was wrong (planner pseudo-vs-reality class — the feedback_specs_need_concrete_code / feedback_plan_pseudo_vs_reality family).
  • iter embedding-abi-m1.1.4: the plan fixture embed_export_float_ok.ail uses (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.ail both use (app + …); codegen lowers to fadd/fmul double by 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.md became dirty in the working tree during this run (a ~98-line P2 "DESIGN.md → design/ role-split" milestone proposal, mtime mid-session). Phase 0's git status --porcelain was empty (clean start). Nothing in this iter writes roadmap.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 47 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 internal lower_workspace_inner call passes Target::Executable". Reality: emit_ir does NOT call lower_workspace_inner directly — it calls lower_workspace (codegen lib.rs:214), which now passes lower_workspace_inner(ws, AllocStrategy::Gc, Target::Executable). The plan's intent (the in-source missing_entry_main_is_error pin, which calls emit_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.rs imports std::path::{Path, PathBuf} but the test body uses only PathBuf — a transcribed unused import that raises unused_imports on every build. Implementer-mindset judgement: a verbatim copy that introduces a compiler warning is not the plan's intent; reduced to use 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::Con has exactly {name: String, args: Vec<Type>} — no mode field; the plan's matches! guard is correct. (b) declared_effs is already Vec<String> (per lib.rs declared_effs.into_iter().collect()), so the plan's conditional .into_iter().collect() conversion did NOT apply — .clone() matches ExportHasEffects(_, Vec<String>) exactly. (c) synth::llvm_type lowers Int"i64", Float"double" (synth.rs:17,21) — the plan's llvm_scalar is an exact mirror for the 2-scalar M1 subset; forwarder call types match @ail_<module>_<fn>'s emitted signature (also proven by the Task-7 E2E real cc link + run). (d) no pre-existing run_cmd helper in main.rs (only inline Command::new blocks) — adding it was correct per the plan. (e) ailang_core::Def is crate-root re-exported (ailang-core lib.rs:76) — ailang_core::Def::Fn valid in main.rs. (f) ailang_surface::load_workspace + ailang_check::check_workspace + Diagnostic.code: String are the exact main.rs:580581 public 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.py fires the tracked P2 *.bump_s / *.max_us known-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 codegen Target enum (every existing path pinned Executable), 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.py exit 0.
  • bench/architect_sweeps.sh exits 1 both with and without the DESIGN.md edit (pre-existing advisory residue, established carry-on adjudicated at milestone-close audit); 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 47 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 47, 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:580581 uses). load_workspaceailang_core::workspace::load_modules_withmodule_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.ail has (module backtest …) — spec-mandated, because the entry module name backtest is what produces libbacktest.a (Task 6), @ail_backtest_step and the exported C symbol backtest_step (Tasks 5/7, the spec headline host host.c declares extern int64_t backtest_step(...)). Stem is embed_backtest_stepModuleNameMismatch.
  • embed_export_str_param_rejected.ail → module bad_str_param; embed_export_io_rejected.ailbad_io; embed_export_effectful_rejected.ailbad; embed_export_adt_ret_rejected.ailbad_adt_ret; embed_export_float_ok.ailembed_float_ok. All stem-mismatched ⇒ every check_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 (backtestlibbacktest.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:

  1. 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/7 libbacktest.a math still holds since module stays backtest).
  2. Rename each fixture module to its filename stem ((module embed_backtest_step …), …) and re-derive the spec's C-symbol / lib<entry>.a story from embed_backtest_step (changes the spec headline; libembed_backtest_step.a, @ail_embed_backtest_step_step — almost certainly not what the spec wants).
  3. 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 how ail check actually 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 47 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 13 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 5259 / 167169) is that the exported C symbol is author-chosen and decoupled from ail_<module> mangling(export "backtest_step") is the contract; host.c asserts on backtest_step, which is invariant under module rename. So spec-faithfulness does not discriminate between the options; libbacktest.a / @ail_backtest_step are 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 illustrative libbacktest.a string.
  • examples/ is a flat shared corpus auto-enrolled in whole-corpus tests (roundtrip_cli); Option 1's examples/bad.ail / backtest.ail / bad_io.ail pollute it with collision-prone, non-self-describing names. Option 2 keeps the self-describing grouped embed_* set — a real maintainability argument in a ~100-file flat dir read by future LLM authors.
  • Option 2 (module = stem, C symbol stays backtest_step via 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_fndef_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 13 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 13, 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 47 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