specreview
Review F*/Pulse specifications for completeness, strength, and usability
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
Review F*/Pulse specifications for completeness, strength, and usability
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Use the F* MCP server for interactive, incremental typechecking of F* and Pulse code
Verify F* and Pulse code with fstar.exe and interpret errors
Extract verified F*/Pulse code to C via KaRaMeL (.krml intermediate representation)
Structure a new F*/Pulse verification project with Makefile and directory layout
Systematic workflows for debugging F*/Pulse verification failures
Debug F* queries sent to Z3, diagnosing proof instability and performance issues
Based on SOC occupation classification
| name | specreview |
| description | Review F*/Pulse specifications for completeness, strength, and usability |
| tools | Read, Bash, Grep |
This skill is used when:
For each function with a specification, verify:
❌ Weak: ensures (result >= 0) — proves a type property, not correctness
✅ Strong: ensures (result == factorial n) — proves functional correctness
❌ Weak: ensures (is_valid_flow result) — proves a structural property
✅ Strong: ensures (flow_value result == max_flow graph) — proves optimality
Every imperative implementation should have a postcondition referencing the corresponding pure spec function:
fn sort_impl (arr: array int) (n: SizeT.t)
(#s: erased (Seq.seq int))
requires A.pts_to arr s ** pure (SZ.v n == Seq.length s)
ensures exists* s'.
A.pts_to arr s' **
pure (
Seq.length s' == Seq.length s /\ // same length
sorted s' /\ // result is sorted
permutation s s' // result is a permutation of input
)
NOT just: ensures exists* s'. A.pts_to arr s' ** pure (sorted s')
(This doesn't prove the output is related to the input!)
Check the .fsti file:
.fsti hides the postcondition, callers cannot reason about the result// BAD .fsti: hides the correctness property
val dijkstra (g: graph) (src: vertex) : ST (array nat) ...
// No ensures clause visible!
// GOOD .fsti: exposes the spec connection
val dijkstra (g: graph) (src: vertex) : ST (array nat)
(requires ...)
(ensures fun dist -> forall v.
dist.[v] == shortest_path_weight g src v)
Verify that the postcondition is stated in terms a caller can work with:
For algorithm implementations, check against the algorithm's mathematical guarantees:
| Algorithm | Must Prove |
|---|---|
| Sorting | Output is sorted AND a permutation of input |
| Shortest path | Distances are actual shortest paths, not just "some path" |
| MST | Result is a spanning tree AND has minimum weight |
| Search | Returns correct index AND element equality |
| Union-Find | Operations maintain equivalence relation correctly |
| Max-flow | Flow value equals the max-flow (not just "a valid flow") |
// WEAK: proves nothing about what the function computes
val lookup : table -> key -> option value
// STRONG: proves the lookup matches the logical model
val lookup : t:table -> k:key -> r:option value{r == Table.find (model t) k}
// WEAK: only proves the output is a tree, not that it's the MST
ensures (is_spanning_tree result graph)
// STRONG: proves it's minimal among all spanning trees
ensures (is_spanning_tree result graph /\
forall t. is_spanning_tree t graph ==> weight result <= weight t)
// WEAK: uses implementation-internal predicate
ensures (imp_valid_state result)
// STRONG: connects to spec via a correspondence lemma
ensures (model result == Spec.expected_state input)
// WEAK: sorting — doesn't prove output relates to input
ensures (sorted result)
// STRONG: proves it's a sorted permutation of the input
ensures (sorted result /\ permutation_of result input)
When reviewing a .fsti file:
requires/ensuresFor the pure spec module: