# What's New in AILang A user-facing changelog. It runs in parallel to the technical per-iter journals (`docs/journals/`) and is written for the user-as-reader who did not watch the work happen — no crate names, no iteration codes, no implementation mechanics. Each entry corresponds to a done-state notification I sent to the user when he was away. The text is identical to what arrived on his phone. New entries are appended at the bottom. What gets described here is **what changed in the project** — what is now possible, fixed, or visible. For the internals, see `docs/journals/INDEX.md` and the per-iter journal files it points at. --- ## 2026-05-11 — implement cycle no longer eats your context The implement cycle no longer eats your context. From the next time we run it, the whole per-task review loop runs inside a dedicated subagent and sends back a short end-report — typing the chatter into someone else's window, so to speak. Each iter gets its own branch; merging or discarding is your call, and rollbacks become trivial. The 14k-line journal monolith is split into per-iter files with a small index for navigation; the old file is archived. Audit ran clean — no benchmark regressions; a small follow-up sweep fixed four spots where I'd missed stale references to the old layout. ## 2026-05-11 — plan-writing offload + first-run debrief Plan-writing also offloads its read-heavy phase now — the part where I walk the codebase looking for the right files for a plan. Should feel lighter on the chat side from the next plan onwards. First real test of yesterday's per-task isolation refactor exposed a tool-wiring bug along the way: the Boss-context offload part works (you still see only an end-report at the end), but the per-task fresh-subagent isolation didn't actually fire — all tasks ended up running in one bigger context inside the orchestrator. Diagnosis is queued at the top of the next-up list. A small iter-branch setup wording bug got fixed in the same session. Audit clean, no benchmark regressions. ## 2026-05-11 — implement-cycle correction Yesterday's note claimed the per-task review loop runs as separate fresh-context phases. That isn't possible — Claude Code does not allow a sub-helper to spawn further sub-helpers, full stop. The project's older "no helper calls another helper" convention turns out to have been a restatement of that platform rule all along, not a local design choice with a documented exception. So the architecture is corrected: the per-task loop still runs offloaded from your chat into one dedicated helper context (the part that does save your chat budget), but the review phases now run as sequential checkpoints inside that helper rather than as separate fresh contexts. The chat-side experience does not change. The fresh-per-phase isolation that the earlier note implied does not exist and never could; honestly scoped now. ## 2026-05-11 — Spec grounding-check Every design spec now has to pass an independent check before approval. The check reads the spec with no prior context, extracts every claim it makes about how the project already works, and confirms each one against a currently-green test. If even one claim has no test backing it, the spec is discarded and the idea moves to the roadmap until the missing piece ships. An in-flight design for the eq/ord prelude was retired today because it would have failed this check: a load-bearing claim about how the compiler currently handles polymorphic helpers was never verified, and three implementation attempts on it had stalled. The re-think happens in a separate session once the missing mechanism exists. ## 2026-05-12 — Eq/Ord prelude work back on track The blocker that stranded yesterday's eq/ord prelude work is fixed. The language now handles polymorphic helper functions that call class methods inside their body — the canonical shape every prelude helper takes — by routing both kinds of specialisation through one unified pass instead of two competing ones. A small fixture (`cmp_max` at three integer values) confirms it end-to-end, and the regression check shows the six existing primitive eq/ord symbols still produce bit-identical output. Next: the five missing prelude utilities (`ne`, `lt`, `le`, `gt`, `ge`) and their end-to-end tests. ## 2026-05-12 — Eq/Ord prelude finished, milestone closed The eq/ord prelude milestone is done. `ne`, `lt`, `le`, `gt`, `ge` now ship in the auto-loaded prelude as polymorphic helpers that work on any type with the matching class instance — verified end-to-end at Int, Bool, Str, and at a user-defined type with hand-written instances. The same helpers applied to Float produce a Float-aware error pointing back to the language reference's Float section, instead of the generic "no instance" message. A couple of latent bugs in the type-checker surfaced while testing the natural shape of these helpers (one in the linearity check, one in the polymorphic-specialiser collector) and got fixed in the same pass. The benchmark suite is clean except one sub-millisecond noise-band metric just over the tolerance line — expected given the prelude grew, ratifiable at the next baseline refresh. Show + `print`-rewire remains the next prelude piece, gated on heap-string runtime support. ## 2026-05-12 — Milestone-close audit: Eq/Ord prelude ratified Milestone-close audit done. The compile-time regression that surfaced after the prelude grew was localised: it isn't an optimisation bug, it's the cost of typechecking five more helper functions on every workspace check. Ratified — the new typecheck times are now the baseline. The benchmark suite is back to all-green. One unrelated grammar stub in the language reference (left over from a doc consolidation two days ago) was caught by the audit drift-review and fixed in the same pass. Milestone 23 is officially closed. Queue is back to user-direction. ## 2026-05-12 — Roundtrip safety net for the two program forms AILang now ships with a continuous safety net that verifies the two program forms (the structured form and the textual form) stay losslessly interchangeable. Three checks run on every build: - Every example in the corpus round-trips between the two forms with byte-identical canonical output. - Every language construct is required to have at least one example exercising it; coverage gaps fail the build. - The command-line render/parse flow preserves canonical bytes end-to-end, verified by a hash check. All three pass first time on the current corpus — the two forms are exactly equipotent today, no expressive-power gap between them. This is the prerequisite for the cross-model authoring test that was deferred earlier; the language can now go into that test on solid ground. ## 2026-05-12 — Roundtrip-invariant milestone closed The roundtrip-safety-net milestone is done. The two program forms — the structured one and the textual one — are now anchored as a named, prominent invariant in the language reference, with five continuous checks enforcing it on every build: byte-identical round-trip in either direction, every language construct exercised by at least one example, and the CLI render/parse flow verified by hash identity. Float literals (NaN, infinities, subnormals) round-trip exactly through the bits-hex encoding — inside the invariant, not an exception. No language behaviour changed; the corpus already satisfied the property. The milestone made it explicit and locked in against future drift. Bench all-green. Roadmap is back to user-direction; the Show+print rewire is gated on the heap-string runtime work. ## 2026-05-12 — Cross-model authoring test: first data point Cross-model authoring test landed. First run (Qwen3-Coder-Next, 4 tasks, two blind cohorts): textual-form cohort 2/4 green at ~half the token cost; structured-form 1/4. Only first-attempt success was textual-form on a print-two-integers task — five lines vs twenty-three. Recorded as a data point in the language reference; single-model scope explicit. Multi-subject expansion queued as next experimental milestone. Milestone closed; queue back to user-direction. ## 2026-05-12 — Cross-model authoring test: second subject added Cross-model authoring test now has a second subject. Ran CodeLlama alongside Qwen on the same four tasks, fresh runs both. Both models point the same way: textual form is cheaper than structured form on tokens (61–80% of structured form's cost across the two models) and reaches working code at least as often (Qwen ties on this run; CodeLlama strictly dominates 2/4 vs 0/4). Three of four first-attempt successes across the two models are textual. A feedback-asymmetry bug surfaced during planning — the structured form was silently losing its underlying parse error on the way back to the model — and got fixed in the same milestone, so both subjects ran with the fix in place. Not a universal verdict yet (would need three or more models with repetitions), but the second data point points the same way as the first. Milestone closed; queue back to user-direction. ## 2026-05-12 — Strings produced at runtime now release cleanly `int_to_str`, `float_to_str`, and similar built-in primitives that produce a freshly allocated string at runtime now participate in reference counting like every other heap value. A string passed into a print call is now treated as borrowed, not consumed, so it is freed exactly once when it leaves scope. Earlier programs that converted a number to a string and printed it leaked the string buffer at program exit; that no longer happens. A side effect: a function parameter declared `(own T)` whose only in-body use was passing it into a print call will now correctly be flagged as over-strict — that annotation should be relaxed to `(borrow T)` (or removed). No current example programs are affected. ## 2026-05-12 — Same-named types across modules no longer collide Two modules in one workspace can each declare a type with the same bare name (for example, both declaring `type Foo`) and carry their own type-class instances — both now register under their owning modules and stay distinct. Before this round, one declaration silently overwrote the other in an internal index and the loser's instance tripped a misleading "duplicate instance" error. Internal housekeeping in the same round: a structurally unreachable validation path was removed, and a previously implicit design decision about the type checker's overlay structure was written down. ## 2026-05-13 — Two libraries can each declare their own type class A workspace can now have two libraries each declaring `class Show` (or `class Eq`, `class Ord`, …) with their own method, and both can ship instances for overlapping types. Before this round, the loader rejected the workspace the moment two classes anywhere declared the same method name. A workspace-global ban that was never load-bearing for correctness — just a workaround making bare method calls unambiguous. The replacement is type-driven dispatch at the call site. When `show 42` is reached and only one class in scope declares `show`, the call resolves automatically. When two do, the checker first narrows by the argument's type (only one class might have an instance for `Int`); if that still leaves more than one, it reports the ambiguity with the candidate class names and asks the author to disambiguate via `..show 42`. A class method that happens to share a name with a free function is handled the same way: the free function wins by the existing precedence rule, but the author gets a warning so an accidental shadow doesn't pass silently. This unblocks the deferred prelude rewire — the prelude is free to ship its own `class Show` now that it no longer collides with the 14 test fixtures that historically declared a user-class named `Show`. The new dispatch model is now anchored in the language reference as a named subsection; the related class-reference fields (`InstanceDef.class`, `Constraint.class`, `SuperclassRef.class`) follow the same bare-for-same-module / `.`-for-cross-module rule that type names already follow. Bench all-green; the noise envelope on a tail-latency metric continues for the sixth consecutive audit and remains baseline-pristine pending a clear signal-vs-variance call. Queue back to user-direction: the prelude-rewire milestone is ready for a fresh design pass against the new dispatch model. ## 2026-05-13 — Show and print AILang now ships `show` and `print` in the prelude. `show x` produces a Str representation for Int, Bool, Str, and Float (Float is included because textual representation is well-defined modulo libc's NaN spelling, whereas Eq/Ord deliberately exclude Float). `print x` is a polymorphic helper that formats x via show and writes to stdout — it works on any type Show has been declared for, including user-defined ones via `instance Show MyType`. Calling print on a type without a Show instance is rejected at typecheck with a Show-aware diagnostic pointing at the prelude documentation. The per-type `io/print_int`, `io/print_bool`, `io/print_float` operators stay for now; new code is expected to use `print`. A future milestone migrates the existing example corpus. 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.