------------------------------------------------------------------------
-- Soundness of algorithmic equality (in the absence of equality
-- reflection)
------------------------------------------------------------------------

open import Definition.Typed.Restrictions
open import Graded.Modality

module Definition.Conversion.Soundness
  {a} {M : Set a}
  {š•„ : Modality M}
  (R : Type-restrictions š•„)
  (open Type-restrictions R)
  ⦃ no-equality-reflection : No-equality-reflection ⦄
  where

open import Definition.Untyped M
open import Definition.Untyped.Neutral.Atomic M type-variant
open import Definition.Untyped.Sup R
open import Definition.Untyped.Whnf M type-variant
open import Definition.Typed R
open import Definition.Typed.EqRelInstance R using (eqRelInstance)
open import Definition.Typed.EqualityRelation.Instance R
open import Definition.Typed.Inversion R
open import Definition.Typed.Properties R
import Definition.Typed.Reasoning.Term R as TmR
import Definition.Typed.Reasoning.Type R as TyR
open import Definition.Typed.Stability R
open import Definition.Typed.Syntactic R
open import Definition.Typed.Well-formed R
open import Definition.Conversion R
open import Definition.Conversion.Whnf R
open import Definition.Conversion.Level R
open import Definition.Typed.Consequences.Injectivity R
open import Definition.Typed.Consequences.Reduction R
open import Definition.Typed.Consequences.NeTypeEq R

open import Tools.Bool
open import Tools.Function
open import Tools.List hiding (_∷_)
open import Tools.Nat as N using (Nat)
open import Tools.Product
import Tools.PropositionalEquality as PE

private
  variable
    Ī“         : Cons _ _
    A B l₁ lā‚‚ : Term _
    d         : Bool

mutual
  -- Algorithmic equality of neutrals is well-formed.
  soundness~↑ : āˆ€ {k l A} → Ī“ ⊢ k ~ l ↑ A → Ī“ ⊢ k ≔ l ∷ A
  soundness~↑ (var-refl x x≔y) =
    PE.subst (Ī» y → _ ⊢ _ ≔ var y ∷ _) x≔y (refl x)
  soundness~↑ (defn-refl ⊢α Ī±ā†¦āŠ˜ α≔β) =
    PE.subst (Ī» β → _ ⊢ _ ≔ defn β ∷ _) α≔β (refl ⊢α)
  soundness~↑ (lower-cong x) = lower-cong (soundness~↓ x)
  soundness~↑ (app-cong k~l x₁) =
    app-cong (soundness~↓ k~l) (soundnessConv↑Term x₁)
  soundness~↑ (fst-cong x) =
    let p≔ = soundness~↓ x
        ⊢ΣFG = proj₁ (syntacticEqTerm p≔)
        _ , ⊢G , _ = inversion-ΠΣ ⊢ΣFG
    in  fst-cong ⊢G p≔
  soundness~↑ (snd-cong x) =
    let p≔ = soundness~↓ x
        ⊢ΣFG = proj₁ (syntacticEqTerm p≔)
        _ , ⊢G , _ = inversion-ΠΣ ⊢ΣFG
    in  snd-cong ⊢G p≔
  soundness~↑ (natrec-cong x₁ xā‚‚ xā‚ƒ k~l) =
    let F≔G = soundnessConv↑ x₁ in
    natrec-cong F≔G (soundnessConv↑Term xā‚‚) (soundnessConv↑Term xā‚ƒ)
      (soundness~↓ k~l)
  soundness~↑ (prodrec-cong x x₁ xā‚‚) =
    let C≔E = soundnessConv↑ x
        g≔h = soundness~↓ x₁
        u≔v = soundnessConv↑Term xā‚‚
        _ , _ , ok = inversion-ΠΣ (proj₁ (syntacticEqTerm g≔h))
    in  prodrec-cong C≔E g≔h u≔v ok
  soundness~↑ (emptyrec-cong x₁ k~l) =
    emptyrec-cong (soundnessConv↑ x₁) (soundness~↓ k~l)
  soundness~↑ (unitrec-cong x x₁ xā‚‚ no-Ī·) =
    let F≔H = soundnessConv↑ x
        k≔l = soundness~↓ x₁
        u≔v = soundnessConv↑Term xā‚‚
        ok = inversion-Unit (proj₁ (syntacticEqTerm k≔l))
    in  unitrec-cong F≔H k≔l u≔v ok no-Ī·
  soundness~↑ (J-cong A₁≔Aā‚‚ t₁≔tā‚‚ B₁≔Bā‚‚ u₁≔uā‚‚ v₁≔vā‚‚ w₁~wā‚‚ ≔Id) =
    case soundnessConv↑ A₁≔Aā‚‚ of Ī» {
      A₁≔Aā‚‚ →
    case soundnessConv↑Term t₁≔tā‚‚ of Ī» {
      t₁≔tā‚‚ →
    J-cong A₁≔Aā‚‚
      (syntacticEqTerm t₁≔tā‚‚ .projā‚‚ .proj₁) t₁≔tā‚‚ (soundnessConv↑ B₁≔Bā‚‚)
      (soundnessConv↑Term u₁≔uā‚‚) (soundnessConv↑Term v₁≔vā‚‚)
      (conv (soundness~↓ w₁~wā‚‚) ≔Id) }}
  soundness~↑ (K-cong A₁≔Aā‚‚ t₁≔tā‚‚ B₁≔Bā‚‚ u₁≔uā‚‚ v₁~vā‚‚ ≔Id ok) =
    K-cong (soundnessConv↑ A₁≔Aā‚‚) (soundnessConv↑Term t₁≔tā‚‚)
      (soundnessConv↑ B₁≔Bā‚‚) (soundnessConv↑Term u₁≔uā‚‚)
      (conv (soundness~↓ v₁~vā‚‚) ≔Id) ok
  soundness~↑ ([]-cong-cong l₁≔lā‚‚ A₁≔Aā‚‚ t₁≔tā‚‚ u₁≔uā‚‚ v₁~vā‚‚ ≔Id ok) =
    []-cong-cong (soundnessConv↑Level l₁≔lā‚‚) (soundnessConv↑ A₁≔Aā‚‚)
      (soundnessConv↑Term t₁≔tā‚‚) (soundnessConv↑Term u₁≔uā‚‚)
      (conv (soundness~↓ v₁~vā‚‚) ≔Id) ok

  -- Algorithmic equality of neutrals in WHNF is well-formed.
  soundness~↓ : āˆ€ {k l A} → Ī“ ⊢ k ~ l ↓ A → Ī“ ⊢ k ≔ l ∷ A
  soundness~↓ ([~] A₁ (D , _) k~l) = conv (soundness~↑ k~l) (subset* D)

  soundness~∷ : āˆ€ {k l A} → Ī“ ⊢ k ~ l ∷ A → Ī“ ⊢ k ≔ l ∷ A
  soundness~∷ (↑ A≔B k~l) = conv (soundness~↑ k~l) (sym A≔B)

  -- Algorithmic equality of types is well-formed.
  soundnessConv↑ : āˆ€ {A B} → Ī“ ⊢ A [conv↑] B → Ī“ ⊢ A ≔ B
  soundnessConv↑ ([↑] _ _ (D , _) (D′ , _) A′<>B′) =
    trans (subset* D) (trans (soundnessConv↓ A′<>B′) (sym (subset* D′)))

  -- Algorithmic equality of types in WHNF is well-formed.
  soundnessConv↓ : āˆ€ {A B} → Ī“ ⊢ A [conv↓] B → Ī“ ⊢ A ≔ B
  soundnessConv↓ (Level-refl ok āŠ¢Ī“) = refl (Levelⱼ′ ok āŠ¢Ī“)
  soundnessConv↓ (U-cong l₁≔lā‚‚) =
    U-cong-āŠ¢ā‰” (soundnessConv↑Level l₁≔lā‚‚)
  soundnessConv↓ (Lift-cong l₁≔lā‚‚ F≔H) =
    Lift-cong (soundnessConv↑Level l₁≔lā‚‚) (soundnessConv↑ F≔H)
  soundnessConv↓ (ā„•-refl āŠ¢Ī“) = refl (āŠ¢ā„• āŠ¢Ī“)
  soundnessConv↓ (Empty-refl āŠ¢Ī“) = refl (⊢Empty āŠ¢Ī“)
  soundnessConv↓ (Unit-refl āŠ¢Ī“ ok) = refl (⊢Unit āŠ¢Ī“ ok)
  soundnessConv↓ (ne x) = univ (soundness~↓ x)
  soundnessConv↓ (ΠΣ-cong A₁≔Aā‚‚ B₁≔Bā‚‚ ok) =
    ΠΣ-cong (soundnessConv↑ A₁≔Aā‚‚) (soundnessConv↑ B₁≔Bā‚‚) ok
  soundnessConv↓ (Id-cong A₁≔Aā‚‚ t₁≔tā‚‚ u₁≔uā‚‚) =
    Id-cong (soundnessConv↑ A₁≔Aā‚‚) (soundnessConv↑Term t₁≔tā‚‚)
      (soundnessConv↑Term u₁≔uā‚‚)

  -- Algorithmic equality of terms is well-formed.
  soundnessConv↑Term : āˆ€ {a b A} → Ī“ ⊢ a [conv↑] b ∷ A → Ī“ ⊢ a ≔ b ∷ A
  soundnessConv↑Term ([↑]ā‚œ B t′ u′ (D , _) (d , _) (d′ , _) t<>u) =
    conv (trans (subset*Term d)
                (trans (soundnessConv↓Term t<>u)
                       (sym′ (subset*Term d′))))
         (sym (subset* D))

  -- Soundness for _⊢_[conv↑]_∷Level.
  soundnessConv↑Level : Ī“ ⊢ l₁ [conv↑] lā‚‚ ∷Level → Ī“ ⊢ l₁ ≔ lā‚‚ ∷Level
  soundnessConv↑Level (literal! not-ok āŠ¢Ī“ l-lit) =
    literal not-ok āŠ¢Ī“ l-lit
  soundnessConv↑Level (term ok l₁≔lā‚‚) =
    term ok (soundnessConv↑Term l₁≔lā‚‚)

  -- Algorithmic equality of terms in WHNF is well-formed.
  soundnessConv↓Term : āˆ€ {a b A} → Ī“ ⊢ a [conv↓] b ∷ A → Ī“ ⊢ a ≔ b ∷ A
  soundnessConv↓Term (Level-ins x) = soundnessConv↓Level x
  soundnessConv↓Term (ā„•-ins x) = soundness~↓ x
  soundnessConv↓Term (Empty-ins x) = soundness~↓ x
  soundnessConv↓Term (UnitŹ·-ins _ t~u) = soundness~↓ t~u
  soundnessConv↓Term (Σʷ-ins x x₁ xā‚‚) =
    let a≔b = soundness~↓ xā‚‚
        _ , neA , _ = ne~↓ xā‚‚
        _ , ⊢a , _ = syntacticEqTerm a≔b
        Σ≔Σ′ = neTypeEq (ne⁻ neA) x ⊢a
    in  conv a≔b (sym Σ≔Σ′)
  soundnessConv↓Term (ne-ins t u x x₁) =
    let _ , neA , _ = ne~↓ x₁
        _ , t∷M , _ = syntacticEqTerm (soundness~↓ x₁)
        M≔A = neTypeEq (ne⁻ neA) t∷M t
    in  conv (soundness~↓ x₁) M≔A
  soundnessConv↓Term (univ ⊢A ⊢B A≔B) =
    soundnessConv↓-U ⊢A ⊢B A≔B .proj₁
  soundnessConv↓Term (Lift-Ī· x x₁ xā‚‚ xā‚ƒ xā‚„) =
    Lift-η′ x x₁ (soundnessConv↑Term xā‚„)
  soundnessConv↓Term (zero-refl āŠ¢Ī“) = refl (zeroā±¼ āŠ¢Ī“)
  soundnessConv↓Term (starŹ·-refl āŠ¢Ī“ ok _) =
    refl (starā±¼ āŠ¢Ī“ ok)
  soundnessConv↓Term (suc-cong c) = suc-cong (soundnessConv↑Term c)
  soundnessConv↓Term (prod-cong x₁ xā‚‚ xā‚ƒ ok) =
    prod-cong x₁ (soundnessConv↑Term xā‚‚)
      (soundnessConv↑Term xā‚ƒ) ok
  soundnessConv↓Term (Ī·-eq x x₁ y y₁ c) =
    Ī·-eq′ x x₁ (soundnessConv↑Term c)
  soundnessConv↓Term (Ī£-Ī· ⊢p ⊢r pProd rProd fstConv sndConv) =
    let fst≔ = soundnessConv↑Term fstConv
        snd≔ = soundnessConv↑Term sndConv
    in  Ī£-η′ ⊢p ⊢r fst≔ snd≔
  soundnessConv↓Term (Ī·-unit [a] [b] _ _ Ī·) =
    Ī·-unit [a] [b] Ī·
  soundnessConv↓Term
    {Ī“} (Id-ins {v₁} {t} {u} {A} {A′} {t′} {u′} ⊢v₁ v₁~vā‚‚) =
    case soundness~↓ v₁~vā‚‚ of Ī» {
      v₁≔vā‚‚ →
    conv v₁≔vā‚‚
      (                                          $⟨ syntacticEqTerm v₁≔vā‚‚ .projā‚‚ .proj₁ , ⊢v₁ ⟩
       Ī“ ⊢ v₁ ∷ Id A′ t′ u′ Ɨ Ī“ ⊢ v₁ ∷ Id A t u  ā†’āŸØ uncurry (neTypeEq (ne⁻ (ne~↓ v₁~vā‚‚ .projā‚‚ .proj₁))) ⟩
       Ī“ ⊢ Id A′ t′ u′ ≔ Id A t u                ā–”) }
  soundnessConv↓Term (rfl-refl t≔u) =
    refl (rflⱼ′ t≔u)

  -- A variant of soundnessConv↓.

  soundnessConv↓-U :
    Ī“ ⊢ A ∷ U l₁ →
    Ī“ ⊢ B ∷ U lā‚‚ →
    Ī“ ⊢ A [conv↓] B →
    Ī“ ⊢ A ≔ B ∷ U l₁ Ɨ Ī“ ⊢ l₁ ≔ lā‚‚ ∷Level
  soundnessConv↓-U {l₁} {lā‚‚} ⊢A ⊢B (ne {l} A~B) =
    let A≔B             = soundness~↓ A~B
        _ , A-ne , B-ne = ne~↓ A~B
        _ , ⊢A′ , ⊢B′   = syntacticEqTerm A≔B
        U≔U₁            = neTypeEq (ne⁻ A-ne) ⊢A′ ⊢A
        U≔Uā‚‚            = neTypeEq (ne⁻ B-ne) ⊢B′ ⊢B
    in
      conv A≔B U≔U₁
    , U-injectivity
        (U l₁  ā‰”Ė˜āŸØ U≔U₁ ⟩⊢
         U l   ā‰”āŸØ U≔Uā‚‚ āŸ©āŠ¢āˆŽ
         U lā‚‚  āˆŽ)
    where
    open TyR
  soundnessConv↓-U {l₁} {lā‚‚} ⊢Level₁ ⊢Levelā‚‚ (Level-refl _ _) =
      refl ⊢Level₁
    , U-injectivity
        (U l₁     ā‰”āŸØ inversion-Level ⊢Level₁ .proj₁ ⟩⊢
         U zeroᵘ  ā‰”Ė˜āŸØ inversion-Level ⊢Levelā‚‚ .proj₁ āŸ©āŠ¢āˆŽ
         U lā‚‚     āˆŽ)
    where
    open TyR
  soundnessConv↓-U
    {l₁} {lā‚‚} ⊢U₁ ⊢Uā‚‚ (U-cong {l₁ = lā‚ƒ} {lā‚‚ = lā‚„} lā‚ƒā‰”lā‚„) =
    let lā‚ƒā‰”lā‚„ = soundnessConv↑Level lā‚ƒā‰”lā‚„
        U≔U₁ = inversion-U ⊢U₁
        U≔Uā‚‚ = inversion-U ⊢Uā‚‚
    in
      conv (U-cong-āŠ¢ā‰”āˆ· lā‚ƒā‰”lā‚„) (sym U≔U₁)
    , U-injectivity
        (U l₁        ā‰”āŸØ inversion-U ⊢U₁ ⟩⊢
         U (sucᵘ lā‚ƒ) ā‰”āŸØ U-cong-āŠ¢ā‰” (sucᵘ-cong-āŠ¢ā‰”āˆ·L lā‚ƒā‰”lā‚„) ⟩⊢
         U (sucᵘ lā‚„) ā‰”Ė˜āŸØ inversion-U ⊢Uā‚‚ āŸ©āŠ¢āˆŽ
         U lā‚‚        āˆŽ)
    where
    open TyR
  soundnessConv↓-U {l₁} {lā‚‚} ⊢Lift₁ ⊢Liftā‚‚ (Lift-cong {l₁ = lā‚ƒ} {lā‚‚ = lā‚„} lā‚ƒā‰”lā‚„ F≔H) =
    let k₁ , _ , ⊢F , U₁≔ = inversion-Lift∷ ⊢Lift₁
        kā‚‚ , _ , ⊢H , U₂≔ = inversion-Lift∷ ⊢Liftā‚‚
        lā‚ƒā‰”lā‚„ = soundnessConv↑Level lā‚ƒā‰”lā‚„
        F≔H , k₁≔kā‚‚ = soundnessConv↑-U ⊢F ⊢H F≔H
    in
      conv (Lift-cong′ lā‚ƒā‰”lā‚„ F≔H) (sym U₁≔)
    , U-injectivity
        (U l₁             ā‰”āŸØ U₁≔ ⟩⊢
         U (k₁ supįµ˜ā‚— lā‚ƒ)  ā‰”āŸØ U-cong-āŠ¢ā‰” (supįµ˜ā‚—-cong k₁≔kā‚‚ lā‚ƒā‰”lā‚„) ⟩⊢
         U (kā‚‚ supįµ˜ā‚— lā‚„)  ā‰”Ė˜āŸØ U₂≔ āŸ©āŠ¢āˆŽ
         U lā‚‚             āˆŽ)
    where
    open TyR
  soundnessConv↓-U {l₁} {lā‚‚} ⊢ΠΣA₁Aā‚‚ ⊢ΠΣB₁Bā‚‚ (ΠΣ-cong A₁≔B₁ A₂≔Bā‚‚ ok) =
    let lā‚ƒ , ⊢lā‚ƒ , ⊢A₁ , ⊢Aā‚‚ , U≔U₁ , _ = inversion-ΠΣ-U ⊢ΠΣA₁Aā‚‚
        lā‚„ , ⊢lā‚„ , ⊢B₁ , ⊢Bā‚‚ , U≔Uā‚‚ , _ = inversion-ΠΣ-U ⊢ΠΣB₁Bā‚‚
        A₁≔B₁ , lā‚ƒā‰”lā‚„            = soundnessConv↑-U ⊢A₁ ⊢B₁ A₁≔B₁
        A₂≔Bā‚‚ , _                =
          soundnessConv↑-U ⊢Aā‚‚
            (stabilityTerm (refl-āˆ™ (sym (univ A₁≔B₁))) ⊢Bā‚‚) A₂≔Bā‚‚
    in
      conv (ΠΣ-cong ⊢lā‚ƒ A₁≔B₁ A₂≔Bā‚‚ ok) (sym U≔U₁)
    , U-injectivity
        (U l₁  ā‰”āŸØ U≔U₁ ⟩⊢
         U lā‚ƒ  ā‰”āŸØ U-cong-āŠ¢ā‰” lā‚ƒā‰”lā‚„ ⟩⊢
         U lā‚„  ā‰”Ė˜āŸØ U≔Uā‚‚ āŸ©āŠ¢āˆŽ
         U lā‚‚  āˆŽ)
    where
    open TyR
  soundnessConv↓-U {l₁} {lā‚‚} ⊢Empty₁ ⊢Emptyā‚‚ (Empty-refl _) =
      refl ⊢Empty₁
    , U-injectivity
        (U l₁    ā‰”āŸØ inversion-Empty ⊢Empty₁ ⟩⊢
         U zeroᵘ ā‰”Ė˜āŸØ inversion-Empty ⊢Emptyā‚‚ āŸ©āŠ¢āˆŽ
         U lā‚‚    āˆŽ)
    where
    open TyR
  soundnessConv↓-U {l₁} {lā‚‚} ⊢Unit₁ ⊢Unitā‚‚ (Unit-refl āŠ¢Ī“ ok) =
    let U≔U₁ , _ = inversion-Unit-U ⊢Unit₁
        U≔Uā‚‚ , _ = inversion-Unit-U ⊢Unitā‚‚
    in
      refl (conv (Unitā±¼ āŠ¢Ī“ ok) (sym U≔U₁))
    , U-injectivity
        (U l₁     ā‰”āŸØ U≔U₁ ⟩⊢
         U zeroᵘ  ā‰”Ė˜āŸØ U≔Uā‚‚ āŸ©āŠ¢āˆŽ
         U lā‚‚     āˆŽ)
    where
    open TyR
  soundnessConv↓-U {l₁} {lā‚‚} āŠ¢ā„•ā‚ āŠ¢ā„•ā‚‚ (ā„•-refl _) =
      refl āŠ¢ā„•ā‚
    , U-injectivity
        (U l₁     ā‰”āŸØ inversion-ā„• āŠ¢ā„•ā‚ ⟩⊢
         U zeroᵘ  ā‰”Ė˜āŸØ inversion-ā„• āŠ¢ā„•ā‚‚ āŸ©āŠ¢āˆŽ
         U lā‚‚     āˆŽ)
    where
    open TyR
  soundnessConv↓-U
    {l₁} {lā‚‚} ⊢IdAt₁tā‚‚ ⊢IdBu₁uā‚‚ (Id-cong A≔B t₁≔u₁ t₂≔uā‚‚) =
    let lā‚ƒ , ⊢A , ⊢t₁ , ⊢tā‚‚ , U≔U₁ = inversion-Id-U ⊢IdAt₁tā‚‚
        lā‚„ , ⊢B , ⊢u₁ , ⊢uā‚‚ , U≔Uā‚‚ = inversion-Id-U ⊢IdBu₁uā‚‚
        A≔B , lā‚ƒā‰”lā‚„          = soundnessConv↑-U ⊢A ⊢B A≔B
    in
      conv
        (Id-cong A≔B (soundnessConv↑Term t₁≔u₁)
           (soundnessConv↑Term t₂≔uā‚‚))
        (sym U≔U₁)
    , U-injectivity
        (U l₁  ā‰”āŸØ U≔U₁ ⟩⊢
         U lā‚ƒ  ā‰”āŸØ U-cong-āŠ¢ā‰” lā‚ƒā‰”lā‚„ ⟩⊢
         U lā‚„  ā‰”Ė˜āŸØ U≔Uā‚‚ āŸ©āŠ¢āˆŽ
         U lā‚‚  āˆŽ)
    where
    open TyR

  -- A variant of soundnessConv↑.

  soundnessConv↑-U :
    Ī“ ⊢ A ∷ U l₁ → Ī“ ⊢ B ∷ U lā‚‚ → Ī“ ⊢ A [conv↑] B →
    Ī“ ⊢ A ≔ B ∷ U l₁ Ɨ Ī“ ⊢ l₁ ≔ lā‚‚ ∷Level
  soundnessConv↑-U {A} {l₁} {B} {lā‚‚} ⊢A ⊢B ([↑] A′ B′ Aā†˜A′ Bā†˜B′ A′≔B′) =
    let A″ , A″-type , A⇒*A″ = red-U ⊢A
        B″ , B″-type , B⇒*B″ = red-U ⊢B
        _ , _ , ⊢A″ = wf-āŠ¢ā‰”āˆ· (subset*Term A⇒*A″)
        _ , _ , ⊢B″ = wf-āŠ¢ā‰”āˆ· (subset*Term B⇒*B″)
        A′≔A″ = whrDet* Aā†˜A′ (univ* A⇒*A″ , typeWhnf A″-type)
        B′≔B″ = whrDet* Bā†˜B′ (univ* B⇒*B″ , typeWhnf B″-type)
        A′≔B′ , l₁≔lā‚‚ =
          soundnessConv↓-U (PE.subst (_ ⊢_∷ _) (PE.sym A′≔A″) ⊢A″)
            (PE.subst (_ ⊢_∷ _) (PE.sym B′≔B″) ⊢B″) A′≔B′
    in
      (A          ⇒*⟨ A⇒*A″ ⟩⊢
       A″         ā‰”Ė˜āŸØ A′≔A″ āŸ©āŠ¢ā‰”
       A′ ∷ U l₁  ā‰”āŸØ A′≔B′ ⟩⊢∷
                   ⟨ U-cong-āŠ¢ā‰” l₁≔lā‚‚ āŸ©ā‰”
       B′ ∷ U lā‚‚  ā‰”āŸØ B′≔B″ āŸ©āŠ¢āˆ·ā‰”
       B″         ⇐*⟨ B⇒*B″ āŸ©āŠ¢āˆŽ
       B          āˆŽ)
    , l₁≔lā‚‚
    where
    open TmR

  -- Algorithmic equality of levels is well-formed.

  soundnessConv↓Level : āˆ€ {a b} → Ī“ ⊢ a [conv↓] b ∷Level → Ī“ ⊢ a ≔ b ∷ Level
  soundnessConv↓Level ([↓]Ė” aįµ› bįµ› a≔ b≔ a≔b) =
    let a≔ = soundness↓ᵛ a≔
        b≔ = soundness↓ᵛ b≔
        ⊢Level , _ , _ = syntacticEqTerm a≔
        āŠ¢Ī“ = wf ⊢Level
        ok = inversion-Level-⊢ ⊢Level
    in trans a≔
        (trans (soundness-≔ᵛ ok āŠ¢Ī“ aįµ› bįµ› a≔b)
          (sym′ b≔))

  -- If t normalises to a level view, then t is well-formed.

  wf↑ᵛ : āˆ€ {t v} → Ī“ ⊢ t ↑ᵛ v → Ī“ ⊢ t ∷ Level
  wf↑ᵛ ([↑]įµ› (d , _) t↓v) = redFirst*Term d

  wf↓ᵛ : āˆ€ {t v} → Ī“ ⊢ t ↓ᵛ v → Ī“ ⊢ t ∷ Level
  wf↓ᵛ (zeroįµ˜ā‚™ ok āŠ¢Ī“) = zeroᵘⱼ ok āŠ¢Ī“
  wf↓ᵛ (sucįµ˜ā‚™ x x₁) = sucᵘⱼ (wf↑ᵛ x₁)
  wf↓ᵛ (neā‚™ x) = wf~įµ› x

  wf~įµ› : āˆ€ {t v} → Ī“ ⊢ t ~įµ› v → Ī“ ⊢ t ∷ Level
  wf~įµ› (supįµ˜Ė”ā‚™ x x₁ xā‚‚) = supᵘⱼ (wf~įµ› x₁) (wf↑ᵛ xā‚‚)
  wf~įµ› (supįµ˜Ź³ā‚™ x x₁ xā‚‚) = supᵘⱼ (sucᵘⱼ (wf↑ᵛ x₁)) (wf~įµ› xā‚‚)
  wf~įµ› (neā‚™ [t] x) = syntacticEqTerm (soundness~↓ [t]) .projā‚‚ .proj₁

  -- A level view in a well-formed context induces a well-formed level
  -- (assuming that Level is allowed).

  ⊢LevelAtom :
    Level-allowed → ⊢ Ī“ → (l : LevelAtom Ī“) →
    Ī“ ⊢ LevelAtom→Term l ∷ Level
  ⊢LevelAtom ok āŠ¢Ī“ zeroᵘ    = zeroᵘⱼ ok āŠ¢Ī“
  ⊢LevelAtom _  āŠ¢Ī“ (ne t≔t) =
    let _ , ⊢t , _ = syntacticEqTerm (soundness~↓ t≔t)
    in ⊢t

  ⊢Level⁺ :
    Level-allowed → ⊢ Ī“ → (l : Level⁺ Ī“) →
    Ī“ ⊢ Level⁺→Term l ∷ Level
  ⊢Level⁺ ok āŠ¢Ī“ (0      , l) = ⊢LevelAtom ok āŠ¢Ī“ l
  ⊢Level⁺ ok āŠ¢Ī“ (N.1+ n , l) = sucᵘⱼ (⊢Level⁺ ok āŠ¢Ī“ (n , l))

  ⊢Levelįµ› :
    Level-allowed → ⊢ Ī“ → (l : Levelįµ› Ī“) → Ī“ ⊢ Levelᵛ→Term l ∷ Level
  ⊢Levelįµ› ok āŠ¢Ī“ L.[]      = zeroᵘⱼ ok āŠ¢Ī“
  ⊢Levelįµ› ok āŠ¢Ī“ (x L.∷ l) = supᵘⱼ (⊢Level⁺ ok āŠ¢Ī“ x) (⊢Levelįµ› ok āŠ¢Ī“ l)

  ⊢suc⁺ :
    Level-allowed → ⊢ Ī“ → (x : Level⁺ Ī“) →
    Ī“ ⊢ Level⁺→Term (suc⁺ x) ∷ Level
  ⊢suc⁺ ok āŠ¢Ī“ (n , a) =
    sucᵘⱼ (⊢∷Levelā†’āŠ¢āˆ·Level ok (⊢sucįµ˜įµ (term-⊢∷ (⊢LevelAtom ok āŠ¢Ī“ a))))

  ⊢map-suc⁺ :
    Level-allowed → ⊢ Ī“ → (l : Levelįµ› Ī“) →
    Ī“ ⊢ Levelᵛ→Term (map-suc⁺ l) ∷ Level
  ⊢map-suc⁺ ok āŠ¢Ī“ L.[]      = zeroᵘⱼ ok āŠ¢Ī“
  ⊢map-suc⁺ ok āŠ¢Ī“ (x L.∷ l) = supᵘⱼ (⊢suc⁺ ok āŠ¢Ī“ x) (⊢map-suc⁺ ok āŠ¢Ī“ l)

  -- The reification of a level view commutes with the level operations.

  Levelᵛ→Term-suc :
    Level-allowed → ⊢ Ī“ → (l : Levelįµ› Ī“) →
    Ī“ ⊢ sucᵘ (Levelᵛ→Term l) ≔ Levelᵛ→Term (sucįµ› l) ∷ Level
  Levelᵛ→Term-suc ok āŠ¢Ī“ L.[] = sym′ (supᵘ-zeroʳⱼ (sucᵘⱼ (zeroᵘⱼ ok āŠ¢Ī“)))
  Levelᵛ→Term-suc ok āŠ¢Ī“ (x L.∷ l) =
    trans (sym′ (supᵘ-sucᵘ (⊢Level⁺ ok āŠ¢Ī“ x) (⊢Levelįµ› ok āŠ¢Ī“ l)))
      (trans
         (supᵘ-cong (refl (sucᵘⱼ (⊢Level⁺ ok āŠ¢Ī“ x)))
            (Levelᵛ→Term-suc ok āŠ¢Ī“ l))
         (supᵘ-comm-assoc (sucᵘⱼ (⊢Level⁺ ok āŠ¢Ī“ x))
            (sucᵘⱼ (zeroᵘⱼ ok āŠ¢Ī“)) (⊢map-suc⁺ ok āŠ¢Ī“ l)))

  Levelᵛ→Term-sup :
    Level-allowed → ⊢ Ī“ → (t u : Levelįµ› Ī“) →
    Ī“ ⊢ Levelᵛ→Term t supᵘ Levelᵛ→Term u ≔ Levelᵛ→Term (supįµ› t u) ∷
      Level
  Levelᵛ→Term-sup ok āŠ¢Ī“ L.[]      x = supᵘ-zeroĖ” (⊢Levelįµ› ok āŠ¢Ī“ x)
  Levelᵛ→Term-sup ok āŠ¢Ī“ (x L.∷ t) u =
    trans
      (supᵘ-assoc (⊢Level⁺ ok āŠ¢Ī“ x) (⊢Levelįµ› ok āŠ¢Ī“ t) (⊢Levelįµ› ok āŠ¢Ī“ u))
      (supᵘ-cong (refl (⊢Level⁺ ok āŠ¢Ī“ x)) (Levelᵛ→Term-sup ok āŠ¢Ī“ t u))

  Levelᵛ→Term-sup-map-suc⁺ :
    Level-allowed → ⊢ Ī“ → (t u : Levelįµ› Ī“) →
    Ī“ ⊢ Levelᵛ→Term (map-suc⁺ t) supᵘ Levelᵛ→Term u ≔
      Levelᵛ→Term (supįµ› (map-suc⁺ t) u) ∷ Level
  Levelᵛ→Term-sup-map-suc⁺ ok āŠ¢Ī“ L.[] u =
    supᵘ-zeroĖ” (⊢Levelįµ› ok āŠ¢Ī“ u)
  Levelᵛ→Term-sup-map-suc⁺ ok āŠ¢Ī“ (x L.∷ t) u =
    trans
      (supᵘ-assoc (⊢suc⁺ ok āŠ¢Ī“ x) (⊢map-suc⁺ ok āŠ¢Ī“ t) (⊢Levelįµ› ok āŠ¢Ī“ u))
      (supᵘ-cong (refl (⊢suc⁺ ok āŠ¢Ī“ x))
         (Levelᵛ→Term-sup-map-suc⁺ ok āŠ¢Ī“ t u))

  Levelᵛ→Term-sup-sucįµ› :
    Level-allowed → ⊢ Ī“ → (t u : Levelįµ› Ī“) →
    Ī“ ⊢ Levelᵛ→Term (sucįµ› t) supᵘ Levelᵛ→Term u ≔
      Levelᵛ→Term (supįµ› (sucįµ› t) u) ∷ Level
  Levelᵛ→Term-sup-sucįµ› ok āŠ¢Ī“ t u =
    trans
      (supᵘ-assoc (sucᵘⱼ (zeroᵘⱼ ok āŠ¢Ī“)) (⊢map-suc⁺ ok āŠ¢Ī“ t)
         (⊢Levelįµ› ok āŠ¢Ī“ u))
      (supᵘ-cong (refl (sucᵘⱼ (zeroᵘⱼ ok āŠ¢Ī“)))
         (Levelᵛ→Term-sup-map-suc⁺ ok āŠ¢Ī“ t u))

  -- If t normalises to a level view v, then t is equal to the reification of v.

  soundness↑ᵛ : āˆ€ {t} {v : Levelįµ› Ī“} → Ī“ ⊢ t ↑ᵛ v → Ī“ ⊢ t ≔ Levelᵛ→Term v ∷ Level
  soundness↑ᵛ ([↑]įµ› (d , _) t↓v) = trans (subset*Term d) (soundness↓ᵛ t↓v)

  soundness↓ᵛ : āˆ€ {t} {v : Levelįµ› Ī“} → Ī“ ⊢ t ↓ᵛ v → Ī“ ⊢ t ≔ Levelᵛ→Term v ∷ Level
  soundness↓ᵛ (zeroįµ˜ā‚™ ok āŠ¢Ī“) = refl (zeroᵘⱼ ok āŠ¢Ī“)
  soundness↓ᵛ (sucįµ˜ā‚™ {v′} PE.refl t≔v) =
    let ⊢t≔v = soundness↑ᵛ t≔v
        ok   = inversion-Level-⊢ (wf-āŠ¢ā‰”āˆ· ⊢t≔v .proj₁)
    in
    trans (sucᵘ-cong ⊢t≔v) (Levelᵛ→Term-suc ok (wfTerm (wf↑ᵛ t≔v)) v′)
  soundness↓ᵛ (neā‚™ x) = soundness~įµ› x

  soundness~įµ› : āˆ€ {t} {v : Levelįµ› Ī“} → Ī“ ⊢ t ~įµ› v → Ī“ ⊢ t ≔ Levelᵛ→Term v ∷ Level
  soundness~įµ› (supįµ˜Ė”ā‚™ {v′} {v″} y t~ u↑) =
    let u↑ = soundness↑ᵛ u↑
        ok = inversion-Level-⊢ (wf-āŠ¢ā‰”āˆ· u↑ .proj₁)
    in
    trans (supᵘ-cong (soundness~įµ› t~) u↑)
      (PE.subst (_ ⊢ _ ≔_∷ _) (PE.cong Levelᵛ→Term (PE.sym y))
        (Levelᵛ→Term-sup ok (wfTerm (wf~įµ› t~)) v′ v″))
  soundness~įµ› (supįµ˜Ź³ā‚™ {v′} {v″} PE.refl t↑ u~) =
    let āŠ¢Ī“ = wfTerm (wf↑ᵛ t↑)
        t↑ = soundness↑ᵛ t↑
        ok = inversion-Level-⊢ (wf-āŠ¢ā‰”āˆ· t↑ .proj₁)
    in
    trans (supᵘ-cong (sucᵘ-cong t↑) (soundness~įµ› u~))
      (trans
         (supᵘ-cong (Levelᵛ→Term-suc ok āŠ¢Ī“ v′)
            (refl (⊢Levelįµ› ok āŠ¢Ī“ v″)))
         (Levelᵛ→Term-sup-sucįµ› ok āŠ¢Ī“ v′ v″))
  soundness~įµ› (neā‚™ [t′] PE.refl) =
    let ⊢Level , ⊢t′ , _ = syntacticEqTerm (soundness~↓ [t′])
    in sym′ (supᵘ-zeroʳⱼ ⊢t′)

  -- Comparison and equality of level views is sound with respect to reification.

  soundness-ā‰¤įµƒ
    : Level-allowed
    → ⊢ Ī“
    → āˆ€ (t u : LevelAtom Ī“)
    → ā‰¤įµƒ d t u
    → Ī“ ⊢ LevelAtom→Term t ≤ LevelAtom→Term u ∷Level
  soundness-ā‰¤įµƒ ok āŠ¢Ī“ t u zeroįµ˜ā‰¤ =
    supᵘ-zeroĖ” (⊢LevelAtom ok āŠ¢Ī“ u)
  soundness-ā‰¤įµƒ _ āŠ¢Ī“ t u (ne≤ (ne≔ x)) =
    supᵘ-subįµ (āŠ¢ā‰¤-refl (soundness~↓ x))
  soundness-ā‰¤įµƒ _ āŠ¢Ī“ t u (ne≤ (ne≔' x)) =
    supᵘ-subįµ (āŠ¢ā‰¤-refl (sym′ (soundness~↓ x)))

  soundness-≤⁺
    : Level-allowed
    → ⊢ Ī“
    → āˆ€ (t u : Level⁺ Ī“)
    → ≤⁺ d t u
    → Ī“ ⊢ Level⁺→Term t ≤ Level⁺→Term u ∷Level
  soundness-≤⁺ ok āŠ¢Ī“ (n , t) (m , u) (n≤m , t≤u) =
    ≤-sucįµ˜įµ n≤m (soundness-ā‰¤įµƒ ok āŠ¢Ī“ _ _ t≤u)

  soundness-≤⁺ᵛ
    : Level-allowed
    → ⊢ Ī“
    → āˆ€ (t : Level⁺ Ī“) (u : Levelįµ› Ī“)
    → ≤⁺ᵛ d t u
    → Ī“ ⊢ Level⁺→Term t ≤ Levelᵛ→Term u ∷Level
  soundness-≤⁺ᵛ ok āŠ¢Ī“ t (u L.∷ us) (Any.here px) =
    let ⊢t = ⊢Level⁺ ok āŠ¢Ī“ t
        ⊢u = ⊢Level⁺ ok āŠ¢Ī“ u
        ⊢us = ⊢Levelįµ› ok āŠ¢Ī“ us
        ⊢Level = syntacticTerm ⊢t
    in
    trans (sym′ (supᵘ-assoc ⊢t ⊢u ⊢us))
      (supᵘ-cong (soundness-≤⁺ ok āŠ¢Ī“ _ _ px) (refl ⊢us))
  soundness-≤⁺ᵛ ok āŠ¢Ī“ t (u L.∷ us) (Any.there x) =
    let ⊢t = ⊢Level⁺ ok āŠ¢Ī“ t
        ⊢u = ⊢Level⁺ ok āŠ¢Ī“ u
        ⊢us = ⊢Levelįµ› ok āŠ¢Ī“ us
    in
    trans (supᵘ-comm-assoc ⊢t ⊢u ⊢us)
      (supᵘ-cong (refl ⊢u) (soundness-≤⁺ᵛ ok āŠ¢Ī“ _ _ x))
  soundness-≤⁺ᵛ _ _ _ L.[] ()

  soundness-≤ᵛ
    : Level-allowed
    → ⊢ Ī“
    → āˆ€ (t u : Levelįµ› Ī“)
    → ≤ᵛ d t u
    → Ī“ ⊢ Levelᵛ→Term t ≤ Levelᵛ→Term u ∷Level
  soundness-≤ᵛ ok āŠ¢Ī“ t u All.[] = supᵘ-zeroĖ” (⊢Levelįµ› ok āŠ¢Ī“ u)
  soundness-≤ᵛ ok āŠ¢Ī“ (t L.∷ ts) u (px All.∷ t≤u) =
    let ⊢t = ⊢Level⁺ ok āŠ¢Ī“ t
        ⊢ts = ⊢Levelįµ› ok āŠ¢Ī“ ts
        ⊢u = ⊢Levelįµ› ok āŠ¢Ī“ u
    in
    trans (supᵘ-assoc ⊢t ⊢ts ⊢u)
      (trans (supᵘ-cong (refl ⊢t) (soundness-≤ᵛ ok āŠ¢Ī“ ts u t≤u))
        (soundness-≤⁺ᵛ ok āŠ¢Ī“ t u px))

  soundness-≔ᵛ
    : Level-allowed
    → ⊢ Ī“
    → āˆ€ (t u : Levelįµ› Ī“)
    → t ≔ᵛ u
    → Ī“ ⊢ Levelᵛ→Term t ≔ Levelᵛ→Term u ∷ Level
  soundness-≔ᵛ ok āŠ¢Ī“ t u (t≤u , u≤t) =
    trans (sym′ (soundness-≤ᵛ ok āŠ¢Ī“ u t u≤t))
      (trans (supᵘ-comm (⊢Levelįµ› ok āŠ¢Ī“ u) (⊢Levelįµ› ok āŠ¢Ī“ t))
        (soundness-≤ᵛ ok āŠ¢Ī“ t u t≤u))