Generate executable code together with formal proofs certifying safety and correctness properties in Isabelle/HOL or Coq. Use when building verified software, safety-critical systems, or when formal guarantees are required. Produces code with accompanying proofs for memory safety, bounds checking, functional correctness, invariant preservation, and termination. Supports extraction to OCaml/Haskell/SML and integration with existing codebases.
npx skills add https://github.com/ArabelaTso/Skills-4-SE --skill proof-carrying-code-generator
Generate executable code bundled with formal proofs that certify key safety and correctness properties.
Proof-carrying code (PCC) is executable code accompanied by formal proofs that certify specific properties. This skill helps generate:
The generated code can be extracted to mainstream languages (OCaml, Haskell, SML) while maintaining proof certificates.
Requirements
↓
Formal Specification
↓
Verified Implementation
↓
Proof Obligations
↓
Certified Code + Proofs
↓
Code Extraction
Start with formal specification, implement, then prove.
Steps:
Example (Isabelle):
(* Specification *)
definition sorted_spec :: "nat list ⇒ nat list ⇒ bool" where
"sorted_spec input output ≡ sorted output ∧ mset output = mset input"
(* Implementation *)
fun insertion_sort :: "nat list ⇒ nat list" where
"insertion_sort [] = []" |
"insertion_sort (x # xs) = insert x (insertion_sort xs)"
(* Correctness theorem *)
theorem insertion_sort_correct:
"sorted_spec input (insertion_sort input)"
proof (induction input)
case Nil
then show ?case by (simp add: sorted_spec_def)
next
case (Cons x xs)
then show ?case
using insert_sorted mset_insert
by (auto simp: sorted_spec_def)
qed
(* Extract code *)
export_code insertion_sort in SML file "sort.sml"
Start abstract, refine to concrete with proofs at each step.
Steps:
Example (Coq):
(* Abstract specification *)
Definition find_spec {A} (P : A → bool) (l : list A) : option A :=
(* Nondeterministic: any element satisfying P *)
...
(* Concrete implementation *)
Fixpoint find {A} (P : A → bool) (l : list A) : option A :=
match l with
| [] => None
| x :: xs => if P x then Some x else find P xs
end.
(* Refinement proof *)
Theorem find_refines : forall A P l,
find P l = find_spec P l.
Proof.
(* Proof that concrete refines abstract *)
Qed.
(* Extract *)
Extraction "find.ml" find.
Write code with annotations, generate proof obligations, prove them.
Steps:
Example (Coq with Program):
Require Import Program.
Program Definition safe_div (a b : nat) (H : b ≠ 0) : nat :=
a / b.
(* Proof obligation automatically generated *)
Next Obligation.
(* Prove division is safe *)
Qed.
Property: No buffer overflows, out-of-bounds access.
Pattern:
lemma array_access_safe:
"⟦ i < length arr ⟧ ⟹ ∃v. arr ! i = v"
by auto
fun safe_get :: "'a list ⇒ nat ⇒ 'a option" where
"safe_get [] _ = None" |
"safe_get (x # xs) 0 = Some x" |
"safe_get (x # xs) (Suc n) = safe_get xs n"
lemma safe_get_bounds:
"safe_get xs i = Some v ⟹ i < length xs"
by (induction xs i rule: safe_get.induct) auto
Property: No null pointer dereferences.
Pattern:
Definition safe_head {A} (l : list A) (H : l ≠ []) : A :=
match l with
| [] => match H eq_refl with end
| x :: _ => x
end.
Lemma safe_head_correct : forall A (l : list A) H,
l ≠ [] → safe_head l H = hd_error l.
Proof.
intros. destruct l; auto. contradiction.
Qed.
Property: All array accesses within bounds.
Pattern:
definition bounded_access :: "'a array ⇒ nat ⇒ 'a option" where
"bounded_access arr i = (if i < array_length arr
then Some (array_get arr i)
else None)"
lemma bounded_access_safe:
"bounded_access arr i = Some v ⟹ i < array_length arr"
by (simp add: bounded_access_def split: if_splits)
Property: Function computes correct result.
Pattern:
fun factorial :: "nat ⇒ nat" where
"factorial 0 = 1" |
"factorial (Suc n) = Suc n * factorial n"
function fact_spec :: "nat ⇒ nat" where
"fact_spec 0 = 1" |
"fact_spec n = n * fact_spec (n - 1)"
by auto
theorem factorial_correct:
"factorial n = fact_spec n"
by (induction n) auto
Property: Data structure invariants maintained.
Pattern:
Inductive BST : tree → Prop :=
| BST_leaf : BST Leaf
| BST_node : forall l x r,
BST l → BST r →
(forall y, In y l → y < x) →
(forall y, In y r → x < y) →
BST (Node l x r).
Fixpoint insert (x : nat) (t : tree) : tree :=
match t with
| Leaf => Node Leaf x Leaf
| Node l y r =>
if x <? y then Node (insert x l) y r
else if y <? x then Node l y (insert x r)
else t
end.
Theorem insert_preserves_BST : forall x t,
BST t → BST (insert x t).
Proof.
induction t; intros; simpl.
- constructor; constructor.
- inversion H; subst.
destruct (x <? n) eqn:E1.
+ (* Insert left *)
+ destruct (n <? x) eqn:E2.
* (* Insert right *)
* (* Equal, no change *)
Qed.
Property: Function always terminates.
Pattern:
function gcd :: "nat ⇒ nat ⇒ nat" where
"gcd a 0 = a" |
"gcd a b = gcd b (a mod b)"
by auto
termination
by (relation "measure (λ(a, b). b)") auto
lemma gcd_terminates:
"∃result. gcd a b = result"
by auto
For Isabelle-specific code generation, extraction, and certification patterns, see references/isabelle_pcc.md.
Key features:
For Coq-specific extraction, Program framework, and certification, see references/coq_pcc.md.
Key features:
For detailed safety and correctness property patterns, see references/safety_properties.md.
Categories include:
Specification:
definition binary_search_spec :: "nat list ⇒ nat ⇒ nat option" where
"binary_search_spec xs target = (
if sorted xs ∧ target ∈ set xs
then Some (THE i. i < length xs ∧ xs ! i = target)
else None)"
Implementation:
fun binary_search :: "nat list ⇒ nat ⇒ nat option" where
"binary_search xs target = bs_aux xs target 0 (length xs)"
fun bs_aux :: "nat list ⇒ nat ⇒ nat ⇒ nat ⇒ nat option" where
"bs_aux xs target low high = (
if low ≥ high then None
else let mid = (low + high) div 2 in
if xs ! mid = target then Some mid
else if xs ! mid < target then bs_aux xs target (mid + 1) high
else bs_aux xs target low mid)"
Safety proofs:
lemma bs_aux_bounds:
"⟦ bs_aux xs target low high = Some i; low ≤ high; high ≤ length xs ⟧
⟹ low ≤ i ∧ i < high"
proof (induction xs target low high rule: bs_aux.induct)
case (1 xs target low high)
then show ?case
by (auto simp: Let_def split: if_splits)
qed
lemma bs_aux_no_overflow:
"⟦ low ≤ high; high ≤ length xs ⟧
⟹ (low + high) div 2 < length xs"
by auto
Correctness proof:
theorem binary_search_correct:
"sorted xs ⟹ binary_search xs target = binary_search_spec xs target"
proof -
assume "sorted xs"
show ?thesis
proof (cases "target ∈ set xs")
case True
then show ?thesis
using binary_search_finds_target[OF `sorted xs` True]
by (simp add: binary_search_spec_def)
next
case False
then show ?thesis
using binary_search_not_found[OF `sorted xs` False]
by (simp add: binary_search_spec_def)
qed
qed
Code extraction:
export_code binary_search in SML file "binary_search.sml"
export_code binary_search in OCaml file "binary_search.ml"
Before finalizing proof-carrying code:
Pattern: Verify critical components, interface with unverified code.
Example:
(* Verified core *)
definition verified_sort :: "nat list ⇒ nat list" where
"verified_sort = insertion_sort"
theorem verified_sort_correct:
"sorted (verified_sort xs) ∧ mset (verified_sort xs) = mset xs"
by (simp add: verified_sort_def insertion_sort_correct)
(* Export for use in larger system *)
export_code verified_sort in OCaml file "verified_sort.ml"
Pattern: Build library of verified functions.
Example:
Module VerifiedList.
(* Verified operations *)
Definition safe_nth := ...
Definition safe_update := ...
Definition verified_map := ...
(* Correctness theorems *)
Theorem safe_nth_correct : ...
Theorem safe_update_correct : ...
Theorem verified_map_correct : ...
End VerifiedList.
(* Extract entire module *)
Extraction "verified_list.ml" VerifiedList.
For detailed guidance on specific aspects:
Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).
Automatically creates user-facing changelogs from git commits by analyzing commit history, categorizing changes, and transforming technical commits into clear, customer-friendly release notes. Turns hours of manual changelog writing into minutes of automated generation.
Use when implementation is complete, all tests pass, and you need to decide how to integrate the work - guides completion of development work by presenting structured options for merge, PR, or cleanup
Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).
React Native and Expo best practices for building performant mobile apps. Use when building React Native components, optimizing list performance, implementing animations, or working with native modules. Triggers on tasks involving React Native, Expo, mobile performance, or native platform APIs.
React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.
Next.js best practices - file conventions, RSC boundaries, data patterns, async APIs, metadata, error handling, route handlers, image/font optimization, bundling
Use when starting feature work that needs isolation from current workspace or before executing implementation plans - creates isolated git worktrees with smart directory selection and safety verification
Take arabelatso/proof-carrying-code-generator from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.