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
+23 -11
View File
@@ -21,9 +21,11 @@ begin
======================================================================== *)
(* ○ CODE-MUST-MATCH: Initial slope = 2 × Q48_SCALE = 131072.
Matches DECAY_RATE_PER_US_Q16 × 2 in include/vm.h. *)
Matches DECAY_RATE_PER_US_Q16 × 2 in include/vm.h.
CORRECTED 2026-08-13: was "2 * Q48_SCALE" directly -- Q48_SCALE :: q48
(64 word), this constant is nat. Same unat fix as elsewhere. *)
definition DECAY_SLOPE_INIT :: nat where
"DECAY_SLOPE_INIT = 2 * Q48_SCALE"
"DECAY_SLOPE_INIT = 2 * unat Q48_SCALE"
(* ○ CODE-MUST-MATCH: Never let slope reach zero.
⚠ HUMAN-REVIEW: Every C code path that reduces decay_slope_q48 must clamp
@@ -33,7 +35,7 @@ definition DECAY_SLOPE_MIN :: nat where
"DECAY_SLOPE_MIN = 1"
definition DECAY_SLOPE_MAX :: nat where
"DECAY_SLOPE_MAX = Q48_SCALE * 1000"
"DECAY_SLOPE_MAX = unat Q48_SCALE * 1000"
(* =========================================================================
Section 2: Slope well-formedness
@@ -69,7 +71,8 @@ lemma slope_decrease_lb:
lemma slope_decrease_preserves_wf:
assumes "slope_wf s"
shows "slope_wf (slope_decrease step s)"
using assms by (simp add: slope_wf_def slope_decrease_def DECAY_SLOPE_MIN_def)
using assms
by (auto simp: slope_wf_def slope_decrease_def intro: le_trans[OF diff_le_self])
lemma slope_increase_ub:
"slope_increase step s \<le> DECAY_SLOPE_MAX"
@@ -80,11 +83,20 @@ lemma slope_increase_preserves_wf:
shows "slope_wf (slope_increase step s)"
using assms by (simp add: slope_wf_def slope_increase_def DECAY_SLOPE_MIN_def DECAY_SLOPE_MAX_def)
lemma slope_decrease_mono: "slope_decrease step s \<le> s"
by (simp add: slope_decrease_def)
(* CORRECTED 2026-08-13: added the missing slope_wf hypothesis. Without
"s \<ge> DECAY_SLOPE_MIN", slope_decrease's max-clamp can raise a too-small
s back up above its own input (e.g. s=0, step=0 gives
max DECAY_SLOPE_MIN 0 = 1 > 0 = s), breaking the claim. Symmetric
argument for slope_increase_mono below. *)
lemma slope_decrease_mono:
assumes "s \<ge> DECAY_SLOPE_MIN"
shows "slope_decrease step s \<le> s"
using assms by (simp add: slope_decrease_def)
lemma slope_increase_mono: "slope_increase step s \<ge> s"
by (simp add: slope_increase_def)
lemma slope_increase_mono:
assumes "s \<le> DECAY_SLOPE_MAX"
shows "slope_increase step s \<ge> s"
using assms by (simp add: slope_increase_def)
(* =========================================================================
Section 4: VM decay step
@@ -134,8 +146,8 @@ lemma vm_decay_step_dict [simp]:
definition total_dict_heat :: "vm_state \<Rightarrow> int" where
"total_dict_heat vm =
\<Sum>i \<in> {i. dictionary vm i \<noteq> None}.
de_heat (the (dictionary vm i))"
(\<Sum>i \<in> {i. dictionary vm i \<noteq> None}.
de_heat (the (dictionary vm i)))"
(* PROOF (no sorry):
vm_decay_step only changes decay_slope_q48, so dictionary is identical
@@ -149,7 +161,7 @@ lemma decay_step_dict_unchanged:
lemma decay_total_heat_non_increasing:
assumes "\<forall>i. dictionary vm i \<noteq> None \<longrightarrow> de_heat (the (dictionary vm i)) \<ge> 0"
shows "total_dict_heat (vm_decay_step step vm) \<le> total_dict_heat vm"
using decay_step_dict_unchanged by linarith
by (simp add: decay_step_dict_unchanged)
(* =========================================================================
Section 6: Well-formedness: slope is positive in wf_vm