lean4-htt/FORK_STRATEGY.md
Maximus Gorog ba016b2130
Some checks failed
CI / configure (push) Has been cancelled
Update stage0 / update-stage0 (push) Has been cancelled
CI / build (push) Has been cancelled
CI / build-secondary (push) Has been cancelled
CI / Build matrix complete (push) Has been cancelled
CI / release (push) Has been cancelled
CI / release-nightly (push) Has been cancelled
Phase 0: fork infrastructure
Add FORK_STRATEGY.md documenting:
- Purpose: HoTT-compatible kernel extensions (Path types without UIP,
  transport, HITs) for polytropos's meta-theory.
- Why kernel-level: library encodings via Quot leak UIP, incompatible
  with univalence. Mirrors Cubical Agda's precedent.
- Sync strategy: track upstream leanprover/lean4, merge (not rebase),
  preserve HoTT additions on conflict.
- Modification strategy: locality principle (new files under hott/
  + src/kernel/hott/ + src/Init/HoTT/); LEAN4-HTT: tag for modifications
  to upstream files; compile-time feature flag (LEAN_HOTT) gates HoTT.
- Patch-series organization for phased primitive additions.
- Forbidden moves: no UIP at kernel level, no Quot.sound dependency for
  HoTT reductions, no Classical.choice in HoTT primitives.

Add hott/ directory structure:
- hott/README.md describing the fork-specific directory's purpose.
- hott/design/ for architectural decisions per phase.
- hott/tests/ for HoTT-specific test suites.

No kernel modifications in this phase. Subsequent phases:
  Phase 1: Path + Refl + J primitives
  Phase 2: transport with computational behavior
  Phase 3: HIT support
  Phase 4: cubical primitives if needed

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 12:43:41 -06:00

186 lines
7.3 KiB
Markdown
Raw Permalink 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.

