The prod-gating measurement (complex-query-bench: tuple-to-userset,
chains, defeasible, comparators, OWA, nested fusion, mixed unions over
cold traffic with binary parity) was committed but never ran in CI. The
benchmark job now runs it alongside the possibilistic baseline compare,
uploads the results artifact, and surfaces both in the run summary.
Also: refreshed the committed .rigor-baseline.json (engine unchanged
since the tag; the runner's canonical baseline lives in its artifact
store), and added npm run benchmark:complex-query for local runs.
Prod gating is dominated by rule-based queries, not direct relations.
complex-query-bench.js measures cold-traffic latency (distinct
subject/object per sample, no cache reuse) across seven complex policy
shapes — tuple-to-userset, 2-hop chain, defeasible exclusion, ABAC
relational comparator, OWA union, nested comparator + OWA fusion, and a
mixed 10-rule union — for both evaluation paths, and enforces binary/
normal decision parity on every query.
At 25k and 100k nodes: binary wins every scenario (1.15x-2.0x median
speedup), p99 stays sub-0.05ms, and parity mismatches are zero across
all scenarios. Binary's early exit wins where a strong rule exists; the
earlier direct-relation 'binary slower' observation was a cache-hit
artifact (normal serves repeat queries from the rule result cache,
binary correctly does not, since thresholds are per-call options).
Note: report median, not avg — GC outliers inflate the mean (avg > p95
observed on two rows).
README: purpose-first (possibility not boolean, caller owns evidence/time),
install, verified quick start, concepts (result shape, overlays, temporal
context), API table, development commands, design notes.
benchmark: scripts/benchmark.js on @tenere/benchmark-lib — eight contours
(direct/union/denied/meta/overlay/binary checks, snapshot build/restore),
committed .rigor-baseline.json, exit 1 on high-severity regressions.
CI: benchmark job compares on push (continue-on-error), re-saves baseline
and uploads it as an artifact on tags; publish now depends on benchmark
passing as well as test.
- @tenere/pltc-core switches from a machine-local file: dependency to the
published ^0.6.3 from the Tenere npm registry (the file: path does not
exist in a fresh checkout; lockfile regenerated to the tarball).
- .npmrc routes @tenere and @arbiter scopes alongside @rigor so registry
installs and the eventual publish resolve against the hub.
- package.json gains a files whitelist (src/ only) so tests, benchmarks,
and scratch directories never ship in the tarball.
- .gitea/workflows/ci.yaml: node 22, full suite + rigor campaigns on push/
PR, npm publish on v* tags to the Arbiter org registry.