Skip to content

Commit 01c19a4

Browse files
fix(tg-0): Tangle.lean compiles cleanly + wire CI build oracle (#33)
Closes #32 (TG-0). Problem ======= Empirical audit on 2026-06-01 found `proofs/Tangle.lean` had **121 errors** on every Lean 4 version v4.9 through v4.16. The 2026-03-30 commit titled *"feat: add Lean 4 formal proofs — progress, preservation, determinism"* with body *"Zero sorry. ... Covers knot-theoretic compose/tensor/close operations"* was committed without ever compiling. No CI ran Lean, so the broken claim went undetected for ~2 months. Fix === **62 inserts / 51 deletes**, zero `sorry` / `axiom` / `admit` / `Admitted`. All 4 headline theorems preserved in full: - `progress` — well-typed closed terms are values or can step - `preservation` — stepping preserves types - `determinism` — the step relation is deterministic - `type_safety` — progress + preservation corollary Auxiliary lemmas (`canonical_*`, `value_no_step`, `generatorWidth_*`) also preserved. What changed mechanically: 1. `foldl_max_init`: replaced terse one-liner with explicit `rw [ih (max a (g.idx+1)), ih (max 0 (g.idx+1))]` — the old `rw [ih, ih (max 0 _)]` left omega with an unresolved metavariable. 2. `foldl_shift_init`: replaced `split <;> omega` (couldn't close the if-then-else interaction) with `by_cases hrest : rest = []` plus targeted simp/omega per branch. 3. `cases ht with | tComposeWord ... =>` and siblings (tTensorWord, tEqWord, tEqNum, tEqStr, tAddNum, tCloseWord, tPipeline): dropped one underscore per pattern; modern Lean does not bind Γ as a separate name when it unifies to `[]`. 4. Progress sub-goals for `composeIdL`/`composeIdR`/`tensorIdL`/ `tensorIdR`: removed spurious explicit args; `Step` constructors have only implicit args. 5. `composeWords` arm of preservation: added `rw [← generatorWidth_append]` so the resulting type matches. 6. `tensorWords` arm of preservation: replaced broken split/rename_i with explicit `have hgoal` and targeted `rw`. 7. `congrArg (·.compose _) (ih h)` and siblings: replaced left-side dot-notation sections (which produced `?m = ?m` failures because `_` became a fresh per-side metavar) with `rw [ih h]`. Right-side forms (`Expr.compose _ ·`) still work unchanged. CI build oracle =============== - `proofs/lean-toolchain`: pins `leanprover/lean4:v4.14.0`. Verified 0 errors on v4.10–v4.16 inclusive. - `.github/workflows/lean-proofs.yml`: builds `proofs/Tangle.lean` on every PR / push to `main` that touches `proofs/**` or the workflow. Two gates: (a) `lean Tangle.lean` returns 0 errors; (b) no `sorry`/`axiom`/`admit`/`Admitted` outside comments. - Future drift fails CI rather than landing silently — same shape as the ephapax `coq-build.yml` rule [[feedback-proof-pr-build-oracle-is-only-truth]]. Truthful narrative update ========================= - `PROOF-NARRATIVE.md` §2: adds "Build oracle" sub-section recording the 121→0 trajectory; cross-documents echo-types audit as NOT-RELEVANT (per [[proofs-must-check-and-cross-doc-echo-types]]). - `ASSUMPTIONS.md` changelog: new 2026-06-01 row noting TG-0 closure and the CI gate. Unblocks ======== - TG-1 (let-binding extension, #26) — was blocked on a base file that did not compile. Now unblocked. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 833f960 commit 01c19a4

5 files changed

Lines changed: 164 additions & 52 deletions

File tree

.github/workflows/lean-proofs.yml

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# SPDX-License-Identifier: MPL-2.0
2+
# Owner: Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
3+
#
4+
# Lean proof build oracle for proofs/Tangle.lean.
5+
#
6+
# Closes the TG-0 gap: prior to 2026-06-01, the Lean file claimed to prove
7+
# Progress / Preservation / Determinism / TypeSafety but had 121 errors on
8+
# every Lean 4 version 4.9-4.16, with no CI running it. This workflow makes
9+
# the build oracle the single source of truth — any future PR that breaks the
10+
# proofs fails CI rather than landing silently.
11+
#
12+
# Pinned via `proofs/lean-toolchain` to `leanprover/lean4:v4.14.0`. Verified
13+
# 0 errors on v4.10–v4.16 inclusive.
14+
15+
name: Lean Proofs
16+
17+
on:
18+
pull_request:
19+
paths:
20+
- 'proofs/**'
21+
- '.github/workflows/lean-proofs.yml'
22+
push:
23+
branches: [main]
24+
paths:
25+
- 'proofs/**'
26+
- '.github/workflows/lean-proofs.yml'
27+
workflow_dispatch: {}
28+
29+
permissions:
30+
contents: read
31+
32+
jobs:
33+
build:
34+
name: Build Lean proofs (oracle)
35+
runs-on: ubuntu-latest
36+
timeout-minutes: 15
37+
steps:
38+
- name: Checkout
39+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
40+
with:
41+
persist-credentials: false
42+
43+
- name: Install elan
44+
run: |
45+
curl -sSf https://raw.githubusercontent.com/leanprover/elan/master/elan-init.sh \
46+
| sh -s -- -y --default-toolchain none
47+
echo "$HOME/.elan/bin" >> "$GITHUB_PATH"
48+
49+
- name: Pin Lean toolchain from proofs/lean-toolchain
50+
working-directory: proofs
51+
run: |
52+
test -f lean-toolchain || { echo "::error::proofs/lean-toolchain missing"; exit 1; }
53+
echo "Using toolchain: $(cat lean-toolchain)"
54+
lean --version
55+
56+
- name: Build Tangle.lean (oracle)
57+
working-directory: proofs
58+
run: |
59+
set -euo pipefail
60+
lean Tangle.lean 2>&1 | tee /tmp/lean-output.txt
61+
errors=$(grep -c "error:" /tmp/lean-output.txt || true)
62+
if [ "$errors" -ne 0 ]; then
63+
echo "::error::Tangle.lean has $errors errors — see job output above."
64+
exit 1
65+
fi
66+
echo "Tangle.lean: 0 errors. Build oracle GREEN."
67+
68+
- name: Assert no sorry / axiom / admit slippage
69+
working-directory: proofs
70+
run: |
71+
set -euo pipefail
72+
banned_count=0
73+
for pat in '\bsorry\b' '\baxiom\b' '\badmit\b' '\bAdmitted\b'; do
74+
matches=$(grep -nE "$pat" Tangle.lean | grep -vE "^\s*--|^\s*/--|/-" || true)
75+
if [ -n "$matches" ]; then
76+
echo "::error::Forbidden token matching '$pat' in Tangle.lean:"
77+
echo "$matches"
78+
banned_count=$((banned_count + 1))
79+
fi
80+
done
81+
if [ "$banned_count" -ne 0 ]; then
82+
exit 1
83+
fi
84+
echo "No sorry/axiom/admit/Admitted found outside comments."

ASSUMPTIONS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,4 @@ date and reason.
7070
|------|--------|-----|
7171
| 2026-06-01 | Initial registry, scoped to Tangle metatheory + implementation refinement obligations | Audit |
7272
| 2026-06-01 | A-TG-9.1 reformulated under TG-9 Option B — accept LSP-only categories instead of pretending refinement (full Option A queued at #28). See `compiler/tangle-lsp/docs/lsp-diagnostic-categories.md`. | TG-9 Option B PR |
73+
| 2026-06-01 | TG-0 closed: `proofs/Tangle.lean` previously had 121 errors on Lean 4.9–4.16 (commit 8ce7be7 was committed without ever compiling). Repaired: 62/51 diff, 0 errors on Lean 4.10–4.16. CI oracle at `.github/workflows/lean-proofs.yml` pinned to v4.14.0 via `proofs/lean-toolchain`. Sorry/axiom/admit slippage check added. Closes hyperpolymath/tangle#32. | TG-0 PR |

PROOF-NARRATIVE.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,22 @@ delivered slice and the remaining gap explicit.
5252
## 2. Proven now
5353

5454
All 16 results live in [`proofs/Tangle.lean`](proofs/Tangle.lean)
55-
(Lean 4, ~560 LoC, no `sorry`, no `axiom`).
55+
(Lean 4, ~570 LoC, no `sorry`, no `axiom`).
56+
57+
**Build oracle.** As of 2026-06-01 (PR closing TG-0, hyperpolymath/tangle#32),
58+
the file is verified at every push/PR by `.github/workflows/lean-proofs.yml`,
59+
pinned to `proofs/lean-toolchain = leanprover/lean4:v4.14.0`. Empirical
60+
result on the original 2026-03-30 commit: 121 errors on every Lean 4
61+
version 4.9–4.16 — the file had never compiled. The current commit
62+
returns **0 errors**, verified locally on v4.10/4.11/4.12/4.13/4.14/4.15/4.16,
63+
with CI gating both `lean Tangle.lean` and a `sorry`/`axiom`/`admit`
64+
slippage check. Future drift will fail CI rather than land silently.
65+
66+
**Echo-types audit.** Per [[proofs-must-check-and-cross-doc-echo-types]]:
67+
echo-types is fibre-based loss-with-residue semantics — it has zero
68+
lambda-calculus / progress / preservation content. Verdict:
69+
**NOT-RELEVANT** for all four theorems below. Recorded once at
70+
`feedback_echo_types_audit_krl_tangle_quandledb_not_relevant.md`.
5671

5772
### Theorems (the main results)
5873

proofs/Tangle.lean

Lines changed: 62 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,10 @@ private theorem foldl_max_init (gs : List Generator) (a : Nat) :
214214
max a (gs.foldl (fun acc g => max acc (g.idx + 1)) 0) := by
215215
induction gs generalizing a with
216216
| nil => simp [List.foldl]
217-
| cons g rest ih => simp only [List.foldl]; rw [ih, ih (max 0 _)]; omega
217+
| cons g rest ih =>
218+
simp only [List.foldl]
219+
rw [ih (max a (g.idx + 1)), ih (max 0 (g.idx + 1))]
220+
omega
218221

219222
theorem generatorWidth_append (gs₁ gs₂ : List Generator) :
220223
generatorWidth (gs₁ ++ gs₂) = max (generatorWidth gs₁) (generatorWidth gs₂) := by
@@ -226,11 +229,14 @@ private theorem foldl_shift_init (gs : List Generator) (n a : Nat) :
226229
if gs = [] then a
227230
else max a (gs.foldl (fun acc g => max acc (g.idx + 1)) 0 + n) := by
228231
induction gs generalizing a with
229-
| nil => simp [List.foldl, List.map]
232+
| nil => simp
230233
| cons g rest ih =>
231-
simp only [List.map, List.foldl, List.cons_ne_nil, ↓reduceIte]
232-
rw [ih, foldl_max_init rest (max 0 _)]
233-
split <;> omega
234+
simp only [List.map, List.foldl, List.cons_ne_nil, if_false]
235+
rw [ih]
236+
rw [foldl_max_init rest (max 0 (g.idx + 1))]
237+
by_cases hrest : rest = []
238+
· subst hrest; simp [List.foldl]; omega
239+
· simp [hrest]; omega
234240

235241
theorem generatorWidth_shift (gs : List Generator) (n : Nat) :
236242
generatorWidth (shiftGenerators gs n) =
@@ -252,39 +258,39 @@ theorem progress : HasType [] e τ → IsValue e ∨ ∃ e', Step e e' := by
252258
| tBool => left; exact .boolLit _
253259
| tIdentity => left; exact .identity
254260
| tBraid => left; exact .braidLit _
255-
| tComposeWord _ _ _ n m h₁ h₂ =>
261+
| tComposeWord _ _ n m h₁ h₂ =>
256262
right
257263
rcases progress h₁ with hv₁ | ⟨e₁', hs₁⟩
258264
· rcases progress h₂ with hv₂ | ⟨e₂', hs₂⟩
259265
· rcases canonical_word hv₁ h₁ with ⟨rfl, _⟩ | ⟨gs₁, rfl, _⟩ <;>
260266
rcases canonical_word hv₂ h₂ with ⟨rfl, _⟩ | ⟨gs₂, rfl, _⟩
261267
· exact ⟨_, .composeIdId⟩
262-
· exact ⟨_, .composeIdL gs₂
263-
· exact ⟨_, .composeIdR gs₁
268+
· exact ⟨_, .composeIdL⟩
269+
· exact ⟨_, .composeIdR⟩
264270
· exact ⟨_, .composeWords⟩
265271
· exact ⟨_, .composeRight hv₁ hs₂⟩
266272
· exact ⟨_, .composeLeft hs₁⟩
267-
| tTensorWord _ _ _ n m h₁ h₂ =>
273+
| tTensorWord _ _ n m h₁ h₂ =>
268274
right
269275
rcases progress h₁ with hv₁ | ⟨e₁', hs₁⟩
270276
· rcases progress h₂ with hv₂ | ⟨e₂', hs₂⟩
271277
· rcases canonical_word hv₁ h₁ with ⟨rfl, _⟩ | ⟨gs₁, rfl, _⟩ <;>
272278
rcases canonical_word hv₂ h₂ with ⟨rfl, _⟩ | ⟨gs₂, rfl, _⟩
273279
· exact ⟨_, .tensorIdId⟩
274-
· exact ⟨_, .tensorIdL gs₂
275-
· exact ⟨_, .tensorIdR gs₁
280+
· exact ⟨_, .tensorIdL⟩
281+
· exact ⟨_, .tensorIdR⟩
276282
· exact ⟨_, .tensorWords⟩
277283
· exact ⟨_, .tensorRight hv₁ hs₂⟩
278284
· exact ⟨_, .tensorLeft hs₁⟩
279-
| tPipeline _ _ _ _ _ => exact .inr ⟨_, .pipeline⟩
280-
| tCloseWord _ _ n h =>
285+
| tPipeline _ _ _ _ => exact .inr ⟨_, .pipeline⟩
286+
| tCloseWord _ n h =>
281287
right
282288
rcases progress h with hv | ⟨e', hs⟩
283289
· rcases canonical_word hv h with ⟨rfl, _⟩ | ⟨gs, rfl, _⟩
284290
· exact ⟨_, .closeId⟩
285291
· exact ⟨_, .closeWord⟩
286292
· exact ⟨_, .closeStep hs⟩
287-
| tAddNum _ _ _ h₁ h₂ =>
293+
| tAddNum _ _ h₁ h₂ =>
288294
right
289295
rcases progress h₁ with hv₁ | ⟨e₁', hs₁⟩
290296
· rcases progress h₂ with hv₂ | ⟨e₂', hs₂⟩
@@ -293,7 +299,7 @@ theorem progress : HasType [] e τ → IsValue e ∨ ∃ e', Step e e' := by
293299
exact ⟨_, .addNums⟩
294300
· exact ⟨_, .addRight hv₁ hs₂⟩
295301
· exact ⟨_, .addLeft hs₁⟩
296-
| tEqWord _ _ _ n h₁ h₂ =>
302+
| tEqWord _ _ n h₁ h₂ =>
297303
right
298304
rcases progress h₁ with hv₁ | ⟨e₁', hs₁⟩
299305
· rcases progress h₂ with hv₂ | ⟨e₂', hs₂⟩
@@ -305,7 +311,7 @@ theorem progress : HasType [] e τ → IsValue e ∨ ∃ e', Step e e' := by
305311
· exact ⟨_, .eqBraids⟩
306312
· exact ⟨_, .eqRight hv₁ hs₂⟩
307313
· exact ⟨_, .eqLeft hs₁⟩
308-
| tEqNum _ _ _ h₁ h₂ =>
314+
| tEqNum _ _ h₁ h₂ =>
309315
right
310316
rcases progress h₁ with hv₁ | ⟨e₁', hs₁⟩
311317
· rcases progress h₂ with hv₂ | ⟨e₂', hs₂⟩
@@ -314,7 +320,7 @@ theorem progress : HasType [] e τ → IsValue e ∨ ∃ e', Step e e' := by
314320
exact ⟨_, .eqNums⟩
315321
· exact ⟨_, .eqRight hv₁ hs₂⟩
316322
· exact ⟨_, .eqLeft hs₁⟩
317-
| tEqStr _ _ _ h₁ h₂ =>
323+
| tEqStr _ _ h₁ h₂ =>
318324
right
319325
rcases progress h₁ with hv₁ | ⟨e₁', hs₁⟩
320326
· rcases progress h₂ with hv₂ | ⟨e₂', hs₂⟩
@@ -334,61 +340,66 @@ theorem preservation : HasType [] e τ → Step e e' → HasType [] e' τ := by
334340
intro ht hs
335341
induction hs generalizing τ with
336342
| composeLeft hs ih =>
337-
cases ht with | tComposeWord _ _ _ n m h₁ h₂ => exact .tComposeWord _ _ _ n m (ih h₁) h₂
343+
cases ht with | tComposeWord _ _ n m h₁ h₂ => exact .tComposeWord _ _ _ n m (ih h₁) h₂
338344
| composeRight _ hs ih =>
339-
cases ht with | tComposeWord _ _ _ n m h₁ h₂ => exact .tComposeWord _ _ _ n m h₁ (ih h₂)
345+
cases ht with | tComposeWord _ _ n m h₁ h₂ => exact .tComposeWord _ _ _ n m h₁ (ih h₂)
340346
| composeWords =>
341-
cases ht with | tComposeWord _ _ _ n m h₁ h₂ =>
342-
cases h₁; cases h₂; exact .tBraid _ _
347+
cases ht with | tComposeWord _ _ n m h₁ h₂ =>
348+
cases h₁; cases h₂
349+
rw [← generatorWidth_append]
350+
exact .tBraid _ _
343351
| composeIdL =>
344-
cases ht with | tComposeWord _ _ _ n m h₁ h₂ =>
352+
cases ht with | tComposeWord _ _ n m h₁ h₂ =>
345353
cases h₁ with | tIdentity => simp at *; exact h₂
346354
| composeIdR =>
347-
cases ht with | tComposeWord _ _ _ n m h₁ h₂ =>
355+
cases ht with | tComposeWord _ _ n m h₁ h₂ =>
348356
cases h₂ with | tIdentity => simp at *; exact h₁
349357
| composeIdId =>
350-
cases ht with | tComposeWord _ _ _ n m h₁ h₂ =>
358+
cases ht with | tComposeWord _ _ n m h₁ h₂ =>
351359
cases h₁; cases h₂; exact .tIdentity _
352360
| tensorLeft hs ih =>
353-
cases ht with | tTensorWord _ _ _ n m h₁ h₂ => exact .tTensorWord _ _ _ n m (ih h₁) h₂
361+
cases ht with | tTensorWord _ _ n m h₁ h₂ => exact .tTensorWord _ _ _ n m (ih h₁) h₂
354362
| tensorRight _ hs ih =>
355-
cases ht with | tTensorWord _ _ _ n m h₁ h₂ => exact .tTensorWord _ _ _ n m h₁ (ih h₂)
363+
cases ht with | tTensorWord _ _ n m h₁ h₂ => exact .tTensorWord _ _ _ n m h₁ (ih h₂)
356364
| tensorWords =>
357-
cases ht with | tTensorWord _ _ _ n m h₁ h₂ =>
365+
cases ht with | tTensorWord _ _ n m h₁ h₂ =>
358366
cases h₁; cases h₂
359-
simp [generatorWidth_append, generatorWidth_shift]
360-
split
361-
· rename_i hempty; subst hempty; simp [generatorWidth, List.foldl]; exact .tBraid _ _
362-
· rename_i hne
363-
have := HasType.tBraid ([] : Ctx) _
364-
simp [generatorWidth_append, generatorWidth_shift, hne] at this ⊢
365-
exact .tBraid _ _
367+
rename_i gs₁ gs₂
368+
have hgoal :
369+
generatorWidth (gs₁ ++ shiftGenerators gs₂ (generatorWidth gs₁))
370+
= generatorWidth gs₁ + generatorWidth gs₂ := by
371+
rw [generatorWidth_append, generatorWidth_shift]
372+
by_cases hempty : gs₂ = []
373+
· subst hempty; simp [generatorWidth, List.foldl]
374+
· simp [hempty]; omega
375+
rw [← hgoal]
376+
exact .tBraid _ _
366377
| tensorIdL =>
367-
cases ht with | tTensorWord _ _ _ n m h₁ h₂ =>
378+
cases ht with | tTensorWord _ _ n m h₁ h₂ =>
368379
cases h₁ with | tIdentity => simp at *; exact h₂
369380
| tensorIdR =>
370-
cases ht with | tTensorWord _ _ _ n m h₁ h₂ =>
381+
cases ht with | tTensorWord _ _ n m h₁ h₂ =>
371382
cases h₂ with | tIdentity => simp at *; exact h₁
372383
| tensorIdId =>
373-
cases ht with | tTensorWord _ _ _ n m h₁ h₂ =>
384+
cases ht with | tTensorWord _ _ n m h₁ h₂ =>
374385
cases h₁; cases h₂; exact .tIdentity _
375-
| pipeline => cases ht with | tPipeline _ _ _ _ h => exact h
376-
| closeStep hs ih => cases ht with | tCloseWord _ _ n h => exact .tCloseWord _ _ n (ih h)
386+
| pipeline => cases ht with | tPipeline _ _ _ h => exact h
387+
| closeStep hs ih => cases ht with | tCloseWord _ n h => exact .tCloseWord _ _ n (ih h)
377388
| closeWord => cases ht with | tCloseWord => exact .tIdentity _
378389
| closeId => cases ht with | tCloseWord => exact .tIdentity _
379-
| addLeft hs ih => cases ht with | tAddNum _ _ _ h₁ h₂ => exact .tAddNum _ _ _ (ih h₁) h₂
380-
| addRight _ hs ih => cases ht with | tAddNum _ _ _ h₁ h₂ => exact .tAddNum _ _ _ h₁ (ih h₂)
390+
| addLeft hs ih => cases ht with | tAddNum _ _ h₁ h₂ => exact .tAddNum _ _ _ (ih h₁) h₂
391+
| addRight _ hs ih => cases ht with | tAddNum _ _ h₁ h₂ => exact .tAddNum _ _ _ h₁ (ih h₂)
381392
| addNums => cases ht with | tAddNum => exact .tNum _ _
382393
| eqLeft hs ih =>
383394
cases ht with
384-
| tEqWord _ _ _ n h₁ h₂ => exact .tEqWord _ _ _ n (ih h₁) h₂
385-
| tEqNum _ _ _ h₁ h₂ => exact .tEqNum _ _ _ (ih h₁) h₂
386-
| tEqStr _ _ _ h₁ h₂ => exact .tEqStr _ _ _ (ih h₁) h₂
395+
| tEqWord _ _ n h₁ h₂ => exact .tEqWord _ _ _ n (ih h₁) h₂
396+
| tEqNum _ _ h₁ h₂ => exact .tEqNum _ _ _ (ih h₁) h₂
397+
| tEqStr _ _ h₁ h₂ => exact .tEqStr _ _ _ (ih h₁) h₂
387398
| eqRight _ hs ih =>
388399
cases ht with
389-
| tEqWord _ _ _ n h₁ h₂ => exact .tEqWord _ _ _ n h₁ (ih h₂)
390-
| tEqNum _ _ _ h₁ h₂ => exact .tEqNum _ _ _ h₁ (ih h₂)
391-
| tEqStr _ _ _ h₁ h₂ => exact .tEqStr _ _ _ h₁ (ih h₂)
400+
| tEqWord _ _ n h₁ h₂ => exact .tEqWord _ _ _ n h₁ (ih h₂)
401+
| tEqNum _ _ h₁ h₂ => exact .tEqNum _ _ _ h₁ (ih h₂)
402+
| tEqStr _ _ h₁ h₂ => exact .tEqStr _ _ _ h₁ (ih h₂)
392403
| eqNums => cases ht with
393404
| tEqNum => exact .tBool _ _
394405
| tEqWord _ _ _ _ h₁ => cases h₁
@@ -423,7 +434,7 @@ theorem determinism : Step e e₁ → Step e e₂ → e₁ = e₂ := by
423434
intro hs₁ hs₂
424435
induction hs₁ generalizing e₂ with
425436
| composeLeft hs ih => cases hs₂ with
426-
| composeLeft h => exact congrArg (·.compose _) (ih h)
437+
| composeLeft h => rw [ih h]
427438
| composeRight hv _ => exact absurd hs (value_no_step hv)
428439
| composeWords => exact absurd hs (value_no_step (.braidLit _))
429440
| composeIdL => exact absurd hs (value_no_step .identity)
@@ -453,7 +464,7 @@ theorem determinism : Step e e₁ → Step e e₂ → e₁ = e₂ := by
453464
| composeRight _ h => exact absurd h (value_no_step .identity)
454465
| composeIdId => rfl
455466
| tensorLeft hs ih => cases hs₂ with
456-
| tensorLeft h => exact congrArg (·.tensor _) (ih h)
467+
| tensorLeft h => rw [ih h]
457468
| tensorRight hv _ => exact absurd hs (value_no_step hv)
458469
| tensorWords => exact absurd hs (value_no_step (.braidLit _))
459470
| tensorIdL => exact absurd hs (value_no_step .identity)
@@ -494,7 +505,7 @@ theorem determinism : Step e e₁ → Step e e₂ → e₁ = e₂ := by
494505
| closeStep h => exact absurd h (value_no_step .identity)
495506
| closeId => rfl
496507
| addLeft hs ih => cases hs₂ with
497-
| addLeft h => exact congrArg (·.add _) (ih h)
508+
| addLeft h => rw [ih h]
498509
| addRight hv _ => exact absurd hs (value_no_step hv)
499510
| addNums => exact absurd hs (value_no_step (.num _))
500511
| addRight hv hs ih => cases hs₂ with
@@ -506,7 +517,7 @@ theorem determinism : Step e e₁ → Step e e₂ → e₁ = e₂ := by
506517
| addRight _ h => exact absurd h (value_no_step (.num _))
507518
| addNums => rfl
508519
| eqLeft hs ih => cases hs₂ with
509-
| eqLeft h => exact congrArg (·.eq _) (ih h)
520+
| eqLeft h => rw [ih h]
510521
| eqRight hv _ => exact absurd hs (value_no_step hv)
511522
| eqNums => exact absurd hs (value_no_step (.num _))
512523
| eqStrs => exact absurd hs (value_no_step (.str _))

proofs/lean-toolchain

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
leanprover/lean4:v4.14.0

0 commit comments

Comments
 (0)