Write Formal Proof
Before writing any code
-
Read the specification section that the proof corresponds to. Know what you are proving and why the spec claims it is true.
-
Identify the proof strategy from the spec’s sketch or from mathematical reasoning. Do not start writing tactics until you know the argument.
-
Check what already exists. Read the formalization directory’s existing files. Do not duplicate definitions. Import what you need.
Writing the proof
-
State the theorem with a complete type signature. The type must precisely match the mathematical claim. If you cannot state the type without stubs or placeholders, you are missing prerequisites — write those first.
-
Write the proof body. In Lean, prefer tactic mode for multi-step proofs, term mode for one-liners. In Agda, proofs are always terms — use equational reasoning chains for clarity.
-
No placeholders. Every field of every record/class must have a real implementation, not
True,trivial, or a type that does not match the mathematical content. If a condition cannot be stated yet, document WHY and mark it withsorry(Lean) or a postulate (Agda) with an explicit comment explaining the gap.
Anti-slop checklist
Before marking a proof as complete, verify ALL of the following:
- No
sorryin the proof (Lean) or unexplained postulate (Agda) - No
Trueplaceholders standing in for real conditions - No placeholder types (e.g.,
Natstanding in forDefOp) - Every axiom/field is mathematically meaningful — it states what the spec says, not a vacuous condition
- Proof compiles. Run
lake build(Lean) oragda --check(Agda). If you cannot compile, say so explicitly rather than claiming the proof is done. - At least one concrete test instance exercises the new definitions (in Test/Trivial.lean or a test module)
- Worked examples demonstrate that the definitions match mathematical intuition
- Doc comments connect each definition to its spec section
After writing
-
Run the build. Do not commit unverified proofs. If the build environment is not available, state this explicitly and flag the proof as unverified.
-
Add test instances. Every new typeclass/record needs at least one concrete instance in the test file, with examples exercising derived lemmas on that instance.
-
Update the module root (SemioticUniverse.lean or Everything.agda) to import the new file.
Common failure modes
-
Writing type signatures that look right but contain stubs. Fix: Read the signature aloud as a mathematical statement. Does it say what the spec says?
-
Proving things about
Prop(where everything is trivial) and assuming they generalize. Fix: Also test on a nontrivial instance (e.g., a 3-element Heyting algebra). -
Writing comments that describe what the proof WILL do rather than what it DOES. Fix: Comments describe the current state. Future work goes in a roadmap, not in proof comments.