Theory AlphabetEnlargement_ComputeCorrect

theory AlphabetEnlargement_ComputeCorrect
  imports AlphabetEnlargement_ValidationBound
begin

text ‹Entry point of the alphabet_enlarge›
  forward-simulation chain (the combinator is defined in
  AlphabetEnlargement_Simulation›).  The chain establishes
  that M' = alphabet_enlarge M› simulates M›, and
  culminates in the three top-level theorems characterising the
  combinator — well-formedness preservation
  (alphabet_enlarge_wf›), forward language preservation
  modulo input encoding
  (alphabet_enlarge_language_forward›), and the linear
  time bound (alphabet_enlarge_time›) — which are proved
  in theory AlphabetEnlargement› at the end of the chain.
  The construction follows the linear-speedup theorem of
  Hartmanis and Stearns
  cite‹Theorem 2› in "Hartmanis1965:computational",
  modernised in Hopcroft and Ullman
  cite‹Theorem 12.3› in "Hopcroft1979:introduction".

  The forward chain is split across theories in dependency
  order, each importing the previous:
   AlphabetEnlargement_ComputeCorrect› (this theory):
    per-substep state shape and invariant preservation, the
    mttm_step› lift, and buffered c-fold compute
    correctness.
   AlphabetEnlargement_SS4›: SS4 trace-existence and
    the buffer characterisations at SS4 entry.
   AlphabetEnlargement_OutputWF›: home classification
    and output well-formedness.
   AlphabetEnlargement_ForwardStage›: the per-tape
    unified forward stage
    ae_simulates_forward_stage_general›.
   AlphabetEnlargement_Acceptance›: acceptance
    correspondence and the step-count / chunked simulation
    engine.
   AlphabetEnlargement›: the three top-level
    theorems.›

subsection ‹Forward simulation chain›

subsubsection ‹Per-substep state shape and invariant preservation›

text ‹Per-substep mid-stage invariant preservation lemmas.
  Eight in total, one per simulation substep transition
  SSn›→›SSn+1› (with SS9 ≡› SS1 by
  wrap-around).›

text ‹Common skeleton: each per-substep delta is a set of
  tuples whose post-state component fixes idx› at the target
  substep and constrains q› via q ∈ Q_tm M›.
  This helper packages the mttm_step›-elimination plus the
  set-comprehension destructuring once, reducing each per-substep
  proof to a one-line shape obligation discharged by auto› on
  the relevant ae_delta_ss<N>_ss<N+1>_def›.

  The helper does not apply to ae_step_ss8_ss1_invariant›:
  that substep's halting branch lands at idx = VFwd›, not
  idx = SS1›, so the post-state's idx› is not uniformly
  fixed.›

lemma ae_substep_state_shape:
  fixes M :: "('q, 'a) mttm"
    and δ :: "(('q × ('a, 'c :: enum) ae_stage)
              × (nat  ('c  'a))
              × ('q × ('a, 'c) ae_stage)
              × (nat  ('c  'a))
              × (nat  dir)) set"
    and c' c'' :: "('c :: enum  'a,
                    'q × ('a, 'c) ae_stage) mt_config"
    and tgt :: substep_idx
  assumes step: "(c', c'')  mttm_step δ"
      and shape: "s a s' a' d.
                    (s, a, s', a', d)  δ
                       q ofs buf dest.
                            s' = (q, ofs, buf, dest, tgt)
                             q  Q_tm M"
  shows "case mt_state c'' of (qM', _, _, _, idx) 
            idx = tgt  qM'  Q_tm M"
proof -
  from step obtain s ts n s' a' d where
      c''_eq: "c'' = ConfigM s' (λk. (ts k)(n k := a' k))
                                (λk. go_dir (d k) (n k))"
      and rel: "(s, (λk. ts k (n k)), s', a', d)  δ"
    by (auto elim: mttm_step.cases)
  from shape[OF rel] obtain q ofs buf dest where
      s'_eq: "s' = (q, ofs, buf, dest, tgt)"
      and q_in: "q  Q_tm M"
    by blast
  show ?thesis using c''_eq s'_eq q_in by simp
qed

lemma ae_step_ss1_ss2_invariant:
  fixes M :: "('q, 'a) mttm"
    and c' c'' :: "('c :: enum  'a,
                    'q × ('a, 'c) ae_stage) mt_config"
  assumes "valid_mttm M"
      and "ae_inv_ss1 M c'"
      and "(c', c'')  mttm_step (ae_delta_ss1_ss2 M)"
    shows "ae_inv_ss2 M c''"
proof -
  have shape: "s a s' a' d.
                  (s, a, s', a', d)  ae_delta_ss1_ss2 M
                     q ofs buf dest.
                          s' = (q, ofs, buf, dest, SS2)
                           q  Q_tm M"
    by (force simp: ae_delta_ss1_ss2_def)
  show "ae_inv_ss2 M c''"
    unfolding ae_inv_ss2_def
    using ae_substep_state_shape[OF assms(3) shape] .
qed

lemma ae_step_ss2_ss3_invariant:
  fixes M :: "('q, 'a) mttm"
    and c' c'' :: "('c :: enum  'a,
                    'q × ('a, 'c) ae_stage) mt_config"
  assumes "valid_mttm M"
      and "ae_inv_ss2 M c'"
      and "(c', c'')  mttm_step (ae_delta_ss2_ss3 M)"
    shows "ae_inv_ss3 M c''"
proof -
  have shape: "s a s' a' d.
                  (s, a, s', a', d)  ae_delta_ss2_ss3 M
                     q ofs buf dest.
                          s' = (q, ofs, buf, dest, SS3)
                           q  Q_tm M"
    by (force simp: ae_delta_ss2_ss3_def)
  show "ae_inv_ss3 M c''"
    unfolding ae_inv_ss3_def
    using ae_substep_state_shape[OF assms(3) shape] .
qed

lemma ae_step_ss3_ss4_invariant:
  fixes M :: "('q, 'a) mttm"
    and c' c'' :: "('c :: enum  'a,
                    'q × ('a, 'c) ae_stage) mt_config"
  assumes "valid_mttm M"
      and "ae_inv_ss3 M c'"
      and "(c', c'')  mttm_step (ae_delta_ss3_ss4 M)"
    shows "ae_inv_ss4 M c''"
proof -
  have shape: "s a s' a' d.
                  (s, a, s', a', d)  ae_delta_ss3_ss4 M
                     q ofs buf dest.
                          s' = (q, ofs, buf, dest, SS4)
                           q  Q_tm M"
    by (force simp: ae_delta_ss3_ss4_def)
  show "ae_inv_ss4 M c''"
    unfolding ae_inv_ss4_def
    using ae_substep_state_shape[OF assms(3) shape] .
qed

lemma ae_step_ss4_ss5_invariant:
  fixes M :: "('q, 'a) mttm"
    and c' c'' :: "('c :: enum  'a,
                    'q × ('a, 'c) ae_stage) mt_config"
  assumes valM: "valid_mttm M"
      and "ae_inv_ss4 M c'"
      and step: "(c', c'')  mttm_step (ae_delta_ss4_ss5 M)"
    shows "ae_inv_ss5 M c''"
