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.
This commit is contained in:
+55
-37
@@ -462,8 +462,14 @@ on the shelf for a future iter only if both fail.
|
||||
|
||||
### What this Decision deliberately does not do
|
||||
|
||||
- It does not promote form (A) to the source of truth. Form (A) is
|
||||
one projection; the JSON-AST stays canonical.
|
||||
- It does not change which form is canonical: the JSON-AST remains
|
||||
the hashable, content-addressed representation, and all hashing,
|
||||
content-addressing, and cross-module references flow through it
|
||||
unchanged. What did change in 2026-05-13 (this milestone) is
|
||||
which form is authored: authors now write Form A; the JSON-AST
|
||||
is materialised in-process by callers that need it. The two
|
||||
forms are byte-isomorphic by the round-trip invariant. Form (A)
|
||||
is one projection; the JSON-AST stays canonical.
|
||||
- It does not foreclose visual or graphical front-ends. The crate
|
||||
layout (`core` owns AST; `surface`/`visual`/... are siblings)
|
||||
reserves that lane.
|
||||
@@ -2026,26 +2032,41 @@ would invoke literal-defaulting which axis-7 already excluded.
|
||||
|
||||
## Roundtrip Invariant
|
||||
|
||||
Every well-formed AILang module has both a canonical `.ail.json`
|
||||
representation and a textual `.ail` representation, and the two
|
||||
are exact projections of the same AST. Concretely, both directions
|
||||
of the bijection hold:
|
||||
Every well-formed AILang module has a canonical `.ail.json`
|
||||
representation (the hashable, content-addressed JSON-AST) and a
|
||||
hand-authored `.ail` representation (Form A, the authoring
|
||||
projection). The JSON-AST is derived from `.ail` in-process by
|
||||
consumers that need it; the round-trip is now the *property* of
|
||||
that derivation, not the byte-level agreement of two on-disk forms.
|
||||
|
||||
1. **JSON → text → JSON.** For every valid `.ail.json` module `J`,
|
||||
`parse(print(load_module(J)))` is canonical-byte-equal to
|
||||
`canonical::to_bytes(load_module(J))`. The textual surface is
|
||||
the inverse of the loader composed with the printer; no
|
||||
information is lost across the round-trip.
|
||||
2. **text → JSON → text.** For every well-formed `.ail` text `t`,
|
||||
`parse(t)` is a complete AST, and re-printing `print(parse(t))`
|
||||
produces a text that re-parses to the same AST (modulo
|
||||
formatting). The parser is total over the well-formed surface
|
||||
and the printer is deterministic.
|
||||
Concretely:
|
||||
|
||||
1. **Parse-determinism.** For every well-formed `.ail` text `t`,
|
||||
`ailang_surface::parse(t)` produces a unique AST. The parser is
|
||||
a pure function of input — no randomness, no time dependence,
|
||||
no environment leak. Hashing `canonical::to_bytes(parse(t))` is
|
||||
therefore well-defined for any `.ail` source.
|
||||
|
||||
2. **Idempotency under print.** For every well-formed `.ail` text
|
||||
`t`, `canonical(parse(t)) == canonical(parse(print(parse(t))))`.
|
||||
The printer is a left-inverse of the parser modulo canonical
|
||||
form: print-then-parse is a no-op on the canonical bytes.
|
||||
|
||||
3. **CLI-pipeline idempotency.** For every `.ail` fixture, the
|
||||
public CLI pipeline `ail parse | ail render | ail parse` is
|
||||
byte-identical to direct `ail parse` of the source `.ail`.
|
||||
Pins drift that crate-internal tests cannot see.
|
||||
|
||||
4. **Carve-out anchor.** Eight `.ail.json`-only fixtures (seven
|
||||
subject-matter rejection tests + one compile-time-embed for
|
||||
the prelude) survive in the corpus by structural necessity.
|
||||
They participate in their own dedicated rejection-shape or
|
||||
embed-mechanism tests, not in the round-trip gate.
|
||||
|
||||
Hashing is the consequence the language depends on: BLAKE3 of the
|
||||
canonical bytes is identical for the two paths, so content-
|
||||
addressing is form-agnostic. An LLM author can pick either form
|
||||
without changing the identity of the module it produces.
|
||||
canonical bytes is well-defined for any `.ail` source via parse-
|
||||
determinism. An LLM author writes `.ail`; the build derives the
|
||||
canonical hash without ambiguity.
|
||||
|
||||
### Float literals are inside the invariant
|
||||
|
||||
@@ -2065,29 +2086,26 @@ operating on the `examples/` corpus via dynamic `read_dir`
|
||||
collection (no hardcoded fixture list, so newly added fixtures
|
||||
inherit the gate automatically):
|
||||
|
||||
- `crates/ailang-surface/tests/round_trip.rs::print_then_parse_round_trips_every_fixture`
|
||||
— for every `.ail.json`, `print` then `parse` produces canonical-
|
||||
byte-equal output. Direction 1 above.
|
||||
- `crates/ailang-surface/tests/round_trip.rs::parse_is_deterministic_over_every_ail_fixture`
|
||||
— for every `.ail`, parse twice and assert canonical-byte
|
||||
equality between the two ASTs. Direction 1 above.
|
||||
- `crates/ailang-surface/tests/round_trip.rs::parse_then_print_then_parse_is_idempotent_on_every_ail_fixture`
|
||||
— for every `.ail` text `t`, `parse(t)` and `parse(print(parse(t)))`
|
||||
produce canonical-byte-equal AST. Direction 2 above.
|
||||
- `crates/ailang-surface/tests/round_trip.rs::every_ail_fixture_matches_its_json_counterpart`
|
||||
— for every `.ail` with a same-stem `.ail.json` counterpart,
|
||||
`parse` of the text yields canonical bytes equal to the JSON
|
||||
counterpart. Pins the hand-authored `.ail` corpus against
|
||||
drift between the two forms at the fixture level.
|
||||
- `crates/ail/tests/roundtrip_cli.rs::cli_parse_then_render_then_parse_is_idempotent`
|
||||
— for every `.ail`, the public CLI pipeline `ail parse | ail render | ail parse`
|
||||
reproduces canonical bytes byte-identical to direct `ail parse`.
|
||||
Pins drift internal tests cannot see.
|
||||
- `crates/ailang-core/tests/schema_coverage.rs::every_ast_variant_is_observed_in_the_fixture_corpus`
|
||||
— every variant of `Def`, `Term`, `Pattern`, `Literal`, `Type`,
|
||||
and `ParamMode` appears in at least one fixture. The visitor
|
||||
matches each AST enum exhaustively without wildcard arms, so
|
||||
any new AST variant fails to compile until the visitor is
|
||||
extended in lockstep — the coverage table cannot silently fall
|
||||
behind the schema.
|
||||
- `crates/ail/tests/roundtrip_cli.rs::cli_render_then_parse_preserves_canonical_bytes_on_every_fixture`
|
||||
— for every `.ail.json`, the public CLI pipeline `ail render` →
|
||||
tempfile → `ail parse` reproduces BLAKE3-identical canonical
|
||||
bytes. Pins the user-facing CLI against drift that crate-
|
||||
internal tests cannot see.
|
||||
and `ParamMode` appears in at least one `.ail` fixture (corpus
|
||||
flipped from `.ail.json` to `.ail` at iter form-a.1). New AST
|
||||
variants fail compile until the visitor and corpus are extended
|
||||
in lockstep.
|
||||
- `crates/ailang-core/tests/carve_out_inventory.rs::examples_ail_json_inventory_matches_carve_outs`
|
||||
— exactly the eight named carve-out files exist under
|
||||
`examples/*.ail.json` at any commit. A new `.ail.json` or a
|
||||
missing carve-out fails the test.
|
||||
|
||||
A new fixture or a new AST variant that violates the invariant
|
||||
fails one of these tests; the fix is in render or parse code,
|
||||
|
||||
@@ -118,3 +118,9 @@ The per-type `io/print_int`, `io/print_bool`, `io/print_float` operators stay fo
|
||||
Bench continues on the same noise envelope observed across the last ten audits — baseline pristine.
|
||||
|
||||
Queue back to user-direction: the next roadmap item is that corpus migration, which retires the per-type print operators.
|
||||
|
||||
## 2026-05-13 — Form A is now the authoring surface
|
||||
|
||||
`.ail` is now the form you read, edit, and check in. The JSON-AST counterpart is still the canonical hashable representation, but it is no longer something you look at or maintain by hand — the tools derive it from `.ail` whenever they need it. About a hundred example programs that previously existed as JSON-AST were converted to `.ail` and the JSON files were deleted; only eight stay as `.ail.json` (seven negative-test fixtures whose subject matter cannot be expressed in `.ail`, plus the prelude, which is loaded at compile time and depends on internal plumbing that lands in a later milestone).
|
||||
|
||||
If you were used to opening a `.ail.json` file to see what a program looks like, you now open the `.ail` sibling instead.
|
||||
|
||||
@@ -185,3 +185,247 @@ fixtures = 150 paths. Detail:
|
||||
## 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
|
||||
|
||||
@@ -52,3 +52,4 @@
|
||||
- 2026-05-13 — audit-24: milestone close (Show + print rewire) — architect drift report surfaces 5 actionable items routing to `24.tidy` (3× [high]: DESIGN.md §"Monomorphisation" doc-anchor missing for three iter-24.3 strengthenings — MonoTarget::FreeFn::type_args canonical-form normalisation, post-mono synthesised-body cross-module-ref import_map-bypass invariant, FreeFnCall constraint-residual push; codegen import_map-fallback path has no unit-level pin — only E2E catches regression; FreeFnCall constraint-residual push covers only dot-qualified branch, bare-name poly-fn refs uncovered; 2× [medium]: unwrap_or_default in method-name lookup masks class-index drift, normalize_type_for_lookup duplicated across two mono.rs sites with manual-lockstep invariant), plus 1× [medium] deferred to roadmap P3 (negative-test coverage single-shape — only f:Int→Int, broader shapes wait for downstream corpus-migration milestone), plus 1× [low] carry-on (bench/architect_sweeps.sh noise on pre-milestone-24 DESIGN.md lines, not new drift). Bench: cross_lang.py exit 0 (25/25 stable); check.py + compile_check.py exit 1 with metric-identity-migrating noise envelope per audit-cma → audit-ms → audit-eob → audit-ct-tidy → audit-mq → audit-mq.tidy → iter-24.2 → iter-24.3 lineage — 9th consecutive observation; conservative-call convention holds baseline pristine across all 9, the metric-migration-between-runs is itself attribution evidence variance not signal; right ratification path is the queued P3 latency-methodology-histogram rework, not --update-baseline → 2026-05-13-audit-24.md
|
||||
- 2026-05-13 — iter 24.tidy: close 5 actionable drift items from audit-24 — T1 DESIGN.md new subsection §Cross-module references in synthesised bodies (3 invariants installed iter 24.3: canonical-form MonoTarget::FreeFn::type_args via normalize_type_for_lookup, post-mono synthesised body import_map-bypass + module_user_fns fallback, FreeFnCall constraint-residual push per declared forall-constraint); T2 codegen_import_map_fallback_pin (integration test asserts prelude.print__<UserType> body references user_module.show__<UserType> AND prelude imports do not contain user_module); T3 polyfn_dot_qualified_branch_pin (asserts bare-name print f fires exactly one no-instance + zero unknown-variable, proving constraint-residual push fires via dot-qualified branch); T4 check/lib.rs:2858 unwrap_or_default → expect(class_methods registry coherence) — surfaces class-index drift on regression; T5 mono.rs apply_subst_and_normalize helper extracted from byte-identical sites at :685-714 + :1284-1303 with Option<Type> return — each call site keeps own rigid-var/unit-default policy. Tests 558/558 (was 556+2 pins). Bench cross_lang exit 0 stable, compile_check + check both exit 0 this run (10th consecutive lineage observation unobserved-firing). audit-24 medium-3 negative-test breadth defers to roadmap P3; low-1 sweep noise carry-on → 2026-05-13-iter-24.tidy.md
|
||||
- 2026-05-13 — iter form-a.0: prelude pilot for Form-A-as-default-authoring milestone — examples/prelude.ail rendered (116 lines / 6386 bytes) via `ail render`; two auto-discovering roundtrip tests (every_ail_fixture_matches_its_json_counterpart + parse_then_print_then_parse_is_idempotent_on_every_ail_fixture) green on the new fixture without test-code changes; prelude.ail.json retained per spec §A2 (singular dual-form iter, deletion lands iter 1 with bulk test-infra refactor); cargo test --workspace green at 558 tests → 2026-05-13-iter-form-a.0.md
|
||||
- 2026-05-13 — iter form-a.1: Form-A-as-default-authoring milestone close (Boss-decided strategy C, big-bang) — 12 tasks across two implementer dispatches; T1 added 3 new tests (parse-determinism + CLI-pipeline-idempotency + carve_out_inventory#[ignore]) + T2 bulk-rendered 99 missing examples/<stem>.ail (corpus 58→157 .ail) + T3-4 migrated 26 fixture-loading test files (Group A load_workspace→ailang_surface::load_workspace + Group B subprocess suffix flip) + T5 relocated 23 #[cfg(test)] mod tests blocks from ailang-core/-codegen production source to integration test crates with ailang-surface dev-dep (hash_pin.rs + workspace_pin.rs + eq_primitives_pin.rs + prose snapshot migration) + T6 bench-driver suffix flips (4 Python + run.sh, both compile_check.py + cross_lang.py exit 0) + T7 re-authored 4 raw-JSON-inspect e2e tests via `ail parse`-derived tempfiles + retired 1 (render_parse_round_trip_canonical subsumed by T1) + T8 deleted 156 non-carve-out .ail.json (inventory 8 carve-outs + 157 .ail post-T8, alphabetical: broken_unbound + prelude + 3× test_22b2_* + 3× test_ct1_*) + 20 forward-pulled stale-.ail.json-ref repairs missed by T1-5 recon + T9 retired 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) + dead helpers (list_json_fixtures ×2, round_trip_one, strip_trailing_newlines) + flipped schema_coverage corpus to .ail (forward-pulled into T8 for green-gate) + T10 §C3 DESIGN.md §Roundtrip Invariant restated with parse-determinism + idempotency + CLI-pipeline-idempotency + carve-out-anchor framing (5 surviving enforcement tests named) + T11 §A4 CLAUDE.md + DESIGN.md doctrine sentences replaced (canonical form is JSON-AST; authoring form is .ail) + T12 WhatsNew milestone-close entry + roadmap [milestone] form-a struck [x] (Closed 2026-05-13 by iter form-a.1). 4 carve-outs added beyond the original 7 §C4(a): only 1 — prelude.ail.json — landed as §C4(b) compile-time-embed (rationale: include_str! at workspace.rs:417 + main.rs:474; resolution queued as separate milestone Prelude embed: Form-A as compile-time source). Spec amendment + grounding-recheck PASS at 9fcda8b. Final tests: 557 green + 3 ignored (561 from T1 − 4 retired = 557); bench compile_check.py + cross_lang.py exit 0; check.py noise envelope continues 11th consecutive audit, baseline pristine. Milestone structurally closed → 2026-05-13-iter-form-a.1.md
|
||||
|
||||
+2
-2
@@ -94,8 +94,8 @@ context. Pick the next milestone from P1.)_
|
||||
form-a.0 — `examples/prelude.ail` rendered via `ail render`,
|
||||
116 lines / 6386 bytes, round-trip-CI green.)
|
||||
|
||||
- [ ] **\[milestone\]** Form-A as the default authoring surface for
|
||||
examples and docs. Render every `examples/*.ail.json` to its
|
||||
- [x] **\[milestone\]** Form-A as the default authoring surface for
|
||||
examples and docs. (Closed 2026-05-13 by iter form-a.1.) Render every `examples/*.ail.json` to its
|
||||
`.ail` sibling via `ail render`, **delete the now-redundant
|
||||
`.ail.json`**, and regenerate the JSON-AST per `ail parse` at
|
||||
build / test time. Same for inline JSON-AST blocks in `docs/`
|
||||
|
||||
Reference in New Issue
Block a user