Merge pull request #697 from AssetOverflow/feat/demo-authority-strength

fix(demo): harden #690 epistemic truth-state — sealed corpus + entailment-decided inference
This commit is contained in:
Shay 2026-06-11 23:27:05 -07:00 committed by GitHub
commit c6d0e2a920
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 852 additions and 176 deletions

9
.gitignore vendored
View file

@ -51,3 +51,12 @@ teaching/math_proposals/proposals.jsonl
engine_state/manifest.json engine_state/manifest.json
engine_state/recognizers.jsonl engine_state/recognizers.jsonl
engine_state/discovery_candidates.jsonl engine_state/discovery_candidates.jsonl
# Private outreach / personal packet — never tracked
01_Anthropic/
# Agent working directories
.agents/
# Cowork/Claude tooling artifacts
skills-lock.json

View file

@ -3,8 +3,8 @@
This demo proves one narrow boundary: This demo proves one narrow boundary:
```text ```text
A model-style proposer submits a claim, an evidence bundle, and an optional A model-style proposer submits a claim, sealed evidence references, and an
bounded-inference block. optional bounded-inference block.
CORE alone assigns the typed epistemic state. CORE alone assigns the typed epistemic state.
The output is a deterministic, replayable evidence artifact. The output is a deterministic, replayable evidence artifact.
The proposer never controls its own truth-state. The proposer never controls its own truth-state.
@ -23,19 +23,37 @@ state is typed
* A model-style proposer can submit a claim without gaining authority over its * A model-style proposer can submit a claim without gaining authority over its
epistemic standing. epistemic standing.
* The proposer supplies evidence references only. CORE resolves those references
against the sealed local corpus in
[`evidence_corpus.json`](evidence_corpus.json), requiring a matching
`content_sha256` before any evidence can count.
* CORE alone assigns the typed state, drawn from the canonical taxonomy in * CORE alone assigns the typed state, drawn from the canonical taxonomy in
[`core/epistemic_state.py`](../../core/epistemic_state.py) — `verified`, [`core/epistemic_state.py`](../../core/epistemic_state.py) — `verified`,
`evidenced`, `inferred`, `undetermined`, `scope_boundary`. There is no `evidenced`, `inferred`, `contradicted`, `undetermined`, `scope_boundary`.
parallel enum. There is no parallel enum.
* CORE derives `normative_clearance`, the `evidence_ledger`, the * CORE derives `normative_clearance`, the `evidence_ledger`, the
`authority_path`, and a fresh `trace_hash` itself. `authority_path`, and a fresh `trace_hash` itself. The corpus seal
(`corpus_sha256`) is pinned into every evaluated trace.
* Any proposer-supplied `proposed_state` or `trace_hash` is recorded as ignored * Any proposer-supplied `proposed_state` or `trace_hash` is recorded as ignored
and never read by the decision path. and never read by the decision path.
* Invalid payloads fail at the typed boundary *before* any state evaluation * Invalid payloads fail at the typed boundary *before* any state evaluation
runs. runs.
* `verified` requires two or more independent evidence records that explicitly * `verified` requires two or more corpus records that explicitly match the
match the claim's subject and predicate — corroboration the proposer cannot claim's subject and predicate and come from distinct provenance roots —
fabricate through the schema. corroboration the proposer cannot fabricate through the request schema.
* `inferred` is decided by a real entailment proof, not by reference counting.
The cited premises (fact records contribute their `subject__predicate` atom;
rule records their committed formula) must *propositionally entail* the
claim's atom under
[`generate/proof_chain/entail.py`](../../generate/proof_chain/entail.py) —
the sound-and-complete ROBDD decision procedure — cross-checked against the
independent truth-table oracle in
[`evals/deductive_logic/oracle.py`](../../evals/deductive_logic/oracle.py)
(no shared code). The ROBDD proof keys and the oracle verdict are both in
the trace; if the two procedures ever disagreed, the demo refuses outright.
Citing records that merely *exist* yields `undetermined`, never `inferred`
the committed scenario `unrelated-premise-still-undetermined` exercises
exactly that attack.
## What this does not prove ## What this does not prove
@ -47,6 +65,9 @@ state is typed
a claim and makes no safety guarantee. a claim and makes no safety guarantee.
* It does not call a network, a model API, a subprocess, or any side-effecting * It does not call a network, a model API, a subprocess, or any side-effecting
tool. It evaluates JSON and returns JSON. tool. It evaluates JSON and returns JSON.
* The entailment leg is propositional only (atoms are `subject__predicate`
pairs); quantified or predicate-logic structure is out of regime and refuses
upstream in the engine.
* It does not claim broader epistemic coverage than the small local envelope and * It does not claim broader epistemic coverage than the small local envelope and
the deterministic rules encoded in `authority.py`. the deterministic rules encoded in `authority.py`.
@ -74,18 +95,27 @@ Each layer keeps the same doctrine: a model-style proposer contributes typed
data, CORE alone decides, and the decision is a deterministic trace artifact data, CORE alone decides, and the decision is a deterministic trace artifact
with no proposer-held authority and no execution path. with no proposer-held authority and no execution path.
## The six scenarios ## The seven scenarios
* `verified-supported-claim` — two independent matching records → `verified`, * `verified-supported-claim` — two matching corpus records with distinct
`verified_by_matching_evidence` (clearance `unassessable`). provenance roots → `verified`, `verified_by_matching_evidence` (clearance
`unassessable`).
* `evidenced-but-not-verified-claim` — one supporting record → `evidenced`, * `evidenced-but-not-verified-claim` — one supporting record → `evidenced`,
`evidence_present_but_not_verifying`. `evidence_present_but_not_verifying`.
* `inferred-from-bounded-evidence` — claim follows from resolved premises → * `inferred-from-bounded-evidence` — two fact premises plus a ratified rule
`inferred`, `bounded_inference_from_evidence`, with `inference_basis` IDs. record propositionally entail the claim's atom → `inferred`,
`entailed_from_resolved_premises`, with the ROBDD entailment trace
(`entailment_check_key: "T"`), the independent oracle verdict, and
`inference_basis` IDs.
* `unrelated-premise-still-undetermined` — a claim with no support citing a
resolvable but logically unrelated record as a premise → the engine decides
`unknown`, the state is `undetermined`. `inferred` cannot be minted by
citing records that merely exist.
* `undetermined-insufficient-evidence` — no relevant evidence → `undetermined`, * `undetermined-insufficient-evidence` — no relevant evidence → `undetermined`,
`insufficient_evidence`, with an explicit `question`. `insufficient_evidence`, with an explicit `question`.
* `refused-outside-scope` — claim declared outside the local envelope → * `refused-outside-scope` — claim declared outside the local envelope →
status `refused`, `scope_boundary`, `outside_epistemic_envelope`. status `refused`, `scope_boundary`, `outside_epistemic_envelope`; the corpus
is never consulted.
* `invalid-state-smuggling-attempt` — root-level `assigned_state` / `status` / * `invalid-state-smuggling-attempt` — root-level `assigned_state` / `status` /
`evidence_ledger` / `authority_path` / `trace_hash` injection → status `evidence_ledger` / `authority_path` / `trace_hash` injection → status
`invalid`, `authority_evaluated: false`, every smuggled property listed in `invalid`, `authority_evaluated: false`, every smuggled property listed in
@ -94,15 +124,22 @@ with no proposer-held authority and no execution path.
## Honesty ledger ## Honesty ledger
* Real: closed recursive schema validation, canonical-enum state assignment via * Real: closed recursive schema validation, canonical-enum state assignment via
`core.epistemic_state`, deterministic trace hashing over the response minus `core.epistemic_state`, sealed-corpus evidence resolution by content hash,
`trace_hash`, evidence-ledger derivation, expected-artifact pinning, sound-and-complete ROBDD entailment with independent-oracle cross-check on
double-run byte-identical determinism, output-directory hardening. the inference leg, deterministic trace hashing over the response minus
`trace_hash`, corpus seal pinning, evidence-ledger derivation,
expected-artifact pinning, double-run byte-identical determinism,
output-directory hardening.
* Simulated: the proposer side is static fixture data standing in for a * Simulated: the proposer side is static fixture data standing in for a
model-style proposer; the evidence bundle is hand-authored, not retrieved from model-style proposer; the evidence corpus is committed local fixture evidence,
the live vault. not retrieved from the live vault.
* Honest non-claim: `normative_clearance` is `unassessable` on every * Honest non-claim: `normative_clearance` is `unassessable` on every
non-invalid output, including `verified`, because this demo runs no non-invalid output, including `verified`, because this demo runs no
safety/ethics verdict pass and therefore has no basis to clear anything. safety/ethics verdict pass and therefore has no basis to clear anything.
* Defensive path: the `entailment_oracle_disagreement` refusal exists and is
tested (by forcing a fake oracle verdict in tests); it has never fired on
real input and is expected never to — both procedures are sound and complete
over the propositional regime.
* Not claimed: runtime integration, serving integration, real evidence * Not claimed: runtime integration, serving integration, real evidence
retrieval, a safety guarantee, or any coverage beyond this local envelope. retrieval, a safety guarantee, or any coverage beyond this local envelope.

View file

