Commit Graph

573 Commits

Author SHA1 Message Date
Brummel 1cf281b217 iter hs.3: heap-Str runtime additions — str_alloc + int_to_str + float_to_str
Append three new symbols to runtime/str.c: a private str_alloc(uint64_t)
slab helper that allocates [rc_header | len | bytes... | NUL] via
ailang_rc_alloc and writes the len prefix, plus two extern formatters
ailang_int_to_str(int64_t) and ailang_float_to_str(double) that compose
str_alloc with snprintf("%lld") / snprintf("%g"). Defensive abort() on
truncation; 64-byte stack buffer comfortably oversized for either
formatter.

The extern declaration of ailang_rc_alloc carries __attribute__((weak)).
First regression sweep without it surfaced 11 e2e link failures under
--alloc=gc and --alloc=bump: public T-visible symbols (int_to_str /
float_to_str) pull their transitive callees (rc_alloc) into every
binary's symbol set, but rc.c is not linked under gc/bump in hs.3.
The weak attribute makes the cross-allocator link safe in isolation;
under rc the strong definition wins as usual. Retained after hs.4
(when rc.c becomes unconditionally linked) as a no-op that keeps
str.c link-safe in isolation.

No IR-side caller wired yet — hs.4 lands the IR-header declare lines,
the int_to_str/float_to_str codegen lowering, the checker install,
and the unconditional rc.c link.

cargo test --workspace + cross_lang.py + compile_check.py + check.py
all green on re-sweep.
2026-05-12 18:03:46 +02:00
Brummel 187d04814d plan: hs.3 — heap-Str runtime additions, 2 tasks
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.
2026-05-12 17:56:03 +02:00
Brummel f9bf97be80 iter hs.2: static-Str layout retrofit — drop sentinel rc-header slot
Per the amended heap-Str ABI spec (2a72a4a), static-Str globals lose
the leading UINT64_MAX sentinel rc-header field that hs.1 introduced.
Layout flips from <{ i64, i64, [N x i8] }> <{ i64 -1, i64 N, ... }>
to <{ i64, [N x i8] }> <{ i64 N, ... }>; the IR-Str pointer now lands
on the len-field at struct-index 0 (was 1) via constexpr-GEP. The four
+8 consumer-side GEPs (@puts / @ail_str_eq / @ail_str_compare / @strcmp)
do not change — the bytes still sit 8 bytes past the len-field. Static-
Str pointers are kept out of ailang_rc_dec at the codegen level via
move-tracking (iter 18d.3) and non-escape lowering (iter 18b), so no
header slot is needed at the global; this is a codegen-level invariant,
not a runtime guard.

Change surface: three format strings + two doc-comments in lib.rs,
rename + assertion update of two IR-shape tests, snapshot regen of
hello.ll. No runtime changes, no checker changes, no new fixtures.
Static-Str globals are now 8 bytes smaller per literal.

cargo test --workspace green; cross_lang.py / compile_check.py /
check.py all green. 3 tasks, 0 re-loops.
2026-05-12 17:51:27 +02:00
Brummel 51a096cf83 plan: hs.2 — rewrite for static-Str sentinel-slot retrofit, 3 tasks
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.
2026-05-12 17:45:23 +02:00
Brummel 2a72a4ad68 spec: heap-str-abi — amend, drop sentinel-rc-header story
hs.2's implementer-orchestrator BLOCKED with an empirical finding: the iter 18d.3 move-tracking and iter 18b non-escape lowering together prevent static-Str pointers from ever reaching ailang_rc_inc/_dec along any shipping execution path. The previously-proposed runtime sentinel guard and the i64 -1 sentinel slot in static-Str globals were both dead by construction.

Amendment is subtractive: remove the runtime/rc.c guard from §Architecture/Runtime layer + §Components/runtime/rc.c (none needed), shrink static-Str globals from <{i64, i64, [N+1 x i8]}> to <{i64, [N+1 x i8]}> (saves 8 bytes per literal), update GEP indices (i32 0, i32 1 → i32 0, i32 0), drop the §Error-handling 'Sentinel collision' subsection, drop the proposed str_field_in_adt_drops_static_str_noop safety-gate test from §Testing strategy (vacuous against natural fixtures), reframe §Architecture/Codegen-4 as 'codegen-level elision invariant, no runtime guard'. Goal/consumer-ABI claims tightened to 'unified along consumer paths, producer + RC sides differ'.

