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
+61 -31
View File
@@ -49,12 +49,16 @@ type_synonym event = "thread \<times> action"
well-defined endomorphism.
======================================================================== *)
(* word_table dropped from exec_equiv 2026-08-13: it is no longer a
vm_state field (StarForth_Base.thy fixed the vm_state self-reference by
making word_table a free-standing global constant), so "word_table s1 =
word_table s2" no longer type-checks -- and would have been vacuously
true anyway, since a global constant cannot differ between s1 and s2. *)
definition exec_equiv :: "vm_state \<Rightarrow> vm_state \<Rightarrow> bool" (infix "\<simeq>" 50) where
"s1 \<simeq> s2 \<longleftrightarrow>
data_stack s1 = data_stack s2 \<and>
return_stack s1 = return_stack s2 \<and>
memory s1 = memory s2 \<and>
word_table s1 = word_table s2"
memory s1 = memory s2"
lemma exec_equiv_refl [simp, intro]: "vm \<simeq> vm"
by (simp add: exec_equiv_def)
@@ -68,7 +72,8 @@ lemma exec_equiv_trans: "s1 \<simeq> s2 \<Longrightarrow> s2 \<simeq> s3 \<Longr
lemma exec_equiv_ds: "s1 \<simeq> s2 \<Longrightarrow> data_stack s1 = data_stack s2" by (simp add: exec_equiv_def)
lemma exec_equiv_rs: "s1 \<simeq> s2 \<Longrightarrow> return_stack s1 = return_stack s2" by (simp add: exec_equiv_def)
lemma exec_equiv_mem:"s1 \<simeq> s2 \<Longrightarrow> memory s1 = memory s2" by (simp add: exec_equiv_def)
lemma exec_equiv_wt: "s1 \<simeq> s2 \<Longrightarrow> word_table s1 = word_table s2" by (simp add: exec_equiv_def)
(* exec_equiv_wt removed 2026-08-13: word_table is global now, not read
from state, so this fact no longer type-checks and is not needed. *)
(* =========================================================================
Section 3: Heartbeat axiom — A1 ×1 (collapsed from ×8)
@@ -87,12 +92,14 @@ lemma exec_equiv_wt: "s1 \<simeq> s2 \<Longrightarrow> word_table s1 = word_ta
Read every code path reachable from vm_tick() — including
vm_tick_window_tuner, vm_tick_slope_validator, and all
inference_engine.c callees — and verify that NONE of those paths write
to the following four fields:
to the following three fields:
data_stack (vm->data_stack / vm->ds_top)
return_stack (vm->return_stack / vm->rs_top)
memory (vm->memory[])
word_table (vm->word_table)
Those four fields are exactly exec_equiv. Everything else is free.
Those three fields are exactly exec_equiv. word_table is no longer
among them (2026-08-13: it is a free-standing global constant, not a
vm_state field, so it cannot be written by any vm_tick() path at all).
Everything else is free.
○ CODE-MUST-MATCH: if a future refactor moves any of those four fields into
the heartbeat's write set, exec_equiv must be updated and a new audit
@@ -118,77 +125,100 @@ lemma heartbeat_rs [simp]: "return_stack (heartbeat_step vm) = return_stack vm"
lemma heartbeat_mem [simp]: "memory (heartbeat_step vm) = memory vm"
using heartbeat_exec_neutral by (simp add: exec_equiv_def)
lemma heartbeat_wt [simp]: "word_table (heartbeat_step vm) = word_table vm"
using heartbeat_exec_neutral by (simp add: exec_equiv_def)
(* heartbeat_wt removed 2026-08-13: word_table no longer varies by state. *)
(* =========================================================================
Section 5: n-fold heartbeat exec-neutrality and field preservation
======================================================================== *)
lemma heartbeat_n_exec_neutral: "heartbeat_step ^^ n $ vm \<simeq> vm"
lemma heartbeat_n_exec_neutral: "(heartbeat_step ^^ n) vm \<simeq> vm"
proof (induction n)
case 0 show ?case by simp
next
case (Suc k)
show "heartbeat_step ^^ Suc k $ vm \<simeq> vm"
show "(heartbeat_step ^^ Suc k) vm \<simeq> vm"
using exec_equiv_trans [OF heartbeat_exec_neutral Suc.IH] by simp
qed
lemma heartbeat_n_steps_ds [simp]: "data_stack (heartbeat_step ^^ n $ vm) = data_stack vm"
lemma heartbeat_n_steps_ds [simp]: "data_stack ((heartbeat_step ^^ n) vm) = data_stack vm"
using heartbeat_n_exec_neutral by (simp add: exec_equiv_def)
lemma heartbeat_n_steps_rs [simp]: "return_stack (heartbeat_step ^^ n $ vm) = return_stack vm"
lemma heartbeat_n_steps_rs [simp]: "return_stack ((heartbeat_step ^^ n) vm) = return_stack vm"
using heartbeat_n_exec_neutral by (simp add: exec_equiv_def)
lemma heartbeat_n_steps_mem [simp]: "memory (heartbeat_step ^^ n $ vm) = memory vm"
lemma heartbeat_n_steps_mem [simp]: "memory ((heartbeat_step ^^ n) vm) = memory vm"
using heartbeat_n_exec_neutral by (simp add: exec_equiv_def)
lemma heartbeat_n_steps_wt [simp]: "word_table (heartbeat_step ^^ n $ vm) = word_table vm"
using heartbeat_n_exec_neutral by (simp add: exec_equiv_def)
(* heartbeat_n_steps_wt removed 2026-08-13: word_table no longer varies by
state -- see the note at heartbeat_wt above. *)
(* =========================================================================
Section 6: Word physics transparency — A4' ×1 (congruence form)
Word execution is a well-defined endomorphism on the exec quotient: if two
states are exec-equivalent, executing any word on each produces identical
results. This is the congruence law that makes word sequences independent
of interleaved heartbeat ticks.
states are exec-equivalent, executing any word on each produces
exec-equivalent results. This is the congruence law that makes word
sequences independent of interleaved heartbeat ticks.
CORRECTED 2026-08-13: the conclusion was full state equality
("word_table n s1 = word_table n s2"), not \<simeq>-equivalence. That is
provably too strong and was never true: two states agreeing only on the
three exec_equiv fields can differ in any physics field (rolling_window,
heartbeat, etc.), and a word that never reads or writes those physics
fields leaves them exactly as it found them -- still different between
the two output states. Concretely, this broke
StarForth_Concurrent.thy's foldl_word_table_eq at the empty-list base
case, which reduced to needing s1 = s2 from s1 \<simeq> s2 alone -- genuinely
unprovable. The audit protocol below only ever justified the \<simeq> form:
"the word body only reads the three exec_equiv fields" gives identical
NEW data_stack/return_stack/memory (since those three inputs agree by
\<simeq>), but says nothing about physics fields the word doesn't touch,
which simply carry through from s1/s2 respectively and so can still
differ. \<simeq> is exactly the right conclusion strength -- it is silent
about physics fields, which is what the design has always wanted.
⚠ AUDIT PROTOCOL: for each word registered in word_table, verify its body
only reads data_stack, return_stack, memory, word_table — the four fields
of exec_equiv. These are exactly the fields a FORTH word may observe.
only reads data_stack, return_stack, memory — the three fields of
exec_equiv (word_table itself is no longer one of them since 2026-08-13;
it is a fixed global, not part of state to read). These are exactly the
fields a FORTH word may observe.
○ CODE-MUST-MATCH: no word in src/word_source/ may read rolling_window,
heartbeat, decay_slope_q48, pipeline_metrics, last_inference, ssm_l8,
tuning_lock, dict_lock, heat thresholds, or any other physics field.
======================================================================== *)
(* word_table's arity dropped from 3 to 2 call-site arguments 2026-08-13:
it used to be read from a specific state first (word_table s n s -- get
s's own copy of the table, apply entry n to s), now it is one fixed
global table (word_table n s -- apply entry n directly to s). The
mathematical content of this axiom (word execution depends only on the
exec-visible fields, not physics state) is unchanged. *)
axiomatization where
word_physics_transparent:
"\<And> (s1 :: vm_state) (s2 :: vm_state) n.
s1 \<simeq> s2 \<Longrightarrow> word_table s1 n s1 = word_table s2 n s2"
s1 \<simeq> s2 \<Longrightarrow> word_table n s1 \<simeq> word_table n s2"
(* =========================================================================
Section 7: Consequences — all proved from A1 + A4'
======================================================================== *)
lemma exec_after_heartbeat_eq:
"word_table (heartbeat_step vm) n (heartbeat_step vm) = word_table vm n vm"
"word_table n (heartbeat_step vm) \<simeq> word_table n vm"
by (rule word_physics_transparent [OF heartbeat_exec_neutral])
lemma exec_after_heartbeat_ds:
"data_stack (word_table (heartbeat_step vm) n (heartbeat_step vm))
= data_stack (word_table vm n vm)"
using exec_after_heartbeat_eq by simp
"data_stack (word_table n (heartbeat_step vm))
= data_stack (word_table n vm)"
using exec_after_heartbeat_eq exec_equiv_ds by blast
lemma exec_after_heartbeat_rs:
"return_stack (word_table (heartbeat_step vm) n (heartbeat_step vm))
= return_stack (word_table vm n vm)"
using exec_after_heartbeat_eq by simp
"return_stack (word_table n (heartbeat_step vm))
= return_stack (word_table n vm)"
using exec_after_heartbeat_eq exec_equiv_rs by blast
lemma exec_after_n_heartbeats_eq:
"word_table (heartbeat_step ^^ k $ vm) n (heartbeat_step ^^ k $ vm)
= word_table vm n vm"
"word_table n ((heartbeat_step ^^ k) vm) \<simeq> word_table n vm"
by (rule word_physics_transparent [OF heartbeat_n_exec_neutral])
(* =========================================================================
@@ -200,7 +230,7 @@ inductive vm_step :: "vm_state \<Rightarrow> event \<Rightarrow> vm_state \<Righ
where
StepExec:
"\<not> vm_error vm \<Longrightarrow> \<not> vm_halted vm \<Longrightarrow>
vm' = word_table vm n vm \<Longrightarrow>
vm' = word_table n vm \<Longrightarrow>
vm \<rightarrow>[(ExecThread, ExecWord n)] vm'"
| StepHeartTick: