feat: intermediate chain condition steps, graph-version cache invalidation, rolling-hash chain keys; fix vacuous rigor invariants
Chain intermediates (rule-based reachability):
- ChainRule: a condition step ({ rule, conditionStep }) at an INTERMEDIATE
position is now EXPANDED from the current node — the rule's base edges'
destinations, filtered by its defeaters/requirements — and traversal
continues from each discovered node. Adds _expandRuleFromSrc / direct /
logical(union/intersection) / defeasible / nested-chain expansion.
- RuleEvaluator: _subjectIsObject flag for unary predicate calls whose subject
entity IS the object parameter (trusted(other) inside peer_trusted(user,
other)); previously only subject-var unary calls (_subjectAsObject) were
handled, so object-var unary defeaters never fired.
Graph-version cache invalidation:
- Arbiter gains a monotonic _graphVersion, incremented on every relation
mutation. ChainRule result cache, RuleEvaluator rule-result cache, and
DecisionCache rule cache now stamp entries with the graph version and treat
any mismatch as a miss — graph mutations can no longer serve stale
chain/authorization results.
Rolling-hash cache keys:
- UnifiedKeyManager.createChainKey now builds a 53-bit rolling hash (dual
FNV-1a lanes, exact for ints/floats/strings/nested configs) instead of
JSON.stringify — no string allocation or serialization on the chain-cache
hot path. Composite keys stay structured strings because the direct-check
cache pattern-invalidates by relation ID.
Rigor invariant migration (correctness):
- All 43 rigor test files' throw-based invariants ({ error, errorMessage } =>
!error && !errorMessage) never saw fn throws — vacuous. Migrated to
({ actual }) => actual !== undefined, which fails on any thrown violation
while passing legitimate null-skips. The migration immediately surfaced
two latent bugs, now fixed:
* node-manager/graph-indices skip paths returned bare undefined (falsy
sentinel) — return { skipped: true }.
* complex-graph-values-crucible expiry section rewrote values equal to the
mutation loop's last write; the engine (by design) keeps the old
timestamp on same-value rewrites so the pre-expiry grant never
materialized. Now writes guaranteed-different values.
This commit is contained in:
@@ -75,7 +75,7 @@ describe('Authorization config consistency (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('path-parity', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('path-parity', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 300, seed: 'authz-config-parity' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -120,7 +120,7 @@ describe('Authorization config consistency (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('override-honored', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('override-honored', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 300, seed: 'authz-config-override' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -168,7 +168,7 @@ describe('Authorization config consistency (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('remediation-contract', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('remediation-contract', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 300, seed: 'authz-config-remediation' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ describe('Authorization graph semantics (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('direct-exact', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('direct-exact', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 400, seed: 'authz-graph-direct' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -101,7 +101,7 @@ describe('Authorization graph semantics (rigor)', () => {
|
||||
rigor.fn('check', check, rigor.args(rigor.gen.int(2, 6)))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('absent-denies', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('absent-denies', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 300, seed: 'authz-graph-absent' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -144,7 +144,7 @@ describe('Authorization graph semantics (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('weakest-link', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('weakest-link', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 400, seed: 'authz-graph-chain' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -194,7 +194,7 @@ describe('Authorization graph semantics (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('disjunctive-max', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('disjunctive-max', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 500, seed: 'authz-graph-multipath' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -246,7 +246,7 @@ describe('Authorization graph semantics (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('tus-weakest-link', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('tus-weakest-link', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 400, seed: 'authz-graph-tus' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -285,7 +285,7 @@ describe('Authorization graph semantics (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('revoke-invalidates', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('revoke-invalidates', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 300, seed: 'authz-graph-mutation' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ describe('Batch loading consistency (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('batch-parity', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('batch-parity', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 400, seed: 'batch-parity' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -177,7 +177,7 @@ describe('Batch loading consistency (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('batch-mutation-parity', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('batch-mutation-parity', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 400, seed: 'batch-mutation-parity' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -290,7 +290,7 @@ describe('Binary (threshold) mode parity (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('binary-normal-agreement', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('binary-normal-agreement', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 1200, seed: 'binary-mode-config-matrix' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -349,7 +349,7 @@ describe('Binary (threshold) mode parity (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('mutation-freshness', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('mutation-freshness', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 800, seed: 'binary-mode-mutation-parity' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ describe('Cache correctness under mutation (rigor)', () => {
|
||||
rigor.fn('check', check, rigor.args(opGen))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('cache-parity', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('cache-parity', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 600, seed: 'cache-onoff-parity' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -159,7 +159,7 @@ describe('Cache correctness under mutation (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('override-cache-fresh', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('override-cache-fresh', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 400, seed: 'cache-override-freshness' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -205,7 +205,7 @@ describe('Cache correctness under mutation (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('ttl-contract', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('ttl-contract', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 300, seed: 'cache-ttl-contract' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ describe('ChainRule evaluation (rigor)', () => {
|
||||
const report = await rigor.campaign(
|
||||
[rigor.fn('check', check, rigor.args())],
|
||||
rigor.crucible([
|
||||
rigor.invariant('empty-steps', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('empty-steps', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'chain-rule-empty-steps', effort: 200 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -82,7 +82,7 @@ describe('ChainRule evaluation (rigor)', () => {
|
||||
rigor.args(rigor.gen.float({ min: 0, max: 1 }))
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('possibility-bounded', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('possibility-bounded', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'chain-rule-possibility-bounded', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -117,7 +117,7 @@ describe('ChainRule evaluation (rigor)', () => {
|
||||
const report = await rigor.campaign(
|
||||
[rigor.fn('check', check, rigor.args())],
|
||||
rigor.crucible([
|
||||
rigor.invariant('no-path', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('no-path', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'chain-rule-no-path', effort: 500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -154,7 +154,7 @@ describe('ChainRule evaluation (rigor)', () => {
|
||||
rigor.args(rigor.gen.float({ min: 0.01, max: 1 }))
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('one-step-pos', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('one-step-pos', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'chain-rule-one-step', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -204,7 +204,7 @@ describe('ChainRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('two-step-chain', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('two-step-chain', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'chain-rule-two-step', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ describe('PartialGraphContext.getChallengeProof (rigor)', () => {
|
||||
rigor.crucible([
|
||||
rigor.invariant(
|
||||
'oracle-matches-brute-force',
|
||||
({ error, errorMessage }) => !error && !errorMessage
|
||||
({ actual }) => actual !== undefined
|
||||
)
|
||||
])
|
||||
).run({ seed: 'challenge-proof-oracle', effort: 1500 , artifacts: { dir: '', persist: 'never' }});
|
||||
@@ -150,7 +150,7 @@ describe('PartialGraphContext.getChallengeProof (rigor)', () => {
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('no-expired', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('no-expired', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'challenge-proof-expired', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -225,7 +225,7 @@ describe('PartialGraphContext.getChallengeProof (rigor)', () => {
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('most-recent', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('most-recent', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'challenge-proof-most-recent', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -281,7 +281,7 @@ describe('PartialGraphContext.getChallengeProof (rigor)', () => {
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('within-window', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('within-window', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'challenge-proof-within-ms', effort: 1500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ describe('ChallengeRule._resolveSubjectKey (rigor)', () => {
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('subjectKey-wins', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('subjectKey-wins', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'challenge-rule-subject-key-wins', effort: 1000 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -116,7 +116,7 @@ describe('ChallengeRule._resolveSubjectKey (rigor)', () => {
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('subject-mapping', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('subject-mapping', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'challenge-rule-subject-mapping', effort: 1500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -197,7 +197,7 @@ describe('ChallengeRule._resolveWithinMs (rigor)', () => {
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('within-units', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('within-units', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'challenge-rule-within-units', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -260,7 +260,7 @@ describe('ChallengeRule._resolveWithinMs (rigor)', () => {
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('within-priority', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('within-priority', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'challenge-rule-within-priority', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -293,7 +293,7 @@ describe('ChallengeRule._resolveWithinMs (rigor)', () => {
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('null-when-absent', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('null-when-absent', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'challenge-rule-null-when-absent', effort: 500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -333,7 +333,7 @@ describe('ChallengeRule._buildRequirement (rigor)', () => {
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('buildRequirement', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('buildRequirement', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'challenge-rule-build-requirement', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ describe('check/explain agreement (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('check-explain-agree', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('check-explain-agree', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 500, seed: 'explain-agreement' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -148,7 +148,7 @@ describe('check/explain agreement (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('used-facts-consistent', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('used-facts-consistent', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 600, seed: 'explain-used-facts' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -196,7 +196,7 @@ describe('check/explain agreement (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('remediation-consistent', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('remediation-consistent', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 400, seed: 'explain-remediation' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ describe('Relational comparator full-path parity (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('comparator-full-path', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('comparator-full-path', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 1200, seed: 'comparator-full-path-parity' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -162,7 +162,7 @@ describe('Relational comparator full-path parity (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('comparator-aggregation', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('comparator-aggregation', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 500, seed: 'comparator-aggregation' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -154,10 +154,10 @@ describe('Complex-graph batch/cache crucibles (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('batch-sequential-parity', ({ error, errorMessage }) => !error || !String(errorMessage).startsWith('[parity]')),
|
||||
rigor.invariant('batch-mutation', ({ error, errorMessage }) => !error || !String(errorMessage).startsWith('[mutation]')),
|
||||
rigor.invariant('cache-interaction', ({ error, errorMessage }) => !error || !String(errorMessage).startsWith('[cache]')),
|
||||
rigor.invariant('fixture-size', ({ error, errorMessage }) => !error || !String(errorMessage).startsWith('[fixture]'))
|
||||
rigor.invariant('batch-sequential-parity', ({ actual }) => actual !== undefined),
|
||||
rigor.invariant('batch-mutation', ({ actual }) => actual !== undefined),
|
||||
rigor.invariant('cache-interaction', ({ actual }) => actual !== undefined),
|
||||
rigor.invariant('fixture-size', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 150, seed: 'complex-graph-batch-crucible', artifacts: { dir: '', persist: 'never' } });
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ describe('Complex-graph crucibles (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('parity', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('parity', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 300, seed: 'complex-graph-parity', artifacts: { dir: '', persist: 'never' } });
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ describe('Complex-graph mutation crucibles (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('mutation-freshness', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('mutation-freshness', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 300, seed: 'complex-graph-mutation-freshness', artifacts: { dir: '', persist: 'never' } });
|
||||
|
||||
|
||||
@@ -145,10 +145,10 @@ describe('Complex-graph overlay crucibles (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('overlay-surfaces', ({ error, errorMessage }) => !error || !String(errorMessage).startsWith('[surfaces]')),
|
||||
rigor.invariant('persistent-wins', ({ error, errorMessage }) => !error || !String(errorMessage).startsWith('[wins]')),
|
||||
rigor.invariant('overlay-binary-parity', ({ error, errorMessage }) => !error || !String(errorMessage).startsWith('[binary]')),
|
||||
rigor.invariant('overlay-on-complex', ({ error, errorMessage }) => !error || !String(errorMessage).startsWith('[complex]'))
|
||||
rigor.invariant('overlay-surfaces', ({ actual }) => actual !== undefined),
|
||||
rigor.invariant('persistent-wins', ({ actual }) => actual !== undefined),
|
||||
rigor.invariant('overlay-binary-parity', ({ actual }) => actual !== undefined),
|
||||
rigor.invariant('overlay-on-complex', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 200, seed: 'complex-graph-overlay-crucible', artifacts: { dir: '', persist: 'never' } });
|
||||
|
||||
|
||||
@@ -148,9 +148,9 @@ describe('Complex-graph PLTC reachability crucibles (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('verdict-parity', ({ error, errorMessage }) => !error || !String(errorMessage).startsWith('[verdict]')),
|
||||
rigor.invariant('fast-fail-soundness', ({ error, errorMessage }) => !error || !String(errorMessage).startsWith('[soundness]')),
|
||||
rigor.invariant('null-defer-contract', ({ error, errorMessage }) => !error || !String(errorMessage).startsWith('[vacuity]'))
|
||||
rigor.invariant('verdict-parity', ({ actual }) => actual !== undefined),
|
||||
rigor.invariant('fast-fail-soundness', ({ actual }) => actual !== undefined),
|
||||
rigor.invariant('null-defer-contract', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 200, seed: 'complex-graph-reachability-crucible', artifacts: { dir: '', persist: 'never' } });
|
||||
|
||||
|
||||
@@ -170,9 +170,9 @@ describe('Complex-graph value-TTL crucibles (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('freshness-parity', ({ error, errorMessage }) => !error || !String(errorMessage).startsWith('[freshness]')),
|
||||
rigor.invariant('mutation-with-time', ({ error, errorMessage }) => !error || !String(errorMessage).startsWith('[mutation]')),
|
||||
rigor.invariant('snapshot-preserves-ttl', ({ error, errorMessage }) => !error || !String(errorMessage).startsWith('[snapshot]'))
|
||||
rigor.invariant('freshness-parity', ({ actual }) => actual !== undefined),
|
||||
rigor.invariant('mutation-with-time', ({ actual }) => actual !== undefined),
|
||||
rigor.invariant('snapshot-preserves-ttl', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 250, seed: 'complex-graph-ttl-crucible', artifacts: { dir: '', persist: 'never' } });
|
||||
|
||||
|
||||
@@ -125,10 +125,15 @@ describe('Complex-graph value/comparator crucibles (rigor)', () => {
|
||||
}
|
||||
|
||||
// TTL-EXPIRY-ON-COMPARATOR: both operands past TTL -> deny, mirror agrees.
|
||||
// Use values NOT in VALUE_SET (137 > 30): the engine keeps the OLD
|
||||
// timestamp when a rewrite does not change the value, so a value equal
|
||||
// to whatever the mutation loop last wrote would NOT refresh freshness
|
||||
// and the pre-expiry grant would (correctly) not materialize. Writing
|
||||
// guaranteed-different values forces a timestamp refresh.
|
||||
const kExp = keys[keys.length - 1];
|
||||
engineNow = BASE_NOW + 2_000_000;
|
||||
write(kExp, 'balance', 100);
|
||||
write(kExp, 'price', 50);
|
||||
write(kExp, 'balance', 137);
|
||||
write(kExp, 'price', 30);
|
||||
if (checkAt(kExp).normal !== 1) fail(`[expiry] pre-expiry grant missing (seed=${seed})`);
|
||||
engineNow += TTL + 1;
|
||||
const expired = checkAt(kExp);
|
||||
@@ -149,9 +154,9 @@ describe('Complex-graph value/comparator crucibles (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('comparator-parity', ({ error, errorMessage }) => !error || !String(errorMessage).startsWith('[parity]')),
|
||||
rigor.invariant('value-mutation', ({ error, errorMessage }) => !error || !String(errorMessage).startsWith('[mutation]')),
|
||||
rigor.invariant('ttl-expiry-on-comparator', ({ error, errorMessage }) => !error || !String(errorMessage).startsWith('[expiry]'))
|
||||
rigor.invariant('comparator-parity', ({ actual }) => actual !== undefined),
|
||||
rigor.invariant('value-mutation', ({ actual }) => actual !== undefined),
|
||||
rigor.invariant('ttl-expiry-on-comparator', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 200, seed: 'complex-graph-values-crucible', artifacts: { dir: '', persist: 'never' } });
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ describe('ComputedRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('possibility-passthrough', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('possibility-passthrough', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'computed-rule-possibility-passthrough', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -106,7 +106,7 @@ describe('ComputedRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('reason-default', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('reason-default', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'computed-rule-reason-default', effort: 500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -143,7 +143,7 @@ describe('ComputedRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('reason-passthrough', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('reason-passthrough', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'computed-rule-reason-passthrough', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -186,7 +186,7 @@ describe('ComputedRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('meta-contract', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('meta-contract', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'computed-rule-meta-contract', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -235,7 +235,7 @@ describe('ComputedRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('collected-values-passthrough', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('collected-values-passthrough', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'computed-rule-collected-values', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -271,7 +271,7 @@ describe('ComputedRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('possibility-fallback-zero', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('possibility-fallback-zero', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'computed-rule-possibility-fallback', effort: 500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -309,7 +309,7 @@ describe('ComputedRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('options-passthrough', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('options-passthrough', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'computed-rule-options-passthrough', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -145,7 +145,7 @@ describe('Config redefinition semantics (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('redefine-parity', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('redefine-parity', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 1200, seed: 'config-redefinition-parity' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -192,7 +192,7 @@ describe('Config redefinition semantics (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('redefine-binary-fastpath', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('redefine-binary-fastpath', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 800, seed: 'config-redefinition-binary' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ describe('DirectRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('no-relation-fallback', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('no-relation-fallback', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'direct-rule-no-relation', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -136,7 +136,7 @@ describe('DirectRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('relation-strength-preserved', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('relation-strength-preserved', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'direct-rule-strength', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -184,7 +184,7 @@ describe('DirectRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('reverse-routing', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('reverse-routing', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'direct-rule-reverse', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -234,7 +234,7 @@ describe('DirectRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('fastPath-early-exit', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('fastPath-early-exit', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'direct-rule-fast-path', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -276,7 +276,7 @@ describe('DirectRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('collectValues-disabled', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('collectValues-disabled', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'direct-rule-collect-off', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -330,7 +330,7 @@ describe('DirectRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('collectValues-default', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('collectValues-default', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'direct-rule-collect-on', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -391,7 +391,7 @@ describe('DirectRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('relation-precedence', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('relation-precedence', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'direct-rule-precedence', effort: 1500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -447,7 +447,7 @@ describe('DirectRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('result-shape-stable', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('result-shape-stable', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'direct-rule-shape', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ describe('DSLCompiler → engine rule mapping (rigor)', () => {
|
||||
// signature — the DSL validator rejects undeclared predicates.
|
||||
[rigor.fn('check', check, rigor.args(rigor.gen.oneOf(['owns', 'canReadInner'])))],
|
||||
rigor.crucible([
|
||||
rigor.invariant('direct-emission', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('direct-emission', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'dsl-compiler-direct', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -126,7 +126,7 @@ describe('DSLCompiler → engine rule mapping (rigor)', () => {
|
||||
const report = await rigor.campaign(
|
||||
[rigor.fn('check', check, rigor.args())],
|
||||
rigor.crucible([
|
||||
rigor.invariant('tus-emission', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('tus-emission', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'dsl-compiler-tus', effort: 200 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -158,7 +158,7 @@ describe('DSLCompiler → engine rule mapping (rigor)', () => {
|
||||
const report = await rigor.campaign(
|
||||
[rigor.fn('check', check, rigor.args())],
|
||||
rigor.crucible([
|
||||
rigor.invariant('parent-emission', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('parent-emission', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'dsl-compiler-parent', effort: 200 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -195,7 +195,7 @@ describe('DSLCompiler → engine rule mapping (rigor)', () => {
|
||||
const report = await rigor.campaign(
|
||||
[rigor.fn('check', check, rigor.args())],
|
||||
rigor.crucible([
|
||||
rigor.invariant('chain-emission', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('chain-emission', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'dsl-compiler-chain', effort: 200 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -244,7 +244,7 @@ describe('DSLCompiler → engine rule mapping (rigor)', () => {
|
||||
const report = await rigor.campaign(
|
||||
[rigor.fn('check', check, rigor.args())],
|
||||
rigor.crucible([
|
||||
rigor.invariant('multi_hop-emission', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('multi_hop-emission', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'dsl-compiler-multi-hop', effort: 200 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -286,7 +286,7 @@ describe('DSLCompiler → engine rule mapping (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('logical-emission', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('logical-emission', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'dsl-compiler-logical', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -321,7 +321,7 @@ describe('DSLCompiler → engine rule mapping (rigor)', () => {
|
||||
const report = await rigor.campaign(
|
||||
[rigor.fn('check', check, rigor.args(rigor.gen.enum(['>', '>=', '<', '<=', '==', '!='])))],
|
||||
rigor.crucible([
|
||||
rigor.invariant('relational-comparator-emission', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('relational-comparator-emission', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'dsl-compiler-relational-comparator', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -369,7 +369,7 @@ describe('DSLCompiler → engine rule mapping (rigor)', () => {
|
||||
const report = await rigor.campaign(
|
||||
[rigor.fn('check', check, rigor.args(rigor.gen.int(0, catalog.length - 1)))],
|
||||
rigor.crucible([
|
||||
rigor.invariant('mapping-consistency', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('mapping-consistency', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'dsl-compiler-mapping-consistency', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ describe('DSL-compiled vs hand-written parity under mutation (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('sequence-parity', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('sequence-parity', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 400, seed: 'dsl-mutation-parity' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -179,7 +179,7 @@ describe('DSL-compiled vs hand-written parity under mutation (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('grant-revoke-cycles', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('grant-revoke-cycles', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 300, seed: 'dsl-grant-revoke-cycles' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ function makeOracle() {
|
||||
const rel = opRel !== undefined ? opRel : r.rel;
|
||||
const directKey = key(srcId, rel, dstId);
|
||||
const stored = direct.get(directKey);
|
||||
if (!stored) return;
|
||||
if (!stored) return { skipped: true };
|
||||
direct.delete(directKey);
|
||||
const srcRel = key(stored.src, stored.rel);
|
||||
const dstRel = key(stored.dst, stored.rel);
|
||||
@@ -180,7 +180,7 @@ describe('GraphIndices indexes (rigor)', () => {
|
||||
const report = await rigor.campaign(
|
||||
[rigor.fn('check', check, rigor.args(opGen))],
|
||||
rigor.crucible([
|
||||
rigor.invariant('getDirectRelation-matches-oracle', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('getDirectRelation-matches-oracle', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 1500, seed: 'graph-indices-direct-a' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -243,7 +243,7 @@ describe('GraphIndices indexes (rigor)', () => {
|
||||
const report = await rigor.campaign(
|
||||
[rigor.fn('check', check, rigor.args(opGen))],
|
||||
rigor.crucible([
|
||||
rigor.invariant('getRelationsFromSrc-matches-oracle', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('getRelationsFromSrc-matches-oracle', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 1500, seed: 'graph-indices-direct-b' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -303,7 +303,7 @@ describe('GraphIndices indexes (rigor)', () => {
|
||||
const report = await rigor.campaign(
|
||||
[rigor.fn('check', check, rigor.args(opGen))],
|
||||
rigor.crucible([
|
||||
rigor.invariant('getRelationsToDst-matches-oracle', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('getRelationsToDst-matches-oracle', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 1500, seed: 'graph-indices-direct-c' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -363,7 +363,7 @@ describe('GraphIndices indexes (rigor)', () => {
|
||||
const report = await rigor.campaign(
|
||||
[rigor.fn('check', check, rigor.args(opGen))],
|
||||
rigor.crucible([
|
||||
rigor.invariant('getRelationsByName-matches-oracle', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('getRelationsByName-matches-oracle', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 1500, seed: 'graph-indices-direct-d' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -419,7 +419,7 @@ describe('GraphIndices indexes (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('addRelation-tuple-idempotent', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('addRelation-tuple-idempotent', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 800, seed: 'graph-indices-src' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -457,7 +457,7 @@ describe('GraphIndices indexes (rigor)', () => {
|
||||
const report = await rigor.campaign(
|
||||
[rigor.fn('check', check, rigor.args(relGen))],
|
||||
rigor.crucible([
|
||||
rigor.invariant('addRelation-idempotent', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('addRelation-idempotent', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 800, seed: 'graph-indices-dst' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -500,7 +500,7 @@ describe('GraphIndices indexes (rigor)', () => {
|
||||
const report = await rigor.campaign(
|
||||
[rigor.fn('check', check, rigor.args(relGen))],
|
||||
rigor.crucible([
|
||||
rigor.invariant('clear-empties-indexes', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('clear-empties-indexes', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 800, seed: 'graph-indices-name' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -547,7 +547,7 @@ describe('GraphIndices indexes (rigor)', () => {
|
||||
const report = await rigor.campaign(
|
||||
[rigor.fn('check', check, rigor.args(relGen))],
|
||||
rigor.crucible([
|
||||
rigor.invariant('add-remove-cycle', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('add-remove-cycle', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 800, seed: 'graph-indices-cycle' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ describe('LogicalOperators evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('union-max', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('union-max', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'logical-operators-union-max', effort: 1500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -102,7 +102,7 @@ describe('LogicalOperators evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('intersection-min', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('intersection-min', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'logical-operators-intersection-min', effort: 1500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -136,7 +136,7 @@ describe('LogicalOperators evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('union-mean', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('union-mean', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'logical-operators-union-mean', effort: 1500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -179,7 +179,7 @@ describe('LogicalOperators evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('exclusion', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('exclusion', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'logical-operators-exclusion', effort: 1500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -212,7 +212,7 @@ describe('LogicalOperators evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('possibility-bounded', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('possibility-bounded', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'logical-operators-possibility-bounded', effort: 1500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -249,7 +249,7 @@ describe('LogicalOperators evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('collected-values-concat', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('collected-values-concat', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'logical-operators-collected-values', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -163,7 +163,7 @@ describe('Manager vs index lookup parity (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('lookup-parity', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('lookup-parity', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 1200, seed: 'manager-index-parity' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ describe('MultiHopRule evaluation (rigor)', () => {
|
||||
rigor.args(rigor.gen.string(0, 20)) // may be empty
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('missing-relation', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('missing-relation', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'multi-hop-missing-relation', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -86,7 +86,7 @@ describe('MultiHopRule evaluation (rigor)', () => {
|
||||
rigor.args(rigor.gen.float({ min: 0, max: 1 }))
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('possibility-bounded', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('possibility-bounded', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'multi-hop-possibility-bounded', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -124,7 +124,7 @@ describe('MultiHopRule evaluation (rigor)', () => {
|
||||
rigor.args(rigor.gen.float({ min: 0.01, max: 1 }))
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('single-path-strength', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('single-path-strength', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'multi-hop-single-path', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -159,7 +159,7 @@ describe('MultiHopRule evaluation (rigor)', () => {
|
||||
const report = await rigor.campaign(
|
||||
[rigor.fn('check', check, rigor.args())],
|
||||
rigor.crucible([
|
||||
rigor.invariant('no-path', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('no-path', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'multi-hop-no-path', effort: 500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -206,7 +206,7 @@ describe('MultiHopRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('multi-hop-finds-path', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('multi-hop-finds-path', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'multi-hop-two-hop', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ describe('Multi-object independence (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('multi-object-isolation', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('multi-object-isolation', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 1000, seed: 'multi-object-independence' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -199,7 +199,7 @@ describe('Node lifecycle semantics (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('remove-cascade', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('remove-cascade', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 1000, seed: 'node-lifecycle-remove' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -252,7 +252,7 @@ describe('Node lifecycle semantics (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('node-readd', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('node-readd', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 600, seed: 'node-lifecycle-readd' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ describe('NodeManager index invariants (rigor)', () => {
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('inverse-maps', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('inverse-maps', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'node-manager-inverse-maps', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -131,7 +131,7 @@ describe('NodeManager index invariants (rigor)', () => {
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('addNode-idempotent', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('addNode-idempotent', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'node-manager-add-idempotent', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -184,7 +184,7 @@ describe('NodeManager index invariants (rigor)', () => {
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('size-invariant', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('size-invariant', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'node-manager-size-invariant', effort: 1500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -198,7 +198,7 @@ describe('NodeManager index invariants (rigor)', () => {
|
||||
it('nextNodeId advances monotonically across distinct addNode calls', async () => {
|
||||
async function check(keys, types) {
|
||||
const { manager, arbiter } = makeManager();
|
||||
if (keys.length !== types.length) return; // skip ill-formed
|
||||
if (keys.length !== types.length) return { skipped: true }; // skip ill-formed
|
||||
const ids = [];
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
ids.push(manager.addNode(keys[i], types[i]));
|
||||
@@ -247,7 +247,7 @@ describe('NodeManager index invariants (rigor)', () => {
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('monotonic-ids', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('monotonic-ids', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'node-manager-monotonic-ids', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -293,7 +293,7 @@ describe('NodeManager index invariants (rigor)', () => {
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('removeNode-cleanup', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('removeNode-cleanup', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'node-manager-remove-cleanup', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -333,7 +333,7 @@ describe('NodeManager index invariants (rigor)', () => {
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('clearNodes-resets', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('clearNodes-resets', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'node-manager-clear-resets', effort: 500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -386,7 +386,7 @@ describe('NodeManager index invariants (rigor)', () => {
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('updateNodeData-merges', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('updateNodeData-merges', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'node-manager-update-merge', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ describe('Partial graph overlay precedence (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('persistent-precedence', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('persistent-precedence', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 500, seed: 'overlay-persistent-precedence' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -136,7 +136,7 @@ describe('Partial graph overlay precedence (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('layer-precedence', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('layer-precedence', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 400, seed: 'overlay-layer-precedence' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ describe('ParentRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('no-parents', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('no-parents', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'parent-rule-no-parents', effort: 500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -129,7 +129,7 @@ describe('ParentRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('one-parent-strength', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('one-parent-strength', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'parent-rule-one-parent', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -173,7 +173,7 @@ describe('ParentRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('threshold-cutoff', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('threshold-cutoff', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'parent-rule-threshold', effort: 1500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -210,7 +210,7 @@ describe('ParentRule evaluation (rigor)', () => {
|
||||
const report = await rigor.campaign(
|
||||
[rigor.fn('check', check, rigor.args())],
|
||||
rigor.crucible([
|
||||
rigor.invariant('cycle-detection', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('cycle-detection', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'parent-rule-cycle', effort: 200 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -256,7 +256,7 @@ describe('ParentRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('multi-parent-max', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('multi-parent-max', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'parent-rule-multi-parent', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -295,7 +295,7 @@ describe('ParentRule evaluation (rigor)', () => {
|
||||
const report = await rigor.campaign(
|
||||
[rigor.fn('check', check, rigor.args(rigor.gen.boolean()))],
|
||||
rigor.crucible([
|
||||
rigor.invariant('parent-relation-default', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('parent-relation-default', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'parent-rule-default-relation', effort: 200 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -339,7 +339,7 @@ describe('ParentRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('possibility-bounded', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('possibility-bounded', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'parent-rule-possibility-bounded', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ describe('PLTC reachability parity (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('pltc-active-bypass-parity', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('pltc-active-bypass-parity', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 1500, seed: 'pltc-parity-active-bypass' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -162,7 +162,7 @@ describe('PLTC reachability parity (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('pltc-fastfail-soundness', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('pltc-fastfail-soundness', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 1000, seed: 'pltc-parity-fastfail' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ describe('QualitativeRelationalComparatorRule._getQualitativeScale (rigor)', ()
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('known-scales', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('known-scales', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'qualitative-known-scales', effort: 500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -123,7 +123,7 @@ describe('QualitativeRelationalComparatorRule._getQualitativeScale (rigor)', ()
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('fallback', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('fallback', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'qualitative-fallback', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -160,7 +160,7 @@ describe('QualitativeRelationalComparatorRule._calculateDecayedPossibility (rigo
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('stable-identity', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('stable-identity', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'qualitative-stable-identity', effort: 1500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -195,7 +195,7 @@ describe('QualitativeRelationalComparatorRule._calculateDecayedPossibility (rigo
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('zero-periods', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('zero-periods', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'qualitative-zero-periods', effort: 1500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -236,7 +236,7 @@ describe('QualitativeRelationalComparatorRule._calculateDecayedPossibility (rigo
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('down-monotone', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('down-monotone', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'qualitative-down-monotone', effort: 1500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -276,7 +276,7 @@ describe('QualitativeRelationalComparatorRule._calculateDecayedPossibility (rigo
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('up-monotone', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('up-monotone', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'qualitative-up-monotone', effort: 1500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -312,7 +312,7 @@ describe('QualitativeRelationalComparatorRule._calculateDecayedPossibility (rigo
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('result-in-scale', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('result-in-scale', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'qualitative-result-in-scale', effort: 1500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -349,7 +349,7 @@ describe('QualitativeRelationalComparatorRule._createQualitativeInterval (rigor)
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('lower-le-upper', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('lower-le-upper', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'qualitative-lower-le-upper', effort: 1500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -387,7 +387,7 @@ describe('QualitativeRelationalComparatorRule._createQualitativeInterval (rigor)
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('point-contained', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('point-contained', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'qualitative-point-contained', effort: 1500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -423,7 +423,7 @@ describe('QualitativeRelationalComparatorRule._createQualitativeInterval (rigor)
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('bounds-in-scale', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('bounds-in-scale', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'qualitative-bounds-in-scale', effort: 1500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -457,7 +457,7 @@ describe('QualitativeRelationalComparatorRule._createQualitativeInterval (rigor)
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('zero-blur', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('zero-blur', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'qualitative-zero-blur', effort: 1500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -488,7 +488,7 @@ describe('QualitativeRelationalComparatorRule._calculatePossibilityLossSteps (ri
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('loss-is-zero', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('loss-is-zero', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'qualitative-loss-is-zero', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -527,7 +527,7 @@ describe('QualitativeRelationalComparatorRule._calculatePossibilityLossSteps (ri
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('loss-symmetric', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('loss-symmetric', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'qualitative-loss-symmetric', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ describe('RelationManager.addRelation/removeRelation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('add-and-get', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('add-and-get', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'relation-manager-add-get', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -125,7 +125,7 @@ describe('RelationManager.addRelation/removeRelation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('addRelation-idempotent', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('addRelation-idempotent', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'relation-manager-add-idempotent', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -193,7 +193,7 @@ describe('RelationManager.addRelation/removeRelation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('remove-clears-indexes', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('remove-clears-indexes', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'relation-manager-remove-cleanup', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -282,7 +282,7 @@ describe('RelationManager.addRelation/removeRelation (rigor)', () => {
|
||||
const report = await rigor.campaign(
|
||||
[rigor.fn('check', check, rigor.args(relGen))],
|
||||
rigor.crucible([
|
||||
rigor.invariant('index-coherence', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('index-coherence', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'relation-manager-index-coherence', effort: 1500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -362,7 +362,7 @@ describe('RelationManager.addRelation/removeRelation (rigor)', () => {
|
||||
const report = await rigor.campaign(
|
||||
[rigor.fn('check', check, rigor.args(opGen))],
|
||||
rigor.crucible([
|
||||
rigor.invariant('add-remove-roundtrip', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('add-remove-roundtrip', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'relation-manager-add-remove-roundtrip', effort: 1500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -394,7 +394,7 @@ describe('RelationManager.addRelation/removeRelation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('getDirectRelation-unknown', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('getDirectRelation-unknown', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'relation-manager-unknown-tuple', effort: 500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ describe('RelationalComparatorRouter._isQualitativeRule (rigor)', () => {
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('qualitative-wins', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('qualitative-wins', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'rc-router-qualitative-wins', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -114,7 +114,7 @@ describe('RelationalComparatorRouter._isQualitativeRule (rigor)', () => {
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('scaleName-triggers', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('scaleName-triggers', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'rc-router-scale-name', effort: 500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -154,7 +154,7 @@ describe('RelationalComparatorRouter._isQualitativeRule (rigor)', () => {
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('decay-blur-triggers', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('decay-blur-triggers', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'rc-router-decay-blur', effort: 500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -188,7 +188,7 @@ describe('RelationalComparatorRouter._isQualitativeRule (rigor)', () => {
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('marginSteps-correct', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('marginSteps-correct', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'rc-router-margin-steps', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -229,7 +229,7 @@ describe('RelationalComparatorRouter._isQualitativeRule (rigor)', () => {
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('plain-numeric', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('plain-numeric', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'rc-router-plain-numeric', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -274,7 +274,7 @@ describe('RelationalComparatorRouter._isQualitativeRule (rigor)', () => {
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('getImplType-consistent', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('getImplType-consistent', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'rc-router-get-impl-type', effort: 1500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -320,7 +320,7 @@ describe('RelationalComparatorRouter._isQualitativeRule (rigor)', () => {
|
||||
)
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('hasValidProperty', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('hasValidProperty', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'rc-router-has-valid-property', effort: 1000 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ describe('RelationalComparatorRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('left-gt-right', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('left-gt-right', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'rc-rule-left-gt-right', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -109,7 +109,7 @@ describe('RelationalComparatorRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('left-lt-right', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('left-lt-right', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'rc-rule-left-lt-right', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -144,7 +144,7 @@ describe('RelationalComparatorRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('possibility-bounded', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('possibility-bounded', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'rc-rule-possibility-bounded', effort: 1500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -179,7 +179,7 @@ describe('RelationalComparatorRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('result-shape-stable', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('result-shape-stable', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'rc-rule-shape-stable', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -218,7 +218,7 @@ describe('RelationalComparatorRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('determinism', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('determinism', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'rc-rule-determinism', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ describe('Condensed snapshot round trip (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('snapshot-parity', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('snapshot-parity', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 400, seed: 'snapshot-parity' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -175,7 +175,7 @@ describe('Condensed snapshot round trip (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('readonly-enforced', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('readonly-enforced', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 300, seed: 'snapshot-readonly' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@ describe('Traversal semantics parity (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('chain-direction-parity', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('chain-direction-parity', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 1500, seed: 'traversal-chain-direction' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -262,7 +262,7 @@ describe('Traversal semantics parity (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('ttu-multi-tuple-parity', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('ttu-multi-tuple-parity', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 1200, seed: 'traversal-ttu-multituple' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -338,7 +338,7 @@ describe('Traversal semantics parity (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('update-path-parity', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('update-path-parity', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 600, seed: 'traversal-update-path' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ describe('TupleToUsersetRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('no-tuples', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('no-tuples', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 500, seed: 'ttu-no-tuples', artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -139,7 +139,7 @@ describe('TupleToUsersetRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('min-fusion', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('min-fusion', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 800, seed: 'ttu-min-fusion', artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -192,7 +192,7 @@ describe('TupleToUsersetRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('multi-tuple-max', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('multi-tuple-max', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'ttu-multi-tuple-max', effort: 1500 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -230,7 +230,7 @@ describe('TupleToUsersetRule evaluation (rigor)', () => {
|
||||
)
|
||||
)],
|
||||
rigor.crucible([
|
||||
rigor.invariant('possibility-bounded', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('possibility-bounded', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'ttu-possibility-bounded', effort: 800 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -290,7 +290,7 @@ describe('TupleToUsersetRule evaluation (rigor)', () => {
|
||||
const report = await rigor.campaign(
|
||||
[rigor.fn('check', check, rigor.args())],
|
||||
rigor.crucible([
|
||||
rigor.invariant('early-exit', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('early-exit', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'ttu-early-exit', effort: 200 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -340,7 +340,7 @@ describe('TupleToUsersetRule evaluation (rigor)', () => {
|
||||
const report = await rigor.campaign(
|
||||
[rigor.fn('check', check, rigor.args())],
|
||||
rigor.crucible([
|
||||
rigor.invariant('cycle-detection', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('cycle-detection', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ seed: 'ttu-cycle-detection', effort: 200 , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ describe('Possibilistic validity metadata (rigor)', () => {
|
||||
};
|
||||
}, rigor.args(rigor.gen.array(rigor.gen.oneOf(['finite_sample', 'anytime', 'conformal', 'approximate', 'heuristic', 'unknown']), 1, 4)))],
|
||||
rigor.crucible([
|
||||
rigor.invariant('helper invariants', ({ error, errorMessage, actual }) => !error && !errorMessage && Object.values(actual).every(Boolean))
|
||||
rigor.invariant('helper invariants', ({ actual }) => !!actual && Object.values(actual).every(Boolean))
|
||||
])
|
||||
).run({ effort: 200, seed: 'validity-helpers-2026', artifacts: { dir: '', persist: 'never' } });
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ describe('Authorization state consistency (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('ttu-mutation', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('ttu-mutation', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 400, seed: 'consistency-ttu-mutation' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -152,7 +152,7 @@ describe('Authorization state consistency (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('chain-mutation', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('chain-mutation', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 400, seed: 'consistency-chain-mutation' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -220,7 +220,7 @@ describe('Authorization state consistency (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('config-change', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('config-change', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 400, seed: 'consistency-config-change' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -272,7 +272,7 @@ describe('Authorization state consistency (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('threshold-excludes', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('threshold-excludes', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 400, seed: 'consistency-threshold' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -338,7 +338,7 @@ describe('Authorization state consistency (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('values-complete', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('values-complete', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 400, seed: 'consistency-value-completeness' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -375,7 +375,7 @@ describe('Authorization state consistency (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('deterministic', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('deterministic', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 300, seed: 'consistency-determinism' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ describe('Defeasible logic, DSL parity, aggregation (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('defeasible-semantics', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('defeasible-semantics', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 600, seed: 'defeasible-semantics' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -172,7 +172,7 @@ describe('Defeasible logic, DSL parity, aggregation (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('dsl-parity', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('dsl-parity', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 400, seed: 'dsl-runtime-parity' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -263,7 +263,7 @@ describe('Defeasible logic, DSL parity, aggregation (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('aggregation-complete', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('aggregation-complete', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 500, seed: 'aggregation-completeness' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -310,7 +310,7 @@ describe('Zanzibar rewrite-rule semantics (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('union-max', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('union-max', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 400, seed: 'zanzibar-union' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -354,7 +354,7 @@ describe('Zanzibar rewrite-rule semantics (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('intersection-min', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('intersection-min', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 400, seed: 'zanzibar-intersection' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -397,7 +397,7 @@ describe('Zanzibar rewrite-rule semantics (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('exclusion-blocks', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('exclusion-blocks', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 400, seed: 'zanzibar-exclusion' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -432,7 +432,7 @@ describe('Zanzibar rewrite-rule semantics (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('expand-parity', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('expand-parity', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 800, seed: 'zanzibar-expand-parity' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -488,7 +488,7 @@ describe('Zanzibar rewrite-rule semantics (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('nested-weakest-link', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('nested-weakest-link', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 500, seed: 'zanzibar-nested-chain' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
@@ -544,7 +544,7 @@ describe('Zanzibar rewrite-rule semantics (rigor)', () => {
|
||||
))
|
||||
],
|
||||
rigor.crucible([
|
||||
rigor.invariant('cycle-safe', ({ error, errorMessage }) => !error && !errorMessage)
|
||||
rigor.invariant('cycle-safe', ({ actual }) => actual !== undefined)
|
||||
])
|
||||
).run({ effort: 400, seed: 'zanzibar-cycle-safety' , artifacts: { dir: '', persist: 'never' }});
|
||||
|
||||
|
||||
@@ -81,14 +81,29 @@ describe('ChainRule condition step (rule-based final hop)', () => {
|
||||
assert.equal(res.reason, 'no_chain_path_found');
|
||||
});
|
||||
|
||||
it('rejects a condition step that is not the final step', () => {
|
||||
it('expands an intermediate condition step (rule-based reachability)', () => {
|
||||
arbiter.setRelationConfig('member_of', { type: 'direct' });
|
||||
arbiter.addNode('group:g', 'group');
|
||||
arbiter.addRelation('user:u', 'member_of', 'group:g', { possibility: 1.0 });
|
||||
arbiter.addRelation('group:g', 'can_view', 'doc:d', { possibility: 0.8 });
|
||||
// [condition(member_of unless banned), can_view] — the condition step is
|
||||
// INTERMEDIATE and discovers its reachable nodes (its base relation's
|
||||
// neighbors from the source, filtered by its defeater).
|
||||
const intermediateConfig = {
|
||||
type: 'logical',
|
||||
when: { intersection: { rules: [{ type: 'direct', relation: 'member_of' }], aggregator: 'min' } },
|
||||
unless: { union: { rules: [{ type: 'direct', relation: 'banned', _subjectIsObject: true }], aggregator: 'max' } }
|
||||
};
|
||||
const rule = {
|
||||
type: 'chain',
|
||||
steps: [{ rule: CONDITION_CONFIG, conditionStep: true }, 'can_view']
|
||||
steps: [{ rule: intermediateConfig, conditionStep: true }, 'can_view']
|
||||
};
|
||||
const res = evalRule('user:u', 'doc:d', rule);
|
||||
assert.equal(res.possibility, 0);
|
||||
assert.equal(res.reason, 'condition_step_not_final');
|
||||
// g not banned → reachable via condition → can_view → doc
|
||||
assert.ok(Math.abs(evalRule('user:u', 'doc:d', rule).possibility - 0.8) < 1e-9);
|
||||
// banning g filters it out of the intermediate expansion → no path
|
||||
arbiter.addRelation('group:g', 'banned', 'group:g', { possibility: 1.0 });
|
||||
const denied = evalRule('user:u', 'doc:d', rule);
|
||||
assert.equal(denied.possibility, 0);
|
||||
});
|
||||
|
||||
it('combines across multiple parallel intermediates (max aggregation)', () => {
|
||||
|
||||
Reference in New Issue
Block a user