Skip to content

replay: assert the engine-emitted refusal class - #101

Draft
Kiran01bm wants to merge 3 commits into
mainfrom
kiran01bm/vt5-replay-class
Draft

replay: assert the engine-emitted refusal class#101
Kiran01bm wants to merge 3 commits into
mainfrom
kiran01bm/vt5-replay-class

Conversation

@Kiran01bm

Copy link
Copy Markdown
Collaborator

Make corpus replay assertions and summaries use the refusal class emitted by pg-sprite.

Why

The replay manifest maintained a separate classification column that could drift from the engine's routing contract and hide class regressions.

What

  • Require refusal expectations to pin both reason and one of the five engine classes.
  • Read class and owner from JSON verdicts and bucket summaries from the emitted class.
  • Re-curate the Buzz assessment and document the engine contract as authoritative.
  • Highlight environmental and invariant-violation results in every summary.

Before / after

Before row: 0002 20-26 refuse:unsupported-statement no-online-safety-problem
After row:  0002 20-26 refuse:unsupported-statement:no-online-safety-problem

Before summary: refusal buckets came from the manifest's optional class column
After summary:  refusal buckets come from verdict.class, with all five classes shown

Refs: docs/refusal-classes.md

Kiran01bm and others added 3 commits September 10, 2026 14:34
A refusal reason names the immediate cause but not the kind of boundary
reached. unsupported-statement covers a data backfill, an imperative
CREATE TABLE, a permanently refused CREATE INDEX IF NOT EXISTS, and a
parse/route incoherence; unsupported-partitioned-parent spans three
classes along its PartitionRefusalCause. Consumers rebuilt that split
from reason strings. docs/refusal-classes.md decided the vocabulary;
this change makes the engine emit it.

pkg/verdict gains the Refusal proof type: NewRefusal(class, reason,
owner) rejects a zero or unknown class, an unknown reason, and an owner
outside no-online-safety-problem; the per-class constructors are total
for valid inputs, so there is no panic path; Verdict.WithRefusal is the
one place a verdict acquires outcome, reason, class, and owner together
(RF-7).

The classification registry has two halves keyed on the typed cause
where one exists and on the refusal site where none does, never on the
reason string. pkg/plan/refusal.go classifies plan-side keys
(CreateShapeRefusal, PartitionRefusal, RouteRefusal);
pkg/migrate/refusal_registry.go classifies statement kinds at the gate,
both admission sentinel sets, and each imperative site.
TestRefusalRegistryIsComplete derives its keys from the production
closed sets and pins a sentinel subset so a broken deriver cannot pass
on an empty set. statement.Kinds() is added and the kinds split so
KindOther no longer absorbs provisioning, catalog-work, or data-change
statements.

Plan refusals fail closed. RefuseUnsupportedPartitionedParent now takes
the causes and returns ErrInvariantViolation on a length mismatch or an
unclassified cause; a plan statement refused without a class keeps its
reason and is reported invariant-violation.

JSON gains class and owner on verdicts, plan statements, and plan
reports (additive, omitempty); the text renderer prints them on
refusals; demo/tour.sh asserts the class beside reason and cause. Docs:
RF-7 registered, refusal-classes.md rewritten from proposal to shipped
behavior, limitations.md and README no longer claim every refusal is an
online-safety gap, and the partitioned-parent NOT VALID FK matrix row
corrected to agree with its environmental class. Exit codes and every
existing reason string are unchanged.
Read refusal class and owner from each JSON verdict, require every refusal
expectation to pin both reason and class, and bucket the replay summary from
the engine output.

Re-curate the Buzz assessment into the compound expectation grammar and
document the engine contract as authoritative, including all five classes.
Base automatically changed from kiran01bm/vt2-refusal-class to main September 10, 2026 08:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant