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
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.
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.
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).
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.
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).
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.
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.
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.
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.
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).
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).
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.
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.
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.
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.
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.
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.
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.
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.
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.
Restructure ailang-check/src/mono.rs::monomorphise_workspace into a
single specialiser over every Type::Forall-quantified Def::Fn, covering
both class-method residuals AND polymorphic free-fn call sites in one
fixpoint pass. Remove the codegen-time specialiser (lower_polymorphic_call,
module_polymorphic_fns, mono_queue, mono_emitted, emit_specialised_fn,
plus the now-dead helpers apply_subst_to_term, descriptor_for_subst,
type_descriptor) entirely. Codegen sees only monomorphic Def::Fns after
this iter — no polymorphic call sites, no codegen-time queue.
Architecture changes:
- MonoTarget: struct → enum with ClassMethod / FreeFn variants; dedup
keys are guaranteed-disjoint via 'class'/'free' first component.
- collect_mono_targets: new FreeFnCall channel through synth (cleaner
than the plan's separate-walker proposal — one less data flow,
substitution tracking comes 'for free' via fresh metavars +
post-synth subst.apply). Plan Step 4.4 (polymorphic_free_fns env
field) consequently obsolete.
- synthesise_mono_fn_for_free_fn: new free-fn entry point; substitutes
rigid vars in BOTH the type AND the body (body substitution required
because free-fn bodies carry inner Lams whose param_tys reference
outer Forall vars — adapted from plan's 'body unchanged' sketch).
- mono_symbol_n: N-ary extension of mono_symbol; bit-stable for the
single-type-var case (hash-stability pin Task 1 fires zero times
through all eight refactor tasks).
- rewrite_class_method_calls → rewrite_mono_calls; interleaved-slot
collector preserves the positional-cursor invariant across both
channels.
- workspace_has_typeclasses → workspace_has_specialisable_targets
(principled correctness; old predicate happened to already be true
for every user workspace because the prelude is auto-injected).
Codegen cleanup:
- Two call sites of lower_polymorphic_call deleted (codegen/src/lib.rs
lines ~1939-1945, ~1965-1973).
- lower_polymorphic_call body, module_polymorphic_fns field +
population + Emitter wiring, mono_queue / mono_emitted, drain loop,
emit_specialised_fn — all removed.
- is_static_callee collapsed to module_user_fns-only.
- subst.rs apply_subst_to_term + descriptor_for_subst removed; synth.rs
type_descriptor removed (all dead post-removal).
- ail emit-ir command pipeline gains lift_letrecs + monomorphise_workspace
pre-passes (pre-iter-23.4 the codegen-time poly path was masking
this dependency — emit-ir is now consistent with build).
- Net codegen reduction: -285 lines lib.rs, -93 lines subst.rs.
Tests:
- mono_hash_stability.rs (new): regression pin for six primitive Eq/Ord
mono-symbol body hashes; stayed bit-stable through all eight refactor
tasks.
- mono_unification.rs (new): six tests covering variant-key disjointness,
free-fn target emission, free-fn synthesis with rigid substitution,
rewrite walker on free fns, identity for poly-free-fn-only workspaces,
end-to-end cmp_max_smoke runtime correctness.
- typeclass_22b3.rs: three test sites updated to MonoTarget::ClassMethod
enum form.
- 73 e2e + 18 typeclass + 81 codegen tests all green workspace-wide.
DESIGN.md §'Monomorphisation (post-typecheck, pre-codegen)' amended:
two-arm fixpoint described, disjoint-keyed dedup, cursor-aligned
walker, removed codegen-time path.
Bench check (all exit 0, 112 metrics stable): bench/check.py +
compile_check.py + cross_lang.py.
Plan parent: docs/plans/2026-05-11-iter-23.4.md (fab1685).
Spec parent: docs/specs/2026-05-11-23-eq-ord-prelude.md (841d65d).
Per-iter journal documents two adapted deviations from the plan
(synth-channel vs separate walker; body substitution; emit-ir fix);
no spec defects.
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.
Two project-wide rules are now explicit across every skill:
1. Only the Boss commits. No skill agent (implementer,
brainstormer, planner, debugger, fieldtester, docwriter,
architect, bencher) runs `git commit`. Agents write their
artefacts to the working tree as unstaged changes; the Boss
inspects, decides commit shape, and commits.
2. main HEAD is sacrosanct. No actor runs `git reset` or
`git revert` on main. Bad work stays in the working tree
where it is still discardable via `git checkout -- <paths>`.
Implement loses the `iter/<iter_id>` branch mechanic entirely;
Phase 0 of the orchestrator-agent now does a clean-tree check
and refuses to start on a dirty tree. Per-task agent commits
are removed everywhere; reviewers operate against
`git diff HEAD` instead of `pre_task_sha..head_sha`.
Motivation: 2026-05-11 iter 23.4 stranded prep2/prep3 commits on
an iter-branch that never integrated to main, then a corrected
spec falsely claimed those commits had shipped. Branch-per-iter
+ manual-Boss-merge + iter-stacking made the strand structurally
possible. See docs/journals/2026-05-11-iter-disc.1.md for the
full per-task notes and motivation.
Brainstorm assumed all four 23.4-prep commits had shipped to main.
Branch verification (post-iter/23.4 deletion) showed only prep1
(linearity + check bare-name) is on main; prep2 + prep3 were
attempted on the stranded iter/23.4 branch and never landed.
Spec corrections:
- Goal section: prep-commit status block reflects actual main state.
- Architecture: drop §2 (prep2/prep3 rollback) — no rollback exists
on main; section count drops from four to three artefacts.
- Components table: prep2/prep3 row now reads 'abandoned 2026-05-11
with iter/23.4 deletion', not 'shipped, rolled back in 23.4'.
- Acceptance criterion 1: drop the 'prep2 + prep3 are rolled back'
clause.
- Load-bearing assumption 5: now states prep2/prep3 never reached
main (fixes the silent-assumption pattern this spec exists to
prevent — same failure mode the original Spec-23 had).
- Load-bearing assumption 6: cite the cherry-picked main SHAs
(0caaced, 923dd8c) alongside the stranded-branch originals
(8d39f13, aef4ab8).
- Known costs: drop the '23.4 rollback' line item.
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.
Plan-recon for iter 23.4 surfaced that poly_box_proj.ail.json does
not exist in examples/. The three load-bearing regression fixtures
are poly_id, poly_apply, and poly_rec_capture (the latter at
examples/poly_rec_capture.ail.json, driven by e2e.rs::poly_rec_capture_demo).
Three references in the spec corrected. Substantive intent (three
existing polymorphic fixtures regress unchanged under unified mono)
unchanged.
Note 3: agent output format leaked internal-thinking preamble before
the structured report block — Iron Law should forbid preamble.
Note 4: Boss-requested behaviour change for impending-BLOCK paths —
on miss, agent attempts to write missing GREEN test (test code only,
never src/) before falling to BLOCK; requires tool + Iron Law update.
Both notes are for the future skillsystem-postmortem entry; out of
gc.1 scope.