Some checks are pending
Lean Action CI / build (push) Waiting to run
Lands the metacoding stack from ALGEBRA_PLAN.md per the user's discipline directive (no shortcuts, end-to-end correct). CubicalTransport/Algebra/Meta.lean (Phase A — meta-mirror types): - MetaCType: 11 constructors mirroring the cubical CType arms. - MetaClassifier: lattice of "where in the codebase" predicates with .always / .never / .meet / .join / .atDecl / .inFile / .underAttribute / .dependencyOf / .inNamespace. - MetaArtifact: source / declAt / refTo / empty. - MetaPosition: (declName, filePath, range?) addressing. - DecidableEq for MetaCType, MetaClassifier (manual mutual decEq for the recursive lattice arms). CubicalTransport/Algebra/Edit.lean (Phase B — Edit + Context): - Edit α: result + List EditOp. Monad / Functor instances. - Context α: focal artifact + position + siblings. Functor + comonad operations (extract / extend). - contextualEdit: the comonad-to-monad distributive law. - MetaClassifier.atPosition: syntactic dispatch on classifier shape; meet/join lattice laws stated as theorems. CubicalTransport/Algebra/Restructure.lean (Phase B — universal macro): - restructure: the comp-shaped 5-field operation, returns Edit Unit. - Frozen aliases: transport_artifact, relocate_invariant, rename_throughout, define_question_shape, compose_proof_fragments, materialize. - Headless interpreter: SourceBuffer + EditOp.apply + Edit.runHeadless. - Soundness scaffold: brokenRefs / selfConsistent / Edit.guarded. CubicalTransport/Algebra/MacroAlias.lean (Phase C): - @[macroAlias] attribute + AliasEntry registry (EnvExtension). - Lookup helpers + diagnostic printer. CubicalTransport/Algebra/Methodology.lean (Phase D'): - @[methodology Identifier] attribute + MethodologyEntry registry. - cubical_search tactic: walks the methodology library by classifier dispatch, applies via exact/apply. deriveByTransport stub awaits @[metaPath] (REL2.6+). - Diagnostic printer for the registry. CubicalTransport/Algebra/Test.lean: compile-time end-to-end tests: - Construct meta-mirror values; check DecidableEq. - Build Edit values via restructure; verify selfConsistent on a broken-ref batch (correctly flagged). - Register an alias via @[macroAlias]. - Register two methodologies via @[methodology] and verify cubical_search dispatches to them on representative goals. Runtime smoke tests: 4 new Algebra smokes verifying restructure emits the right ops, the broken-ref guard fires, and the classifier lattice computes correctly. 93/93 tests pass. Documentation: - docs/QUESTIONS.md §4: Levels 1, 2, 3-light marked LANDED with commit refs; full Level 3 graph-walking marked pending. - docs/ALGEBRA_PLAN.md §6: phase table updated with status column; Phases A/B/C/D' marked landed; Phases B.2 (LSP) + D (widget) + REL2.6 methodology-transport explicitly marked pending. - docs/EULERIAN.md §9, §10: "the map" and "autodiscovery" rows updated from "planned REL2.5" to "landed 2026-05-01" with module-level cross-references. - docs/KERNEL_BOUNDARY.md §3.7: cubical_simp (light) and cubical_search marked landed; full graph-walking cubical_simp marked dependent on @[metaPath]. Pending items deliberately out of scope this session: - LSP widget (D) — needs running Lean LSP server. - B.2 LSP integration — needs CodeActionContext. - @[metaPath] declarations + full deriveByTransport — REL2.6+. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
185 lines
8.1 KiB
Text
185 lines
8.1 KiB
Text
/-
|
||
CubicalTransport.Algebra.Restructure — the universal macro
|
||
==========================================================
|
||
Phase B of `docs/ALGEBRA_PLAN.md`. Defines the `restructure`
|
||
operation — a function with the same five-field shape as
|
||
`comp i A φ u t`, lifted to the meta-source-code level.
|
||
|
||
Per ALGEBRA_PLAN §0:
|
||
> One macro. Built from `comp`. Aliases accrue by usage; tactics
|
||
> are search over a library that grows under structural-Path
|
||
> declarations alone.
|
||
|
||
All 32 enumerated macros from the original sketch are *frozen
|
||
partial applications* of this single `restructure`; the alias
|
||
layer in `Algebra/MacroAlias.lean` lets users (or the system)
|
||
name recurring patterns.
|
||
-/
|
||
|
||
import CubicalTransport.Algebra.Edit
|
||
|
||
namespace CubicalTransport.Algebra
|
||
|
||
-- ── The universal `restructure` operation ───────────────────────────────────
|
||
|
||
/-- `restructure i ctx φ witness fallback` — the universal source-
|
||
mutation operation. Five fields, each mirroring a field of
|
||
`comp i A φ u t`:
|
||
|
||
· `i : MetaPosition` — where in source.
|
||
· `ctx : MetaCType` — meta-type of the artifact.
|
||
· `φ : MetaClassifier` — when this restructuring applies.
|
||
· `witness : MetaArtifact` — new content valid on φ.
|
||
· `fallback : MetaArtifact` — existing content off-φ.
|
||
|
||
The result is an `Edit Unit`: a single `EditOp` whose content is
|
||
`witness` (when `φ` matches at `i`) or `fallback` (otherwise).
|
||
|
||
The `ctx` argument is currently used only for documentation /
|
||
diagnostics — Phase C's `@[macroAlias]` attribute consumes it
|
||
when binding aliases. Future Phase D' may use it to dispatch
|
||
different rendering / preview modes in the widget. -/
|
||
def restructure (i : MetaPosition) (_ctx : MetaCType)
|
||
(φ : MetaClassifier) (witness fallback : MetaArtifact) : Edit Unit :=
|
||
let active := φ.atPosition i
|
||
let chosen := if active then witness else fallback
|
||
let label := if active then "hit" else "miss"
|
||
Edit.emit
|
||
{ position := i
|
||
, newContent := chosen
|
||
, oldContent := none
|
||
, description := s!"restructure φ={label} at {repr i}" }
|
||
|
||
-- ── The 32 macros as frozen aliases ─────────────────────────────────────────
|
||
-- Per ALGEBRA_PLAN §2.3 every "macro" in the original 32-item list
|
||
-- is a frozen partial application. These are the foundational
|
||
-- aliases; a downstream user / agent can register more via
|
||
-- `@[macroAlias]` (Phase C).
|
||
|
||
/-- Frozen alias: `transport_artifact i ctx w` — `restructure` with
|
||
`φ = .always`, `witness = fallback = w`. Always applies; just
|
||
relocates `w` to `i`. -/
|
||
@[reducible]
|
||
def transport_artifact (i : MetaPosition) (ctx : MetaCType) (w : MetaArtifact) :
|
||
Edit Unit :=
|
||
restructure i ctx .always w w
|
||
|
||
/-- Frozen alias: `relocate_invariant i src dst` — moves a file's
|
||
content from `src` to `dst`, classifier set to "in source file." -/
|
||
@[reducible]
|
||
def relocate_invariant (decl : Lean.Name) (src dst : String) : Edit Unit :=
|
||
restructure { declName := decl, filePath := dst, range := none }
|
||
.file (.inFile src) (.refTo decl) .empty
|
||
|
||
/-- Frozen alias: `rename_throughout x y` — emit a rename edit for
|
||
declaration `x` (witness on `.atDecl x`, fallback `.empty`). -/
|
||
@[reducible]
|
||
def rename_throughout (oldName newName : Lean.Name) : Edit Unit :=
|
||
restructure { declName := oldName, filePath := "", range := none }
|
||
.definition (.atDecl oldName) (.refTo newName) .empty
|
||
|
||
/-- Frozen alias: `define_question_shape S` — register a new question
|
||
schema as an inductive declaration. -/
|
||
@[reducible]
|
||
def define_question_shape (declName : Lean.Name) (witness : MetaArtifact) :
|
||
Edit Unit :=
|
||
restructure { declName := declName, filePath := "", range := none }
|
||
.inductive_ .always witness .empty
|
||
|
||
/-- Frozen alias: `compose_proof_fragments` — pure `restructure` with
|
||
no freezing. This is the "raw" `restructure` exposed under a
|
||
documentary name; identical in behaviour. -/
|
||
@[reducible]
|
||
def compose_proof_fragments
|
||
(i : MetaPosition) (ctx : MetaCType) (φ : MetaClassifier)
|
||
(w f : MetaArtifact) : Edit Unit :=
|
||
restructure i ctx φ w f
|
||
|
||
/-- Frozen alias: `materialize` — emit a piece of raw Lean source at
|
||
a position. The leaf operation; everything else composes from
|
||
here. -/
|
||
@[reducible]
|
||
def materialize (i : MetaPosition) (ctx : MetaCType) (src : String) :
|
||
Edit Unit :=
|
||
restructure i ctx .always (.source src) .empty
|
||
|
||
-- ── Headless interpreter: apply edits to an in-memory buffer ────────────────
|
||
-- Phase 5.3 No-LSP fallback: same operations as `lake exe
|
||
-- algebra-restructure` subcommands. Useful for batch CI runs.
|
||
|
||
/-- A simple in-memory source buffer. Maps file paths to current
|
||
contents. `applyOp` mutates the buffer in place. -/
|
||
abbrev SourceBuffer := Std.HashMap String String
|
||
|
||
/-- Apply a single `EditOp` to a source buffer. For now this is a
|
||
crude full-file overwrite when `position.range` is `none`; range-
|
||
based partial overwrites are scheduled for the LSP-backed
|
||
integration in `Algebra/EditLSP.lean`.
|
||
|
||
Returns the updated buffer. Diagnostic lines printed to
|
||
`IO.stderr` describe what changed. -/
|
||
def EditOp.apply (op : EditOp) (buf : SourceBuffer) : IO SourceBuffer := do
|
||
let path := op.position.filePath
|
||
match op.newContent with
|
||
| .source s =>
|
||
IO.eprintln s!"[restructure] writing {path} (decl {op.position.declName})"
|
||
return buf.insert path s
|
||
| .empty =>
|
||
IO.eprintln s!"[restructure] removing {path} (decl {op.position.declName})"
|
||
return buf.erase path
|
||
| .refTo n =>
|
||
IO.eprintln s!"[restructure] {path}: rename / link → {n}"
|
||
return buf
|
||
| .declAt _ =>
|
||
IO.eprintln s!"[restructure] {path}: emit syntax (LSP-bound; headless skipped)"
|
||
return buf
|
||
|
||
/-- Run an `Edit` headless: apply every emitted op in order to an
|
||
initial source buffer. Returns the final buffer plus the
|
||
computation's value. -/
|
||
def Edit.runHeadless {α : Type} (e : Edit α) (initial : SourceBuffer) :
|
||
IO (α × SourceBuffer) := do
|
||
let mut buf := initial
|
||
for op in e.ops do
|
||
buf ← op.apply buf
|
||
return (e.result, buf)
|
||
|
||
-- ── Soundness guard scaffold ────────────────────────────────────────────────
|
||
-- ALGEBRA_PLAN §3.3: every Edit passes through `preserve_typing`.
|
||
-- The full integration requires invoking `lean` on a fresh source
|
||
-- buffer; the data-level guard here checks that no edit deletes
|
||
-- a declaration that other edits in the same batch reference.
|
||
|
||
/-- The names referenced by an `EditOp` (as a `MetaArtifact.refTo`). -/
|
||
def EditOp.referenced : EditOp → List Lean.Name
|
||
| { newContent := .refTo n, .. } => [n]
|
||
| _ => []
|
||
|
||
/-- The decl-name *removed* by an `EditOp` (when content is `.empty`). -/
|
||
def EditOp.removed : EditOp → List Lean.Name
|
||
| { newContent := .empty, position := p, .. } => [p.declName]
|
||
| _ => []
|
||
|
||
/-- A "broken reference" predicate: does this batch reference any
|
||
name that the same batch removes? The structural check that
|
||
runs in any environment, headless or not. -/
|
||
def Edit.brokenRefs {α : Type} (e : Edit α) : List Lean.Name :=
|
||
let removed := e.ops.flatMap EditOp.removed
|
||
let referenced := e.ops.flatMap EditOp.referenced
|
||
referenced.filter (· ∈ removed)
|
||
|
||
/-- The structural soundness check: an `Edit` is *self-consistent*
|
||
if no op references a name another op in the batch removes.
|
||
Full type-checking of the post-edit buffer is the LSP-integrated
|
||
layer's job (`Algebra/EditLSP.lean`). -/
|
||
def Edit.selfConsistent {α : Type} (e : Edit α) : Bool :=
|
||
e.brokenRefs.isEmpty
|
||
|
||
/-- Guarded wrapper: aborts the edit if its self-consistency check
|
||
fails. Mirrors the `Edit.guarded` shape in ALGEBRA_PLAN §3.3. -/
|
||
def Edit.guarded {α : Type} [Inhabited α] (e : Edit α) :
|
||
Except String (Edit α) :=
|
||
if e.selfConsistent then .ok e
|
||
else .error s!"restructure batch breaks references: {repr e.brokenRefs}"
|
||
|
||
end CubicalTransport.Algebra
|