core/generate
Shay 1ff06726a6
feat(determine): add transitive strict-order relational inference (#781)
* feat(determine): add transitive strict-order relational inference

Add sound transitive closure for declared strict-order relational predicates —
less_than, greater_than, before_event, after_event, and ONLY these. A query
p(a, c) determines True when a same-predicate chain p(a, b), p(b, c), ... over the
predicate's OWN realized edges is found (BFS reachability) and the proof_chain ROBDD
verifies the transitive entailment (search-then-verify, through the UNCHANGED
evaluate_entailment via a new lower_transitive_chain). Mirrors _determine_subsumption.

Scope / firewall:
- TRANSITIVE_PREDICATES is closed and default-off; sibling_of, parent_of,
  left_of/right_of, inside_of, during_event, overlaps_event are EXCLUDED.
- Same-predicate edges only — no transitive-through-inverse, no cross-predicate
  (triple firewall: recall filter + lowering re-reject + ROBDD re-verify).
- Open-world: asserts only answer=True via the shared _relational_determined
  surface (rule="transitive"), so INV-30 stays at exactly 3 Determined sites and
  no answer=False is added. One-hop inverse/symmetric (#775) is unchanged.
  FrameVerdict / closed-world (ADR-0222) is untouched.

wrong=0 bite (unit + lane + independent oracle): non-transitive-predicate chains,
non-admitted spatial chains, mixed-predicate chains, disjoint chains, reflexive
cycles, and inverse+transitive composition all REFUSE.

Measurement: new evals/relational_transitive lane with an INDEPENDENT BFS
transitive-closure oracle (imports no engine module; INV-25/27), cross-checked both
directions (positives oracle-True, confusers oracle-False). Capability-index breadth
10 -> 11, wrong_total 0, deterministic digest re-frozen.

Cross-PR reconcile: migrated the one-hop confuser rinf-ref-001 (a less_than chain,
which now correctly determines transitively) to a B2 positive; repurposed its unit
test to a non-transitive parent_of chain; corrected a pre-existing stale breadth==9
assertion (#775 added a 10th domain but never updated test_capability_index).

Verified in the worktree: determine + transitive/one-hop lanes + capability
baseline/index + ProofWriter-OWA floor + INV-30/29/21/02 + full smoke — all green.
A 3-skeptic read-only adversarial review found no wrong=0 leak.

* test(determine): B2 hardening — TRANSITIVE_PREDICATES pin + lower_transitive defensive + budget

Add the required B2 hardening tests before merge:

- test_transitive_predicates_closed_and_excludes: the table is EXACTLY
  {less_than, greater_than, before_event, after_event}, every member is in
  RELATIONAL_PREDICATES, and every deliberately-excluded predicate (sibling_of,
  spouse_of, parent_of, child_of, left_of, right_of, inside_of, during_event,
  overlaps_event) is explicitly absent. (Closes the gap where relational.py's
  comment claimed this test existed but it did not.)

- tests/test_composition_lower_transitive.py: direct defensive tests on
  lower_transitive_chain — empty path, mislabeled (cross-predicate) edge, wrong
  arity, non-contiguous path, and path-not-reaching-target all lower to None
  (refuse); plus exact 2-hop and 3-hop theory pins.

- test_edge_budget_exhaustion_refuses: above _TRANSITIVE_EDGE_BUDGET the transitive
  search declines (a safe coverage refusal), never proves.
2026-06-15 14:20:30 -07:00
..
answer_choices feat(answer-choices): multiple-choice verifier with contradiction flag (R2 C4) 2026-06-07 07:26:00 -07:00
binding_graph feat(comprehension): the divisive comparative frame — "half as many" as exact integer division (PR-6c) 2026-06-06 20:18:39 -07:00
combined_rate_comprehension docs(cmb): lookback review + fix single-agent-attribution hygiene hazard (H3) 2026-06-08 13:27:17 -07:00
composition feat(determine): add transitive strict-order relational inference (#781) 2026-06-15 14:20:30 -07:00
comprehension
constraint_comprehension docs(comprehension): whole-system organ capability ledger + fix ADR-0211 number collision 2026-06-08 06:15:51 -07:00
contemplation feat(ask): split question artifact path from proposal path 2026-06-09 11:28:52 -07:00
cue_precision
derivation test(derivation): add ADR-0184 semantic replay equivalence harness 2026-06-10 14:35:22 -07:00
determine feat(determine): add transitive strict-order relational inference (#781) 2026-06-15 14:20:30 -07:00
meaning_graph feat(determine): add transitive strict-order relational inference (#781) 2026-06-15 14:20:30 -07:00
proof_chain feat(teaching): ADR-0218 P3 — proof-carrying coherence promotion 2026-06-11 17:02:45 -07:00
rate_comprehension feat(rate): exact time-unit conversion for single-rate (R3.2b-e) 2026-06-08 05:43:51 -07:00
realize refactor(comprehension): drop QuantQuery — consumers read the target from graph.unknowns (PR-3) 2026-06-06 16:49:09 -07:00
__init__.py
admissibility.py
articulation.py
articulation_legality.py
attention.py
bridge_trace.py
dialogue.py feat(persistence): Shape B+ Phase C — SessionContext.snapshot/restore (full lived state) 2026-06-05 12:13:46 -07:00
discourse_planner.py
exhaustion.py
graph_constraint.py
graph_planner.py
grounding_accessors.py
intent.py
intent_bridge.py
intent_ratifier.py
logic_canonical.py feat: modus_ponens + disagreement rule — proof_chain wrong=0 mechanism (ADR-0205) 2026-06-02 20:56:57 -07:00
logic_equivalence.py
math_candidate_graph.py feat: add gsm8k r1 reconstruction 2026-06-04 13:25:11 -07:00
math_candidate_parser.py fix(ADR-0136.S.3): expose both consumed tokens to completeness guard 2026-06-03 01:01:50 -07:00
math_completeness.py
math_parser.py
math_problem_graph.py
math_realizer.py
math_roundtrip.py
math_solver.py
math_symbolic_equivalence.py
math_symbolic_normalizer.py
math_verifier.py
morphology.py
ood_surface_generator.py
operators.py
perturbation_suite.py
proposition.py feat(persistence): Shape B+ Phase C — SessionContext.snapshot/restore (full lived state) 2026-06-05 12:13:46 -07:00
quantitative_comprehension.py feat(comprehension): inverse reader frame — base of a more/fewer-than (PR-7b / R2 C0) 2026-06-07 07:06:26 -07:00
quantitative_expr.py feat(comprehension): the divisive comparative frame — "half as many" as exact integer division (PR-6c) 2026-06-06 20:18:39 -07:00
realizer.py
realizer_guard.py
recognizer_anchor_inject.py docs(adr-0170): reconcile status to shipped reality — W1/W2 serve; fix sealed-lane comment (#771) 2026-06-15 10:22:58 -07:00
recognizer_match.py
recognizer_registry.py
relational_field_reader.py feat(field-wedge): geometric field reader — relational-metric lane wrong=0 (Phase W.1) 2026-06-04 19:34:43 -07:00
relational_symbolic_reader.py feat(field-wedge): ablation verdict — field is decoration on additive (C3) (Phase W.2) 2026-06-04 19:44:22 -07:00
result.py
rotor_admissibility.py
salience.py
semantic_templates.py
stream.py refactor(generate): remove redundant forbidden-site _close_final_state; rename "Drift fix 2" 2026-06-05 08:17:17 -07:00
surface.py
templates.py