Systemic reliability gap found by the probe sweep: the compiled evaluation
paths never emitted the reliability the engine computes.
- Compiled _evaluateDirect omitted the relation's reliability, and the
chain/multi_hop rules hardcoded reliability: 1.0 — so check() results
reported 1.0 for any rule whose decision came through a chain, multi_hop,
union, intersection, exclusion, or defeasible combination.
- The chain and multi_hop traversals now track per-path reliability (product
of edge reliabilities) and report the winning path's value; the compiled
and fallback logical operators (union/intersection/exclusion, direct_list
fast path, early exits) report the selected child's reliability
(max/min child or OWA trace index; exclusion multiplies both legs), and
normal-mode defeasible combines base x requires x defeater reliabilities.
- The checker's logical fast path dropped collectedValues from union/
intersection/exclusion results; it now passes them through.
- MultiHopRule.valueManager was read off relationManager where the real
arbiter keeps it on the arbiter — collectValues: true on a multi_hop rule
with a value-carrying edge crashed the evaluation (error result, silent
denial). Now resolved at the arbiter level with a relationManager
fallback for stubs.
Campaign pins: reliability per kind (chain/multi_hop product, union/intersection
selected child, exclusion/defeasible product), and multi_hop value collection
through persistent and partial contexts.
Two issues found by the extended probe sweep:
- A relational_comparator operand backed by a tuple_to_userset rule always
denied: the TTU rule collected only the intermediate KEY, which the
operand extraction skips as non-numeric, so no value was ever available.
The TTU rule now emits a value-carrying collected entry when the
tupleset edge carries a numeric value (entityKey = tuple src, relation =
tupleset relation), keeping the bare intermediate key when there is no
value. Comparator-with-TTU-operand now allows/denies on the tuple value
through both persistent and partial contexts.
- _modifyRelation ignored the changed_last_at override that the add path
honors: value-changing modifies stamped fresh Date.now() regardless of
the pin, so replay/restore tools pinning timestamps got different
semantics via modify vs add. The override now applies to refresh events
(value/reliability/possibility change) and is ignored for value-unchanged
writes, preserving the TTL parity contract that identical replays never
un-expire old values.
Verified clean: intersection through partial, defeasible with logical
when, challenge subject object/session with sessionKey, non-binary
minAllowPossibility threshold, batch value updates, explain agreement
under partial.
Bug 34: ArbiterChecks.check destructured { reliability, ...rest } out of
every normal (and binary) check result since the initial commit — the
engine computes reliability faithfully (TTU tupleset.reli * computed.reli,
direct relation reliability) and explain() preserved it, but the public
check() API silently dropped it. explain() kept it, so exposing it in
check() is the intended contract. The destructuring is removed; direct
and TTU checks now return reliability (0.6 / 0.72 in the pins).
Campaign pins added: TTU multi-path fusion (max over intermediates of
min(legs)) with reliability propagation through both persistent and
partial contexts, the maxIntermediates circuit breaker through partial,
and snapshot-restored arbiters evaluating TTU.
The reverse branch of TupleToUsersetRule ignored tuplesetDirection: it
looked up the tupleset relation as outgoing-from-user even when 'in' was
set, while the join honored 'in' by using t.src as the intermediate —
the documented shape (intermediates hold the relation TO the user) never
matched, and only a degenerate join-on-user shape produced results. The
same gap existed in the compiled direct_join optimization.
Fixed the fallback tupleset lookup (including the graph-neighbor path and
the computed-join tupleEdge direction) and the optimized direct_join to
honor tuplesetDirection in reverse mode. Matrix pins reverse-in (both
evaluation paths, persistent + partial), multi_hop reverse, chain-in,
union-with-chain-child, defeasible split legs, TTU value flow, and
challenge-via-binary.
Two real bugs found by the new rule-kind x partial-graph parity campaign:
- TupleToUsersetRule 'computed' join mode (computed side has fewer
intermediates than the tupleset side) pushed path objects carrying
combinedPossibility, but _buildFinalResult reads path.possibility —
every valid TTU grant in that mode silently returned 0, in persistent
and partial contexts alike.
- _collectRelationUsages only registered explicit type:'direct' children,
so shorthand logical operands ({ relation: 'owner' } inside union/
intersection/exclusion) left the dependency index empty: writes to a
base relation never invalidated cached logical decisions, and a check
performed before an add kept serving its stale result forever.
New campaign rule-kind-partial-parity.test.js pins the full kind x
persistent/partial matrix (direct, chain, multi_hop, TTU out/in/reverse,
parent, computed, defeasible, union, exclusion, comparator, challenge,
binary) plus seeded differential properties for TTU, comparator, and
exclusion; artifact persistence disabled to avoid disk bloat.