proof -
  ― ‹Unlike the template substeps, ss4 →›
      ss5 advances the q›-component via
      m_steps_buffered›; Q_tm›-membership is preserved
      through the chain by
      m_steps_buffered_state_preservation›.  The
      ae_substep_state_shape› helper does not apply directly
      because its uniform shape obligation can't pull in
      valM› at the right scope; we instead inline the
      mttm_step›-elimination.›
  from step obtain s ts n s' a' d where
      c''_eq: "c'' = ConfigM s' (λk. (ts k)(n k := a' k))
                                (λk. go_dir (d k) (n k))"
      and rel: "(s, (λk. ts k (n k)), s', a', d)  ae_delta_ss4_ss5 M"
    by (auto elim: mttm_step.cases)
  from rel[unfolded ae_delta_ss4_ss5_def mem_Collect_eq]
  obtain q ofs buf dest_old q' ofs' buf' dest'
         buf_full end_pos bufC
    where s_eq: "s = (q, ofs, buf, dest_old, SS4)"
      and s'_eq: "s' = (q', ofs', buf', dest', SS5)"
      and q_Q: "q  Q_tm M"
      and m_steps: "((q, buf_full, λk. (AE_Home, ofs k)),
                      (q', bufC, end_pos))
                         m_steps_buffered M"
    by auto
  from m_steps_buffered_state_preservation[OF valM m_steps q_Q]
  have q'_in_Q: "q'  Q_tm M" .
  show "ae_inv_ss5 M c''"
    unfolding ae_inv_ss5_def using c''_eq s'_eq q'_in_Q by simp
qed

lemma ae_step_ss5_ss6_invariant:
  fixes M :: "('q, 'a) mttm"
    and c' c'' :: "('c :: enum  'a,
                    'q × ('a, 'c) ae_stage) mt_config"
  assumes "valid_mttm M"
      and "ae_inv_ss5 M c'"
      and "(c', c'')  mttm_step (ae_delta_ss5_ss6 M)"
    shows "ae_inv_ss6 M c''"
proof -
  have shape: "s a s' a' d.
                  (s, a, s', a', d)  ae_delta_ss5_ss6 M
                     q ofs buf dest.
                          s' = (q, ofs, buf, dest, SS6)
                           q  Q_tm M"
    by (force simp: ae_delta_ss5_ss6_def)
  show "ae_inv_ss6 M c''"
    unfolding ae_inv_ss6_def
    using ae_substep_state_shape[OF assms(3) shape] .
qed

lemma ae_step_ss6_ss7_invariant:
  fixes M :: "('q, 'a) mttm"
    and c' c'' :: "('c :: enum  'a,
                    'q × ('a, 'c) ae_stage) mt_config"
  assumes "valid_mttm M"
      and "ae_inv_ss6 M c'"
      and "(c', c'')  mttm_step (ae_delta_ss6_ss7 M)"
    shows "ae_inv_ss7 M c''"
proof -
  have shape: "s a s' a' d.
                  (s, a, s', a', d)  ae_delta_ss6_ss7 M
                     q ofs buf dest.
                          s' = (q, ofs, buf, dest, SS7)
                           q  Q_tm M"
    by (force simp: ae_delta_ss6_ss7_def)
  show "ae_inv_ss7 M c''"
    unfolding ae_inv_ss7_def
    using ae_substep_state_shape[OF assms(3) shape] .
qed

lemma ae_step_ss7_ss8_invariant:
  fixes M :: "('q, 'a) mttm"
    and c' c'' :: "('c :: enum  'a,
                    'q × ('a, 'c) ae_stage) mt_config"
  assumes "valid_mttm M"
      and "ae_inv_ss7 M c'"
      and "(c', c'')  mttm_step (ae_delta_ss7_ss8 M)"
    shows "ae_inv_ss8 M c''"
proof -
  have shape: "s a s' a' d.
                  (s, a, s', a', d)  ae_delta_ss7_ss8 M
                     q ofs buf dest.
                          s' = (q, ofs, buf, dest, SS8)
                           q  Q_tm M"
    by (force simp: ae_delta_ss7_ss8_def)
  show "ae_inv_ss8 M c''"
    unfolding ae_inv_ss8_def
    using ae_substep_state_shape[OF assms(3) shape] .
qed

lemma ae_step_ss8_ss1_invariant:
  fixes M :: "('q, 'a) mttm"
    and c' c'' :: "('c :: enum  'a,
                    'q × ('a, 'c) ae_stage) mt_config"
  assumes "valid_mttm M"
      and "ae_inv_ss8 M c'"
      and non_halt: "case mt_state c' of (qM', _, _, _, _) 
                        qM'  t_tm M  qM'  r_tm M"
      and step: "(c', c'')  mttm_step (ae_delta_ss8_ss1 M)"
    shows "ae_inv_ss1 M c''"
proof -
  ― ‹The cycle-closure substep has a halting branch
      (q ∈ {t_tm M, r_tm M}›) that lands at idx = VFwd›,
      not idx = SS1›; the non_halt› assumption forces
      the steady-state branch.›
  from step obtain s ts n s' a' d where
      c'_eq: "c' = ConfigM s ts n"
      and c''_eq: "c'' = ConfigM s' (λk. (ts k)(n k := a' k))
                                    (λk. go_dir (d k) (n k))"
      and rel: "(s, (λk. ts k (n k)), s', a', d)  ae_delta_ss8_ss1 M"
    by (auto elim: mttm_step.cases)
  from rel obtain q ofs buf dest stage' where
      s_eq: "s = (q, ofs, buf, dest, SS8)"
      and s'_eq: "s' = (q, stage')"
      and q_in: "q  Q_tm M"
      and stage'_eq: "stage' = (if q  {t_tm M, r_tm M}
                                  then init_stage (le_tm M)
                                  else (ofs, buf, init_dest, SS1))"
    by (auto simp: ae_delta_ss8_ss1_def)
  from non_halt c'_eq s_eq have q_non_halt: "q  t_tm M  q  r_tm M"
    by simp
  with stage'_eq have stage'_resolved:
      "stage' = (ofs, buf, init_dest, SS1)" by simp
  show "ae_inv_ss1 M c''"
    unfolding ae_inv_ss1_def
    using c''_eq s'_eq stage'_resolved q_in by simp
qed

text ‹Halt-branch invariant for SS8→›SS1: when
  M›'s simulated state at SS8 is halting
  (qM' ∈ {t_tm M, r_tm M}›), the SS8→›SS1
  step routes to init_stage le› (post-idx is VFwd›, not
  SS1›) and preserves the halt-state q›.  Companion to
  ae_step_ss8_ss1_invariant› (non-halt branch).  The chain
  proof in ae_simulates_forward_stage› case-splits on whether
  M›'s state is halting at SS8 and applies one of these two
  lemmas accordingly; the halt branch lands in the simulation's
  halt disjunct (qM' ∈ {t_tm M, r_tm M}›), the non-halt
  branch in the SS1 disjunct.›

lemma ae_step_ss8_ss1_invariant_halt:
  fixes M :: "('q, 'a) mttm"
    and c' c'' :: "('c :: enum  'a,
                    'q × ('a, 'c) ae_stage) mt_config"
  assumes inv: "ae_inv_ss8 M c'"
      and halt: "case mt_state c' of (qM', _, _, _, _) 
                    qM'  {t_tm M, r_tm M}"
      and step: "(c', c'')  mttm_step (ae_delta_ss8_ss1 M)"
    shows "(case mt_state c'' of (qM', _, _, _, idx) 
              qM'  {t_tm M, r_tm M}  idx = VFwd)"
proof -
  from step obtain s ts n s' a' d where
      c'_eq: "c' = ConfigM s ts n"
      and c''_eq: "c'' = ConfigM s' (λk. (ts k)(n k := a' k))
                                    (λk. go_dir (d k) (n k))"
      and rel: "(s, (λk. ts k (n k)), s', a', d)  ae_delta_ss8_ss1 M"
    by (auto elim: mttm_step.cases)
  from rel obtain q ofs buf dest stage' where
      s_eq: "s = (q, ofs, buf, dest, SS8)"
      and s'_eq: "s' = (q, stage')"
      and q_in: "q  Q_tm M"
      and stage'_eq: "stage' = (if q  {t_tm M, r_tm M}
                                  then init_stage (le_tm M)
                                  else (ofs, buf, init_dest, SS1))"
    by (auto simp: ae_delta_ss8_ss1_def)
  from halt c'_eq s_eq have q_halt: "q  {t_tm M, r_tm M}"
    by simp
  with stage'_eq have stage'_resolved:
      "stage' = init_stage (le_tm M)" by simp
  show ?thesis
    using c''_eq s'_eq stage'_resolved q_halt
    unfolding init_stage_def by simp
qed

subsubsection mttm_step› lifts of cross-phase exclusions›

text mttm_step›-level lifts of the cross-phase exclusion
  lemmas ae_delta_ssN_only›: when a substrate-level step
  in the alphabet-enlarged combinator's union has source
  substep_idx› SSN›, the step is in the canonical
  ae_delta_ssN_ssM› substep relation.  Used by the reverse
  arm to commit each peeled δ'›-step to its canonical
  substep before invoking the per-substep invariant
  propagation.›

lemma mttm_step_ae_delta_ss1_only:
  fixes M :: "('q, 'a) mttm"
    and c c' :: "('c :: enum  'a,
                  'q × ('a, 'c) ae_stage) mt_config"
  assumes step: "(c, c')  mttm_step (alphabet_enlarge_delta M)"
      and ss1: "snd (snd (snd (snd (mt_state c)))) = SS1"
    shows "(c, c')  mttm_step (ae_delta_ss1_ss2 M)"
proof -
  from step obtain s ts n s' a' d where
      c_eq: "c = ConfigM s ts n"
      and c'_eq: "c' = ConfigM s' (λk. (ts k)(n k := a' k))
                                    (λk. go_dir (d k) (n k))"
      and rel: "(s, (λk. ts k (n k)), s', a', d)
                   alphabet_enlarge_delta M"
    by (auto elim: mttm_step.cases)
  from ss1 c_eq have s_ss1: "snd (snd (snd (snd s))) = SS1"
    by simp
  have rel_sub: "(s, (λk. ts k (n k)), s', a', d)
                     ae_delta_ss1_ss2 M"
    by (rule ae_delta_ss1_only[OF rel s_ss1])
  show ?thesis
    unfolding c_eq c'_eq
    by (rule mttm_step.step[where ts = ts and n = n and a = a' and dir = d,
                            OF rel_sub])
qed

lemma mttm_step_ae_delta_ss2_only:
  fixes M :: "('q, 'a) mttm"
    and c c' :: "('c :: enum  'a,
                  'q × ('a, 'c) ae_stage) mt_config"
  assumes step: "(c, c')  mttm_step (alphabet_enlarge_delta M)"
      and ss2: "snd (snd (snd (snd (mt_state c)))) = SS2"
    shows "(c, c')  mttm_step (ae_delta_ss2_ss3 M)"
proof -
  from step obtain s ts n s' a' d where
      c_eq: "c = ConfigM s ts n"
      and c'_eq: "c' = ConfigM s' (λk. (ts k)(n k := a' k))
                                    (λk. go_dir (d k) (n k))"
      and rel: "(s, (λk. ts k (n k)), s', a', d)
                   alphabet_enlarge_delta M"
    by (auto elim: mttm_step.cases)
  from ss2 c_eq have s_ss2: "snd (snd (snd (snd s))) = SS2"
    by simp
  have rel_sub: "(s, (λk. ts k (n k)), s', a', d)
                     ae_delta_ss2_ss3 M"
    by (rule ae_delta_ss2_only[OF rel s_ss2])
  show ?thesis
    unfolding c_eq c'_eq
    by (rule mttm_step.step[where ts = ts and n = n and a = a' and dir = d,
                            OF rel_sub])
qed

lemma mttm_step_ae_delta_ss3_only:
  fixes M :: "('q, 'a) mttm"
    and c c' :: "('c :: enum  'a,
                  'q × ('a, 'c) ae_stage) mt_config"
  assumes step: "(c, c')  mttm_step (alphabet_enlarge_delta M)"
      and ss3: "snd (snd (snd (snd (mt_state c)))) = SS3"
    shows "(c, c')  mttm_step (ae_delta_ss3_ss4 M)"
proof -
  from step obtain s ts n s' a' d where
      c_eq: "c = ConfigM s ts n"
      and c'_eq: "c' = ConfigM s' (λk. (ts k)(n k := a' k))
                                    (λk. go_dir (d k) (n k))"
      and rel: "(s, (λk. ts k (n k)), s', a', d)
                   alphabet_enlarge_delta M"
    by (auto elim: mttm_step.cases)
  from ss3 c_eq have s_ss3: "snd (snd (snd (snd s))) = SS3"
    by simp
  have rel_sub: "(s, (λk. ts k (n k)), s', a', d)
                     ae_delta_ss3_ss4 M"
    by (rule ae_delta_ss3_only[OF rel s_ss3])
  show ?thesis
    unfolding c_eq c'_eq
    by (rule mttm_step.step[where ts = ts and n = n and a = a' and dir = d,
                            OF rel_sub])
qed

lemma mttm_step_ae_delta_ss4_only:
  fixes M :: "('q, 'a) mttm"
    and c c' :: "('c :: enum  'a,
                  'q × ('a, 'c) ae_stage) mt_config"
  assumes step: "(c, c')  mttm_step (alphabet_enlarge_delta M)"
      and ss4: "snd (snd (snd (snd (mt_state c)))) = SS4"
    shows "(c, c')  mttm_step (ae_delta_ss4_ss5 M)"
