The tidy's gate-first Task 1 RED-verification + Boss independent
verification surfaced two defects in the audit Resolution as first
written — caught exactly where the planner->Boss loop is designed to,
before any contract byte moved. Per the 'two+ defects in one
iteration => fix the upstream artifact, do not patch a third time'
discipline, the audit Resolution is corrected in lockstep with the
plan re-derivation:
- Mechanism (Resolution-4): the 'case-insensitive iter-code regex'
clause-3 design is REJECTED as unworkable — a blanket
iter/milestone detector conflates the memory-model rule-names
'Iter A'/'Iter B' and ordinary words 'pre-existing'/'pre-set'/
'pre-Boehm' with provenance, over-firing on legit present-tense
contract prose (4 no-strip files). Replaced by a FAITHFUL Sweep-1
superset: case-sensitive digit-anchored Sweep-1 line anchors
(confirmed ZERO across all contracts) + Sweep-1's ^[^/]*
path-excluded date (so docs/specs/2026-.. citations are not
flagged — repairs the iso_date over-fire the implement
orchestrator correctly BLOCKED on) + the audit-named
decision-record phrases (case-insensitive). No regex dep. The
load-bearing invariant (clause-3 GREEN => Sweep-1 clean) is
preserved; it never required the blanket detector.
- Scope (Resolution-1): the architect's [medium] was a 3-file
spot-check; the exhaustive scan found roundtrip-invariant.md:73
('at iter form-a.1') and data-model.md:149,161 ('loop-recur iter
1:') also carry lowercase provenance. True strip set = 5 files;
plan Task 5b adds the 2 (spirit-cleanup, not gate-blocking).
Plan self-review 8/8 re-run; clause-3 = hand-rolled faithful Sweep-1
superset, no regex dep, no blanket iter detector.
30 KiB
design-md-rolesplit.tidy — Implementation Plan (audit drift fix)
Parent spec:
docs/specs/2026-05-19-design-md-rolesplit.mdScope authority:docs/journals/2026-05-19-audit-design-md-rolesplit.md"Resolution" (committed2ba5e16) — the architect[medium]+[low]drift fix, 5 orchestrator-decided points.For agentic workers: REQUIRED SUB-SKILL: use
skills/implementto run this plan. Steps use- [ ]checkboxes for tracking.
Goal: Close the spirit-vs-letter gap: extract the
faithfully-migrated history/decision-record prose out of the 3
affected contract files into the decision-record journal, fix the
one stale cross-ref, re-scope the honesty sweeps to
design/contracts/ only, and widen design_index_pin.rs clause-3
so the in-code hard gate provably subsumes architect_sweeps.sh
Sweep-1 over the contracts scope.
Architecture: TDD by gate-first ordering — Task 1 widens
clause-3 and verifies it goes RED against the current (un-stripped)
contract files (proving the widened gate catches what the 6 literal
markers missed); Tasks 2–5 strip the history prose (sentence-level
per recon's contract-residue map) → clause-3 returns GREEN; Task 6
re-scopes the sweep + its lockstep doc; Task 7 is the whole-tree
gate. Build stays green throughout (only one test file's body +
Markdown change; the test compiles, fails at runtime until the strip
lands). The widened clause-3 is a hand-rolled provable superset of
Sweep-1 (no regex dep).
Tech Stack: Markdown (design/contracts/*.md,
docs/journals/2026-05-19-design-decision-records.md), one Rust
test (crates/ailang-core/tests/design_index_pin.rs),
bench/architect_sweeps.sh, skills/audit/agents/ailang-architect.md.
Pinned-byte hazard (recon Cross-references — honor in every strip
task): each history strip runs adjacent to a docs_honesty_pin.rs
verbatim substring pin. norm() collapses whitespace but the pinned
run must stay a contiguous token-run:
str-abi.md:19type-installed; codegen is reserved and not yet shipped←docs_honesty_pin.rs:121-122typeclasses.md:317`io/print_str` is the only built-in direct-output effect-op←docs_honesty_pin.rs:125-126scope-boundaries.md:9`Diverge` is a reserved effect name with no op and no codegen←docs_honesty_pin.rs:112-113(over-strip guard — NOT in any edit span; do not touch)
Task 1: widen design_index_pin.rs clause-3 (gate-first, RED)
Files:
-
Modify:
crates/ailang-core/tests/design_index_pin.rs:130-157(fn contracts_carry_no_decision_record_prose) -
Step 1: Replace the clause-3 body with the widened, provable-superset matcher
Replace fn contracts_carry_no_decision_record_prose (current
:130-157, the 6-literal-marker markers array + body.contains(m)
loop) with this. The other 3 clauses + helpers (root :10-12,
read :14-17, norm :19-21, index_tables :23-62,
link_target_exists :67-81, design_md_is_gone :83-90,
every_index_link_resolves :92-107,
every_contract_names_a_resolvable_ratifying_test :109-128) are
untouched.
#[test]
fn contracts_carry_no_decision_record_prose() {
// clause 3 — the conflation tripwire, widened (design-md-rolesplit.tidy,
// audit Resolution-4) to a FAITHFUL SUPERSET of
// bench/architect_sweeps.sh Sweep-1's history-anchor regex over the
// design/contracts/ scope, PLUS the audit-named decision-record
// phrases (the deliberate widening that closes the case-variance
// dodge the 6 literal markers left open).
//
// Invariant: clause-3 GREEN ⟹ Sweep-1 finds nothing in design/contracts/.
//
// Sweep-1 = 'Iter [0-9]+[a-z]?(\.[0-9]+)?|Family [0-9]+
// |^[^/]*2026-[0-9]{2}-[0-9]{2}|\*\*Status: |pre-[0-9]+[a-z]?
// |[0-9]+[a-z]? sketch|21\.g'
// Faithfulness, per Sweep-1 alternative:
// - Iter / Family / pre- / <n> sketch / 21.g / **Status:
// → sweep1_line_anchor() reproduces each verbatim,
// case-SENSITIVE (grep -E, no -i) — exactly Sweep-1 here,
// never narrower.
// - ^[^/]*2026-NN-NN → date_anchor() reproduces Sweep-1's
// ^[^/]* PATH-EXCLUSION (only the line prefix before the
// first '/' is scanned) and generalises 2026→20NN
// (⊇ Sweep-1, never narrower). A `docs/specs/2026-..`
// citation has '/' before the date ⇒ NOT flagged — faithful
// to Sweep-1, no over-fire on legit present-tense spec
// cross-refs (the iter-.1 plan defect this repairs).
// - PHRASES: literal decision-record idioms (case-insensitive) —
// the deliberate widening that closes the capital-variance
// dodge ("An earlier draft" vs "an earlier draft").
//
// A blanket case-insensitive iter/milestone detector was evaluated
// and REJECTED (audit Resolution-4 corrected): it conflates the
// memory-model rule-names "Iter A"/"Iter B", and ordinary words
// "pre-existing"/"pre-set"/"pre-Boehm"/"pre-tail-call", with
// provenance stamps — unworkable. faithful-Sweep-1 (the capital-I,
// digit-anchored form) already excludes those by construction and
// is confirmed ZERO across every contract file; lowercase
// `(iter <code>)` provenance is removed by the strip tasks, not by
// a fragile hard-gate regex. The load-bearing invariant
// (clause-3 GREEN ⟹ Sweep-1 clean in contracts/) holds with
// sweep1_line_anchor + date_anchor + PHRASES alone.
let dir = root().join("design/contracts");
const PHRASES: &[&str] = &[
"we rejected", "an earlier draft", "earlier draft committed",
"why not other", "was retired", "were retired", "rollback plan",
"previously all", "deliberately deferred", "new-baseline decision",
"amends the above", "out of scope per",
"the journal records when", "unchanged from the original draft",
];
// Sweep-1's non-date alternatives, hand-rolled verbatim, case-SENSITIVE
// (grep -E without -i), on the raw physical line.
fn sweep1_line_anchor(line: &str) -> Option<&'static str> {
let kw_digit = |kw: &str| -> bool {
let mut from = 0;
while let Some(i) = line[from..].find(kw) {
let p = from + i + kw.len();
if line[p..].chars().next().map_or(false, |c| c.is_ascii_digit()) {
return true;
}
from = p;
}
false
};
if kw_digit("Iter ") { return Some("Iter <n>"); }
if kw_digit("Family ") { return Some("Family <n>"); }
if kw_digit("pre-") { return Some("pre-<n>"); }
if line.contains("**Status: ") { return Some("**Status:"); }
if line.contains("21.g") { return Some("21.g"); }
if let Some(s) = line.find(" sketch") {
let pre = line[..s].as_bytes();
if pre.last().map_or(false, u8::is_ascii_alphanumeric)
&& pre.iter().rev()
.take_while(|c| c.is_ascii_alphanumeric())
.any(u8::is_ascii_digit)
{
return Some("<n> sketch");
}
}
None
}
// Sweep-1's `^[^/]*2026-NN-NN`, generalised to 20NN-NN-NN,
// PATH-EXCLUDED: scan only the line prefix BEFORE the first '/'.
fn date_anchor(line: &str) -> Option<String> {
let prefix = line.split('/').next().unwrap_or(line).as_bytes();
for w in prefix.windows(10) {
if w[0] == b'2' && w[1] == b'0'
&& w[2].is_ascii_digit() && w[3].is_ascii_digit()
&& w[4] == b'-' && w[5].is_ascii_digit() && w[6].is_ascii_digit()
&& w[7] == b'-' && w[8].is_ascii_digit() && w[9].is_ascii_digit()
{
return Some(String::from_utf8_lossy(w).into_owned());
}
}
None
}
for entry in fs::read_dir(&dir).expect("design/contracts/ exists") {
let p = entry.unwrap().path();
if p.extension().and_then(|e| e.to_str()) != Some("md") {
continue;
}
let raw = fs::read_to_string(&p).unwrap();
let fname = p.file_name().unwrap().to_string_lossy().into_owned();
let low = norm(&raw).to_lowercase();
for ph in PHRASES {
assert!(
!low.contains(ph),
"clause-3: history phrase {ph:?} in contract {fname:?}"
);
}
for line in raw.lines() {
if let Some(a) = sweep1_line_anchor(line) {
panic!("clause-3: Sweep-1 anchor {a:?} in contract {fname:?}: {line:?}");
}
if let Some(d) = date_anchor(line) {
panic!("clause-3: history date {d:?} in contract {fname:?}: {line:?}");
}
}
}
}
- Step 2: Verify clause-3 is now RED against the un-stripped tree
Run: cargo test -p ailang-core --test design_index_pin contracts_carry_no_decision_record_prose 2>&1 | tail -8
Expected: FAIL — fires on still-present history prose: a PHRASES
hit (e.g. clause-3: history phrase "deliberately deferred" in contract "str-abi.md") and/or the path-excluded date
(clause-3: history date "2026-05-13" in contract "str-abi.md").
This is the required RED: the widened gate catches what the 6
literal case-sensitive markers missed (the capital-variance dodge).
- Step 3: Verify the other 3 clauses + build still GREEN
Run: cargo test -p ailang-core --test design_index_pin 2>&1 | grep -E '^test (design_md_is_gone|every_index_link_resolves|every_contract_names) '
Expected: those 3 still ok (only clause-3 RED). cargo build -p ailang-core --tests 2>&1 | tail -1 → Finished (the new matcher compiles; no new dependency).
Task 2: strip history prose from design/contracts/typeclasses.md
Files:
-
Modify:
design/contracts/typeclasses.md(:77-78, :182-186, :197-200, :279-289, :291-300, :302-317 — recon's complete scan) -
Modify:
docs/journals/2026-05-19-design-decision-records.md(append at EOF, after :431) -
Step 1: Append the migrated typeclasses history to the decision-record journal
Append at EOF of docs/journals/2026-05-19-design-decision-records.md:
## Migrated from design/contracts/ at design-md-rolesplit.tidy (2026-05-19)
History/decision-record prose extracted from contract files by the
post-audit tidy (the `###`-whole relocation in iter .1 dragged these
into contracts; they are relitigation-guard content, not contract).
### typeclasses.md — Prelude-classes evolution
An earlier draft committed to a fixed Prelude (Show/Eq/Ord on the
primitives), but the implementation work to wire `int_to_str` as a
heap-allocated-string runtime primitive proved substantively
separable from the typeclass machinery itself, and the LLM-utility
case for primitive `Show` is weak (LLM-natural form is `int_to_str
x`, not `show x`). Milestone 23 added `Ordering`/`Eq`/`Ord` +
primitive instances + the five helpers; operator routing through
`Eq`/`Ord` and `print`-rewire were held out for bench-rebaseline /
post-mq-dispatcher reasons; `Show` shipped in milestone 24 (iters
24.2/24.3). `MethodNameCollision` was retired at iter mq.3
(cross-class method sharing became structurally legal). The
dedicated `KindMismatch` diagnostic was retired at iter ctt.3
(`BareCrossModuleTypeRef` subsumes it).
- Step 2: Rewrite the 6 typeclasses.md spans present-tense (recon's contract-residue map)
Apply each, keeping every present-tense contract fact, dropping the history clause:
-
:77-78Three invariants make this work, all installed in milestone 24's iter 24.3 and worth keeping load-bearing:→Three invariants make this work: -
:182-186drop the parenthetical(MethodNameCollisionwas retired at iter mq.3. …)opening; keep the present-tense replacement sentence:Cross-class method sharing is structurally legal; ambiguity surfaces at the call site viaAmbiguousMethodResolutionor, for class-fn name overlap, via theclass-method-shadowed-by-fnwarning. See §"Method dispatch" below. -
:197-200keep… is rejected earlier by the canonical-form validator asBareCrossModuleTypeRef—fis a bare, non-primitive name not declared as aTypeDefin the owning module.; dropso the dedicatedKindMismatchdiagnostic was retired at iter ctt.3. -
:279-289(the "Milestone 22 ships no built-in Prelude classes / An earlier draft committed to…" paragraph) — delete wholesale (pure decision-record; the present-tense state is the m24 prelude below). -
:291-300replace theMilestone 23 amends the above:paragraph with present-tense:The prelude ships theOrderingADT, theEqandOrdclasses, primitiveEq Int/Bool/StrandOrd Int/Bool/Strinstances, and the five polymorphic free-fn helpersne/lt/le/gt/ge. Float has neitherEqnorOrdinstance per §"Float semantics"; a polymorphic helper invoked at Float firesNoInstanceat typecheck with a Float-aware diagnostic cross-referencing this section.(drop "remain out of scope per their original substantive reasons (bench rebaseline, milestone-24 dependency…); Show itself ships in milestone 24" — that relitigation is now in the journal.) -
:302-317replace theMilestone 24 amends the above further:opening with present-tense:The prelude shipsclass Show a where show : (a borrow) -> Strand primitiveShow Int,Show Bool,Show Str,Show Floatinstances. Float **is** included in Show (unlike Eq/Ord) …— keep verbatim and byte-contiguous the tail through:317`io/print_str` is the only built-in direct-output effect-op(pinned bydocs_honesty_pin.rs:125-126) and the:315print_mono_body_shape.rscross-reference; drop onlyMilestone 24 amends the above further,(iter 24.2),shipped in iter 24.3(→ replaceshipped in iter 24.3 with bodywithwith body). -
Step 3: Verify typeclasses.md pin + clause-3 progress
Run: cargo test -p ailang-core --test docs_honesty_pin 2>&1 | grep -E 'test result:'
Expected: PASS (the io/print_str… pinned run intact). Run
grep -n 'io/print_str is the only built-in direct-output effect-op' design/contracts/typeclasses.md`
Expected: exactly one contiguous match (pin survived).
Task 3: strip history prose from design/contracts/str-abi.md
Files:
-
Modify:
design/contracts/str-abi.md(:14, :16, :18, :20, :22-23, :74, :38-43, :45-47) -
Modify:
docs/journals/2026-05-19-design-decision-records.md(append under the tidy section) -
Step 1: Append str-abi history to the journal
Append under the ## Migrated … section:
### str-abi.md — heap-Str builtin provenance + deferred-operator rationale
Builtin iter provenance: `int_to_str`/`bool_to_str`/`float_to_str`/
`str_clone` shipped iter 24.1; `str_concat` shipped iter str-concat
(2026-05-13); the non-escape static-Str lowering pass landed iter
18b, move-tracking partial-drop iter 18d.3. Operator routing through
classes is deliberately deferred — it would migrate every fixture
and re-baseline the bench corpus (a new-baseline decision, not an
iter detail). `Num` is not in milestone 22: class-based numeric
overloading would invoke literal-defaulting which axis-7 excluded.
-
Step 2: Strip the
(iter …)parentheticals + deferred rationale -
:14-int_to_str : (borrow Int) -> Str(iter 24.1) — decimal rendering→-int_to_str : (borrow Int) -> Str— decimal rendering -
:16-bool_to_str : (borrow Bool) -> Str(iter 24.1) —"true"/"false".→ drop(iter 24.1) -
:18-float_to_str : (borrow Float) -> Str(iter 24.1) —→ drop(iter 24.1). Hazard::19type-installed; codegen is reserved and not yet shipped.is pinned (docs_honesty_pin.rs:121-122) — keep:19byte-identical and contiguous with:18's—. -
:20-str_clone : (borrow Str) -> Str(iter 24.1) — allocates a fresh→ drop(iter 24.1) -
:22-23-str_concat : (borrow Str, borrow Str) -> Str(iter str-concat,\n 2026-05-13) — combines …→-str_concat : (borrow Str, borrow Str) -> Str— combines twoStrvalues into a single ownedStr.(collapse the soft-wrap; drop the whole(iter str-concat, 2026-05-13)— this is the Sweep-1 exit-1 trip) -
:74drop(iter 18b)and(iter 18d.3); keep the present-tense mechanism sentence. -
:38-43keep`==`, `<`, `<=`, `>`, `>=` REMAIN primitive operators. Class methods are accessed by name (`eq x y`, `lt x y`, …), not via these operators.; drop(unchanged from the original draft)and the wholeRouting operators through classes is deliberately deferred — … new-baseline decision rather than an iter detail. -
:45-47keepArithmetic operators (+,-,*,/) stay primitive and per-type.; drop`Num` is NOT in milestone 22.andClass-based numeric overloading would invoke literal-defaulting which axis-7 already excluded. -
Step 3: Verify str-abi pin intact
Run: grep -n 'type-installed; codegen is reserved and not yet shipped' design/contracts/str-abi.md
Expected: exactly one contiguous match. Run
cargo test -p ailang-core --test docs_honesty_pin 2>&1 | grep 'test result:' → PASS.
Task 4: strip history prose from design/contracts/scope-boundaries.md
Files:
-
Modify:
design/contracts/scope-boundaries.md(:5-6, :14-17, :36-38) -
Modify:
docs/journals/2026-05-19-design-decision-records.md(append under the tidy section) -
Step 1: Append scope-boundaries history to the journal
### scope-boundaries.md — retired ops + deferral rationale
Polymorphic-fn-as-value is deferred because it would need one
closure-pair global per instantiation. The per-type print ops
`io/print_int`/`io/print_bool`/`io/print_float` were retired in iter
rpe.1 (the polymorphic `print` is the canonical non-Str output path).
-
Step 2: Rewrite the 3 scope-boundaries spans
-
:5-6keepSnapshot of the current boundary.; deleteItems move out of this list as iterations land; the JOURNAL records when.(process-meta, not a scope contract; not decision-record either — plain delete, not journal-moved). -
:14-17keepPolymorphic fns must be **directly called** at the use site. Passing a polymorphic fn as a value (let f = id in f(42)) is not yet supported.; drop— it would need one closure-pair global per instantiation, deferred.(rationale → journal, Step 1). -
:36-38keepEffects on function signatures, withdo op(args)for direct effect ops (io/print_str). The polymorphicprint(§"Polymorphic print") is the canonical output path for non-Str values.; dropThe per-type print opsio/print_int,io/print_bool,io/print_floatwere retired in iter rpe.1;(→ journal). -
Step 3: Over-strip guard — the Diverge pin must be untouched
Run: grep -n 'Diverge is a reserved effect name with no op and no codegen' design/contracts/scope-boundaries.md Expected: exactly one match at the original location (:9, unedited — it is NOT in any edit span; this guards against collateral deletion). cargo test -p ailang-core --test effect_doc_honesty_pin 2>&1 | grep 'test result:'` → PASS.
Task 5: fix the stale cross-ref in design/contracts/float-semantics.md
Files:
-
Modify:
design/contracts/float-semantics.md:100 -
Step 1: Repoint the stale "below" direction
:99-100 verbatim Both allocate a fresh heap-Str slab at the call site (see "Str ABI" below for the dual realisation) and carry ret_mode: Own…. Replace (see "Str ABI" below for the dual realisation) → (see design/contracts/str-abi.md for the dual realisation). (design/contracts/str-abi.md exists — confirmed
recon; INDEX row design/INDEX.md:93.)
- Step 2: Verify float-semantics pin intact + no stale "below"
Run: grep -n '"Str ABI" below' design/contracts/float-semantics.md || echo "CLEAN: stale below gone"
Expected: CLEAN: stale below gone. Run
cargo test -p ail --test eq_float_noinstance 2>&1 | grep 'test result:' → PASS.
Task 5b: residual lowercase provenance stamps (exhaustive-scan additions)
The audit's
[medium]finding was a 3-file spot-check. The planning-time exhaustive scan found two more contract files carrying lowercaseiter <code>provenance the audit missed (audit Resolution corrected in the same iter). These are spirit cleanup — faithful-Sweep-1/clause-3 do NOT trip on them (lowercase, no digit-anchored capitalIter), so they are not gate-blocking, but a contract carrying "iter form-a.1" is exactly the residue this milestone exists to remove. Strip + journal-note for completeness.
Files:
-
Modify:
design/contracts/roundtrip-invariant.md:73 -
Modify:
design/contracts/data-model.md:149,161 -
Modify:
docs/journals/2026-05-19-design-decision-records.md(append under the tidy section) -
Step 1: Append the provenance to the journal
### roundtrip-invariant.md / data-model.md — corpus + loop-recur provenance
The Form-A round-trip corpus was flipped from `.ail.json` to `.ail`
at iter form-a.1. The `loop`/`recur` schema entries were added at
loop-recur iter 1 (strictly additive; pre-existing fixtures hash
bit-identically). Provenance only — the present-tense schema/contract
is the entry shapes themselves.
-
Step 2: Strip the stamps, keep the present-tense contract
-
roundtrip-invariant.md:73… in at least one.ailfixture (corpus flipped from.ail.jsonto.ailat iter form-a.1). New AST→ drop the parenthetical:… in at least one.ailfixture. New AST(the invariant is "every variant appears in ≥1.ailfixture"; the flip provenance is journal-class). -
data-model.md:149// loop-recur iter 1: strict iteration block.bindersdeclares→// loop: strict iteration block.bindersdeclares(drop-recur iter 1:→ the schema-comment names the construct, not the iter). -
data-model.md:161// loop-recur iter 1: re-enter the lexically innermost enclosing→// recur: re-enter the lexically innermost enclosing(this entry is therecurschema — name itrecur, drop the iter stamp). -
Leave
data-model.md:154pre-existing fixtures hash bit-identicallyuntouched — "pre-existing" is an ordinary present-tense word, NOT provenance (faithful-Sweep-1'spre-[0-9]does not match it; confirmed). -
Step 3: Verify no lowercase
iter <code>provenance remains in contracts
Run: grep -rnoE 'iter [a-z0-9][-a-z0-9.]*[0-9]' design/contracts/ | grep -ivE 'iteration|iterat' || echo "CLEAN: no iter-code provenance"
Expected: CLEAN: no iter-code provenance (the (iter 24.1) /
iter str-concat / iter form-a.1 / loop-recur iter 1 stamps all
removed by Tasks 3 + 5b; iteration-word usages excluded). Run
cargo test -p ailang-core --test design_schema_drift 2>&1 | grep 'test result:'
then cargo test -p ailang-surface --test round_trip 2>&1 | grep 'test result:'
Expected: both PASS — design_schema_drift anchors on the JSON
"t": "loop" / "t": "recur" schema tokens (untouched; only the
prose comment changed), and the round-trip corpus is
content-unchanged.
Task 6: re-scope architect_sweeps.sh honesty sweeps + lockstep doc
Files:
-
Modify:
bench/architect_sweeps.sh:25(+ header:5-7) -
Modify:
skills/audit/agents/ailang-architect.md:77-84 -
Step 1: Narrow
DESIGN_GLOBtodesign/contracts
bench/architect_sweeps.sh:25 verbatim
DESIGN_GLOB="design/contracts design/models" →
DESIGN_GLOB="design/contracts". (Substantive reason, encoded as a
comment on the same line: # contracts only — design/models is the narrative tier; "as of milestone N" context is legitimate there.)
Header :5-7 prose design/ prose set (design/contracts + design/models) → design/contracts (the honesty-bound contract surface; design/models is the narrative tier, out of honesty-sweep scope). The 5 run_sweep regexes (:46-59) are unchanged; the
exit-code block (:61-64) is unchanged.
- Step 2: Lockstep
ailang-architect.md
In skills/audit/agents/ailang-architect.md the :77-84
history-anchor-regrowth bullet: append one sentence after the
exit-semantics lines: Sweeps 1–4 scan design/contracts/only —design/models/ is the narrative tier (§ reading-list: "context, not a drift surface"), so a milestone-context phrase there is not a regrowth. (:34 already states models/ is not a drift surface;
this makes the sweep scope explicit and consistent.) No other
edit; Sweep count stays 5 so docs_honesty_pin.rs:10 //! needs no
change.
- Step 3: Verify the sweep now scans contracts only
Run: bash bench/architect_sweeps.sh; echo "exit=$?"
Expected: at this point Tasks 2–5b have stripped the contract
history, so exit=0 and All five sweeps clean. (If exit 1
with a design/contracts/... match, a history span was missed —
fix it; if the match is design/models/... the glob narrowing
didn't apply — re-check :25.)
Task 7: whole-tree GREEN gate (milestone-close proof)
Files: none (verification only).
- Step 1: clause-3 now GREEN, design_index_pin 4/4
Run: cargo test -p ailang-core --test design_index_pin 2>&1 | grep -E '^test |test result:'
Expected: all 4 ok — contracts_carry_no_decision_record_prose
flipped RED→GREEN (history stripped), the other 3 unchanged-GREEN.
- Step 2: the retargeted pins + E2Es still GREEN
Run: cargo test -p ailang-core --test design_schema_drift --test docs_honesty_pin --test effect_doc_honesty_pin 2>&1 | grep 'test result:'
Expected: 3× PASS. Run
cargo test -p ail --test eq_float_noinstance --test show_no_instance_e2e 2>&1 | grep 'test result:'
Expected: 2× PASS.
- Step 3: whole workspace GREEN + sweep exit 0 + acceptance grep
Run: cargo test --workspace 2>&1 | grep -oE '[0-9]+ passed; [0-9]+ failed' | awk -F'[ ;]' '{p+=$1; f+=$4} END {print "TOTAL passed="p" failed="f}'
Expected: failed=0 and passed ≥ 646 (the iter .1 baseline; the
widened clause-3 adds no new test count, it replaces a body).
Run: bash bench/architect_sweeps.sh; echo "exit=$?"
Expected: exit=0.
Run: grep -rIn 'DESIGN\.md' . --exclude-dir=.git --exclude-dir=target | grep -vE '(^\./)?(docs/(journals/|specs/|plans/|roadmap\.md|WhatsNew\.md|journal-archive\.md)|bench/orchestrator-stats/)' | grep -v 'design-md-rolesplit' | grep -v 'design_index_pin.rs' || echo "CLEAN"
Expected: CLEAN (no live-ref regression from the tidy edits).
Self-review (planner Step 5)
- Spec/Resolution coverage: Task 1 = Resolution-4 (clause-3 = faithful-Sweep-1 + path-excluded-date + PHRASES; the case-insensitive-iter-detector mechanism was found unworkable and is corrected in the audit Resolution + this plan — it conflated the "Iter A/B" rule-names and "pre-existing"/"pre-set" with provenance); Tasks 2–4 = Resolution-1 (history → journal, the 3 audit-named files); Task 5 = Resolution-2 (stale "below"); Task 5b = Resolution-1 scope correction (the planning-time exhaustive scan found 2 more contract files with lowercase provenance the audit's 3-file spot-check missed); Task 6 = Resolution-3 (sweep re-scope + lockstep); Task 7 = Resolution-5 exit state. All points covered, scope corrected on evidence. ✓
- Placeholder scan: no TBD/TODO/"similar to". Every strip names the exact recon line + verbatim before→after text. ✓
- Type/path consistency:
design/contracts/str-abi.md,docs/journals/2026-05-19-design-decision-records.md,contracts_carry_no_decision_record_proseused identically across tasks; the journal append section header## Migrated … (2026-05-19)consistent Tasks 2/3/4. ✓ - Step granularity: each step is one file's edit-set or one Run; the largest (Task 2 Step 2, 6 spans) is one mechanical-per-span pass, 2–5 min. ✓
- No commit steps: none. ✓
- Pin/replacement contiguity: the three
docs_honesty_pin.rspinned runs (str-abi.md:19,typeclasses.md:317,scope-boundaries.md:9) are called out as hazards in the header AND verified by an explicitgrep -ncontiguity check in Tasks 2/3/4 Step 3 + the over-strip guard in Task 4 Step 3. The widened clause-3 matcher (Task 1) is a single self-contained function body — no cross-task substring split. ✓ - Compile-gate vs deferred-caller: the only Rust edit is one self-contained test fn body (Task 1); it compiles standalone (no signature change, no caller, no new dependency — hand-rolled matcher). Every Run gate is satisfiable at its task: Task 1 Step 2 expects RED (pre-strip), Task 7 expects GREEN (post-strip); no gate depends on a later task's code. Build green throughout (test compiles; only its runtime assertion is RED until the strip lands). ✓
- Verification filter strings resolve:
-p ailang-core --test design_index_pin/design_schema_drift/docs_honesty_pin/effect_doc_honesty_pin,-p ail --test eq_float_noinstance/show_no_instance_e2e, and-p ailang-surface --test round_trip(Task 5b — corrected to its real crateailang-surface, notail) all exist (iter .1 created/retargeted them). The clause-3 filtercontracts_carry_no_decision_record_proseis the exact fn name. Task 7 Step 3 uses the unfilteredcargo test --workspacewith a numericfailed=0+passed≥646assertion (cannot masquerade as "nothing ran"). Thegrep/bash architect_sweepsgates have explicitCLEAN/exit=0sentinels; Task 5b Step 3'sgrep … || echo "CLEAN…"likewise. ✓
Plan is placeholder-free; clause-3 is a hand-rolled faithful
Sweep-1 superset — faithful-Sweep-1 line anchors (case-sensitive,
digit-anchored — confirmed ZERO across all contracts) + Sweep-1's
path-excluded date + the audit-named decision-record phrases; no
regex dep, no blanket iter detector (the rejected mechanism).
The audit Resolution-4 is corrected in lockstep. Hand off to
implement.