The formal tier's input is hand-authored, and its serde forms are easy to guess
wrong (PascalCase enums, a stringified ContentAddress, JR-N rigor). Removes that
friction without touching the upstream schema serde:
- formal.example.json — a working, copy-pasteable template (the netting
postcondition), with the gotchas spelled out in an ignored _comment key.
- the FormalSpec doc and the parse-error message now name the exact forms and
point at the template.
- a test deserializes the shipped template and checks its indices, so it can
never drift from the schema.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
25 lines
1.3 KiB
JSON
25 lines
1.3 KiB
JSON
{
|
|
"_comment": "Copy to <workspace>/.joule-fix/formal.json to enable the formally-verified fix tier. Delete this _comment key (or keep it — unknown keys are ignored). Serde forms that bite if you guess: rigor_target is one of JR-1..JR-4 (uppercase); enb_ref is a STRING 'sha2-256:<64-hex>', not an object; kind is one of Trivial|Arithmetic|Decidable|General|Hard; grounding is one of Ungrounded|HumanReviewed|CrossChecked (all PascalCase). 'obligation' indexes the contract's obligations in declaration order: pre[0..], then post, then inv, then frame.",
|
|
"contract": {
|
|
"joulecontract": "joulecontract/0.6",
|
|
"subject": "settlement netting — net(debits, credits)",
|
|
"rigor_target": "JR-2",
|
|
"pre": ["debits and credits are integers"],
|
|
"post": ["when debits == credits, the net is zero"],
|
|
"inv": [],
|
|
"frame": ["the settlement ledger row"],
|
|
"ceiling": {
|
|
"enpi_joules": 10.0,
|
|
"unit": "joules/settlement",
|
|
"enb_ref": "sha2-256:0000000000000000000000000000000000000000000000000000000000000000"
|
|
}
|
|
},
|
|
"formalizations": [
|
|
{
|
|
"obligation": 1,
|
|
"statement": "(declare-const debits Int)(declare-const credits Int)(declare-const net Int)(assert (= net (- debits credits)))(assert (= debits credits))(assert (not (= net 0)))",
|
|
"kind": "Decidable",
|
|
"grounding": "CrossChecked"
|
|
}
|
|
]
|
|
}
|