# AILang Roadmap

Priority-ordered list of upcoming work — milestones, features, todos,
and ideas. The orchestrator maintains this file. The user can request
additions; the orchestrator chooses what to remove or reprioritise as
work progresses.

## Conventions

- One checkbox per entry. `- [ ]` is open; `- [~]` is in progress
  (work has started — a plan exists, a branch is open, or commits are
  landing); `- [x]` is done. A finished entry may stay briefly for
  context, then is removed (with a one-line mirror in
  `docs/JOURNAL.md`).
- Each entry is tagged by **kind** and lives under a **priority**
  bucket:
  - **\[milestone\]** — big chunk that will get a `docs/specs/<milestone>.md`.
  - **\[feature\]** — smaller addition inside a milestone, no full
    spec.
  - **\[todo\]** — concrete task that can run without a brainstorm
    (cleanup, doc fix, mechanical refactor, test backfill).
  - **\[idea\]** — not yet decision-ready, no commitment.
- Optional `depends on:` line names another entry that has to land
  first.
- Optional `context:` line points to the JOURNAL entry where the
  rationale lives. The roadmap is intentionally terse; rationale
  stays in JOURNAL.
- Priority buckets:
  - **P0** — in flight. Spec or plan already exists.
  - **P1** — next up. Decision made; not yet started.
  - **P2** — medium-term. Decided in principle, scheduled later.
  - **P3** — ideas. No commitment; may be cut.

## P0 — In flight

- [x] **\[milestone\]** Floats — introduce `Float` as IEEE-754
  binary64 primitive type. One float type only (no `f32`).
  IEEE-conformant equality: `eq : Float → Float → Bool` returns
  `false` for `NaN == NaN`; **no `Eq` instance** (the partiality
  is real and surfaces through `Maybe`-shaped comparators rather
  than through a lying total instance). `Ord` likewise partial:
  `compare : Float → Float → Maybe Ordering`. Includes literal
  syntax in Form-A + Surface, codegen for arithmetic ops,
  conversions Int↔Float, and `Show`-style printing without the
  typeclass machinery (the typeclass wiring lands in Post-22
  Prelude).
  - context: this conversation (2026-05-10) — Float status quo
    was "documented as a primitive but never implemented";
    `crates/ailang-core/src/canonical.rs:14` says "no floats".

## P1 — Next

- [ ] **\[milestone\]** Post-22 Prelude — ship `Show` / `Eq` / `Ord`
  with the three total-orderable primitive instances (Int, Bool, Str);
  rewire `print` through `Show.show`. Float gets `Show` but **not**
  `Eq` / `Ord` (partial — see Floats milestone). Originally queued
  as 22b.4 in the typeclass milestone, kept on hold pending demand.
  - context: JOURNAL 2026-05-09 ("JOURNAL queue"). Floats milestone
    closed 2026-05-10 — partial-Eq/Ord-for-Float story is documented
    in DESIGN.md §"Float semantics", so the Prelude can decide
    what's instanced (Show: yes, Eq/Ord: no for Float).

## P2 — Medium-term

