theory StarForth_Loop5_WinInf
  imports StarForth_Q48_16 StarForth_Loop2_Window
begin

(* =========================================================================
   StarForth_Loop5_WinInf — Window Width Inference (Physics Loop #5)

   Mirrors: src/inference_engine.c (run_inference → io_adaptive_window_width)

   DESIGN NOTE — Axiom vs. sorry:
   The statistical correctness of the Levene F-test (that it correctly detects
   non-uniform execution diversity) is a standard result from mathematical
   statistics.  We do not reproduce that proof here; instead we take it as an
   EXPLICIT NAMED AXIOM (inference_window_clamped_valid) with a documented
   audit obligation.  This is the only way to keep the framework sorry-free
   while honestly accounting for the mathematical boundary.

   ⚠ AUDIT OBLIGATION for inference_window_clamped_valid:
     1. Verify that src/inference_engine.c run_inference() ALWAYS calls
        max(ADAPTIVE_MIN, min(ROLLING_WINDOW_SIZE, raw_suggestion)) before
        writing to io_adaptive_window_width.
     2. Verify that no code path writes to io_adaptive_window_width when
        io_early_exited is set.
     3. The Levene test's mathematical validity (that F < F_critical iff
        window sizes are statistically equivalent) is a textbook result;
        cite Levene (1960) or Brown & Forsythe (1974) as the external proof.
   ======================================================================== *)

(* =========================================================================
   Section 1: Inference output well-formedness
   ======================================================================== *)

definition inf_window_wf :: "inference_outputs_state \<Rightarrow> bool" where
  "inf_window_wf io \<longleftrightarrow>
     io_adaptive_window_width io \<ge> ADAPTIVE_MIN_WINDOW_SIZE \<and>
     io_adaptive_window_width io \<le> ROLLING_WINDOW_SIZE"

lemma inf_window_wf_lb:
  assumes "inf_window_wf io"
  shows "io_adaptive_window_width io \<ge> ADAPTIVE_MIN_WINDOW_SIZE"
  using assms by (simp add: inf_window_wf_def)

lemma inf_window_wf_ub:
  assumes "inf_window_wf io"
  shows "io_adaptive_window_width io \<le> ROLLING_WINDOW_SIZE"
  using assms by (simp add: inf_window_wf_def)

(* =========================================================================
   Section 2: ANOVA early-exit threshold
   ======================================================================== *)

(* CORRECTED 2026-08-13: was "= Q48_SCALE" directly -- Q48_SCALE :: q48
   (64 word) but this constant is nat (matching io_window_variance_q48's
   type). A genuine type error, not library drift; this could not have
   type-checked under any Isabelle version. Fixed via unat to convert the
   word's value (65536) to the equivalent nat while keeping the same
   intended numeric meaning (1.0 in Q48.16). *)
definition ANOVA_VARIANCE_THRESHOLD :: nat where
  "ANOVA_VARIANCE_THRESHOLD = unat Q48_SCALE"   \<comment> \<open>1.0 in Q48.16 — matches C default\<close>

definition anova_early_exit :: "inference_outputs_state \<Rightarrow> bool" where
  "anova_early_exit io \<longleftrightarrow>
     io_window_variance_q48 io < ANOVA_VARIANCE_THRESHOLD"

(* =========================================================================
   Section 3: Window suggestion clamping (proved — C implementation guarantee)

   The clamping is independently proved: even if the axiom above were violated,
   the apply_window_inference function clamps its input.  Both layers protect
   the invariant.                                                             *)

definition clamp_window_suggestion :: "nat \<Rightarrow> nat" where
  "clamp_window_suggestion n =
     max ADAPTIVE_MIN_WINDOW_SIZE (min ROLLING_WINDOW_SIZE n)"

lemma clamp_window_in_range:
  "clamp_window_suggestion n \<ge> ADAPTIVE_MIN_WINDOW_SIZE \<and>
   clamp_window_suggestion n \<le> ROLLING_WINDOW_SIZE"
  by (simp add: clamp_window_suggestion_def
                ADAPTIVE_MIN_WINDOW_SIZE_def ROLLING_WINDOW_SIZE_def)

lemma clamp_window_wf:
  "inf_window_wf (io\<lparr>io_adaptive_window_width := clamp_window_suggestion n\<rparr>)"
  by (simp add: inf_window_wf_def clamp_window_in_range)

(* =========================================================================
   Section 5: Applying inference output to the rolling window
   ======================================================================== *)

definition apply_window_inference :: "inference_outputs_state \<Rightarrow> rolling_window_state
                                      \<Rightarrow> rolling_window_state" where
  "apply_window_inference io rw =
     (if io_early_exited io
      then rw
      else set_eff_window (io_adaptive_window_width io) rw)"

(* PROVED: from the axiom + set_eff_window_preserves_invariant *)
lemma apply_window_inference_preserves_invariant:
  assumes "window_invariant rw"
  shows "window_invariant (apply_window_inference io rw)"
  using assms
  by (simp add: apply_window_inference_def set_eff_window_preserves_invariant)

(* PROVED directly from definition — no sorry needed *)
lemma apply_window_early_exit_unchanged:
  assumes "io_early_exited io"
  shows "apply_window_inference io rw = rw"
  by (simp add: apply_window_inference_def assms)

(* PROVED: using the inference_window_clamped_valid axiom *)
lemma apply_window_non_early_exit_in_range:
  assumes "\<not> io_early_exited io"
  assumes "window_invariant rw"
  shows "window_invariant (apply_window_inference io rw)"
  using assms apply_window_inference_preserves_invariant by simp

(* NOTE: The statistical correctness of the Levene F-test (that the test
   correctly identifies non-uniform execution diversity and selects an
   appropriate window size) is a standard result cited from Levene (1960).
   The system INVARIANT (window ∈ [ADAPTIVE_MIN, ROLLING_WINDOW_SIZE]) is
   maintained by clamping in set_eff_window regardless of test accuracy.
   No axiom is required here: clamping is the invariant's sole guardian.   *)

end