@ -1,9 +1,19 @@
"""Local deterministic epistemic-state authority substrate for the demo. """Local deterministic epistemic-state authority substrate for the demo.
A model-style proposer submits a claim, an evidence bundle, and (optionally) a A model-style proposer submits a claim, sealed evidence references, and
bounded-inference block. The proposer contributes *data only*. CORE alone: (optionally) a bounded-inference block. The proposer contributes *references only*
for evidence; CORE resolves those references against a sealed local corpus. CORE
alone:
* validates a closed payload, * validates a closed payload,
* resolves evidence references by committed content hash,
* derives support and provenance independence from the committed record bodies
(never from proposer-supplied labels the schema rejects them),
* decides the bounded-inference leg with the real propositional entailment
engine (:func:`generate.proof_chain.entail.evaluate_entailment_with_trace`,
the sound-and-complete ROBDD decision procedure) cross-checked against the
independent truth-table oracle
(:func:`evals.deductive_logic.oracle.oracle_entailment`),
* assigns the typed epistemic state drawn from the canonical taxonomy in * assigns the typed epistemic state drawn from the canonical taxonomy in
:mod:`core.epistemic_state` (never a parallel enum), :mod:`core.epistemic_state` (never a parallel enum),
* derives normative clearance, * derives normative clearance,
@ -11,7 +21,10 @@ bounded-inference block. The proposer contributes *data only*. CORE alone:
* regenerates a deterministic trace hash. * regenerates a deterministic trace hash.
The proposer cannot set ``assigned_state``, ``status``, ``trace_hash``, The proposer cannot set ``assigned_state``, ``status``, ``trace_hash``,
``authority_path``, the evidence ledger, or ``normative_clearance``. Any ``authority_path``, the evidence ledger, or ``normative_clearance`` and it
cannot mint them indirectly: ``inferred`` is assigned only when the cited,
resolved premises *propositionally entail* the claim's atom, so citing
unrelated records as premises yields ``undetermined``, not ``inferred``. Any
proposer-supplied ``proposed_state`` / ``trace_hash`` is recorded as ignored proposer-supplied ``proposed_state`` / ``trace_hash`` is recorded as ignored
and never read by the decision path. Nothing here executes a side effect. and never read by the decision path. Nothing here executes a side effect.
""" """
@ -21,6 +34,7 @@ from __future__ import annotations
import hashlib import hashlib
import json import json
import re import re
from dataclasses import dataclass
from functools import lru_cache from functools import lru_cache
from pathlib import Path from pathlib import Path
from typing import Any, Final from typing import Any, Final
@ -31,10 +45,13 @@ from core.epistemic_state import (
coerce_epistemic_state, coerce_epistemic_state,
coerce_normative_clearance, coerce_normative_clearance,
) )
from evals.deductive_logic.oracle import oracle_entailment
from generate.proof_chain.entail import Entailment, evaluate_entailment_with_trace
TOOL_NAME: Final[str] = "core.epistemic_truth_state.review" TOOL_NAME: Final[str] = "core.epistemic_truth_state.review"
_HERE: Final[Path] = Path(__file__).resolve().parent _HERE: Final[Path] = Path(__file__).resolve().parent
SCHEMA_PATH: Final[Path] = _HERE / "schema.json" SCHEMA_PATH: Final[Path] = _HERE / "schema.json"
EVIDENCE_CORPUS_PATH: Final[Path] = _HERE / "evidence_corpus.json"
# The local epistemic authority envelope: only claims declared inside these # The local epistemic authority envelope: only claims declared inside these
# domains are evaluated. Anything else is refused as outside scope rather than # domains are evaluated. Anything else is refused as outside scope rather than
@ -42,8 +59,11 @@ SCHEMA_PATH: Final[Path] = _HERE / "schema.json"
ENVELOPE_DOMAINS: Final[frozenset[str]] = frozenset({"demo.local_factual"}) ENVELOPE_DOMAINS: Final[frozenset[str]] = frozenset({"demo.local_factual"})
_ROOT_AUTHORITY: Final[str] = "demos.epistemic_truth_state.authority.validate_payload" _ROOT_AUTHORITY: Final[str] = "demos.epistemic_truth_state.authority.validate_payload"
_CORPUS_AUTHORITY: Final[str] = "demos.epistemic_truth_state.authority.resolve_evidence_refs"
_ASSIGN_AUTHORITY: Final[str] = "demos.epistemic_truth_state.authority.assign_epistemic_state" _ASSIGN_AUTHORITY: Final[str] = "demos.epistemic_truth_state.authority.assign_epistemic_state"
_ENVELOPE_AUTHORITY: Final[str] = "demo_epistemic_truth_state_envelope(local-v1)" _ENVELOPE_AUTHORITY: Final[str] = "demo_epistemic_truth_state_envelope(local-v1)"
_ENTAIL_AUTHORITY: Final[str] = "generate.proof_chain.entail.evaluate_entailment_with_trace"
_ORACLE_AUTHORITY: Final[str] = "evals.deductive_logic.oracle.oracle_entailment"
_TAXONOMY_AUTHORITY: Final[str] = "core.epistemic_state.coerce_epistemic_state" _TAXONOMY_AUTHORITY: Final[str] = "core.epistemic_state.coerce_epistemic_state"
_SUPPORTED_SCHEMA_KEYS: Final[frozenset[str]] = frozenset( _SUPPORTED_SCHEMA_KEYS: Final[frozenset[str]] = frozenset(
@ -75,6 +95,40 @@ def load_schema() -> dict[str, Any]:
return json.loads(SCHEMA_PATH.read_text(encoding="utf-8")) return json.loads(SCHEMA_PATH.read_text(encoding="utf-8"))
@lru_cache(maxsize=1)
def load_evidence_corpus() -> dict[str, dict[str, Any]]:
raw = json.loads(EVIDENCE_CORPUS_PATH.read_text(encoding="utf-8"))
records = raw.get("records")
if not isinstance(records, list):
raise ValueError("evidence corpus must contain a records array")
by_id: dict[str, dict[str, Any]] = {}
for record in records:
if not isinstance(record, dict):
raise ValueError("evidence corpus records must be objects")
evidence_id = record.get("evidence_id")
if not isinstance(evidence_id, str):
raise ValueError("evidence corpus record missing evidence_id")
if evidence_id in by_id:
raise ValueError(f"duplicate evidence_id {evidence_id!r}")
by_id[evidence_id] = dict(record)
return by_id
def _evidence_record_hash(record: dict[str, Any]) -> str:
return _hash_text(_canonical(record))
@lru_cache(maxsize=1)
def corpus_file_sha256() -> str:
"""Hash of the committed corpus file bytes — the seal pinned into traces."""
return _hash_text(EVIDENCE_CORPUS_PATH.read_text(encoding="utf-8"))
@lru_cache(maxsize=1)
def corpus_identifier() -> str:
return str(json.loads(EVIDENCE_CORPUS_PATH.read_text(encoding="utf-8"))["corpus_id"])
def _clip(value: object) -> str: def _clip(value: object) -> str:
rendered = repr(value) rendered = repr(value)
return rendered if len(rendered) <= 80 else rendered[:79] + "" return rendered if len(rendered) <= 80 else rendered[:79] + ""
@ -230,6 +284,29 @@ def _invalid_response(payload: Any, errors: tuple[str, ...]) -> dict[str, Any]:
) )
def _invalid_evidence_response(payload: dict[str, Any], errors: tuple[str, ...]) -> dict[str, Any]:
return _finalize(
{
"tool": TOOL_NAME,
"status": "invalid",
"request_id": payload["request_id"],
"scenario_id": payload["scenario_id"],
"authority_path": [_ROOT_AUTHORITY, _CORPUS_AUTHORITY],
"decision_reason": "invalid_evidence_reference",
"assigned_state": None,
"normative_clearance": None,
"evidence_ledger": [],
"trace_summary": {
"authority_evaluated": False,
"evidence_reference_errors": list(errors),
"proposer_trace_hash_ignored": _proposer_trace_hash_present(payload),
"proposer_state_ignored": _proposer_state_present(payload),
},
"invalid_reason": "; ".join(errors),
}
)
def _claim_fingerprint(payload: dict[str, Any]) -> str: def _claim_fingerprint(payload: dict[str, Any]) -> str:
proposer = payload["proposer"] proposer = payload["proposer"]
digest_input = { digest_input = {
@ -245,43 +322,174 @@ def _claim_fingerprint(payload: dict[str, Any]) -> str:
return _hash_text(_canonical(digest_input)) return _hash_text(_canonical(digest_input))
def resolve_evidence_refs(refs: list[dict[str, Any]]) -> tuple[list[dict[str, Any]], tuple[str, ...]]:
"""Resolve proposer-supplied refs against the sealed local evidence corpus."""
corpus = load_evidence_corpus()
resolved: list[dict[str, Any]] = []
errors: list[str] = []
seen: set[str] = set()
for ref in refs:
evidence_id = ref["evidence_id"]
if evidence_id in seen:
errors.append(f"duplicate evidence reference {evidence_id!r}")
continue
seen.add(evidence_id)
record = corpus.get(evidence_id)
if record is None:
errors.append(f"unknown evidence reference {evidence_id!r}")
continue
expected_hash = _evidence_record_hash(record)
if ref["content_sha256"] != expected_hash:
errors.append(f"content hash mismatch for evidence reference {evidence_id!r}")
continue
# Hand out a copy: the corpus cache must stay immutable in-process.
resolved.append(dict(record))
return resolved, tuple(errors)
def _matching_evidence(claim: dict[str, Any], evidence: list[dict[str, Any]]) -> list[dict[str, Any]]: def _matching_evidence(claim: dict[str, Any], evidence: list[dict[str, Any]]) -> list[dict[str, Any]]:
"""Evidence records that explicitly support the claim subject and predicate.""" """Corpus records that match the claim subject and predicate."""
subject = claim["subject"] subject = claim["subject"]
predicate = claim["predicate"] predicate = claim["predicate"]
return [ return [
record record
for record in evidence for record in evidence
if bool(record.get("supports")) if record.get("source_kind") != "premise"
and record.get("subject") == subject and record.get("subject") == subject
and record.get("predicate") == predicate and record.get("predicate") == predicate
] ]
def _resolved_inference_basis(payload: dict[str, Any]) -> list[str] | None: def _independent_evidence(evidence: list[dict[str, Any]]) -> list[dict[str, Any]]:
"""Return sorted premise IDs iff an inference block resolves fully, else None.""" by_root: dict[str, dict[str, Any]] = {}
for record in evidence:
root = record["provenance_root"]
by_root.setdefault(root, record)
return list(by_root.values())
def _claim_atom(claim: dict[str, Any]) -> str:
"""The propositional atom the claim asserts (schema guarantees snake_case
parts, so the derivation is total)."""
return f"{claim['subject']}__{claim['predicate']}"
def _premise_formula(record: dict[str, Any]) -> str:
"""The propositional contribution of one resolved corpus record: a rule
record contributes its committed formula, a fact record its atom."""
formula = record.get("formula")
if isinstance(formula, str) and formula:
return formula
return f"{record['subject']}__{record['predicate']}"
@dataclass(frozen=True, slots=True)
class _InferenceReport:
"""What the bounded-inference leg did, as inert trace data."""
consulted: bool
detail: str
premise_ids: tuple[str, ...] = ()
outcome: str | None = None
reason: str | None = None
oracle_verdict: str | None = None
agreement: bool | None = None
entailment: dict[str, Any] | None = None
def to_trace_dict(self) -> dict[str, Any]:
summary: dict[str, Any] = {"consulted": self.consulted, "detail": self.detail}
if self.consulted:
summary.update(
{
"premise_ids": list(self.premise_ids),
"outcome": self.outcome,
"reason": self.reason,
"oracle_verdict": self.oracle_verdict,
"engine_oracle_agreement": self.agreement,
"entailment_trace": self.entailment,
}
)
return summary
_INFERENCE_NOT_PRESENT: Final[_InferenceReport] = _InferenceReport(
consulted=False, detail="no_inference_block"
)
def _evaluate_inference(
payload: dict[str, Any], evidence: list[dict[str, Any]]
) -> _InferenceReport:
"""Decide the bounded-inference leg with the real entailment engine.
Premises must be cited evidence references that resolved against the sealed
corpus; a rule record contributes its committed formula, a fact record its
atom. The query is the claim's atom. ``inferred`` is therefore an actual
sound-and-complete entailment decision citing records that merely *exist*
proves nothing. The engine verdict is cross-checked against the
independent truth-table oracle; the caller treats disagreement as a
defensive refusal.
"""
inference = payload.get("inference") inference = payload.get("inference")
if not isinstance(inference, dict): if not isinstance(inference, dict):
return None return _INFERENCE_NOT_PRESENT
premise_ids = inference.get("premise_ids") or [] premise_ids = tuple(inference.get("premise_ids") or ())
known_ids = {record["evidence_id"] for record in payload.get("evidence", [])} if not premise_ids:
if not premise_ids or any(pid not in known_ids for pid in premise_ids): return _InferenceReport(consulted=False, detail="no_premises")
return None
return sorted(premise_ids) resolved_by_id = {record["evidence_id"]: record for record in evidence}
premises: list[str] = []
for premise_id in premise_ids:
record = resolved_by_id.get(premise_id)
if record is None:
return _InferenceReport(consulted=False, detail="premise_unresolved")
premises.append(_premise_formula(record))
query = _claim_atom(payload["claim"])
trace = evaluate_entailment_with_trace(tuple(premises), query)
oracle_verdict = oracle_entailment(tuple(premises), query)
return _InferenceReport(
consulted=True,
detail="evaluated",
premise_ids=tuple(sorted(premise_ids)),
outcome=trace.outcome.value,
reason=trace.reason,
oracle_verdict=oracle_verdict,
agreement=trace.outcome.value == oracle_verdict,
entailment=trace.as_dict(),
)
def _base_trace_summary(payload: dict[str, Any], evidence: list[dict[str, Any]], independent: list[dict[str, Any]]) -> dict[str, Any]: def _base_trace_summary(
payload: dict[str, Any],
evidence: list[dict[str, Any]],
independent: list[dict[str, Any]],
inference: _InferenceReport,
) -> dict[str, Any]:
return { return {
"authority_evaluated": True, "authority_evaluated": True,
"envelope_version": "local-v1", "envelope_version": "local-v1",
"claim_fingerprint": _claim_fingerprint(payload), "claim_fingerprint": _claim_fingerprint(payload),
"corpus_id": corpus_identifier(),
"corpus_sha256": corpus_file_sha256(),
"evidence_considered": len(evidence), "evidence_considered": len(evidence),
"independent_support_count": len(independent), "independent_support_count": len(independent),
"proposer_trace_hash_ignored": "trace_hash" in payload["proposer"], "proposer_trace_hash_ignored": "trace_hash" in payload["proposer"],
"proposer_state_ignored": "proposed_state" in payload["proposer"], "proposer_state_ignored": "proposed_state" in payload["proposer"],
"inference": inference.to_trace_dict(),
} }
def _authority_path(inference: _InferenceReport) -> list[str]:
"""Consulted authorities in order — the entailment engine and the oracle
appear only when the inference leg actually ran."""
path = [_ROOT_AUTHORITY, _ASSIGN_AUTHORITY, _ENVELOPE_AUTHORITY, _CORPUS_AUTHORITY]
if inference.consulted:
path.extend([_ENTAIL_AUTHORITY, _ORACLE_AUTHORITY])
path.append(_TAXONOMY_AUTHORITY)
return path
def _assigned( def _assigned(
payload: dict[str, Any], payload: dict[str, Any],
*, *,
@ -290,6 +498,7 @@ def _assigned(
decision_reason: str, decision_reason: str,
evidence_ledger: list[str], evidence_ledger: list[str],
trace_summary: dict[str, Any], trace_summary: dict[str, Any],
inference: _InferenceReport,
extra: dict[str, Any] | None = None, extra: dict[str, Any] | None = None,
) -> dict[str, Any]: ) -> dict[str, Any]:
response = { response = {
@ -297,12 +506,7 @@ def _assigned(
"status": "assigned", "status": "assigned",
"request_id": payload["request_id"], "request_id": payload["request_id"],
"scenario_id": payload["scenario_id"], "scenario_id": payload["scenario_id"],
"authority_path": [ "authority_path": _authority_path(inference),
_ROOT_AUTHORITY,
_ASSIGN_AUTHORITY,
_ENVELOPE_AUTHORITY,
_TAXONOMY_AUTHORITY,
],
"decision_reason": decision_reason, "decision_reason": decision_reason,
"assigned_state": coerce_epistemic_state(state).value, "assigned_state": coerce_epistemic_state(state).value,
"normative_clearance": coerce_normative_clearance(clearance).value, "normative_clearance": coerce_normative_clearance(clearance).value,
@ -318,15 +522,14 @@ def assign_epistemic_state(payload: dict[str, Any]) -> dict[str, Any]:
"""CORE's sole authority over the typed epistemic state. """CORE's sole authority over the typed epistemic state.
The proposer's ``proposed_state`` is never read here. The state is derived The proposer's ``proposed_state`` is never read here. The state is derived
only from the claim, the evidence bundle, and the bounded-inference block. only from the claim, sealed evidence references, and the bounded-inference
block.
""" """
claim = payload["claim"] claim = payload["claim"]
evidence: list[dict[str, Any]] = payload.get("evidence", []) evidence_refs: list[dict[str, Any]] = payload.get("evidence", [])
matching = _matching_evidence(claim, evidence)
independent = [record for record in matching if bool(record.get("independent"))]
trace_summary = _base_trace_summary(payload, evidence, independent)
# Scope: refuse claims declared outside the local epistemic envelope. # Scope: refuse claims declared outside the local epistemic envelope before
# consulting the corpus at all.
if claim["domain"] not in ENVELOPE_DOMAINS: if claim["domain"] not in ENVELOPE_DOMAINS:
return _finalize( return _finalize(
{ {
@ -345,11 +548,64 @@ def assign_epistemic_state(payload: dict[str, Any]) -> dict[str, Any]:
NormativeClearance.UNASSESSABLE NormativeClearance.UNASSESSABLE
).value, ).value,
"evidence_ledger": [], "evidence_ledger": [],
"trace_summary": trace_summary, "trace_summary": {
"authority_evaluated": True,
"envelope_version": "local-v1",
"claim_fingerprint": _claim_fingerprint(payload),
"evidence_considered": len(evidence_refs),
"evidence_resolution": "not_consulted",
"proposer_trace_hash_ignored": "trace_hash" in payload["proposer"],
"proposer_state_ignored": "proposed_state" in payload["proposer"],
},
"refusal_reason": "outside_epistemic_envelope", "refusal_reason": "outside_epistemic_envelope",
} }
) )
evidence, ref_errors = resolve_evidence_refs(evidence_refs)
if ref_errors:
return _invalid_evidence_response(payload, ref_errors)
matching = _matching_evidence(claim, evidence)
independent = _independent_evidence(matching)
inference = _evaluate_inference(payload, evidence)
trace_summary = _base_trace_summary(payload, evidence, independent, inference)
# Defensive fail-closed: the engine and the independent oracle must agree
# before any inference-derived state is assigned. This path should never
# fire (both procedures are sound and complete over the regime); if it
# does, refusing is the only honest output.
if inference.consulted and inference.agreement is False:
return _finalize(
{
"tool": TOOL_NAME,
"status": "refused",
"request_id": payload["request_id"],
"scenario_id": payload["scenario_id"],
"authority_path": _authority_path(inference),
"decision_reason": "entailment_oracle_disagreement",
"assigned_state": None,
"normative_clearance": coerce_normative_clearance(
NormativeClearance.UNASSESSABLE
).value,
"evidence_ledger": [],
"trace_summary": trace_summary,
"refusal_reason": "entailment_oracle_disagreement",
}
)
# Contradicted: the resolved premises propositionally refute the claim.
# Conflict is surfaced, never averaged away.
if inference.consulted and inference.outcome == Entailment.REFUTED.value:
return _assigned(
payload,
state=EpistemicState.CONTRADICTED,
clearance=NormativeClearance.UNASSESSABLE,
decision_reason="claim_refuted_by_entailment",
evidence_ledger=list(inference.premise_ids),
trace_summary=trace_summary,
inference=inference,
extra={"inference_basis": list(inference.premise_ids)},
)
# Verified: two or more independent records that match subject and predicate. # Verified: two or more independent records that match subject and predicate.
# Clearance stays UNASSESSABLE even here: this demo assigns epistemic # Clearance stays UNASSESSABLE even here: this demo assigns epistemic
# truth-state only and runs no normative/safety/ethics clearance pass, so it # truth-state only and runs no normative/safety/ethics clearance pass, so it
@ -362,19 +618,28 @@ def assign_epistemic_state(payload: dict[str, Any]) -> dict[str, Any]:
decision_reason="verified_by_matching_evidence", decision_reason="verified_by_matching_evidence",
evidence_ledger=sorted(record["evidence_id"] for record in independent), evidence_ledger=sorted(record["evidence_id"] for record in independent),
trace_summary=trace_summary, trace_summary=trace_summary,
inference=inference,
) )
# Inferred: claim follows from bounded premises and is not directly matched. # Inferred: the claim is not directly supported but its atom is PROVED from
inference_basis = _resolved_inference_basis(payload) # the resolved premises by the sound-and-complete entailment decision, with
if inference_basis is not None and not matching: # the independent oracle agreeing. Premises that merely resolve do not
# infer anything.
if (
inference.consulted
and inference.outcome == Entailment.ENTAILED.value
and inference.agreement is True
and not matching
):
return _assigned( return _assigned(
payload, payload,
state=EpistemicState.INFERRED, state=EpistemicState.INFERRED,
clearance=NormativeClearance.UNASSESSABLE, clearance=NormativeClearance.UNASSESSABLE,
decision_reason="bounded_inference_from_evidence", decision_reason="entailed_from_resolved_premises",
evidence_ledger=inference_basis, evidence_ledger=list(inference.premise_ids),
trace_summary=trace_summary, trace_summary=trace_summary,
extra={"inference_basis": inference_basis}, inference=inference,
extra={"inference_basis": list(inference.premise_ids)},
) )
# Evidenced: at least one supporting record, but not enough to verify. # Evidenced: at least one supporting record, but not enough to verify.
@ -386,9 +651,11 @@ def assign_epistemic_state(payload: dict[str, Any]) -> dict[str, Any]:
decision_reason="evidence_present_but_not_verifying", decision_reason="evidence_present_but_not_verifying",
evidence_ledger=sorted(record["evidence_id"] for record in matching), evidence_ledger=sorted(record["evidence_id"] for record in matching),
trace_summary=trace_summary, trace_summary=trace_summary,
inference=inference,
) )
# Undetermined: nothing grounds the claim. CORE asks rather than guesses. # Undetermined: nothing grounds the claim. CORE asks rather than guesses —
# unrelated premises and unsupported claims land here, never in `inferred`.
return _assigned( return _assigned(
payload, payload,
state=EpistemicState.UNDETERMINED, state=EpistemicState.UNDETERMINED,
@ -396,6 +663,7 @@ def assign_epistemic_state(payload: dict[str, Any]) -> dict[str, Any]:
decision_reason="insufficient_evidence", decision_reason="insufficient_evidence",
evidence_ledger=[], evidence_ledger=[],
trace_summary=trace_summary, trace_summary=trace_summary,
inference=inference,
extra={ extra={
"question": ( "question": (
"CORE has insufficient grounded evidence to assign a determined " "CORE has insufficient grounded evidence to assign a determined "
@ -416,10 +684,13 @@ def run_authority(payload: Any) -> dict[str, Any]:
__all__ = [ __all__ = [
"ENVELOPE_DOMAINS", "ENVELOPE_DOMAINS",
"EVIDENCE_CORPUS_PATH",
"SCHEMA_PATH", "SCHEMA_PATH",
"TOOL_NAME", "TOOL_NAME",
"assign_epistemic_state", "assign_epistemic_state",
"load_evidence_corpus",
"load_schema", "load_schema",
"resolve_evidence_refs",
"run_authority", "run_authority",
"validate_payload", "validate_payload",
] ]

View file

@ -0,0 +1,68 @@
{
"corpus_id": "demo.epistemic_truth_state.evidence_corpus.v1",
"records": [
{
"evidence_id": "ev-a1-trace",
"subject": "reviewed_teaching_loop",
"predicate": "ran_on_pinned_cognition_pack",
"source_kind": "vault",
"provenance_root": "vault:pinned-cognition-trace",
"assertion": "The vault trace records that the reviewed teaching loop ran on the pinned cognition pack."
},
{
"evidence_id": "ev-a1-replay",
"subject": "reviewed_teaching_loop",
"predicate": "ran_on_pinned_cognition_pack",
"source_kind": "teaching",
"provenance_root": "teaching:pinned-cognition-replay",
"assertion": "The teaching replay report records that the reviewed teaching loop ran on the pinned cognition pack."
},
{
"evidence_id": "ev-b1-log",
"subject": "smoke_suite",
"predicate": "passed_on_current_branch",
"source_kind": "observation",
"provenance_root": "observation:smoke-log",
"assertion": "The local smoke log records that the smoke suite passed on the current branch."
},
{
"evidence_id": "ev-c1-tag-on-main",
"subject": "release_tag",
"predicate": "points_at_main",
"source_kind": "premise",
"provenance_root": "premise:release-tag",
"assertion": "The release tag points at main."
},
{
"evidence_id": "ev-c1-branch-from-main",
"subject": "current_branch",
"predicate": "branched_from_main",
"source_kind": "premise",
"provenance_root": "premise:current-branch",
"assertion": "The current branch was created from main."
},
{
"evidence_id": "ev-c1-rule-reachability",
"source_kind": "premise",
"provenance_root": "premise:reachability-rule",
"formula": "release_tag__points_at_main & current_branch__branched_from_main -> release_tag__reachable_from_current_branch",
"assertion": "Ratified rule: a release tag that points at main is reachable from any branch created from main."
},
{
"evidence_id": "ev-d1-unrelated",
"subject": "documentation_pass",
"predicate": "merged_to_main",
"source_kind": "observation",
"provenance_root": "observation:documentation-pass",
"assertion": "The documentation pass merged to main."
},
{
"evidence_id": "ev-e1-rumor",
"subject": "named_public_stock",
"predicate": "closes_higher_tomorrow",
"source_kind": "observation",
"provenance_root": "observation:market-rumor",
"assertion": "A rumor-style observation claims that the named public stock will close higher tomorrow."
}
]
}

View file

@ -4,6 +4,7 @@
"demos.epistemic_truth_state.authority.validate_payload", "demos.epistemic_truth_state.authority.validate_payload",
"demos.epistemic_truth_state.authority.assign_epistemic_state", "demos.epistemic_truth_state.authority.assign_epistemic_state",
"demo_epistemic_truth_state_envelope(local-v1)", "demo_epistemic_truth_state_envelope(local-v1)",
"demos.epistemic_truth_state.authority.resolve_evidence_refs",
"core.epistemic_state.coerce_epistemic_state" "core.epistemic_state.coerce_epistemic_state"
], ],
"decision_reason": "evidence_present_but_not_verifying", "decision_reason": "evidence_present_but_not_verifying",
@ -15,13 +16,19 @@
"scenario_id": "evidenced-but-not-verified-claim", "scenario_id": "evidenced-but-not-verified-claim",
"status": "assigned", "status": "assigned",
"tool": "core.epistemic_truth_state.review", "tool": "core.epistemic_truth_state.review",
"trace_hash": "f9f2e153e66aaba9dcb1d7e57bb30947cb7f4dd9b09de3625b12c21b55d80b3c", "trace_hash": "c4fcd4ae033cad4f609ef2e1bcc4a3c1d36647feb4e1931301ce48110cf20c6c",
"trace_summary": { "trace_summary": {
"authority_evaluated": true, "authority_evaluated": true,
"claim_fingerprint": "289e494aa06b8bd26b9cd26d61e08b966f78dcfc0f211db250ccf0ec7539a744", "claim_fingerprint": "289e494aa06b8bd26b9cd26d61e08b966f78dcfc0f211db250ccf0ec7539a744",
"corpus_id": "demo.epistemic_truth_state.evidence_corpus.v1",
"corpus_sha256": "62e03b4ac981eaeebdeed64bb2ff9ab1bcfef8cb521ec4029acdbe3b9f120b2e",
"envelope_version": "local-v1", "envelope_version": "local-v1",
"evidence_considered": 1, "evidence_considered": 1,
"independent_support_count": 1, "independent_support_count": 1,
"inference": {
"consulted": false,
"detail": "no_inference_block"
},
"proposer_state_ignored": true, "proposer_state_ignored": true,
"proposer_trace_hash_ignored": true "proposer_trace_hash_ignored": true
} }

View file

@ -4,15 +4,20 @@
"demos.epistemic_truth_state.authority.validate_payload", "demos.epistemic_truth_state.authority.validate_payload",
"demos.epistemic_truth_state.authority.assign_epistemic_state", "demos.epistemic_truth_state.authority.assign_epistemic_state",
"demo_epistemic_truth_state_envelope(local-v1)", "demo_epistemic_truth_state_envelope(local-v1)",
"demos.epistemic_truth_state.authority.resolve_evidence_refs",
"generate.proof_chain.entail.evaluate_entailment_with_trace",
"evals.deductive_logic.oracle.oracle_entailment",
"core.epistemic_state.coerce_epistemic_state" "core.epistemic_state.coerce_epistemic_state"
], ],
"decision_reason": "bounded_inference_from_evidence", "decision_reason": "entailed_from_resolved_premises",
"evidence_ledger": [ "evidence_ledger": [
"ev-c1-branch-from-main", "ev-c1-branch-from-main",
"ev-c1-rule-reachability",
"ev-c1-tag-on-main" "ev-c1-tag-on-main"
], ],
"inference_basis": [ "inference_basis": [
"ev-c1-branch-from-main", "ev-c1-branch-from-main",
"ev-c1-rule-reachability",
"ev-c1-tag-on-main" "ev-c1-tag-on-main"
], ],
"normative_clearance": "unassessable", "normative_clearance": "unassessable",
@ -20,13 +25,41 @@
"scenario_id": "inferred-from-bounded-evidence", "scenario_id": "inferred-from-bounded-evidence",
"status": "assigned", "status": "assigned",
"tool": "core.epistemic_truth_state.review", "tool": "core.epistemic_truth_state.review",
"trace_hash": "bc11e858ece140813c2307aa9c6c602650a4cec63972f520f29ba6863f437949", "trace_hash": "3d7e92fceeba328186721e9e4dd33338eff50a72f547988f88f27cbc9cc2526a",
"trace_summary": { "trace_summary": {
"authority_evaluated": true, "authority_evaluated": true,
"claim_fingerprint": "12e38c11f88615b1afb8e035e6e942eedd434ea0c6e3b4b25fbb7ff06695204a", "claim_fingerprint": "12e38c11f88615b1afb8e035e6e942eedd434ea0c6e3b4b25fbb7ff06695204a",
"corpus_id": "demo.epistemic_truth_state.evidence_corpus.v1",
"corpus_sha256": "62e03b4ac981eaeebdeed64bb2ff9ab1bcfef8cb521ec4029acdbe3b9f120b2e",
"envelope_version": "local-v1", "envelope_version": "local-v1",
"evidence_considered": 2, "evidence_considered": 3,
"independent_support_count": 0, "independent_support_count": 0,
"inference": {
"consulted": true,
"detail": "evaluated",
"engine_oracle_agreement": true,
"entailment_trace": {
"conjunction_key": "0:release_tag__reachable_from_current_branch?T:F;1:release_tag__points_at_main?@0:F;2:current_branch__branched_from_main?@1:F",
"entailment_check_key": "T",
"outcome": "entailed",
"premise_keys": [
"0:release_tag__points_at_main?T:F",
"0:current_branch__branched_from_main?T:F",
"0:release_tag__reachable_from_current_branch?T:F;1:release_tag__points_at_main?@0:T;2:current_branch__branched_from_main?@1:T"
],
"query_key": "0:release_tag__reachable_from_current_branch?T:F",
"reason": "tautological_implication",
"refutation_check_key": "0:release_tag__reachable_from_current_branch?F:T;1:release_tag__points_at_main?@0:T;2:current_branch__branched_from_main?@1:T"
},
"oracle_verdict": "entailed",
"outcome": "entailed",
"premise_ids": [
"ev-c1-branch-from-main",
"ev-c1-rule-reachability",
"ev-c1-tag-on-main"
],
"reason": "tautological_implication"
},
"proposer_state_ignored": true, "proposer_state_ignored": true,
"proposer_trace_hash_ignored": true "proposer_trace_hash_ignored": true
} }

View file

@ -13,13 +13,13 @@
"scenario_id": "refused-outside-scope", "scenario_id": "refused-outside-scope",
"status": "refused", "status": "refused",
"tool": "core.epistemic_truth_state.review", "tool": "core.epistemic_truth_state.review",
"trace_hash": "c9ef9560bcf71052f9e4f323d5f6c49dc23113dcaa6a63048cfdffafec6dd024", "trace_hash": "f1d8936f7616d2739041edd1b7e2c85b4355e39665d94c21b9a4d2e6e0c802f8",
"trace_summary": { "trace_summary": {
"authority_evaluated": true, "authority_evaluated": true,
"claim_fingerprint": "ef9317e405906823799755113ccb216ab39dd7b055c9f9883ada6480b80ef98c", "claim_fingerprint": "ef9317e405906823799755113ccb216ab39dd7b055c9f9883ada6480b80ef98c",
"envelope_version": "local-v1", "envelope_version": "local-v1",
"evidence_considered": 1, "evidence_considered": 1,
"independent_support_count": 1, "evidence_resolution": "not_consulted",
"proposer_state_ignored": true, "proposer_state_ignored": true,
"proposer_trace_hash_ignored": true "proposer_trace_hash_ignored": true
} }

View file

@ -4,6 +4,7 @@
"demos.epistemic_truth_state.authority.validate_payload", "demos.epistemic_truth_state.authority.validate_payload",
"demos.epistemic_truth_state.authority.assign_epistemic_state", "demos.epistemic_truth_state.authority.assign_epistemic_state",
"demo_epistemic_truth_state_envelope(local-v1)", "demo_epistemic_truth_state_envelope(local-v1)",
"demos.epistemic_truth_state.authority.resolve_evidence_refs",
"core.epistemic_state.coerce_epistemic_state" "core.epistemic_state.coerce_epistemic_state"
], ],
"decision_reason": "insufficient_evidence", "decision_reason": "insufficient_evidence",
@ -14,13 +15,19 @@
"scenario_id": "undetermined-insufficient-evidence", "scenario_id": "undetermined-insufficient-evidence",
"status": "assigned", "status": "assigned",
"tool": "core.epistemic_truth_state.review", "tool": "core.epistemic_truth_state.review",
"trace_hash": "35b319eb0186be2d9bedf65263d5acb8f397f747e7efe1ea01960655deafc7d2", "trace_hash": "80559d4b02668e36d7858097c09eac3e6e4e10c20615fdc2c9b5f3c4afa09cdf",
"trace_summary": { "trace_summary": {
"authority_evaluated": true, "authority_evaluated": true,
"claim_fingerprint": "dc8720472531486a19edbb82c2accd279d291afe2a797c23d2745469c4f91662", "claim_fingerprint": "dc8720472531486a19edbb82c2accd279d291afe2a797c23d2745469c4f91662",
"corpus_id": "demo.epistemic_truth_state.evidence_corpus.v1",
"corpus_sha256": "62e03b4ac981eaeebdeed64bb2ff9ab1bcfef8cb521ec4029acdbe3b9f120b2e",
"envelope_version": "local-v1", "envelope_version": "local-v1",
"evidence_considered": 1, "evidence_considered": 1,
"independent_support_count": 0, "independent_support_count": 0,
"inference": {
"consulted": false,
"detail": "no_inference_block"
},
"proposer_state_ignored": true, "proposer_state_ignored": true,
"proposer_trace_hash_ignored": true "proposer_trace_hash_ignored": true
} }