Acceptance: re-dispatched grounding-check PASS. The amendment leaves hs.1 (committed at c56498a) needing a forward-fix retrofit — that is the new hs.2's scope, planned next.
2026-05-12 17:34:41 +02:00
Brummel 8ca602dc1f plan: hs.2 — runtime sentinel + Str-in-ADT drop safety, 3 tasks
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.
2026-05-12 16:53:36 +02:00
Brummel c56498aca7 iter hs.1: static-Str layout migration — packed-struct globals + sentinel rc-header + len
First iter of the heap-Str ABI milestone. Pure codegen refactor; every existing program produces byte-identical stdout.

Static-Str LLVM globals migrate from `[N x i8] c"…\00"` to `<{ i64, i64, [N x i8] }> <{ i64 -1, i64 N-1, [N x i8] c"…\00" }>`, carrying the UINT64_MAX sentinel rc-header (slot exploited in hs.2 via runtime short-circuit) and an explicit byte length. Two parallel intern paths (`intern_string` for raw format scaffolding, new `intern_str_literal` for language Str values) keep format strings untouched in `[N x i8]` shape.

IR-Str pointers now uniformly land on the len-field (offset +8 from rc-header, -8 from bytes). Four codegen sites that hand a Str pointer to a NUL-terminated-bytes C-API consumer now emit a +8 GEP first: `@puts` (io/print_str), `@ail_str_eq` (eq__Str intercept), `@ail_str_compare` (compare__Str intercept), and `@strcmp` (lower_eq Str arm — the 4th site was not in the plan; surfaced by Task-5 e2e regression and fixed inline).

6 new IR-shape pinning tests; `hello.ll` snapshot regenerated; cross_lang.py + compile_check.py + full `cargo test --workspace` green.
2026-05-12 16:48:24 +02:00
Brummel 69bb5f9952 plan: hs.1 — Static-Str layout migration, 5 tasks
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.
2026-05-12 16:36:29 +02:00
Brummel 750f97e455 spec: heap-str-abi — runtime-allocated Str slab + sentinel-static ABI
Two builtins ship together: int_to_str (new) and float_to_str (today type-installed but codegen-deferred). Both produce malloc-backed, refcounted Str slabs via new ailang_int_to_str / ailang_float_to_str runtime exports.

Slab layout is {rc_header, len, bytes, NUL}. Static-Str globals migrate to the same packed-struct shape with a UINT64_MAX sentinel rc_header; ailang_rc_inc / _dec short-circuit on the sentinel. From every caller's POV static and heap Str values are indistinguishable, so existing code paths (eq__Str, compare__Str, io/print_str, per-type drop walks) keep working with a single +8 GEP at the three C-API callsites and no change to drop dispatch.

Out of scope: ++ concat operator, Show typeclass + print rewire, length-aware comparison for embedded-NUL Strs.
2026-05-12 16:24:12 +02:00
Brummel 78c26b3596 boss: new milestones never start autonomously — fourth bounce-back trigger
Cross-milestone hops are high-context work and I cannot compact my own
context window. Adding a `brainstorm`-on-an-unspec'd-roadmap-item rule
that forces a bounce-back lets the user decide whether the next
milestone wants a fresh session or a continuation of the current one,
instead of consuming tens of thousands of tokens on a fresh spec Q&A
on top of whatever the just-closed milestone left behind.

Mechanics: Iron Law gains a fourth clause; Direction-Freedom-Bouncebacks
list a fourth trigger with the rationale spelled out; Step 3 reroutes
"new milestone → brainstorm" through the trigger; Problem-state
notification list, Common Rationalisations, and Red Flags all gain
the corresponding entries.
2026-05-12 14:54:52 +02:00
Brummel 79cc78507b iter ext-cli.1: CLI accepts .ail (Form A) sources alongside .ail.json
Closes the loop opened by this morning's .ailx → .ail rename. Every
path-taking ail subcommand (check, build, run, manifest, render,
prose, merge-prose, describe, emit-ir, diff, workspace, deps) now
accepts a .ail (Form A) input as well as .ail.json (Form B). For
.ail paths the subcommand parses through ailang_surface::parse
in-line and proceeds with the same loaded Module value .ail.json
would have produced; binary semantics are extension-agnostic.

