Repair Coq + Agda formal verification so it actually checks (axiom-free) - #48
Merged
Merged
Conversation
… checks The Coq formalization never compiled. Faults found and fixed: - `omega` (removed in Coq 8.12+) -> `lia`. - `value_eqb`/`phr_type_eqb` used a mutual `Fixpoint ... with` across phr_type and list, which Coq's guard checker rejects (not mutually inductive) -> rewritten with the nested-`fix` idiom. - `value_eqb_refl` invoked a nonexistent phr_value_rect P0/P1 eliminator -> two strong (nested) induction principles phr_type_ind'/phr_value_ind' added. - `phr_type_eq_dec`'s `decide equality` could not dispatch nested TRecord -> genuinely decidable now (this is the obligation that was unsound in Agda). - `preservation` was missing the T_List case, elided the record-field case, and lost the empty context in the EVar case -> reproved by induction on evaluation (keeps [] concrete); T_List via a list helper; field case closed by stating VT_Record over field_lookup. - `eval_deterministic` had a variable-name clash + miscalibrated bullets -> uniform IH-driven tactic. - `no_system_calls` was unsound (ELit (VString "system") satisfied it) and ill-typed (untyped existential) -> honest by-construction sandbox_no_call_form. - `totality` was malformed (Theorem ... with Fixpoint) and false as stated (no typing hypothesis) -> free_vars extracted; restated correctly and left as the lone explicit Admitted (termination, not yet mechanized, unused by core). Result: `coqc Phronesis.v` exits 0. `Print Assumptions` on preservation, eval_deterministic, type_safety, phr_type_eq_dec, subtype_trans, value_eqb_refl, literal_preservation, sandbox_no_call_form = "Closed under the global context" (axiom-free). SPDX header left unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…oved `totality` was the lone Admitted. Discharged as genuine progress-to-a-value: a well-typed closed expression always evaluates (the language has no loops or recursion). Proof is induction on the expression using the now-proved `preservation` + canonical value shapes to pin each operand; the value environment `ρ` is arbitrary because `[] ⊢ e ∈ τ` already forces closedness. The redundant `free_vars` hypothesis (and the previously-unsound free-vars-only statement) is dropped, since well-typedness in the empty context implies the expression is closed. Whole file now: `coqc Phronesis.v` exits 0 with NO Admitted/Abort/sorry, and `Print Assumptions totality` / `type_safety` = "Closed under the global context" (axiom-free). The mechanized safety story is complete: type safety (preservation), totality/progress, determinism, decidable type equality, subtyping transitivity, and by-construction sandbox isolation. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… --safe --without-K
The Agda formalization never typechecked. Fixes:
- Ctx's `_,_` clashed with Data.Product `_,_` (AmbiguousParseForApplication at
the context-extension sites) -> renamed to `_,,_`.
- Two `Data.Integer` imports listed names in both `using` and `renaming`
(RepeatedNamesInImportDirective) and re-imported `_+_`, clashing with
Data.Nat -> kept only the renamings.
- `_≟ᵗ_` (decidable type equality) was UNSOUND: it omitted the TRecord case and
used a single `_ ≟ᵗ _ = no (λ ())` catch-all, which --safe rejects
([ShouldBeEmpty]) since `TRecord fs ≡ TRecord gs` is inhabited by refl.
Rewritten as a mutual decision with `_≟ᶠ_` over the field list; every
same-head case is handled and the distinct-head pairs are enumerated.
- `_<ᵛ_` parsed as `a ≤ᵇ (b ∧ …)` (fixity) and used `_≡ᵛ_` at an ambiguous type
index -> parenthesised and indexed at TInt.
- Added `{-# OPTIONS --safe --without-K #-}`.
`agda Phronesis.agda` now exits 0 under --safe --without-K (no postulates, no
holes, termination + positivity checked), so the intrinsic-typing "type safety
is automatic" and "eval is total" claims now genuinely hold. SPDX header
unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
hyperpolymath
enabled auto-merge (rebase)
June 15, 2026 15:22
🔍 Hypatia Security ScanFindings: 30 issues detected
View findings[
{
"reason": "Action trufflesecurity/trufflehog@main needs attention",
"type": "unpinned_action",
"file": "secret-scanner.yml",
"action": "pin_sha",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"reason": "Issue in secret-scanner.yml",
"type": "missing_timeout_minutes",
"file": "secret-scanner.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in scorecard-enforcer.yml",
"type": "scorecard_publish_with_run_step",
"file": "scorecard-enforcer.yml",
"action": "split_scorecard_publish_job",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"reason": "binary_to_term without :safe option -- deserialization attack (1 occurrences, CWE-502)",
"type": "elixir_send_unsanitised",
"file": "/home/runner/work/phronesis/phronesis/lib/phronesis/compiler.ex",
"action": "flag",
"rule_module": "code_safety",
"severity": "high"
},
{
"reason": "Nominal-only SAST in phronesis: codeql.yml language matrix contains no language present in the repo and lacks `actions`, so CodeQL records zero results on every commit. Remediation: set the CodeQL matrix to `language: actions`.",
"type": "StaticAnalysis",
"file": "/home/runner/work/phronesis/phronesis",
"action": "auto_fix",
"rule_module": "scorecard",
"severity": "medium",
"remediation": "Add CodeQL or equivalent SAST workflow.",
"scorecard_check": "SAST"
},
{
"reason": "Repository has 3 non-main remote branch(es). Policy: single main branch only.",
"type": "GS007",
"file": ".",
"action": "delete_remote_branches",
"rule_module": "git_state",
"severity": "medium"
},
{
"reason": "Code scanning (Hypatia): hypatia/structural_drift/SD007 -- Hypatia structural_drift: SD007 -- 3 day(s) old",
"type": "CSA001",
"file": ".claude/CLAUDE.md",
"action": "review",
"rule_module": "code_scanning_alerts",
"severity": "medium"
},
{
"reason": "Code scanning (Hypatia): hypatia/structural_drift/SD007 -- Hypatia structural_drift: SD007 -- 3 day(s) old",
"type": "CSA001",
"file": ".claude/CLAUDE.md",
"action": "review",
"rule_module": "code_scanning_alerts",
"severity": "medium"
},
{
"reason": "Code scanning (Hypatia): hypatia/structural_drift/SD007 -- Hypatia structural_drift: SD007 -- 3 day(s) old",
"type": "CSA001",
"file": ".claude/CLAUDE.md",
"action": "review",
"rule_module": "code_scanning_alerts",
"severity": "medium"
},
{
"reason": "Code scanning (Hypatia): hypatia/structural_drift/SD007 -- Hypatia structural_drift: SD007 -- 3 day(s) old",
"type": "CSA001",
"file": ".claude/CLAUDE.md",
"action": "review",
"rule_module": "code_scanning_alerts",
"severity": "medium"
}
]Powered by Hypatia Neurosymbolic CI/CD Intelligence |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this is
A ground-truth audit of Phronesis's verification layer found that none of the three machine-checked proof files had ever compiled — the "120+ theorems / Mechanized: Coq, Lean4, Agda" claims in
theorem-index.mdand the "100% production-ready" inANALYSIS-COMPLETE.mdwere not backed by anything a tool checks (academic/TODO.mdis the honest doc). This PR makes the Coq and Agda formalizations genuinely check.Coq —
academic/formal-verification/coq/Phronesis.v(fully proved, axiom-free)The file never compiled. Faults found & fixed:
omega(removed in Coq 8.12+) →lia.value_eqb/phr_type_eqbused a mutualFixpoint … withacrossphr_typeandlist, which Coq's guard checker rejects (they aren't mutually inductive) → rewritten with the nested-fixidiom.value_eqb_reflinvoked a nonexistentphr_value_rectP0/P1 eliminator → two strong (nested) induction principlesphr_type_ind'/phr_value_ind'.phr_type_eq_dec'sdecide equalitycouldn't dispatch the nestedTRecord→ now genuinely decidable (the same obligation that was unsound in Agda).preservationwas missing theT_Listcase, elided the record-field case, and lost the empty context inEVar→ reproved by induction on evaluation (keeps[]concrete);T_Listvia a list helper; field case closed by statingVT_Recordoverfield_lookup.eval_deterministichad a variable-name clash + miscalibrated bullets → uniform IH-driven tactic.no_system_callswas unsound (ELit (VString "system")satisfied it) and ill-typed → honest by-constructionsandbox_no_call_form.totalitywas malformed (Theorem … with Fixpoint) and false as stated (no typing hypothesis) → restated correctly and discharged as genuine progress-to-a-value.Result:
coqc Phronesis.vexits 0, noAdmitted/Abort/sorry, andPrint Assumptionsonpreservation,totality,eval_deterministic,type_safety,phr_type_eq_dec,subtype_trans,value_eqb_refl,sandbox_no_call_form= "Closed under the global context" (axiom-free).Agda —
academic/formal-verification/agda/Phronesis.agda(checks under--safe --without-K)Ctx's_,_clashed withData.Product._,_→ renamed to_,,_.Data.Integerimports listed names in bothusingandrenaming(and re-imported_+_, clashing withData.Nat) → kept only the renamings._≟ᵗ_was unsound: it omitted theTRecordcase and used a single_ ≟ᵗ _ = no (λ ())catch-all, which--saferejects (TRecord fs ≡ TRecord gsis inhabited byrefl) → rewritten as a mutual decision with_≟ᶠ_over the field list, every same-head case handled and distinct-head pairs enumerated._<ᵛ_parsed asa ≤ᵇ (b ∧ …)(fixity) and used_≡ᵛ_at an ambiguous index → parenthesised + indexed atTInt.{-# OPTIONS --safe --without-K #-}.So the intrinsic-typing "type safety is automatic" and "
evalis total" claims now genuinely hold.Notes
Apache-2.0 OR MIT) left unchanged.Phronesis.lean—sorry, needs lake+Mathlib), TLA+ (never model-checked), the multi-surface semantics drift, and the AST representation drift remain open and are not addressed here.How to verify
🤖 Generated with Claude Code