View file

@ -0,0 +1,54 @@
{
"assigned_state": "undetermined",
"authority_path": [
"demos.epistemic_truth_state.authority.validate_payload",
"demos.epistemic_truth_state.authority.assign_epistemic_state",
"demo_epistemic_truth_state_envelope(local-v1)",
"demos.epistemic_truth_state.authority.resolve_evidence_refs",
"generate.proof_chain.entail.evaluate_entailment_with_trace",
"evals.deductive_logic.oracle.oracle_entailment",
"core.epistemic_state.coerce_epistemic_state"
],
"decision_reason": "insufficient_evidence",
"evidence_ledger": [],
"normative_clearance": "unassessable",
"question": "CORE has insufficient grounded evidence to assign a determined epistemic state to this claim. Provide supporting, refuting, or premise evidence.",
"request_id": "demo-eps-g1",
"scenario_id": "unrelated-premise-still-undetermined",
"status": "assigned",
"tool": "core.epistemic_truth_state.review",
"trace_hash": "48c9932a5dd99f1a41ee879f1f39f6de5e365162797129c23f339054a5e92d1b",
"trace_summary": {
"authority_evaluated": true,
"claim_fingerprint": "9f381a36a05cb5c0f98ce7339522abb36be89f142f7668aae4359e8a0367537b",
"corpus_id": "demo.epistemic_truth_state.evidence_corpus.v1",
"corpus_sha256": "62e03b4ac981eaeebdeed64bb2ff9ab1bcfef8cb521ec4029acdbe3b9f120b2e",
"envelope_version": "local-v1",
"evidence_considered": 1,
"independent_support_count": 0,
"inference": {
"consulted": true,
"detail": "evaluated",
"engine_oracle_agreement": true,
"entailment_trace": {
"conjunction_key": "0:documentation_pass__merged_to_main?T:F",
"entailment_check_key": "0:vault_recall__is_approximate?T:F;1:documentation_pass__merged_to_main?@0:T",
"outcome": "unknown",
"premise_keys": [
"0:documentation_pass__merged_to_main?T:F"
],
"query_key": "0:vault_recall__is_approximate?T:F",
"reason": "undetermined",
"refutation_check_key": "0:vault_recall__is_approximate?F:T;1:documentation_pass__merged_to_main?@0:T"
},
"oracle_verdict": "unknown",
"outcome": "unknown",
"premise_ids": [
"ev-d1-unrelated"
],
"reason": "undetermined"
},
"proposer_state_ignored": true,
"proposer_trace_hash_ignored": true
}
}

