iter ext-rename: .ailx → .ail across the live toolchain
The surface-form file extension changes from .ailx to .ail. AILang's
authoring surface now uses the same .ail stem as its canonical JSON
form (.ail.json), giving the language a single coherent extension
family: .ail is the LLM-authored Form A, .ail.json is the canonical
JSON-AST Form B.
Scope (touched):
- 61 example renames examples/**/*.ailx → .ail (git mv)
- 1 rename experiments/.../rendered/ailx.md → ail.md
- 35 content-edited live-toolchain files (crates/, docs/DESIGN.md,
docs/roadmap.md, docs/PROSE_ROUNDTRIP.md, skills/, bench/reference/*.c,
experiment crates under experiments/.../{render,harness,master})
- Experiment-crate cohort rename Cohort::Ailx → Cohort::Ail,
Form::Ailx → Form::Ail, per_cohort/ailx → per_cohort/ail,
{form-only: ailx} → {form-only: ail}, ```ailx → ```ail
Out of scope (deliberately untouched, to preserve honest history):
- docs/journal-archive.md (content-frozen per CLAUDE.md)
- docs/journals/, docs/specs/, docs/plans/, bench/orchestrator-stats/
- experiments/.../runs/ (frozen LLM-output artefacts; models actually
saw .ailx — renaming would falsify the experimental record)
Verification: cargo build/test --workspace green; experiment crate
cargo test green; bench/check.py + compile_check.py + cross_lang.py
all 0-regressed; negative grep for ailx|Ailx|AILX outside the
out-of-scope paths returns zero matches.
Opens immediate follow-up: roadmap.md P2 todo `ail check`/build/run
accept .ail extension — after this rename, .ail is canonical
authoring surface but the CLI still produces a misleading JSON-parse
error on `ail check foo.ail`. That's the next iter.
This commit is contained in:
+25
-25
@@ -175,7 +175,7 @@ Trade-off: no inline optimisations through the LLVM API. We rely on
|
||||
Form (A) is implemented as
|
||||
the `ailang-surface` crate (parser + printer). Form-A is
|
||||
gated against drift by `ailang-surface/tests/round_trip.rs`, which
|
||||
parses every `.ailx` fixture, prints it back, re-parses, and demands
|
||||
parses every `.ail` fixture, prints it back, re-parses, and demands
|
||||
canonical-byte equality. `ail render` and both branches
|
||||
of `ail describe` were rewired to use `ailang_surface::print`, making
|
||||
form (A) the **sole** text projection of a module — the legacy
|
||||
@@ -247,7 +247,7 @@ the AST and remain projection-agnostic.
|
||||
semantic indentation, maximal-munch lexing, context-sensitive
|
||||
reductions.
|
||||
2. **AST-isomorphic.** Every surface form maps to exactly one AST
|
||||
shape. The full bijection between `.ail.json` and `.ailx` (both
|
||||
shape. The full bijection between `.ail.json` and `.ail` (both
|
||||
directions, BLAKE3-stable hashing, Float-bits-hex encoding,
|
||||
workspace-CI enforcement points) is anchored as the top-level
|
||||
§"Roundtrip Invariant" — this constraint records that Decision
|
||||
@@ -437,11 +437,11 @@ on the shelf for a future iter only if both fail.
|
||||
continue to consume `ailang-core::ast::Module` values regardless
|
||||
of which projection produced them.
|
||||
- Round-trip test: for every `examples/*.ail.json`, parse the
|
||||
corresponding hand-written `*.ailx`, canonicalise, and assert
|
||||
corresponding hand-written `*.ail`, canonicalise, and assert
|
||||
hash-equivalence to the original. Hash equivalence is the truth
|
||||
check; the surface ships only if every fixture round-trips
|
||||
identically.
|
||||
- CLI: `ail parse <file.ailx> -o <file.ail.json>`. Symmetric to
|
||||
- CLI: `ail parse <file.ail> -o <file.ail.json>`. Symmetric to
|
||||
existing `ail render`. **`.ail.json` remains a first-class input**
|
||||
to every existing subcommand; the parser is a producer, not a
|
||||
gatekeeper.
|
||||
@@ -497,7 +497,7 @@ Neither change extends the grammar's rule budget meaningfully:
|
||||
the 30-production ceiling of constraint 1 is intact (the parser
|
||||
implements ~28 named productions). All 17 `examples/*.ail.json`
|
||||
fixtures round-trip identically through `print → parse → canonical
|
||||
JSON`; the three hand-written `.ailx` exhibits parse to canonical
|
||||
JSON`; the three hand-written `.ail` exhibits parse to canonical
|
||||
JSON identical to their corresponding `.ail.json` files.
|
||||
|
||||
3. **Tail-call surface.** Decision 8 ships two new
|
||||
@@ -580,12 +580,12 @@ foreign LLM enough to produce valid output. The current prompt revises this:
|
||||
|
||||
- The LLM emits **Form-A** (the canonical authoring surface), not
|
||||
JSON. JSON-AST stays the only hashable artefact, but it is not
|
||||
a writing surface. The user runs `ail parse foo.new.ailx`
|
||||
a writing surface. The user runs `ail parse foo.new.ail`
|
||||
before `ail check` to produce the canonical JSON.
|
||||
- `crates/ailang-core/specs/form_a.md` is the complete LLM-targeted
|
||||
Form-A specification — grammar, every term / pattern / type /
|
||||
def keyword, schema invariants, pitfall catalogue, four
|
||||
few-shot modules drawn from `examples/*.ailx`. It is exported
|
||||
few-shot modules drawn from `examples/*.ail`. It is exported
|
||||
as `ailang_core::FORM_A_SPEC` and embedded verbatim in every
|
||||
`merge-prose` prompt.
|
||||
- `crates/ailang-core/tests/spec_drift.rs` walks every variant of
|
||||
@@ -615,7 +615,7 @@ so JSON-cohort feedback carries the full anyhow cause chain):
|
||||
- `meta-llama/CodeLlama-13b-Instruct-hf` —
|
||||
`experiments/2026-05-12-cross-model-authoring/runs/2026-05-12-9197fd/`
|
||||
|
||||
| metric | Qwen / JSON | Qwen / AILX | CodeLlama / JSON | CodeLlama / AILX |
|
||||
| metric | Qwen / JSON | Qwen / AIL | CodeLlama / JSON | CodeLlama / AIL |
|
||||
|---|---|---|---|---|
|
||||
| reached green | 1/4 | 1/4 | 0/4 | 2/4 |
|
||||
| first-attempt green | 1/4 | 1/4 | 0/4 | 2/4 |
|
||||
@@ -625,16 +625,16 @@ so JSON-cohort feedback carries the full anyhow cause chain):
|
||||
| top error class | check (×3) | parse (×3) | check (×2) | parse (×2) |
|
||||
|
||||
Both subjects show the same direction on every metric the table
|
||||
tracks. AILX is cheaper than JSON on prompt tokens (Qwen 61%,
|
||||
tracks. AIL is cheaper than JSON on prompt tokens (Qwen 61%,
|
||||
CodeLlama 80% of the JSON cohort's spend) and cheaper on completion
|
||||
tokens (Qwen 23%, CodeLlama 82%). AILX reached-green is greater than
|
||||
tokens (Qwen 23%, CodeLlama 82%). AIL reached-green is greater than
|
||||
or equal to JSON reached-green for each subject (Qwen ties at 1/4;
|
||||
CodeLlama strictly dominates, 2/4 vs 0/4). The failure-class
|
||||
symmetry observed on the original Qwen baseline holds for both
|
||||
subjects: JSON cohorts fail at the typecheck stage, AILX cohorts at
|
||||
subjects: JSON cohorts fail at the typecheck stage, AIL cohorts at
|
||||
the parse stage — each form's front-of-pipeline check. Three of the
|
||||
four first-attempt-green cells observed across the two subjects are
|
||||
AILX (Qwen-AILX t3, CodeLlama-AILX t1, CodeLlama-AILX t3); the
|
||||
AIL (Qwen-AIL t3, CodeLlama-AIL t1, CodeLlama-AIL t3); the
|
||||
fourth is Qwen-JSON t3, the same task the original baseline already
|
||||
flagged as the JSON-form's only first-attempt success. Two CodeLlama
|
||||
JSON-cohort cells (`t2_length`, `t4_count_zeros`) terminated as
|
||||
@@ -642,7 +642,7 @@ JSON-cohort cells (`t2_length`, `t4_count_zeros`) terminated as
|
||||
IONOS-side terminal error, not a model-output failure; CodeLlama
|
||||
JSON-cohort numbers therefore average over 2 informative cells, not
|
||||
4. The Qwen re-run also shifted by one cell against the cma.3
|
||||
baseline (AILX 2/4 → 1/4, JSON 1/4 → 1/4) despite identical
|
||||
baseline (AIL 2/4 → 1/4, JSON 1/4 → 1/4) despite identical
|
||||
temperature=0 inputs; this is IONOS-side state-of-day noise on a
|
||||
single deterministic re-run, not an effect of the ms.1
|
||||
feedback-formatting fix (which only changes JSON-cohort prompt
|
||||
@@ -650,10 +650,10 @@ content).
|
||||
|
||||
**Scope of this addendum:** two subjects, n=1 each, deterministic.
|
||||
This is a second data point pointing in the same direction as the
|
||||
first, not a verdict. The universal claim of this Decision (".ailx
|
||||
first, not a verdict. The universal claim of this Decision (".ail
|
||||
is the AI authoring projection") would need ≥3 subjects with
|
||||
statistical robustness to ratify; both current points point the
|
||||
same way (AILX cohort cheaper and at-least-as-green) but neither
|
||||
same way (AIL cohort cheaper and at-least-as-green) but neither
|
||||
the sample size nor the cross-call noise observed in the Qwen
|
||||
re-run is enough to close out the Decision.
|
||||
|
||||
@@ -1813,7 +1813,7 @@ 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 `.ailx` representation, and the two
|
||||
representation and a textual `.ail` representation, and the two
|
||||
are exact projections of the same AST. Concretely, both directions
|
||||
of the bijection hold:
|
||||
|
||||
@@ -1822,7 +1822,7 @@ of the bijection hold:
|
||||
`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 `.ailx` text `t`,
|
||||
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
|
||||
@@ -1854,13 +1854,13 @@ 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_then_print_then_parse_is_idempotent_on_every_ailx_fixture`
|
||||
— for every `.ailx` text `t`, `parse(t)` and `parse(print(parse(t)))`
|
||||
- `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_ailx_fixture_matches_its_json_counterpart`
|
||||
— for every `.ailx` with a same-stem `.ail.json` counterpart,
|
||||
- `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 `.ailx` corpus against
|
||||
counterpart. Pins the hand-authored `.ail` corpus against
|
||||
drift between the two forms at the fixture level.
|
||||
- `crates/ailang-core/tests/schema_coverage.rs::every_ast_variant_is_observed_in_the_fixture_corpus`
|
||||
— every variant of `Def`, `Term`, `Pattern`, `Literal`, `Type`,
|
||||
@@ -1882,7 +1882,7 @@ never by relaxing the test.
|
||||
### Why this is anchored at top level
|
||||
|
||||
The invariant is a property of the language identity, not of any
|
||||
one surface-design Decision. Decision 6 introduces the `.ailx`
|
||||
one surface-design Decision. Decision 6 introduces the `.ail`
|
||||
surface and lists round-trip-as-property as one of its
|
||||
constraints, but the property is load-bearing for every
|
||||
downstream concern that treats the two forms as exchangeable:
|
||||
@@ -2186,7 +2186,7 @@ ail check <module.ail.json> — loads, validates, typechecks
|
||||
ail manifest <module.ail.json> — table: name :: type !effects [hash]
|
||||
ail describe <module> <name> — detail of a definition (form-A body)
|
||||
ail render <module.ail.json> — JSON-AST → form-A text (exact inverse of `parse`)
|
||||
ail parse <module.ailx> — form-A text → canonical JSON-AST
|
||||
ail parse <module.ail> — form-A text → canonical JSON-AST
|
||||
ail prose <module.ail.json> — JSON-AST → form-B (lossy human prose, no parser)
|
||||
ail merge-prose <m.ail.json> <m.prose.txt>
|
||||
— compose the LLM-mediator prompt for the prose round-trip
|
||||
@@ -2403,7 +2403,7 @@ What **is** supported (and used as the smoke test for the pipeline):
|
||||
`(term-ctor std_pair.Pair MkPair x y)` and `(pat-ctor MkPair x y)`
|
||||
inside that scrutinee. Std-library demos (`examples/std_*_demo.ail.json`)
|
||||
exercise this end-to-end.
|
||||
- **AI-authoring text surface, form (A)** (Decision 6). The `ailang-surface` crate parses `.ailx` form-A
|
||||
- **AI-authoring text surface, form (A)** (Decision 6). The `ailang-surface` crate parses `.ail` form-A
|
||||
text into a canonical `ailang-core::ast::Module` and prints any module
|
||||
back as form-A text. `ail render` and `ail describe` use it as the
|
||||
sole text projection; `ail parse` is the inverse direction. Round-trip
|
||||
|
||||
Reference in New Issue
Block a user