Tasks: T1 DESIGN.md new subsection §Cross-module references in
synthesised bodies documenting three iter-24.3 strengthenings
(canonical-form type_args, post-mono cross-module-ref import_map-
bypass, FreeFnCall constraint-residual push). T2 codegen import_map-
fallback pin (integration-style in crates/ail/tests/). T3 bare-name
poly-fn dot-qualified-branch invariant pin (asserts NoInstance fires
at typecheck not codegen). T4 replace unwrap_or_default() at
check/lib.rs:2852-2858 with expect(class_methods registry coherence).
T5 extract apply_subst_and_normalize helper from duplicated mono.rs
sites at :685-714 + :1284-1303. T6 integration + bench verification.
Boss decisions in Pre-flight section: T1 placement = new subsection
between DESIGN.md:1693 and :1695 (anchorable block beats append-in-
place); T2+T3 = integration-style tests (canonical xmod-test pattern,
not in-crate codegen); T5 helper extracts common concrete-resolved
arm only, returns Option<Type> so each call site keeps its rigid-
var / unit-default policy explicit.
Plan for iter 24.3, the second + final half of milestone 24.
Task 1: append fn print to prelude.ail.json with explicit-let body
\\x -> let s = show x in do io/print_str s. Task 2: mono symbol
IR-shape pin (AST-level Term-pattern match on post-mono
print__Int.body — protects the load-bearing let-binder for the
heap-Str RC discipline per eob.1 Str carve-out). Tasks 3-5:
three E2E fixtures + tests (positive 4-prim smoke, user-ADT
data IntBox + instance prelude.Show IntBox, negative print f
where f : Int -> Int firing NoInstance). Task 5 also extends
the Float-aware NoInstance arm at lib.rs:770-779 with a parallel
Show-aware branch. Task 6: DESIGN.md amendments (§Prelude classes
flip print to shipped, §Float semantics gains Show-Float NaN
paragraph). Task 7: roadmap P1 Show+print flips to [x] + new
P2 entry for io/print_int|bool|float retirement (insert at top of P2).
Task 8: integration + bench.
Boss decisions in plan Pre-flight section: ship explicit-let
(no auto-desugarer); AST-level IR-shape pin (Term pattern match);
NoInstance Show diagnostic wording with literal DESIGN.md section
cross-reference; P2 top-insertion for the retirement entry;
let-bound concrete fn-type for the negative fixture.
Plan for iter 24.2. Tasks 1-2: preemptive 22b-Show → TShow/tshow
rename across 21 fixtures + 2 Rust test files (the recon-corrected
count vs spec's '~14' undercount). Task 3: insert 5 new top-level
defs (class Show + 4 primitive instances Int/Bool/Str/Float) at
prelude.ail.json:223 before fn ne. Task 4: mono-synthesis existence
test for show__T. Task 5: dispatch-singleton pin (show vs tshow,
both Step-2 singletons post-migration). Task 6: hash-stability pin
extension. Task 7: DESIGN.md §Prelude(built-in) classes amendment.
Task 8: integration + bench verification.
Recon-Boss reconciliation captured in Pre-flight notes: 21 fixtures
(not 14), prelude line 223 insertion point, str_clone-reachability
verified by Task 3 round-trip.
Rigid-var refinement type-unification leg in refine_multi_candidate_residual
(high-1); same-module bare-class qualifier shape accepted (high-2);
class-method-shadowed-by-fn warning tightened to require an instance
in workspace_registry (medium-1); DESIGN.md Data Model schema fragments
cross-reference the canonical-form rule (medium-2).
Q1 revised from carrier "fix both sites" to "fix only discharge-time"
after code inspection: synth-time resolve_method_dispatch is invoked
with concrete_arg_type: None and the residual's metavar is constructed
AFTER the dispatch call, so the rigid-var leg has no residual type to
unify against — class-only filter is semantically correct there.
Q2 conservative tightening: filter via "any candidate class has any
registry instance" instead of deferring to App-arm via pending-warning
list (full spec rule).
Installs the dispatch infrastructure without retiring
MethodNameCollision yet:
- 2 new CheckError variants (AmbiguousMethodResolution, UnknownClass)
- NoInstance gains optional candidate_classes field
- ResidualConstraint gains optional candidates: BTreeSet<String>
- Env gains workspace-flat method_to_candidate_classes index
- New resolve_method_dispatch helper implementing the 5-step rule
- Synth Var-arm rewritten to route through the helper
- Constraint-discharge refines multi-candidate residuals
(concrete-type path → registry filter; rigid-var path →
declared-constraint filter)
- Mono's residual-to-target mapping mirrors the discharge refinement
End-to-end multi-class fixtures still gated by MethodNameCollision
(iter mq.3); new path exercised in this iter only by 6 unit-test
cases on resolve_method_dispatch + 3 each on refine and mono
resolver.
Boss decisions on recon open questions: residual extension via
Option<BTreeSet<String>> field; index lives workspace-flat on Env;
NoInstance.candidate_classes wired through to_diagnostic this iter;
qualify_class_ref_in_check consolidation deferred per mq.1
known-debt.
Iter mq.1 plan: move InstanceDef.class / Constraint.class /
SuperclassRef.class from bare-only to canonical form per ct.1's
existing rule, extend validate_canonical_type_names with three new
field walks, narrow check_class_name_fields to ClassDef.name-only,
qualify build_registry's class_def_module + class_by_name + entries
+ four lookup sites, qualify ClassMethodEntry.class_name +
class_superclasses, update affected test-assertion strings.
Pre-flight recon flagged that the spec's '14 fixtures migrated' cost
claim is over-stated: all existing fixture class refs are intra-module
under the canonical-form rule. Plan does not add migration work that
does not need doing; Task 7 Step 3 verifies zero existing-fixture
diff.
Six tasks: (1) runtime C functions in runtime/str.c, (2) builtin
install lockstep across builtins.rs + synth.rs + list() row + 2
unit tests, (3) codegen IR wiring (2 declares + 2 lower_app arms +
is_static_callee whitelist), (4) 2 IR-shape unit pins, (5) regen
5 IR snapshots, (6) 4 fixtures + 5 E2E tests + acceptance gate.
Mechanical mirror of hs.4's int_to_str/float_to_str pattern. Plan
captures every Edit verbatim (old_string + new_string) per planner
Iron Law. Pre-existing drift fix included inline: int_to_str row
missing from builtins.rs::list() since hs.4 — adding it adjacent
to the two new rows. Three open questions from plan-recon resolved
by Boss judgement (C uses bool from <stdbool.h>; tests live in
crates/ail/tests/e2e.rs as the existing real path; int_to_str
list() row drift fixed inline).
Single iter closes the milestone: language rule at three check-time
sites (uniqueness.rs + linearity.rs + linearity.rs doc-comment),
four lockstep ret_mode-Own edits (builtins.rs + synth.rs for
int_to_str and float_to_str), one Str carve-out in
drop_symbol_for_binder's App arm, RED→GREEN verification of the
two existing pinning tests, two new positive tests (Int-arg
primitive non-leak, repeated Str-arg borrow), DESIGN.md anchor
under Decision 10 covering BOTH arg-position rules (Ctor=Consume,
Do=Borrow), WhatsNew entry, roadmap close of the heap-Str ABI P1
milestone.
Plan-recon DONE: lint-side-effect surface (over-strict-mode on
(own T) params used solely via effect-ops) is empty for the
current corpus, so no follow-up sweep iter needed. IR-snapshot
regen confirmed no-op. Two inline IR-shape tests at
codegen/src/lib.rs:4127-4205 stay green (ret_mode flip does not
change their emitted-call assertions).
Wires the hs.3 runtime symbols (ailang_int_to_str, ailang_float_to_str)
into live AILang builtins. Four layers, one iter: checker install +
synth.rs lockstep partner; IR-header declares + Emitter::lower_app
arms (float arm replaces CodegenError::Internal, new int arm); rc.c
hoisted to unconditional link (weak attr on str.c's extern becomes
permanent no-op, retained intentionally); two new IR-shape pins + four
new E2E (two stdout-smoke, two RC-stats discipline) + drop.rs comment
refresh. Spec line refs were stale (hs.1+hs.2+hs.3 commits shifted
them); plan anchors to recon-verified positions lib.rs:1890-1903 and
:486-535. Edge cases (0, -1, i64::MAX, ±Inf, NaN) deferred to
follow-up tidy iter if regression sweep does not surface need.
Pure runtime/str.c addition: str_alloc helper + ailang_int_to_str +
ailang_float_to_str. No codegen, checker, or build-pipeline changes
in this iter — the IR-side wiring (declare lines, lowering, checker
install, rc.c always-linked) all batch into hs.4. Acceptance gate:
runtime continues to build and link with the new symbols present but
unreferenced (clang -O2 dead-strips them until hs.4 wires a caller).
Two tasks: (1) append three functions + includes + extern decl to
str.c, verify via clang -c + nm; (2) full workspace + cross_lang +
compile_check + check sweep stays green.
Supersedes the defunct hs.2 plan at 8ca602d (runtime-sentinel +
Str-in-ADT drop safety). After the spec amendment at 2a72a4a dropped
the sentinel-rc-header story, the iter scope is now a surgical retrofit
of hs.1's emission: drop the leading i64 sentinel slot from static-Str
globals, land the IR-Str pointer on the (now first) len-field via
GEP (i32 0, i32 0). The four +8 consumer GEPs are invariant across the
switch. Three tasks: (1) update the two IR-shape tests to the new
layout (RED); (2) flip three format-string sites + two doc-comments
in lib.rs (GREEN); (3) regenerate hello.ll snapshot + workspace +
cross_lang + compile_check + check.
Second iter of the heap-Str ABI milestone. Adds the UINT64_MAX sentinel-header short-circuit to ailang_rc_inc / ailang_rc_dec so the hs.1 packed-struct globals (whose first slot is i64 -1) flow safely through generic RC paths. Tasks: (1) author rc_str_field_in_adt_static.ail.json + confirm builds; (2) TDD cycle for the safety test + runtime guards; (3) full regression sweep.
First iter of the heap-Str ABI milestone (docs/specs/2026-05-12-heap-str-abi.md). Carrier reversed by Boss judgement: original carrier said runtime+checker first, but the spec's no-intermediate-state clause forbids installing int_to_str without its codegen arm, and the runtime/str.c additions can't be tested in isolation. Layout migration is the natural prerequisite that everything else builds on.
Tasks: (1) intern_str_literal table + function + emission loop + Literal::Str callsite switch; (2-4) +8 GEPs at io/print_str, eq__Str, compare__Str callsites; (5) snapshot regen + cross_lang.py regression check. Acceptance: every existing program byte-identical.
Boss-direct plan (no parent spec — this is a P2-roadmap-todo, not a
milestone iter). Option 1 picked from the roadmap fork: auto-parse
.ail internally so `ail check foo.ail` works the same as
`ail check foo.ail.json` (modulo the surface-parse step). Option 2
(hint-only) was a workaround that would have forced LLM-authors to
prepend `ail parse` before every check/build/run.
Architecture: extension dispatch lives in ailang-surface (which
already depends on core); core gains a `load_workspace_with` injection
point so the dispatch reaches transitive imports; surface parse
errors get a new WorkspaceLoadError::SurfaceParse variant so
`workspace_error_to_diagnostic` can route them in --json mode.
Tasks:
1. core::load_workspace_with + WorkspaceLoadError::SurfaceParse
+ .ail-first import resolution
2. surface::load_module + surface::load_workspace
3. crates/ail/src/main.rs rewire (~17 callsites) + 2 e2e tests
4. workspace_error_to_diagnostic SurfaceParse arm + DESIGN.md
§Decision-6 CLI addendum + ct1_check_cli diagnostic test
Walks the implementer from a fresh harness/ Cargo project to a green
test sweep across strip_locations (5 unit + 5 integration on real
captured stderr), verify_references (4 reference solutions run
through the live ail+clang pipeline locally), mock_full_run (eight
canned-cohort-task pairs end-to-end), and budget_abort (tiny budget
exhaustion). Six modules: strip_locations, pipeline, ionos
(reqwest blocking + retry per spec §Error handling), mock, scoring,
tasks. Captures five real stderr samples (recon-collected) as
fixtures; strip_locations regex calibrated to the actual diagnostic
shape (handles `at byte N`, anyhow `Caused by:` chains).
Workspace-table and .gitignore included in Task 1 from the outset
(learned from cma.1 surfaced concerns; not repeated as
post-hoc journal items). Out-of-workspace pattern matches render/
verbatim. AIL_BIN env var with PATH fallback for `ail` resolution;
clang preflight check added since `ail build` shells to clang.
Two explicit deferrals to implementer named in the plan:
ParamMode names (lifted from cma.1) and prelude function symbols
(from crates/ailang-check/src/builtins.rs); both stable from cma.1
authoring, no re-derivation needed.
Walks the implementer from a fresh directory to a green test sweep
(splitter_unit, spec_completeness, example_roundtrip, token_balance)
plus two checked-in rendered/*.md files. Visitor borrowed verbatim
from schema_coverage; master/examples authored fresh as a curated 13-
fixture set (one per AST variant cluster); master/spec.md authored in
13 sections with form-only blocks balanced by the ±5% gate.
Open authoring deferrals to the implementer (named at the planner
level, intentional): exact ParamMode enum names and the canonical
prelude function names — both retrieved from current source by
reading ailang-core/src/ast.rs and the prelude module at authoring
time, rather than pinned in the plan against a possibly-stale recall.
Plan for the corrected iter 23.4: restructure mono.rs into a single
specialiser for every Type::Forall-quantified Def::Fn (class methods
+ polymorphic free fns) in one fixpoint pass, and remove the codegen-
time specialiser (lower_polymorphic_call + module_polymorphic_fns +
mono_queue) entirely.
11 tasks, 4-step TDD template per task (write-failing-test →
verify-fail → write-impl → verify-pass), no per-task commit step
under the new disc.1 discipline.
Parent spec: docs/specs/2026-05-11-23-eq-ord-prelude.md (re-grounded
2026-05-11 against main HEAD 51da9fa, PASS, 10 load-bearing
assumptions verified).
Open commitments resolved:
- N-ary mono-symbol naming: spec default <name>__<t1>__<t2>__...
- Target-collector: extension of existing collect_mono_targets
(lockstep with collect_residuals_ordered)
- Original poly Def::Fn retention: kept parallel to Def::Class/
Def::Instance
Float-NoInstance diagnostic wording remains deferred to iter 23.5.
The 23.4 mono-unification plan (ea0285b) assumed prep1 + prep2 +
prep3 were on main. They never were — they sit only on iter/23.4.
Spec component table was factually wrong. Plan Task 10 (revert prep
commits) was impossible on main. Discarding the plan; the spec is
next revised against the actual main state.