View file

@ -4,6 +4,7 @@
"demos.epistemic_truth_state.authority.validate_payload", "demos.epistemic_truth_state.authority.validate_payload",
"demos.epistemic_truth_state.authority.assign_epistemic_state", "demos.epistemic_truth_state.authority.assign_epistemic_state",
"demo_epistemic_truth_state_envelope(local-v1)", "demo_epistemic_truth_state_envelope(local-v1)",
"demos.epistemic_truth_state.authority.resolve_evidence_refs",
"core.epistemic_state.coerce_epistemic_state" "core.epistemic_state.coerce_epistemic_state"
], ],
"decision_reason": "verified_by_matching_evidence", "decision_reason": "verified_by_matching_evidence",
@ -16,13 +17,19 @@
"scenario_id": "verified-supported-claim", "scenario_id": "verified-supported-claim",
"status": "assigned", "status": "assigned",
"tool": "core.epistemic_truth_state.review", "tool": "core.epistemic_truth_state.review",
"trace_hash": "1341c27c5906ae528ecc1f0cc4ebd3f71db68f138f6d8365fe0e93dd2d7f7097", "trace_hash": "fd0042f5f2bea77d15bfe387faa2a1045e38c61593d93232e35653f492890154",
"trace_summary": { "trace_summary": {
"authority_evaluated": true, "authority_evaluated": true,
"claim_fingerprint": "cef9198360d02ce3133c1095e776ae86a714fd1c9718aa3576616f935eccdf98", "claim_fingerprint": "cef9198360d02ce3133c1095e776ae86a714fd1c9718aa3576616f935eccdf98",
"corpus_id": "demo.epistemic_truth_state.evidence_corpus.v1",
"corpus_sha256": "62e03b4ac981eaeebdeed64bb2ff9ab1bcfef8cb521ec4029acdbe3b9f120b2e",
"envelope_version": "local-v1", "envelope_version": "local-v1",
"evidence_considered": 2, "evidence_considered": 2,
"independent_support_count": 2, "independent_support_count": 2,
"inference": {
"consulted": false,
"detail": "no_inference_block"
},
"proposer_state_ignored": true, "proposer_state_ignored": true,
"proposer_trace_hash_ignored": true "proposer_trace_hash_ignored": true
} }

