Commit Graph

5 Commits

Author SHA1 Message Date
Brummel 1faee673f7 fieldtest: mut-local — 6 examples (4 positive + 2 negative probes), 0 bugs / 3 friction / 1 spec_gap
Boss-dispatched fieldtest after audit-mut-local closed. Six AIL
Surface (.ail) fixtures under examples/fieldtest/ exercise the
shipped mut-local surface from a downstream-LLM-author's perspective
(no compiler-source access; DESIGN.md + public examples only).

Positive fixtures all run end-to-end first-try:
- mut-local_1_factorial.ail: straight-line Int accumulator
  unroll (5!), prints 120.
- mut-local_2_classify_temp.ail: nested-if assigns into a Unit-
  typed mut block, prints classification code.
- mut-local_3_horner.ail: Float mut accumulator for polynomial
  evaluation, prints 18.
- mut-local_4_has_small_factor.ail: Bool mut flag via four
  if-then-assign checks, prints true.

Negative probes confirm diagnostics fire as documented:
- mut-local_5_lambda_capture_probe.ail: [mut-var-captured-by-lambda].
- mut-local_6_diag_probe.ail: [mut-var-unsupported-type].

Findings:

[friction] F1 — mut without iteration: the accumulator-over-an-
iteration shape never materializes. Without while/for, the LLM-
author still writes a tail-recursive helper (the very pattern
the milestone Goal said mut would replace). examples/mut_counter.ail
illustrates the degeneration. Routing: planner for a while/for
iteration OR tighten DESIGN.md to name the gap honestly.

[friction] F2 — all four mut-related diagnostics emit their
bracketed [code] twice ('error: [code] fn-name: [code] message').
Mechanical bug: the #[error('[code] ...')] Display attributes I
authored in mut.2/mut.4-tidy include the bracketed prefix in the
message body, and the cli-diag-human formatter adds another from
CheckError::code(). Routing: debug (mechanical message-body
cleanup).

[friction] F3 — no surface form to call a zero-arg fn ('(app f)'
rejected at parse with 'expected at least one argument').
Orthogonal to mut-local but surfaced building the closure-factory
probe. Routing: planner for a small tidy iter.

[spec_gap] F4 — DESIGN.md does not name the 'use a tail-rec
helper instead' workaround for the iteration-over-accumulator
shape that mut alone cannot express. Routing: ratify in DESIGN.md
alongside F1's resolution.

[working] W1/W2/W3 — surface reachable on first read; diagnostics
pinpoint cause (mut-assign-out-of-scope even lists available
vars); composes cleanly with if + lambda-without-capture +
final-expression position.

Spec: docs/specs/2026-05-15-fieldtest-mut-local.md (333 lines).

Refs: docs/specs/2026-05-15-mut-local.md, audit-mut-local close
at 8685e96.
2026-05-15 09:52:43 +02:00
Brummel 6fdb45d2f2 iter rpe.1: retire per-type print effect-ops
Single iter shipping the post-milestone-24 follow-up named in
docs/specs/2026-05-14-retire-per-type-print-effects.md. After this
iter the only surviving direct-output effect-op is `io/print_str`;
all per-type print primitives are replaced by the polymorphic
`print` helper (prelude, iter 24.3).

