feat: tuple_to_userset intermediate reachability; ratio-based benchmark gate
- ChainRule._expandRuleFromSrc now expands tuple_to_userset configs: from a source node the reachable set is the objects sharing an intermediate with the source (src ->computed-> intermediate ->tupleset-> object, direction aware, weakest-link combined). Lets a TTU evidence serve as an intermediate condition step in a chain. - scripts/benchmark.js: ratio-based self-calibration. Comparing each action's RATIO to a cheap reference action (default check[direct-hit]) cancels machine-load swings that scale all actions proportionally, so the gate only fails on code regressions that shift a single action's ratio. The reference is still checked absolutely with a loose bound. Verified: stable across runs, and a simulated union-ttu slowdown is caught (+76.8% ratio). Tests: chain-condition-step intermediate TTU expansion.
This commit is contained in:
@@ -106,6 +106,35 @@ describe('ChainRule condition step (rule-based final hop)', () => {
|
||||
assert.equal(denied.possibility, 0);
|
||||
});
|
||||
|
||||
it('expands a tuple_to_userset evidence as an intermediate condition step', () => {
|
||||
arbiter.setRelationConfig('member_of', { type: 'direct' });
|
||||
arbiter.setRelationConfig('owner', { type: 'direct' });
|
||||
arbiter.setRelationConfig('doc_route', { type: 'direct' });
|
||||
arbiter.addNode('group:g', 'group');
|
||||
arbiter.addNode('doc:1', 'doc');
|
||||
arbiter.addNode('doc:2', 'doc');
|
||||
arbiter.addRelation('user:u', 'member_of', 'group:g', { possibility: 1.0 });
|
||||
arbiter.addRelation('group:g', 'owner', 'doc:1', { possibility: 0.8 });
|
||||
arbiter.addRelation('doc:1', 'doc_route', 'doc:2', { possibility: 0.9 });
|
||||
const ttuConfig = {
|
||||
type: 'tuple_to_userset',
|
||||
tuplesetRelation: 'owner',
|
||||
computedRelation: 'member_of',
|
||||
tuplesetDirection: 'in'
|
||||
};
|
||||
const rule = {
|
||||
type: 'chain',
|
||||
steps: [{ rule: ttuConfig, conditionStep: true }, 'doc_route']
|
||||
};
|
||||
// TTU reachable from user = doc:1 (min(1.0, 0.8) = 0.8), then doc_route → 0.9
|
||||
const res = evalRule('user:u', 'doc:2', rule);
|
||||
assert.ok(Math.abs(res.possibility - 0.8) < 1e-9, `expected 0.8, got ${res.possibility} (${res.reason})`);
|
||||
// Direct expansion unit check
|
||||
const expanded = chainRule._expandRuleFromSrc(arbiter.resolveNodeId('user:u'), ttuConfig, {});
|
||||
assert.equal(expanded.size, 1);
|
||||
assert.equal(arbiter.resolveKey([...expanded.keys()][0]), 'doc:1');
|
||||
});
|
||||
|
||||
it('combines across multiple parallel intermediates (max aggregation)', () => {
|
||||
arbiter.addNode('group:g2', 'group');
|
||||
arbiter.addRelation('user:u', 'member_of', 'group:g', { possibility: 0.5 });
|
||||
|
||||
Reference in New Issue
Block a user