View file

@ -20,11 +20,7 @@
"evidence": [ "evidence": [
{ {
"evidence_id": "ev-b1-log", "evidence_id": "ev-b1-log",
"subject": "smoke_suite", "content_sha256": "22049f3356d6e5398f80ad58683ba94ee559296b85ee009b02cf04dd453aa773"
"predicate": "passed_on_current_branch",
"supports": true,
"independent": true,
"source_kind": "observation"
} }
] ]
} }

View file

@ -20,24 +20,24 @@
"evidence": [ "evidence": [
{ {
"evidence_id": "ev-c1-tag-on-main", "evidence_id": "ev-c1-tag-on-main",
"subject": "release_tag", "content_sha256": "83dbbf3ff366458233ed71e153d3608a643ea6d6646958148c8746c181e00be2"
"predicate": "points_at_main",
"supports": true,
"independent": true,
"source_kind": "premise"
}, },
{ {
"evidence_id": "ev-c1-branch-from-main", "evidence_id": "ev-c1-branch-from-main",
"subject": "current_branch", "content_sha256": "bb792e8ff12a6a29f5dc50e988aa9012ae68a010cbe42096c7727266ee1b9444"
"predicate": "branched_from_main", },
"supports": true, {
"independent": true, "evidence_id": "ev-c1-rule-reachability",
"source_kind": "premise" "content_sha256": "b9a51ca7d9d596b1ac91a85b11420c92c1bbdb989a7739621200a3590e591573"
} }
], ],
"inference": { "inference": {
"mode": "bounded_deductive", "mode": "bounded_deductive",
"premise_ids": ["ev-c1-tag-on-main", "ev-c1-branch-from-main"] "premise_ids": [
"ev-c1-tag-on-main",
"ev-c1-branch-from-main",
"ev-c1-rule-reachability"
]
} }
} }
} }

View file