# lean4-htt: Fork Strategy
This is a fork of [leanprover/lean4](https://github.com/leanprover/lean4)
maintained for HoTT-compatible kernel extensions. The fork exists to add
foundational primitives that upstream Lean does not provide: identity Path
types without UIP, transport with full computational behavior, higher
inductive types (HITs), and (eventually) cubical primitives.
The fork is the meta-theoretic foundation for the polytropos project (a
cubical-transport HoTT engine). Polytropos's σ-calculus and substitution
machinery need HoTT-compatible meta-level reasoning that cannot be built
out of standard Lean inductive types alone without leaking UIP via
`Quot.sound` + `propext`.
## Why kernel-level, not library-level
Standard Lean library encodings of HoTT (e.g., via `Quot`) inherit UIP
from the kernel's quotient axiom. UIP is incompatible with univalence:
in a univalent universe, paths between types can be non-trivially
distinct, and UIP collapses this. The fork avoids this by adding Path
types as kernel primitives with their own reduction rules — no Quot
trapdoor, no inherited UIP.
This is the same engineering decision Cubical Agda made when extending
Agda with cubical primitives. The work is bounded, the precedent exists,
the architectural pattern is known.
## Sync strategy with upstream
The fork tracks `leanprover/lean4` (`upstream` remote) and publishes to
`maxgit.wg/max/lean4-htt` (`origin` remote).
### Sync cadence
Merge from upstream regularly. The cadence is "frequently enough that
each merge is mechanical" rather than a fixed schedule. Typical triggers:
- New upstream release
- Significant upstream features (e.g., LLVM backend updates, compiler
improvements) that we want to inherit
- After any local modification, before extending further
### Merge over rebase
The fork uses merges (not rebases) when pulling upstream. Rationale:
- Preserves the divergence history visibly in git log
- Avoids force-pushing the fork's master branch
- Makes each upstream sync a single commit (the merge commit) that can
be examined or reverted
### Conflict resolution discipline
When upstream and the fork modify the same file:
- Resolve in favor of preserving the fork's HoTT additions
- Verify the merged result still passes both upstream's tests and the
fork's HoTT-specific tests
- Document non-trivial conflicts in the merge commit's body
If upstream restructures something the fork depends on (e.g., changing
the `Expr` representation, refactoring `whnf`), the fork's patches need
re-application. Keep modifications localized so re-application is
mechanical.
## Modification strategy
### Locality principle
Add HoTT primitives in NEW files where possible:
- `src/kernel/hott/path.cpp`, `src/kernel/hott/transp.cpp`, etc.
- `src/Init/HoTT/` for Lean-side exposure of the new primitives
- `hott/` directory at the repo root for fork-specific design docs,
rationale, and tests
Only modify existing upstream files where the kernel architecture
requires it:
- `src/kernel/expr.h` (or equivalent): add new `Expr::Kind` variants
- `src/kernel/whnf.cpp` (or equivalent): add a single hook that
dispatches to the HoTT reducer
- `src/kernel/type_checker.cpp` (or equivalent): add a single hook for
HoTT inference rules
Every modification to an upstream file is documented with a comment
naming what it does and why. The grep-friendly tag is `LEAN4-HTT:`.
### Feature flag (compile-time gating)
HoTT primitives are gated behind a compile-time flag (likely a CMake
option `LEAN_HOTT=ON`). When `OFF`, the fork builds as vanilla Lean.
When `ON`, the HoTT extensions activate.
This reduces upstream-merge friction: most upstream changes don't touch
HoTT code paths, so they merge cleanly into the fork. It also gives a
testable "is the fork still upstream-equivalent in vanilla mode?"
property.
### Patch-series organization
HoTT additions are organized as a series of focused commits, each adding
one cohesive feature:
- Commit: add `Path` type former
- Commit: add `Refl` constructor
- Commit: add `J` eliminator + reduction
- Commit: add `transport` + reduction
- Commit: add HIT support
- etc.
Each commit is self-contained where possible. If upstream restructures
something that breaks a commit's assumptions, that commit can be
identified and re-applied without disturbing the others.
## Directory structure
```
lean4-htt/
├── FORK_STRATEGY.md # this file
├── hott/ # fork-specific design + tests
│ ├── README.md # what's in this directory
│ ├── design/ # architectural decisions
│ └── tests/ # HoTT-specific test suites
├── src/ # upstream Lean source (modified per locality principle)
│ ├── kernel/
│ │ ├── hott/ # new directory for HoTT kernel primitives
│ │ └── ... # upstream files; LEAN4-HTT: tags mark modifications
│ ├── Init/
│ │ ├── HoTT/ # new directory for Lean-side HoTT API
│ │ └── ... # upstream files
│ └── ... # rest of upstream src
├── tests/ # upstream tests (run unchanged)
└── ... # rest of upstream files
```
## CI and verification
Two test suites:
1. Upstream's full test suite, run in `LEAN_HOTT=OFF` mode. Must pass
with no regression.
2. The fork's HoTT-specific test suite under `hott/tests/`, run in
`LEAN_HOTT=ON` mode. Verifies the new primitives behave correctly.
CI runs both on every commit to the fork's master.
## Forbidden moves
The fork's HoTT extensions must not:
- Introduce UIP at the kernel level (defeats the purpose of forking)
- Depend on `Quot.sound` for HoTT primitive reductions
- Use `Classical.choice` in HoTT primitive implementations
- Add ad-hoc axioms beyond the minimum needed for soundness
If a HoTT primitive cannot be implemented constructively (no axioms, no
UIP-leaky principles), it doesn't go in the fork. This is the same
discipline polytropos enforces at the engine's object level.
## Maintenance
The fork's maintainer:
- Runs upstream sync per the cadence above
- Resolves conflicts preserving HoTT additions
- Updates `FORK_STRATEGY.md` when the strategy evolves
- Documents non-mechanical decisions in `hott/design/`
The fork is at `maxgit.wg/max/lean4-htt`.
## Phases
This is Phase 0: fork infrastructure (this file, directory structure,
remotes, sync workflow). No kernel modifications yet.
Subsequent phases add HoTT primitives:
- Phase 1: minimal `Path` + `Refl` + `J` (the foundational core)
- Phase 2: `transport` with full computational behavior
- Phase 3: HIT support
- Phase 4: cubical primitives (interval, faces, Glue) if needed for
polytropos's full spec
Each phase is gated on the previous landing and passing both test
suites.
## Related projects
- [polytropos](https://maxgit.wg/max/polytropos) — the cubical-transport
HoTT engine that depends on this fork.
- [Cubical Agda](https://github.com/agda/cubical) — the precedent for
adding cubical primitives to a host proof assistant.
- [topolei](https://maxgit.wg/max/topolei) — the prior project that
used Rust FFI for the computational kernel; informs the architectural
pattern for foundational extensions.