js-rigor: OWA fusion hardened; reliabilityWeighting, shorthand children, cache key
Probe sweep of the OWA surfaces found three real defects:
- reliabilityWeighting was a silent no-op everywhere: every implementation
scaled possibilities by metas[i].reliability, but no child meta ever
carried a reliability field (the compiled direct omitted it and the
DirectRule handler omitted it too), so the weighting was always x1.0.
All weighting branches now use the tracked child reliabilities, and the
DirectRule handler + its meta now carry the relation's reliability.
- The compiled union and the direct_list fast path had no
reliabilityWeighting branch at all; both now apply it.
- Shorthand children ({ relation: 'editor' }) dispatch to the direct
handler but carry no type, so _getRuleResultCacheKey derived the generic
'rule' suffix for every shorthand child of a logical rule — the first
child's cached result was served for all of them (the fallback path
returned the owner's 0.8 for the editor). The key derivation now matches
the shorthand dispatch. The RuleEvaluator also treats shorthand operands
as direct rules instead of unknown_rule_type on the non-compiled path.
New pins: an OWA differential property (custom weights, max/min/average
aggregators, reliabilityWeighting, compiled path) and a multi_hop
pathAggregation=owa fixed pin with reliability propagation.
This commit is contained in:
@@ -95,7 +95,10 @@ export class RuleEvaluator {
|
||||
}
|
||||
|
||||
// For other rule types, evaluate normally first
|
||||
const handler = this.ruleHandlers[rule.type];
|
||||
// Shorthand operand objects ({ relation: 'owner' } inside logical rules,
|
||||
// or caller-supplied raw configs) carry no type: treat them as direct
|
||||
// rules instead of failing with unknown_rule_type.
|
||||
const handler = this.ruleHandlers[rule.type || (rule.relation || rule.rel || rule.label || rule.name ? 'direct' : null)];
|
||||
if (!handler) {
|
||||
return {
|
||||
possibility_allow: 0,
|
||||
@@ -123,8 +126,12 @@ export class RuleEvaluator {
|
||||
if (rule) {
|
||||
if (rule.union || rule.intersection || rule.exclusion) {
|
||||
suffix = 'logical';
|
||||
} else if (rule.type === 'direct') {
|
||||
suffix = `direct:${rule.relation || 'unknown'}`;
|
||||
} else if (rule.type === 'direct' || (!rule.type && (rule.relation || rule.rel || rule.label || rule.name) && !rule.union && !rule.intersection && !rule.exclusion)) {
|
||||
// Shorthand operands ({ relation: 'editor' }) dispatch to the direct
|
||||
// handler but carry no type; without this, every shorthand child of
|
||||
// a logical rule shares one cache key and the first child's result
|
||||
// is served for all of them.
|
||||
suffix = `direct:${rule.relation || rule.rel || rule.label || rule.name || 'unknown'}`;
|
||||
} else if (rule.type === 'tuple_to_userset') {
|
||||
suffix = `tupleset:${rule.tuplesetRelation || 'unknown'}:${rule.computedRelation || 'unknown'}`;
|
||||
} else if (rule.type === 'chain' && Array.isArray(rule.steps)) {
|
||||
|
||||
Reference in New Issue
Block a user