# iter embedding-abi-m5.1 — lean `ail-embed` core + build.rs + hermetic smoke

**Date:** 2026-05-19
**Started from:** 22f02aa26b57c478760265dfc6468b54d35c7cdc
**Status:** DONE
**Tasks completed:** 3 of 3

## Summary

Stood up the workspace-excluded `ail-embed` crate: a zero-dependency
embedding core that links the M3-frozen staticlib via a `build.rs`
and folds a price stream through the frozen `(State, Tick) -> State`
C ABI, plus a hermetic `data-server` smoke test proving the real
adapter wiring without `/mnt`. The crate is its own cargo workspace
root (not an AILang `[workspace]` member); `data-server` is a
dev-dependency only, so Invariant 1 holds in the dependency graph,
mechanically verified by both the `cargo metadata` grep (Task 1
Step 7 → `0`) and the `git status` path filter (Task 3 Step 4 →
empty). Zero diff to `crates/ailang-*`, `crates/ail/`, `runtime/`,
`examples/*.ail`. Both ratifying tests are green
(`kernel_run_sums_prices` unit + `hermetic_smoke_data_server_roundtrip`
integration; 2/0). Two minimal, toolchain-forced corrections to the
plan's verbatim `ail-embed/Cargo.toml` were required (see Concerns) —
neither alters the iter's intent or any acceptance gate.

## Per-task notes

- iter embedding-abi-m5.1.1: Scaffold the workspace-excluded crate +
  build.rs. Created `ail-embed/{Cargo.toml,.gitignore,src/lib.rs
  (stub),build.rs}`; appended the deliberate-non-membership comment
  to the root `Cargo.toml` members block (verbatim). Build gate
  PASS, `cargo metadata … grep -c data-server` == 0. RED-first N/A
  (build-infra de-risking task; verification is the build+metadata
  gate, which the plan scripts).
- iter embedding-abi-m5.1.2: The lean embedding core. RED-first
  honored: wrote the test-only `src/lib.rs` first, observed RED
  (`unresolved import \`super::Kernel\``, exactly the plan's
  expected reason), then prepended the verbatim impl block
  (`extern "C"` ABI, `Ctx` + frozen-layout box helpers + `Drop`,
  `Kernel::new`/`run`, `Default`). GREEN: `kernel_run_sums_prices`
  1/0.
- iter embedding-abi-m5.1.3: Hermetic data-server smoke. Created
  `ail-embed/tests/smoke.rs` verbatim (synthetic Pepperstone ZIP
  fixture → real `DataServer` → `Kernel` fold → bit-exact assertion
  vs host reference and against the closed-form `55.0`). Test-only
  task (no separate RED). Full suite 2/0; Invariant-1 path filter
  empty.

## Concerns

- iter .1 (DONE_WITH_CONCERNS): the plan's verbatim
  `ail-embed/Cargo.toml` could not satisfy its own Step 6 build gate
  as written. Two minimal toolchain-forced corrections, both confined
  to the in-scope plan-created `ail-embed/Cargo.toml`, neither
  changing iter intent or any acceptance gate:
  1. Added an empty `[workspace]` table. Cargo hard-errors on a
     nested package that "believes it's in a workspace when it's
     not"; the empty table is cargo's documented mechanism for a
     deliberately workspace-excluded nested crate (and is what makes
     the Step 7 metadata grep return `0` — the AILang root manifest
     no longer traverses into `ail-embed`). A comment at the table
     records the rationale.
  2. Corrected the `data-server` dev-dep path from
     `../libs/data-server` to `../../libs/data-server`. The crate
     lives at `/home/brummel/dev/libs/data-server` — a sibling of
     the repo *directory*, one level above the repo root. From
     `ail-embed/Cargo.toml`, `../` is the repo root, so the plan's
     literal resolved to the non-existent
     `repo/libs/data-server`. The plan's read-only cross-reference
     anchors (`../libs/data-server/...`) are written from the
     repo-root cwd and are correct *there*; only the manifest path
     literal, resolved relative to `ail-embed/`, needed the extra
     `../`. `build.rs` is unaffected (it never references
     data-server; it computes `repo = manifest.parent()`).

  Plan-template implication for the orchestrator: planner path-recon
  for a workspace-excluded nested crate should (a) emit the empty
  `[workspace]` table in the manifest template and (b) resolve
  sibling-dependency paths relative to the *manifest's* directory,
  not the repo-root cwd the anchors are written from.

## Known debt

- No `examples/*.ail.json` + `crates/ail/tests/e2e.rs` E2E fixture
  added. Deliberate, not a gap: this iter ships zero compiler-surface
  change (mechanically enforced by Task 3 Step 4 — adding a fixture
  under `examples/` or `crates/ail/tests/` would itself break the
  iter's Invariant-1 acceptance). The milestone invariant
  ("M3-frozen staticlib embeds + folds bit-exactly via the C ABI;
  data-server is a dev-only meeting point") is already protected by
  the two tests this iter ships. Standard E2E protects compiler
  invariants; there is none to protect here.
- Adapter API + thread-swarm are explicitly deferred to embedding-abi
  iter 2+ per the plan and spec — not touched, not debt of this iter.

## Blocked detail

N/A — DONE.

## Files touched

- Modified: `Cargo.toml` (root — 4-line non-membership comment after
  the `members` array; no other change)
- Created: `ail-embed/Cargo.toml`, `ail-embed/.gitignore`,
  `ail-embed/build.rs`, `ail-embed/src/lib.rs`,
  `ail-embed/tests/smoke.rs`
- Untracked build artefacts under `ail-embed/target/` are
  `.gitignore`d by `ail-embed/.gitignore`.

## Stats

bench/orchestrator-stats/2026-05-19-iter-embedding-abi-m5.1.json
