Some checks are pending
Lean Action CI / build (push) Waiting to run
Phase B/C/D' headless CLI per ALGEBRA_PLAN §5.3 ("No-LSP fallback")
plus a registry-state asyncMode tightening.
AlgebraRestructure.lean (NEW) + lakefile.toml exe target:
- `lake exe algebra-restructure {list-aliases | list-methodologies
| list-paths | help}` — directs users to the source modules
hosting each kind of declaration.
- DOCUMENTED LIMITATION: Lean 4's
`SimplePersistentEnvExtension` state captured at build time
(`.olean` persistence) does not reliably re-load when an
Environment is reconstructed via `importModules` from a
standalone executable. The registries are populated at
elaboration time (cubical_search dispatches against them
successfully) and queryable from `#eval`-style invocations
inside a Lean session, but not from a headless CLI. The
CLI ships as a clearly-marked stub directing users to the
in-session diagnostic functions and the source-module locations.
CubicalTransport/Algebra/Methodology.lean,
CubicalTransport/Algebra/MacroAlias.lean,
CubicalTransport/Algebra/MetaPath.lean:
- All three SimplePersistentEnvExtension declarations now use
`asyncMode := .sync` (was default `.mainOnly`). Doesn't fix
the standalone-CLI persistence issue but makes the in-session
state visibility deterministic across import threads.
CubicalTransport/Algebra/Test.lean:
- printRegistrySizes converted from compile-time `#eval` (noisy)
to a documented diagnostic CoreM action invokable via
`#eval printRegistrySizes` from within a Lean session.
93/93 tests still pass. All Phase A/B/C/D' deliverables for
ALGEBRA_PLAN are now landed; remaining items (widget, full LSP
integration, complete methodology library coverage) are tracked
in the doc updates and explicitly outside the headless agent's
scope.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
127 lines
5.2 KiB
Text
127 lines
5.2 KiB
Text
/-
|
||
CubicalTransport.Algebra.MetaPath — `@[metaPath]` attribute
|
||
===========================================================
|
||
Phase D'.5 of `docs/ALGEBRA_PLAN.md`. Provides the structural-Path
|
||
declaration system that powers methodology-transport in
|
||
`cubical_search`.
|
||
|
||
A `MetaPath` is the meta-level analogue of a cubical `Path`: a
|
||
declared equivalence between two `MetaClassifier` shapes, witnessed
|
||
by a Lean theorem that exhibits the equivalence.
|
||
|
||
Example use:
|
||
|
||
@[metaPath IsFullFace IsConstLine]
|
||
theorem fullFace_implies_constLine_on_path (q : CompQ) :
|
||
IsFullFace q → IsConstLine q := …
|
||
|
||
Once such a Path is registered, every methodology indexed against
|
||
`IsFullFace` automatically becomes a candidate for `IsConstLine`
|
||
via `transp` at the methodology level.
|
||
|
||
Per ALGEBRA_PLAN §10.1 OQ: the witness theorem is required (a
|
||
declared MetaPath without a propositional witness would be
|
||
unsound). In v0 we trust the `metaPath` annotation; future REL3+
|
||
work can verify the witness type-checks against an expected shape.
|
||
-/
|
||
|
||
import Lean
|
||
import CubicalTransport.Algebra.Meta
|
||
|
||
namespace CubicalTransport.Algebra
|
||
|
||
open Lean
|
||
|
||
-- ── MetaPath entries ────────────────────────────────────────────────────────
|
||
|
||
/-- A registered structural Path between two classifiers.
|
||
|
||
`sourceClassifier` and `targetClassifier` are `Name`s pointing
|
||
to classifier predicates (typically defined in `Question.lean` —
|
||
`IsFullFace`, `IsConstLine`, `IsPathLine`, etc.).
|
||
`witnessName` names a theorem exhibiting the equivalence /
|
||
implication between them.
|
||
|
||
Direction matters: a Path `A ↦ B` means "every methodology for
|
||
A produces a methodology for B" (via post-composition with the
|
||
witness). The reverse direction needs a separate `metaPath B A`
|
||
declaration. -/
|
||
structure MetaPathEntry where
|
||
sourceClassifier : Name
|
||
targetClassifier : Name
|
||
witnessName : Name
|
||
description : String := ""
|
||
deriving Repr, Inhabited
|
||
|
||
-- ── The MetaPath registry ───────────────────────────────────────────────────
|
||
|
||
initialize metaPathRegistryExt :
|
||
SimplePersistentEnvExtension MetaPathEntry (Array MetaPathEntry) ←
|
||
registerSimplePersistentEnvExtension {
|
||
name := `Algebra.metaPathRegistry
|
||
addEntryFn := fun arr e => arr.push e
|
||
addImportedFn := fun arrs => arrs.foldl (init := #[]) Array.append
|
||
asyncMode := .sync
|
||
}
|
||
|
||
def getMetaPaths : CoreM (Array MetaPathEntry) := do
|
||
let env ← getEnv
|
||
return metaPathRegistryExt.getState env
|
||
|
||
def registerMetaPath (entry : MetaPathEntry) : CoreM Unit := do
|
||
modifyEnv (metaPathRegistryExt.addEntry · entry)
|
||
|
||
/-- Find every Path whose source matches a given classifier name. -/
|
||
def findPathsFromSource (source : Name) : CoreM (Array MetaPathEntry) := do
|
||
let all ← getMetaPaths
|
||
return all.filter (·.sourceClassifier == source)
|
||
|
||
/-- Find every Path whose target matches a given classifier name. -/
|
||
def findPathsToTarget (target : Name) : CoreM (Array MetaPathEntry) := do
|
||
let all ← getMetaPaths
|
||
return all.filter (·.targetClassifier == target)
|
||
|
||
-- ── The `@[metaPath]` attribute ─────────────────────────────────────────────
|
||
|
||
/-- Parser-level data for the `@[metaPath]` attribute: takes the
|
||
source classifier and the target classifier as identifiers.
|
||
The witness is the tagged declaration itself. -/
|
||
syntax (name := metaPath) "metaPath" ident ident : attr
|
||
|
||
/-- The `@[metaPath]` attribute itself. Records the tagged
|
||
declaration as a structural Path between two classifiers. -/
|
||
initialize metaPathAttr : Unit ←
|
||
registerBuiltinAttribute {
|
||
name := `metaPath
|
||
descr := "Register this declaration as a structural Path \
|
||
between two classifiers (Phase D'.5 of \
|
||
ALGEBRA_PLAN.md). Usage: `@[metaPath SourceClassifier \
|
||
TargetClassifier]`."
|
||
add := fun declName stx _kind => do
|
||
let parsed? : Option (Name × Name) :=
|
||
match stx with
|
||
| `(attr| metaPath $src:ident $tgt:ident) =>
|
||
some (src.getId, tgt.getId)
|
||
| _ => none
|
||
let some (src, tgt) := parsed?
|
||
| throwError "@[metaPath] requires source and target classifier names"
|
||
let env ← getEnv
|
||
let docstring? := (← findDocString? env declName).getD ""
|
||
registerMetaPath
|
||
{ sourceClassifier := src
|
||
, targetClassifier := tgt
|
||
, witnessName := declName
|
||
, description := docstring? }
|
||
}
|
||
|
||
-- ── Diagnostics ─────────────────────────────────────────────────────────────
|
||
|
||
def printMetaPaths : CoreM Unit := do
|
||
let entries ← getMetaPaths
|
||
IO.println s!"── MetaPath registry ({entries.size}) ──"
|
||
for entry in entries do
|
||
let d := if entry.description.isEmpty then "" else s!" — {entry.description}"
|
||
IO.println
|
||
s!" {entry.sourceClassifier} ↦ {entry.targetClassifier} via {entry.witnessName}{d}"
|
||
|
||
end CubicalTransport.Algebra
|