@ -20,11 +20,7 @@
"evidence": [ "evidence": [
{ {
"evidence_id": "ev-e1-rumor", "evidence_id": "ev-e1-rumor",
"subject": "named_public_stock", "content_sha256": "5c41a3b6b0e1ca53e688c470be67740b628f689b304247cb72ce7fc382d56e1a"
"predicate": "closes_higher_tomorrow",
"supports": true,
"independent": true,
"source_kind": "observation"
} }
] ]
} }

View file

@ -20,11 +20,7 @@
"evidence": [ "evidence": [
{ {
"evidence_id": "ev-d1-unrelated", "evidence_id": "ev-d1-unrelated",
"subject": "documentation_pass", "content_sha256": "d47df7dc3a7d7e51dcac951de2981777f612af4c40924b7f8d9e8abca3b98af2"
"predicate": "merged_to_main",
"supports": true,
"independent": true,
"source_kind": "observation"
} }
] ]
} }

View file

@ -0,0 +1,31 @@
{
"tool": "core.epistemic_truth_state.review",
"expected_status": "assigned",
"arguments": {
"request_id": "demo-eps-g1",
"scenario_id": "unrelated-premise-still-undetermined",
"proposer": {
"lane": "frontier_fixture",
"model_family": "model_style_proposer",
"proposal_id": "proposal-g1",
"proposed_state": "inferred",
"trace_hash": "9999999999999999999999999999999999999999999999999999999999999999"
},
"claim": {
"text": "Vault recall is approximate.",
"domain": "demo.local_factual",
"subject": "vault_recall",
"predicate": "is_approximate"
},
"evidence": [
{
"evidence_id": "ev-d1-unrelated",
"content_sha256": "d47df7dc3a7d7e51dcac951de2981777f612af4c40924b7f8d9e8abca3b98af2"
}
],
"inference": {
"mode": "bounded_deductive",
"premise_ids": ["ev-d1-unrelated"]
}
}
}

View file

@ -20,19 +20,11 @@
"evidence": [ "evidence": [
{ {
"evidence_id": "ev-a1-trace", "evidence_id": "ev-a1-trace",
"subject": "reviewed_teaching_loop", "content_sha256": "a507b19de0860fafdfc00e7d581a4c1b5ded7f1510e052ba92f7325abfebbaf5"
"predicate": "ran_on_pinned_cognition_pack",
"supports": true,
"independent": true,
"source_kind": "vault"
}, },
{ {
"evidence_id": "ev-a1-replay", "evidence_id": "ev-a1-replay",
"subject": "reviewed_teaching_loop", "content_sha256": "a8564c2daa27c7fe851711f068b682ffa87f769014a13a7d5b5625e44ebb9679"
"predicate": "ran_on_pinned_cognition_pack",
"supports": true,
"independent": true,
"source_kind": "teaching"
} }
] ]
} }

View file

@ -1,7 +1,7 @@
{ {
"name": "core.epistemic_truth_state.review", "name": "core.epistemic_truth_state.review",
"title": "CORE epistemic truth-state authority demo", "title": "CORE epistemic truth-state authority demo",
"description": "Submit one model-style claim proposal to CORE's local deterministic epistemic-state authority. CORE validates a closed payload, ignores any proposer-supplied proposed_state and trace hash, assigns a typed epistemic state drawn from the canonical core.epistemic_state taxonomy, derives normative clearance, builds an evidence ledger, and returns assigned | refused | invalid plus a deterministic trace artifact. The proposer cannot set the assigned state, status, clearance, evidence ledger, authority path, or trace hash.", "description": "Submit one model-style claim proposal to CORE's local deterministic epistemic-state authority. CORE validates a closed payload, resolves sealed evidence references by content hash, ignores any proposer-supplied proposed_state and trace hash, decides the bounded-inference leg with the sound-and-complete ROBDD entailment engine cross-checked against an independent truth-table oracle, assigns a typed epistemic state drawn from the canonical core.epistemic_state taxonomy, derives normative clearance, builds an evidence ledger, and returns assigned | refused | invalid plus a deterministic trace artifact. The proposer cannot set the assigned state, status, clearance, evidence ledger, authority path, trace hash, support labels, or independence labels — and cannot mint inferred by citing records that merely exist, because inferred requires an actual entailment proof.",
"inputSchema": { "inputSchema": {
"type": "object", "type": "object",
"properties": { "properties": {
@ -56,12 +56,14 @@
"subject": { "subject": {
"type": "string", "type": "string",
"minLength": 1, "minLength": 1,
"maxLength": 120 "maxLength": 120,
"pattern": "^[a-z][a-z0-9_]*$"
}, },
"predicate": { "predicate": {
"type": "string", "type": "string",
"minLength": 1, "minLength": 1,
"maxLength": 120 "maxLength": 120,
"pattern": "^[a-z][a-z0-9_]*$"
} }
}, },
"required": ["text", "domain", "subject", "predicate"], "required": ["text", "domain", "subject", "predicate"],
@ -76,28 +78,12 @@
"type": "string", "type": "string",
"pattern": "^[A-Za-z0-9._-]{1,64}$" "pattern": "^[A-Za-z0-9._-]{1,64}$"
}, },
"subject": { "content_sha256": {
"type": "string", "type": "string",
"minLength": 1, "pattern": "^[a-f0-9]{64}$"
"maxLength": 120
},
"predicate": {
"type": "string",
"minLength": 1,
"maxLength": 120
},
"supports": {
"type": "boolean"
},
"independent": {
"type": "boolean"
},
"source_kind": {
"type": "string",
"enum": ["pack", "teaching", "vault", "observation", "premise"]
} }
}, },
"required": ["evidence_id", "subject", "predicate", "supports"], "required": ["evidence_id", "content_sha256"],
"additionalProperties": false "additionalProperties": false
} }
}, },

View file

@ -6,6 +6,7 @@ This checklist applies to public CORE demos.
- [ ] Demo purpose is stated narrowly. - [ ] Demo purpose is stated narrowly.
- [ ] Demo status is clear: merged, draft PR, proposed, or not yet implemented. - [ ] Demo status is clear: merged, draft PR, proposed, or not yet implemented.
- [ ] Demo evidence class is stated: substrate-capability, interface-contract, simulation-only, or proposed.
- [ ] README includes "what this proves." - [ ] README includes "what this proves."
- [ ] README includes "what this does not prove." - [ ] README includes "what this does not prove."
- [ ] README avoids named-company outreach strategy. - [ ] README avoids named-company outreach strategy.
@ -34,10 +35,19 @@ This checklist applies to public CORE demos.
- [ ] Proposer input cannot set final authority status. - [ ] Proposer input cannot set final authority status.
- [ ] Proposer input cannot smuggle final action artifacts. - [ ] Proposer input cannot smuggle final action artifacts.
- [ ] Proposer input cannot indirectly decide the result through trusted support, independence, verdict, or clearance labels.
- [ ] Invalid payloads fail closed. - [ ] Invalid payloads fail closed.
- [ ] Refusal and ask outcomes are first-class successes. - [ ] Refusal and ask outcomes are first-class successes.
- [ ] Authorized outputs, if present, are inert artifacts unless a later production system explicitly implements execution. - [ ] Authorized outputs, if present, are inert artifacts unless a later production system explicitly implements execution.
## Evidence strength
- [ ] Capability claims route through a real CORE operator, runtime path, sealed eval lane, or independently checked proof surface.
- [ ] Interface-contract demos are not described as substrate-capability demos.
- [ ] Fixture evidence is labeled as fixture evidence.
- [ ] Sealed-corpus or independent-oracle claims name the corpus/oracle and the no-shared-code boundary.
- [ ] Boolean/string policy demos are framed as boundary checks unless another substrate decision is actually present.
## Public hygiene ## Public hygiene
- [ ] No named-person outreach planning. - [ ] No named-person outreach planning.

View file

