Files
AILang/docs/journals/2026-05-13-iter-form-a.1.md
T
Brummel 9fdc4cacff iter form-a.1 (Tasks 6-12): milestone close
Second half of the form-a-default-authoring milestone-close iter
(Boss-decided strategy C, big-bang). All seven tasks DONE; cargo
test --workspace green at every per-task boundary.

T6 — Bench-driver suffix flip from .ail.json to .ail across 4
Python scripts + run.sh. compile_check.py + cross_lang.py exit 0.

T7 — Re-author e2e.rs raw-JSON-inspect tests:
- diff_detects_changed_def — derive sum.ail.json on-the-fly via
  `ail parse examples/sum.ail` into tempdir, then mutate + diff.
- borrow_own_demo_modes_are_metadata_only — same pattern.
- reuse_as_demo_under_rc_uses_inplace_rewrite — same pattern.
- render_parse_round_trip_canonical — RETIRED (subsumed by T1's
  cli_parse_then_render_then_parse_is_idempotent over whole corpus).
- ail_run_accepts_ail_source_with_same_stdout_as_ail_json —
  re-authored to derive hello.ail.json in a per-process tempdir
  from hello.ail via `ail parse`, then assert dual-form stdout.

T8 — Bulk-delete 156 non-carve-out .ail.json. Inventory:
8 .ail.json (carve-outs, alphabetical: broken_unbound + prelude
+ 3× test_22b2_* + 3× test_ct1_*) + 157 .ail. carve_out_inventory
test un-#[ignore]'d and green. Forward-pulled 20 repairs that the
T1-5 dispatch's recon missed (12 Group-B suffix + 5 Group-A
load_workspace + 3 ail_run sites). Also forward-pulled T9 Step 5
(schema_coverage corpus flip from .ail.json to .ail) to satisfy
T8's green-gate.

T9 — Retire obsolete roundtrip tests:
- print_then_parse_round_trips_every_fixture (round_trip.rs)
- every_ail_fixture_matches_its_json_counterpart (round_trip.rs)
- cli_render_then_parse_preserves_canonical_bytes_on_every_fixture
- Dead helpers: list_json_fixtures ×2, round_trip_one,
  strip_trailing_newlines.
Schema-coverage corpus already flipped in T8 (forward-pull).

T10 — DESIGN.md §"Roundtrip Invariant" (lines 2027-2109) restated
with parse-determinism + idempotency + CLI-pipeline-idempotency +
carve-out-anchor framing. Five surviving enforcement tests named.
§"Float literals" and §"Why anchored at top level" preserved.

T11 — §A4 doctrine edits: CLAUDE.md:5-6 + DESIGN.md:465-466.
Canonical form remains JSON-AST; authoring projection is .ail;
build derives JSON-AST in-process via ailang_surface::parse.

T12 — Milestone close:
- WhatsNew entry: user-facing language, lead with the change.
- Roadmap: [milestone] form-a struck [x] with closing note.
- Final inventory verified: 8 .ail.json + 157 .ail.
- Final cargo test --workspace: 557 passed, 0 failed, 3 ignored.
- bench/compile_check.py + bench/cross_lang.py: exit 0.

Test math: pre-iter 558 baseline + 3 new T1 tests = 561, − 1
(T7 retire) − 3 (T9 retire) = 557 final.

INDEX.md appended with the full iter summary covering T1-T12 (the
T1-5 commit at 77b28ad deferred the INDEX line to full-iter close).

Milestone [Form-A as the default authoring surface] structurally
closed. The compile-time-embed carve-out (prelude.ail.json) is
the subject of the queued follow-up milestone [Prelude embed:
Form-A as compile-time source]. audit-form-a runs as the next
dispatch.
2026-05-13 11:31:39 +02:00

432 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# iter form-a.1 — Big-bang migration (Tasks 1-5: additive phase + relocation)
**Date:** 2026-05-13
**Started from:** 1a065b37 (post-iter 24.tidy)
**Status:** DONE (Tasks 1-5 only; Tasks 6-12 deferred to next dispatch)
**Tasks completed:** 5 of 12
## Summary
First half of the form-a-default-authoring milestone-close iter: T1
adds three new tests (parse-determinism + CLI-pipeline-idempotency +
carve-out-inventory-but-`#[ignore]`'d), T2 bulk-renders the 99
missing `examples/<stem>.ail` files via `ail render` (corpus 58 →
157), T3 + T4 migrate ~26 test files from `ailang_core::load_workspace`
to `ailang_surface::load_workspace` (Group A) and flip subprocess
fixture-suffix strings from `.ail.json` to `.ail` (Group B), T5
relocates `#[cfg(test)] mod tests` blocks from production source
(`ailang-core/src/hash.rs`, `ailang-core/src/workspace.rs`
non-carve-out subset, `ailang-codegen/src/lib.rs:3717-3799`) to
integration test crates that carry `ailang-surface` as a
dev-dependency, eliminating the production-source dependency on
`.ail.json` fixture reads. The remaining Tasks 6-12 (bench-driver
suffix flips, e2e diff-test rewrite, the actual 156-file
`.ail.json` deletion, retiring obsolete roundtrip tests +
schema_coverage corpus flip, DESIGN.md §Roundtrip Invariant
restatement, CLAUDE.md + DESIGN.md doctrine edits, WhatsNew +
roadmap close) run in the Boss's next dispatch on this iter ID.
`cargo test --workspace` is green at every per-task boundary (560
passed + 4 ignored at iter-half close; 558 + 3 new 1 transit
`#[ignore]` on the inventory test). One Task-2 plan defect surfaced
inline and was repaired by pre-emptive forward-pull of Task-3
migrations.
## Per-task notes
- **iter form-a.1.1** — Added `parse_is_deterministic_over_every_ail_fixture`
(round_trip.rs) and `cli_parse_then_render_then_parse_is_idempotent`
(roundtrip_cli.rs); created `crates/ailang-core/tests/carve_out_inventory.rs`
with the 8-file hardcoded list and `#[ignore]`'d until Task 8.
The plan's `cli_parse_then_render_then_parse_is_idempotent` body
used an `ail()` helper that doesn't exist in the repo (assert_cmd
is not a dev-dep); adapted to use `Command::new(ail_bin())`
matching the file's existing pattern. Plan acknowledged this
possibility — "verify before writing the body; if `list_ail_fixtures`
is missing in roundtrip_cli.rs, add a parallel helper at lines 47+."
- **iter form-a.1.2** — Rendered the 99 missing `.ail` files. The
bulk render exposed a recon defect: `load_workspace` (since
ext-cli.1) prefers `.ail` siblings for *imports* even when the
entry is `.ail.json`. The seven Group-A test files whose entries
were `.ail.json` but whose imports gained newly-rendered `.ail`
siblings broke at Task 2's green-gate. Repair pulled forward five
Task-3 migrations (mono_xmod_ctor_pattern, 3 sites in
typeclass_22b2, 1 site in typeclass_22b3, env_construction_pin,
4 sites in ailang-check/tests/workspace.rs, ctt2_registry_rekey)
plus `#[ignore]`'d the 4 fixture-loading tests in
`ailang-core/src/workspace.rs` `mod tests` with explicit
`form-a.1 transit: Task 5 relocates...` markers. Also added
`ailang-surface = { path = "../ailang-surface" }` to
`crates/ailang-core/Cargo.toml` `[dev-dependencies]` (required
for the ctt2_registry_rekey integration test to use
`ailang_surface::load_workspace`).
- **iter form-a.1.3** — Finished Group A migration across the
remaining 12 Group-A files (10 + the 2 already migrated in T2
scope-pull). Two files (`mono_recursive_fn.rs`,
`mono_xmod_qualified_ref.rs`) were Group-B-pattern (subprocess
CLI, suffix-only flip) but listed in plan's Group A; treated
per their actual shape.
- **iter form-a.1.4** — Group-B migration: bulk regex flip of
`build_and_run("X.ail.json")``build_and_run("X.ail")` (3
patterns) in e2e.rs across 59 invocations; plus targeted
subprocess `examples/<fixture>.ail.json``.ail` flips at 11
more e2e.rs sites (6× `ws_main`, 2× `sum`, 1× `escape_local_demo`,
1× `list_map_poly`, 1× `std_either` left as-is per its raw-bytes
roundtrip semantics). Four additional sites in e2e.rs preserved
intentionally for raw-JSON inspection (`borrow_own_demo`,
`reuse_as_demo`, the `sum.ail.json` diff-test pending Task 7
rewrite, and the `ail_run_accepts_ail_source...` dual-form smoke).
Four plan-Group-B files (`mono_hash_stability`, `prelude_free_fns`,
`print_mono_body_shape`, `show_mono_synthesis`) were
Group-A-pattern (consumers of `load_workspace`); migrated both
imports AND paths.
- **iter form-a.1.5** — Relocated 10 fixture-loading tests from
`ailang-core/src/workspace.rs` `mod tests` to new
`crates/ailang-core/tests/workspace_pin.rs` (integration test
crate); relocated all 8 tests from `ailang-core/src/hash.rs`
`mod tests` plus 2 in-memory unit tests to
`crates/ailang-core/tests/hash_pin.rs`; relocated 3 tests from
`ailang-codegen/src/lib.rs:3717-3799` to
`crates/ailang-codegen/tests/eq_primitives_pin.rs`; migrated
`ailang-prose/tests/snapshot.rs` (helper + 8 fixtures) to `.ail`
+ `ailang_surface::load_module`. Carve-out tests stay in-place
(3× `class_param_in_applied_position` / `superclass_with_wrong_param`
/ `constraint_with_unbound_var` for 22b2; 3× `ct1_fixture_*`
for ct.1). Tempdir-based loader tests
(`user_module_named_prelude_is_rejected`, `detects_import_cycle`,
`module_not_found_yields_structured_error`) stay in-place too —
they don't consume the examples corpus, so they don't need
migration for the Form-A goal. Added `ailang-surface` as a
`[dev-dependencies]` entry to `ailang-codegen/Cargo.toml` and
`ailang-prose/Cargo.toml`. Hash.rs has `mod tests {}` placeholder
kept; workspace.rs `mod tests` shrunk from 73 to 57 tests +
6 carve-outs unchanged.
## Concerns
- **e2e.rs raw-JSON-inspect tests** (4 sites: `borrow_own_demo_modes_are_metadata_only`,
`reuse_as_demo_under_rc_uses_inplace_rewrite`, `diff_detects_changed_def`,
`render_parse_round_trip_canonical`, plus the dual-form smoke
`ail_run_accepts_ail_source_with_same_stdout_as_ail_json`) currently
read raw `.ail.json` bytes for substring asserts or byte-roundtrip
comparison. They pass today (the `.ail.json` files still exist
pre-T8) but will break at T8 when `.ail.json` siblings are deleted.
Plan Task 7 only addresses the `diff_detects_changed_def` test (the
one that mutates JSON). The other three are out of T1-5 scope and
inherit to Boss for T6-12 dispatch resolution (either parse-derived
JSON via `ail parse` per T7 pattern, or `#[ignore]` with explicit
marker).
- **`ailang-core/src/workspace.rs` `mod tests`**: 3 tempdir-based
loader-mechanism tests (lines :1743, :1759, :1776 pre-relocation;
current line numbers shifted by the deletions) remain in-place
per implementer-judgement (they don't consume `examples/`, so
the Form-A goal is trivially satisfied). Plan suggested
relocating them for doctrinal cleanup; scope reduction is
deliberate. They continue to test what they always tested
(loader cycle/missing-module/user-prelude-conflict behaviour)
and pass.
- **Plan recon defect on Group-A vs. Group-B classification**:
`mono_hash_stability.rs`, `prelude_free_fns.rs`,
`print_mono_body_shape.rs`, `show_mono_synthesis.rs` were listed
in plan's Group B but actually use `ailang_core::workspace::load_workspace`
directly (Group-A pattern). Migrated correctly by switching both
the import and the path. Recorded so a future recon-tightening
pass on the planner skill can review whether path-grep-only
recon is sufficient for Group A/B classification.
- **`mono_recursive_fn.rs` and `mono_xmod_qualified_ref.rs`** were
symmetric — listed in plan's Group A but actually CLI subprocess
callers (Group-B pattern). Suffix-only flip applied as if Group B.
## Known debt
- 4 raw-JSON-inspect tests in e2e.rs need T7-style rewrites or
`#[ignore]` markers before Task 8's `.ail.json` deletion lands
(see Concerns).
- 3 tempdir tests in `ailang-core/src/workspace.rs` `mod tests`
could be relocated as doctrinal cleanup but functionally don't
need to be (see Concerns).
- `mod tests {}` placeholder in `ailang-core/src/hash.rs` could
be deleted entirely; left as a structural breadcrumb pointing at
the integration test crate.
## Files touched
Working tree: 37 modified + 14 new test files + 99 new `.ail`
fixtures = 150 paths. Detail:
### Modified production / test source (37)
- `crates/ail/tests/`: codegen_import_map_fallback_pin.rs,
ct1_check_cli.rs, e2e.rs (extensive build_and_run + 11
subprocess sites), eq_float_noinstance.rs, eq_ord_e2e.rs,
floats_e2e.rs, ir_snapshot.rs, mono_hash_stability.rs,
mono_recursive_fn.rs, mono_unification.rs, mono_xmod_ctor_pattern.rs,
mono_xmod_qualified_ref.rs, mq3_multi_class_e2e.rs,
polyfn_dot_qualified_branch_pin.rs, prelude_free_fns.rs,
print_mono_body_shape.rs, roundtrip_cli.rs, show_mono_synthesis.rs,
show_no_instance_e2e.rs, show_print_e2e.rs, typeclass_22b2.rs,
typeclass_22b3.rs, typeclass_22c.rs (23 files)
- `crates/ailang-check/tests/`: env_construction_pin.rs,
method_collision_pin.rs, show_dispatch_pin.rs, workspace.rs (4)
- `crates/ailang-codegen/`: Cargo.toml + src/lib.rs (2)
- `crates/ailang-core/`: Cargo.toml + src/hash.rs + src/workspace.rs
+ tests/ctt2_registry_rekey.rs (4)
- `crates/ailang-prose/`: Cargo.toml + tests/snapshot.rs (2)
- `crates/ailang-surface/tests/round_trip.rs` (1)
- `Cargo.lock` (1)
### New (14 test files + 99 rendered .ail fixtures)
- `crates/ailang-codegen/tests/eq_primitives_pin.rs` (relocated T5)
- `crates/ailang-core/tests/hash_pin.rs` (relocated T5)
- `crates/ailang-core/tests/workspace_pin.rs` (relocated T5)
- `crates/ailang-core/tests/carve_out_inventory.rs` (new T1)
- 99× `examples/<stem>.ail` rendered via `ail render` (T2)
## Stats
bench/orchestrator-stats/2026-05-13-iter-form-a.1.json
---
# iter form-a.1 — Big-bang migration (Tasks 6-12: bench drivers, e2e rewrites, deletion, doctrine, milestone close)
**Date:** 2026-05-13
**Started from:** 9332d1e (post-T1-5 commit 77b28ad + plan-amendment 9332d1e)
**Status:** DONE (Tasks 6-12; iter form-a.1 fully closed)
**Tasks completed:** 7 of 7 (this dispatch); 12 of 12 (iter total)
## Summary
Second half of the form-a-default-authoring milestone-close iter: T6
flips the bench-driver fixture suffix from `.ail.json` to `.ail` (4
Python scripts + run.sh). T7 re-authors three e2e tests
(`diff_detects_changed_def`, `borrow_own_demo_modes_are_metadata_only`,
`reuse_as_demo_under_rc_uses_inplace_rewrite`) to derive their
canonical-JSON via `ail parse` on the `.ail` source rather than
raw-reading the soon-to-be-deleted `.ail.json` file, retires the
redundant `render_parse_round_trip_canonical` (subsumed by T1's
`cli_parse_then_render_then_parse_is_idempotent`), and re-authors
`ail_run_accepts_ail_source_with_same_stdout_as_ail_json` to derive
a tempdir-based `hello.ail.json` from `hello.ail` via `ail parse`
rather than reading a deleted `.ail.json` sibling. T8 deletes the
156 non-carve-out `.ail.json` files (count drops 164 → 8), removes
the `#[ignore]` on the carve-out inventory test, and pulls forward
20 stale-`.ail.json`-reference repairs that the T1-5 dispatch missed
(12 `let example = "X.ail.json"` Group-B sites + 5
`ailang_core::load_workspace` Group-A sites in e2e.rs + 3 `ail_run`
Group-B sites in typeclass_22b3.rs); to keep T8's green-gate, T9
Step 5 (schema_coverage corpus flip from `.ail.json` to `.ail`) is
also pulled forward into T8. T9 retires the 3 obsolete roundtrip
tests (`print_then_parse_round_trips_every_fixture`,
`every_ail_fixture_matches_its_json_counterpart`,
`cli_render_then_parse_preserves_canonical_bytes_on_every_fixture`)
plus the dead helpers `list_json_fixtures` (×2),
`round_trip_one`, and `strip_trailing_newlines`. T10 restates the
DESIGN.md §Roundtrip Invariant with parse-determinism + idempotency
+ CLI-pipeline-idempotency + carve-out-anchor framing, replacing
the old Direction-1/Direction-2 framing and the five enforcement
bullets with the five surviving test names. T11 replaces the
CLAUDE.md and DESIGN.md doctrine sentences per spec §A4. T12
appends the WhatsNew milestone-close entry, strikes the roadmap
entry (`- [x]` + `(Closed 2026-05-13 by iter form-a.1.)`), and
verifies final inventory (8 `.ail.json` carve-outs + 157 `.ail`).
Final test count: 557 green + 3 ignored (3 pre-existing doctests).
The `cargo test --workspace` baseline holds green at every per-task
boundary; both `python3 bench/compile_check.py` and
`python3 bench/cross_lang.py` exit 0. The milestone
`[Form-A as the default authoring surface]` is fully closed.
## Per-task notes
- **iter form-a.1.6** — Bench-driver suffix flips in
`bench/compile_check.py:43,101`, `bench/cross_lang.py:48,80`,
`bench/mono_dispatch.py:10,112`, `bench/run.sh:68,182,183`.
Mechanical edit; comment text and path string updated at each
site. `python3 bench/compile_check.py` exit 0; `python3
bench/cross_lang.py` exit 0. (First compile_check run reported
exit-1 due to sub-millisecond `check_ms` noise on `hello` and
`borrow_own_demo`; second run clean. The noise is unrelated to
the migration — the bench measures `ail check` runtime, and the
Python edits did not touch the binary path.)
- **iter form-a.1.7** — Re-authored 3 raw-JSON-inspect tests +
retired 1 + re-authored the dual-form smoke. Pattern for the
three substring-assert tests: replace
`std::fs::read*("examples/<X>.ail.json")` with a `Command::new(ail_bin()).args(["parse", "examples/<X>.ail", "-o", tmpfile])`
+ `read_to_string(tmpfile)`. `reuse_as_demo_under_rc_uses_inplace_rewrite`
additionally switches its `ailang_core::load_workspace(&json_path)`
call to `ailang_surface::load_workspace(&ail_path)` (the
IR-lowering path no longer needs the JSON file). The dual-form
smoke (`ail_run_accepts_ail_source_with_same_stdout_as_ail_json`)
uses a per-process tempdir with `hello.ail.json` as the file
basename — necessary because the loader name-checks the module
name against the file stem, and the first attempt at a
tempfile-with-PID-suffix path tripped that check. Net test
count: 1 (retirement of `render_parse_round_trip_canonical`).
559 green at task close.
- **iter form-a.1.8** — CRITICAL task. Before the deletion command,
20 stale-`.ail.json`-reference repairs were pulled forward
(T1-5 dispatch missed these despite the plan's Group-A/B scope):
(a) 12 `let example = "X.ail.json"` patterns in `e2e.rs` flipped
to `"X.ail"` via sed; (b) 5 `ailang_core::load_workspace(&json_path)`
sites in `e2e.rs` switched to `ailang_surface::load_workspace`
(the `let example = "X.ail"` from (a) feeds into `workspace.join("examples").join(example)`,
which is `.ail` post-flip — needs the extension-dispatching loader);
(c) 3 `ail_run("X.ail.json")` sites in `typeclass_22b3.rs` flipped
via sed. Cargo-test green pre-deletion at 559. The plan's deletion
bash loop ran clean (exit 0); `ls examples/*.ail.json | wc -l`
8, `ls examples/*.ail | wc -l` → 157. The `#[ignore]` attribute
on `examples_ail_json_inventory_matches_carve_outs` was removed;
the test passes (8 files match `EXPECTED`). Post-deletion
cargo-test surfaced 1 failure
(`every_ast_variant_is_observed_in_the_fixture_corpus` in
`schema_coverage.rs`) because its corpus walker still looked at
`.ail.json` (now down to 8 carve-outs, insufficient to cover all
AST variants). The plan-T8 vs. T9 ordering implicitly assumed T9
Step 5 (schema_coverage corpus flip) would land before T8 — but
T9 is plan-ordered after T8. To satisfy T8's green-gate, T9
Step 5 was pulled forward inline (helper rename
`list_json_fixtures``list_ail_fixtures`, filter `.ail.json`
`.ail`, loader `ailang_core::load_module`
`ailang_surface::load_module`). Post-fix: 560 green + 3 ignored
(was 559 pre-T8 with 4 ignored including carve_out_inventory;
un-ignore + correct schema_coverage flip = +1 net = 560).
- **iter form-a.1.9** — Retired 3 obsolete roundtrip tests +
cleanups. `round_trip.rs`: retired
`print_then_parse_round_trips_every_fixture` (lines 57-101 in
pre-iter numbering) and `every_ail_fixture_matches_its_json_counterpart`
(lines 120-204); retired the `list_json_fixtures` helper and
the `round_trip_one` helper (only consumers were the two retired
tests); updated the file's doc-comment to describe the two
surviving tests (`parse_is_deterministic_*` and
`parse_then_print_then_parse_*`); removed the unused `Path`
import (only `PathBuf` remains). `roundtrip_cli.rs`: retired
`cli_render_then_parse_preserves_canonical_bytes_on_every_fixture`
(lines 116-146 pre-iter) and the `list_json_fixtures` +
`roundtrip_one` + `strip_trailing_newlines` helpers; updated the
doc-comment. T9 Step 5 (schema_coverage corpus flip) was already
done in T8; nothing to do here. 557 green + 3 ignored at task
close (560 pre-T9 3 retired = 557).
- **iter form-a.1.10** — DESIGN.md §Roundtrip Invariant restatement.
Lines 2029-2048 (Direction 1/Direction 2 framing) replaced with
the new 4-property framing (parse-determinism +
idempotency-under-print + CLI-pipeline-idempotency +
carve-out-anchor) verbatim from the plan. Lines 2061-2094
(Enforcement bullets, five tests) replaced with the five
surviving tests verbatim. Float-literals subsection (lines
2050-2059 pre-edit, 2065-2074 post-edit) preserved. Why-anchored-at-top-level
subsection (lines 2096-2108 pre-edit, 2108-2120 post-edit)
preserved. The numbered prose (4 properties) and the bulleted
enforcement (5 tests) are internally consistent; the carve-out
inventory is the 5th enforcement bullet, covering property 4
("carve-out anchor") as a meta-property.
- **iter form-a.1.11** — Doctrine edits. CLAUDE.md:5-6 sentence
replaced verbatim with spec §A4 wording. DESIGN.md:465-466 first
sentence replaced verbatim with spec §A4 wording; second
sentence ("Form (A) is one projection; the JSON-AST stays
canonical.") preserved as the trailing sentence of the new
replacement block. Doc-only; tests unaffected.
- **iter form-a.1.12** — Milestone close. WhatsNew.md entry
appended ("Form A is now the authoring surface", per-boss
editorial rules: no crate names, no iter codes, lead with the
change, factual). docs/roadmap.md entry at line 97 changed from
`- [ ]` to `- [x]` with `(Closed 2026-05-13 by iter form-a.1.)`
prepended. Final cargo-test: 557 green + 3 ignored. Final bench:
both compile_check and cross_lang exit 0. Final inventory:
exactly 8 `.ail.json` (carve-outs alphabetically: broken_unbound,
prelude, test_22b2_invalid_superclass_param,
test_22b2_kind_mismatch, test_22b2_unbound_constraint_var,
test_ct1_bad_qualifier, test_ct1_bare_xmod_rejected,
test_ct1_qualified_class_rejected) + 157 `.ail`.
## Concerns
- **Forward-pull of T9 Step 5 into T8.** The plan ordered T8
(deletion) before T9 (test retirement + schema_coverage flip),
but T8's green-gate required schema_coverage to be flipped
*first* — otherwise the schema_coverage corpus walker shrinks
from 164 `.ail.json` to 8 carve-outs and the AST-variant
coverage assertion fails. Pulled T9 Step 5 inline into T8;
T9 then had no schema_coverage work left to do. Recorded so a
future planner-skill recon pass can detect this ordering
defect class (a Task K green-gate depending on an edit
scripted for Task K+N).
- **T1-5 Group-A/B classification gaps.** The T1-5 dispatch's
Concerns flagged 4 raw-JSON-inspect e2e.rs tests but missed
20 additional sites of the same kind in two patterns: 12
`let example = "X.ail.json"` Group-B-pattern sites in e2e.rs
(feeds `build_and_run_with_alloc`) + 5
`ailang_core::load_workspace` Group-A-pattern sites in e2e.rs
+ 3 `ail_run` Group-B sites in typeclass_22b3.rs. All repaired
inline in T8 before the deletion command ran. The pattern that
T1-5 missed is "binding pulled out of the call expression" —
the `let example = "X.ail.json"` introduces a local that the
Group-B sed for `build_and_run("X.ail.json")` doesn't match.
Worth noting for a future planner-recon tightening pass.
- **bench/compile_check.py first-run flakiness.** The first run
after T6 reported exit-1 because two `check_ms` metrics on
sub-millisecond timings (`hello`, `borrow_own_demo`) drifted
past the 25% tolerance; the second run was exit-0. The drift is
measurement noise (system load + ms-scale latency), not a
migration-induced regression. Final T12 bench run was exit-0
on both scripts.
## Known debt
- **None known.** The iter closes the milestone cleanly. Two
follow-up roadmap items already exist:
- `[milestone] Prelude embed: Form-A as compile-time source`
(queued; retires carve-out (b) `prelude.ail.json`).
- The Show/print fieldtest example-corpus migration (separately
queued; orthogonal to this milestone).
- Cosmetic: the `mod tests {}` placeholder in
`ailang-core/src/hash.rs` from T5 is still in-tree; could be
deleted entirely in a doctrinal cleanup pass. Functionally
harmless.
## Files touched (Tasks 6-12)
### Modified bench (4)
- `bench/compile_check.py`
- `bench/cross_lang.py`
- `bench/mono_dispatch.py`
- `bench/run.sh`
### Modified test source (5)
- `crates/ail/tests/e2e.rs` — T7 re-authoring of 5 tests; T8
forward-pull of 12 Group-B + 5 Group-A sites
- `crates/ail/tests/typeclass_22b3.rs` — T8 forward-pull of 3
Group-B sites
- `crates/ail/tests/roundtrip_cli.rs` — T9 retirement +
helpers cleanup + doc-comment update
- `crates/ailang-surface/tests/round_trip.rs` — T9 retirement +
helpers cleanup + doc-comment update + import cleanup
- `crates/ailang-core/tests/schema_coverage.rs` — T8 corpus flip
to `.ail` (pulled forward from T9 Step 5)
### Modified test discipline (1)
- `crates/ailang-core/tests/carve_out_inventory.rs` — T8 un-ignored
### Modified doc (4)
- `CLAUDE.md` — T11 doctrine sentence (lines 5-6)
- `docs/DESIGN.md` — T10 §Roundtrip Invariant restatement; T11
§"What this Decision deliberately does not do" first sentence
- `docs/WhatsNew.md` — T12 milestone-close entry
- `docs/roadmap.md` — T12 strike of the Form-A milestone entry
### Deleted (T8) — 156 files
`examples/*.ail.json` — every non-carve-out fixture (the eight
carve-outs `broken_unbound`, `prelude`,
`test_22b2_invalid_superclass_param`, `test_22b2_kind_mismatch`,
`test_22b2_unbound_constraint_var`, `test_ct1_bad_qualifier`,
`test_ct1_bare_xmod_rejected`, `test_ct1_qualified_class_rejected`
preserved).
## Stats
bench/orchestrator-stats/2026-05-13-iter-form-a.1.json