Skip to main content

Online edition for BLOGE 0.9.8-RC1 · facts verified 2026-09-15 · 中文

Chapter 27 — Contract Sensitivity: Can the Suite Reject a Wrong Answer?

Chapter promise: Turn one green loan Case into a controlled negative experiment, then distinguish a KILLED witness from a SURVIVED blind spot without confusing either result with exhaustive mutation coverage.

Learning goals

  1. Explain why “candidate equals expected” does not prove that the contract rejects nearby wrong answers.
  2. Use verifyContractSensitivity(Path) against one governed BUSINESS_CONTRACT Expectation.
  3. Read KILLED, SURVIVED, report status, and source-bound evidence as separate facts.
  4. Design one-variable witnesses that a business owner can review.

The same green Case can hide two very different contracts

The low-risk loan Case expects APPROVE, and the graph returns APPROVE. Now imagine two matchers:

  • exact: actual must equal APPROVE;
  • broad: actual must merely be different from DECLINE.

Both pass today. Only the first rejects REVIEW. A positive example establishes that one point matches; sensitivity asks whether a selected wrong answer crosses the contract boundary.

Figure 27.1: The same controlled wrong answer is killed by an exact contract and survives a broad one

Change the expected answer, not the running system

The sidecar names the exact governed Expectation and replaces only its expected value:

schemaVersion: 1
sensitivityId: loan-decision-witnesses
scenario: loan-approval.scenario.yaml
mutants:
- mutantId: low-risk-must-not-review
requirementRef: LOAN-DECISION-001
caseId: auto-approve
expectationId: decision-approved
kind: EXPECTATION_VALUE_REPLACED
replacementExpected: REVIEW
VerificationContractSensitivityReport result =
verifier.verifyContractSensitivity(sensitivityPath);

BLOGE executes the baseline Case once. It then projects the real observation onto the alternate expected value. It does not patch production code, rerun a different Operator, or invent a business rule. That isolation matters: if both the implementation and Oracle changed, a failure would no longer identify contract sensitivity.

Observe the transition, not just the final badge

The RC1 test ContractSensitivityTest.passesOnlyWhenEveryRequiredWitnessIsKilled uses an exact EQUALS Expectation. The graph still observes APPROVE; replacing expected with REVIEW is rejected, so the witness is KILLED, the report is PASS, and reasonCodes is empty.

The companion test sealsASurvivingWitnessAsARecheckableSensitivityFailure starts from a broader “not review” style contract and replaces expected with DECLINE. The same observation is still accepted. The witness becomes SURVIVED, the report becomes FAIL, and the published artifact remains independently recheckable as SOURCE_BOUND evidence.

ObservationWitness outcomeReportMeaning
alternate expected is rejectedKILLEDPASS only if every required witness is killedthe contract notices this selected wrong answer
alternate expected is still acceptedSURVIVEDFAILthe matcher or Oracle boundary is too broad for this witness
plan points to a missing/unsupported targetNOT_EVALUATEDINVALIDthe experiment itself is not valid

The important asymmetry is deliberate: a surviving witness is useful failure evidence. It should not disappear because the business Case happened to be green.

Design witnesses from business mistakes

Do not enumerate random strings. Start from a mistake the business can name:

  1. Pick one protected decision, such as “low-risk applications must not enter manual review.”
  2. Keep Scenario, Policy, Fixture, graph, execution profile, and source commit fixed.
  3. Replace one expected value with one plausible wrong answer.
  4. Ask the owner whether the witness represents a real decision boundary.
  5. Keep the witness in version control only after that review.

For loan approval, useful witnesses include REVIEW for an auto-approve Case and APPROVE for a blacklist Case. A nonsense value may test serialization while teaching nothing about the business contract.

Lab: make one witness survive

  1. Run the low-risk Case and record its baseline PASS and actual APPROVE.
  2. Add the REVIEW replacement above; verify that the exact matcher yields KILLED.
  3. Change only the matcher to a broader condition that also accepts REVIEW.
  4. Run the same sidecar again; record SURVIVED and CONTRACT_MUTANT_SURVIVED:<mutantId>.
  5. Restore the exact matcher and rerun. The witness must return to KILLED.
  6. Save the artifact receipt outside the run directory and ask another reader to verify it.

This is a two-run, one-variable experiment: the witness is fixed, and only contract strictness changes. That makes the result explainable.

Transfer: discount-rule sensitivity

For retail pricing, replace an expected 10% loyalty discount with 30% while keeping the cart and implementation fixed. An exact amount matcher should kill that witness; a matcher that checks only discount > 0 will let it survive. The result measures whether the contract rejects this chosen pricing error, not whether every promotion interaction is covered.

Chapter boundary

  • Sensitivity covers only author-declared mutations; it is not mutation coverage of all rules or outputs.
  • A KILLED witness proves rejection of one selected wrong answer, not correctness over an input domain.
  • A SURVIVED witness locates an ambiguity; it does not decide whether the matcher or business Oracle should change.
  • Source-bound publication makes the result recheckable; it does not turn the tool into the business owner.

Experiment acceptance card

  • Expected and observed: One observation becomes KILLED under an exact contract and SURVIVED under a loose one.
  • Failure and recovery: Loosen one expectation so the witness survives; restore the exact answer.
  • Proof boundary: Proves sensitivity to a declared witness, not discovery of every blind spot.
  • Exercise contract: Green case and one witness; change one expectation; deliver the transition; stop when the bad witness is KILLED.

Summary

A green example says “this answer matched.” A killed witness adds “this selected wrong answer would not have matched.” A surviving witness exposes where the contract is too permissive. Chapter 28 changes the question again: instead of one hand-picked wrong answer, it explores a bounded input domain and reduces a real failure.

Next: Chapter 28 — Bounded Property Verification and Useful Counterexamples

Coding Agent: Open the versioned task guide.