fieldtest: loop-recur — 10 examples, 6 findings (milestone CLOSE, clean on all axes)
Post-audit downstream-LLM-author field test of the shipped loop/recur surface (DESIGN.md + public examples only). 3 real iterative programs (Newton isqrt, Collatz, Euclidean gcd) + 5 plausible-mistake negatives + 2 no-termination probes, all run through the public ail CLI. 0 bugs. 4 working findings on the milestone's own axes: rejection diagnostics point-exact AND self-fixing; recur tail-position threads through match/let/outer-if (spec only showed if); loop composes as a value sub-expression + byte-stable round-trip; no-termination boundary exact. This empirically substantiates the "LLM author can now write iterative programs" claim. Two orthogonal non-blocking findings, neither in loop/recur scope, both routed to P2 todos (refused the scope creep into a loop/recur tidy): niladic (app f) spec_gap independently re-confirms the existing mut-local-F3 roadmap item (the design-fork decision deliberately NOT auto-ratified under /boss — parked, priority-strengthened); module-level (doc) diagnostic-hint friction (one-line tidy). Boss-verified independently (gcd->27; recur-outside-loop fires exact). The standalone loop/recur milestone is fully ratified and CLOSED: 3 iterations + tidy shipped, audit clean (drift resolved, bench pristine carry-on), fieldtest clean on every axis. Roadmap P0 marked closed.
This commit is contained in:
+39
-18
@@ -35,20 +35,22 @@ work progresses.
|
||||
|
||||
## P0 — In flight
|
||||
|
||||
- [~] **\[milestone\]** Standalone `loop` / `recur` — strictly-additive
|
||||
iteration surface, `recur` valid only in tail position. All three
|
||||
iterations + a tidy shipped: iter 1 `a179ec3` (additive AST nodes),
|
||||
- [x] **\[milestone\]** Standalone `loop` / `recur` — CLOSED 2026-05-18.
|
||||
Strictly-additive strict-iteration surface, `recur` tail-position-only,
|
||||
no totality claim. Shipped: iter 1 `a179ec3` (additive AST nodes),
|
||||
iter 2 `1566ce0` (typecheck), iter 3 `edd2558` (codegen + run-to-value
|
||||
E2E), tidy (lambda-captures-loop-binder rejected at check, symmetric
|
||||
to mut.4-tidy). Milestone-close `audit` clean: architect drift
|
||||
resolved (the `[high]` codegen crash fixed in the tidy + two
|
||||
`[medium]` doc-honesty edits folded in), bench pristine (25 metrics,
|
||||
0 regressed — strictly-additive surface, no hot-path touched).
|
||||
**Remaining: `fieldtest`** (loop/recur is user-visible Form-A
|
||||
surface) — the only step before full close.
|
||||
- context: `docs/specs/2026-05-17-loop-recur.md`; principles entry
|
||||
`docs/specs/2026-05-17-llm-surface-discipline.md` §6.2; revert
|
||||
rationale `docs/specs/2026-05-16-iteration-discipline-revert.md`.
|
||||
E2E), tidy `39380d3`/`2ee9794` (lambda-captures-loop-binder rejected
|
||||
at check). Milestone-close `audit` clean (architect drift resolved,
|
||||
bench pristine 25/0 carry-on); `fieldtest` 2026-05-18 clean on all
|
||||
four milestone axes (0 bugs; diagnostics point-exact+self-fixing,
|
||||
recur-tail through match/let, loop-as-value-subexpr byte-stable,
|
||||
no-termination exact). Two orthogonal non-blocking findings routed
|
||||
to P2 todos (niladic `(app f)` — re-confirms mut-local F3; module
|
||||
`(doc)` diagnostic hint). Stays here briefly for context; remove
|
||||
once stale (full record in `docs/journals/INDEX.md`).
|
||||
- context: `docs/specs/2026-05-17-loop-recur.md`;
|
||||
`docs/specs/2026-05-18-fieldtest-loop-recur.md`; principles entry
|
||||
`docs/specs/2026-05-17-llm-surface-discipline.md` §6.2.
|
||||
|
||||
## P1 — Next
|
||||
|
||||
@@ -294,11 +296,30 @@ work progresses.
|
||||
- [ ] **\[todo\]** Zero-arg `(app f)` rejected at parse — the Form-A
|
||||
parser refuses an application with an empty argument list, so a
|
||||
nullary call has no surface form. Surfaced by the mut-local
|
||||
fieldtest (F3). Decide: accept `(app f)` as the nullary-call
|
||||
surface, or ratify in DESIGN.md that nullary functions are
|
||||
expressed differently (and say how). Not a blocker; no current
|
||||
corpus program needs it, but an LLM author reaches for it.
|
||||
- context: `docs/specs/2026-05-15-fieldtest-mut-local.md` finding F3.
|
||||
fieldtest (F3) AND **independently re-confirmed by the loop/recur
|
||||
fieldtest** (2026-05-18, finding spec_gap): the maximally-natural
|
||||
infinite-event-loop shape is a niladic `run_forever : fn() -> Int`
|
||||
called `(app run_forever)`, which dies at parse before reaching
|
||||
loop/recur semantics. Two independent fieldtests hitting the same
|
||||
gap raises the priority signal. Decide: accept `(app f)` as the
|
||||
nullary-call surface, or ratify in DESIGN.md that nullary functions
|
||||
are expressed differently (and say how). DESIGN.md's `Term::App`
|
||||
`args:[Term...]` states no minimum, so the surface "expected at
|
||||
least one argument" rule is unbacked by spec — a genuine design
|
||||
fork, deliberately NOT auto-ratified under autonomous orchestration.
|
||||
Not a blocker; no current corpus program needs it, but an LLM
|
||||
author reaches for it.
|
||||
- context: `docs/specs/2026-05-15-fieldtest-mut-local.md` finding F3;
|
||||
`docs/specs/2026-05-18-fieldtest-loop-recur.md` spec_gap.
|
||||
- [ ] **\[todo\]** Module-level `(doc …)` diagnostic omits where `doc`
|
||||
belongs — a `(module NAME (doc "…") (fn …))` is correctly rejected
|
||||
(`unknown def head \`doc\``) but the message lists valid def heads
|
||||
without saying doc strings attach *inside* `fn`/`data` defs; an
|
||||
author can read it and conclude doc strings are unsupported. One-line
|
||||
tidy: append a hint like "(doc strings attach inside `fn`/`data`
|
||||
defs, not at module level)". Low cost; verbose-diagnostic-philosophy
|
||||
gap, not a bug.
|
||||
- context: `docs/specs/2026-05-18-fieldtest-loop-recur.md` friction.
|
||||
- [ ] **\[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
|
||||
|
||||
Reference in New Issue
Block a user