@ -22,12 +22,31 @@ Public repository docs must not include:
- company-specific red-team personas; - company-specific red-team personas;
- current-facts dossiers for outreach. - current-facts dossiers for outreach.
## Evidence strength
Public demos must distinguish the strength of the evidence they provide.
**Substrate-capability demos** route the proposal through a real CORE operator,
runtime path, sealed eval lane, or independently checked proof surface. These demos
may support capability claims, within their stated envelope.
**Interface-contract demos** prove the typed boundary: closed schema, fail-closed
validation, proposer-held status ignored, inert outputs, deterministic traces, and
no side effects. These demos are useful, but they must not be described as proving
deep CORE reasoning capability by themselves.
This distinction is load-bearing. A demo that only checks strings, booleans, or
schema shape may prove an authority boundary; it does not prove that the geometric
or deductive substrate made a non-trivial decision.
## Demonstrated ## Demonstrated
### Hybrid Verification Demo (#687 — authority over claims) ### Hybrid Verification Demo (#687 — authority over claims)
Status: merged (PR #687). Status: merged (PR #687).
Evidence class: substrate-capability demo.
Purpose: demonstrate a bounded proposer-to-substrate verification path with typed outcomes. A model-style proposer submits a claim; the substrate, not the proposer, decides the typed outcome. Purpose: demonstrate a bounded proposer-to-substrate verification path with typed outcomes. A model-style proposer submits a claim; the substrate, not the proposer, decides the typed outcome.
Hard finding recorded by this demo: agreement between reasoning paths is not reliable safety. Multiple paths can agree and still be wrong. Authority must live at the typed boundary, not merely in multiple model outputs. Hard finding recorded by this demo: agreement between reasoning paths is not reliable safety. Multiple paths can agree and still be wrong. Authority must live at the typed boundary, not merely in multiple model outputs.
@ -51,8 +70,16 @@ Public safety boundary:
Status: merged (PR #688, merge commit `c55f7dfb`). Status: merged (PR #688, merge commit `c55f7dfb`).
Evidence class: interface-contract demo.
Purpose: demonstrate that a model-style proposer may submit a typed action proposal, while CORE alone may authorize, ask, refuse, or invalidate. The authorized output is an inert `licensed_action` artifact only; no external side effect executes and the proposer holds no execution authority. Purpose: demonstrate that a model-style proposer may submit a typed action proposal, while CORE alone may authorize, ask, refuse, or invalidate. The authorized output is an inert `licensed_action` artifact only; no external side effect executes and the proposer holds no execution authority.
Evidence caveat: this demo proves the digital-action boundary contract. Its local
authority evaluator is deliberately small, so it must not be described as proving
general tool-safety reasoning or production MCP capability. Its value is that the
proposer cannot self-authorize, inject a license, supply a trusted trace hash, or
cause side effects.
Public outcome vocabulary: Public outcome vocabulary:
- `authorized` - `authorized`
@ -69,45 +96,81 @@ Public safety boundary:
- inert `licensed_action` artifact only; - inert `licensed_action` artifact only;
- MCP-shaped, not production MCP. - MCP-shaped, not production MCP.
## Proposed ### Epistemic Truth-State Demo (#690 — authority over state assignment)
Recommended order of next public evidence: Status: merged (PR #690); hardened in this reconciliation pass to use sealed
evidence references and an entailment-decided inference leg.
1. Epistemic Truth-State Demo (next target); Evidence class: local epistemic-state authority demo; the `inferred` leg is a
2. Embodied Authority Simulation Demo (simulation-only); substrate-capability decision (it routes through the proof-chain entailment
3. SaaS / On-Prem Boundary Demo. engine with an independent-oracle cross-check).
Merged evidence so far establishes two authority boundaries: authority over claims (#687) and authority over proposed tool actions (#688). The next target extends the same pattern to epistemic state. Purpose: show that a model-style proposer can submit a claim, sealed evidence
references, and `proposed_state`, while CORE emits the canonical typed state and
deterministic trace. The proposer controls neither the assigned state nor the
trace.
### Epistemic Truth-State Demo (next public evidence target) Public outcome vocabulary:
Status: proposed.
Purpose: show that a model-style proposer can submit a claim, answer, or state proposal, but CORE assigns the typed epistemic state and emits deterministic, replayable evidence. The proposer controls neither the assigned state nor the trace.
Possible states (illustrative; the implementing PR fixes the closed set):
- `perceived`;
- `evidenced`;
- `verified`; - `verified`;
- `decoded`; - `evidenced`;
- `inferred`; - `inferred`;
- `refused`; - `contradicted`;
- `undetermined`; - `undetermined`;
- `scope_boundary`; - `scope_boundary`;
- `invalid`. - `invalid`.
Possible outputs: Evidence caveat: the evidence corpus is still local fixture evidence, not live
vault retrieval or arbitrary web evidence. The proposer supplies evidence
references only; CORE resolves them by committed content hash and computes support
and independence from sealed corpus records. `inferred` is assigned only when the
cited premises propositionally entail the claim's atom under the sound-and-complete
ROBDD entailment engine, cross-checked against the independent truth-table oracle;
citing records that merely exist yields `undetermined` (the committed
`unrelated-premise-still-undetermined` scenario exercises that attack). The demo
must not be described as production epistemic evaluation across arbitrary evidence
sources.
- state ledger entry; ## Proposed
- evidence / provenance spans;
- deterministic trace hash;
- `ask` or refusal when evidence is insufficient;
- no proposer-controlled state;
- no proposer-controlled trace;
- `invalid` rejected before state evaluation.
No claim is made here that the full demo is implemented until a PR lands. Recommended order of next public evidence:
1. Deductive Entailment / Proof-Carrying Authority Demo (next substrate-capability target);
2. Embodied Authority Simulation Demo (simulation-only);
3. SaaS / On-Prem Boundary Demo.
Merged evidence establishes three authority boundaries: authority over claims
(#687), proposed tool actions (#688), and epistemic state assignment (#690). The
next public target should make the non-trivial substrate decision visible: a
proposer supplies premises, conclusion, and claimed verdict; CORE decides through
the existing deductive/proof surface and emits replayable proof evidence.
### Deductive Entailment / Proof-Carrying Authority Demo
Status: proposed.
Purpose: demonstrate a non-trivial authority boundary over formal entailment. The
proposer submits premises, a conclusion, and a claimed verdict. CORE decides via
the existing proof-chain / deductive-logic substrate, with trace evidence that can
be checked against the independent truth-table oracle discipline already used by
the deductive lane.
Required outcomes:
- `entailed`;
- `refuted`;
- `unknown`;
- `refused`;
- `invalid`.
Required proof obligations:
- proposer verdict ignored;
- malformed or out-of-regime logic refused;
- inconsistent premises refused rather than vacuously proving everything;
- at least one scenario where the proposer is wrong and CORE's verdict differs;
- deterministic trace includes canonical proof keys or certificate evidence;
- no shared-code oracle is presented as independent evidence.
### Embodied Authority Simulation Demo ### Embodied Authority Simulation Demo

View file

@ -152,9 +152,7 @@ deterministically, with the proof chain as the audit artifact — the logical fo
of the *"structural coherence metric"* ADR-0021 names as the successor to curator of the *"structural coherence metric"* ADR-0021 names as the successor to curator
mediation. What review still gates there is the faithfulness of the reading, not mediation. What review still gates there is the faithfulness of the reading, not
the deduction. This proof-carrying promotion path is **specified but not yet the deduction. This proof-carrying promotion path is **specified but not yet
wired** (see wired**; until it lands, all promotion is curator-mediated.
[`docs/issues/proof-carrying-coherence-promotion.md`](issues/proof-carrying-coherence-promotion.md));
until it lands, all promotion is curator-mediated.
This is not a safety overlay. It is a consequence of the decoding thesis: if the This is not a safety overlay. It is a consequence of the decoding thesis: if the
system decodes a reality that already is, then inputs that contradict — or merely system decodes a reality that already is, then inputs that contradict — or merely
@ -384,8 +382,13 @@ behavioral testing of a black-box sampler.
## Concrete Evidence — Merged Demos (2026-06-11) ## Concrete Evidence — Merged Demos (2026-06-11)
The claims in §4 are abstract without pointers to reproducible artifacts. This The claims in §4 are abstract without pointers to reproducible artifacts. This
section ties each abstract property to a specific merged demo, trace hash, and section ties those properties to merged demos, trace hashes, and runnable
runnable command. All three demos are in the public repository under `demos/`. commands. The demos are not all the same kind of evidence. #687 routes through the
real derivation and ASK machinery and is the substrate-capability anchor. #688 is
an interface-contract demo. #690 is a local epistemic-state authority demo using a
sealed fixture corpus. They prove that proposer-held status cannot cross the typed
boundary, but they must not be mistaken for production tool safety or arbitrary
evidence evaluation.
### Authority over claims — PR #687, merge `3ba65d51` ### Authority over claims — PR #687, merge `3ba65d51`
@ -412,11 +415,11 @@ architecture would not.
### Authority over proposed tool actions — PR #688, merge `c55f7dfb` ### Authority over proposed tool actions — PR #688, merge `c55f7dfb`
`demos/claude_tool_authority/` demonstrates the same authority boundary for `demos/claude_tool_authority/` demonstrates the same typed boundary for proposed
proposed digital actions across four typed outcomes. A model-style proposer submits digital actions across four outcomes. A model-style proposer submits action
action proposals; CORE alone authorizes, asks, refuses, or invalidates. Authorized proposals; the local authority envelope authorizes, asks, refuses, or invalidates.
outputs are inert `licensed_action` artifacts; `execution_performed: false` on every Authorized outputs are inert `licensed_action` artifacts; `execution_performed:
scenario. false` on every scenario.
Representative trace hashes: Representative trace hashes:
- Authorized (inert): `9e797710ed34dfa5…` (`write_local_note`, `proposer_trace_hash_ignored: true`) - Authorized (inert): `9e797710ed34dfa5…` (`write_local_note`, `proposer_trace_hash_ignored: true`)
@ -426,19 +429,26 @@ Representative trace hashes:
Run: `python demos/claude_tool_authority/run_demo.py` Run: `python demos/claude_tool_authority/run_demo.py`
Evidence caveat: #688 is an interface-contract demo. It proves no proposer can
self-authorize, smuggle a license, provide a trusted trace hash, or cause a side
effect through this boundary. It does not prove production MCP integration or
general autonomous tool-safety reasoning; its decision core is intentionally a
small local envelope.
### Authority over epistemic state assignment — PR #690, merge `e80c8eae` ### Authority over epistemic state assignment — PR #690, merge `e80c8eae`
`demos/epistemic_truth_state/` demonstrates the same authority boundary for `demos/epistemic_truth_state/` demonstrates the same typed boundary for epistemic
epistemic state assignment across six typed outcomes. A model-style proposer state assignment across six outcomes. A model-style proposer submits a claim,
submits a claim with evidence and a `proposed_state`; CORE assigns the canonical sealed evidence references, and a `proposed_state`; the demo assigns a canonical
state from the evidence. `proposer_state_ignored: true` on every output. state from committed corpus records whose content hashes must match.
`proposer_state_ignored: true` on every non-invalid output.
Typed state vocabulary: `verified`, `evidenced`, `inferred`, `undetermined`, Typed state vocabulary: `verified`, `evidenced`, `inferred`, `undetermined`,
`scope_boundary`. A proposer that injects `assigned_state` or `authority_path` into `scope_boundary`. A proposer that injects `assigned_state` or `authority_path` into
the request payload is rejected at the typed schema boundary before evaluation. the request payload is rejected at the typed schema boundary before evaluation.
Representative trace hashes: Representative trace hashes:
- Verified: `1341c27c5906ae52…` (2 independent evidence items, `normative_clearance: unassessable`) - Verified: `1341c27c5906ae52…` (2 sealed corpus records with distinct provenance roots, `normative_clearance: unassessable`)
- Evidenced: `f9f2e153e66aaba9…` (1 item, below threshold — proposer proposed `verified`) - Evidenced: `f9f2e153e66aaba9…` (1 item, below threshold — proposer proposed `verified`)
- Inferred: `bc11e858ece14081…` (premise-only evidence — proposer proposed `verified`) - Inferred: `bc11e858ece14081…` (premise-only evidence — proposer proposed `verified`)
- Undetermined: `35b319eb0186be2d…` (off-topic evidence) - Undetermined: `35b319eb0186be2d…` (off-topic evidence)
@ -448,11 +458,12 @@ Representative trace hashes:
Run: `python demos/epistemic_truth_state/run_demo.py` Run: `python demos/epistemic_truth_state/run_demo.py`
**Honesty note:** `normative_clearance` is `"unassessable"` on every non-invalid **Honesty note:** `normative_clearance` is `"unassessable"` on every non-invalid
scenario; the invalid scenario has `null` (no evaluation reached). The demos do not scenario; the invalid scenario has `null` because evaluation never reached the
perform a normative, safety, or ethics clearance pass for any scenario. The authority path. The demo runs no normative, safety, or ethics clearance pass. The
`deterministic replay` and `identity protection` claims in §4 are substrate evidence corpus is local fixture evidence, so #690 should be read as a
properties; the epistemic state demos extend them to claim/action/state authority state-authority demo over a sealed local corpus, not as proof that CORE evaluates
surfaces not covered in the original paper. arbitrary evidence sources. The next proof obligation is proof-carrying entailment
evidence for claims that should move from stated premises to promoted knowledge.
--- ---
@ -463,10 +474,10 @@ generation is the right substrate for cognition in the first place.
CORE is a running argument that it is not. The argument is not in this paper. It CORE is a running argument that it is not. The argument is not in this paper. It
is in the versor invariant, the zero-wrong eval gate, the deterministic trace is in the versor invariant, the zero-wrong eval gate, the deterministic trace
hash, the reviewed teaching path, the two-layer identity firewall, and now in three hash, the reviewed teaching path, the two-layer identity firewall, and the public
public demos where a deterministic substrate holds exclusive authority over claims, authority-demo stack. The strongest current demo proves substrate authority over
proposed actions, and epistemic state — each of which would fail visibly if the claims; the surrounding boundary demos expose the exact places where broader
thesis were wrong. action and epistemic authority still need harder evidence.
The code is open source under the CORE Non-Commercial License. The code is open source under the CORE Non-Commercial License.
All commercial licensing inquiries: shayj292@gmail.com All commercial licensing inquiries: shayj292@gmail.com

View file

@ -19,6 +19,7 @@ SCENARIOS = {
"verified-supported-claim": ("assigned", "verified"), "verified-supported-claim": ("assigned", "verified"),
"evidenced-but-not-verified-claim": ("assigned", "evidenced"), "evidenced-but-not-verified-claim": ("assigned", "evidenced"),
"inferred-from-bounded-evidence": ("assigned", "inferred"), "inferred-from-bounded-evidence": ("assigned", "inferred"),
"unrelated-premise-still-undetermined": ("assigned", "undetermined"),
"undetermined-insufficient-evidence": ("assigned", "undetermined"), "undetermined-insufficient-evidence": ("assigned", "undetermined"),
"refused-outside-scope": ("refused", "scope_boundary"), "refused-outside-scope": ("refused", "scope_boundary"),
"invalid-state-smuggling-attempt": ("invalid", None), "invalid-state-smuggling-attempt": ("invalid", None),
@ -110,15 +111,34 @@ def test_verified_requires_matching_evidence():
assert downgraded["assigned_state"] == "evidenced" assert downgraded["assigned_state"] == "evidenced"
assert downgraded["decision_reason"] == "evidence_present_but_not_verifying" assert downgraded["decision_reason"] == "evidence_present_but_not_verifying"
# Subject/predicate mismatch is not matching evidence at all. # A corpus reference for a different subject/predicate is not matching
# evidence at all.
mismatched = _arguments("verified-supported-claim") mismatched = _arguments("verified-supported-claim")
for record in mismatched["evidence"]: mismatched["evidence"] = _arguments("undetermined-insufficient-evidence")["evidence"]
record["predicate"] = "something_else"
none_match = authority.run_authority(mismatched) none_match = authority.run_authority(mismatched)
assert none_match["assigned_state"] == "undetermined" assert none_match["assigned_state"] == "undetermined"
assert none_match["decision_reason"] == "insufficient_evidence" assert none_match["decision_reason"] == "insufficient_evidence"
def test_proposer_cannot_supply_support_or_independence_labels():
payload = _arguments("verified-supported-claim")
payload["evidence"][0]["supports"] = True
payload["evidence"][0]["independent"] = True
response = authority.run_authority(payload)
assert response["status"] == "invalid"
assert "payload.evidence[0] unexpected property 'supports'" in response["invalid_reason"]
assert "payload.evidence[0] unexpected property 'independent'" in response["invalid_reason"]
def test_evidence_reference_hash_mismatch_is_invalid():
payload = _arguments("verified-supported-claim")
payload["evidence"][0]["content_sha256"] = "0" * 64
response = authority.run_authority(payload)
assert response["status"] == "invalid"
assert response["decision_reason"] == "invalid_evidence_reference"
assert "content hash mismatch for evidence reference 'ev-a1-trace'" in response["invalid_reason"]
def test_clearance_is_unassessable_for_all_non_invalid_outputs(): def test_clearance_is_unassessable_for_all_non_invalid_outputs():
# The demo assigns epistemic truth-state only; it runs no normative/safety/ # The demo assigns epistemic truth-state only; it runs no normative/safety/
# ethics clearance pass, so it must never positively clear anything. # ethics clearance pass, so it must never positively clear anything.
@ -138,19 +158,96 @@ def test_evidenced_state_for_single_support():
assert response["evidence_ledger"] == ["ev-b1-log"] assert response["evidence_ledger"] == ["ev-b1-log"]
def test_inferred_includes_inference_basis(): def test_inferred_is_decided_by_entailment_engine_with_oracle_agreement():
response = _run("inferred-from-bounded-evidence") response = _run("inferred-from-bounded-evidence")
assert response["assigned_state"] == "inferred" assert response["assigned_state"] == "inferred"
assert response["decision_reason"] == "bounded_inference_from_evidence" assert response["decision_reason"] == "entailed_from_resolved_premises"
assert response["inference_basis"] == ["ev-c1-branch-from-main", "ev-c1-tag-on-main"] assert response["inference_basis"] == [
"ev-c1-branch-from-main",
"ev-c1-rule-reachability",
"ev-c1-tag-on-main",
]
assert response["evidence_ledger"] == response["inference_basis"] assert response["evidence_ledger"] == response["inference_basis"]
inference = response["trace_summary"]["inference"]
assert inference["consulted"] is True
assert inference["outcome"] == "entailed"
assert inference["reason"] == "tautological_implication"
assert inference["oracle_verdict"] == "entailed"
assert inference["engine_oracle_agreement"] is True
# The ROBDD proof evidence is present: the implication check canonicalized
# to the tautology node.
assert inference["entailment_trace"]["entailment_check_key"] == "T"
# Both deciders appear in the authority path only because they were consulted.
assert "generate.proof_chain.entail.evaluate_entailment_with_trace" in (
response["authority_path"]
)
assert "evals.deductive_logic.oracle.oracle_entailment" in response["authority_path"]
def test_unrelated_premise_cannot_mint_inferred():
# The hazard this leg exists to prevent: a claim with no support, citing a
# resolvable but logically UNRELATED record as a premise, must not be
# assigned `inferred`. The engine decides `unknown`; the state falls to
# `undetermined`.
response = _run("unrelated-premise-still-undetermined")
assert response["assigned_state"] == "undetermined"
assert response["decision_reason"] == "insufficient_evidence"
inference = response["trace_summary"]["inference"]
assert inference["consulted"] is True
assert inference["outcome"] == "unknown"
assert inference["oracle_verdict"] == "unknown"
def test_premises_without_the_rule_do_not_entail():
# Dropping the rule record from the premises leaves two atoms that cannot
# entail the claim: the engine decides `unknown`, no inferred state.
payload = _arguments("inferred-from-bounded-evidence")
payload["inference"]["premise_ids"] = ["ev-c1-tag-on-main", "ev-c1-branch-from-main"]
response = authority.run_authority(payload)
assert response["assigned_state"] == "undetermined"
inference = response["trace_summary"]["inference"]
assert inference["outcome"] == "unknown"
assert inference["engine_oracle_agreement"] is True
def test_engine_oracle_disagreement_refuses(monkeypatch):
# Defensive fail-closed: if the independent oracle ever disagreed with the
# ROBDD engine, the demo must refuse rather than assign an inferred state.
monkeypatch.setattr(authority, "oracle_entailment", lambda premises, query: "unknown")
payload = _arguments("inferred-from-bounded-evidence")
response = authority.run_authority(payload)
assert response["status"] == "refused"
assert response["refusal_reason"] == "entailment_oracle_disagreement"
assert response["assigned_state"] is None
def test_unconsulted_entailment_engine_not_in_authority_path():
response = _run("verified-supported-claim")
assert "generate.proof_chain.entail.evaluate_entailment_with_trace" not in (
response["authority_path"]
)
assert response["trace_summary"]["inference"] == {
"consulted": False,
"detail": "no_inference_block",
}
def test_corpus_seal_is_pinned_in_traces():
response = _run("verified-supported-claim")
assert response["trace_summary"]["corpus_sha256"] == authority.corpus_file_sha256()
assert response["trace_summary"]["corpus_id"] == (
"demo.epistemic_truth_state.evidence_corpus.v1"
)
def test_inference_with_unresolved_premise_does_not_infer(): def test_inference_with_unresolved_premise_does_not_infer():
payload = _arguments("inferred-from-bounded-evidence") payload = _arguments("inferred-from-bounded-evidence")
payload["inference"]["premise_ids"] = ["ev-c1-tag-on-main", "does-not-exist"] payload["inference"]["premise_ids"] = ["ev-c1-tag-on-main", "does-not-exist"]
response = authority.run_authority(payload) response = authority.run_authority(payload)
assert response["assigned_state"] == "undetermined" assert response["assigned_state"] == "undetermined"
assert response["trace_summary"]["inference"]["detail"] == "premise_unresolved"
def test_undetermined_emits_question(): def test_undetermined_emits_question():
@ -160,13 +257,18 @@ def test_undetermined_emits_question():
assert "insufficient grounded evidence" in response["question"] assert "insufficient grounded evidence" in response["question"]
def test_scope_boundary_refuses(): def test_scope_boundary_refuses_without_consulting_corpus():
response = _run("refused-outside-scope") response = _run("refused-outside-scope")
assert response["status"] == "refused" assert response["status"] == "refused"
assert response["assigned_state"] == "scope_boundary" assert response["assigned_state"] == "scope_boundary"
assert response["refusal_reason"] == "outside_epistemic_envelope" assert response["refusal_reason"] == "outside_epistemic_envelope"
assert response["decision_reason"] == "outside_epistemic_envelope" assert response["decision_reason"] == "outside_epistemic_envelope"
assert response["evidence_ledger"] == [] assert response["evidence_ledger"] == []
# An out-of-envelope claim is refused before the corpus is consulted.
assert response["trace_summary"]["evidence_resolution"] == "not_consulted"
assert "demos.epistemic_truth_state.authority.resolve_evidence_refs" not in (
response["authority_path"]
)
def test_proposer_cannot_set_assigned_state(): def test_proposer_cannot_set_assigned_state():