- [ ] **\[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
  to make sure the indirection doesn't tank latency.
  - context: JOURNAL 2026-05-09
  - depends on: Post-22 Prelude
- [ ] **\[todo\]** `types` / `ctor_index` overlay shape question —
  decide whether the env's two parallel ctor maps should collapse
  into one overlay, or stay split. Surfaced during the
  env-construction unify audit.
  - context: JOURNAL 2026-05-10 ("Audit close: env-construction unify")
- [ ] **\[todo\]** CLI human-mode diagnostic surface for `WorkspaceLoadError` —
  non-JSON `ail check` routes ct.1 errors via `anyhow`/`thiserror`
  Display (`Error: <message>`) instead of going through
  `workspace_error_to_diagnostic`, so the bracketed `[code]` prefix
  the JSON path carries is missing. Plausibly applies to every CLI
  subcommand that calls `load_workspace(&path)?` directly.
  - context: JOURNAL 2026-05-11 ("Iteration ct.1") — surfaced by ct.1.8 tester.
- [ ] **\[todo\]** Retire dead `KindMismatch` arm — `validate_classdefs`'s
  `walk_kind_mismatch` path is structurally unreachable through
  well-formed schema post-ct.1 (the canonical-form validator catches
  the malformed `Type::Con { name: param }` shape earlier). The
  enum variant + `walk_kind_mismatch` helper stay as dead-but-defensive
  code; a future tidy can delete both.
  - context: JOURNAL 2026-05-11 ("Iteration ct.1").
- [ ] **\[todo\]** Re-key `Registry.type_def_module` to handle
  bare-name-collision-across-modules — `BTreeMap<String, String>` keyed
  by bare type name silently overwrites when two modules each define
  `type Foo`; `normalize_type_for_registry` would then collapse `M.Foo`
  and `N.Foo` to whichever insert won. Acceptable for current corpus
  (distinct bare type names across modules), but the proper fix is to
  key by `(owning_module, bare_name) → defining_module`.
  - context: JOURNAL 2026-05-11 ("Iteration ct.1") — flagged by ct.1.5a quality reviewer.
- [ ] **\[feature\]** 22c — typeclass corpus expansion. User-defined
  classes beyond the prelude four; multi-parameter classes; superclass
  chains; richer instance bodies. Deferred from milestone 22.
  - context: JOURNAL 2026-05-09
- [ ] **\[milestone\]** Module-qualified class names + type-driven
  method dispatch — retire the `MethodNameCollision` workaround
  (`crates/ailang-core/src/workspace.rs:472`) that today keeps bare
  class names viable by enforcing workspace-global method-name
  uniqueness. Replaces name-driven method resolution
  (`ModuleGlobals::class_methods: IndexMap<String, ClassMethodEntry>`,
  `crates/ailang-check/src/lib.rs:983`; consumed by
  `mono::rewrite_class_method_calls`, `crates/ailang-check/src/mono.rs:657`)
  with type-driven dispatch — look up `eq` candidates by argument
  type, pick the unique class instance, fail closed on ambiguity.
  Once shipped, two libraries can each declare `class Eq` with their
  own `eq`. Carries its own DESIGN spec: inference rules, ambiguity
  diagnostics, and the canonical-form extension for class-reference
  fields (`InstanceDef.class`, `SuperclassRef.class`, `Constraint.class`)
  that the canonical-type-names milestone explicitly out-of-scoped.
  - context: `docs/specs/2026-05-10-canonical-type-names.md` "Out of
    scope: Class names" — the workaround is named there so it stays
    visible until this milestone retires it.
- [ ] **\[todo\]** Boehm full retirement — remove the transitional
  Boehm GC path now that RC + uniqueness is the canonical memory
  story.
  - context: JOURNAL pre-22, "Boehm transitional"
- [ ] **\[feature\]** Closure-pair slab / pool — codegen tweak to
  pool the env+code closure pairs instead of one-shot heap allocs.
  Bench-gated.
- [ ] **\[todo\]** `FnDef::synthetic` flag — formalise the
  monomorphiser-emitted FnDefs so downstream passes can tell
  user-authored from synthesised at a glance. Currently inferred from
  symbol naming.
- [ ] **\[todo\]** 21'h iteration — final 21' carry-over (latency
  methodology pass). Numbering kept for continuity with the 21' arc.

- [ ] **\[todo\]** `io/print_float` always-emit-`.0` — surface
  printer always emits `.` or `e/E` so re-lex routes to Float;
  the runtime printer (`printf("%g\n", v)`) doesn't, so `2.0`
  prints as `2` (Int-shaped). Asymmetric. Either switch the
  runtime path to a `.0`-fallback printer (matching surface) or
  document the `%g` contract in DESIGN.md §"Float semantics" so
  the LLM-author knows `io/print_float`'s output is for-humans
  not round-trip.
  - context: `docs/specs/2026-05-10-fieldtest-floats.md` finding F1.
- [ ] **\[todo\]** Rustdoc warning sweep — `cargo doc --no-deps`
  reports 16 pre-existing warnings (15 in `ailang-check`, 1 in
  `ailang-core`: private-item links from public doc, unresolved
  intra-crate links). All predate the design-md-consolidation
  milestone; treat as a one-off sweep.
  - context: JOURNAL 2026-05-10 ("Audit close: design-md-consolidation").
- [ ] **\[todo\]** `design_schema_drift.rs` fidelity widening —
  current test checks anchor *presence* anywhere in DESIGN.md;
  the audit found that `[high]` schema gaps in §"Data model"
  are invisible because anchors live in Decision 11 instead.
  Constrain the test to scan only §"Data model" + ParamMode
  block, or extract JSON-schema blocks into a machine-readable
  file the test consumes.
  - context: JOURNAL 2026-05-10 ("Audit close").

## P3 — Ideas

- [ ] **\[idea\]** Latency methodology rework — switch from per-run
  timing to a histogram-based approach so tail-latency regressions
  are visible without re-running. Queued from 21'g.
- [ ] **\[idea\]** Parser-test backfill for 22b.4a-era duplicate-clause
  sites (class × 3, class method × 2, instance × 3, instance method
  × 1). No regression pin today; only worth it if a 22b.4a-era
  diagnostic needs to change.
  - context: JOURNAL 2026-05-10 ("Iteration 22-tidy.7")
- [ ] **\[idea\]** `write_type` `Type::Forall` arm in
  `crates/ailang-prose/src/lib.rs` silently drops constraints in
  inline-type rendering. Dormant — surface forms today only carry
  forall at fn-signature top level. Fix only if a future feature
  carries forall + constraints inline.
  - context: JOURNAL 2026-05-10 ("Iteration 22-tidy.6")
- [ ] **\[idea\]** Richer integration paths between RC and
  uniqueness — deferred from the 21' arc; revisit once the
  uniqueness inference covers more program shapes.
