9fdc4cacff
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.
432 lines
22 KiB
Markdown
432 lines
22 KiB
Markdown
# 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
|