Skip to content

Commit dae4e75

Browse files
Merge pull request #3 from dollspace-gay/feature/5i5F-Y4vs-spike-1-the-substkit-toy-lean-implement-only-req-1
SPIKE-1: the de Bruijn SubstKit toy (Lean) — sdenote_push_lift + sdenote_subst, axiom-clean
2 parents 4f56537 + fc09df4 commit dae4e75

13 files changed

Lines changed: 1885 additions & 0 deletions

.design/m0-spikes.md

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
# Feature: M0 — the two de-risking spikes (SPIKE-1 SubstKit toy, SPIKE-2 normalizer probe)
2+
3+
## Summary
4+
5+
The two week-one spikes from the RFC-1 program plan §1, specified to
6+
opening-an-issue precision. SPIKE-1 (the SubstKit toy) de-risks the
7+
stage-2 binder-metatheory grind — risk row 1 of the metatheory sketch,
8+
fallback F-A — by proving the two load-bearing de Bruijn lemmas end to end
9+
on a 3-constructor toy formula language before `Strat/SubstKit.lean` is
10+
scheduled. SPIKE-2 (the normalizer probe) de-risks the stage-2 TV-query
11+
design — risk row 3, fallback F-C — by measuring the syntactic-equality
12+
hit rate of a prototype normalizer over the conformance corpus's
13+
combinator contracts in raw-quantifier form. Both gate M0: no stage-1 or
14+
stage-2 implementation issue opens until both acceptance criteria are met.
15+
Umbrella: `.design/thermite2-program.md` (REQ-1). Baseline:
16+
`dollspace-gay/Thermite @ c46da3ac` or later.
17+
18+
## Requirements
19+
20+
### SPIKE-1 — the SubstKit toy
21+
22+
- REQ-1: A toy formula language lives at `lean/Thermite/Spike/SubstKit.lean`
23+
inside the existing lake package (`lean/lakefile.toml`), namespace
24+
`Thermite.Spike`, core-Lean-only (no Mathlib import — the same hot-path
25+
discipline as `lean/Thermite/Denote.lean`). Exactly three `Frm`
26+
constructors (one atom, one connective, one binder) over a de Bruijn
27+
term language with `lift` and `subst`, denoting into `Bool`. The carrier
28+
is *parametric*, not fixed: a `CarrierAssign`-lite with one opaque sort
29+
carrying a **hand-rolled finiteness witness** — an enumeration `List`
30+
plus a completeness proof (`∀ x, x ∈ enum`) and `DecidableEq` (core
31+
Lean, via `deriving`), **not** Mathlib's `Fintype`. This is a
32+
deliberate correction to the metatheory sketch's CarrierAssign (which
33+
literally writes `Fintype`, a Mathlib type, contradicting the sketch's
34+
own §4 core-Lean-only-hot-path claim): SPIKE-1 must determine whether
35+
finite-carrier `Bool`-denotation can stay core-Lean-only with a
36+
hand-rolled witness, because "fights universe/`Decidable` plumbing" is
37+
one of the two failure signals the spike exists to probe, and the
38+
Mathlib-vs-core verdict is itself a stage-2 `Strat/Carrier.lean` input.
39+
(The lakefile pulls Mathlib transitively via the `smt` require, so a
40+
`Fintype` import would *compile* — which is exactly why the discipline
41+
must be enforced by intent here, not by the build failing.)
42+
- REQ-2: `sdenote_push_lift` and `sdenote_subst` (the metatheory sketch
43+
§4's statement shapes, specialized to the toy) are proven end to end:
44+
zero `sorry`, axioms of both lemmas ⊆ {propext, Classical.choice,
45+
Quot.sound} under `#print axioms`.
46+
- REQ-3: A micro-pin `lean/Thermite/Spike/PinBrokenLift.lean` refutes a
47+
deliberately broken `lift` (off-by-one cutoff shift) in the repo's
48+
established `Pin*.lean` style: the wrong lemma instance is disproven on
49+
a concrete small carrier via `decide`.
50+
- REQ-4: The conventions note — the spike's real deliverable — lands at
51+
`.design/strat/substkit-conventions.md` (one page): lift direction,
52+
environment push order, binder-traversal convention, the exact lemma
53+
statement shapes as proven (verbatim-inheritable by
54+
`lean/Thermite/Strat/Syntax.lean`), the final lemma count, the
55+
**carrier verdict** (did the hand-rolled finiteness witness keep the
56+
denotation core-Lean-only, or was Mathlib's `Fintype` needed? — a
57+
direct input to stage-2 `Strat/Carrier.lean` and a resolution of the
58+
metatheory sketch's §2/§4 tension), and an
59+
explicit failure-signal verdict: if the toy needed more than 40 lemmas
60+
or the instance plumbing fought back, the note says so and a fallback
61+
F-A review (locally nameless / single-prefix S₂⁻) is opened before the
62+
real SubstKit is scheduled.
63+
64+
### SPIKE-2 — the normalizer probe
65+
66+
- REQ-5: The fixture set is built per **combinator shape**, not per
67+
instance, to keep the hit-rate denominator meaningful. For each of the
68+
(≤8) registry combinator shapes that appears, write two raw-quantifier
69+
S₂ expansion templates: a production-style spelling (following the
70+
shape `thermite-lower/src/lower.rs` emits for that combinator today)
71+
and a reference-style spelling (following `lean/Thermite/RefEncode.lean`).
72+
Apply each shape's templates to (a) every combinator-bearing clause in
73+
`conformance/*.th` — which the plan analysis confirms is **only
74+
`binary_search.th`, 4 clauses** (`req sorted`, the `ens` None-arm
75+
`forall_in`, `inv forall_below`, `inv forall_from`) — and (b) a
76+
generator-drawn sample of instances of those same shapes from
77+
`thermite-tv/src/gen.rs`'s `gen_combinator` (≥ 5 per shape), so the
78+
denominator is ≥ ~30 rather than 4. Fixture home:
79+
`thermite-tv/tests/fixtures/strat_probe/`, one file per instance pair,
80+
README naming the source: a scheme-validated address for `inv`
81+
clauses (`binary_search.loop#1.inv#2`/`inv#3`) and an informal
82+
designation for `req`/`ens` clauses (`binary_search.req`,
83+
`binary_search.ens.None`), since `thermite-syntax/src/address.rs`
84+
addresses loop/inv/dec but not req/ens.
85+
- REQ-6: A prototype normalizer at `thermite-tv/src/normalize.rs`
86+
experimental, exported but not referenced by any TV pipeline code path —
87+
implementing the four passes from metatheory §8.2 layer 1: NNF, prenex,
88+
canonical bound-name/de Bruijn form, atom ordering. Unit tests cover
89+
each pass on the fixtures (no soundness lemmas in the spike — those are
90+
stage-2 work; the spike wants the *number*).
91+
- REQ-7: The hit rate — the fraction of fixture pairs whose normalized
92+
forms are syntactically equal — is computed by a test/bin target,
93+
reported as a number in the SPIKE-2 issue and recorded in the fixtures
94+
README, **broken out two ways**: the corpus-only rate (n=4, flagged as
95+
small-n and not threshold-bearing on its own) and the
96+
corpus+generated rate (n ≥ ~30, the threshold-bearing number). The
97+
decision rule from the program plan is then applied to the
98+
corpus+generated rate and recorded: hit rate ≥ 90% → the stage-2
99+
semantic TV phase ships as a thin fallback; below → a dedicated
100+
quantified-equivalence-query design issue opens before stage 2
101+
commits. The per-shape breakdown is also reported so a single
102+
pathological shape is visible rather than averaged away.
103+
104+
### The gate
105+
106+
- REQ-8: M0 closes only when AC-1 through AC-7 hold. Per the umbrella's
107+
Q-TRACK split: each spike gets a GH issue on `dollspace-gay/Thermite`
108+
(gate-visible), with implementation increments tracked as crosslink
109+
issues referencing it. No stage-1 or stage-2 implementation issue opens
110+
before both GH spike issues close with results.
111+
112+
## Acceptance Criteria
113+
114+
- [ ] AC-1: `lake build` (from `lean/`) is green with the two Spike files
115+
present; `grep -r sorry lean/Thermite/Spike/` returns nothing;
116+
`import Mathlib` (and any `Mathlib.*` import) is absent from the Spike
117+
files (the core-Lean-only discipline); `#print axioms` on
118+
`sdenote_push_lift` and `sdenote_subst` shows only the gated three or
119+
fewer, run as a spike-local probe (not via `make audit`, whose theorem
120+
list is fixed and must not be perturbed by Spike files). (REQ-1, REQ-2)
121+
- [ ] AC-2: `PinBrokenLift.lean` contains a `lift` variant differing only
122+
in the cutoff arithmetic, and a `decide`-discharged theorem showing the
123+
push/lift lemma *fails* for it on a concrete carrier. (REQ-3)
124+
- [ ] AC-3: `.design/strat/substkit-conventions.md` exists with all six
125+
required sections (lift direction, push order, traversal, statement
126+
shapes, lemma count, carrier verdict) and a one-line failure-signal
127+
verdict. (REQ-4)
128+
- [ ] AC-4: If the verdict reports >40 lemmas or instance-plumbing
129+
fights, an F-A review issue exists before any `Strat/SubstKit.lean`
130+
issue is opened; otherwise the note states the count and that no
131+
trigger fired. (REQ-4)
132+
- [ ] AC-5: Each appearing combinator shape has production-style and
133+
reference-style expansion templates; they are applied to all 4
134+
`binary_search.th` clauses and to ≥5 generator-drawn instances per
135+
shape, yielding ≥ ~30 fixture pairs under
136+
`thermite-tv/tests/fixtures/strat_probe/`; the README lists each
137+
source (scheme-validated address for `inv`, informal for `req`/`ens`);
138+
`cargo test -p thermite-tv` passes the normalizer unit tests.
139+
(REQ-5, REQ-6)
140+
- [ ] AC-6: No module in the TV pipeline path imports
141+
`thermite_tv::normalize` (mechanically: `grep -rn "normalize" thermite-tv/src/ forge/src/` shows
142+
no non-test, non-`normalize.rs` consumer). (REQ-6)
143+
- [ ] AC-7: Both hit-rate numbers (corpus-only n=4, flagged small-n; and
144+
corpus+generated n ≥ ~30, threshold-bearing) plus the per-shape
145+
breakdown appear in the SPIKE-2 GH issue and the fixtures README, with
146+
the decision rule's branch recorded against the corpus+generated rate;
147+
if < 90%, a quantified-equivalence design issue exists. (REQ-7)
148+
- [ ] AC-8: Two GH spike issues exist (open before any stage-labeled
149+
issue) quoting the acceptance text from the program plan §1 (GH issue
150+
#2, third comment — quoted via `gh issue view 2`, since the program
151+
plan lives as an issue comment, not a repo file), and both are closed
152+
with results before any stage-1/stage-2 implementation issue opens.
153+
(REQ-8)
154+
155+
## Architecture
156+
157+
**SPIKE-1.** Lives inside the audited lake package
158+
(`lean/lakefile.toml`) as a `Thermite.Spike` namespace — zero new build
159+
plumbing, and the de Bruijn conventions get proven against the exact
160+
toolchain pin (`lean/lean-toolchain`) that `Strat/` will use. The
161+
`make audit` axiom probe targets a fixed theorem list, so Spike files
162+
don't perturb it; the spike's own axiom discipline is checked by AC-1
163+
directly. Style models in-tree: `lean/Thermite/Denote.lean` (Bool-valued
164+
total denotation), the `lean/Thermite/Pin*.lean` battery (the
165+
refute-a-plausibly-wrong-neighbor shape REQ-3 copies). The whole
166+
`Spike/` directory is deletable scaffolding: it is removed in the same
167+
change that lands `lean/Thermite/Strat/Syntax.lean` inheriting its
168+
conventions, with the conventions note (`.design/strat/`) as the
169+
surviving artifact — the note also seeds the `.design/strat/` area where
170+
stage-2 house docs will live.
171+
172+
**SPIKE-2.** Lives in `thermite-tv` because its production successor is
173+
stage-2's two-phase TV (metatheory §8.2): the prototype normalizer
174+
evolves in place rather than being rewritten. `thermite-tv/src/gen.rs`
175+
(the SplitMix64 generator) and the existing TV pipeline are untouched —
176+
`normalize.rs` is a leaf module consumed only by its tests and the
177+
hit-rate target until stage 2 wires it in behind `nnf_sound`/
178+
`prenex_sound` lemmas. The expansion templates are hand-written because
179+
neither emitter exists yet for stratified forms: the production-style
180+
spelling mimics `thermite-lower/src/lower.rs`'s current combinator
181+
emission conventions, the reference-style mimics
182+
`lean/Thermite/RefEncode.lean`'s — the two real columns the stage-2 TV
183+
will eventually compare. The hand-work is bounded *per combinator
184+
shape* (≤8 shapes), then instantiated across the 4 corpus clauses plus
185+
generator-drawn instances (read out of the existing `gen_combinator`
186+
no new generator productions, those are stage-2 binder work) so the
187+
threshold-bearing denominator is meaningful rather than n=4. This is the
188+
plan analysis's most material correction: a 90% bar over 4 clauses is
189+
4/4, which the corpus alone cannot support. This mimicry is the probe's known
190+
approximation, and it biases the measured hit rate *downward* if
191+
anything (real stage-2 emitters can be nudged toward convergence,
192+
fallback F-C step 1), so a high measured rate is trustworthy evidence
193+
and a low one triggers the design issue — the asymmetry is safe.
194+
195+
**What the spikes deliberately do not do:** no soundness lemmas for the
196+
normalizer passes, no `Strat/` modules, no classifier, no changes to
197+
`forge/`, no generator binder productions. Each of those belongs to a
198+
stage with its own design pass.
199+
200+
## Open Questions
201+
202+
None. The two genuine candidates — fixture format and emission-spelling
203+
derivation — are resolved by adopted defaults above (plain fixture files
204+
under `thermite-tv/tests/fixtures/strat_probe/`; spellings derived from
205+
the v1 emitters' current shapes), both cheap to revisit at stage-2
206+
design time.
207+
208+
## Out of Scope
209+
210+
- The real `Strat/SubstKit.lean` (~25-lemma kit) and all
211+
`lean/Thermite/Strat/` modules — stage 2.
212+
- Normalizer soundness lemmas (`nnf_sound`, `prenex_sound`) and wiring
213+
the normalizer into TV — stage 2.
214+
- The classifier, the sort graph, restratification — stage 2.
215+
- Generator binder productions in `thermite-tv/src/gen.rs` — M2b.
216+
- Any `forge/` or `thermite-syntax/` change — stage 1.
217+
218+
---
219+
220+
*M0 spike spec · child of `.design/thermite2-program.md` (REQ-1) ·
221+
sources: RFC-1 program plan §1, metatheory sketch §4/§8.2/§11 ·
222+
baseline `dollspace-gay/Thermite @ c46da3ac`.*

.design/m0-spikes.pipeline.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"schema_version": 1,
3+
"design_doc": ".design/m0-spikes.md",
4+
"doc_hash": "sha256:1abfb05418575ebcb9f43c5d0863242be08128e03185f01eeb38b7bbc3a45551",
5+
"stage": "planning",
6+
"plans": [
7+
{
8+
"agent_id": "driver--plan-m0-the-two-de-risking-spikes-spike-1-substkit-toy-9c56",
9+
"worktree": "/Users/maxine/code/.personal/Thermite/.worktrees/plan-m0-the-two-de-risking-spikes-spike-1-substkit-toy-9c56",
10+
"started_at": "2026-06-12T21:08:06.264052+00:00",
11+
"status": "running",
12+
"blocking_gaps": 0,
13+
"advisory_gaps": 0
14+
}
15+
],
16+
"runs": []
17+
}

0 commit comments

Comments
 (0)