proof -
  from step obtain s ts n s' a' d where
      c_eq: "c = ConfigM s ts n"
      and c'_eq: "c' = ConfigM s' (λk. (ts k)(n k := a' k))
                                    (λk. go_dir (d k) (n k))"
      and rel: "(s, (λk. ts k (n k)), s', a', d)
                   alphabet_enlarge_delta M"
    by (auto elim: mttm_step.cases)
  from ss4 c_eq have s_ss4: "snd (snd (snd (snd s))) = SS4"
    by simp
  have rel_sub: "(s, (λk. ts k (n k)), s', a', d)
                     ae_delta_ss4_ss5 M"
    by (rule ae_delta_ss4_only[OF rel s_ss4])
  show ?thesis
    unfolding c_eq c'_eq
    by (rule mttm_step.step[where ts = ts and n = n and a = a' and dir = d,
                            OF rel_sub])
qed

lemma mttm_step_ae_delta_ss5_only:
  fixes M :: "('q, 'a) mttm"
    and c c' :: "('c :: enum  'a,
                  'q × ('a, 'c) ae_stage) mt_config"
  assumes step: "(c, c')  mttm_step (alphabet_enlarge_delta M)"
      and ss5: "snd (snd (snd (snd (mt_state c)))) = SS5"
    shows "(c, c')  mttm_step (ae_delta_ss5_ss6 M)"
proof -
  from step obtain s ts n s' a' d where
      c_eq: "c = ConfigM s ts n"
      and c'_eq: "c' = ConfigM s' (λk. (ts k)(n k := a' k))
                                    (λk. go_dir (d k) (n k))"
      and rel: "(s, (λk. ts k (n k)), s', a', d)
                   alphabet_enlarge_delta M"
    by (auto elim: mttm_step.cases)
  from ss5 c_eq have s_ss5: "snd (snd (snd (snd s))) = SS5"
    by simp
  have rel_sub: "(s, (λk. ts k (n k)), s', a', d)
                     ae_delta_ss5_ss6 M"
    by (rule ae_delta_ss5_only[OF rel s_ss5])
  show ?thesis
    unfolding c_eq c'_eq
    by (rule mttm_step.step[where ts = ts and n = n and a = a' and dir = d,
                            OF rel_sub])
qed

lemma mttm_step_ae_delta_ss6_only:
  fixes M :: "('q, 'a) mttm"
    and c c' :: "('c :: enum  'a,
                  'q × ('a, 'c) ae_stage) mt_config"
  assumes step: "(c, c')  mttm_step (alphabet_enlarge_delta M)"
      and ss6: "snd (snd (snd (snd (mt_state c)))) = SS6"
    shows "(c, c')  mttm_step (ae_delta_ss6_ss7 M)"
proof -
  from step obtain s ts n s' a' d where
      c_eq: "c = ConfigM s ts n"
      and c'_eq: "c' = ConfigM s' (λk. (ts k)(n k := a' k))
                                    (λk. go_dir (d k) (n k))"
      and rel: "(s, (λk. ts k (n k)), s', a', d)
                   alphabet_enlarge_delta M"
    by (auto elim: mttm_step.cases)
  from ss6 c_eq have s_ss6: "snd (snd (snd (snd s))) = SS6"
    by simp
  have rel_sub: "(s, (λk. ts k (n k)), s', a', d)
                     ae_delta_ss6_ss7 M"
    by (rule ae_delta_ss6_only[OF rel s_ss6])
  show ?thesis
    unfolding c_eq c'_eq
    by (rule mttm_step.step[where ts = ts and n = n and a = a' and dir = d,
                            OF rel_sub])
qed

lemma mttm_step_ae_delta_ss7_only:
  fixes M :: "('q, 'a) mttm"
    and c c' :: "('c :: enum  'a,
                  'q × ('a, 'c) ae_stage) mt_config"
  assumes step: "(c, c')  mttm_step (alphabet_enlarge_delta M)"
      and ss7: "snd (snd (snd (snd (mt_state c)))) = SS7"
    shows "(c, c')  mttm_step (ae_delta_ss7_ss8 M)"
proof -
  from step obtain s ts n s' a' d where
      c_eq: "c = ConfigM s ts n"
      and c'_eq: "c' = ConfigM s' (λk. (ts k)(n k := a' k))
                                    (λk. go_dir (d k) (n k))"
      and rel: "(s, (λk. ts k (n k)), s', a', d)
                   alphabet_enlarge_delta M"
    by (auto elim: mttm_step.cases)
  from ss7 c_eq have s_ss7: "snd (snd (snd (snd s))) = SS7"
    by simp
  have rel_sub: "(s, (λk. ts k (n k)), s', a', d)
                     ae_delta_ss7_ss8 M"
    by (rule ae_delta_ss7_only[OF rel s_ss7])
  show ?thesis
    unfolding c_eq c'_eq
    by (rule mttm_step.step[where ts = ts and n = n and a = a' and dir = d,
                            OF rel_sub])
qed

lemma mttm_step_ae_delta_ss8_only:
  fixes M :: "('q, 'a) mttm"
    and c c' :: "('c :: enum  'a,
                  'q × ('a, 'c) ae_stage) mt_config"
  assumes step: "(c, c')  mttm_step (alphabet_enlarge_delta M)"
      and ss8: "snd (snd (snd (snd (mt_state c)))) = SS8"
    shows "(c, c')  mttm_step (ae_delta_ss8_ss1 M)"
proof -
  from step obtain s ts n s' a' d where
      c_eq: "c = ConfigM s ts n"
      and c'_eq: "c' = ConfigM s' (λk. (ts k)(n k := a' k))
                                    (λk. go_dir (d k) (n k))"
      and rel: "(s, (λk. ts k (n k)), s', a', d)
                   alphabet_enlarge_delta M"
    by (auto elim: mttm_step.cases)
  from ss8 c_eq have s_ss8: "snd (snd (snd (snd s))) = SS8"
    by simp
  have rel_sub: "(s, (λk. ts k (n k)), s', a', d)
                     ae_delta_ss8_ss1 M"
    by (rule ae_delta_ss8_only[OF rel s_ss8])
  show ?thesis
    unfolding c_eq c'_eq
    by (rule mttm_step.step[where ts = ts and n = n and a = a' and dir = d,
                            OF rel_sub])
qed

subsubsection ‹Buffered c-fold compute correctness›

text ‹Algebraic correctness of the buffered c-fold compute:
  starting from a 3-block buffer matching a 3c-cell window of
  the M-tape, with M's head at the home block and within the
  non-LE region, the buffered compute simulates M's actual
  c-step trace.  The conclusion exhibits a buffered-compute
  trajectory and a matching M-trace, with the post-state buffer
  / head still satisfying the window invariant.

  Proof skeleton:

  Induction on a step counter i ∈ [0, c]›.

  Base case (i = 0›): pre-state matches itself by the
  window› hypothesis.

  Step case (i ≤ c›): assume the IH holds at step i›.
  Either M halts at i› (early-stop branch fires;
  q_i ∈ {t, r}›; done), or M takes an (i + 1)›-st step.
  In the second sub-case:

  1. Read symbol from the buffer at IH's bp_i› via
     read_bp›; the window invariant gives this equals
     tsM_i (nM_i)›.
  2. Apply M's δ› (total on non-halting states by
     valid_mttm›) to get (q_{i+1}, a', d)›.
  3. Write a' k› back to the buffer via write_bp›.
  4. Advance bp_i› via bp_advance_le›.  The load-bearing
     claim is that this returns Some bp_{i+1}› (i.e., the
     head doesn't walk off the buffer).  This holds because
     displacement after i + 1› steps is at most i + 1
     ≤ c›, and the buffer covers 3c positions with the
     head starting at home (linearised positions
     [c, 2c-1]›), so the head stays within
     [1, 3c-2] ⊂ [0, 3c-1]›.
  5. Verify the post-state still satisfies the window
     invariant: same p_start›; new bp_{i+1}›;
     buffer's linearised reading at position
     bp_linear bp_{i+1}› agrees with tsM_{i+1}› at
     nM_{i+1}›.

  The step case's load-bearing arithmetic (item 4) is a
  bp_advance_le›-vs-tape-position commutation lemma:
  bp_linear› of the advanced bp› equals the
  linearised tape position relative to p_start›.  This
  sub-lemma is non-trivial but standalone — it doesn't depend
  on M's δ›, only on the encoding's arithmetic.

  The delta_total› precondition rules out the
  stuck-non-halt case: the substrate's δ_set› axiom
  permits non-halting states with no δ›-successor
  (δ ⊆ (Q - {t,r}) × ...› is a subset, not an
  equality).  Without this hypothesis the conclusion is
  unprovable: a stuck qM› has no buffered run and is
  non-halt, so neither disjunct of the final claim can hold.
  Hartmanis and Stearns's Theorem 2 implicitly assumes δ› is
  total on Q - {t,r}›; a caller whose machines are total by
  construction discharges this precondition trivially.›


text ‹Per-tape unified companion of ae_coupled_run_aux›,
  _le0›, and _le1›.  Takes a per-tape regime
  selector pos :: nat ⇒ nat› (= mt_pos c' k›
  at the SS4 entry) and the per-tape hybrid window-invariant
  predicate ae_window_invariant_general›, which
  dispatches internally on each tape's regime.  The buffered
  run is the same simultaneous m_step_buffered M›
  relation as the three siblings — the regime selector is
  frozen per tape during the run (m_step_buffered›
  has no c'› in scope), so per-tape regime case-splits
  commute with the induction on n›.

  The no-LE hypothesis is per-tape regime-aware: width
  c› for pos = 0›, 2c› for
  pos = 1›, 3c› for pos ≥ 2›.
  Uniform p_start = (pos - 2) * c + 1› simplifies to
  1› on pos ∈ {0, 1}› by nat arithmetic,
  matching the three siblings' Suc i› shape.

  The post-compute left-slot guard
  (fst (buf' k) ≠ LE_block›) is preserved on
  pos = 0› tapes (the generalisation of the le0 chain
  strengthening); le1 tapes have fst (buf k) = LE_block›
  on entry, and steady tapes do not need this property at the
  SS4→›SS5 boundary.

  It sits alongside
  ae_coupled_run_aux_le0› and _le1› as
  load-bearing inductive helpers.  Consumer:
  ae_m_steps_buffered_correct_trace_general›, feeding
  ae_step_ss4_ss5_exists_general_trace›, which closes
  the SS4→›SS5 trace in
  ae_simulates_forward_stage_general›'s body.›

lemma ae_coupled_run_aux_general:
  fixes M :: "('q, 'a) mttm"
    and qM :: 'q
    and tsM :: "nat  nat  'a"
    and nM :: "nat  nat"
    and ofs :: "nat  ('c :: enum)"
    and buf_full :: "nat  (('c  'a) × ('c  'a) × ('c  'a))"
    and pos :: "nat  nat"
    and n :: nat
    and cM_n :: "('a, 'q) mt_config"
  assumes vM:        "valid_mttm M"
      and lu:        "le_unique M"
      and qM_in:     "qM  Q_tm M"
      and window:    "k<k_tm M. ae_window_invariant_general (tsM k) (nM k)
                            (AE_Home, ofs k) (buf_full k) (pos k) (le_tm M)"
      and pad_home:  "kk_tm M. fst (snd (buf_full k)) = bl_block (bl_tm M)"
      and trace:     "(ConfigM qM tsM nM, cM_n)
                         mttm_step (delta_tm M) ^^ n"
      and n_bound:   "n  card (UNIV :: 'c set)"
      and no_le:
            "k. (pos k = 0
                     (i. i < card (UNIV :: 'c set)
                               tsM k (Suc i)  le_tm M))
                  (pos k = 1
                       (i. i < 2 * card (UNIV :: 'c set)
                                 tsM k (Suc i)  le_tm M))
                  (pos k  2
                       (i. i < 3 * card (UNIV :: 'c set)
                                 tsM k
                                      ((pos k - 2) * card (UNIV :: 'c set)
                                        + 1 + i)
                                     le_tm M))"
      and left_not_le_pos0:
            "k<k_tm M. pos k = 0  fst (buf_full k)  LE_block (le_tm M)"
  shows "buf' end_pos.
            ((qM, buf_full, λk. (AE_Home, ofs k)),
             (mt_state cM_n, buf', end_pos))
                 (m_step_buffered M) ^^ n
           (k<k_tm M. ae_window_invariant_general
                    (mt_tape cM_n k) (mt_pos cM_n k)
                    (end_pos k) (buf' k) (pos k) (le_tm M))
           (k. (pos k = 0
                     (i. i < card (UNIV :: 'c set)
                               mt_tape cM_n k (Suc i)  le_tm M))
                  (pos k = 1
                       (i. i < 2 * card (UNIV :: 'c set)
                                 mt_tape cM_n k (Suc i)  le_tm M))
                  (pos k  2
                       (i. i < 3 * card (UNIV :: 'c set)
                                 mt_tape cM_n k
                                      ((pos k - 2) * card (UNIV :: 'c set)
                                        + 1 + i)
                                     le_tm M)))
           (k<k_tm M. pos k = 0
                     fst (buf' k)  LE_block (le_tm M))
           (k. card (UNIV :: 'c set)  bp_linear (end_pos k) + n
                   bp_linear (end_pos k)
                        < 2 * card (UNIV :: 'c set) + n)
           (kk_tm M. fst (snd (buf' k)) = bl_block (bl_tm M)
                   end_pos k = (AE_Home, ofs k))"
  using trace n_bound
proof (induction n arbitrary: cM_n)
  case 0
  ― ‹Base case: zero M›-steps means cM_n› is the
    initial config, the buffered run is empty, and the four
    output conjuncts hold by direct lifting of the lemma's input
    hypotheses (window›, no_le›,
    left_not_le_pos0›) at the unchanged buffered state.
    Witnesses: buf' = buf_full›,
    end_pos = λk. (AE_Home, ofs k)›.›
  from (ConfigM qM tsM nM, cM_n)
             mttm_step (delta_tm M) ^^ 0
  have cM_eq: "cM_n = ConfigM qM tsM nM" by simp
  hence st: "mt_state cM_n = qM"
    and tp: "mt_tape cM_n = tsM"
    and ps: "mt_pos cM_n = nM" by auto
  show ?case
  proof (intro exI [where x = buf_full]
                exI [where x = "λk. (AE_Home, ofs k)"]
                conjI)
    show "((qM, buf_full, λk. (AE_Home, ofs k)),
            (mt_state cM_n, buf_full, λk. (AE_Home, ofs k)))
               (m_step_buffered M) ^^ 0"
      using st by simp
    show "k<k_tm M. ae_window_invariant_general
                (mt_tape cM_n k) (mt_pos cM_n k)
                ((λk. (AE_Home, ofs k)) k)
                (buf_full k) (pos k) (le_tm M)"
      using window tp ps by simp
    show "k. (pos k = 0
                 (i. i < card (UNIV :: 'c set)
                           mt_tape cM_n k (Suc i)  le_tm M))
              (pos k = 1
                   (i. i < 2 * card (UNIV :: 'c set)
                             mt_tape cM_n k (Suc i)  le_tm M))
              (pos k  2
                   (i. i < 3 * card (UNIV :: 'c set)
                             mt_tape cM_n k
                                  ((pos k - 2) * card (UNIV :: 'c set)
                                    + 1 + i)
                                 le_tm M))"
      using no_le tp by simp
    show "k<k_tm M. pos k = 0
                 fst (buf_full k)  LE_block (le_tm M)"
      using left_not_le_pos0 .
    show "k. card (UNIV :: 'c set)
                 bp_linear ((λk. (AE_Home, ofs k)) k) + 0
               bp_linear ((λk. (AE_Home, ofs k)) k)
                    < 2 * card (UNIV :: 'c set) + 0"
    proof (intro allI conjI)
      fix k
      have lin: "bp_linear ((λk. (AE_Home, ofs k)) k)
                    = card (UNIV :: 'c set) + c_idx (ofs k)"
        unfolding bp_linear_def by simp
      show "card (UNIV :: 'c set)
               bp_linear ((λk. (AE_Home, ofs k)) k) + 0"
        using lin by simp
      show "bp_linear ((λk. (AE_Home, ofs k)) k)
              < 2 * card (UNIV :: 'c set) + 0"
        using lin c_idx_lt_card[where x = "ofs k"] by simp
    qed
    show "kk_tm M. fst (snd (buf_full k)) = bl_block (bl_tm M)
                 (λk. (AE_Home, ofs k)) k = (AE_Home, ofs k)"
      using pad_home by simp
  qed
next
  case (Suc n')
  ― ‹Inductive step: peel the last M›-side step via
    relpow_Suc_E› to obtain an intermediate config
    cM_n'›; apply the IH at n'› to obtain a
    coupled buffered run of length n'›; extend it by one
    m_step_buffered› step mirroring the M-side
    transition; re-establish the four output conjuncts at
    n = Suc n'›.

    The four ingredients are: (i) buffered read matches M-side
    read via window-invariant buf-linearisation; (ii) same
    δ›-tuple drives both sides; (iii)
    bp_advance_le› is total at every reached head
    position (no_le› rules out the only None case);
    (iv) window invariant preserved by parallel writes and
    head advances.›
  have n'_bound: "n'  card (UNIV :: 'c set)"
    using Suc.prems(2) by simp
  from Suc.prems(1) obtain cM_n' where
      trace_n': "(ConfigM qM tsM nM, cM_n')
                     mttm_step (delta_tm M) ^^ n'"
    and last_step: "(cM_n', cM_n)  mttm_step (delta_tm M)"
    by (rule relpow_Suc_E)
  from Suc.IH[OF trace_n' n'_bound]
  obtain buf_n' end_pos_n' where
      coupled_n':
        "((qM, buf_full, λk. (AE_Home, ofs k)),
          (mt_state cM_n', buf_n', end_pos_n'))
             (m_step_buffered M) ^^ n'"
    and window_n':
        "k<k_tm M. ae_window_invariant_general
                (mt_tape cM_n' k) (mt_pos cM_n' k)
                (end_pos_n' k) (buf_n' k) (pos k) (le_tm M)"
    and no_le_n':
        "k. (pos k = 0
                 (i. i < card (UNIV :: 'c set)
                           mt_tape cM_n' k (Suc i)
                                 le_tm M))
              (pos k = 1
                   (i. i < 2 * card (UNIV :: 'c set)
                             mt_tape cM_n' k (Suc i)
                                   le_tm M))
              (pos k  2
                   (i. i < 3 * card (UNIV :: 'c set)
                             mt_tape cM_n' k
                                  ((pos k - 2)
                                      * card (UNIV :: 'c set)
                                    + 1 + i)
                                 le_tm M))"
    and left_n':
        "k<k_tm M. pos k = 0
               fst (buf_n' k)  LE_block (le_tm M)"
    and bp_bound_n':
        "k. card (UNIV :: 'c set)  bp_linear (end_pos_n' k) + n'
               bp_linear (end_pos_n' k)
                    < 2 * card (UNIV :: 'c set) + n'"
    and pad_n':
        "kk_tm M. fst (snd (buf_n' k)) = bl_block (bl_tm M)
               end_pos_n' k = (AE_Home, ofs k)"
    by blast
  ― ‹Unpack last_step› via mttm_step.cases›
    into its δ›-tuple ingredients: a state shape
    cM_n' = Config q_pre ts_pre n_pre›, the resulting
    cM_n› as the M-side write + head-advance, and the
    (q_pre, read, q_post, a_step, dir_step)›
    δ›-membership.›
  from last_step obtain q_pre ts_pre n_pre q_post a_step dir_step where
      cM_n'_eq: "cM_n' = ConfigM q_pre ts_pre n_pre"
    and cM_n_eq:
        "cM_n = ConfigM q_post
                  (λk. (ts_pre k)(n_pre k := a_step k))
                  (λk. go_dir (dir_step k) (n_pre k))"
    and delta_mem:
        "(q_pre, λk. ts_pre k (n_pre k),
            q_post, a_step, dir_step)  delta_tm M"
    by (rule mttm_step.cases)
  ― ‹Derived closed forms on cM_n'› /
    cM_n›'s components — convenient handles for the
    buffered-side construction in the next increment.›
  have st_n': "mt_state cM_n' = q_pre"
   and tp_n': "mt_tape cM_n' = ts_pre"
   and ps_n': "mt_pos cM_n' = n_pre"
    using cM_n'_eq by auto
  have st_n: "mt_state cM_n = q_post"
   and tp_n: "k. mt_tape cM_n k
                    = (ts_pre k)(n_pre k := a_step k)"
   and ps_n: "k. mt_pos cM_n k
                    = go_dir (dir_step k) (n_pre k)"
    using cM_n_eq by auto
  ― ‹At this point we have:
    (a) the coupled buffered run of length n'› ending at
        (q_pre, buf_n', end_pos_n')›;
    (b) the four invariants at cM_n'›;
    (c) the M-side δ›-tuple
        (q_pre, read, q_post, a_step, dir_step)›;
    (d) closed forms for cM_n›'s state / tape / pos.›
  ― ‹Ingredient (i) of the inductive step: per-tape
    read-match.  The buffered read at end_pos_n' k›
    equals the M-side read at n_pre k›, via the unified
    read_bp_via_window_general›.›
  have read_match:
      "k. read_bp (buf_n' k) (end_pos_n' k) = ts_pre k (n_pre k)"
  proof (intro allI)
    fix k
    show "read_bp (buf_n' k) (end_pos_n' k) = ts_pre k (n_pre k)"
    proof (cases "k < k_tm M")
      case True
      ― ‹Active tape: the read-match is the window invariant's
          buf-linearisation clause projected at the head offset.›
      from window_n'[rule_format, OF True] have wi_k:
          "ae_window_invariant_general
              (mt_tape cM_n' k) (mt_pos cM_n' k)
              (end_pos_n' k) (buf_n' k) (pos k) (le_tm M)" .
      hence wi_k':
          "ae_window_invariant_general
              (ts_pre k) (n_pre k)
              (end_pos_n' k) (buf_n' k) (pos k) (le_tm M)"
        using tp_n' ps_n' by simp
      show ?thesis
        by (rule read_bp_via_window_general[OF wi_k'])
    next
      case False
      ― ‹Padding tape k ≥ k_tm M›: M reads blank
          (valid_mttm_delta_support›) and the buffered home block is
          blank with the head parked at home (pad_n'›), so both
          sides read bl_tm M›.›
      hence kge: "k_tm M  k" by simp
      from pad_n'[rule_format, OF kge]
      have ph: "fst (snd (buf_n' k)) = bl_block (bl_tm M)"
        and ep: "end_pos_n' k = (AE_Home, ofs k)" by simp_all
      have rd: "ts_pre k (n_pre k) = bl_tm M"
        using valid_mttm_delta_support[OF vM delta_mem kge] by simp
      obtain l h r where blk: "buf_n' k = (l, h, r)"
        by (cases "buf_n' k") auto
      from ph blk have h_eq: "h = bl_block (bl_tm M)" by simp
      have "read_bp (buf_n' k) (end_pos_n' k) = bl_tm M"
        using blk ep h_eq by (simp add: read_bp_def bl_block_def)
      thus ?thesis using rd by simp
    qed
  qed
  ― ‹Per-tape position bounds at step n'›: the fifth
    output conjunct of the IH (bp_bound_n'›) plus the
    bound Suc n' ≤ c› (giving n' < c›) yields
    strict bounds bp_linear < 3c - 1› and
    0 < bp_linear› per tape, excluding both None
    configurations of bp_advance›.›
  have c_pos: "1  card (UNIV :: 'c set)"
    using Suc.prems(2) by linarith
  have bp_lt_max:
      "k. bp_linear (end_pos_n' k)
              < 3 * card (UNIV :: 'c set) - 1"
  proof (intro allI)
    fix k
    have lin_lt: "bp_linear (end_pos_n' k) < 2 * card (UNIV :: 'c set) + n'"
      using bp_bound_n' by blast
    show "bp_linear (end_pos_n' k) < 3 * card (UNIV :: 'c set) - 1"
      using lin_lt Suc.prems(2) c_pos by linarith
  qed
  have bp_gt_zero:
      "k. 0 < bp_linear (end_pos_n' k)"
  proof (intro allI)
    fix k
    have low: "card (UNIV :: 'c set)  bp_linear (end_pos_n' k) + n'"
      using bp_bound_n' by blast
    show "0 < bp_linear (end_pos_n' k)"
      using low Suc.prems(2) c_pos by linarith
  qed
  ― ‹Ingredient (iii): per-tape bp_advance_le› totality
    at step n'›.  Apply bp_advance_le_total› per tape
    with bp_lt_max›, bp_gt_zero›; lift across tapes
    via choice to obtain the new per-tape head position function
    end_pos_n :: nat ⇒ 'c bp›.›
  have per_tape_total:
      "k. p'. bp_advance_le (le_tm M)
                    (ts_pre k (n_pre k))
                    (end_pos_n' k) (dir_step k)
                = Some p'"
  proof (intro allI)
    fix k
    show "p'. bp_advance_le (le_tm M)
                  (ts_pre k (n_pre k))
                  (end_pos_n' k) (dir_step k)
              = Some p'"
      by (rule bp_advance_le_total[OF bp_lt_max[rule_format]
                                       bp_gt_zero[rule_format]])
  qed
  from per_tape_total
  have "end_pos_n.
            k. bp_advance_le (le_tm M)
                    (ts_pre k (n_pre k))
                    (end_pos_n' k) (dir_step k)
                  = Some (end_pos_n k)"
    by (rule choice)
  then obtain end_pos_n where
      end_pos_n_eq:
        "k. bp_advance_le (le_tm M)
                (ts_pre k (n_pre k))
                (end_pos_n' k) (dir_step k)
              = Some (end_pos_n k)"
    by blast
  ― ‹Ingredient (ii): assemble the buffered last step's
    membership in m_step_buffered M›.  Define the new
    buffer buf_n› as the per-tape write-back of
    buf_n'› at end_pos_n'› with a_step›;
    apply the intro rule m_step_bufferedI› with the four
    ingredients (delta_mem›, read_match›'s
    reverse, buf_n›'s definitional read-back, and
    end_pos_n_eq›).›
  define buf_n where
    "buf_n = (λk. write_bp (buf_n' k) (end_pos_n' k) (a_step k))"
  have read_match_sym:
      "k. ts_pre k (n_pre k) = read_bp (buf_n' k) (end_pos_n' k)"
    using read_match by auto
  have buf_n_def_forall:
      "k. buf_n k = write_bp (buf_n' k) (end_pos_n' k) (a_step k)"
    using buf_n_def by simp
  have m_step_last:
      "((q_pre, buf_n', end_pos_n'),
        (q_post, buf_n, end_pos_n))
             m_step_buffered M"
    by (rule m_step_bufferedI[OF delta_mem read_match_sym
                                  buf_n_def_forall end_pos_n_eq])
  ― ‹Chain extension: bridge coupled_n'›'s endpoint
    (mt_state cM_n', buf_n', end_pos_n')› through
    st_n'› (mt_state cM_n' = q_pre›) to match
    m_step_last›'s start, then compose via
    relpow_Suc_I› for a Suc n'›-step buffered run
    ending at (q_post, buf_n, end_pos_n)›.›
  have coupled_n_pre:
      "((qM, buf_full, λk. (AE_Home, ofs k)),
        (q_pre, buf_n', end_pos_n'))
             (m_step_buffered M) ^^ n'"
    using coupled_n' st_n' by simp
  have coupled_n:
      "((qM, buf_full, λk. (AE_Home, ofs k)),
        (q_post, buf_n, end_pos_n))
             (m_step_buffered M) ^^ Suc n'"
    using coupled_n_pre m_step_last by (rule relpow_Suc_I)
  ― ‹Conjunct 5 (bp_linear› bound at step Suc n'): apply
    the helper bp_advance_le_lin_bounded› per tape.
    Given the IH's conjunct (bp_bound_n'›) plus the
    position bounds (bp_gt_zero›) plus the advance
    end_pos_n_eq›, the helper closes both bound
    components.›
  have bp_bound_n:
      "k. card (UNIV :: 'c set)  bp_linear (end_pos_n k) + Suc n'
             bp_linear (end_pos_n k)
                  < 2 * card (UNIV :: 'c set) + Suc n'"
  proof (intro allI)
    fix k
    show "card (UNIV :: 'c set)  bp_linear (end_pos_n k) + Suc n'
           bp_linear (end_pos_n k)
                < 2 * card (UNIV :: 'c set) + Suc n'"
      by (rule bp_advance_le_lin_bounded
                  [OF end_pos_n_eq[rule_format, of k]
                      bp_gt_zero[rule_format, of k]
                      conjunct2[OF bp_bound_n'[rule_format, of k]]
                      conjunct1[OF bp_bound_n'[rule_format, of k]]])
  qed
  ― ‹Conjunct 4 (left_not_le_pos0› at step Suc n'):
    in pos k = 0› regime, the window invariant excludes
    fst (end_pos_n' k) = AE_Left›, so write_bp›'s
    update doesn't touch the left slot.  Hence
    fst (buf_n k) = fst (buf_n' k)›, and the IH's
    left_n'› closes the goal.›
  have left_n:
      "k<k_tm M. pos k = 0
               fst (buf_n k)  LE_block (le_tm M)"
  proof (intro allI impI)
    fix k
    assume klt: "k < k_tm M"
    assume pos_0: "pos k = 0"
    from window_n'[rule_format, OF klt] have wi_k:
        "ae_window_invariant_general (mt_tape cM_n' k) (mt_pos cM_n' k)
            (end_pos_n' k) (buf_n' k) (pos k) (le_tm M)" .
    with pos_0 have wi_le0:
        "ae_window_invariant_le0 (mt_tape cM_n' k) (mt_pos cM_n' k)
            (end_pos_n' k) (buf_n' k) (le_tm M)"
      unfolding ae_window_invariant_general_def by simp
    have fst_bp_not_left: "fst (end_pos_n' k)  AE_Left"
    proof (rule ccontr)
      assume "¬ fst (end_pos_n' k)  AE_Left"
      hence "fst (end_pos_n' k) = AE_Left" by simp
      with wi_le0 show False
        unfolding ae_window_invariant_le0_def by simp
    qed
    have fst_buf_n: "fst (buf_n k) = fst (buf_n' k)"
    proof -
      obtain l h r where blocks_eq: "buf_n' k = (l, h, r)"
        by (cases "buf_n' k") auto
      obtain b off where bp_eq: "end_pos_n' k = (b, off)"
        by (cases "end_pos_n' k") auto
      from fst_bp_not_left bp_eq have "b  AE_Left" by simp
      thus ?thesis
        unfolding buf_n_def
        using blocks_eq bp_eq
        by (cases b) (auto simp: write_bp_def)
    qed
    have "fst (buf_n' k)  LE_block (le_tm M)"
      using left_n' pos_0 klt by blast
    thus "fst (buf_n k)  LE_block (le_tm M)"
      using fst_buf_n by simp
  qed
  ― ‹Conjunct 1 (coupled run with mt_state cM_n›
    witness at step Suc n'): re-express coupled_n›'s
    endpoint state from q_post› to mt_state cM_n›
    via st_n›.›
  have coupled_chain:
      "((qM, buf_full, λk. (AE_Home, ofs k)),
        (mt_state cM_n, buf_n, end_pos_n))
             (m_step_buffered M) ^^ Suc n'"
    using coupled_n st_n by simp
  ― ‹Contrapositive of the substrate axiom
    valid_mttm_deltaLE_no_write›: if M reads non-LE on tape k›
    cell n_pre k›, then it does not write LE on tape k›.
    This is what powers the j = n_pre k› case of conjunct 3:
    the new tape value at the updated cell is a_step k›, and
    we need to show a_step k ≠ le› when the read value was
    in a no-LE window.›
  have no_le_contra:
      "k. ts_pre k (n_pre k)  le_tm M
               a_step k  le_tm M"
  proof (intro allI impI)
    fix k
    assume rd_not_le: "ts_pre k (n_pre k)  le_tm M"
    show "a_step k  le_tm M"
    proof
      assume a_le: "a_step k = le_tm M"
      have "(λk. ts_pre k (n_pre k)) k = le_tm M"
        by (rule valid_mttm_deltaLE_no_write[OF lu delta_mem a_le])
      hence "ts_pre k (n_pre k) = le_tm M" by simp
      with rd_not_le show False ..
    qed
  qed
  ― ‹Conjunct 3 regime pos k = 0› (no LE in cells
    Suc 0 .. card UNIV›): for each cell Suc i› in
    the window, case-split on whether the M-step's update site
    n_pre k› coincides with Suc i›.

    ∙› If not, the fun-update leaves mt_tape cM_n k (Suc i)›
    equal to ts_pre k (Suc i) = mt_tape cM_n' k (Suc i)›;
    the IH (no_le_n'›) closes the goal.

    ∙› If yes, the new value is a_step k›; the IH gives
    ts_pre k (n_pre k) = ts_pre k (Suc i) ≠ le_tm M›;
    the contrapositive no_le_contra› gives
    a_step k ≠ le_tm M›.›
  have no_le0_n:
      "k. pos k = 0
               (i. i < card (UNIV :: 'c set)
                         mt_tape cM_n k (Suc i)  le_tm M)"
  proof (intro allI impI allI impI)
    fix k i
    assume pos_0: "pos k = 0"
       and i_bd: "i < card (UNIV :: 'c set)"
    have ih_at: "ts_pre k (Suc i)  le_tm M"
    proof -
      from no_le_n' pos_0 i_bd
      have "mt_tape cM_n' k (Suc i)  le_tm M" by blast
      thus ?thesis using tp_n' by simp
    qed
    show "mt_tape cM_n k (Suc i)  le_tm M"
    proof (cases "Suc i = n_pre k")
      case False
      hence "mt_tape cM_n k (Suc i) = ts_pre k (Suc i)"
        using tp_n by simp
      thus ?thesis using ih_at by simp
    next
      case True
      hence tape_eq: "mt_tape cM_n k (Suc i) = a_step k"
        using tp_n by simp
      from True have "ts_pre k (n_pre k) = ts_pre k (Suc i)"
        by simp
      with ih_at have "ts_pre k (n_pre k)  le_tm M" by simp
      hence "a_step k  le_tm M" using no_le_contra by blast
      thus ?thesis using tape_eq by simp
    qed
  qed
  ― ‹Conjunct 3 regime pos k = 1›: same window shape
    Suc i› as pos = 0›, but the bound is doubled to
    2 * card UNIV›.  The proof shape is identical;
    only the bound on i› changes.›
  have no_le1_n:
      "k. pos k = 1
               (i. i < 2 * card (UNIV :: 'c set)
                         mt_tape cM_n k (Suc i)  le_tm M)"
  proof (intro allI impI allI impI)
    fix k i
    assume pos_1: "pos k = 1"
       and i_bd: "i < 2 * card (UNIV :: 'c set)"
    have ih_at: "ts_pre k (Suc i)  le_tm M"
    proof -
      from no_le_n' pos_1 i_bd
      have "mt_tape cM_n' k (Suc i)  le_tm M" by blast
      thus ?thesis using tp_n' by simp
    qed
    show "mt_tape cM_n k (Suc i)  le_tm M"
    proof (cases "Suc i = n_pre k")
      case False
      hence "mt_tape cM_n k (Suc i) = ts_pre k (Suc i)"
        using tp_n by simp
      thus ?thesis using ih_at by simp
    next
      case True
      hence tape_eq: "mt_tape cM_n k (Suc i) = a_step k"
        using tp_n by simp
      from True have "ts_pre k (n_pre k) = ts_pre k (Suc i)"
        by simp
      with ih_at have "ts_pre k (n_pre k)  le_tm M" by simp
      hence "a_step k  le_tm M" using no_le_contra by blast
      thus ?thesis using tape_eq by simp
    qed
  qed
  ― ‹Conjunct 3 regime pos k ≥ 2› (steady regime): the
    no-LE window spans 3 * card UNIV› cells starting at
    offset (pos k - 2) * card UNIV + 1›.  The proof shape
    is identical to the pos = 0›/pos = 1› cases; only
    the cell expression changes.›
  have no_le2_n:
      "k. pos k  2
               (i. i < 3 * card (UNIV :: 'c set)
                         mt_tape cM_n k
                              ((pos k - 2) * card (UNIV :: 'c set) + 1 + i)
                             le_tm M)"
  proof (intro allI impI allI impI)
    fix k i
    assume pos_ge: "pos k  2"
       and i_bd: "i < 3 * card (UNIV :: 'c set)"
    let ?j = "(pos k - 2) * card (UNIV :: 'c set) + 1 + i"
    have ih_at: "ts_pre k ?j  le_tm M"
    proof -
      from no_le_n' pos_ge i_bd
      have "mt_tape cM_n' k ?j  le_tm M" by blast
      thus ?thesis using tp_n' by simp
    qed
    show "mt_tape cM_n k ?j  le_tm M"
    proof (cases "?j = n_pre k")
      case False
      hence "mt_tape cM_n k ?j = ts_pre k ?j"
        using tp_n by simp
      thus ?thesis using ih_at by simp
    next
      case True
      hence tape_eq: "mt_tape cM_n k ?j = a_step k"
        using tp_n by simp
      from True have "ts_pre k (n_pre k) = ts_pre k ?j"
        by simp
      with ih_at have "ts_pre k (n_pre k)  le_tm M" by simp
      hence "a_step k  le_tm M" using no_le_contra by blast
      thus ?thesis using tape_eq by simp
    qed
  qed
  ― ‹Conjunct 3 (no-LE invariant at cM_n›): assemble the
    three regime sub-lemmas no_le0_n›, no_le1_n›,
    no_le2_n› into the dispatch-on-pos› shape that
    matches the lemma statement.›
  have no_le_n:
      "k. (pos k = 0
               (i. i < card (UNIV :: 'c set)
                         mt_tape cM_n k (Suc i)  le_tm M))
            (pos k = 1
                 (i. i < 2 * card (UNIV :: 'c set)
                           mt_tape cM_n k (Suc i)  le_tm M))
            (pos k  2
                 (i. i < 3 * card (UNIV :: 'c set)
                           mt_tape cM_n k
                                ((pos k - 2) * card (UNIV :: 'c set)
                                  + 1 + i)
                               le_tm M))"
    using no_le0_n no_le1_n no_le2_n by blast
  ― ‹Conjunct 2 regime pos k ≥ 2› (steady regime): apply
    ae_window_invariant_step› per tape.  Five ingredients:
    the IH-side invariant from window_n'›; the
    bp_advance_le› step from end_pos_n_eq›; the position
    bounds from bp_lt_max› and bp_gt_zero›; and the
    no-LE-at-head fact derived from the IH's no_le_n'›
    instantiated at the buffered-head's linearised offset
    (which lies inside the regime's no-LE window).›
  have win2_n:
      "k<k_tm M. pos k  2
               ae_window_invariant
                    (mt_tape cM_n k) (mt_pos cM_n k)
                    (end_pos_n k) (buf_n k)
                    ((pos k - 2) * card (UNIV :: 'c set) + 1)"
  proof (intro allI impI)
    fix k
    assume klt: "k < k_tm M"
    assume pos_ge: "pos k  2"
    from window_n'[rule_format, OF klt] pos_ge have wi_k:
        "ae_window_invariant (mt_tape cM_n' k) (mt_pos cM_n' k)
              (end_pos_n' k) (buf_n' k)
              ((pos k - 2) * card (UNIV :: 'c set) + 1)"
      unfolding ae_window_invariant_general_def by simp
    hence wi_k': "ae_window_invariant (ts_pre k) (n_pre k)
                    (end_pos_n' k) (buf_n' k)
                    ((pos k - 2) * card (UNIV :: 'c set) + 1)"
      using tp_n' ps_n' by simp
    have adv_k: "bp_advance_le (le_tm M) (ts_pre k (n_pre k))
                    (end_pos_n' k) (dir_step k) = Some (end_pos_n k)"
      using end_pos_n_eq by blast
    have bp_lt_k: "bp_linear (end_pos_n' k)
                      < 3 * card (UNIV :: 'c set) - 1"
      using bp_lt_max by blast
    have bp_pos_k: "0 < bp_linear (end_pos_n' k)"
      using bp_gt_zero by blast
    ― ‹No-LE-at-head: n_pre k = (pos k - 2)*c + 1 + j› where
      j = bp_linear (end_pos_n' k) < 3c›; instantiate the
      IH's no-LE window at this j›.›
    have no_le_k: "ts_pre k (n_pre k)  le_tm M"
    proof -
      let ?j = "bp_linear (end_pos_n' k)"
      from wi_k' have head_corr:
          "n_pre k = (pos k - 2) * card (UNIV :: 'c set) + 1 + ?j"
        unfolding ae_window_invariant_def by simp
      have j_lt: "?j < 3 * card (UNIV :: 'c set)"
        by (rule bp_linear_lt_3c)
      from no_le_n' pos_ge j_lt have
          "mt_tape cM_n' k
              ((pos k - 2) * card (UNIV :: 'c set) + 1 + ?j)
             le_tm M" by blast
      hence "ts_pre k
              ((pos k - 2) * card (UNIV :: 'c set) + 1 + ?j)
             le_tm M" using tp_n' by simp
      thus ?thesis using head_corr by simp
    qed
    have wi_step:
        "ae_window_invariant
              ((ts_pre k)(n_pre k := a_step k))
              (go_dir (dir_step k) (n_pre k))
              (end_pos_n k)
              (write_bp (buf_n' k) (end_pos_n' k) (a_step k))
              ((pos k - 2) * card (UNIV :: 'c set) + 1)"
      by (rule ae_window_invariant_step
                [OF wi_k' adv_k bp_lt_k bp_pos_k no_le_k])
    show "ae_window_invariant
              (mt_tape cM_n k) (mt_pos cM_n k)
              (end_pos_n k) (buf_n k)
              ((pos k - 2) * card (UNIV :: 'c set) + 1)"
      using wi_step tp_n ps_n buf_n_def by simp
  qed
  ― ‹Conjunct 2 regime pos k = 1› (LE-edge le1›): apply
    ae_window_invariant_le1_step› per tape.  The two LE-aware
    preconditions:

    ∙› a_le_k› (tM nM = le ⟹ a_step k = le ∧ dir_step k ∈ {N, R}›):
    derived from valid_mttm_deltaLE› applied to delta_mem› at tape k›.

    ∙› a_not_le_k› (tM nM ≠ le ⟹ a_step k ≠ le›):
    a per-tape instance of no_le_contra› already in scope.

    The no_le_win_k› precondition (no LE in cells 1..2c›)
    follows from no_le_n'›'s pos = 1› branch via tp_n'›.›
  have win1_n:
      "k<k_tm M. pos k = 1
               ae_window_invariant_le1
                    (mt_tape cM_n k) (mt_pos cM_n k)
                    (end_pos_n k) (buf_n k) (le_tm M)"
  proof (intro allI impI)
    fix k
    assume klt: "k < k_tm M"
    assume pos_1: "pos k = 1"
    from window_n'[rule_format, OF klt] pos_1 have wi_k:
        "ae_window_invariant_le1 (mt_tape cM_n' k) (mt_pos cM_n' k)
              (end_pos_n' k) (buf_n' k) (le_tm M)"
      unfolding ae_window_invariant_general_def by simp
    hence wi_k': "ae_window_invariant_le1 (ts_pre k) (n_pre k)
                    (end_pos_n' k) (buf_n' k) (le_tm M)"
      using tp_n' ps_n' by simp
    have adv_k: "bp_advance_le (le_tm M) (ts_pre k (n_pre k))
                    (end_pos_n' k) (dir_step k) = Some (end_pos_n k)"
      using end_pos_n_eq by blast
    have bp_lt_k: "bp_linear (end_pos_n' k)
                      < 3 * card (UNIV :: 'c set) - 1"
      using bp_lt_max by blast
    have bp_pos_k: "0 < bp_linear (end_pos_n' k)"
      using bp_gt_zero by blast
    have a_le_k:
        "ts_pre k (n_pre k) = le_tm M
             a_step k = le_tm M  dir_step k  {dir.N, dir.R}"
    proof -
      assume rd_le: "ts_pre k (n_pre k) = le_tm M"
      have "a_step k = le_tm M  dir_step k  {dir.N, dir.R}"
        by (rule valid_mttm_deltaLE[OF vM delta_mem, of k, OF rd_le])
      thus "a_step k = le_tm M  dir_step k  {dir.N, dir.R}" .
    qed
    have a_not_le_k:
        "ts_pre k (n_pre k)  le_tm M  a_step k  le_tm M"
      using no_le_contra by blast
    have no_le_win_k:
        "i. 0 < i  i  2 * card (UNIV :: 'c set)
                   ts_pre k i  le_tm M"
    proof (intro allI impI)
      fix i
      assume i_bd: "0 < i  i  2 * card (UNIV :: 'c set)"
      obtain j where j_eq: "i = Suc j" using i_bd by (cases i) auto
      have j_lt: "j < 2 * card (UNIV :: 'c set)"
        using i_bd j_eq by simp
      from no_le_n' pos_1 j_lt
      have "mt_tape cM_n' k (Suc j)  le_tm M" by blast
      thus "ts_pre k i  le_tm M" using tp_n' j_eq by simp
    qed
    have wi_step:
        "ae_window_invariant_le1
              ((ts_pre k)(n_pre k := a_step k))
              (go_dir (dir_step k) (n_pre k))
              (end_pos_n k)
              (write_bp (buf_n' k) (end_pos_n' k) (a_step k))
              (le_tm M)"
      by (rule ae_window_invariant_le1_step
                [OF wi_k' adv_k bp_lt_k bp_pos_k
                    a_le_k a_not_le_k no_le_win_k])
    show "ae_window_invariant_le1
              (mt_tape cM_n k) (mt_pos cM_n k)
              (end_pos_n k) (buf_n k) (le_tm M)"
      using wi_step tp_n ps_n buf_n_def by simp
  qed
  ― ‹Conjunct 2 regime pos k = 0› (LE-edge le0›): apply
    ae_window_invariant_le0_step› per tape.  Pattern identical
    to the pos = 1› call; only the lemma and the no-LE
    window range (cells 1..c›) differ.›
  have win0_n:
      "k<k_tm M. pos k = 0
               ae_window_invariant_le0
                    (mt_tape cM_n k) (mt_pos cM_n k)
                    (end_pos_n k) (buf_n k) (le_tm M)"
  proof (intro allI impI)
    fix k
    assume klt: "k < k_tm M"
    assume pos_0: "pos k = 0"
    from window_n'[rule_format, OF klt] pos_0 have wi_k:
        "ae_window_invariant_le0 (mt_tape cM_n' k) (mt_pos cM_n' k)
              (end_pos_n' k) (buf_n' k) (le_tm M)"
      unfolding ae_window_invariant_general_def by simp
    hence wi_k': "ae_window_invariant_le0 (ts_pre k) (n_pre k)
                    (end_pos_n' k) (buf_n' k) (le_tm M)"
      using tp_n' ps_n' by simp
    have adv_k: "bp_advance_le (le_tm M) (ts_pre k (n_pre k))
                    (end_pos_n' k) (dir_step k) = Some (end_pos_n k)"
      using end_pos_n_eq by blast
    have bp_lt_k: "bp_linear (end_pos_n' k)
                      < 3 * card (UNIV :: 'c set) - 1"
      using bp_lt_max by blast
    have bp_pos_k: "0 < bp_linear (end_pos_n' k)"
      using bp_gt_zero by blast
    have a_le_k:
        "ts_pre k (n_pre k) = le_tm M
             a_step k = le_tm M  dir_step k  {dir.N, dir.R}"
    proof -
      assume rd_le: "ts_pre k (n_pre k) = le_tm M"
      show "a_step k = le_tm M  dir_step k  {dir.N, dir.R}"
        by (rule valid_mttm_deltaLE[OF vM delta_mem, of k, OF rd_le])
    qed
    have a_not_le_k:
        "ts_pre k (n_pre k)  le_tm M  a_step k  le_tm M"
      using no_le_contra by blast
    have no_le_win_k:
        "i. 0 < i  i  card (UNIV :: 'c set)
                   ts_pre k i  le_tm M"
    proof (intro allI impI)
      fix i
      assume i_bd: "0 < i  i  card (UNIV :: 'c set)"
      obtain j where j_eq: "i = Suc j" using i_bd by (cases i) auto
      have j_lt: "j < card (UNIV :: 'c set)"
        using i_bd j_eq by simp
      from no_le_n' pos_0 j_lt
      have "mt_tape cM_n' k (Suc j)  le_tm M" by blast
      thus "ts_pre k i  le_tm M" using tp_n' j_eq by simp
    qed
    have wi_step:
        "ae_window_invariant_le0
              ((ts_pre k)(n_pre k := a_step k))
              (go_dir (dir_step k) (n_pre k))
              (end_pos_n k)
              (write_bp (buf_n' k) (end_pos_n' k) (a_step k))
              (le_tm M)"
      by (rule ae_window_invariant_le0_step
                [OF wi_k' adv_k bp_lt_k bp_pos_k
                    a_le_k a_not_le_k no_le_win_k])
    show "ae_window_invariant_le0
              (mt_tape cM_n k) (mt_pos cM_n k)
              (end_pos_n k) (buf_n k) (le_tm M)"
      using wi_step tp_n ps_n buf_n_def by simp
  qed
  ― ‹Conjunct 2 (window invariant at cM_n›): assemble the
    three regime sub-lemmas win0_n›, win1_n›,
    win2_n› into the dispatch-on-pos› shape that
    matches the lemma statement
    (ae_window_invariant_general›).›
  have window_n:
      "k<k_tm M. ae_window_invariant_general
              (mt_tape cM_n k) (mt_pos cM_n k)
              (end_pos_n k) (buf_n k) (pos k) (le_tm M)"
  proof (intro allI impI)
    fix k
    assume klt: "k < k_tm M"
    show "ae_window_invariant_general
            (mt_tape cM_n k) (mt_pos cM_n k)
            (end_pos_n k) (buf_n k) (pos k) (le_tm M)"
      unfolding ae_window_invariant_general_def
      using win0_n win1_n win2_n klt by blast
  qed
  ― ‹Padding shadow invariant at step Suc n'›: empty
    tapes k ≥ k_tm M› keep a blank home block and a head
    parked at (AE_Home, ofs k)›.  Preserved from the IH's
    pad_n'› by the M-step's δ›-support (read = a' = bl›,
    d = N› past tape count): the head stays put under bp_advance›
    of a dir.N› step, and writing bl› into the blank home
    is idempotent.›
  have pad_n:
      "kk_tm M. fst (snd (buf_n k)) = bl_block (bl_tm M)
               end_pos_n k = (AE_Home, ofs k)"
  proof (intro allI impI)
    fix k
    assume kge: "k_tm M  k"
    from pad_n'[rule_format, OF kge]
    have ph: "fst (snd (buf_n' k)) = bl_block (bl_tm M)"
      and ep: "end_pos_n' k = (AE_Home, ofs k)" by simp_all
    from valid_mttm_delta_support[OF vM delta_mem kge]
    have rd: "ts_pre k (n_pre k) = bl_tm M"
      and wr: "a_step k = bl_tm M"
      and dr: "dir_step k = dir.N" by simp_all
    have ep_n: "end_pos_n k = (AE_Home, ofs k)"
    proof -
      have adv: "bp_advance_le (le_tm M) (ts_pre k (n_pre k))
                    (end_pos_n' k) (dir_step k) = Some (end_pos_n k)"
        using end_pos_n_eq by blast
      have "bp_advance_le (le_tm M) (bl_tm M) (AE_Home, ofs k) dir.N
              = Some (AE_Home, ofs k)"
        by (simp add: bp_advance_le_def bp_advance_def)
      thus ?thesis using adv rd ep dr by simp
    qed
    have buf_n_k: "fst (snd (buf_n k)) = bl_block (bl_tm M)"
    proof -
      obtain l h r where blk: "buf_n' k = (l, h, r)"
        by (cases "buf_n' k") auto
      from ph blk have h_eq: "h = bl_block (bl_tm M)" by simp
      have "buf_n k = (l, h(ofs k := bl_tm M), r)"
        using blk ep wr by (simp add: buf_n_def write_bp_def)
      hence "fst (snd (buf_n k)) = h(ofs k := bl_tm M)" by simp
      also have " = bl_block (bl_tm M)"
        using h_eq by (simp add: bl_block_def fun_eq_iff)
      finally show ?thesis .
    qed
    show "fst (snd (buf_n k)) = bl_block (bl_tm M)
             end_pos_n k = (AE_Home, ofs k)"
      using buf_n_k ep_n by simp
  qed
  ― ‹Final show ?case› assembly: package the five
    discharged conjuncts (coupled_chain›, window_n›,
    no_le_n›, left_n›, bp_bound_n›) into the
    existential output via buf_n› and end_pos_n›.›
  show ?case
  proof (intro exI [where x = buf_n] exI [where x = end_pos_n] conjI)
    show "((qM, buf_full, λk. (AE_Home, ofs k)),
            (mt_state cM_n, buf_n, end_pos_n))
               (m_step_buffered M) ^^ Suc n'"
      by (rule coupled_chain)
    show "k<k_tm M. ae_window_invariant_general
                (mt_tape cM_n k) (mt_pos cM_n k)
                (end_pos_n k) (buf_n k) (pos k) (le_tm M)"
      by (rule window_n)
    show "k. (pos k = 0
                 (i. i < card (UNIV :: 'c set)
                           mt_tape cM_n k (Suc i)  le_tm M))
              (pos k = 1
                   (i. i < 2 * card (UNIV :: 'c set)
                             mt_tape cM_n k (Suc i)  le_tm M))
              (pos k  2
                   (i. i < 3 * card (UNIV :: 'c set)
                             mt_tape cM_n k
                                  ((pos k - 2) * card (UNIV :: 'c set)
                                    + 1 + i)
                                 le_tm M))"
      by (rule no_le_n)
    show "k<k_tm M. pos k = 0
                 fst (buf_n k)  LE_block (le_tm M)"
      by (rule left_n)
    show "k. card (UNIV :: 'c set)  bp_linear (end_pos_n k) + Suc n'
               bp_linear (end_pos_n k)
                    < 2 * card (UNIV :: 'c set) + Suc n'"
      by (rule bp_bound_n)
    show "kk_tm M. fst (snd (buf_n k)) = bl_block (bl_tm M)
                 end_pos_n k = (AE_Home, ofs k)"
      by (rule pad_n)
  qed
qed


text ‹Per-tape unified companion of
  ae_m_steps_buffered_correct_trace›, _le0›, and
  _le1›.  A wrapper over
  ae_coupled_run_aux_general›: builds the
  m_steps_buffered› step (= relpow plus
  kM ≤ c› and end-or-halt) and re-packages the aux's
  existential into an obtains›-style witness.

  The hypothesis shape matches the three siblings' wrapper
  pattern: a per-tape regime selector pos›, the per-tape
  hybrid window invariant, the per-tape regime-guarded
  no_le›, and the pos = 0›-conditional left-slot
  guard.  Output conjuncts mirror the input, with the buffered
  config existentially bound.›

lemma ae_m_steps_buffered_correct_trace_general:
  fixes M :: "('q, 'a) mttm"
    and qM :: 'q
    and tsM :: "nat  nat  'a"
    and nM :: "nat  nat"
    and ofs :: "nat  ('c :: enum)"
    and buf_full :: "nat  (('c  'a) × ('c  'a) × ('c  'a))"
    and pos :: "nat  nat"
    and kM :: nat
    and cM_k :: "('a, 'q) mt_config"
  assumes vM:        "valid_mttm M"
      and lu:        "le_unique M"
      and qM_in:     "qM  Q_tm M"
      and window:    "k<k_tm M. ae_window_invariant_general (tsM k) (nM k)
                            (AE_Home, ofs k) (buf_full k) (pos k) (le_tm M)"
      and pad_home:  "kk_tm M. fst (snd (buf_full k)) = bl_block (bl_tm M)"
      and no_le:
            "k. (pos k = 0
                     (i. i < card (UNIV :: 'c set)
                               tsM k (Suc i)  le_tm M))
                  (pos k = 1
                       (i. i < 2 * card (UNIV :: 'c set)
                                 tsM k (Suc i)  le_tm M))
                  (pos k  2
                       (i. i < 3 * card (UNIV :: 'c set)
                                 tsM k
                                      ((pos k - 2) * card (UNIV :: 'c set)
                                        + 1 + i)
                                     le_tm M))"
      and trace:     "(ConfigM qM tsM nM, cM_k)
                         mttm_step (delta_tm M) ^^ kM"
      and kM_le:     "kM  card (UNIV :: 'c set)"
      and end_or_halt:
            "kM = card (UNIV :: 'c set)
               mt_state cM_k  {t_tm M, r_tm M}"
      and left_not_le_pos0:
            "k<k_tm M. pos k = 0  fst (buf_full k)  LE_block (le_tm M)"
  obtains q_out buf' end_pos where
      "((qM, buf_full, λk. (AE_Home, ofs k)),
         (q_out, buf', end_pos))  m_steps_buffered M"
    and "q_out = mt_state cM_k"
    and "k<k_tm M. ae_window_invariant_general
              (mt_tape cM_k k) (mt_pos cM_k k)
              (end_pos k) (buf' k) (pos k) (le_tm M)"
    and "k. (pos k = 0
                 (i. i < card (UNIV :: 'c set)
                           mt_tape cM_k k (Suc i)  le_tm M))
              (pos k = 1
                   (i. i < 2 * card (UNIV :: 'c set)
                             mt_tape cM_k k (Suc i)  le_tm M))
              (pos k  2
                   (i. i < 3 * card (UNIV :: 'c set)
                             mt_tape cM_k k
                                  ((pos k - 2) * card (UNIV :: 'c set)
                                    + 1 + i)
                                 le_tm M))"
    and "k<k_tm M. pos k = 0
               fst (buf' k)  LE_block (le_tm M)"
proof -
  have ae_result_general:
      "buf' end_pos.
          ((qM, buf_full, λk. (AE_Home, ofs k)),
           (mt_state cM_k, buf', end_pos))
               (m_step_buffered M) ^^ kM
         (k<k_tm M. ae_window_invariant_general
                  (mt_tape cM_k k) (mt_pos cM_k k)
                  (end_pos k) (buf' k) (pos k) (le_tm M))
         (k. (pos k = 0
                   (i. i < card (UNIV :: 'c set)
                             mt_tape cM_k k (Suc i)  le_tm M))
                (pos k = 1
                     (i. i < 2 * card (UNIV :: 'c set)
                               mt_tape cM_k k (Suc i)  le_tm M))
                (pos k  2
                     (i. i < 3 * card (UNIV :: 'c set)
                               mt_tape cM_k k
                                    ((pos k - 2) * card (UNIV :: 'c set)
                                      + 1 + i)
                                   le_tm M)))
         (k<k_tm M. pos k = 0
                   fst (buf' k)  LE_block (le_tm M))
         (k. card (UNIV :: 'c set)  bp_linear (end_pos k) + kM
                 bp_linear (end_pos k)
                      < 2 * card (UNIV :: 'c set) + kM)
         (kk_tm M. fst (snd (buf' k)) = bl_block (bl_tm M)
                 end_pos k = (AE_Home, ofs k))"
    by (rule ae_coupled_run_aux_general[OF vM lu qM_in window pad_home trace kM_le
                                           no_le left_not_le_pos0])
  obtain buf' end_pos where
      coupled: "((qM, buf_full, λk. (AE_Home, ofs k)),
                 (mt_state cM_k, buf', end_pos))
                     (m_step_buffered M) ^^ kM"
    and new_window:
        "k<k_tm M. ae_window_invariant_general
              (mt_tape cM_k k) (mt_pos cM_k k)
              (end_pos k) (buf' k) (pos k) (le_tm M)"
    and post_no_le:
        "k. (pos k = 0
                 (i. i < card (UNIV :: 'c set)
                           mt_tape cM_k k (Suc i)  le_tm M))
              (pos k = 1
                   (i. i < 2 * card (UNIV :: 'c set)
                             mt_tape cM_k k (Suc i)  le_tm M))
              (pos k  2
                   (i. i < 3 * card (UNIV :: 'c set)
                             mt_tape cM_k k
                                  ((pos k - 2) * card (UNIV :: 'c set)
                                    + 1 + i)
                                 le_tm M))"
    and post_left_not_le_pos0:
        "k<k_tm M. pos k = 0
               fst (buf' k)  LE_block (le_tm M)"
    and bp_bound:
        "k. card (UNIV :: 'c set)  bp_linear (end_pos k) + kM
               bp_linear (end_pos k)
                    < 2 * card (UNIV :: 'c set) + kM"
    using ae_result_general by blast
  have buffered_full:
      "((qM, buf_full, λk. (AE_Home, ofs k)),
        (mt_state cM_k, buf', end_pos))  m_steps_buffered M"
    unfolding m_steps_buffered_def
    using coupled kM_le end_or_halt by auto
  show thesis
  proof (rule that[where q_out = "mt_state cM_k"
                     and buf' = buf' and end_pos = end_pos])
    show "((qM, buf_full, λk. (AE_Home, ofs k)),
           (mt_state cM_k, buf', end_pos))  m_steps_buffered M"
      using buffered_full .
    show "mt_state cM_k = mt_state cM_k" by (rule refl)
    show "k<k_tm M. ae_window_invariant_general
              (mt_tape cM_k k) (mt_pos cM_k k)
              (end_pos k) (buf' k) (pos k) (le_tm M)"
      using new_window .
    show "k. (pos k = 0
                 (i. i < card (UNIV :: 'c set)
                           mt_tape cM_k k (Suc i)  le_tm M))
              (pos k = 1
                   (i. i < 2 * card (UNIV :: 'c set)
                             mt_tape cM_k k (Suc i)  le_tm M))
              (pos k  2
                   (i. i < 3 * card (UNIV :: 'c set)
                             mt_tape cM_k k
                                  ((pos k - 2) * card (UNIV :: 'c set)
                                    + 1 + i)
                                 le_tm M))"
      using post_no_le .
    show "k<k_tm M. pos k = 0
                 fst (buf' k)  LE_block (le_tm M)"
      using post_left_not_le_pos0 .
  qed
qed

end