44c6e56a0a
Milestone-close audit found three drift items (architect) plus two carry-on items; bench all-green. Fixes (rt.tidy, boss-direct): - 5th test parse_then_print_then_parse_is_idempotent_on_every_ailx_fixture enforces Direction 2 of the Roundtrip Invariant directly. The DESIGN.md enforcement list grows from four to five tests. - docs/roadmap.md P1 'Round-trip completeness invariant' entry retired with one-line journal mirror per roadmap convention. - DESIGN.md wording sync: <16-hex> → <16-lowercase-hex> for the Float-bits-hex spelling in the new section (matches §Data model). Milestone closed clean; five workspace-wide tests anchor the .ail.json ↔ .ailx bijection plus AST-variant coverage.
331 lines
18 KiB
Markdown
331 lines
18 KiB
Markdown
# 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/journals/`).
|
||
- 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 (per-iter
|
||
file under `docs/journals/` or, for pre-2026-05-11 entries, the
|
||
archived `docs/journal-archive.md`) where the rationale lives.
|
||
The roadmap is intentionally terse; rationale stays in the
|
||
journals.
|
||
- 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
|
||
|
||
_(empty — canonical-type-names milestone closed 2026-05-11; Floats
|
||
closed 2026-05-10 and was removed once it stopped being load-bearing
|
||
context. Pick the next milestone from P1.)_
|
||
|
||
## P1 — Next
|
||
|
||
- [x] **\[milestone\]** Post-22 Prelude — Eq/Ord — shipped milestone
|
||
23 (2026-05-12). `Ordering` ADT, `Eq`/`Ord` classes, primitive
|
||
instances on Int / Bool / Str, polymorphic free fns
|
||
`ne`/`lt`/`le`/`gt`/`ge`, runtime `ail_str_eq` + `ail_str_compare`,
|
||
end-to-end coverage including user-ADT-instance integration. Float
|
||
has neither instance by design; polymorphic helpers at Float fire
|
||
Float-aware `NoInstance` per DESIGN.md §"Float semantics".
|
||
|
||
- [ ] **\[todo\]** Brainstorm Step 7.5 — Grounding-check is the *last*
|
||
step before the spec is committed. Any post-PASS edit to the spec
|
||
(Boss-side polish, user-requested change, anything) must
|
||
re-dispatch `ailang-grounding-check` before the commit. Today the
|
||
skill's Step 7.5 + Step 8 wording allows a "fix issues inline and
|
||
re-run Step 7" loop *without* re-running Step 7.5 — closes the
|
||
loop on linguistic self-review only, not on grounding. Update
|
||
`skills/brainstorm/SKILL.md`: any change to the spec file after
|
||
the grounding-check PASS report invalidates that report and
|
||
requires a fresh dispatch before Step 8 commit.
|
||
- context: surfaced 2026-05-12 during iter rt.1 planning — Boss
|
||
edited the roundtrip-invariant spec to add acceptance #7
|
||
("tests are pure readers") *after* the PASS report from
|
||
`ailang-grounding-check`, then committed the spec without a
|
||
re-dispatch. User flagged the skill gap that allowed this.
|
||
|
||
- [ ] **\[milestone\]** Post-22 Prelude — Show + print rewire — ship
|
||
`Show` typeclass with `Show Int/Bool/Str/Float` instances; rewire
|
||
`print` through `Show.show`. Gated on heap-`Str` ABI runtime work
|
||
(`int_to_str` needs to allocate). Originally queued as 22b.4 in
|
||
the typeclass milestone, kept on hold pending demand and the
|
||
heap-`Str` prerequisite.
|
||
- context: brainstorm 2026-05-12 (iter 23.5 wrap). Heap-`Str` ABI
|
||
is the load-bearing prerequisite; until it ships, `Show Int`
|
||
cannot allocate a `Str` to return.
|
||
|
||
## P2 — Medium-term
|
||
|
||
- [ ] **\[milestone\]** Cross-model authoring-form test — empirically
|
||
measure whether `.ail.json` or `.ailx` is the form a foreign LLM
|
||
author reaches for and succeeds with. Setup: three configurations
|
||
per task — (i) JSON-mandated, (ii) `.ailx`-mandated, (iii) free
|
||
choice (both corpora available, model picks). Multiple subjects to
|
||
check whether form-preference is model-robust. For each (model ×
|
||
form × task): system prompt includes DESIGN.md verbatim (~28k
|
||
tokens); user prompt is the task plus the form mandate; an error-
|
||
roundtrip loop feeds `ail check` / `ail parse` errors back to the
|
||
model until green or iter-limit. Measure: first-attempt success
|
||
(yes/no), iterations to green, total tokens spent, error classes
|
||
encountered (schema violation, type mismatch, hash mismatch, syntax
|
||
error in the chosen form); for free-choice runs, which form the
|
||
model picked unprompted. The output is a JOURNAL'd dataset +
|
||
interpretation + a concrete DESIGN.md edit on Decision 6 —
|
||
either ratify "ailx is the AI authoring projection" with empirical
|
||
backing across N subjects, or retire the form if JSON wins
|
||
consistently across all subjects.
|
||
- context: brainstorm 2026-05-12 (aborted in favour of two roadmap
|
||
entries). The Decision-6 prose currently asserts `.ailx` is the
|
||
AI authoring projection while §"Feature-acceptance criterion"
|
||
cites JSON-as-canonical-authoring-surface as a behavioural
|
||
counterexample to human-driven feature picks. The tension is
|
||
real; only empirical data over multiple downstream subjects
|
||
resolves it.
|
||
- depends on: Round-trip completeness invariant (P1 above) —
|
||
without it, measured preference is confounded by expressive-
|
||
power gaps. Strongly benefits from (but is not strictly
|
||
blocked by): `ail check`/`build`/`run` accept `.ailx`
|
||
extension (P2 todo below); workspace search beyond entry-
|
||
module's directory (P2 todo below). Both will be encountered
|
||
during the test if not closed first.
|
||
- smoke-test evidence (2026-05-12): Qwen3-Coder-Next reads
|
||
DESIGN.md and produces a structurally correct AILang program
|
||
that passes `ail check` in two turns; first turn missed the
|
||
module-name-matches-file-path rule, second turn fixed it after
|
||
`ail check` error was fed back. ~28k prompt tokens, ~150
|
||
completion tokens, ~2-5 s latency per turn.
|
||
- how to address the IONOS endpoint:
|
||
- URL: `https://openai.inference.de-txl.ionos.com/v1/chat/completions`
|
||
- protocol: OpenAI-compatible chat completions API.
|
||
`/v1/models` returns the catalogue.
|
||
- auth: HTTP header `Authorization: Bearer <token>`. Store the
|
||
token outside the repo (e.g. `~/.ionos_token`, `chmod 600`).
|
||
Tokens are JWTs; the one used in the 2026-05-12 smoke test
|
||
was IONOS-issued and time-bound — refresh when re-engaging.
|
||
- model IDs to try (subset of the IONOS catalogue as of
|
||
2026-05-12, sorted by relevance to this test):
|
||
- `Qwen/Qwen3-Coder-Next` — code-specialised, smoke-tested.
|
||
- `meta-llama/Meta-Llama-3.1-405B-Instruct-FP8` — large
|
||
general instruct, useful as a contrast subject.
|
||
- `meta-llama/Llama-3.3-70B-Instruct` — mid-size instruct.
|
||
- `openai/gpt-oss-120b` — OpenAI open-weight 120B.
|
||
- `mistralai/Mistral-Small-24B-Instruct` — smaller subject,
|
||
stresses spec comprehension.
|
||
- `meta-llama/CodeLlama-13b-Instruct-hf` — older code model,
|
||
useful as a low-capability floor.
|
||
- request shape: standard `messages: [{role: "system", ...},
|
||
{role: "user", ...}, ...]`, with DESIGN.md (107 KB / ~28k
|
||
tokens) in the system message and the task + form mandate in
|
||
the first user message. Subsequent turns alternate
|
||
`assistant` / `user` with the `ail check` error verbatim in
|
||
the user message.
|
||
- response shape: `choices[0].message.content` carries the
|
||
generated program (request "no markdown fences, no
|
||
explanation" in the prompt to skip post-processing).
|
||
`usage.prompt_tokens` + `usage.completion_tokens` give per-
|
||
turn token spend.
|
||
- cost estimate: ~56k tokens per task per (model × form)
|
||
configuration including a few correction roundtrips; a
|
||
full matrix (4 tasks × 3 forms × 4 models × 1 run each) is
|
||
~2.7M tokens total. Multiply by repetition count if a
|
||
median-of-3 design is chosen.
|
||
|
||
- [ ] **\[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 — Eq/Ord (shipped 23.5)
|
||
- [ ] **\[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").
|
||
- [ ] **\[todo\]** Split `BadCrossModuleTypeRef` into two diagnostics —
|
||
the current single shape collapses unknown-owner and
|
||
known-owner / unknown-type-in-owner into one message. The two
|
||
cases suggest different fixes (add `(import <owner>)` vs. fix the
|
||
type name). In the known-owner branch, list the owner's available
|
||
type defs as candidates the way `bare-cross-module-type-ref`
|
||
lists candidates from imports.
|
||
- context: fieldtest 2026-05-11 — `examples/ct_3*.ailx` exhibits both branches with identical-shape diagnostics.
|
||
- [ ] **\[todo\]** Workspace search beyond entry-module's directory —
|
||
`load_workspace` only finds sibling `.ail.json` files in the same
|
||
directory as the entry module, so any consumer of prelude/std in a
|
||
subdirectory has no way to resolve cross-module imports. Add either
|
||
a `--workspace-root` flag on `ail check` / `ail build` / `ail run`,
|
||
or upward-search from the entry module's directory. Alternatively
|
||
ratify the flat-workspace assumption in DESIGN.md if intentional.
|
||
- context: fieldtest 2026-05-11 — fieldtest fixtures could not be
|
||
placed under `examples/fieldtest/` because of this; predates the
|
||
canonical-type-names milestone but surfaces every time.
|
||
- [ ] **\[todo\]** `ail check`/`build`/`run` accept `.ailx` extension —
|
||
today `ail check foo.ailx` produces a misleading JSON-parse error
|
||
(`json: expected value at line 1 column 1`) because the loader only
|
||
accepts `.ail.json`. Either teach the CLI subcommands to auto-parse
|
||
`.ailx` internally, or detect the extension and emit a
|
||
"did you mean `ail parse foo.ailx`?" hint. The LLM-author's natural
|
||
first command should not be the one that produces a misleading
|
||
diagnostic.
|
||
- context: fieldtest 2026-05-11 — orthogonal to canonical-type-names
|
||
but every fieldtest invocation hits this on its first command.
|
||
- [ ] **\[todo\]** `check_in_workspace` per-module overlay narrowing —
|
||
`crates/ailang-check/src/lib.rs:1234` still clears+rebuilds
|
||
`env.ctor_index` per-module; ct.3.2 narrowed the analogous mono
|
||
overlay to types-only. The typecheck-side overlay's `env.ctor_index`
|
||
half serves the duplicate-detection diagnostic at workspace-build
|
||
time, not the runtime ctor lookup (which is type-driven post-ct.2.2).
|
||
Narrowing is mechanical but needs a careful read to confirm no
|
||
other consumer survives.
|
||
- context: JOURNAL 2026-05-11 ("Iteration ct.4") — milestone close
|
||
follow-up.
|
||
|
||
## P3 — Ideas
|
||
|
||
- [ ] **\[todo\]** `compare_primitives_smoke.ailx` counterpart —
|
||
the canonical happy-path exhibit for canonical-type-names ships
|
||
only as JSON. Per Decision 6, Surface is the LLM-author surface;
|
||
the milestone should have a `.ailx` counterpart. Two paths: author
|
||
`examples/compare_primitives_smoke.ailx` to round-trip into the
|
||
existing JSON, OR retire the JSON fixture in favour of
|
||
`examples/ct_1_ordering_signum.{ailx,ail.json}` as the new canonical
|
||
happy-path exhibit.
|
||
- context: fieldtest 2026-05-11 (spec_gap).
|
||
- [ ] **\[todo\]** Codegen `lookup_ctor_in_pattern` type-anchoring —
|
||
`crates/ailang-codegen/src/lib.rs:1790` still walks every module's
|
||
ctor_index by bare ctor name. Plumbing the scrutinee's
|
||
qualified `Type::Con` through pattern lowering would type-anchor
|
||
it symmetric to the ct.2.2 typecheck-side fix. Not load-bearing
|
||
(uniqueness is enforced at typecheck), but cleaner.
|
||
- context: JOURNAL 2026-05-11 ("Iteration ct.3" + ct.4 close).
|
||
- [ ] **\[todo\]** `compare_primitives_smoke` IR-shape assertion —
|
||
observe `compare__Int` / `compare__Bool` / `compare__Str` symbols
|
||
in the emitted IR. Blocked on `emit-ir` CLI not running mono;
|
||
resolution paths include extending the CLI to run mono, using
|
||
library APIs directly in e2e.rs, or adding `--dump-ir` to `ail
|
||
build`. The E2E stdout assertion already covers correctness; the
|
||
IR-shape test would catch refactor regressions that rename
|
||
mono symbols.
|
||
- context: JOURNAL 2026-05-11 ("Iteration ct.4") — dropped from
|
||
ct.4.4 when the BLOCKED condition surfaced.
|
||
|
||
- [ ] **\[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.
|