Witnessed Validators for Hard Criteria — Structural Decidability and Bounded Slices, Never Truthfulness

Accepted

ontoref
The constellation-memory work (plan 2026-06-08-constellation-memory-chronicle-criteria) introduces criteria — release/quality/coherence conditions a project holds itself to — harvested from insight

Context

The constellation-memory work (plan 2026-06-08-constellation-memory-chronicle-criteria) introduces criteria — release/quality/coherence conditions a project holds itself to — harvested from insights and the interaction trace (ADR-037) or declared as requirements. ADR-026 already established validators as first-class, three-plane, SLA-bound, with a pluggable commitment backend, and ADR-024 fixed the agent-action boundary: authoritative state mutates only through declared operations carrying a witness. What is unresolved is the boundary question that decides whether criteria-backed validation stays coherent with the protocol's identity: WHICH criteria may become executable validators, and what they are allowed to read. Two failure modes are in scope. First, a criterion that asserts TRUTHFULNESS ('the positioning is honest', 'the architecture is sound') is not structurally decidable — turning it into a validator makes the reflection axis (judgment, an act) masquerade as the ontology axis (an invariant, what IS), and a passing/failing verdict on such a claim is the engine deciding truth. Second, a validator that reads unbounded state (the whole graph, every level) is an adoption cost: it is slow, it couples validation to the daemon, and it breaks the ADR-029 local-fallback guarantee that every read has a no-daemon Nushell path. The witness seam (ADR-031/023) names the exact point where an act that mutates substance is bound to a commitment; a validator over a criterion must live on the ontology side of that seam (verify structure) while being invoked by a reflection-side act (run + witness).

Decision

A criterion is eligible to become an executable validator ONLY if it reduces to a bounded, structurally-decidable slice query; truthfulness criteria are rejected at the eligibility gate and remain QA entries (normative/discovered, ADR-049), never validators. Establish this via four mechanisms. (1) DECIDABILITY ELIGIBILITY GATE — a ValidatorDecl is well-formed only if its predicate is a pure function of a declared, bounded slice plus the state_root commitment; a criterion whose satisfaction depends on a judgment not reducible to structure (honesty, soundness, quality-in-the-abstract) cannot declare a ValidatorDecl and is recorded as a discovered/normative criterion only. (2) BOUNDED SLICE — every ValidatorDecl declares a slice_query naming exactly the nodes/edges/fields it reads; the Rust #[onto_validator] predicate reads ONLY that slice plus state_root and is forbidden from widening its read at runtime. The slice is the validator's read envelope, the structural analogue of ADR-046's authority envelope. (3) STRUCTURE-NOT-TRUTHFULNESS SEVERITY RULE — a validator over a criterion that core.ncl does NOT name as a Spiral tension may carry severity 'Hard (structure is decidable, so pass/fail is meaningful); a validator whose criterion touches a 'Spiral-poled question MUST be 'Soft and report direction of motion, never a 'Hard biconditional — the ondaod prohibition on hard-biconditionals on Spiral questions, applied to validators. (4) NCL-RUST COHERENCE WITNESS — the ValidatorDecl (NCL, the declared structural claim) and the #[onto_validator] predicate (Rust, the executable check) must agree; a coherence check (runtime O6) fails the inventory if a declared validator has no registered predicate or a registered predicate reads beyond its declared slice, and each validator run emits a witness binding the verdict to the state_root it was computed against (ADR-024).

Constraints

  • Hard A criterion may declare a ValidatorDecl ONLY if its predicate is a pure function of a declared bounded slice plus state_root; criteria asserting truthfulness (not reducible to structure) are rejected and remain QA entries, never validators
  • Hard Every ValidatorDecl declares a slice_query naming the nodes/edges/fields it reads; the #[onto_validator] predicate reads only that slice plus state_root and never widens its read at runtime
  • Hard A validator whose underlying criterion touches a question core.ncl names as a 'Spiral tension must be severity 'Soft and report direction of motion; 'Hard biconditional pass/fail is forbidden for Spiral-touching criteria
  • Hard The inventory fails if a declared ValidatorDecl has no registered #[onto_validator] predicate, or a registered predicate reads beyond its declared slice; every validator run emits a witness binding the verdict to the state_root it was computed against

Alternatives considered

  • Allow any criterion to become a validator, let authors choose severity freelyrejected: Collapses ontology-vs-reflection toward reflection-dominates: a truthfulness criterion with a Hard pass/fail makes the engine adjudicate truth, and a verdict on an undecidable claim circulates as if it were an invariant. The decidability gate exists precisely to keep validators on the ontology axis.
  • Let validators read whole state for simplicity, optimize laterrejected: Breaks ADR-029 local-fallback and Protocol-not-Runtime: an unbounded validator couples validation to the daemon and to full-graph materialization, putting infrastructure at the adoption floor. Bounded slices are the same authority-envelope discipline ADR-046 established for reads.
  • Use a check_hint string per criterion (the deprecated constraint pattern)rejected: check_hint is untyped and unexecutable — it cannot enforce the slice bound, cannot be coherence-checked against a Rust predicate, and cannot emit a witness. The typed ValidatorDecl is what makes the structural claim and its execution bindable at the witness seam.
  • Make every criterion-validator Soft to be saferejected: Over-collapses toward never-blocking: a structurally-decidable criterion (no over-read, NCL↔Rust coherent, bounded) is genuinely Hard-checkable, and forcing it Soft discards a real guarantee. The severity rule draws the line by whether the criterion touches a Spiral question, not by blanket caution.
  • Adjudicate truthfulness via an LLM-judge validatorrejected: Maximally collapses ontology-vs-reflection: a model verdict on honesty/soundness is pure reflection issuing an ontology-grade pass/fail, unreproducible and unwitnessable against a state_root. Truthfulness criteria stay human-facing QA entries; no mechanical adjudication.

Anti-patterns

  • Validator adjudicates truth — A criterion asserting truthfulness (honesty, soundness, quality-in-the-abstract) is promoted to an executable validator that issues a pass/fail verdict, making reflection's judgment circulate as an ontology-grade invariant.
  • Unbounded validator read — A validator predicate reads the whole graph or arbitrary levels rather than a declared bounded slice, coupling validation to full-graph materialization and the daemon and breaking local fallback.
  • Hard biconditional on a Spiral criterion — A validator over a criterion that touches a named Spiral tension is declared 'Hard with an A ⟺ B pass/fail, collapsing the tension by fiat instead of reporting direction of motion.
  • Declared but unwitnessed verdict — A ValidatorDecl exists with no registered predicate, or a predicate over-reads its slice, or a run produces a verdict not bound to a state_root — a verdict that cannot be reproduced or audited.

Related ADRs

ADR-026 · ADR-024 · ADR-023 · ADR-031 · ADR-029 · ADR-046 · ADR-037 · ADR-049

Was this useful? Rate it
Got something to add? Tell me what you think, what you'd suggest, or whether we should keep exploring this topic.
· reads

We use cookies to help this site function, understand service usage, and support marketing efforts. Cookie Policy for more info.