core/core/reasoning/adapters.py
Shay 568face63e feat(reasoning): field-wedge foundation — f64 embedding, lineage firewall, INV-27
Phase 0 of the field-reasoner wedge — net hardening regardless of the
experiment's outcome.

- algebra/cga.py: embed_point gains a dtype kwarg (f32 default byte-unchanged;
  cl41.geometric_product already preserves f64) + read_scalar_e1 projective
  dehomogenization read-back (weight-invariant; correct for dilations, where a
  raw distance-from-origin is wrong) + EMBED_EXACT_MAX pinned magnitude ceiling.
  f32 silently collapsed integer coordinates past ~1e4.
- core/reasoning/evidence.py: verify_tier2_agreement now keys independence on a
  reader_lineage pathway token (refuses SAME_READER_LINEAGE), replacing the
  label-only len(set(signatures))<2 check a single reader could satisfy by
  relabeling. reader_lineage is excluded from canonical serialization, so the
  entailment trace_hash is unchanged.
- tests INV-27: transitive reader-disjointness over TIER2_READER_PATHWAYS makes
  the lineage check load-bearing (distinct lineage => proven import-disjoint
  pathway). The two seeded readers share zero transitive first-party modules.

Green: smoke 87, algebra 82, cognition 121, 53 architectural invariants,
reasoning/deductive/r1 50; 16 new f64-exactness tests; zero regressions.
2026-06-04 19:22:16 -07:00

119 lines
3.8 KiB
Python

"""Adapters from existing operator traces into shared reasoning evidence."""
from __future__ import annotations
import hashlib
import json
from typing import Any
from core.reasoning.evidence import OperatorEvidence
from generate.math_problem_graph import MathProblemGraph
from generate.math_solver import SolutionTrace
from generate.proof_chain import Entailment, EntailmentTrace
def evidence_from_entailment_trace(trace: EntailmentTrace) -> OperatorEvidence:
"""Convert propositional entailment trace evidence to the shared contract."""
query_key = trace.query_key or ""
check_keys = tuple(
key for key in (
trace.conjunction_key,
trace.entailment_check_key,
trace.refutation_check_key,
)
if key
)
if trace.outcome is Entailment.REFUSED:
commitment_key = ""
else:
commitment_key = f"entailment:{trace.outcome.value}:{query_key}"
structural_signature = _sha256_text(
json.dumps(
{
"operator": "propositional_entailment",
"premise_keys": list(trace.premise_keys),
"check_keys": list(check_keys),
},
sort_keys=True,
separators=(",", ":"),
)
)
return OperatorEvidence(
domain="mathematics_logic",
operator="propositional_entailment",
outcome=trace.outcome.value,
reason=trace.reason,
input_keys=(*trace.premise_keys, query_key),
check_keys=check_keys,
commitment_key=commitment_key,
structural_signature=structural_signature,
reader_lineage="proof_chain.entail",
payload={"entailment_trace": trace.as_dict()},
)
def evidence_from_math_solution(
*,
graph: MathProblemGraph,
trace: SolutionTrace,
reader_trace: tuple[str, ...] = (),
operator: str = "math_problem_graph_solve_verify",
reason: str = "solver_verifier_passed",
) -> OperatorEvidence:
"""Convert a verified MathProblemGraph solution to shared evidence."""
graph_hash = hashlib.sha256(graph.canonical_bytes()).hexdigest()
trace_hash = hashlib.sha256(trace.canonical_bytes()).hexdigest()
operation_kinds = tuple(step.operation_kind for step in trace.steps)
commitment_key = json.dumps(
{
"answer_entity": trace.answer_entity,
"answer_unit": trace.answer_unit,
"answer_value": trace.answer_value,
},
sort_keys=True,
separators=(",", ":"),
)
structural_signature = _sha256_text(
json.dumps(
{
"graph_hash": graph_hash,
"operation_kinds": list(operation_kinds),
"operator": operator,
"pack_id": trace.pack_id,
},
sort_keys=True,
separators=(",", ":"),
)
)
return OperatorEvidence(
domain="mathematics_logic",
operator=operator,
outcome="verified",
reason=reason,
input_keys=(graph_hash,),
check_keys=(trace_hash, trace.graph_canonical_hash),
commitment_key=commitment_key,
structural_signature=structural_signature,
reader_lineage="math_problem_graph.solve_verify",
payload={
"answer_entity": trace.answer_entity,
"answer_unit": trace.answer_unit,
"answer_value": trace.answer_value,
"graph_hash": graph_hash,
"operation_kinds": list(operation_kinds),
"pack_id": trace.pack_id,
"reader_trace": tuple(_reader_event(ev) for ev in reader_trace),
"trace_hash": trace_hash,
},
)
def _reader_event(event: str) -> Any:
try:
return json.loads(event)
except json.JSONDecodeError:
return event
def _sha256_text(text: str) -> str:
return hashlib.sha256(text.encode("utf-8")).hexdigest()