Never unfold definitions downstream; erw or trailing rfl = missing API | API lemmas are the abstraction boundary | review ("missing API" smell) |
Terminal simp stays unsqueezed; non-terminal simp becomes simp only [...] | squeezed terminal calls bury the key lemmas and break on renames | style guide |
One focused goal at a time (· blocks) | kills goal-ordering fragility | linter.style.multiGoal |
show must not change the goal (use change) | stated goals stay honest | linter.style.show |
No set_option debug/trace/profiler or unscoped maxHeartbeats in final code | debugging scaffolding | linter.style.setOption |
State lemmas in simp-normal form, < not > | simp matches syntactically | simpNF linter |
| Golf only when the result is at least as readable; trivial results exempt | short ≠ better | review |
Fact instances are local, never global | global instances degrade all typeclass search | review |
| Name lemmas from their statements (see naming reference) | names become guessable without search | linter.style.nameCheck catches only __; #lint defsWithUnderscore and review cover more |
| Search a bare goal by shape before writing a helper or claiming an API gap | names are not always guessable from the target | exact?, apply?, type/source search |
| Generally one tactic invocation per line; a one-line closing proof is the exception | preserves readable proof structure without inventing an absolute rule | style guide |
Gate sorry with collectAxioms/#print axioms, never grep | grep matches comments, misses unproved helpers | axiom audit in CI |
| Prefer simp-lemma LHSs keyed on structure, not numerals; one spelling per constant | 2 ^ 32 never matches a goal normalized to 4294967296 | simpNF, review |
Re-derive every simp only list with simp? at its own site | lists do not transfer between look-alike goals | linter.flexible |
Every maxHeartbeats override is an unproven claim — measure before believing | copy-pasted budgets carry no information | #count_heartbeats, bisection |
Conditional simp lemma fires shallow but not deep → raise maxDischargeDepth (default 2) | chained side conditions truncate silently, no diagnostic | diagnosis (proof-style, simp discipline) |
| Every project-specific convention gets a custom linter, in CI from day one | review misses the 29-of-30 failure mode | @[env_linter] + #lint |