/-
  Topolei.Cubical.ValueTyping
  ===========================
  Semantic typing on values (Stream B #2a, Stage 2.3).

  This module states the *semantic* typing relation on `CVal` / `CNeu`
  needed to close the last two step-level residuals (T3 transport and
  C4 composition subject reduction).  The relation is declarative —
  fully inductive definition is future Lean-discharge work; the
  important structural fact is that its three preservation obligations
  (`eval`, `readback`, and their composition `step`) let us consolidate
  T3 and C4 into a single axiom, and derive them as theorems.

  ## The preservation story (sketch)

  For the full discharge:

      HasVal v A   -- v is a value of type A
      HasNeu n A   -- n is a neutral at type A

  defined mutually-inductively (logical-relations style) over CVal /
  CNeu.  The three obligations are:

  1. **eval preserves typing.**  Given a well-typed term `t : A` under
     a well-typed env, `eval env t : A` — i.e. `HasVal (eval env t) A`.

  2. **readback preserves typing.**  Given `HasVal v A`,
     `readback v` is a well-typed term of type `A` in the open context.

  3. **step preserves typing.**  Composition of (1) + (2) at the empty
     env gives: `HasType Γ t A → HasType Γ (CTerm.step t) A`, i.e. the
     classical subject reduction.

  Once (3) holds, T3 (transport subject reduction) and C4 (composition
  subject reduction) are immediate corollaries — instantiate at the
  `.transp` / `.comp` constructors and use their `HasType` rules.

  ## MVP in this module

  HasVal / HasNeu are *opaque stubs* — their full structural definition
  is deferred.  The three preservation axioms are stated with
  Lean-discharge provenance (future work will prove them by induction
  on the inductive definition once HasVal / HasNeu are concretely
  populated).  The crucial consolidation is the single axiom
  `CTerm.step_preserves_type`, from which T3 and C4 follow as theorems
  — eliminating the need for separate step-level axioms for each
  type-former.

  ## Why this is consolidation, not just renaming

  Before Stage 2.3: T3 and C4 were independently posited step-level
  axioms, each specific to a type-former (`.transp` / `.comp`).  Adding
  another type-former (e.g. Σ transport once Stage 2.4 or beyond) would
  require a new axiom.

  After Stage 2.3: T3 and C4 are *theorems*, derivable from the single
  `step_preserves_type` axiom.  New type-formers get subject reduction
  for free — as long as they have a typing rule in `HasType`, they
  automatically inherit preservation under `CTerm.step`.  The axiom
  surface scales O(1) in type-formers, not O(n).
-/

import CubicalTransport.Typing
import CubicalTransport.Readback

-- ── Semantic typing (declarative stubs) ─────────────────────────────────────

/-- `HasVal v A` — the value `v` inhabits type `A` semantically.
    Full inductive definition is Lean-discharge future work; for now
    this is an opaque predicate whose structural properties are
    captured by the preservation axioms below. -/
opaque HasVal : CVal → CType → Prop

/-- `HasNeu n A` — the neutral `n` is a stuck term of type `A`.
    Mutual partner to `HasVal`. -/
opaque HasNeu : CNeu → CType → Prop

/-- Semantic well-typedness of an environment: every binding's value
    has the type the context assigns to the name.  Declarative;
    populated in lockstep with `HasVal`. -/
opaque EnvHasType : CEnv → Ctx → Prop

-- ── Preservation axioms ─────────────────────────────────────────────────────

/-- **eval preserves typing.**  If `t : A` in context `Γ` and `env`
    inhabits `Γ` semantically, then `eval env t` is a value of type `A`.

    **Lean-discharge obligation.**  Proof: mutual structural induction
    on the `eval` / `vApp` / `vPApp` / `vTransp` / `vHCompValue` /
    `vCompAtTerm` / `vCompNAtTerm` arms, using the HasType typing
    rules to produce HasVal / HasNeu witnesses at each arm.

    The full discharge requires HasVal / HasNeu to be inductively
    populated (currently opaque); this is future Lean work. -/
axiom eval_preserves_type
    (env : CEnv) (Γ : Ctx) (t : CTerm) (A : CType)
    (hEnv : EnvHasType env Γ)
    (ht : HasType Γ t A) :
    HasVal (eval env t) A

/-- **readback preserves typing.**  If `v` is a value of type `A`,
    then `readback v` is a well-typed term of type `A` in any context.

    **Lean-discharge obligation.**  Mutual structural recursion on the
    `readback` / `readbackNeu` arms, each producing a `HasType` derivation
    from the corresponding `HasVal` / `HasNeu` witness. -/
axiom readback_preserves_type
    (Γ : Ctx) (v : CVal) (A : CType)
    (hv : HasVal v A) :
    HasType Γ (readback v) A

/-- The empty context / empty env is trivially well-typed — foundational
    base case for threading the preservation story through `CTerm.step`. -/
axiom EnvHasType.nil : EnvHasType .nil []

/-- **CTerm.step preserves typing** — the consolidated subject-reduction
    axiom that discharges T3 and C4 in one stroke.

    **Lean-discharge obligation.**  Composition of `eval_preserves_type`
    (at `.nil` / `[]`, via `EnvHasType.nil`), `readback_preserves_type`,
    and the definition `CTerm.readback t = readback (eval .nil t)`.
    The opaque `CTerm.step` is tied to `CTerm.readback` via the Week 7
    step↔eval bridge — the bridge is what makes this axiom's discharge
    concrete once HasVal is populated.

    **Scope note.** Stated over arbitrary `Γ`: the intuition is that
    step preserves the context-typing since the reduction lives inside
    the term (not the context).  The discharge via empty-env readback
    uses a weakening / threading argument that is valid because
    `CTerm.step` does not introduce free variables. -/
axiom CTerm.step_preserves_type
    (Γ : Ctx) (t : CTerm) (A : CType) (ht : HasType Γ t A) :
    HasType Γ (CTerm.step t) A
