cubical-transport-hott-lean4/CubicalTransport/Algebra/Test.lean
Maximus Gorog 48b7326523
Some checks are pending
Lean Action CI / build (push) Waiting to run
Abstract the four ⚠️ tools into well-defined primitives
Per feedback "tooling possible, not tools — highly selective".
Each former opinionated wrapper either reduces to a Lean-standard
mechanism or splits into stated-contract primitives.

CubicalTransport/Question.lean:
- Drop the `cubical_simp` and `cubical_simp [..]` macros.  They
  baked in a fixed lemma list with a fixed expansion order.
- Drop the proposed `register_simp_attr question_simp` named-set
  too — strictly more curation than the foundation principle calls
  for.  Anyone wanting a named bundle can register one downstream.
- The genuinely-equational classifier-conditioned theorems remain
  `@[simp]`-tagged; existential-conclusion theorems
  (`ask_of_pi_line`, `ask_of_path_line`, HCompQ pi) lose their
  `@[simp]` tag (they don't rewrite goals — they produce
  witnesses).
- Examples now use Lean's standard `simp` against the `@[simp]`
  database — no special tactic involved.

CubicalTransport/Algebra/Methodology.lean:
- New foundation primitive `tryEntryAsClosed : MethodologyEntry →
  TacticM Bool` with stated contract: tries `exact` then `apply`,
  restores tactic state on failure, never throws, returns whether
  goal closed.  Order fixed to those two attempts in that sequence;
  alternative orders are user-side compositions of the primitive.
- `cubical_search` rewritten using `tryEntryAsClosed` +
  `findMethodologies` + `getMetaPaths` + `findMethodologies` (for
  source classifiers).  Docstring reframes it explicitly as a
  *reference-composition demonstrator* — exposes one obvious order
  for stages 1 (direct) and 2 (transport), with a "register your
  own dispatcher" pointer for users wanting different ordering /
  retry / failure shape.

CubicalTransport/Algebra/EngineMethodologies.lean:
- Drop the `cubical_close` macro entirely.  A `simp; (rfl |
  cubical_search)` composition is one line at the call site;
  baking it in imposed an opinionated default.

CubicalTransport/Algebra/Test.lean:
- Remove the three `cubical_close` examples (the macro is gone).
- Engine-bound methodologies remain (they exercise the @[methodology]
  registration mechanism).

AlgebraRestructure.lean:
- Docstring reframed as "thin labeled shell over `Algebra.print*`
  registry-printer functions, not a normative CLI."  The four
  subcommands are this demonstrator's choice; underlying printers
  accept any other shell equally.

93/93 tests pass.  No new functionality removed, just the opinion
layer between user code and the foundations.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 02:57:48 -06:00

206 lines
8.9 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
CubicalTransport.Algebra.Test — end-to-end tests
================================================
Exercises the Phase AD' Algebra layer at compile time:
- Phase A: construct meta-mirror values; verify decidable
equality.
- Phase B: build an `Edit Unit` value via `restructure` and check
`selfConsistent`; run the headless interpreter.
- Phase C: register an alias via `@[macroAlias]` and verify it
appears in the registry.
- Phase D': register a methodology via `@[methodology]` and verify
`cubical_search` finds it on a representative goal.
These are compile-time correctness tests; the runtime smoke tests
live in `FFITest.lean`.
-/
import CubicalTransport.Algebra.Methodology
import CubicalTransport.Algebra.MetaPath
import CubicalTransport.Algebra.EngineMethodologies
import CubicalTransport.Question
namespace CubicalTransport.Algebra.Test
open CubicalTransport.Algebra
open Question
-- ── Phase A: meta-mirror types ─────────────────────────────────────────────
/-- Meta-mirror types are inhabited and well-formed. -/
example : MetaCType := .theorem_
example : MetaCType := .file
example : MetaCType := .classifierSet
example : MetaClassifier := .always
example : MetaClassifier := .never
example : MetaClassifier := .meet (.atDecl `Foo) (.inFile "Bar.lean")
example : MetaArtifact := .source "def x := 1"
example : MetaArtifact := .empty
example : MetaArtifact := .refTo `Existing
example : MetaPosition :=
{ declName := `Test, filePath := "Test.lean", range := none }
/-- DecidableEq fires correctly on MetaClassifier. -/
example : decide (MetaClassifier.always = .always) = true := by decide
example : decide (MetaClassifier.always = .never) = false := by decide
example : decide ((.meet .always (.atDecl `Foo) : MetaClassifier) =
(.meet .always (.atDecl `Foo))) = true := by decide
-- ── Phase B: Edit + Context + restructure ───────────────────────────────────
/-- A simple restructure call produces an Edit with one op. -/
example :
let pos : MetaPosition := { declName := `Foo, filePath := "F.lean", range := none }
let e := restructure pos .theorem_ .always (.source "def x := 1") .empty
e.ops.length = 1 := by
rfl
/-- The restructure picks `witness` when the classifier is `.always`. -/
example :
let pos : MetaPosition := { declName := `Foo, filePath := "F.lean", range := none }
let e := restructure pos .theorem_ .always (.source "yes") (.source "no")
(e.ops.head?).isSome = true := by
rfl
/-- The restructure picks `fallback` when the classifier is `.never`. -/
example :
let pos : MetaPosition := { declName := `Foo, filePath := "F.lean", range := none }
let e := restructure pos .theorem_ .never (.source "yes") (.source "no")
(e.ops.head?).isSome = true := by
rfl
/-- Self-consistency check on a single restructure op. -/
example :
let pos : MetaPosition := { declName := `Foo, filePath := "F.lean", range := none }
let e := restructure pos .theorem_ .always (.source "x") .empty
e.selfConsistent = true := by
rfl
/-- A batch that removes a decl AND references it by `refTo` is
flagged as inconsistent. -/
example :
let pos₁ : MetaPosition := { declName := `Foo, filePath := "F.lean", range := none }
let pos₂ : MetaPosition := { declName := `Bar, filePath := "F.lean", range := none }
let e : Edit Unit := do
restructure pos₁ .theorem_ .always .empty .empty -- removes Foo
restructure pos₂ .theorem_ .always (.refTo `Foo) .empty -- refs Foo
e.selfConsistent = false := by
rfl
-- ── Frozen aliases ──────────────────────────────────────────────────────────
/-- The `transport_artifact` alias produces a single Edit op. -/
example :
let pos : MetaPosition := { declName := `Foo, filePath := "F.lean", range := none }
let e := transport_artifact pos .theorem_ (.source "x")
e.ops.length = 1 := by rfl
/-- The `materialize` alias emits raw Lean source. -/
example :
let pos : MetaPosition := { declName := `Foo, filePath := "F.lean", range := none }
let e := materialize pos .theorem_ "theorem x : True := trivial"
e.ops.length = 1 := by rfl
-- ── Phase C: @[macroAlias] registration ─────────────────────────────────────
/-- A custom alias for testing. Registered via the attribute below. -/
@[macroAlias]
def custom_alias_test (i : MetaPosition) : Edit Unit :=
restructure i .definition .always (.source "test") .empty
-- ── Phase D': @[methodology] registration ───────────────────────────────────
/-- A trivial methodology: solves `True` goals. Registered against
a placeholder classifier name `IsTrueGoal`. -/
@[methodology IsTrueGoal]
theorem trueMethodology : True := True.intro
/-- `cubical_search` finds the registered methodology for `True`
goals. Demonstrates the dispatch loop end-to-end. -/
example : True := by cubical_search
/-- Methodology for `Eq.refl`-shaped goals. Lean's `rfl` tactic
handles these natively — registering as a methodology
demonstrates that `cubical_search` can dispatch to non-trivial
universe-equality goals. -/
@[methodology IsReflGoal]
theorem reflMethodologyNat (n : Nat) : n = n := rfl
example : 7 = 7 := by cubical_search
-- ── Phase D'.5: @[metaPath] + methodology-transport ─────────────────────────
/-- A trivial structural Path: every reflexivity goal is also a
"trivial-truth" goal. This declares the meta-Path so
methodology-transport can lift `IsTrueGoal` methodologies onto
`IsReflGoal` targets and vice versa. -/
@[metaPath IsReflGoal IsTrueGoal]
theorem refl_path_to_true (n : Nat) (_ : n = n) : True := True.intro
/-- An identity methodology that closes any `Iff.refl`-shaped goal. -/
@[methodology IsIffReflGoal]
theorem iffRefl (P : Prop) : P ↔ P := Iff.rfl
example : True ↔ True := by cubical_search
-- ── Engine-bound methodologies — concrete CompQ closers ─────────────────────
-- These register classifier-conditioned engine theorems as
-- `cubical_search`-applicable methodologies. Each one fully
-- discharges its classifier via `decide` (since the classifier
-- predicates are Decidable for concrete `.top`/`.bot`/`.interval`
-- shapes), turning a hypothesis-bearing simp lemma into a stand-
-- alone closer.
/-- Closing methodology for full-face CompQ: literal `.top` face
questions reduce to `eval env (u.substDim i .one)`. Discharges
`IsFullFace` via `rfl` (`.top = .top` after struct projection). -/
@[methodology IsCompQFullFace]
theorem compq_top_concrete (env : CEnv) (i : DimVar) (A : CType) (u t : CTerm) :
(CompQ.mk env i A .top u t).ask = eval env (u.substDim i .one) :=
CompQ.ask_of_full_face _ rfl
/-- Closing methodology for full-face TranspQ: literal `.top` face
transports reduce to identity. -/
@[methodology IsTranspQFullFace]
theorem transpq_top_concrete (env : CEnv) (i : DimVar) (A : CType) (t : CTerm) :
(TranspQ.mk env i A .top t).ask = eval env t :=
TranspQ.ask_of_full_face _ rfl
/-- Closing methodology for interval-line TranspQ: any face on
`.interval` reduces to identity. -/
@[methodology IsTranspQInterval]
theorem transpq_interval_concrete (env : CEnv) (i : DimVar)
(φ : FaceFormula) (t : CTerm) :
(TranspQ.mk env i .interval φ t).ask = eval env t :=
TranspQ.ask_of_interval_line _ rfl
/-- `cubical_search` on a concrete CompQ full-face goal. -/
example (env : CEnv) (i : DimVar) (A : CType) (u t : CTerm) :
(CompQ.mk env i A .top u t).ask = eval env (u.substDim i .one) := by
cubical_search
/-- `cubical_search` on a concrete TranspQ interval-line goal. -/
example (env : CEnv) (i : DimVar) (t : CTerm) :
(TranspQ.mk env i .interval .top t).ask = eval env t := by
cubical_search
-- ── Compile-time registry diagnostics ───────────────────────────────────────
/-- A diagnostic action that prints registry sizes. Run via `#eval`
inside a Lean session to verify that @[methodology] /
@[macroAlias] / @[metaPath] declarations have populated the
EnvExtensions. This is the live way to inspect the registries
(the standalone CLI in `AlgebraRestructure.lean` cannot — see
its docstring for the Lean 4 EnvExtension limitation). -/
def printRegistrySizes : Lean.CoreM Unit := do
let aliases ← getAliases
let methodologies ← getMethodologies
let paths ← getMetaPaths
IO.println s!"[Algebra.Test] aliases={aliases.size} \
methodologies={methodologies.size} paths={paths.size}"
end CubicalTransport.Algebra.Test