Negative fixtures for the context-contract schema
These are the must-reject witnesses for
../../context-contract-schema.json (the portable
context-contract schema, #1212 / G4). The positive round-trip — the four declared
views (../context-view-resident.json,
../context-view-fault.json,
../context-view-stale.json,
../context-view-fabrication.json) and the three
review decisions (../context-decision-resident.json,
../context-decision-fault.json,
../context-decision-stale.json,
../context-decision-fabrication.json) — shows the
schema accepts a well-formed view and its decision. These five files make the acceptance
criterion — “the view-kind set, the taint lattice, the invalidation rule, and the
deny-reason set are a closed, validatable vocabulary, and the check is
fail-closed” — checkable rather than asserted. Each isolates exactly one defect so
the rejection reason is unambiguous.
A ContextView (the authored INPUT) validates against the schema root; a Decision
(the review OUTPUT) validates against $defs/Decision:
| Fixture | Validated against | Defect | Why the schema rejects it |
|---|---|---|---|
view-kind-out-of-set.json |
root (ContextView) |
view_kind: "paragraph" |
not in the closed ViewKind set — an out-of-set kind can’t even be expressed; a runtime that receives one treats it as UNKNOWN_VIEW_KIND, denied fail-closed |
taint-out-of-set.json |
root (ContextView) |
source_taint: "unknown" |
not in the closed Taint lattice (trusted < tainted < quarantined) — an unrecognized label is treated as tainted (fail-closed), never admitted |
empty-span.json |
root (ContextView) |
source.length: 0 |
a view must name a non-empty source window (minimum: 1) — a zero-length span is EMPTY_SPAN, refused (mirrors memview.ErrEmptySpan) |
unknown-field.json |
root (ContextView) |
extra summary key |
the view is closed (additionalProperties: false); an unknown field — here a smuggled model-authored summary — is not silently ignored |
deny-missing-reason.json |
$defs/Decision |
decision: "deny", no reason |
a non-allow verdict MUST carry a reason from the closed DenyReason set — a bare refusal with no closed reason is rejected (no free-text refusals) |
The round-trip, witnessed with no fak engine
Any off-the-shelf Draft 2020-12 validator runs this. The recipe below uses the
jsonschema Python package (pip install jsonschema) — no fak engine, no network, no
model. Run it from the repo root; it exits non-zero if any expectation is unmet:
import json, sys
from jsonschema import Draft202012Validator
schema = json.load(open("docs/standards/context-contract-schema.json"))
F = "docs/standards/fixtures"
# The root validates a ContextView (the authored INPUT, $ref -> #/$defs/ContextView).
root = Draft202012Validator(schema)
# A Decision is the review OUTPUT — validate it against $defs/Decision, NOT the root
# (the root's $ref is ContextView; a Decision is a different shape).
decision = Draft202012Validator(
{"$schema": schema["$schema"], "$defs": schema["$defs"], "$ref": "#/$defs/Decision"})
ok = True
def expect(name, valid, want_valid):
global ok
good = valid == want_valid
ok = ok and good
print(("PASS" if good else "FAIL"), name,
"->", "accepted" if valid else "rejected")
# author + review round-trip; every disposition's positive case must validate
for v in ("resident", "fault", "stale", "fabrication"):
expect(f"view {v} (author)", root.is_valid(json.load(open(f"{F}/context-view-{v}.json"))), True)
for d in ("resident", "fault", "stale", "fabrication"):
expect(f"decision {d} (review)", decision.is_valid(json.load(open(f"{F}/context-decision-{d}.json"))), True)
# closed vocabulary + fail-closed: every negative must be rejected
for neg in ("view-kind-out-of-set", "taint-out-of-set", "empty-span", "unknown-field"):
expect(neg, root.is_valid(json.load(open(f"{F}/context-contract-invalid/{neg}.json"))), False)
expect("deny-missing-reason", decision.is_valid(json.load(open(f"{F}/context-contract-invalid/deny-missing-reason.json"))), False)
sys.exit(0 if ok else 1)
Expected output — the seven positives accepted, all five negatives rejected:
PASS view resident (author) -> accepted
PASS view fault (author) -> accepted
PASS view stale (author) -> accepted
PASS view fabrication (author) -> accepted
PASS decision resident (review) -> accepted
PASS decision fault (review) -> accepted
PASS decision stale (review) -> accepted
PASS decision fabrication (review) -> accepted
PASS view-kind-out-of-set -> rejected
PASS taint-out-of-set -> rejected
PASS empty-span -> rejected
PASS unknown-field -> rejected
PASS deny-missing-reason -> rejected