A constraint declares whether consulting it OBLIGES or merely ORIENTS — routing reach is derivable, binding force is not

Accepted

ontoref
ADR-095 shipped the act gate with two of its six refusals deliberately unwired:

Context

ADR-095 shipped the act gate with two of its six refusals deliberately unwired: governed-surface-unconsulted and consultation-stale. The reason recorded in act.nu was that a SPECIFICITY rule was missing — which of the constraints a path routes to actually obliges a read — and that inventing a threshold there is the acceptability rule `plane-habitability` forbids. bl-079 carried the remainder.

THE RULE WAS LOOKED FOR, ON 2026-08-17, AND IT DOES NOT EXIST OVER THIS INPUT. Four candidates were measured over six representative staged paths, using real `governs` output rather than the raw declarations:

all routed 2..23 constraints, up to 11 ADRs unreadable before a commit Hard only 2..14 unreadable longest prefix 1..13 unstable — not a rule Hard ∩ longest 0..9 ZERO for code/install/install.nu, a file five constraints govern

The last row decides it. A rule that answers «nothing obliges you» about a genuinely governed file is worse than the noise it was meant to cure, and the shape of the whole table is a menu whose every option sacrifices a pole — legible as unacceptable only because the options were named before one was chosen.

WHAT IS ACTUALLY MISSING IS NOT A THRESHOLD. A first reading of this blamed the input: 60% of declared `scope` strings carry a space or a comma, so — the argument went — the router extracts prefixes from prose and no ranking over them means anything. That was measured NEXT TO the subject rather than ON it and is false. routing.nu already solves both halves deliberately: `expand-scope` splits comma, brace and ` + ` forms into separate routes, `path-shaped` rejects anything carrying a space or bracket, and `governs coverage` publishes the residue instead of hiding it — 372 of 391 constraints route, 5 are unroutable, 14 declare themselves non-path. Reach is DERIVED, correctly, and has been all along.

The gap is on a different axis entirely. Among the routes the router does admit — clean, path-shaped, correctly expanded — nothing says whether reading a constraint is a PRECONDITION for acting on the path or merely useful context. `severity` answers how forcefully the claim binds once known; it does not answer whether it must be known first. `subject` answers what kind of thing the constraint addresses. `gateable` answers whether a machine can falsify it. None of the three is the question the act gate needs to ask, and no combination of them approximates it — which is what the four measurements above demonstrate rather than assert.

Decision

A constraint MAY declare the force of consulting it, and absence means it orients.

consultation | [| 'Orients, 'Obliges |] | optional

ABSENT IS 'Orients, AND THE DEFAULT IS THE PERMISSIVE ONE ON PURPOSE. Every one of the 391 existing constraints stays valid unchanged and behaves exactly as it does today; a reader that does not know the field is unaffected. This follows the field beside it — `subject`, added by the same reasoning — and the tension that governs it: «schemas are optional layers, not mandatory gates» (formalization-vs-adoption). A required field here would oblige a full corpus classification to satisfy a rule about a subset, which is the mandatory-gate failure that tension exists to refuse.

THE REFUSAL SET STARTS EMPTY, AND THAT IS THE POINT. Once the field exists, the act gate's consultation refusals can be wired against the 'Obliges subset — and on the day they are wired that subset is empty, so nothing refuses. The gate grows teeth one declaration at a time, by the author who knows which constraint is a precondition, rather than by a threshold chosen centrally to make a count comfortable. This is the shape ADR-095 already established and measured for the act itself: opt-in, then binding — free to whoever declares nothing, real for whoever declares.

WHAT THIS DOES NOT DECIDE. It does not prescribe how many constraints should declare 'Obliges, nor which. It does not wire the two refusals — that stays blocked on the second, independent prerequisite (bl-088: the same `governs` call costs 3.5s directly and 17.4s through the CLI, and ~12s of that has no identified cause). And it does not touch reach: `expand-scope`, `path-shaped` and the `subject` declaration keep deriving that, unchanged.

Constraints

  • Hard The `consultation` field MUST be optional on the constraint record, and its absence MUST mean 'Orients. A constraint declaring nothing behaves exactly as it did before this ADR.
  • Hard No mechanism may compute consultation obligation from prefix length, match count, severity, or any other property of the route. The only source is the constraint's own `consultation` declaration.
  • Hard Any consultation refusal wired into the act gate MUST consider only constraints declaring `consultation = 'Obliges`. It MUST NOT refuse on the strength of a route alone.
  • Soft This ADR MUST NOT be used to declare routing reach. `scope`, `check` paths and `subject` remain the only sources of which paths a constraint addresses, and they stay DERIVED on every call.

Alternatives considered

  • Infer obligation from route specificity — longest matching prefix, or the most specific declared scoperejected: Measured and refuted: 1..13 constraints per path with no stable relationship to how much the file is actually governed. It ranks patterns, and a pattern's length is a fact about how its author wrote it.
  • Treat severity as the proxy — Hard obliges, Soft orientsrejected: Measured: 2..14 Hard constraints per path, still unreadable before a commit. And it conflates two questions — a Soft constraint can be exactly the one a reader must know first, and a Hard one can be a background invariant nobody needs to re-read to change a line.
  • Hard AND longest prefix, the narrowest combination availablerejected: Produces ZERO for code/install/install.nu, a file five constraints govern. A gate reporting «nothing obliges you» over real governance is the false-green the eighth reading of enforcement-vs-emergence names as the more dangerous column.
  • Make every routed constraint obliging and accept the volumerejected: 2..23 constraints and up to 11 ADRs per staged path. This is the gate that always fires, whose cost ADR-095 already paid for and recorded: markdownlint, skipped four times in one session before anyone read it.
  • Leave it undecided and keep `act consulted` reporting onlyrejected: That is the status quo and it is stable, but it leaves bl-079 blocked on something described as a missing measurement when the measurement has now been taken. The honest move is to record what the measurement found — the axis is absent from the data — rather than to keep waiting for a rule that cannot be derived.

Anti-patterns

  • The derived rule comes back as a default — A later author, finding the 'Obliges set empty and the refusals therefore silent, makes obligation default to something computed — Hard constraints, or the most specific match — so the gate «does something». The declaration survives as an override nobody sets, and every number in this ADR's context table returns at once.
  • An empty declared set treated as a migration to complete — The 'Obliges set starting empty is read as work in progress, and a sweep declares it across the corpus to «finish» the adoption. That converts a per-author judgment into a bulk edit made by whoever ran the sweep, which is the central threshold this ADR rejected wearing 391 signatures.
  • The corpus is measured instead of the mechanism — A claim about the router is established by grepping the ADR files the router reads, rather than by running the router. It produced a false conclusion in this ADR's own first draft — that 60% of scopes are prose the router cannot handle — when `expand-scope` and `path-shaped` already handle exactly those forms and `governs coverage` publishes the residue.

Related ADRs

ADR-095 · ADR-088 · ADR-072 · ADR-070 · ADR-071

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.