Architecture: a new ailang_surface::{load_module, load_workspace}
pair dispatches on file extension. A new injection point
ailang_core::workspace::load_workspace_with<F> lets the surface
crate plug in an extension-aware loader without core having to
import surface (which would close a crate cycle). Import resolution
in workspace::visit now prefers a .ail sibling over a .ail.json
sibling. The CLI binary's 18 callsites switched to the surface
loaders. Surface parse failures route through
workspace_error_to_diagnostic as a new SurfaceParse variant of
WorkspaceLoadError, so `ail check --json foo.ail` on a malformed
.ail returns a parseable JSON diagnostic with code
surface-parse-error instead of the misleading
`json: expected value at line 1 column 1` fall-through.

Boss pre-commit correction: the implementer followed the plan
verbatim and used snake_case `surface_parse_error`, but every
existing diagnostic code in the codebase is kebab-case (verified
via `git grep` over crates/ailang-check/src and crates/ail/src);
realigned to `surface-parse-error` at three sites (the diagnostic
arm + two ct1 test strings). Journal Concerns section records
the correction.

Tests: cargo test --workspace 487 green (+7 from this iter:
1 core unit, 4 surface integration, 1 ail E2E pair, 1 ct1 CLI
diagnostic-shape). bench/check.py, compile_check.py, cross_lang.py
clean on re-run; the latency.{explicit,implicit}_at_rc tail
cluster occasionally flagged on first runs is the same
nondeterministic cluster the previous two audits documented;
baseline left pristine for the third consecutive iter.

Roadmap follow-up "ail check/build/run accept .ail extension" (P2)
removed.

DESIGN.md §Decision 6 / "CLI" bullet gained the symmetric upward
sentence: both .ail and .ail.json are first-class CLI inputs.
2026-05-12 14:45:03 +02:00
Brummel efecbaa3e6 plan: ext-cli.1 — CLI accepts .ail extension, 4 tasks
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
2026-05-12 14:28:28 +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 17b370bbb3 WhatsNew: cross-model authoring test — second subject added 2026-05-12 13:29:34 +02:00
Brummel 9dc6263b6e audit-ms: close milestone Multi-subject Authoring-Form Test — CodeLlama Replication
Architect drift review: clean (two [low] items both expected
audit by-products, not drift). Bench-regression check: all
three exit-code gates green; the 5-metric
latency.explicit_at_rc / gc_over_bump improvement cluster from
audit-cma earlier today reappears, second consecutive audit
showing the same shift uncorrelated with milestone work —
baseline left pristine for one more audit before considering
ratification.

All seven spec acceptance criteria green. Milestone closed.
2026-05-12 13:29:28 +02:00
Brummel 65a4f0aa16 iter ms.2: Qwen retroactive re-run + first CodeLlama-13b-Instruct run + DESIGN.md §Decision-6 addendum extended to two subjects
Two live IONOS harness invocations with the ms.1 fix in place:

  - Qwen/Qwen3-Coder-Next   → runs/2026-05-12-080864/  (RUN_STATUS=ok)
  - meta-llama/CodeLlama-13b-Instruct-hf
                            → runs/2026-05-12-9197fd/  (RUN_STATUS=ok;
                              2/8 JSON cells terminated as api_failure
                              on turn 1 zero-token — transient IONOS
                              terminal error, disclosed in addendum)

Per-cell results (reached/4, prompt tokens, completion tokens):

  Qwen      JSON     1/4   182,378   14,972
  Qwen      AILX     1/4   110,575    3,474
  CodeLlama JSON     0/4   116,015    2,711   [2 cells api_failure]
  CodeLlama AILX     2/4    93,017    2,234

Both subjects agree on direction: AILX cohort cheaper on prompt
tokens (Qwen 61%, CodeLlama 80% of JSON-cohort spend) and on
completion tokens (Qwen 23%, CodeLlama 82%); AILX reached-green
≥ JSON reached-green for each subject. Three of four
first-attempt-green cells across the two subjects are AILX.
Failure classes split symmetric to form: JSON cohorts fail at
typecheck, AILX cohorts at parse — each form's
front-of-pipeline check.

