One-hole contexts and local refinement

One-hole contexts and local refinement

Matching retained and hidden counts does not establish that an operation changed only the selected region. HoleContext s e records a surrounding cut of the original Lean.Expr e, with one hole for the original expression s. Its siblings, constructors and payload parameters remain fixed. plug C S inserts the cut S : Cut s into that hole.

The pinned Lean kernel checks ten laws. In particular, filling the hole refines the original cut; every previously visible path remains visible. Two stronger equalities describe exactly which region changes. If q is the hole’s path:

outside q:  visible(C[S], p) = visible(C[T], p)
inside q:   visible(C[S], q ++ p) = visible(S, p)

Outside means that q is not a prefix of p. The outside equality holds for any two replacement cuts, including cuts with different visibility. It preserves the entire surrounding cut, rather than merely preserving its total size. Nested contexts compose as compose(C, D)[S] = C[D[S]]; their source routes concatenate in the same order.

The exact count identities are:

retained(C[S]) = retained(C[hole s]) + retained(S)
hidden(C[S]) + size(s) = hidden(C[hole s]) + hidden(S)

The model has all eleven structural child positions: both application fields, binder type/body fields of lambdas and foralls, the three let fields, metadata’s expression and a projection’s structure. Any of the twelve expression kinds may occupy the hole. Source names, binder information, universe parameters, metadata and the let’s nondependency flag remain parameters of the original expression; the operation does not rewrite or reindex them. An occurrence path, rather than a shared expression identifier, determines the hole.

Evidence

The native checker separately checks each theorem’s type, proof term and expected-type conversion with Kernel.check. Allowed axiom sets are subsets of propext and Quot.sound; plug_refines and fill_refines have no axioms. The general laws quantify over expressions, cuts and paths. They are not inferred from the finite examples.

The compiled fixture packet has 156 cases: twelve focus kinds in thirteen contexts (the root, eleven child positions and a nested shadowing example). Four replacement depths give 624 replacements. An independent reader reconstructs each source cut, replaces only the selected hole and compares the complete result, including literal payloads and sibling cuts. It checks 1,196 inside-path and 2,208 outside-path observations. Twenty-two changed-record controls must reject.

Payloads in these small fixtures use literal pinned-compiler representations. They are not a general Expr interchange decoder. Metadata fixtures use an empty metadata map. Some controls contain open variables or deliberately untyped surroundings; no fixture receives a proof-typing claim. The source-indexed laws preserve their original syntax regardless of whether it is well typed.

These laws extend the source-cut model. The browser replacement rule has separate finite implementation checks. This development does not prove the JavaScript, its lexical-link implementation, native type composition, semantic interpretation or human comprehension. No expanded large-proof tree is built by the browser rule; the fixtures here are small structural controls, not an AI-proof benchmark.

Reproduction

Only pinned core Lean and this repository’s public control sources are used. Private mathematical source projects are absent. Two isolated native reproductions must agree on compiled theorem and fixture records before publication. The packet records producer hashes; --check also compares a fresh native result with the published output.

python3 research/proof-atlas/local-cut-context/verify.py \
  --lean /absolute/path/to/lean-4.33.1/bin/lean \
  --workdir /absolute/path/to/new-private-workdir --check
node scripts/test-proof-atlas-local-cut-context.cjs

Definitions and proofs · Native fixture producer · Bounded native checker · Compiled records · Independent reader · Altered-record checks