core/docs/adr/ADR-0201.1-out-of-regime-detector.md
Shay 54e6bfc0d0
docs: reorganize docs landscape
Implements the 4-phase documentation reorganization master plan.

- Consolidation: Merged brief/, handoff/, planning/, and decisions/ into briefs/, handoffs/, plans/, and adr/ respectively (101 ADRs relocated)
- Root Cleanup: Relocated HANDOFF-gpt55-*.md and key top-level docs (runtime_contracts.md, etc.) to canonical folders. Added superseded alerts.
- Indices & Navigation: Created docs/README.md navigation document, docs/sessions/README.md index, docs/adr/README.md index
- Note: Also includes prior commit adding ADR-0200+ corpus hygiene governance (ADR-0225, dependency map, backfilled cross-references)
2026-06-30 16:59:36 -07:00

6.6 KiB
Raw Blame History

ADR-0201.1 — Principled Out-of-Regime Detector (out_of_decidable_regime)

Status: Accepted (additive hardening of ADR-0201; phase-1 canonicalizer) Date: 2026-06-02 Relates to: ADR-0201 (propositional canonicalizer — this hardens it; see §amend-vs-additive), ADR-0202 §3 (the contract that names this typed refusal), ADR-0203 (the prior additive-not-amend precedent).


Context

GPT-5.5's independent proof-chain corpus (the separate-author oracle for logic_canonical.py) cross-checked 22/22 cases against the real canonicalizer. Twenty agreed exactly; two — the out-of-regime probes forall x. rains(x) -> wet(x) and exists x. wet(x) — agreed on outcome (both refused) but disagreed on the reason:

  • ADR-0202 §3 names a typed refusal: quantified/predicate input "must REFUSE (out_of_decidable_regime)."
  • The keystone refused, but with a generic LogicError: "unexpected character '.' at position 8" — it had no regime detector. It refused these inputs only because the tokenizer incidentally chokes on the . (or trips on the predicate ().

That is a by-luck-not-by-design refusal — the exact failure mode the wrong == 0 discipline rejects. The propositional-only boundary that ADR-0202 declares load-bearing was being enforced by accident, not on purpose. Blessing it (relaxing the contract) would write the accident into the contract. The corpus caught precisely the thing an independent oracle exists to catch.

Decision

Make the boundary principled. Add a typed regime refusal, checked before the generic grammar error:

  • LogicRegimeError(LogicError) carrying the typed reason OUT_OF_DECIDABLE_REGIME = "out_of_decidable_regime". A LogicError subclass, so callers refusing on LogicError still refuse — but the regime boundary is now distinguishable from a malformed-propositional-formula grammar error.
  • _reject_out_of_regime_text(formula) — a raw-text pre-scan (before tokenizing) for quantifier markers: the words forall/exists (word-boundary, case-insensitive) and the symbols /. forall/exists are thereby reserved — not usable as atom ids.
  • _reject_out_of_regime_tokens(tokens) — a token-stream scan for predicate-application shape: an ATOM immediately followed by (. In the propositional grammar an atom is never followed by (, so ATOM ( is a predicate (rains(x)), not a well-formed formula. Keyword operators (not, and, …) are not ATOM tokens, so not (P) is unaffected.
  • canonicalize runs _reject_out_of_regime_text_tokenize_reject_out_of_regime_tokens → parse. check_equivalence surfaces the typed reason via a LogicRegimeError branch placed before its generic LogicError branch.

This is a refusal, not new capability: the engine still does no predicate/FOL reasoning. It now refuses it on purpose, with an inspectable typed reason, instead of by tokenizer accident.

amend-vs-additive

This is a new additive sub-ADR (ADR-0201.1), not an amendment of the landed ADR-0201 — same discipline as ADR-0203-vs-0132: the regime detector became load-bearing only when the corpus surfaced the incidental-refusal gap; recording it additively preserves that why-added-later history rather than rewriting the closed canonicalizer record.

Chosen as a sub-number (0201.1), not a fresh top-level number, for two reasons: (a) it is specifically a hardening of the ADR-0201 canonicalizer (same module, same phase-1 keystone), which the sub-number communicates precisely; and (b) a top-level ADR-0204 would collide with the forward references in the already-merged ADR-0203 and the recorded phase-2 plan (0204 = wiring, 0205 = modus_ponens, 0206 = grounding). The sub-number keeps those intact.

Honesty boundary (load-bearing — carried by every phase-2 ADR, 02030205)

Through phase 2.3, proof_chain is sound over its declared atoms, not grounded in recognized input (grounding is phase 2.4). This ADR does not soften that, and it does not add predicate/FOL reasoning — it makes the propositional-only boundary principled by refusing out-of-regime input with a typed reason. The boundary is enforced by design, never "reasons over input."

Evidence

  • tests/test_logic_canonical.py — 43 tests (33 keystone + 10 new): quantifier words/symbols and predicate application refuse with LogicRegimeError / out_of_decidable_regime; the equivalence path surfaces the typed reason; genuine grammar errors (P &, P @ Q, (P) still raise plain LogicError (detector does not over-fire); not (P) is not mistaken for predicate application.
  • Mutation-verified by-design: neutering both detectors makes forall x. … fall through to the generic grammar error (unexpected character '.') instead of the typed reason — test_out_of_regime_refuses_with_typed_reason would fail. The boundary holds on purpose, not by luck.
  • Corpus now 22/22: the two OOR cases (PC-OOR-001/002) now agree on the principled out_of_decidable_regime reason.
  • Full canonicalizer suite green; smoke: 67 passed.

Note carried to the corpus (rule-reasons pending 2.3)

The 3 modus_ponens corpus cases were validated only at the entailment level the canonicalizer provides ((⋀premises) → conclusion is/ isn't a tautology). Their typed rule reasons (modus_ponens_conclusion_mismatch, modus_ponens_missing_implication) are deferred to ADR-0205 (phase 2.3), when the modus_ponens rule is built. The corpus should carry an explicit "rule-reasons pending 2.3" marker on those cases so the deferral is recorded, not assumed validated.

Scope

Phase-1 canonicalizer hardening only. Does not build modus_ponens, binding-graph wiring, or any predicate/FOL support.

Governance Cross-Reference (ADR-0225)

This late-corpus ADR is governed by ADR-0225:

  • Safety boundaries: changes must preserve ADR-0027/0028/0029 identity and safety-pack boundaries; no identity, safety, or policy mutation is implied unless explicitly reviewed.
  • Versor closure: runtime field paths must preserve versor_condition(F) < 1e-6; this ADR does not authorize hidden normalization or hot-path drift repair.
  • Reconstruction-over-storage: evidence must remain reconstructive and content-addressed rather than duplicating opaque state.
  • Replay-equivalence: serving, teaching, promotion, or checkpoint changes require a named deterministic replay / byte-equivalence gate.
  • Mutation standing: any durable corpus, pack, policy, or epistemic-status mutation remains reviewed, proposal-only until accepted, or proof-carrying as applicable.