From 1f5689a952d507549028983527ccf2ceaf96d7bc Mon Sep 17 00:00:00 2001 From: Brummel Date: Sun, 10 May 2026 20:00:40 +0200 Subject: [PATCH] =?UTF-8?q?plan:=20architect-iron-law=20extension=20?= =?UTF-8?q?=E2=80=94=20sweep=20script=20+=20lockstep-checklist?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...2026-05-10-architect-iron-law-extension.md | 351 ++++++++++++++++++ 1 file changed, 351 insertions(+) create mode 100644 docs/plans/2026-05-10-architect-iron-law-extension.md diff --git a/docs/plans/2026-05-10-architect-iron-law-extension.md b/docs/plans/2026-05-10-architect-iron-law-extension.md new file mode 100644 index 0000000..ab2ab8e --- /dev/null +++ b/docs/plans/2026-05-10-architect-iron-law-extension.md @@ -0,0 +1,351 @@ +# Architect Iron-Law Extension — Implementation Plan + +> **Parent:** `docs/roadmap.md` P2 todo "Architect-iron-law standing-grep +> extension" (no per-iteration spec — this is a tooling-discipline +> extension, not a milestone). +> +> **Context:** JOURNAL 2026-05-10 "Milestone close: design-md-consolidation" +> (the four sweep regexes); JOURNAL 2026-05-10 "Fieldtest close: +> Floats milestone" (the lockstep failure-mode that B1 surfaced). +> +> **For agentic workers:** REQUIRED SUB-SKILL: use `skills/implement` +> to run this plan. Steps use `- [ ]` checkboxes for tracking. + +**Goal:** Extend `ailang-architect`'s drift review with two standing +checks so DESIGN.md cannot silently regrow history anchors, and so +new typecheck-reject / `lower_app` arms cannot ship without their +cross-file companion update. + +**Architecture:** A new helper script `bench/architect_sweeps.sh` +runs the four sweep regexes from the design-md-consolidation +milestone against `docs/DESIGN.md` and prints any matched lines. +The architect agent's standing reading list and "What you check" +section are extended with two new bullets: one that invokes the +sweep script, one that walks the two known cross-file lockstep +pairings (`Pattern::Lit::*` rejects ↔ `pre_desugar_validation.rs`, +and `lower_app` arms ↔ `is_static_callee`). No production code +changes; this is process-tooling only. + +**Tech Stack:** bash, markdown. + +**Files this plan creates or modifies:** + +- Create: `bench/architect_sweeps.sh` — runs the four design-md- + consolidation sweep regexes against `docs/DESIGN.md`. Exit 0 if + all sweeps are clean, 1 if any anchor is found. Output is the + matched lines, prefixed by sweep name. +- Modify: `skills/audit/agents/ailang-architect.md` — adds two new + bullets to "What you check" (DESIGN.md history-anchor regrowth + + Lockstep invariants across files), and inserts a Step 2.5 in "The + Process" that runs the sweep script. +- Modify: `docs/JOURNAL.md` — append a closing entry under today's + date. +- Modify: `docs/roadmap.md` — strike the "Architect-iron-law + standing-grep extension" P2 todo (entry done). + +--- + +## Task 1: Helper script `bench/architect_sweeps.sh` + +**Files:** +- Create: `bench/architect_sweeps.sh` +- Test: manual invocation against current `docs/DESIGN.md` + +- [ ] **Step 1: Write the script** + +Create `bench/architect_sweeps.sh` with the following exact contents: + +```bash +#!/usr/bin/env bash +# bench/architect_sweeps.sh +# +# Run the four design-md-consolidation sweep-invariant greps against +# docs/DESIGN.md. Output: matched lines, prefixed by sweep name. Exit 0 +# if all four sweeps are clean, 1 if any anchor was found. +# +# Companion to skills/audit/agents/ailang-architect.md "What you check +# / DESIGN.md history-anchor regrowth". See JOURNAL 2026-05-10 +# ("Milestone close: design-md-consolidation") for the rationale of +# each sweep regex; the regexes here are copied verbatim from JOURNAL +# entries 12487 (Sweep 1), 12619 (Sweep 2), 12718-12720 (Sweep 3), +# and 12840 (Sweep 4). +# +# A non-zero exit is advisory, not authoritative: the architect agent +# reviews each match and decides whether it is a legitimate quote +# (e.g. a JOURNAL citation inside a block-quote) or fresh drift. + +set -u +DESIGN="docs/DESIGN.md" +HITS=0 + +if [[ ! -f "$DESIGN" ]]; then + echo "architect_sweeps: $DESIGN not found (run from repo root)" >&2 + exit 2 +fi + +run_sweep() { + local name="$1" + local pattern="$2" + local matches + matches=$(grep -nE "$pattern" "$DESIGN" || true) + if [[ -n "$matches" ]]; then + echo "=== Sweep: $name ===" + echo "$matches" + echo + HITS=1 + fi +} + +run_sweep "1 (history anchors)" \ + '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' + +run_sweep "2 (REVERTED + migration)" \ + 'REVERTED|preserved for the audit trail|Migration plan|[Oo]riginally framed|original rationale|empirically-grounded version|A future (iter|iteration|milestone|Prelude) may|A future iter that|a (later|future) iter(ation)? \(deferred\)|Concrete design deferred' + +run_sweep "3 (schema SoT)" \ + '^\s*(struct |enum |pub (struct|enum|fn))|whenever the two disagree|ast\.rs is the source of truth' + +run_sweep "4 (workflow + stale cross-references)" \ + 'agents/README\.md|ailang-docwriter|Recently lifted|see the JOURNAL queue|later the same day|Sharpened later|closure conversion in JOURNAL' + +if [[ $HITS -eq 0 ]]; then + echo "All four sweeps clean." +fi +exit $HITS +``` + +- [ ] **Step 2: Make it executable** + +Run: `chmod +x bench/architect_sweeps.sh` +Expected: no output, exit 0. + +- [ ] **Step 3: Run against current DESIGN.md, expect clean** + +Run: `bash bench/architect_sweeps.sh` +Expected: stdout = `All four sweeps clean.`, exit code 0. + +If any sweep matches, the script implementation is wrong (the +design-md-consolidation milestone closed all four sweeps as clean +on 2026-05-10; today's DESIGN.md is the post-close baseline). Diff +the regex against the JOURNAL-recorded one character-by-character. + +- [ ] **Step 4: Commit** + +```bash +git add bench/architect_sweeps.sh +git commit -m "iter architect-iron-law.1: bench/architect_sweeps.sh runs the four design-md-consolidation sweeps against DESIGN.md" +``` + +--- + +## Task 2: Extend `ailang-architect` agent prose + +**Files:** +- Modify: `skills/audit/agents/ailang-architect.md` + +- [ ] **Step 1: Add "DESIGN.md history-anchor regrowth" bullet to "What you check"** + +In `skills/audit/agents/ailang-architect.md`, locate the "What you +check" section (currently has bullets: Drift against DESIGN.md, Drift +against the milestone spec, Growing debt, Consistency across crates, +Test coverage, Scaling break points, JOURNAL truthfulness). + +Insert a new bullet immediately AFTER the "JOURNAL truthfulness" +bullet (i.e. as the last bullet in the list): + +```markdown +- **DESIGN.md history-anchor regrowth.** Run + `bash bench/architect_sweeps.sh` from the repo root. Exit 0 = clean. + Exit 1 = at least one of the four sweeps from the + design-md-consolidation milestone (2026-05-10) matched. Review each + match: a legitimate quote (e.g. a JOURNAL citation inside a block- + quote) is fine; a fresh history anchor / REVERTED narrative / + workflow detail / stale cross-reference is drift to flag. +- **Lockstep invariants across files.** Two known cross-file pairings + must move together; a new arm in one without the matching update in + the other ships silently broken (B1 in the Floats fieldtest is the + canonical example). On every milestone-close, walk these pairs: + + | Pair | Failure mode | + |---|---| + | `Pattern::Lit::*` typecheck rejects in `crates/ailang-check/src/lib.rs` ↔ pre-desugar walkers in `crates/ailang-check/src/pre_desugar_validation.rs` | A reject arm placed AFTER `desugar_module` in the call chain is unreachable through the public `check` API if the desugar pass rewrites that pattern shape first (e.g. `desugar::build_eq` rewrites `Pattern::Lit::Float` into `(== scrut lit)` before typecheck runs). New rejects on a `Pattern::Lit::*` shape MUST live in `pre_desugar_validation.rs`, or be paired with a written guarantee that no desugar pass eats the shape. | + | `lower_app` arms in `crates/ailang-codegen/src/lib.rs::lower_app` (line ~1749) ↔ name recognition in `crates/ailang-codegen/src/lib.rs::is_static_callee` (line ~2189) | A name lowered by a direct `lower_app` arm but unrecognised by `is_static_callee` falls through to the indirect-call path with `UnknownVar` (`UnknownVar` panic in worst case). Every new builtin lowering arm in `lower_app` must have a matching `is_static_callee` entry. | + + Walk procedure: for each milestone-scope commit-range arm landed in + these files (use `git diff ..HEAD --` on each file in + the pair), open both files in the pair and confirm the matching + update is present. Flag any unpaired arm as drift. +``` + +- [ ] **Step 2: Add Step 2.5 to "The Process"** + +In `skills/audit/agents/ailang-architect.md`, locate "The Process" +section. Steps are currently numbered 1 through 6. + +Replace Step 2 + the current Step 3 with Step 2 + Step 2.5 + Step 3 +(renumbering nothing else). The current Step 2 reads: + +```markdown +2. `git log --oneline -30` and `git diff ..HEAD` for + the factual diff. +``` + +Replace it with: + +```markdown +2. `git log --oneline -30` and `git diff ..HEAD` for + the factual diff. +2.5. Run `bash bench/architect_sweeps.sh` from the repo root. If exit + code is 1, treat each matched line as a drift-suspicion to verify. + If exit code is 2, the script could not find DESIGN.md — fix the + working directory and re-run before continuing. +``` + +- [ ] **Step 3: Self-check by re-reading the modified agent file** + +Read `skills/audit/agents/ailang-architect.md` end-to-end. Verify: +- The two new bullets appear at the end of "What you check". +- Step 2.5 appears between Step 2 and Step 3 in "The Process". +- File path references resolve: `crates/ailang-check/src/lib.rs`, + `crates/ailang-check/src/pre_desugar_validation.rs`, + `crates/ailang-codegen/src/lib.rs`, `bench/architect_sweeps.sh` + all exist. + +- [ ] **Step 4: Commit** + +```bash +git add skills/audit/agents/ailang-architect.md +git commit -m "iter architect-iron-law.2: extend ailang-architect with sweep-script invocation + lockstep-checklist for two known cross-file pairings" +``` + +--- + +## Task 3: JOURNAL entry + roadmap close-out + +**Files:** +- Modify: `docs/JOURNAL.md` +- Modify: `docs/roadmap.md` + +- [ ] **Step 1: Append JOURNAL entry** + +Append the following block at the end of `docs/JOURNAL.md`: + +```markdown +## 2026-05-10 — Architect iron-law extension: sweep script + lockstep-checklist + +`ailang-architect`'s drift-review iron law extended with two +standing checks, both motivated by failure modes that shipped in +the closing milestones of the typeclass-and-floats arc: + +1. **DESIGN.md history-anchor regrowth.** The four sweep regexes + from the design-md-consolidation milestone (history anchors, + REVERTED + migration, schema SoT, workflow + stale cross- + references) are now packaged as `bench/architect_sweeps.sh` and + run as Step 2.5 of the architect's process. Today's DESIGN.md + is clean against all four; the script's job is to keep it that + way against future commits. Non-zero exit is advisory: the + architect reads each match and decides legitimate-quote vs. fresh + drift. +2. **Lockstep invariants across files.** Two cross-file pairings + are pinned in the agent's "What you check" section as standing + walks: `Pattern::Lit::*` typecheck-rejects ↔ + `pre_desugar_validation.rs` walkers (the B1 lockstep — the + typecheck reject is unreachable through `check_module` if a + desugar pass rewrites the shape first), and `lower_app` arms ↔ + `is_static_callee` recognition (the iter-4.2 / 4.4 lockstep — + a direct lowering arm without `is_static_callee` recognition + falls through to indirect-call with `UnknownVar`). For each + milestone-scope commit-range arm landed in these files, the + architect now opens both files in the pair. + +Both pairings are real, both shipped silently broken at least once, +and both were caught only by post-hoc means (B1 by fieldtest, the +iter-4 ones by mid-iter implementer review). The architect was the +right role to catch them prospectively; the standing checklist is +how that role catches them in future. + +Per-task commits: + +- `` iter architect-iron-law.1: bench/architect_sweeps.sh runs the four design-md-consolidation sweeps against DESIGN.md +- `` iter architect-iron-law.2: extend ailang-architect with sweep-script invocation + lockstep-checklist for two known cross-file pairings + +The roadmap entry "Architect-iron-law standing-grep extension" +under P2 is closed by this iteration. Future lockstep pairings, as +they surface in JOURNAL entries, can extend the table inline +without further iteration ceremony. +``` + +(The hashes will be filled in when the actual commits are made; the +commit-creating step in this task patches them in.) + +- [ ] **Step 2: Resolve commit-hash placeholders** + +After Tasks 1 and 2 have been committed, get the two short hashes: + +Run: `git log --oneline -5 | head -3` +Expected: top three lines start with the two iter-1/iter-2 commits +plus the previous (Floats) commit. + +Edit `docs/JOURNAL.md` — replace `` and `` with the +short SHA from the corresponding commits. The Task 1 commit is +"iter architect-iron-law.1:..." and Task 2 is "...iron-law.2:...". + +- [ ] **Step 3: Strike the roadmap entry** + +In `docs/roadmap.md`, locate the bullet: + +```markdown +- [ ] **\[todo\]** Architect-iron-law standing-grep extension — + the architect agent's drift review should run the four sweep + invariant greps on every milestone-close so DESIGN.md cannot + silently regrow history anchors / REVERTED narratives / + workflow detail / stale cross-references. Path-anchored + exceptions (`docs/specs/2026-05-09-*`) need an allowlist. + Same extension should add the **lockstep-checklist** the + Floats fieldtest exposed: for every new typecheck reject arm + on a pattern shape, verify the corresponding desugar pass does + not eat that shape first; for every new lowering arm in + `lower_app`, verify `is_static_callee` recognises it. Both + shipped silently-broken in the Floats milestone (B1 and the + iter-4.2/4.4 pull-forwards) and the architect missed them. + - context: JOURNAL 2026-05-10 ("Milestone close: + design-md-consolidation"); 2026-05-10 ("Fieldtest close: + Floats milestone") — B1 + architect-checklist follow-up. +``` + +Delete it entirely. (Done entries are deleted from the roadmap once +they are no longer interesting context; the JOURNAL entry above +preserves the rationale.) + +- [ ] **Step 4: Verify the script still runs clean after agent-prose changes** + +Run: `bash bench/architect_sweeps.sh` +Expected: `All four sweeps clean.`, exit 0. (Sanity — Tasks 2 and 3 +should not have touched DESIGN.md.) + +- [ ] **Step 5: Commit** + +```bash +git add docs/JOURNAL.md docs/roadmap.md +git commit -m "iter architect-iron-law.3: JOURNAL entry + close roadmap todo" +``` + +--- + +## Self-review checklist + +1. **Spec coverage:** the roadmap entry has two halves (standing + greps + lockstep checklist); Task 1 covers the script that + embodies the greps, Task 2 covers the agent-prose for both halves, + Task 3 covers the JOURNAL + roadmap closure. All covered. ✓ +2. **Placeholder scan:** `` / `` are placeholders + resolved in Task 3 Step 2 by the implementer reading actual git + output. No "TBD", no "TODO", no "implement later", no "similar to + Task N". ✓ +3. **Type / path consistency:** `bench/architect_sweeps.sh` is the + same path in script, agent file, and JOURNAL. `lower_app` / + `is_static_callee` line numbers match the verified `grep` output + from this conversation (1749 / 2189). `pre_desugar_validation.rs` + exists. ✓ +4. **Step granularity:** each step is a single file-edit-or-command, + 2-5 minutes. ✓