proven, unknown, or disproven. These are epistemic statements about the declared facts in your model. They describe what the verifier can or cannot establish, not what the running system has been observed to do.
The Three Verdicts
proven
The verifier has established that the declared requirement follows from the facts in your model. The proof names the specific declarations it relies on — topic ordering, dispatch routing, transaction isolation, keyed commit deduplication, external idempotency guarantees, and so on — in the obligation’s assumptions list.
A proven verdict is conditional on implementation conformance. If your real implementation does not actually provide the semantics you declared — for example, you declared deduplicated_by but the execution environment does not enforce it — the proof is invalid. Conseqa verifies what you declare, not what you build.
unknown
The verifier could not establish whether the property holds. This is the most common verdict for requirements whose proof depends on facts you have not yet declared.
unknown arises in several situations:
- A key component that is not sourced from the triggering input (the governing key rule).
- A transaction with
idempotency: unspecifiedornot_deduplicatedthat the verifier cannot prove naturally replayable. - An external effect with
idempotency: unspecifiedornot_deduplicated. - A branch condition that depends on a value the verifier cannot establish as replay-stable.
- A cascade where a downstream consumer’s idempotency is itself
unknown.
unknown, read the obligation’s evidence list. It names the specific obstacles: which transaction cannot be resolved, which effect boundary provides no deduplication fact, which decision is not established to replay.
disproven
The verifier has found a counterexample — a concrete trace within the declared model that demonstrates a violation of the property. The obligation’s counterexample field contains the trace.
In the current V1 engine,
disproven obligations are reserved in the format and may appear in future releases. The present engine raises unknown rather than disproven for gaps it cannot close.Declarations That Are Not Verdicts
Several DSL values affect what the verifier can infer but are themselves declarations, not verdicts.unspecified
unspecified in any field means: the model provides no fact from which this property may be inferred. It does not mean the property is false. An unspecified fact cannot be used as evidence in any proof, so a proof that would require it produces unknown rather than proven.
Examples:
ordering: unspecifiedon a topic does not prove messages are unordered.concurrency: unspecifiedon an operation does not prove unbounded concurrency.idempotency: unspecifiedon an external effect does not prove repeated calls are unsafe.
unordered, unbounded, not_deduplicated
These are explicit negative declarations — stronger than unspecified because they actively assert the absence of a guarantee. Even so, they describe declared guarantees, not observed runtime behavior:
unorderedsays the topic provides no ordering guarantee. It does not mean messages are never delivered in order in practice.not_deduplicatedon a transaction or external effect says no keyed deduplication is provided. It does not mean every duplicate invocation causes harm at runtime.
unknown in the negative direction. For example, not_deduplicated on an external effect causes any idempotency requirement that reaches that effect on a retryable path to be unknown — the gap is now explicitly declared rather than merely absent.
Coinductive Verdicts
Someproven obligations are marked coinductive in the report. This means the proof was established by greatest-fixpoint analysis over a cycle of mutually dependent requirements.
A coinductive proof arises when two or more operations each depend on the other’s idempotency verdict — for example, operation A makes a request to operation B, and B makes a request back to A. The V1 engine assumes all requirements and drops those that fail; a cycle whose members each pass their local checks under the mutual assumption is proven. The coinductive label records that the proof rests on this mutual assumption rather than on independent evidence.
Responding to Each Verdict
proven
Confirm that your implementation actually provides the declared facts the proof relies on. The
assumptions list in the obligation report names them exactly.unknown
Read the
evidence list. Decide whether to declare the missing fact, restructure the operation, or accept the gap. Re-run Conseqa after any change.disproven
Inspect the
counterexample trace. Revise the model or the implementation to eliminate the demonstrated violation.coinductive
Verify that the mutually dependent cycle in your architecture is genuinely self-consistent — each operation in the cycle really does collapse duplicates from the others.
Real Examples
Theflash_checkout example model ships with a genuine report that illustrates both outcomes:
10 proven obligations — including serialization, ordering, and recoverability for apply_payment and create_order, and result replay for create_order. These operations use keyed commits, identified events, and by_topic_key dispatch with bounded(1) lane concurrency.
4 unknown obligations — including idempotency for reserve_inventory, charge_payment, and create_order. The root causes:
tx.reserve_inventoryis declarednot_deduplicatedand its mutation depends on a transaction read, so neither the recovery nor the reconstruction route is available.- The external card charge (
effect.charge_payment.card) is declarednot_deduplicated, which means no same-key terminal result is fixed. Thematch_resulton the card result is therefore not established to replay, because a retry may observe a different outcome. create_order’s idempotency cascades through theOrderCreatedevent toreserve_inventory, whose idempotency is itselfunknown.
video_streaming example model is designed to be fully proven. Every operation uses a keyed commit, every external effect declares deduplicated_by, and the transcoding engine’s error disposition is declared terminal, which fixes the result for retries and allows the match_result to replay.