Files
AILang/docs/journals/2026-05-15-iter-it.3.md
T
Brummel 305ffd1367 iter it.3 BLOCKED: surfaced fundamental milestone-design fork (bounce-back)
it.3 Task 1 (non-destructive oracle + spec-delegated class-(b)
sweep) ran complete; zero production code changed. The mandated
sweep surfaced that 6 corpus fixtures contain
build(d:Int)=if d==0 then Leaf else Node(1,build(d-1),build(d-1)) —
a terminating, maximally-LLM-natural, non-structural non-tail
BRANCHING recursion the milestone's totality dichotomy makes
inexpressible (not ADT-structural; not recur-able — branching is
not a single tail back-edge). The milestone as-specified would
fail its own feature-acceptance criterion. Orchestrator correctly
bounced rather than patch a 4th time (spec_over_plan_patches).
Records the blocked attempt + the reusable bench/it3-oracle/
(40-fixture behavioural oracle, valid for the post-decision
re-dispatch). main forward-only; nothing reverted. Resolution
(it.2b + a user purity-pillar decision) tracked in the roadmap.
2026-05-15 16:06:42 +02:00

188 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# iter it.3 — retire tail-app/tail-do + corpus migration
**Date:** 2026-05-15
**Started from:** c992eb93df4c5ec0a0686c924535cb9951be552f
**Status:** BLOCKED
**Tasks completed:** 1 of 7 (Task 1 complete; BLOCKED at the
Task-1.3 → Task-2 boundary before any destructive task)
## Summary
Third and terminal iteration of the iteration-discipline milestone
(destructive: retire `tail-app`/`tail-do`, migrate the corpus).
Task 1 (the non-destructive pre-migration oracle + the spec-delegated
class-(b) live enumeration) ran to completion: 40 recursive corpus
fixtures classified, 40 behavioural oracles captured under
`bench/it3-oracle/`, `MANIFEST.tsv` written. Task 1.3's mandated
live sweep surfaced a **real spec-signal** that the plan's own
self-review (lines 550-560) and the carrier explicitly defined as a
BLOCKED-to-Boss condition, not a silent reshape: **six fixtures
contain a recursive fn that resists BOTH a natural `(loop)`/`recur`
form AND a structural-plain form.** Per DD-2/DD-3 (migrate before
remove; Task 4's completeness gate must not be softened and a RED
there is a Task-2 defect, never a restored exemption) there is **no
in-plan migration target** for these six. The destructive tasks
(4/5) were therefore not started — correctly, since the migration
they depend on is impossible for this subset and DD-3 forbids
working around it. No production code was modified; the working
tree contains only the new `bench/it3-oracle/` artefacts.
## Per-task notes
- iter it.3.1: Pre-migration oracle + migration-set enumeration —
**complete.** `cargo build -p ail` clean at HEAD c992eb9.
Class-(a): 23 `(tail-app|tail-do)` fixtures (recon-confirmed).
Class-(b) live sweep (Task 1.3, spec-delegated): read
`verify_structural_recursion` + the two it.2 exemptions
(`lib.rs:3027` `if !*tail` grandfather; `lib.rs:3197`
`if cand.is_empty() && group.members.is_empty()` no-ADT skip),
then classified every self-recursive corpus fn against the
post-Task-4 verdict logic (`lib.rs:3219-3267`). Authoritative
result: 13 no-ADT-candidate single-recursion fns are
loop-migratable; 11 fixtures recurse structurally on an ADT param
(clean before AND after Task 4 — no migration, only the redundant
`tail-app` marker if class-(a) is dropped); **6 fixtures have a
no-ADT-candidate DOUBLE non-tail recursion (binary-tree build)
that is neither structural nor loop-expressible.** Oracles
captured for all 40 (`bench/it3-oracle/<stem>.out` + `MANIFEST.tsv`).
Task 1.5 fallout list recorded below for the eventual unblocked
re-dispatch. No code changed (Task 1 is non-destructive by spec).
- iter it.3.2 … it.3.7: not started. Task 2 (migration) has no
valid action for the 6 blocked fixtures; Tasks 4/5 are
destructive and gated behind a complete Task-2 migration that
cannot be completed. Halted at the spec-signal per carrier.
## Concerns
- **The RC-RSS / 18g.1 load-bearing risk (DD-4 / Task 5.5 / 5b) was
NOT reached.** The iter blocked before Task 5, so the 18g.1
husk-dec deletion and the RC-RSS bench gate were never exercised.
No RC-RSS evidence exists from this dispatch. The milestone-close
audit must NOT treat the RC-RSS contingency as resolved — it is
untested. When the spec defect below is resolved and it.3 is
re-dispatched, Task 5.5 (and conditionally 5b) is still the
milestone's load-bearing risk and must be run + its evidence
journalled then.
## Known debt
- `bench/it3-oracle/` currently holds 40 `.out` snapshots +
`MANIFEST.tsv` (41 files). They are the Task-1 deliverable and
stay valid for a re-dispatch from the same `start_sha`. Boss
call at commit whether to keep them under `bench/` (plan §"Files
this plan creates": "deleted in Task 6 … or kept under `bench/`
if cheap") — but do NOT delete before the re-dispatch; the
re-dispatched Task 7.3 diffs against them.
- The 11 class-(a) `plaincall` fixtures (structural on an ADT param,
carrying only a redundant `tail-app` marker) and the 11
`already-structural` fixtures need no semantic migration — only
marker-stripping (class-a) — and are unaffected by the blocker.
Recorded so the re-dispatch does not re-derive this.
## Blocked detail
**Task:** 1 (the Task-1.3 spec-delegated sweep) → halts entry to
Task 2 / Task 4.
**Reason:** `spec-ambiguous` / spec defect surfaced by the mandated
live sweep — six corpus fixtures contain a recursive fn that is
**neither structural recursion (no ADT-typed parameter — `cand`
empty in `verify_structural_recursion`) nor expressible as
`(loop …)`/`recur`** (the recursion is two non-tail self-calls
building both children of a binary `Tree`; `recur` is
tail-position-only with a single back-edge, so a balanced-tree
build cannot be a tail loop). After Task 4 removes the
no-ADT-candidate skip (`lib.rs:3197`, mandated by DD-3 and the
spec's it.3 acceptance bullet "no grandfather/no-candidate skip
remains"), each of these deterministically fires
`CheckError::NonStructuralRecursion` (verdict logic `lib.rs:3219-3267`:
`cand` empty ⇒ `self_clear=false` ⇒ NSR). DD-3 forbids softening
Task 4 or restoring the exemption; the carrier and project memory
(`feedback_dont_adapt_tests_to_bugs`) forbid reshaping the
LLM-natural fixture (e.g. changing `depth: Int` to an ADT-encoded
`Nat`, or hand-rolling an explicit stack/continuation). There is
**no in-plan migration target**, so the destructive split cannot
proceed.
**The six fixtures (fn :: shape):**
1. `examples/bench_tree_walk.ail` :: `build_tree`
(`(if (== depth 0) (Tree Leaf) (Tree Node 1 (build_tree (- depth 1)) (build_tree (- depth 1))))`)
2. `examples/bench_latency_explicit.ail` :: `build_tree` (same shape; file is class-(a) for other fns but `build_tree` itself is non-tail double recursion)
3. `examples/bench_latency_implicit.ail` :: `build_tree` (same)
4. `examples/rc_let_owned_app_leak.ail` :: `build` (same Tree shape on `d: Int`)
5. `examples/rc_pin_recurse_implicit.ail` :: `build` (same; the RC-regression-guard fixture from it.2 Concerns §2)
6. `examples/rc_let_alias_implicit_param.ail` :: `build` (same; the RC-regression-guard fixture from it.2 Concerns §2)
This is exactly the spec-signal the it.2 journal §1 foreshadowed
(it named `bench_latency_explicit:build_tree` as a no-ADT-candidate
case "whose migration to `(loop …)` is the destructive it.3 corpus
pass") and the plan self-review's "Recorded risk" anticipated
("a genuine non-structural recursion with no natural loop form …
surfaces as a Task-2 BLOCKED to the Boss with the fixture named").
The spec/plan assumed every no-ADT-candidate recursion is a
loopable counter/accumulator; balanced-binary-tree construction by
double recursion on a depth counter is the counter-example.
**Suggested next step:** Boss-level spec decision required (this is
not an implementer or planner judgement call — see
`feedback_spec_over_plan_patches`: a spec defect goes back through
`brainstorm`, not a fourth plan patch). Candidate resolutions for
the Boss to weigh, language-first:
(a) **Add a structural accommodation for tree recursion** — extend
`verify_structural_recursion` so a non-tail recursive call on a
*structurally-derived smaller value* is guarded even when the
decreasing quantity is a primitive depth counter feeding an ADT
build (i.e. recognise the `build_tree` shape as bounded). This
keeps the six fixtures verbatim and is the only option that does
not reshape LLM-natural code, but it widens it.2's structural
checker — a Decision-10/Decision-3 spec change, brainstorm-gated.
(b) **Carve the six into a permanent allow-list / carve-out** (like
the existing `.ail.json` carve-outs) with an explicit
"constructor-blocked recursion, depth-bounded by construction"
annotation, leaving the no-ADT-candidate skip retired for
everything else. Requires a spec sentence defining the carve-out
predicate.
(c) **Retire the bench fixtures that exist only to exercise the
removed `musttail`/RC-RSS path** (`bench_latency_*`,
`rc_pin_recurse_implicit`, `rc_let_alias_implicit_param`,
`rc_let_owned_app_leak`) and replace `bench_tree_walk`'s
`build_tree` coverage with a structural equivalent — but this is
the "adapt the fixture to dodge" path the carrier and
`feedback_dont_adapt_tests_to_bugs` explicitly forbid for
language-limitation cases; named only for completeness, not
recommended.
Once the Boss resolves the spec, re-dispatch it.3 from the same
`start_sha` (the `bench/it3-oracle/` artefacts remain valid).
## Files touched
Created (untracked, non-code):
- `bench/it3-oracle/MANIFEST.tsv` (40-fixture classification)
- `bench/it3-oracle/<stem>.out` × 40 (behavioural oracle:
`ail run` stdout for `main` fixtures, `ail check` output for
check-only)
No production code, no spec, no test files modified (Task 1 is
non-destructive by plan; the BLOCKED halted before any code-edit
task).
## Task 1.5 fallout map (recorded for the unblocked re-dispatch)
Tail-app-specific tests the plan's Task 6.4 will delete:
`crates/ailang-prose` `app_tail_renders_with_keyword`,
`binop_with_tail_flag_keeps_prefix_form`,
`not_with_tail_flag_keeps_prefix_form`;
`crates/ailang-core/tests/spec_drift.rs::spec_mentions_tail_variants`;
`crates/ailang-check` `TailCallNotInTailPosition` pins
(`tail_call_in_tail_position_is_accepted` /
`..._non_tail_position_is_rejected` if present); any
`iter14e_*musttail*` e2e. (Enumeration deferred to the
re-dispatch's Task 1.5 against the then-current tree, since the
exact test names will drift; recorded here as the recon seed.)
## Stats
bench/orchestrator-stats/2026-05-15-iter-it.3.json