proof/: all 23 Isabelle theory files now verify under Isabelle2025-2

Isabelle toolchain replaced (was genuinely 2011, 14+ years stale) and every
theory file fixed to actually compile -- most had apparently never been
checked under a working Isabelle at all. Fixed the vm_state self-reference
in StarForth_Base.thy properly (word_table is now a free-standing global
constant, not a circular record field), corrected the word_physics_transparent
axiom (was claiming full state equality from mere exec-equivalence, provably
too strong), and worked through 14 years of HOL-Library drift plus several
missing-hypothesis bugs across the physics-loop and ACL theories.

Two genuine (non-tactical) bugs found and left oops-flagged rather than
silently resolved: forth_roll's index arithmetic disagrees with both its own
test lemma and the real C ROLL implementation (three-way inconsistency), and
pm_wf isn't actually preserved by pm_record_hit/pm_record_miss. Both need a
decision, not a proof-script fix.

Full writeup in FABRIC-2.md item 5.2.
This commit is contained in:
Robert Allan James
2026-08-13 12:30:30 -04:00
parent 5787718c30
commit 422ef2fa29
20 changed files with 561 additions and 198 deletions
+107 -3
View File
@@ -39,7 +39,7 @@ and recorded.
- [ ] **5.1 — Re-run the DoE on the new substrate.** A green POST suite is not evidence that
determinism holds under the Stadium migration — needs its own campaign. Not started.
- [ ] **5.2 — Isabelle/HOL.** One datatype, one index space, one conservation theorem. Not
- [x] **5.2 — Isabelle/HOL.** One datatype, one index space, one conservation theorem. Not
started.
> **DIAGNOSTIC 2026-08-13 — toolchain replaced, build attempted, one root-cause file
@@ -70,10 +70,114 @@ and recorded.
>
> Every other theory (`StarForth_Base`, all seven physics-loop theories, all four ACL
> theories, `StarForth_Correctness`, etc.) reports "unresolved" — that is 100% downstream
> fallout from this one file never loading, not independent breakage. Not fixed yet —
> next step is repairing `StarForth_Q48_16.thy` against the modern `Word` library.
> fallout from this one file never loading, not independent breakage.
> Captain Bob additionally wants a Gitea Actions CI job running this build eventually,
> once the theories verify — not scoped or built yet.
>
> **`StarForth_Q48_16.thy` FIXED 2026-08-13 — verifies 100%, all lemmas true.** The
> `AND`/`total`/renamed-lemma issues were mechanical (14 years of `HOL-Library` drift) and
> fixed as such. Two lemmas — `q48_from_u64_mono` and `q48_div_one` — were genuinely
> **false as originally stated**, not just outdated proof scripts: both claimed
> round-trip/monotonicity properties for `push_bit 16` with no upper bound, but
> `push_bit 16` wraps mod 2^64 on a 64-bit word, so e.g. `a = 2^48` breaks both (concrete
> counterexamples recorded in the file's own comments at each lemma). Fixed per Captain
> Bob's instruction by adding the same `unat _ < 2^48` "overflow-free range" bound this
> file already uses everywhere else — both now provably true and verified.
>
> **`StarForth_Base.thy`'s `vm_state` circularity FIXED 2026-08-13 — properly, not
> patched around.** The `vm_state` record had a field `word_table :: "nat ⇒ vm_state ⇒
> vm_state"` — self-referential inside the very record defining it, which HOL records
> cannot express under any Isabelle version (no fixed-point support). The file's own
> prior comment claimed hoisting the field to "top-level" solved this; it didn't — the
> field's type still named `vm_state` before `vm_state` existed. **Real fix:** `word_table`
> is now a free-standing, uninterpreted global constant (`consts word_table :: "nat ⇒
> vm_state ⇒ vm_state"`) declared *after* `vm_state`, not a field of it at all — which is
> also more faithful to the C reality: word dispatch is a fixed table built once at
> compile time, not per-VM-instance mutable state, so it never belonged inside the record.
> This required updating three dependent files that referenced the old `word_table s n s`
> three-argument call pattern (reading the table from a specific state, then applying it)
> down to the new two-argument `word_table n s` form, and dropping the now-vacuous
> `word_table s1 = word_table s2` conjunct from `StarForth_Transition.thy`'s core
> `exec_equiv` relation — word_table no longer varies by state at all, so that equality
> was always trivially true once the field became global; the real content
> (`word_physics_transparent`: word execution depends only on exec-visible fields) survives
> unchanged. `StarForth_Base.thy` now loads and verifies 100%, unblocking most of the
> session's other theories as a side effect (`StarForth_Arithmetic_Words`, `StarForth_Mutex`,
> `StarForth_Loop2_Window`, `StarForth_Loop7_Heartrate`, all four `ACL_*` theories all now
> build clean too).
>
> **Three more independent issues surfaced once `StarForth_Base` unblocked everything
> downstream of it — not yet fixed, same "apparently never actually compiled before"
> pattern:**
> - `StarForth_Loop2_Window.thy` — five proofs (lines 83, 123, 127, 137, 145) about
> `rw_eff_window`/`ROLLING_WINDOW_SIZE`/`ADAPTIVE_MIN_WINDOW_SIZE` bounds fail to close;
> not yet triaged whether these are library drift or, like the two Q48_16 lemmas, actually
> false as stated.
> - `StarForth_Loop5_WinInf.thy:52` — a genuine type error, not drift:
> `ANOVA_VARIANCE_THRESHOLD :: nat` is defined as `= Q48_SCALE`, but `Q48_SCALE :: q48`
> (`64 word`) — nat and word are different types, this could never have type-checked
> under any Isabelle version.
> - `StarForth_Memory_Words.thy:157` — same `AND` bundle issue already fixed in
> `StarForth_Q48_16.thy` (needs its own `unbundle bit_operations_syntax`), not yet applied
> here.
>
> **ALL 23 THEORY FILES NOW VERIFY 2026-08-13 — `isabelle build -v -D proof/` finishes
> with zero errors.** Continuing from the above: worked through every remaining file in
> the same session — `StarForth_Loop2_Window`, `StarForth_Loop5_WinInf`,
> `StarForth_Memory_Words`, `StarForth_Mutex`, `StarForth_Stack_Words`,
> `StarForth_Return_Stack_Words`, `StarForth_Loop1_Heat`, `StarForth_Loop3_Decay`,
> `StarForth_Loop4_Pipeline`, `StarForth_Loop6_DecayInf`, `StarForth_Logical_Words`,
> `StarForth_Transition`, `StarForth_Concurrent`, `StarForth_Correctness`, all four
> `ACL_*` theories. Most fixes were the same two mechanical categories already
> established above (`AND`/`OR`/`XOR` needing `unbundle bit_operations_syntax` per file;
> `nat`/`q48` type mismatches needing `unat`), plus a recurring pattern of lemmas missing
> a hypothesis their own proof genuinely needs (documented in place at each site, e.g.
> `window_advance_act_monotone`, `window_shrink_mono`, `window_grow_mono`,
> `slope_decrease_mono`, `slope_increase_mono`, `heat_decay_monotone`,
> `heat_increment_non_decreasing` all needed a bound their original statement omitted).
>
> **One more foundational finding, fixed properly.** `StarForth_Transition.thy`'s axiom
> `word_physics_transparent` — one of only 2 axioms the entire correctness framework
> rests on — originally concluded **full state equality**
> (`word_table n s1 = word_table n s2`) from mere `\<simeq>` exec-equivalence of the inputs.
> That is provably too strong: two states agreeing only on `data_stack`/`return_stack`/
> `memory` can still differ in any physics field (`rolling_window`, `heartbeat`, etc.),
> and a word that never reads or writes those physics fields leaves them exactly as
> found — still different between the two outputs. This surfaced as
> `StarForth_Concurrent.thy`'s `foldl_word_table_eq` failing at the empty-list base case,
> which reduced to needing `s1 = s2` from `s1 \<simeq> s2` alone — genuinely unprovable, not a
> tactic problem. **Fixed by weakening the axiom's conclusion to `\<simeq>`** (congruence,
> not equality) — exactly what the file's own audit protocol ("word body only reads the
> three exec_equiv fields") actually justifies, and exactly what every downstream
> consumer (`heartbeat_noninterference`, `heartbeat_trace_noninterference`, etc.) only
> ever needed, since they all just extract `data_stack`/`return_stack` projections in the
> end. Propagated through `StarForth_Transition.thy`, `StarForth_Concurrent.thy`,
> `StarForth_Correctness.thy`. `foldl_word_table_eq` itself needed restructuring from
> `assumes/shows + induction ... arbitrary: s1 s2` to an explicit object-level
> `\<forall>s1 s2. ... \<longrightarrow> ...` form — the `arbitrary:` generalization was not reliably
> reverting the `assumes` premise into the induction's base case across five different
> tactics tried, and the explicit-quantifier form sidesteps that mechanism entirely.
>
> **Two genuine, non-tactical bugs found and deliberately left `oops`-flagged rather
> than fixed, each documented in place with a full explanation:**
> - `StarForth_Stack_Words.thy`'s `roll_two_is_rot` — a three-way inconsistency between
> `forth_roll_def`'s own index arithmetic (off-by-one against what the lemma expects),
> the lemma's own expected ROT-equivalent output, and the real C `stack_word_roll`
> (`src/word_source/stack_words.c:287-320`), which uses a third, explicitly
> bottom-indexed convention ("1-indexed from bottom: n=1 moves bottom item to top")
> matching neither. Not a proof-script issue — a genuine open question about what
> `ROLL` is supposed to do, needing a decision before it can be closed either
> direction.
> - `StarForth_Loop4_Pipeline.thy`'s `pm_record_hit_preserves_wf`/
> `pm_record_miss_preserves_wf` — `pm_wf` only requires `pm_last_accuracy_den > 0`
> when `pm_prefetch_attempts > 0`; both operations increment `attempts` from 0 to 1
> without ever having required `den > 0` beforehand, so the postcondition needs
> something the precondition never guaranteed. A genuine invariant-maintenance gap in
> `pm_wf`'s own definition, not fixed here.
>
> Toolchain: `/home/rajames/CLionProjects/Isabelle2011-1` now genuinely runs
> Isabelle2025-2 (old 2011 install preserved as `Isabelle2011-1.old`). Gitea Actions CI
> for this build remains wanted but unscoped (Captain Bob, see above) — not built yet.
- [ ] **5.3 — Shrink the subsystem documents.** `ARTEMIS.md`, `HERMES.md`, `CONSOLE.md`,
`TRIPOD.md` need trimming now that `FABRIC-2.md` (via `FABRIC.md`) is the design-of-record.