DESIGN.md §"Decision 6 / Empirical addendum (2026-05-12)"
replaced: 2-column single-subject view → 4-column two-subject
view, framing paragraph reports direction agreement and the
api_failure / Qwen-rerun-noise anomalies, scope paragraph
updated to 'two subjects, n=1 each, deterministic; not a
verdict — a universal claim would need ≥3 subjects with
statistical robustness'.

Roadmap P3 'Multi-subject expansion' entry removed; scoped
goal met for two subjects.

Milestone token spend: prompt 501,985 + completion 23,391
= 525,376.
2026-05-12 13:29:15 +02:00
Brummel 5858377c99 plan: ms.2 — multi-subject run + DESIGN.md addendum extension, 6 tasks (Qwen re-run + CodeLlama run + per-cell metrics + addendum + roadmap close + acceptance sweep) 2026-05-12 13:28:55 +02:00
Brummel 614fd8bc93 iter ms.1: pipeline.rs format!("check: {e}") → {e:#} preserves anyhow Caused-by chain in JSON-cohort feedback
Inline pinning test in pipeline.rs constructs the same chain
shape module_name_from_json produces on serde-parse failure
(leaf wrapped with "parsing JSON in <path>" context) and
asserts both layers survive the formatter. RED→GREEN against
the property, not against production line bytes — for a
two-character fix, extracting a helper just for testability
would be over-engineering.

The strip_locations regex collapses \nCaused by: chains; the
{:#} alternate Display joins with ': ' on one line, so the
collapser is a no-op on the fixed output. AILX cohort
unaffected — only the harness-side anyhow path (module
rename pre-check) was dropping cause information.

Harness suite: 14/14 green (was 13/13 + 1 new pin).
2026-05-12 13:28:48 +02:00
Brummel 2efaee07f0 plan: ms.1 — pipeline anyhow-chain preservation, 3 tasks (RED→GREEN pin + 2-char fix + full harness sweep) 2026-05-12 13:28:31 +02:00
Brummel 5526d839f8 spec: multi-subject CodeLlama replication — pipeline anyhow-chain fix + second subject run 2026-05-12 13:28:25 +02:00
Brummel 8689f7a238 WhatsNew: cross-model authoring test landed — first data point
Mirrors verbatim the done-state notification sent at milestone
close. Single-subject scope; multi-subject expansion queued.
2026-05-12 12:22:08 +02:00
Brummel 94d6963995 audit-cma: close milestone Cross-model authoring-form test
Architect drift_found, both [low]:
- INDEX backfill for commit 90512d5 (brainstorm Step 7.5 SKILL.md
  edit + roadmap P1 todo removed without a paired INDEX mirror).
- README "Total 8 passed" understated the actual 13/13 sweep.

Both fixed inline (mechanical, ≤30 LOC) per CLAUDE.md trivial-edits
carve-out; no implementer dispatch.

Bench: all three scripts exit 0, 0 regressed, 5 unexplained
latency.explicit_at_rc improvements not coupled to milestone work
(no in-workspace crate touched). Baseline left pristine — future
audits will reveal whether the improvements hold.

All 9 spec acceptance criteria green. Milestone closed clean.
2026-05-12 12:20:30 +02:00
Brummel e91e31aadb iter cma.3: live Qwen3-Coder-Next run + DESIGN.md §Decision-6 empirical addendum + milestone close
Milestone "Cross-model authoring-form test" closed. Live IONOS run
against Qwen/Qwen3-Coder-Next executed at temperature=0, max-turns=5,
token-budget=500000. Raw dataset under runs/2026-05-12-df7531/:
RUN_STATUS=ok, scores.csv with 8 rows (4 tasks × 2 cohorts),
summary.md, plus 156 per-turn raw artefacts (request/response/program/
stderr/stdout) preserved for any future analysis.

Headline numbers:
- AILX cohort: 2/4 green, 1/4 first-attempt, ~95k prompt + ~2.6k completion
- JSON cohort: 1/4 green, 0/4 first-attempt, ~192k prompt + ~15k completion
- Only first-attempt success was AILX on t3_main_prints (~5 lines of
  tagged s-expr vs ~23 lines of structured JSON for the JSON cohort's
  turn-1 attempt that needed correction).
- Per spec, single subject + single deterministic run = data point,
  not verdict.

DESIGN.md §"Decision 6: authoring surface" gains an "Empirical
addendum (2026-05-12)" subsection: 6-row metric table, illustrative
t3 contrast, explicit single-subject scope note pointing at the
roadmap follow-up entry for multi-subject expansion.

Roadmap: P2 entry "Cross-model authoring-form test" removed (this
journal is the convention's one-line mirror); P3 entry
"Multi-subject expansion (cross-model authoring-form follow-up)"
added with the run dir named as baseline.

Milestone artefacts span three iters (cma.1 master mini-spec +
renderer; cma.2 harness + tasks + reference solutions; cma.3 this
live run + DESIGN.md addendum + close).
2026-05-12 12:16:32 +02:00
Brummel fe1fb6b4f0 iter cma.2: harness binary + 4 tasks + reference solutions + 4 integration tests
Sibling standalone Cargo crate `harness/` under
experiments/2026-05-12-cross-model-authoring/ (out-of-workspace
idiom carried forward from cma.1 verbatim). Six modules:
strip_locations (regex pass for form-asymmetric location info,
calibrated against five real `ail check`/`ail parse` stderr
captures), pipeline (subprocess wrapper for parse|check|build +
5s-timeout exec; preflight on ail+clang), ionos (blocking reqwest
client + retry policy per spec), mock (canned-response loader),
scoring (CSV + summary.md), tasks (definition struct + loader).
main.rs ties them into the per-(cohort,task) loop with budget
accounting and per-turn artefact recording.

Four MVP tasks land with reference solutions that compile, build,
and execute green through the actual ail+clang pipeline:
t1_add_three (chained `+` + io/print_int), t2_length (polymorphic
List + recursion), t3_main_prints (minimal IO module), t4_count_zeros
(prelude Eq Int + branched if). Reference solutions stay in canonical
AILang form — param_modes is omitted when every parameter is the
Implicit default, consistent with the existing examples/ corpus.

13/13 tests green: 5 lib unit (strip_locations) + 5 integration
(strip_locations against verbatim captured fixtures) + 1
verify_references (drives every reference through the real
ail+clang pipeline) + 1 mock_full_run (full eight-row sweep with
mixed green-on-turn-2 + turn-limit cycles) + 1 budget_abort
(synthetic budget exhaustion with budget_abort rows + run_status).

Two implementer-phase repairs beyond the plan, both small and
surfaced in the iter journal Concerns:
1. pipeline.rs renames the program file to `<module-name>.ail.json`
   between parse and check because `ail check` enforces filename
   stem == module name (compiler contract the plan did not anticipate).
2. main.rs fills synthetic budget_abort rows for tasks the outer
   loop never reached so scores.csv preserves the expected eight-row
   shape on budget exhaustion.

One plan/text mismatch carried over: README "Total 8 passed" reflects
the plan's four-suite count; actual sweep produces 13. Doc-fix
candidate for cma.3.

cma.3 (live IONOS run + DESIGN.md addendum + roadmap edits) remains
out of scope.
2026-05-12 12:06:34 +02:00
Brummel 21c2d2cfaa plan: cma.2 — harness binary + 4 task definitions + 3 integration tests, 13 tasks, 46 steps
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.
2026-05-12 11:52:42 +02:00
Brummel a8c29d130b iter cma.1: master mini-spec + render binary for cross-model authoring experiment
New top-level experiments/2026-05-12-cross-model-authoring/ (out of
root Cargo workspace; nested-crate standalone via empty [workspace]
table per Cargo idiom). The renderer projects one canonical
master/spec.md into two form-specific files (rendered/json.md and
rendered/ailx.md) by walking three directive forms ({form-only:
json}, {form-only: ailx}, {example: <id>}) and emitting per-example
fenced blocks sourced from 13 curated .ail.json fixtures.

Four test gates green (10/10 total):
- splitter_unit (7) — directive parser, malformed inputs panic
- spec_completeness (1) — AST-variant visitor lifted verbatim from
  schema_coverage.rs; 34/34 variants covered by the curated subset
- example_roundtrip (1) — every fixture roundtrips through
  ailang_surface::{print, parse} to identical canonical bytes
- token_balance (1) — form-only block totals balanced to 3.22% under
  tiktoken-rs::cl100k_base (gate is ±5%)

Six of the 34 variants did not have a dedicated fixture topic in the
plan and were absorbed into the closest existing fixture per the
plan's Step 4.14 escape hatch (Let/Clone → fn_calls_prelude; LetRec
→ data_with_match; If → match_literal_pattern; ReuseAs →
data_simple; Const → floats). Surfaced as a journal note, not a
plan revision.

Two ancillary additions vs. plan, both structural Cargo necessities,
spec-compatible: render/Cargo.toml carries an empty [workspace] table
so the nested crate refuses parent-workspace discovery, and
render/.gitignore drops /target + Cargo.lock. Both surfaced inline
in the per-iter journal's Concerns section.

cma.2 (harness) and cma.3 (live IONOS run + DESIGN.md addendum +
journal + roadmap edits) remain out of scope per the spec.
2026-05-12 11:43:10 +02:00
Brummel fd6efdbcf6 plan: cma.1 — master mini-spec + render binary + tests, 9 tasks, 49 steps
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.
2026-05-12 11:31:19 +02:00
Brummel e1c2f2e3ca spec: cross-model authoring-form test — two-cohort experiment, master+renderer, 4 MVP tasks
Single foreign subject (Qwen3-Coder-Next via IONOS). Two blind
cohorts: one sees only a JSON mini-spec, the other only an .ailx
mini-spec; same four tasks. Fairness anchored by a master source
plus a renderer (built on the existing ailang-surface roundtrip
machinery) that projects two form versions from one canonical
content base. Harness shells out to ail parse / check / build / run
and feeds back location-stripped errors so the JSON-pointer
asymmetry doesn't tilt the experiment. Out of scope for v1: a
verdict on Decision 6, a free-choice cohort, repetitions, a second
subject.

Grounding-check PASS on cma.1 (master + renderer + tests).
2026-05-12 11:21:43 +02:00
Brummel ef1ebf2138 roadmap: heap-Str ABI as P1 milestone, blocker for Show + print rewire
Names the runtime infrastructure prerequisite (malloc-backed refcounted
Str alongside static @.str_* globals) as its own milestone. Show + print
rewire now carries an explicit depends-on link. Existing Eq/Ord [x]
entry removed (shipped milestone 23; mirrored in WhatsNew + journal).
2026-05-12 10:47:35 +02:00
Brummel e953b137eb iter boss: /boss skill — autonomous-mode discipline gated to user invocation
CLAUDE.md previously mixed universal facts (agent role boundaries,
commit discipline, design rationale, file roles, TDD-for-bugs) with
mode-specific autonomy rules (direction freedom, notifications,
WhatsNew procedure). Autonomous-by-default conflicted with the user's
intent that a fresh session should be collaborative-interactive unless
explicitly elevated.

Add `skills/boss/` containing only the three genuinely mode-specific
subsections — Direction freedom, Notifications, Done-state notifications:
WhatsNew.md. Trim CLAUDE.md from 343 to 243 lines; extend the skill-
system pointer paragraph with a one-sentence /boss gate. Universal
orchestrator discipline stays in CLAUDE.md because it applies whether
/boss is active or not.

Two cross-references that named the moved subsections by sub-heading
are repointed: skills/implement/SKILL.md and the implement-orchestrator
agent's standing reading list. The other ~11 agent-file references to
"orchestrator framing" still resolve correctly because that framing
stays in CLAUDE.md.

skills/README.md skill table extended with a `boss` row (now eight
skills); pipeline-diagram caption notes /boss wraps the pipeline.
.claude/skills/boss symlink follows the existing relative-path
convention.
2026-05-12 10:14:33 +02:00
Brummel a99a39b65e plan: boss — three-section move + symlink + README row + repoints + journal 2026-05-12 10:09:45 +02:00
Brummel 1c50c2d981 spec: tighten /boss move-list to the three mode-specific sections
Recon surfaced that several draft 'moved OUT' sections were universal,
not mode-specific (agent role boundaries, authority over skills, design
rationale, feature-acceptance criterion, when-not-to-delegate). These
apply in any session — interactive or /boss-active — because agents can
be dispatched, design choices can be made, and skills can be edited
outside /boss too.

Tighten the move-list to the three genuinely mode-specific subsections:
Direction freedom, Notifications, Done-state notifications: WhatsNew.md.
Everything else stays in CLAUDE.md. /boss becomes leaner, the universal/
mode-specific boundary is drawn at content that only applies inside the
autonomous loop. Re-dispatched grounding-check: PASS.
2026-05-12 10:07:09 +02:00
Brummel 3f20a589d6 spec: /boss skill — extract autonomous-mode discipline from CLAUDE.md 2026-05-12 10:01:12 +02:00
Brummel d1e514f2e7 WhatsNew: roundtrip-invariant milestone closed 2026-05-12 09:47:25 +02:00
Brummel 90512d5d89 brainstorm: re-dispatch grounding-check on any post-PASS spec edit
Closes the P1 todo from earlier today: Step 7.5 PASS report is
bound to the exact bytes of the spec at dispatch time. Any
subsequent edit — wording polish, user-requested change, anything
— invalidates the report and forces a fresh dispatch before the
Step 8 commit.

Three edits:
- Step 7.5 gets a 'Re-dispatch on any post-PASS edit' subsection
  stating the rule and explaining why (PASS attests to bytes).
- Step 8 wording: '... edit in place, re-run Step 7 AND re-dispatch
  Step 7.5, then return here. Only proceed after approval AND a
  fresh Step 7.5 PASS.'
- Common Rationalisations + Red Flags gain matching entries
  ('just polishing wording, no need to re-dispatch' / 'Editing the
  spec after PASS without re-dispatching').

Roadmap P1 todo retired with this commit.
2026-05-12 09:46:56 +02:00
Brummel 77a92a1a0d CLAUDE.md: notification policy — done-state = queue empty, not sub-goal complete
The previous one-liner 'notify when done and nothing left to do'
left 'done' under-defined. Concrete failure mode (2026-05-12, this
session): test suite for an open milestone landed, I notified on
the user-specified stop trigger, but the milestone still had two
follow-up iters (DESIGN.md anchor + audit) plainly in scope. The
user's intent behind the trigger was 'wake me when there's
nothing else to do', not 'wake me at this checkpoint'.

The expanded section codes two states (done-state, problem-state),
explicitly names sub-goal completion as NOT a notify event, and
calibrates user-specified stop triggers: hit only if the trigger
leaves the queue truly empty.
2026-05-12 09:45:24 +02:00
Brummel 44c6e56a0a audit-rt: milestone close — Direction-2 5th test + roadmap entry retired + wording sync
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.
2026-05-12 09:44:29 +02:00
Brummel e3b0dd20c5 iter rt.2: DESIGN.md anchor — Roundtrip Invariant lifted to top-level
New top-level section '## Roundtrip Invariant' between Decision 11
and '## Mangling scheme'. States both directions of the .ail.json
↔ .ailx bijection, names Float-bits-hex encoding as the in-
invariant mechanism (not an exception), lists the four enforcement
tests by path, and explains why the property is top-level
(load-bearing on language identity, not on Decision 6's surface-
design rationale).

Decision 6 Constraint 2 rewritten as upward cross-reference to the
new section; the substantive content now lives at the anchor.

Direct boss edit (no planner/implement dispatch): spec Architecture
#1 fully specified the content, no design judgement deferred to
execution. The iter is a deterministic projection of the spec
onto DESIGN.md prose.
2026-05-12 09:38:56 +02:00
Brummel b6046bb6eb WhatsNew: rt.1 — roundtrip safety net landed 2026-05-12 09:32:11 +02:00
Brummel 098fa7e9be iter rt.1: roundtrip-invariant audit tests — 3 new tests, all PASS first-shot
Three new reader-only tests pin the .ail.json / .ailx bijection
plus AST-variant coverage. All three passed first observation
across the current corpus — no roundtrip, schema-coverage, or
CLI-drift gaps surfaced.

- every_ailx_fixture_matches_its_json_counterpart (replaces the
  3-pair handwritten exhibits): 57 paired .ailx fixtures pass.
- every_ast_variant_is_observed_in_the_fixture_corpus (new): 34/34
  AST variants exercised across 136 fixtures; exhaustive matches
  without _ wildcard so AST drift fails the build.
- cli_render_then_parse_preserves_canonical_bytes_on_every_fixture
  (new): 136 fixtures round-trip through ail render → tempfile →
  ail parse with BLAKE3 identity on canonical bytes.

No production code, no DESIGN.md changes (those follow in later
iterations). Tests are pure readers of the repo per spec
acceptance #7 — tempfile crate added as workspace dep for the CLI
roundtrip's intermediate file outside the repo.
2026-05-12 09:31:38 +02:00
Brummel 10ccd1406c plan: rt.1 — three new tests (ailx pair cross-check dynamic + schema_coverage + CLI roundtrip via BLAKE3) 2026-05-12 09:24:50 +02:00
Brummel d71b5ca6c1 roadmap: brainstorm Step 7.5 — re-dispatch grounding-check on any post-PASS spec edit (P1 todo) 2026-05-12 09:24:24 +02:00
Brummel ea2c485459 spec: roundtrip invariant milestone — bidirectional .ail.json/.ailx bijection, schema-coverage, CLI roundtrip, hard-fail, dynamic fixture collection 2026-05-12 09:19:01 +02:00
Brummel daf9f4fdc9 roadmap: roundtrip-invariant milestone (P1) + cross-model authoring-form test (P2)
Surfaced while scoping an empirical test of Decision 6 (.ailx as the
AI authoring projection). The cross-model test depends on a structural
.ail.json <-> .ailx bijection being established and prominently anchored
in DESIGN.md first; otherwise measured form-preference is contaminated
by expressive-power gaps rather than authoring ergonomics. P2 entry
carries the smoke-test evidence and full IONOS-endpoint addressing
notes so the test can be picked up without redoing the connection work.
2026-05-12 08:53:47 +02:00
Brummel edccc087a4 WhatsNew: audit-23 — milestone closed, regression ratified 2026-05-12 00:57:36 +02:00
Brummel 94616240ec audit 23: ratify compile_check baseline + DESIGN.md stub-fix
Milestone-23 close audit. Architect clean on substance; one
pre-existing DESIGN.md grammar stub (line 1692, dangling 'The
original' from 2026-05-10 design-md-consolidation) caught and
fixed.

Bencher localised the compile_check.py regression to H2 (the 5 new
polymorphic prelude Def::Fns iter 23.5 added — each carries forall
+ class constraint + match/not body, all typechecked on every
workspace check). H1 (linearity workspace-visibility extension +
contains_rigid_var) is negligible at today's 2-module workspace.

The regression is the feature's measured cost. Ratified per audit
skill (--update-baseline + journal entry). 0/24 metrics regressed
post-update.

Milestone 23 (Eq/Ord prelude) is closed.
2026-05-12 00:57:12 +02:00
Brummel 3fed372d77 WhatsNew: iter 23.5 — Eq/Ord prelude milestone closed 2026-05-12 00:39:59 +02:00
Brummel 326c995c1d iter 23.5: INDEX append 2026-05-12 00:39:11 +02:00
Brummel 92e830e6c2 iter 23.5: prelude free fns + E2E — Eq/Ord milestone close
Five polymorphic prelude free fns (ne/lt/le/gt/ge) plus three E2E
fixtures: positive composition over Int/Bool/Str, user-ADT with
user-written Eq/Ord on IntBox, and Float-NoInstance with a
Float-aware diagnostic addendum cross-referencing DESIGN.md §"Float
semantics".

Two checker-side fixes were needed alongside the prelude additions,
both symmetric to the iter 23.4-prep visibility fix:
- linearity::check_module_with_visible — workspace-aware callee-mode
  resolution so a Borrow-mode user fn forwarding into a prelude poly
  fn (e.g. `at_most x y = not (gt x y)`) doesn't false-fire
  consume-while-borrowed.
- mono::collect_mono_targets — distinguish rigid forall vars from
  unbound metavars; rigid-bearing free-fn targets skip (they get
  re-collected with concrete subst when the enclosing fn itself
  monomorphises). Without this, a polymorphic body calling another
  polymorphic free fn produced a spurious __Unit specialisation
  whose body referenced compare at Unit.

Roadmap split: shipped Eq/Ord half checked, Show + print-rewire half
remains pending behind the heap-Str ABI prerequisite. DESIGN.md
§"Prelude classes" amended.

One pre-existing fixture (test_22b1_missing_method) renamed its
class method ne → tne to avoid collision with the new prelude `ne`.

Bench: check.py + cross_lang.py exit 0; compile_check.py exits 1
with one sub-ms check_ms.local_rec_capture at +26% (tolerance 25%) —
prelude-growth-related noise-band fluctuation, ratifiable per spec
§248-249 and journal Concerns.
2026-05-12 00:38:52 +02:00
Brummel 35c6eb5736 plan: iter 23.5 prelude free fns + E2E — 8 tasks 2026-05-12 00:16:23 +02:00