spec: form-a-default-authoring milestone — roadmap entry + draft spec

Form A (.ail) becomes the sole authoring surface for every program
in the working tree. The seven negative-test JSON-AST fixtures are
the only post-milestone .ail.json files; everything else is rendered
to .ail and the JSON counterpart is deleted (single representation
per program).

Spec decides the four open design questions inline:
- A1: in-process parse via ailang_surface::parse, no build-time
  target/ artefacts (would reintroduce a second representation).
- A2: prelude.ail ships as iter-0 pilot, validated by the existing
  every_ail_fixture_matches_its_json_counterpart gate.
- A3: per-file deletion cadence; iter 0 is the singular dual-form
  window because the JSON counterpart is the witness the CI gate
  uses.
- A4: CLAUDE.md and DESIGN.md reworded — canonical vs authoring
  forms separated, JSON-AST stays canonical/hashable, .ail becomes
  the authoring entry point.

Roundtrip invariant restates from "two forms agree byte-for-byte"
to "parse is deterministic + idempotent under print"; carve-out
inventory test pins the seven JSON-only fixtures against silent
list drift.

Grounding-check PASS over 8 load-bearing assumptions.

Iteration scope: iter 0 = prelude pilot only (render
prelude.ail.json -> prelude.ail; do not delete the JSON yet; do
not touch CLAUDE.md/DESIGN.md/tests yet).
This commit is contained in:
2026-05-13 09:52:04 +02:00
parent 319b73c281
commit e864c85840
2 changed files with 527 additions and 0 deletions
+65
View File
@@ -89,6 +89,71 @@ context. Pick the next milestone from P1.)_
separate so migration runs against a frozen architecture. Same
call milestone 23 made for `==` / `eq`.
- [ ] **\[todo\]** Author `examples/prelude.ail` alongside
`examples/prelude.ail.json`. Today the prelude exists only as
canonical-form JSON-AST; the textual surface form has to be
reconstructed via `ail render` every time someone wants to read
it. Check in the Form-A text as the authoring source and let
`ail parse` regenerate the JSON-AST at build time (or keep both
and gate equivalence via the existing round-trip invariant).
Either way the LLM-author's natural reading surface (Form A
text) becomes the entry point rather than a derived view.
- context: surfaced 2026-05-13 while demonstrating the
Show + print milestone via `ail prose`; the prelude is the
one file most likely to be read by humans and by LLM authors
learning the language, and it's the only fixture without a
`.ail` sibling.
- [ ] **\[milestone\]** Form-A as the default authoring surface for
examples and docs. 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/`
markdown (~7 in DESIGN.md plus ~29 other md files) — convert to
Form-A snippets where the snippet's purpose is to show "what the
language looks like", not "what the schema is".
After this milestone the working tree contains exactly one
representation per program: the `.ail` source. The JSON-AST is a
build artefact, not a checked-in twin. Tests and benches that
currently glob `*.ail.json` either parse-then-consume or are
rewired to point at `.ail` directly. The round-trip invariant
flips role: today it gates that the two forms agree; afterwards
it gates that `parse` is deterministic.
Carve-outs that MUST stay JSON-AST (no Form-A counterpart, and
no `.ail` sibling shall be created — these are the only seven
files that remain `.ail.json`-only post-milestone):
- Fixtures that test canonical-form rejection — Form A would
reject them at parse, defeating the test:
`test_ct1_bare_xmod_rejected.ail.json`,
`test_ct1_qualified_class_rejected.ail.json`,
`test_ct1_bad_qualifier.ail.json`, `broken_unbound.ail.json`,
`test_22b2_invalid_superclass_param.ail.json`,
`test_22b2_kind_mismatch.ail.json`,
`test_22b2_unbound_constraint_var.ail.json`.
- DESIGN.md schema documentation blocks where the JSON-AST shape
*is* the point (Decision 11, ParamMode, canonical-form
invariants).
- Any other case where the structured form is the artefact under
discussion, not a vehicle for a program.
Touches CLAUDE.md ("source of truth is structured data") — the
language doctrine doesn't change (JSON-AST is still the canonical
hashable form), but the *authoring* doctrine does: authors write
`.ail`, the build derives JSON-AST. Sentence in CLAUDE.md needs
rewording in the same milestone.
Mechanical for the bulk; per-fixture judgement call only for the
carve-out list. Run as one milestone so the corpus flip-over
happens at a single, audit-gated point.
- context: post-Form-A-as-canonical-authoring corollary of the
`examples/prelude.ail` entry above. Generalises the same idea
to the rest of the corpus and follows through on the cross-
model authoring data (textual form cheaper, more first-try
hits) by treating Form A as the privileged surface in the
working tree, not just in flavour text.
- [ ] **\[feature\]** Operator routing through `Eq` / `Ord``==`,
`<` etc. resolved via the typeclass instead of the built-in
primitive comparators. No commitment; gated on bench re-baselining