Components:
- 92 examples/*.ail fixtures migrated (do io/print_<T> x) →
  (app print x); 6 .prose.txt snapshots regenerated via `ail prose`.
- Four-site lockstep compiler deletion: crates/ailang-check/src/builtins.rs
  (3 effect_ops.insert blocks + 3 list() rows + the
  install_io_print_float_signature test + module + EffectOpSig
  doc-comments); crates/ailang-codegen/src/lib.rs lower_app
  (3 arms + lowers_io_print_float test); crates/ailang-codegen/src/synth.rs
  builtin_effect_op_ret match-arm pattern. Dead `intern_string`
  helper removed as a follow-up.
- Five incidental test-body migrations (ailang-check x2, ailang-core
  spec_drift + design_schema_drift, ailang-surface/src/lex.rs,
  ailang-prose/src/lib.rs round-trip test).
- Cat B test-harness patch: six IR-shape tests in
  crates/ail/tests/e2e.rs gained a monomorphise_workspace call
  before lower_workspace_with_alloc so they follow the same
  pipeline as `ail build` (the home-rolled desugar+lift loop
  stayed because mono's precondition is "already lifted"; mono
  inserts after lift).
- Six doc-comment touch-ups (lex.rs module doc, parse.rs
  diagnostic example, ail/src/main.rs x2, runtime/str.c %g anchor,
  crates/ailang-core/specs/form_a.md surface-spec example).
- DESIGN.md seven-site sweep (Decision 11 example, Polymorphic
  print past-tense, Heap-Str output sentence, effect-op
  invocation comment, Float NaN paragraph re-anchored on
  float_to_str, two "What is supported" lists).
- Three E2E test-comment polish + four IR-snapshot refresh + one
  canonical-hash pin update (plan-unanticipated downstream
  consequences of the corpus migration).
- bench/{check,compile_check,cross_lang}.py: all exit 0; no
  ratification needed.
- Roadmap entry struck through; per-iter journal at
  docs/journals/2026-05-14-iter-rpe.1.md.

Tests 564/0/3. cargo clippy and cargo doc: zero warnings.

Two upstream codegen bugs surfaced during the first BLOCKED
attempt and were fixed in separate iters before this retry:
- 1fb225e bugfix: mono cursor misalignment at poly-free-fn Var
  with class-constrained Forall.
- feb9413 bugfix: print leak — propagate ret_mode through rigid
  substitution + prelude Show.show ret_mode.

Known debt (carried forward for next /audit):
- Emitter.strings field is functionally dead post-iter (orphan
  after intern_string removal); cycles over empty map harmlessly.
2026-05-14 02:12:34 +02:00
Brummel 8698d897b6 fieldtest-form-a: 4 fixtures + spec report; agent doctrine update
Boss-dispatched fieldtest at milestone close. Agent authored 4 .ail
fixtures (factorial smoke + Show user-ADT + user-class Describe with
two instances + two-module workspace) from DESIGN.md + form_a.md only
(no compiler-source reads, no spec-of-milestone reads). All four
fixtures `ail check` ok and `ail run` produces expected stdout.

Findings (1 bug, 1 friction, 2 spec_gaps, 3 working):

- [bug] instance-method-body unbound-var bypasses `ail check` —
  forma_3 first attempt called `str_concat` inside the instance
  method body; `ail check` returned ok, `ail build` died with the
  monomorphise_workspace "unknown identifier" diagnostic. Same
  shape at fn-body level correctly fires `[unbound-var]` at check
  time. Next: debug skill, RED-first against `ail check`.

- [friction] no `str_concat` primitive. Every realistic Show MyType
  body wants string concatenation; the absence forced the agent to
  shape examples around bare int_to_str / ctor-arity-1 patterns.
  Next: small planner tidy iter wiring `str_concat` symmetric to
  `str_clone` and `int_to_str`.

- [spec_gap] form_a.md has zero references to class, instance,
  constraint, or method productions — pre-22 surface only. The
  form-a-default-authoring milestone made .ail the authoring form,
  but the form_a spec doc remains pre-typeclass.

- [spec_gap] form_a.md leaves the class-qualifier ambiguity in
  `(instance (class X))` unspecified — bare-class-name vs canonical-
  form rule from mq.1 is not documented at the surface level. The
  agent picked the bare-name reading from the corpus; the canonical-
  form reading is equally plausible from the schema.

Boss-side cleanup at commit time:
- Deleted 8 stale .ail.json sidecars in examples/fieldtest/ (4
  forma_* derived by the fieldtester per old dual-form workflow + 4
  pre-existing floats_* from the prior fieldtest milestone that
  iter form-a.1 T8 missed because the bash deletion loop globbed
  only examples/*.ail.json direct children).
- Updated skills/fieldtest/agents/ailang-fieldtester.md to remove
  the now-obsolete "generate canonical JSON sidecar" step (Phase 3
  rewritten + Iron Law + Reading list + Common Rationalisations +
  Red Flags all aligned to the post-form-a single-form doctrine).

cargo test --workspace: 557 passed, 0 failed, 3 ignored (unchanged
from audit-form-a — the fieldtest fixtures are standalone, not
referenced by any test).

Findings deferred to follow-up iters; the milestone close itself is
still clean.
2026-05-13 11:48:58 +02:00
Brummel 72e54f4fd3 iter ext-rename: .ailx → .ail across the live toolchain
The surface-form file extension changes from .ailx to .ail. AILang's
authoring surface now uses the same .ail stem as its canonical JSON
form (.ail.json), giving the language a single coherent extension
family: .ail is the LLM-authored Form A, .ail.json is the canonical
JSON-AST Form B.

Scope (touched):
- 61 example renames examples/**/*.ailx → .ail (git mv)
- 1 rename experiments/.../rendered/ailx.md → ail.md
- 35 content-edited live-toolchain files (crates/, docs/DESIGN.md,
  docs/roadmap.md, docs/PROSE_ROUNDTRIP.md, skills/, bench/reference/*.c,
  experiment crates under experiments/.../{render,harness,master})
- Experiment-crate cohort rename Cohort::Ailx → Cohort::Ail,
  Form::Ailx → Form::Ail, per_cohort/ailx → per_cohort/ail,
  {form-only: ailx} → {form-only: ail}, ```ailx → ```ail

Out of scope (deliberately untouched, to preserve honest history):
- docs/journal-archive.md (content-frozen per CLAUDE.md)
- docs/journals/, docs/specs/, docs/plans/, bench/orchestrator-stats/
- experiments/.../runs/ (frozen LLM-output artefacts; models actually
  saw .ailx — renaming would falsify the experimental record)

Verification: cargo build/test --workspace green; experiment crate
cargo test green; bench/check.py + compile_check.py + cross_lang.py
all 0-regressed; negative grep for ailx|Ailx|AILX outside the
out-of-scope paths returns zero matches.

Opens immediate follow-up: roadmap.md P2 todo `ail check`/build/run
accept .ail extension — after this rename, .ail is canonical
authoring surface but the CLI still produces a misleading JSON-parse
error on `ail check foo.ail`. That's the next iter.
2026-05-12 14:20:27 +02:00
Brummel 2052f4dfcc fieldtest: floats — 4 examples, 6 findings (1 bug, 1 friction, 1 spec_gap, 3 working) 2026-05-10 16:57:38 +02:00