feat(jeg): judgement evidence graph — reify derivations, and CHECK them - #100
Conversation
`typecheck.ml` computes a type and discards how it got there; the Lean side
holds the derivation as a proof term but never exports it. So "why does this
typecheck?" had no answer you could hold, compare, or transmit.
That gap is not only about explanation. TG-3's obligations assert
infer [] e = some tau
— the RESULT type. Two different derivations reaching the same type are
indistinguishable to it. A reified derivation is comparable.
## What makes it EVIDENCE rather than a log
`derive` and `check` are independent. `check` does NOT call `derive`: it
re-establishes every node from its premises, recomputing each rule's side
condition. A graph that was hand-edited, truncated, or produced by some other
tool is rejected.
Without that independence this would be a log of what the checker did, which
proves nothing to anyone who does not already trust the checker.
Twelve forgery tests, each hand-building an ill-founded derivation:
a literal claiming the wrong type; a braid claiming the wrong width; an axiom
handed premises; a variable absent from its own recorded context; a compose
whose premises do not license its conclusion; residue projecting a non-echo;
an unknown rule name; a truncated derivation with a premise removed.
## The TG-11 test that matters
forged: T-Evidence concluding the CLAIM type is rejected
A warrant with evidence Word[2] for a claim Num. A forger wants
`evidence(w) : Num` — the claim — which would make the warrant FACTIVE. No
rule licenses that, so the graph refuses, with a message naming
epi_only_yields_evidence. The honest counterpart (concluding Word[2], the
evidence) is accepted.
That is non-factivity enforced at the evidence layer, not just in the proofs.
## Coverage, stated rather than implied
21 rules are fully validated: the literals, T-Var, the binary operators
(re-run through infer_binop on the PREMISE types), the echo and product
projections, and all three epistemic rules.
16 are deferred — T-Let, T-Match, T-App, T-Close, T-Pipeline and the unary
forms — whose side conditions are not yet re-derivable here. They are listed
EXPLICITLY rather than swallowed by a wildcard, so the gap is visible and an
unknown rule name is itself an error.
## Surface
tanglec --derive <file> indented proof tree per definition
tanglec --derive-dot <file> Graphviz DOT (nodes = judgements,
edges = conclusion <- premise)
Both CHECK the graph before printing it and exit non-zero if a check fails.
Relation to TG-11: a checked derivation is exactly what Epi[k, rho, tau] is
for — standpoint k holds evidence rho for claim tau, and the JEG is the rho.
The same discipline applies: holding a derivation is not the judgement being
true. You must check it. `check` is this module's SoundWarrant.sound.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Note Automatic reviews are paused because your trial's included automatic processing has been used for this period. Upgrade now, or comment "Gitar review" to run a review anytime. Code Review ✅ Approved 2 resolved / 2 findingsAdds the Judgement Evidence Graph to reify and independently check type derivations, but --derive exits 0 on type errors and DOT label escaping corrupts quotes. ✅ 2 resolved✅ Bug: --derive exits 0 on type errors despite gating claim
✅ Quality: DOT label escaping corrupts quotes and ignores backslashes
OptionsDisplay: compact → Showing less information. Comment with these commands to change the behavior for this request:
Was this helpful? React with 👍 / 👎 | Gitar |
typecheck.mlcomputes a type and discards how it got there; the Lean side holds the derivation as a proof term but never exports it. So "why does this typecheck?" had no answer you could hold, compare, or transmit.That gap isn't only about explanation. TG-3's obligations assert:
— the result type. Two different derivations reaching the same type are indistinguishable to it. A reified derivation is comparable.
What makes it evidence rather than a log
deriveandcheckare independent.checkdoes not callderive— it re-establishes every node from its premises, recomputing each rule's side condition. A graph that was hand-edited, truncated, or produced by some other tool is rejected.Without that independence this would be a log of what the checker did, which proves nothing to anyone who doesn't already trust the checker.
Twelve forgery tests, each hand-building an ill-founded derivation:
The TG-11 test that matters
A warrant with evidence
Word[2]for a claimNum. A forger wantsevidence(w) : Num— the claim — which would make the warrant factive. No rule licenses it, so the graph refuses, with a message namingepi_only_yields_evidence. The honest counterpart (concludingWord[2]) is accepted.That's non-factivity enforced at the evidence layer, not just in the proofs.
Coverage — stated, not implied
21 rules fully validated: literals,
T-Var, the binary operators (re-run throughinfer_binopon the premise types), echo and product projections, and all three epistemic rules.16 deferred:
T-Let,T-Match,T-App,T-Close,T-Pipelineand the unary forms, whose side conditions aren't yet re-derivable here. They're listed explicitly rather than swallowed by a wildcard — so the gap is visible, and an unknown rule name is itself an error.Surface
Both check before printing, and exit non-zero on failure. Real output:
Relation to TG-11
A checked derivation is exactly what
Epi[κ, ρ, τ]is for — standpoint κ holds evidence ρ for claim τ, and the JEG is the ρ. The same discipline applies: holding a derivation is not the judgement being true. You must check it.checkis this module'sSoundWarrant.sound.All suites green (new suite 19/19); corpus and RSR gates pass.
🤖 Generated with Claude Code