js-rigor: TTU reverse+tuplesetDirection-in now honors direction

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.
This commit is contained in:
John Dvorak
2026-07-31 18:54:57 -07:00
parent 0149926344
commit 30fc7e5017
3 changed files with 146 additions and 6 deletions
+3 -1
View File
@@ -208,7 +208,9 @@ export class CompiledEvaluator {
const tuplesetDirection = optimized.tuplesetDirection || 'out';
let tuples;
if (optimized.reverse) {
tuples = this.arbiter.relationManager.getRelationsFromSrc(userId, optimized.tuplesetRelation, options);
tuples = tuplesetDirection === 'in'
? this.arbiter.relationManager.getRelationsToDst(userId, optimized.tuplesetRelation, options)
: this.arbiter.relationManager.getRelationsFromSrc(userId, optimized.tuplesetRelation, options);
} else {
tuples = tuplesetDirection === 'in'
? this.arbiter.relationManager.getRelationsToDst(objectId, optimized.tuplesetRelation, options)
+15 -5
View File
@@ -83,19 +83,27 @@ export class TupleToUsersetRule extends BaseRule {
let tuples;
const useRelationGraph = !options?.partialGraphContext;
if (reverse) {
// reverse honors tuplesetDirection like the forward path: 'in' means
// intermediates hold the tupleset relation TO the user (edge.src is the
// intermediate), 'out' means the user holds it to the intermediate.
const reverseLookup = tuplesetDirection === 'in';
const useGraphNeighbors = useRelationGraph &&
this.arbiter.relationManager.shouldUseRelationGraphTraversal(userId, rule.tuplesetRelation, false);
this.arbiter.relationManager.shouldUseRelationGraphTraversal(userId, rule.tuplesetRelation, reverseLookup);
const neighbors = useGraphNeighbors
? this.arbiter.relationManager.getRelationGraphNeighbors(userId, rule.tuplesetRelation, false)
? this.arbiter.relationManager.getRelationGraphNeighbors(userId, rule.tuplesetRelation, reverseLookup)
: null;
if (neighbors) {
tuples = [];
for (const neighborId of neighbors) {
const edge = this.arbiter.relationManager.getDirectRelation(userId, rule.tuplesetRelation, neighborId, options);
const edge = reverseLookup
? this.arbiter.relationManager.getDirectRelation(neighborId, rule.tuplesetRelation, userId, options)
: this.arbiter.relationManager.getDirectRelation(userId, rule.tuplesetRelation, neighborId, options);
if (edge) tuples.push(edge);
}
} else {
tuples = this.arbiter.relationManager.getRelationsFromSrc(userId, rule.tuplesetRelation, options);
tuples = reverseLookup
? this.arbiter.relationManager.getRelationsToDst(userId, rule.tuplesetRelation, options)
: this.arbiter.relationManager.getRelationsFromSrc(userId, rule.tuplesetRelation, options);
}
} else {
const reverseLookup = tuplesetDirection === 'in';
@@ -189,7 +197,9 @@ export class TupleToUsersetRule extends BaseRule {
processedCount++;
const tupleEdge = reverse
? this.arbiter.relationManager.getDirectRelation(userId, rule.tuplesetRelation, intermediateId, options)
? (tuplesetDirection === 'in'
? this.arbiter.relationManager.getDirectRelation(intermediateId, rule.tuplesetRelation, userId, options)
: this.arbiter.relationManager.getDirectRelation(userId, rule.tuplesetRelation, intermediateId, options))
: (tuplesetDirection === 'in'
? this.arbiter.relationManager.getDirectRelation(intermediateId, rule.tuplesetRelation, objectId, options)
: this.arbiter.relationManager.getDirectRelation(objectId, rule.tuplesetRelation, intermediateId, options));