{"_id":"trilean","_rev":"30-4aa49e123256d0d533c2ac77364cdb9a","name":"trilean","dist-tags":{"latest":"1.6.3"},"versions":{"0.0.0":{"name":"trilean","version":"0.0.0","_id":"trilean@0.0.0","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"dist":{"shasum":"6012eca1f05285321f5bd2060f3942c2235ceed8","tarball":"https://registry.npmjs.org/trilean/-/trilean-0.0.0.tgz","fileCount":1,"integrity":"sha512-B4Fqa1Jw5CLIzO/3Zfdsz6DNN6pb7jSWSTSD1tqW0sFVlUnBq7AYKLVJ0ckimNd8Pj/7YLFVZQH+5iCfGZU8Zg==","signatures":[{"sig":"MEYCIQDgqVLFuhoQtY19WrwfD5IzbbYADTrL4ja3kjaog9GnYwIhAIH7qxKI/C1l/ucAUXX/QGYBg7YaPdnLpl4eTHglQi7I","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":66},"private":false,"_npmUser":{"name":"jmearman","email":"joseph@mearman.co.uk"},"_npmVersion":"11.17.0","directories":{},"_nodeVersion":"26.1.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/trilean_0.0.0_1788160528556_0.6205895624442983","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"trilean","version":"1.0.0","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"license":"MIT","_id":"trilean@1.0.0","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"homepage":"https://github.com/ExaDev/trilean#readme","bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"dist":{"shasum":"67a0363ad6cdb3bbad5359da24abd580d7183a18","tarball":"https://registry.npmjs.org/trilean/-/trilean-1.0.0.tgz","fileCount":46,"integrity":"sha512-NYJC7Qi07u9eSsGW3wuy7kTsXfKqq9CzVz5IL+60Y3PaDBL7D82QjSXxc/JdbuDagvtGjcQrkdCJouO0Vy/+0w==","signatures":[{"sig":"MEUCIQDgrVvZFMeWQpw7wAuN8hWAs4eJvnomcEAYYEnpn4ZdIQIgHGKwU+v7U1e90jDxUuilcR8RuI2w9SesuBfO0aUuvoo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIBGAfJix7FVJofZCaCr1LP+oBZQzmZF9Om5/NyCg+mG/AiBFM+6rlB4yVZw9jOkJO7yeqvmeINOOR39XFp0DaZZbrw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/trilean@1.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":224736},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":{"import":"./dist/index.d.ts","require":"./dist/index.d.cts"},"import":"./dist/index.js","require":"./dist/index.cjs"},"./*":{"types":{"import":"./dist/*.d.ts","require":"./dist/*.d.cts"},"import":"./dist/*.js","require":"./dist/*.cjs"},"./schemas/*.schema.json":"./schemas/*.schema.json"},"gitHead":"f3b4032303d9da5722774b1e510038bc50062dcd","scripts":{"lint":"turbo run _lint","test":"turbo run _test","_lint":"eslint . --fix --cache --max-warnings 0","_test":"vitest run --project unit","build":"turbo run _build","_build":"tsdown && tsx scripts/generate-json-schema.ts","prepare":"husky","release":"semantic-release","typecheck":"turbo run _typecheck","_typecheck":"tsc -p tsconfig.json && tsc -p tsconfig.node.json","test:smoke":"turbo run _test:smoke","_test:smoke":"vitest run --project smoke","test:workers":"turbo run _test:workers","_test:workers":"vitest run --project workers","test:coverage":"turbo run _test:coverage","_test:coverage":"vitest run --project unit --coverage","prepublishOnly":"pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run test:integration && pnpm run build && pnpm run test:smoke && publint && attw --pack","test:integration":"turbo run _test:integration","_test:integration":"vitest run --project integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d7eb3cb5-d633-45a5-ab93-9551baab353f"}},"repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git"},"_npmVersion":"12.0.2","description":"Consumer-agnostic, three-valued predicate/expression evaluation trees over injected resolvers -- no assumptions about consumer data, no I/O of its own.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"packageManager":"pnpm@11.6.0","devDependencies":{"tsx":"^4.23.13","husky":"^9.1.7","turbo":"^2.10.12","eslint":"^10.9.1","tsdown":"^0.22.14","vitest":"^4.1.11","globals":"^17.11.0","publint":"^0.3.24","prettier":"^3.9.6","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^26.4.0","lint-staged":"^17.4.1","canonicalize":"^4.0.0","@commitlint/cli":"^21.2.2","semantic-release":"^25.0.9","typescript-eslint":"^8.68.0","@vitest/coverage-v8":"^4.1.11","@arethetypeswrong/cli":"^0.18.5","@exadev/eslint-config":"^2.10.2","@semantic-release/git":"^11.0.1","@semantic-release/npm":"^13.1.5","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@semantic-release/github":"^12.0.9","@semantic-release/changelog":"^7.0.0","@cloudflare/vitest-pool-workers":"^0.22.0","@commitlint/config-conventional":"^21.2.2","@semantic-release/commit-analyzer":"^13.0.1","@semantic-release/release-notes-generator":"^14.1.1"},"_npmOperationalInternal":{"tmp":"tmp/trilean_1.0.0_1788237797310_0.5046489406560282","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"trilean","version":"1.0.1","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"license":"MIT","_id":"trilean@1.0.1","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"homepage":"https://github.com/ExaDev/trilean#readme","bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"dist":{"shasum":"6e19cee0eb3349b0fd708ab9fd602f86cdb84c5e","tarball":"https://registry.npmjs.org/trilean/-/trilean-1.0.1.tgz","fileCount":46,"integrity":"sha512-Iaj5+H0SzOpo5/GEO4p6W7XGE4auaUZcxEDFs3tZ3SBzY8BYJBCzD98S1o0GKEAxKHjpgVd5t/t2bhcbGZmHlw==","signatures":[{"sig":"MEUCIFZVcrrnkH/SLcAwBAhWhyRM6sOP+hnoZeeEsHbqiPN8AiEA6VPf/3ni+O2H1z/nxMo1yaRPAw/ud5yGa2wkRMImzh4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIDiysTbqMGsoghhNfqxY9bA7HlVBQHrsNtkYAPz2WxSbAiEArS4FGRTsDH+/2Zsma97JI0af8P/DOdorjsJKoKiArp0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/trilean@1.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":225230},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":{"import":"./dist/index.d.ts","require":"./dist/index.d.cts"},"import":"./dist/index.js","require":"./dist/index.cjs"},"./*":{"types":{"import":"./dist/*.d.ts","require":"./dist/*.d.cts"},"import":"./dist/*.js","require":"./dist/*.cjs"},"./schemas/*.schema.json":"./schemas/*.schema.json"},"gitHead":"054655dfe289ace690e992473eea2b1bd3b153c4","scripts":{"lint":"turbo run _lint","test":"turbo run _test","_lint":"eslint . --fix --cache --max-warnings 0","_test":"vitest run --project unit","build":"turbo run _build","_build":"tsdown && tsx scripts/generate-json-schema.ts","prepare":"husky","release":"semantic-release","typecheck":"turbo run _typecheck","_typecheck":"tsc -p tsconfig.json && tsc -p tsconfig.node.json","test:smoke":"turbo run _test:smoke","_test:smoke":"vitest run --project smoke","test:workers":"turbo run _test:workers","_test:workers":"vitest run --project workers","test:coverage":"turbo run _test:coverage","_test:coverage":"vitest run --project unit --coverage","prepublishOnly":"pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run test:integration && pnpm run build && pnpm run test:smoke && publint && attw --pack","test:integration":"turbo run _test:integration","_test:integration":"vitest run --project integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d7eb3cb5-d633-45a5-ab93-9551baab353f"}},"repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git"},"_npmVersion":"12.0.2","description":"Consumer-agnostic, three-valued predicate/expression evaluation trees over injected resolvers -- no assumptions about consumer data, no I/O of its own.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"packageManager":"pnpm@11.6.0","devDependencies":{"tsx":"^4.23.13","husky":"^9.1.7","turbo":"^2.10.12","eslint":"^10.9.1","tsdown":"^0.22.14","vitest":"^4.1.11","globals":"^17.11.0","publint":"^0.3.24","prettier":"^3.9.6","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^26.4.0","lint-staged":"^17.4.1","canonicalize":"^4.0.0","@commitlint/cli":"^21.2.2","semantic-release":"^25.0.9","typescript-eslint":"^8.68.0","@vitest/coverage-v8":"^4.1.11","@arethetypeswrong/cli":"^0.18.5","@exadev/eslint-config":"^2.10.2","@semantic-release/git":"^11.0.1","@semantic-release/npm":"^13.1.5","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@semantic-release/github":"^12.0.9","@semantic-release/changelog":"^7.0.0","@cloudflare/vitest-pool-workers":"^0.22.0","@commitlint/config-conventional":"^21.2.2","@semantic-release/commit-analyzer":"^13.0.1","@semantic-release/release-notes-generator":"^14.1.1"},"_npmOperationalInternal":{"tmp":"tmp/trilean_1.0.1_1788238251805_0.16360260496521417","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"trilean","version":"1.0.2","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"license":"MIT","_id":"trilean@1.0.2","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"homepage":"https://github.com/ExaDev/trilean#readme","bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"dist":{"shasum":"d65333de33ace43cb697d556e0139fdcb83ea678","tarball":"https://registry.npmjs.org/trilean/-/trilean-1.0.2.tgz","fileCount":46,"integrity":"sha512-Mr5Vm8O6oZNNll0Ot8kaHcRVA0C0MAEL9L+tiEDLBW1cM6qsG7HMqfh5u2/4LvPxX7Hrsz6Q9OqZW69Bj0MiWg==","signatures":[{"sig":"MEUCIE9mP0ilvuB1ODe5fG8dXcn2L8IO1WJm9QF+nuKVisA+AiEAmTH/V4vtBKvLSNado+Rui9M0SHOVXkJ8GhJeOCfm7Hc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDzNejdXAaTx47ystnnYNsw8/rhlQwJvFqaqF4eQUaL+QIgYpuZ5Q6/21EpvB4Nn14SXel2/EKBOVZavP0D6ByEasw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/trilean@1.0.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":225230},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":{"import":"./dist/index.d.ts","require":"./dist/index.d.cts"},"import":"./dist/index.js","require":"./dist/index.cjs"},"./*":{"types":{"import":"./dist/*.d.ts","require":"./dist/*.d.cts"},"import":"./dist/*.js","require":"./dist/*.cjs"},"./schemas/*.schema.json":"./schemas/*.schema.json"},"gitHead":"4898a4e5ae7502a4cce52ada094770fbbd7490fe","scripts":{"lint":"turbo run _lint","test":"turbo run _test","_lint":"eslint . --fix --cache --max-warnings 0","_test":"vitest run --project unit","build":"turbo run _build","_build":"tsdown && tsx scripts/generate-json-schema.ts","prepare":"husky","release":"semantic-release","typecheck":"turbo run _typecheck","_typecheck":"tsc -p tsconfig.json && tsc -p tsconfig.node.json","test:smoke":"turbo run _test:smoke","_test:smoke":"vitest run --project smoke","test:workers":"turbo run _test:workers","_test:workers":"vitest run --project workers","test:coverage":"turbo run _test:coverage","_test:coverage":"vitest run --project unit --coverage","prepublishOnly":"pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run test:integration && pnpm run build && pnpm run test:smoke && publint && attw --pack","test:integration":"turbo run _test:integration","_test:integration":"vitest run --project integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d7eb3cb5-d633-45a5-ab93-9551baab353f"}},"repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git"},"_npmVersion":"12.0.2","description":"Consumer-agnostic, three-valued predicate/expression evaluation trees over injected resolvers -- no assumptions about consumer data, no I/O of its own.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"packageManager":"pnpm@11.6.0","devDependencies":{"tsx":"^4.23.13","husky":"^9.1.7","turbo":"^2.10.12","eslint":"^10.9.1","tsdown":"^0.22.14","vitest":"^4.1.11","globals":"^17.11.0","publint":"^0.3.24","prettier":"^3.9.6","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^26.4.0","lint-staged":"^17.4.1","canonicalize":"^4.0.0","@commitlint/cli":"^21.2.2","semantic-release":"^25.0.9","typescript-eslint":"^8.68.0","@vitest/coverage-v8":"^4.1.11","@arethetypeswrong/cli":"^0.18.5","@exadev/eslint-config":"^2.10.2","@semantic-release/git":"^11.0.1","@semantic-release/npm":"^13.1.5","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@semantic-release/github":"^12.0.9","@semantic-release/changelog":"^7.0.0","@cloudflare/vitest-pool-workers":"^0.22.0","@commitlint/config-conventional":"^21.2.2","@semantic-release/commit-analyzer":"^13.0.1","@semantic-release/release-notes-generator":"^14.1.1"},"_npmOperationalInternal":{"tmp":"tmp/trilean_1.0.2_1788238634596_0.9532092390887921","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"trilean","version":"1.0.3","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"license":"MIT","_id":"trilean@1.0.3","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"homepage":"https://github.com/ExaDev/trilean#readme","bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"dist":{"shasum":"7238e3c2979fbd2c7ee6752de3dc6d03c5328630","tarball":"https://registry.npmjs.org/trilean/-/trilean-1.0.3.tgz","fileCount":46,"integrity":"sha512-WPRFgZSo5fIM1qEQFPzP0rd5ShlxO9sAsu1el+xZQ/xJBp5UlcfEShexgB1ioT7f7bkPwDEI+uNgu9GyhazXOQ==","signatures":[{"sig":"MEUCIQCeSn/mHFbI+xlKABQVu7RigLMYzjLSNqfXBt9SDGzvQAIgYTFtU6C2gGeicxp1umvArTaBUuHXiPEFBm8OMfKYJxM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEMCICprQ6PB2NLo7SmX/bh++T4TfLIdT1QA9LKRhdDuKdkJAh8leEFkwDEkV6Ea03WtW8qQCGkLbuqUQTeYbKG6JIj8","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/trilean@1.0.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":224028},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":{"import":"./dist/index.d.ts","require":"./dist/index.d.cts"},"import":"./dist/index.js","require":"./dist/index.cjs"},"./*":{"types":{"import":"./dist/*.d.ts","require":"./dist/*.d.cts"},"import":"./dist/*.js","require":"./dist/*.cjs"},"./schemas/*.schema.json":"./schemas/*.schema.json"},"gitHead":"656529fffb1e99105a9a73bdeddd7629ad466e15","scripts":{"lint":"turbo run _lint","test":"turbo run _test","_lint":"eslint . --fix --cache --max-warnings 0","_test":"vitest run --project unit","build":"turbo run _build","_build":"tsdown && tsx scripts/generate-json-schema.ts","prepare":"husky","release":"semantic-release","typecheck":"turbo run _typecheck","_typecheck":"tsc -p tsconfig.json && tsc -p tsconfig.node.json","test:smoke":"turbo run _test:smoke","_test:smoke":"vitest run --project smoke","test:workers":"turbo run _test:workers","_test:workers":"vitest run --project workers","test:coverage":"turbo run _test:coverage","_test:coverage":"vitest run --project unit --coverage","prepublishOnly":"pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run test:integration && pnpm run build && pnpm run test:smoke && publint && attw --pack","test:integration":"turbo run _test:integration","_test:integration":"vitest run --project integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d7eb3cb5-d633-45a5-ab93-9551baab353f"}},"repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git"},"_npmVersion":"12.0.2","description":"Consumer-agnostic, three-valued predicate/expression evaluation trees over injected resolvers -- no assumptions about consumer data, no I/O of its own.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"packageManager":"pnpm@11.6.0","devDependencies":{"tsx":"^4.23.13","husky":"^9.1.7","turbo":"^2.10.12","eslint":"^10.9.1","tsdown":"^0.22.14","vitest":"^4.1.11","globals":"^17.11.0","publint":"^0.3.24","prettier":"^3.9.6","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^26.4.0","lint-staged":"^17.4.1","canonicalize":"^4.0.0","@commitlint/cli":"^21.2.2","semantic-release":"^25.0.9","typescript-eslint":"^8.68.0","@vitest/coverage-v8":"^4.1.11","@arethetypeswrong/cli":"^0.18.5","@exadev/eslint-config":"^2.10.2","@semantic-release/git":"^11.0.1","@semantic-release/npm":"^13.1.5","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@semantic-release/github":"^12.0.9","@semantic-release/changelog":"^7.0.0","@cloudflare/vitest-pool-workers":"^0.22.0","@commitlint/config-conventional":"^21.2.2","@semantic-release/commit-analyzer":"^13.0.1","@semantic-release/release-notes-generator":"^14.1.1"},"_npmOperationalInternal":{"tmp":"tmp/trilean_1.0.3_1788242530445_0.46161490092302015","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"trilean","version":"1.0.4","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"license":"MIT","_id":"trilean@1.0.4","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"homepage":"https://github.com/ExaDev/trilean#readme","bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"dist":{"shasum":"62e01fb0159dfa919a05d227df9c163498e2e982","tarball":"https://registry.npmjs.org/trilean/-/trilean-1.0.4.tgz","fileCount":46,"integrity":"sha512-1pB7OliAVkyvSvPpKjjT7c2oNLKLmQgt3pffs6O/5Y5XycTOaQ9KEQnxFvenCtw6QBcHK52r1aYvVoRdCQqcSQ==","signatures":[{"sig":"MEUCIQC7+F7EydmilgqyJn/oJKA01NjpDT/by/PNJZYEJ3PZ3gIgIgBTdrvbCU+b030G+WNTpbSCrvMLuBIF2QRaGLr2ydM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIDvXQ1DQlBcP1nYeL/ITislEbtM0f1RleDkpHJgoER58AiBrmr5xVsn/txBto3p7ZEw7tFMGn4b6zdzWuRnOjzYhFg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/trilean@1.0.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":224342},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":{"import":"./dist/index.d.ts","require":"./dist/index.d.cts"},"import":"./dist/index.js","require":"./dist/index.cjs"},"./*":{"types":{"import":"./dist/*.d.ts","require":"./dist/*.d.cts"},"import":"./dist/*.js","require":"./dist/*.cjs"},"./schemas/*.schema.json":"./schemas/*.schema.json"},"gitHead":"7afca5729cdbccc1737fe6779f31665b8a587f60","scripts":{"lint":"turbo run _lint","test":"turbo run _test","_lint":"eslint . --fix --cache --max-warnings 0","_test":"vitest run --project unit","build":"turbo run _build","_build":"tsdown && tsx scripts/generate-json-schema.ts","prepare":"husky","release":"semantic-release","typecheck":"turbo run _typecheck","_typecheck":"tsc -p tsconfig.json && tsc -p tsconfig.node.json","test:smoke":"turbo run _test:smoke","_test:smoke":"vitest run --project smoke","test:workers":"turbo run _test:workers","_test:workers":"vitest run --project workers","test:coverage":"turbo run _test:coverage","_test:coverage":"vitest run --project unit --coverage","prepublishOnly":"pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run test:integration && pnpm run build && pnpm run test:smoke && publint && attw --pack","test:integration":"turbo run _test:integration","_test:integration":"vitest run --project integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d7eb3cb5-d633-45a5-ab93-9551baab353f"}},"repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git"},"_npmVersion":"12.0.2","description":"Consumer-agnostic, three-valued predicate/expression evaluation trees over injected resolvers -- no assumptions about consumer data, no I/O of its own.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"packageManager":"pnpm@11.6.0","devDependencies":{"tsx":"^4.23.13","husky":"^9.1.7","turbo":"^2.10.12","eslint":"^10.9.1","tsdown":"^0.22.14","vitest":"^4.1.11","globals":"^17.11.0","publint":"^0.3.24","prettier":"^3.9.6","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^26.4.0","lint-staged":"^17.4.1","canonicalize":"^4.0.0","@commitlint/cli":"^21.2.2","semantic-release":"^25.0.9","typescript-eslint":"^8.68.0","@vitest/coverage-v8":"^4.1.11","@arethetypeswrong/cli":"^0.18.5","@exadev/eslint-config":"^2.10.2","@semantic-release/git":"^11.0.1","@semantic-release/npm":"^13.1.5","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@semantic-release/github":"^12.0.9","@semantic-release/changelog":"^7.0.0","@cloudflare/vitest-pool-workers":"^0.22.0","@commitlint/config-conventional":"^21.2.2","@semantic-release/commit-analyzer":"^13.0.1","@semantic-release/release-notes-generator":"^14.1.1"},"_npmOperationalInternal":{"tmp":"tmp/trilean_1.0.4_1788242930870_0.4141516623897352","host":"s3://npm-registry-packages-npm-production"}},"1.0.5":{"name":"trilean","version":"1.0.5","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"license":"MIT","_id":"trilean@1.0.5","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"homepage":"https://github.com/ExaDev/trilean#readme","bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"dist":{"shasum":"ef02946c182ac7fda4c2abd39cb1996010d3b6e7","tarball":"https://registry.npmjs.org/trilean/-/trilean-1.0.5.tgz","fileCount":46,"integrity":"sha512-dZi8183wWioXAHhIavTjMflICW6vKLlZ42133SR5dl2k/6s0y7ebT6u9GdneY5XG0u7RR5XhRv/bWUMKlFWH+g==","signatures":[{"sig":"MEYCIQDL080x9ISBeM4d/puPePzScd6ugTRQAzDOp51IGrJxMwIhAL28mAPokDa4IFq7AdtgNsucF0O8Onb2Ll5ILG6WZmW1","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQCZBMfN0vRa76K36oaG18o9Po4Ham8MkgzaEni9D3UABwIgJ/Y7HWjzCpsi1I45UJ6JIos7r59lwyTlk/gHV8U8aNI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/trilean@1.0.5","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":224482},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":{"import":"./dist/index.d.ts","require":"./dist/index.d.cts"},"import":"./dist/index.js","require":"./dist/index.cjs"},"./*":{"types":{"import":"./dist/*.d.ts","require":"./dist/*.d.cts"},"import":"./dist/*.js","require":"./dist/*.cjs"},"./schemas/*.schema.json":"./schemas/*.schema.json"},"gitHead":"59538a6eba8d0492a8fe4f24c88650bf7de8cce9","scripts":{"lint":"turbo run _lint","test":"turbo run _test","_lint":"eslint . --fix --cache --max-warnings 0","_test":"vitest run --project unit","build":"turbo run _build","_build":"tsdown && tsx scripts/generate-json-schema.ts","prepare":"husky","release":"semantic-release","typecheck":"turbo run _typecheck","_typecheck":"tsc -p tsconfig.json && tsc -p tsconfig.node.json","test:smoke":"turbo run _test:smoke","_test:smoke":"vitest run --project smoke","test:workers":"turbo run _test:workers","_test:workers":"vitest run --project workers","test:coverage":"turbo run _test:coverage","_test:coverage":"vitest run --project unit --coverage","prepublishOnly":"pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run test:integration && pnpm run build && pnpm run test:smoke && publint && attw --pack","test:integration":"turbo run _test:integration","_test:integration":"vitest run --project integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d7eb3cb5-d633-45a5-ab93-9551baab353f"}},"repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git"},"_npmVersion":"12.0.2","description":"Consumer-agnostic, three-valued predicate/expression evaluation trees over injected resolvers -- no assumptions about consumer data, no I/O of its own.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"packageManager":"pnpm@11.6.0","devDependencies":{"tsx":"^4.23.13","husky":"^9.1.7","turbo":"^2.10.12","eslint":"^10.9.1","tsdown":"^0.22.14","vitest":"^4.1.11","globals":"^17.11.0","publint":"^0.3.24","prettier":"^3.9.6","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^26.4.0","lint-staged":"^17.4.1","canonicalize":"^4.0.0","@commitlint/cli":"^21.2.2","semantic-release":"^25.0.9","typescript-eslint":"^8.68.0","@vitest/coverage-v8":"^4.1.11","@arethetypeswrong/cli":"^0.18.5","@exadev/eslint-config":"^2.10.2","@semantic-release/git":"^11.0.1","@semantic-release/npm":"^13.1.5","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@semantic-release/github":"^12.0.9","@semantic-release/changelog":"^7.0.0","@cloudflare/vitest-pool-workers":"^0.22.0","@commitlint/config-conventional":"^21.2.2","@semantic-release/commit-analyzer":"^13.0.1","@semantic-release/release-notes-generator":"^14.1.1"},"_npmOperationalInternal":{"tmp":"tmp/trilean_1.0.5_1788244474594_0.5218506493202051","host":"s3://npm-registry-packages-npm-production"}},"1.0.6":{"name":"trilean","version":"1.0.6","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"license":"MIT","_id":"trilean@1.0.6","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"homepage":"https://github.com/ExaDev/trilean#readme","bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"dist":{"shasum":"9b4f3c774125733e5803555e7e66f3603ac584ea","tarball":"https://registry.npmjs.org/trilean/-/trilean-1.0.6.tgz","fileCount":46,"integrity":"sha512-v0Rj/YKk+R1VyUnnfp3bdGiiySTp6S315PtgIhiuCZfEUkI4WTC00MX61sqhf66+v4wv++yntcIYmoYuNNKERQ==","signatures":[{"sig":"MEYCIQDFcsm1bsv7JZqNXhKjIQuYLDrsNM6Dhnz25nd9moCpBQIhAONa72OHhIQuUx26LaCfdufvwNbGY8VpXZd+DGu/n/vN","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCID9Mwqw/Pc+d7OmGXzKyjhqw8aXgCWAUdxiqgZ3xMOAKAiBTb2qz8WP4GAIWLbKdXImUpU+gWKL3RoCKIOS13xY7qw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/trilean@1.0.6","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":224482},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":{"import":"./dist/index.d.ts","require":"./dist/index.d.cts"},"import":"./dist/index.js","require":"./dist/index.cjs"},"./*":{"types":{"import":"./dist/*.d.ts","require":"./dist/*.d.cts"},"import":"./dist/*.js","require":"./dist/*.cjs"},"./schemas/*.schema.json":"./schemas/*.schema.json"},"gitHead":"d20b0cde3b8d63944e861e644cf8b64c1c089acb","scripts":{"lint":"turbo run _lint","test":"turbo run _test","_lint":"eslint . --fix --cache --max-warnings 0","_test":"vitest run --project unit","build":"turbo run _build","_build":"tsdown && tsx scripts/generate-json-schema.ts","prepare":"husky","release":"semantic-release","typecheck":"turbo run _typecheck","_typecheck":"tsc -p tsconfig.json && tsc -p tsconfig.node.json","test:smoke":"turbo run _test:smoke","_test:smoke":"vitest run --project smoke","test:workers":"turbo run _test:workers","_test:workers":"vitest run --project workers","test:coverage":"turbo run _test:coverage","_test:coverage":"vitest run --project unit --coverage","prepublishOnly":"pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run test:integration && pnpm run build && pnpm run test:smoke && publint && attw --pack","test:integration":"turbo run _test:integration","_test:integration":"vitest run --project integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d7eb3cb5-d633-45a5-ab93-9551baab353f"}},"repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git"},"_npmVersion":"12.0.2","description":"Consumer-agnostic, three-valued predicate/expression evaluation trees over injected resolvers -- no assumptions about consumer data, no I/O of its own.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"packageManager":"pnpm@11.6.0","devDependencies":{"tsx":"^4.23.13","husky":"^9.1.7","turbo":"^2.10.12","eslint":"^10.9.1","tsdown":"^0.22.14","vitest":"^4.1.11","globals":"^17.11.0","publint":"^0.3.24","prettier":"^3.9.6","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^26.4.0","lint-staged":"^17.4.1","canonicalize":"^4.0.0","@commitlint/cli":"^21.2.2","semantic-release":"^25.0.9","typescript-eslint":"^8.68.0","@vitest/coverage-v8":"^4.1.11","@arethetypeswrong/cli":"^0.18.5","@exadev/eslint-config":"^2.10.2","@semantic-release/git":"^11.0.1","@semantic-release/npm":"^13.1.5","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@semantic-release/github":"^12.0.9","@semantic-release/changelog":"^7.0.0","@cloudflare/vitest-pool-workers":"^0.22.0","@commitlint/config-conventional":"^21.2.2","@semantic-release/commit-analyzer":"^13.0.1","@semantic-release/release-notes-generator":"^14.1.1"},"_npmOperationalInternal":{"tmp":"tmp/trilean_1.0.6_1788249982912_0.7686644597939931","host":"s3://npm-registry-packages-npm-production"}},"1.0.7":{"name":"trilean","version":"1.0.7","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"license":"MIT","_id":"trilean@1.0.7","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"homepage":"https://github.com/ExaDev/trilean#readme","bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"dist":{"shasum":"7f0a513f5c0fbf966c58eac3444ac8936c30465f","tarball":"https://registry.npmjs.org/trilean/-/trilean-1.0.7.tgz","fileCount":46,"integrity":"sha512-kOif4oQSxjw456sReUqxEKKV+4dKz0uRrHPoPc8Gjg+lxMAuuo7E7xSJt8xE+LxdcE8AI/kVC/MXOBG8MIikVQ==","signatures":[{"sig":"MEUCIQCede8aDxRfN+rzyvgepXKAbAH5qtRh+TAombo0F98XcQIgWek/Ngjj/EMZi4Sd8XCi6VKmjR+DQuvrPVwctsbH49E=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDOhrWsz4enUJZhbNJsw9mwKyG/pRrum70DcW86t95cHQIhAM/+hEoLU+8g5h7LSx1nn0eG280AKakA3gVlOYHvEH4b","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/trilean@1.0.7","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":224543},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":{"import":"./dist/index.d.ts","require":"./dist/index.d.cts"},"import":"./dist/index.js","require":"./dist/index.cjs"},"./*":{"types":{"import":"./dist/*.d.ts","require":"./dist/*.d.cts"},"import":"./dist/*.js","require":"./dist/*.cjs"},"./schemas/*.schema.json":"./schemas/*.schema.json"},"gitHead":"47b5e1ed273e835b6e38156f0f200570c159cf76","scripts":{"lint":"turbo run _lint","test":"turbo run _test","_lint":"eslint . --fix --cache --max-warnings 0","_test":"vitest run --project unit","build":"turbo run _build","_build":"tsdown && tsx scripts/generate-json-schema.ts","prepare":"husky","prepush":"turbo run _prepush","release":"semantic-release","_prepush":"true","typecheck":"turbo run _typecheck","_typecheck":"tsc -p tsconfig.json && tsc -p tsconfig.node.json","test:smoke":"turbo run _test:smoke","_test:smoke":"vitest run --project smoke","test:workers":"turbo run _test:workers","_test:workers":"vitest run --project workers","test:coverage":"turbo run _test:coverage","_test:coverage":"vitest run --project unit --coverage","prepublishOnly":"pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run test:integration && pnpm run build && pnpm run test:smoke && publint && attw --pack","test:integration":"turbo run _test:integration","_test:integration":"vitest run --project integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d7eb3cb5-d633-45a5-ab93-9551baab353f"}},"repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git"},"_npmVersion":"12.0.2","description":"Consumer-agnostic, three-valued predicate/expression evaluation trees over injected resolvers -- no assumptions about consumer data, no I/O of its own.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"packageManager":"pnpm@11.6.0","devDependencies":{"tsx":"^4.23.13","husky":"^9.1.7","turbo":"^2.10.12","eslint":"^10.9.1","tsdown":"^0.22.14","vitest":"^4.1.11","globals":"^17.11.0","publint":"^0.3.24","prettier":"^3.9.6","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^26.4.0","lint-staged":"^17.4.1","canonicalize":"^4.0.0","@commitlint/cli":"^21.2.2","semantic-release":"^25.0.9","typescript-eslint":"^8.68.0","@vitest/coverage-v8":"^4.1.11","@arethetypeswrong/cli":"^0.18.5","@exadev/eslint-config":"^2.10.2","@semantic-release/git":"^11.0.1","@semantic-release/npm":"^13.1.5","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@semantic-release/github":"^12.0.9","@semantic-release/changelog":"^7.0.0","@cloudflare/vitest-pool-workers":"^0.22.0","@commitlint/config-conventional":"^21.2.2","@semantic-release/commit-analyzer":"^13.0.1","@semantic-release/release-notes-generator":"^14.1.1"},"_npmOperationalInternal":{"tmp":"tmp/trilean_1.0.7_1788250701697_0.9851667744043338","host":"s3://npm-registry-packages-npm-production"}},"1.0.8":{"name":"trilean","version":"1.0.8","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"license":"MIT","_id":"trilean@1.0.8","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"homepage":"https://github.com/ExaDev/trilean#readme","bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"dist":{"shasum":"9eddad2a6eb653ac66389c93aea3d5c1465dc7c2","tarball":"https://registry.npmjs.org/trilean/-/trilean-1.0.8.tgz","fileCount":46,"integrity":"sha512-jqObIC1fzq6rKsNdDormxdRwLONP6IWigi4SO+CdkFi3zK3cubH6o3s+4y5sqScIDTd48HW9J+m/TGLCkbgYyw==","signatures":[{"sig":"MEYCIQDCLK3A40BHunoFlMiIE69VVBbOaRM9cT62U8N3p2POrgIhAMoSt82jnLFPABUcIooRFyOeKPM9P+5ap0HSySjcY7cn","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDZc5HHGtXd9cqwed9A/eBtqV7ThOKupvN1qJVsT2AnbQIhANywqlOyPkIuS5gcmAIYobxAIbNbylwz3/1sUN+dG3bx","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/trilean@1.0.8","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":228340},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":{"import":"./dist/index.d.ts","require":"./dist/index.d.cts"},"import":"./dist/index.js","require":"./dist/index.cjs"},"./*":{"types":{"import":"./dist/*.d.ts","require":"./dist/*.d.cts"},"import":"./dist/*.js","require":"./dist/*.cjs"},"./schemas/*.schema.json":"./schemas/*.schema.json"},"gitHead":"7d129a3b41aad110a2a35e1ccdc820ab67f8226a","scripts":{"lint":"turbo run _lint","test":"turbo run _test","_lint":"eslint . --fix --cache --max-warnings 0","_test":"vitest run --project unit","build":"turbo run _build","_build":"tsdown && tsx scripts/generate-json-schema.ts","prepare":"husky","prepush":"turbo run _prepush","release":"semantic-release","_prepush":"true","typecheck":"turbo run _typecheck","_typecheck":"tsc -p tsconfig.json && tsc -p tsconfig.node.json","test:smoke":"turbo run _test:smoke","_test:smoke":"vitest run --project smoke","test:workers":"turbo run _test:workers","_test:workers":"vitest run --project workers","test:coverage":"turbo run _test:coverage","_test:coverage":"vitest run --project unit --coverage","prepublishOnly":"pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run test:integration && pnpm run build && pnpm run test:smoke && publint && attw --pack","test:integration":"turbo run _test:integration","_test:integration":"vitest run --project integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d7eb3cb5-d633-45a5-ab93-9551baab353f"}},"repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git"},"_npmVersion":"12.0.2","description":"Consumer-agnostic, three-valued predicate/expression evaluation trees over injected resolvers -- no assumptions about consumer data, no I/O of its own.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"packageManager":"pnpm@11.6.0","devDependencies":{"tsx":"^4.23.13","husky":"^9.1.7","turbo":"^2.10.12","eslint":"^10.9.1","tsdown":"^0.22.14","vitest":"^4.1.11","globals":"^17.11.0","publint":"^0.3.24","prettier":"^3.9.6","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^26.4.0","lint-staged":"^17.4.1","canonicalize":"^4.0.0","@commitlint/cli":"^21.2.2","semantic-release":"^25.0.9","typescript-eslint":"^8.68.0","@vitest/coverage-v8":"^4.1.11","@arethetypeswrong/cli":"^0.18.5","@exadev/eslint-config":"^2.10.2","@semantic-release/git":"^11.0.1","@semantic-release/npm":"^13.1.5","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@semantic-release/github":"^12.0.9","@semantic-release/changelog":"^7.0.0","@cloudflare/vitest-pool-workers":"^0.22.0","@commitlint/config-conventional":"^21.2.2","@semantic-release/commit-analyzer":"^13.0.1","@semantic-release/release-notes-generator":"^14.1.1"},"_npmOperationalInternal":{"tmp":"tmp/trilean_1.0.8_1788252361177_0.024844029141695145","host":"s3://npm-registry-packages-npm-production"}},"1.0.9":{"name":"trilean","version":"1.0.9","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"license":"MIT","_id":"trilean@1.0.9","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"homepage":"https://github.com/ExaDev/trilean#readme","bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"dist":{"shasum":"767781919c9d490447907b7de8a6d12b6b0e399c","tarball":"https://registry.npmjs.org/trilean/-/trilean-1.0.9.tgz","fileCount":46,"integrity":"sha512-oah08uIUYF3kepSPKk4f37Js4Z0VJs7qdO6b4jCfN5vUciQ55KUcbppXrksmNplTYXMow/Gkm5t+VAAPMUi6Bw==","signatures":[{"sig":"MEUCIQDomel+qVxoYcavCI/2S25FmVcOA+7aBpRfkBuF/UtOywIgbgAF9Dycd67DrxQK6IGHAZ6gfuKhKKlkViulnwkb4G4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQCnqutRZD01gQsBuYc1hmGRoRl3PJk33HtnacUO6q8BeAIhALzXuMJ6tTP4fjwl6Hdswtzk754Egy+rnstsAclMzFgm","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/trilean@1.0.9","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":228437},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":{"import":"./dist/index.d.ts","require":"./dist/index.d.cts"},"import":"./dist/index.js","require":"./dist/index.cjs"},"./*":{"types":{"import":"./dist/*.d.ts","require":"./dist/*.d.cts"},"import":"./dist/*.js","require":"./dist/*.cjs"},"./schemas/*.schema.json":"./schemas/*.schema.json"},"gitHead":"2522ef7e99b1c706e6aa5bf1b643df1ea3362829","scripts":{"lint":"turbo run _lint","test":"turbo run _test","_lint":"eslint . --fix --cache --max-warnings 0","_test":"vitest run --project unit","build":"turbo run _build","_build":"tsdown && tsx scripts/generate-json-schema.ts","prepare":"husky","prepush":"turbo run _prepush","release":"semantic-release","_prepush":"true","typecheck":"turbo run _typecheck","_typecheck":"tsc -p tsconfig.json && tsc -p tsconfig.node.json","test:smoke":"turbo run _test:smoke","_test:smoke":"vitest run --project smoke","test:workers":"turbo run _test:workers","_test:workers":"vitest run --project workers","test:coverage":"turbo run _test:coverage","_test:coverage":"vitest run --project unit --coverage","prepublishOnly":"pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run test:integration && pnpm run build && pnpm run test:smoke && publint && attw --pack","test:integration":"turbo run _test:integration","_test:integration":"vitest run --project integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d7eb3cb5-d633-45a5-ab93-9551baab353f"}},"repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git"},"_npmVersion":"12.0.2","description":"Three-valued predicate and expression evaluation trees, stored as JSON and evaluated against injected resolvers, for business rules, eligibility checks, pricing formulae, and REST API search filters that need to be editable without redeploying.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"packageManager":"pnpm@11.6.0","devDependencies":{"tsx":"^4.23.13","husky":"^9.1.7","turbo":"^2.10.12","eslint":"^10.9.1","tsdown":"^0.22.14","vitest":"^4.1.11","globals":"^17.11.0","publint":"^0.3.24","prettier":"^3.9.6","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^26.4.0","lint-staged":"^17.4.1","canonicalize":"^4.0.0","@commitlint/cli":"^21.2.2","semantic-release":"^25.0.9","typescript-eslint":"^8.68.0","@vitest/coverage-v8":"^4.1.11","@arethetypeswrong/cli":"^0.18.5","@exadev/eslint-config":"^2.10.2","@semantic-release/git":"^11.0.1","@semantic-release/npm":"^13.1.5","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@semantic-release/github":"^12.0.9","@semantic-release/changelog":"^7.0.0","@cloudflare/vitest-pool-workers":"^0.22.0","@commitlint/config-conventional":"^21.2.2","@semantic-release/commit-analyzer":"^13.0.1","@semantic-release/release-notes-generator":"^14.1.1"},"_npmOperationalInternal":{"tmp":"tmp/trilean_1.0.9_1788253242781_0.3762399303342767","host":"s3://npm-registry-packages-npm-production"}},"1.0.10":{"name":"trilean","version":"1.0.10","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"license":"MIT","_id":"trilean@1.0.10","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"homepage":"https://github.com/ExaDev/trilean#readme","bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"dist":{"shasum":"2c3a3bcb41ec9f6e8e57f392c245417656b2c0d8","tarball":"https://registry.npmjs.org/trilean/-/trilean-1.0.10.tgz","fileCount":46,"integrity":"sha512-kgSIQCtLgg4ANFFRXNJbZNW/TfQI2HGATn6fx6mBEpWdP49fyAfkMMssyz9rL+NyWaotECSgMKVcp/BPcjp7Eg==","signatures":[{"sig":"MEUCIQDzIklj2TnV1MZbVbLxfh3piJsE1KeOXjerAyTpA1XMJwIgKLyTIzhQIfOB830rWM3TOHGiQVM76UY+qKhQAOAKFqU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQCvYKDTRTG6vmfEzjuv+0bPiSqYFCDZsT9V8bwCu0QD6gIhAPvUgM3WVZUK/EgJsBMIx+o2WDuqWtm5FZLx1NeOGDHz","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/trilean@1.0.10","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":228439},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":{"import":"./dist/index.d.ts","require":"./dist/index.d.cts"},"import":"./dist/index.js","require":"./dist/index.cjs"},"./*":{"types":{"import":"./dist/*.d.ts","require":"./dist/*.d.cts"},"import":"./dist/*.js","require":"./dist/*.cjs"},"./schemas/*.schema.json":"./schemas/*.schema.json"},"gitHead":"1b2797e820ce519cc5661224ac49c4397f1949f2","scripts":{"lint":"turbo run _lint","test":"turbo run _test","_lint":"eslint . --fix --cache --max-warnings 0","_test":"vitest run --project unit","build":"turbo run _build","_build":"tsdown && tsx scripts/generate-json-schema.ts","prepare":"husky","prepush":"turbo run _prepush","release":"semantic-release","_prepush":"true","typecheck":"turbo run _typecheck","_typecheck":"tsc -p tsconfig.json && tsc -p tsconfig.node.json","test:smoke":"turbo run _test:smoke","_test:smoke":"vitest run --project smoke","test:workers":"turbo run _test:workers","_test:workers":"vitest run --project workers","test:coverage":"turbo run _test:coverage","_test:coverage":"vitest run --project unit --coverage","prepublishOnly":"pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run test:integration && pnpm run build && pnpm run test:smoke && publint && attw --pack","test:integration":"turbo run _test:integration","_test:integration":"vitest run --project integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d7eb3cb5-d633-45a5-ab93-9551baab353f"}},"repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git"},"_npmVersion":"12.0.2","description":"Three-valued predicate and expression evaluation trees, stored as JSON and evaluated against injected resolvers, for business rules, eligibility checks, pricing formulas, and REST API search filters that need to be editable without redeploying.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"packageManager":"pnpm@11.6.0","devDependencies":{"tsx":"^4.23.13","husky":"^9.1.7","turbo":"^2.10.12","eslint":"^10.9.1","tsdown":"^0.22.14","vitest":"^4.1.11","globals":"^17.11.0","publint":"^0.3.24","prettier":"^3.9.6","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^26.4.0","lint-staged":"^17.4.1","canonicalize":"^4.0.0","@commitlint/cli":"^21.2.2","semantic-release":"^25.0.9","typescript-eslint":"^8.68.0","@vitest/coverage-v8":"^4.1.11","@arethetypeswrong/cli":"^0.18.5","@exadev/eslint-config":"^2.10.2","@semantic-release/git":"^11.0.1","@semantic-release/npm":"^13.1.5","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@semantic-release/github":"^12.0.9","@semantic-release/changelog":"^7.0.0","@cloudflare/vitest-pool-workers":"^0.22.0","@commitlint/config-conventional":"^21.2.2","@semantic-release/commit-analyzer":"^13.0.1","@semantic-release/release-notes-generator":"^14.1.1"},"_npmOperationalInternal":{"tmp":"tmp/trilean_1.0.10_1788253513376_0.7176963264803464","host":"s3://npm-registry-packages-npm-production"}},"1.0.11":{"name":"trilean","version":"1.0.11","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"license":"MIT","_id":"trilean@1.0.11","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"homepage":"https://github.com/ExaDev/trilean#readme","bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"dist":{"shasum":"8c6e6c643748a330d569b6a89dda02d2cc52da5a","tarball":"https://registry.npmjs.org/trilean/-/trilean-1.0.11.tgz","fileCount":46,"integrity":"sha512-4XyKK9EdkTaHVaP+obixToWaJzvWPkMdZaRVo5pivmx0L8SXHi3RqJZrKE+ffHaqLQRexXwOHRdMOUI9DphCaQ==","signatures":[{"sig":"MEQCIBeTWJB7Dtgbvs7NmTbA7O5Ti47Lpqq7RrSS/G2iwa/SAiBPhB2tyIrvKEijcOFLge9hso+jyLL0sbZ2ZG0WQBDE3g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIGlRjSPE1vMR7y9+KeSFeNgvxzR4jm6Ab3Ne+r2EVxqvAiEAksf1iWVc+chg3+0uvGVehlJafJtHZGUiz2tG17zczgA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/trilean@1.0.11","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":228423},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":{"import":"./dist/index.d.ts","require":"./dist/index.d.cts"},"import":"./dist/index.js","require":"./dist/index.cjs"},"./*":{"types":{"import":"./dist/*.d.ts","require":"./dist/*.d.cts"},"import":"./dist/*.js","require":"./dist/*.cjs"},"./schemas/*.schema.json":"./schemas/*.schema.json"},"gitHead":"5395b27ed2384f1e8a0a445a3ae05d86b6528ef3","scripts":{"lint":"turbo run _lint","test":"turbo run _test","_lint":"eslint . --fix --cache --max-warnings 0","_test":"vitest run --project unit","build":"turbo run _build","_build":"tsdown && tsx scripts/generate-json-schema.ts","prepare":"husky","prepush":"turbo run _prepush","release":"semantic-release","_prepush":"true","typecheck":"turbo run _typecheck","_typecheck":"tsc -p tsconfig.json && tsc -p tsconfig.node.json","test:smoke":"turbo run _test:smoke","_test:smoke":"vitest run --project smoke","test:workers":"turbo run _test:workers","_test:workers":"vitest run --project workers","test:coverage":"turbo run _test:coverage","_test:coverage":"vitest run --project unit --coverage","prepublishOnly":"pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run test:integration && pnpm run build && pnpm run test:smoke && publint && attw --pack","test:integration":"turbo run _test:integration","_test:integration":"vitest run --project integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d7eb3cb5-d633-45a5-ab93-9551baab353f"}},"repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git"},"_npmVersion":"12.0.2","description":"Three-valued predicate and expression evaluation trees, stored as JSON and evaluated against injected resolvers, for business rules, eligibility checks, formulas, and REST API search filters that need to be editable without redeploying.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"packageManager":"pnpm@11.6.0","devDependencies":{"tsx":"^4.23.13","husky":"^9.1.7","turbo":"^2.10.12","eslint":"^10.9.1","tsdown":"^0.22.14","vitest":"^4.1.11","globals":"^17.11.0","publint":"^0.3.24","prettier":"^3.9.6","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^26.4.0","lint-staged":"^17.4.1","canonicalize":"^4.0.0","@commitlint/cli":"^21.2.2","semantic-release":"^25.0.9","typescript-eslint":"^8.68.0","@vitest/coverage-v8":"^4.1.11","@arethetypeswrong/cli":"^0.18.5","@exadev/eslint-config":"^2.10.2","@semantic-release/git":"^11.0.1","@semantic-release/npm":"^13.1.5","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@semantic-release/github":"^12.0.9","@semantic-release/changelog":"^7.0.0","@cloudflare/vitest-pool-workers":"^0.22.0","@commitlint/config-conventional":"^21.2.2","@semantic-release/commit-analyzer":"^13.0.1","@semantic-release/release-notes-generator":"^14.1.1"},"_npmOperationalInternal":{"tmp":"tmp/trilean_1.0.11_1788253611478_0.0553585281893092","host":"s3://npm-registry-packages-npm-production"}},"1.0.12":{"name":"trilean","version":"1.0.12","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"license":"MIT","_id":"trilean@1.0.12","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"homepage":"https://github.com/ExaDev/trilean#readme","bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"dist":{"shasum":"faa7caaa1861084b18c9bbf788495f2083a2f7d5","tarball":"https://registry.npmjs.org/trilean/-/trilean-1.0.12.tgz","fileCount":46,"integrity":"sha512-+VNYPV6G04uekv2MMhKp/ZDgiUwOg4qR5uRwXurLO5akWX1syNgFZFKxHpGBz8YshHKwhq8mMFB8dUoB2BpSCQ==","signatures":[{"sig":"MEQCIF2y00b9OiUvin+sZvfK7DFTHn7xEPbFqSsNtwznvyGAAiBOYyj9aiGUu1ISg3qJnSRlahHS2xCEoXL/nuTc2lnAKA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQCNnoTRWKrpgqBLsPgsPX/tIvILUWi5hy0sDOZbe7ajKAIgOUqLFkzjc/EI4qdyBxr0EN4qCtxpvAH5Cb0wet+ga4Q=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/trilean@1.0.12","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":228434},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":{"import":"./dist/index.d.ts","require":"./dist/index.d.cts"},"import":"./dist/index.js","require":"./dist/index.cjs"},"./*":{"types":{"import":"./dist/*.d.ts","require":"./dist/*.d.cts"},"import":"./dist/*.js","require":"./dist/*.cjs"},"./schemas/*.schema.json":"./schemas/*.schema.json"},"gitHead":"140ee6b1b286f22b23f9ba140d23f86006825434","scripts":{"lint":"turbo run _lint","test":"turbo run _test","_lint":"eslint . --fix --cache --max-warnings 0","_test":"vitest run --project unit","build":"turbo run _build","_build":"tsdown && tsx scripts/generate-json-schema.ts","prepare":"husky","prepush":"turbo run _prepush","release":"semantic-release","_prepush":"true","typecheck":"turbo run _typecheck","_typecheck":"tsc -p tsconfig.json && tsc -p tsconfig.node.json","test:smoke":"turbo run _test:smoke","_test:smoke":"vitest run --project smoke","test:workers":"turbo run _test:workers","_test:workers":"vitest run --project workers","test:coverage":"turbo run _test:coverage","_test:coverage":"vitest run --project unit --coverage","prepublishOnly":"pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run test:integration && pnpm run build && pnpm run test:smoke && publint && attw --pack","test:integration":"turbo run _test:integration","_test:integration":"vitest run --project integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d7eb3cb5-d633-45a5-ab93-9551baab353f"}},"repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git"},"_npmVersion":"12.0.2","description":"Three-valued predicate and expression evaluation trees, stored as JSON and evaluated against injected resolvers, for domain logic — business rules, eligibility checks, formulas, search filters, and more — that needs to be data instead of code.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"packageManager":"pnpm@11.6.0","devDependencies":{"tsx":"^4.23.13","husky":"^9.1.7","turbo":"^2.10.12","eslint":"^10.9.1","tsdown":"^0.22.14","vitest":"^4.1.11","globals":"^17.11.0","publint":"^0.3.24","prettier":"^3.9.6","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^26.4.0","lint-staged":"^17.4.1","canonicalize":"^4.0.0","@commitlint/cli":"^21.2.2","semantic-release":"^25.0.9","typescript-eslint":"^8.68.0","@vitest/coverage-v8":"^4.1.11","@arethetypeswrong/cli":"^0.18.5","@exadev/eslint-config":"^2.10.2","@semantic-release/git":"^11.0.1","@semantic-release/npm":"^13.1.5","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@semantic-release/github":"^12.0.9","@semantic-release/changelog":"^7.0.0","@cloudflare/vitest-pool-workers":"^0.22.0","@commitlint/config-conventional":"^21.2.2","@semantic-release/commit-analyzer":"^13.0.1","@semantic-release/release-notes-generator":"^14.1.1"},"_npmOperationalInternal":{"tmp":"tmp/trilean_1.0.12_1788253963224_0.2855691633106687","host":"s3://npm-registry-packages-npm-production"}},"1.0.13":{"name":"trilean","version":"1.0.13","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"license":"MIT","_id":"trilean@1.0.13","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"homepage":"https://github.com/ExaDev/trilean#readme","bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"dist":{"shasum":"0439005f510f118970abee33e97d8808ebd5b220","tarball":"https://registry.npmjs.org/trilean/-/trilean-1.0.13.tgz","fileCount":46,"integrity":"sha512-JSVRiPLon6XmuScJ+3zuwNXwcvbeqquMWfw9D3iOZ9LhCc1NFxEB8kiSKig+MbwzUoAEzo8kT1bJnofkl3isQQ==","signatures":[{"sig":"MEQCIGb8QenQaEvZzcyk2u7Zdn7W1QfQKBBjHhUjRZcBLeUSAiBb/EKFW3SwVFesC3VY7XMFVIMiAWgxJuaYA5SDmSZ21Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIG57sXuJMxqSSCs88Zukqmi9OeLhbnrzYfRQKf7dKkA3AiEA3GDZhol1KjFTpt/Cf5+dy9JPTBX0V3sR+VQ+YwV3o2E=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/trilean@1.0.13","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":238028},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":{"import":"./dist/index.d.ts","require":"./dist/index.d.cts"},"import":"./dist/index.js","require":"./dist/index.cjs"},"./*":{"types":{"import":"./dist/*.d.ts","require":"./dist/*.d.cts"},"import":"./dist/*.js","require":"./dist/*.cjs"},"./schemas/*.schema.json":"./schemas/*.schema.json"},"gitHead":"efcc8e82fbac95c6297c0918afed13db81bcd3d7","scripts":{"lint":"turbo run _lint","test":"turbo run _test","_lint":"eslint . --fix --cache --max-warnings 0","_test":"vitest run --project unit","build":"turbo run _build","_build":"tsdown && tsx scripts/generate-json-schema.ts","prepare":"husky","prepush":"turbo run _prepush","release":"semantic-release","_prepush":"true","typecheck":"turbo run _typecheck","_typecheck":"tsc -p tsconfig.json && tsc -p tsconfig.node.json","test:smoke":"turbo run _test:smoke","_test:smoke":"vitest run --project smoke","test:workers":"turbo run _test:workers","_test:workers":"vitest run --project workers","test:coverage":"turbo run _test:coverage","_test:coverage":"vitest run --project unit --coverage","prepublishOnly":"pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run test:integration && pnpm run build && pnpm run test:smoke && publint && attw --pack","test:integration":"turbo run _test:integration","_test:integration":"vitest run --project integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d7eb3cb5-d633-45a5-ab93-9551baab353f"}},"repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git"},"_npmVersion":"12.0.2","description":"Three-valued predicate and expression evaluation trees, stored as JSON and evaluated against injected resolvers, for domain logic — business rules, eligibility checks, formulas, search filters, and more — that needs to be data instead of code.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"packageManager":"pnpm@11.6.0","devDependencies":{"tsx":"^4.23.13","husky":"^9.1.7","turbo":"^2.10.12","eslint":"^10.9.1","tsdown":"^0.22.14","vitest":"^4.1.11","globals":"^17.11.0","publint":"^0.3.24","prettier":"^3.9.6","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^26.4.0","lint-staged":"^17.4.1","canonicalize":"^4.0.0","@commitlint/cli":"^21.2.2","semantic-release":"^25.0.9","typescript-eslint":"^8.68.0","@vitest/coverage-v8":"^4.1.11","@arethetypeswrong/cli":"^0.18.5","@exadev/eslint-config":"^2.10.2","@semantic-release/git":"^11.0.1","@semantic-release/npm":"^13.1.5","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@semantic-release/github":"^12.0.9","@semantic-release/changelog":"^7.0.0","@cloudflare/vitest-pool-workers":"^0.22.0","@commitlint/config-conventional":"^21.2.2","@semantic-release/commit-analyzer":"^13.0.1","@semantic-release/release-notes-generator":"^14.1.1"},"_npmOperationalInternal":{"tmp":"tmp/trilean_1.0.13_1788259018818_0.7407835926790745","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"trilean","version":"1.1.0","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"license":"MIT","_id":"trilean@1.1.0","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"homepage":"https://github.com/ExaDev/trilean#readme","bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"dist":{"shasum":"1f691b0a3c1fe853e76900a45e29606653c194ac","tarball":"https://registry.npmjs.org/trilean/-/trilean-1.1.0.tgz","fileCount":50,"integrity":"sha512-9Sqkr6cQDMP0wiyi9BPqeYZJUKZ4EHEBp3RsWoDXjIUeYOse20sHj62vzvJ8hT2M5/mfjCk5DYmoyUpcxfqdQA==","signatures":[{"sig":"MEUCIDJ3LIDvBBqZ71nNiHwoNyV+xCBJepHL/m5VArO4W2NZAiEA/80tFstyK6c0n78+GNKOyQiSEyNlhFkJiAZaM7wmMsM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQD3AWpKli9nN4pXALPBn2XYmy3Z/bGKgyyQsbF2BhO6kQIgTqhB9Huz3gvBWf0B+GHM4IyHyvng19I/SuEzDKFdGsg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/trilean@1.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":270841},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":{"import":"./dist/index.d.ts","require":"./dist/index.d.cts"},"import":"./dist/index.js","require":"./dist/index.cjs"},"./*":{"types":{"import":"./dist/*.d.ts","require":"./dist/*.d.cts"},"import":"./dist/*.js","require":"./dist/*.cjs"},"./schemas/*.schema.json":"./schemas/*.schema.json"},"gitHead":"9131f284f632f7ea23ee83dd69f914a8d4f0b4ac","scripts":{"lint":"turbo run _lint","test":"turbo run _test","_lint":"eslint . --fix --cache --max-warnings 0","_test":"vitest run --project unit","build":"turbo run _build","_build":"tsdown && tsx scripts/generate-json-schema.ts","prepare":"husky","prepush":"turbo run _prepush","release":"semantic-release","_prepush":"true","typecheck":"turbo run _typecheck","_typecheck":"tsc -p tsconfig.json && tsc -p tsconfig.node.json","test:smoke":"turbo run _test:smoke","_test:smoke":"vitest run --project smoke","test:workers":"turbo run _test:workers","_test:workers":"vitest run --project workers","test:coverage":"turbo run _test:coverage","_test:coverage":"vitest run --project unit --coverage","prepublishOnly":"pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run test:integration && pnpm run build && pnpm run test:smoke && publint && attw --pack","test:integration":"turbo run _test:integration","_test:integration":"vitest run --project integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d7eb3cb5-d633-45a5-ab93-9551baab353f"}},"repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git"},"_npmVersion":"12.0.2","description":"Three-valued predicate and expression evaluation trees, stored as JSON and evaluated against injected resolvers, for domain logic — business rules, eligibility checks, formulas, search filters, and more — that needs to be data instead of code.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"packageManager":"pnpm@11.6.0","devDependencies":{"tsx":"^4.23.13","husky":"^9.1.7","turbo":"^2.10.12","eslint":"^10.9.1","tsdown":"^0.22.14","vitest":"^4.1.11","globals":"^17.11.0","publint":"^0.3.24","prettier":"^3.9.6","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^26.4.0","lint-staged":"^17.4.1","canonicalize":"^4.0.0","@commitlint/cli":"^21.2.2","semantic-release":"^25.0.9","typescript-eslint":"^8.68.0","@vitest/coverage-v8":"^4.1.11","@arethetypeswrong/cli":"^0.18.5","@exadev/eslint-config":"^2.10.2","@semantic-release/git":"^11.0.1","@semantic-release/npm":"^13.1.5","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@semantic-release/github":"^12.0.9","@semantic-release/changelog":"^7.0.0","@cloudflare/vitest-pool-workers":"^0.22.0","@commitlint/config-conventional":"^21.2.2","@semantic-release/commit-analyzer":"^13.0.1","@semantic-release/release-notes-generator":"^14.1.1"},"_npmOperationalInternal":{"tmp":"tmp/trilean_1.1.0_1788264563336_0.4682441393727679","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"trilean","version":"1.2.0","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"license":"MIT","_id":"trilean@1.2.0","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"homepage":"https://github.com/ExaDev/trilean#readme","bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"dist":{"shasum":"eff4a104b552c27d88b7b91189ed6a23368d7434","tarball":"https://registry.npmjs.org/trilean/-/trilean-1.2.0.tgz","fileCount":54,"integrity":"sha512-e/3hUB/m0Izz+qG9rbY5CR0M8gtYw7II8Cr8ZO4Ui0PhnO4EgEX6jwjaQq3Bv7sYJcT8xyQ35k6DsSHEDragoQ==","signatures":[{"sig":"MEYCIQC7l1LPmCKb5V2f2M/j2ZR9xcD0CPLVvR2PbVbiSB2+hAIhAOjJiZwBlmynSdA4nOk+EaMIJhurqScQueUIKBxNaw7h","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQC2L7+Doz/VRQlUDwvcdzG2QHgqxULKS21ZpTeJ8OK2EQIhAIIjTcx2swv5k1Jds8VGOUIz4UiPSYl6o4JKvcxRPuvA","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/trilean@1.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":319058},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":{"import":"./dist/index.d.ts","require":"./dist/index.d.cts"},"import":"./dist/index.js","require":"./dist/index.cjs"},"./*":{"types":{"import":"./dist/*.d.ts","require":"./dist/*.d.cts"},"import":"./dist/*.js","require":"./dist/*.cjs"},"./schemas/*.schema.json":"./schemas/*.schema.json"},"gitHead":"51d792291e5d048ac80265feaf2d604d096c28a4","scripts":{"lint":"turbo run _lint","test":"turbo run _test","_lint":"eslint . --fix --cache --max-warnings 0","_test":"vitest run --project unit","build":"turbo run _build","_build":"tsdown && tsx scripts/generate-json-schema.ts","prepare":"husky","prepush":"turbo run _prepush","release":"semantic-release","_prepush":"true","typecheck":"turbo run _typecheck","_typecheck":"tsc -p tsconfig.json && tsc -p tsconfig.node.json","test:smoke":"turbo run _test:smoke","_test:smoke":"vitest run --project smoke","test:workers":"turbo run _test:workers","_test:workers":"vitest run --project workers","test:coverage":"turbo run _test:coverage","_test:coverage":"vitest run --project unit --coverage","prepublishOnly":"pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run test:integration && pnpm run build && pnpm run test:smoke && publint && attw --pack","test:integration":"turbo run _test:integration","_test:integration":"vitest run --project integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d7eb3cb5-d633-45a5-ab93-9551baab353f"}},"repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git"},"_npmVersion":"12.0.2","description":"Three-valued predicate and expression evaluation trees, stored as JSON and evaluated against injected resolvers, for domain logic — business rules, eligibility checks, formulas, search filters, and more — that needs to be data instead of code.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"packageManager":"pnpm@11.6.0","devDependencies":{"tsx":"^4.23.13","husky":"^9.1.7","turbo":"^2.10.12","eslint":"^10.9.1","tsdown":"^0.22.14","vitest":"^4.1.11","globals":"^17.11.0","publint":"^0.3.24","prettier":"^3.9.6","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^26.4.0","lint-staged":"^17.4.1","canonicalize":"^4.0.0","@commitlint/cli":"^21.2.2","semantic-release":"^25.0.9","typescript-eslint":"^8.68.0","@vitest/coverage-v8":"^4.1.11","@arethetypeswrong/cli":"^0.18.5","@exadev/eslint-config":"^2.10.2","@semantic-release/git":"^11.0.1","@semantic-release/npm":"^13.1.5","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@semantic-release/github":"^12.0.9","@semantic-release/changelog":"^7.0.0","@cloudflare/vitest-pool-workers":"^0.22.0","@commitlint/config-conventional":"^21.2.2","@semantic-release/commit-analyzer":"^13.0.1","@semantic-release/release-notes-generator":"^14.1.1"},"_npmOperationalInternal":{"tmp":"tmp/trilean_1.2.0_1788277995665_0.8893976261016028","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"trilean","version":"1.3.0","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"license":"MIT","_id":"trilean@1.3.0","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"homepage":"https://github.com/ExaDev/trilean#readme","bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"dist":{"shasum":"225d086959208637b6b1854d4baccd944b910f30","tarball":"https://registry.npmjs.org/trilean/-/trilean-1.3.0.tgz","fileCount":58,"integrity":"sha512-MPvJYgoVfQBVr7fbPde/pfwgenTfsYb+gOGCzeQVb4OyHsDuM1XIDfztBAs+FVvZs0G2GJBfHClSk8QfAgCbbA==","signatures":[{"sig":"MEUCIFkzjOn0QYErHdzHKMcJAk2zHJ/cxVyACPtRTRh6mb23AiEA4kRo1gRBu40N+q2gI5Go8hhOYotF/GUl32Flo532BU8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCICMmvrRtrtHMcBRDN3YIRA4ayqPAwSFYfKtSmy9D0+oKAiEA7SXaNKDN3wOxPug7kYLnBkid3enkVDo602DWkDNFbHU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/trilean@1.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":337337},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":{"import":"./dist/index.d.ts","require":"./dist/index.d.cts"},"import":"./dist/index.js","require":"./dist/index.cjs"},"./*":{"types":{"import":"./dist/*.d.ts","require":"./dist/*.d.cts"},"import":"./dist/*.js","require":"./dist/*.cjs"},"./schemas/*.schema.json":"./schemas/*.schema.json"},"gitHead":"460864cbad70212a7b3db67e265757e68d4a06eb","scripts":{"lint":"turbo run _lint","test":"turbo run _test","_lint":"eslint . --fix --cache --max-warnings 0","_test":"vitest run --project unit","build":"turbo run _build","_build":"tsdown && tsx scripts/generate-json-schema.ts","prepare":"husky","prepush":"turbo run _prepush","release":"semantic-release","_prepush":"true","typecheck":"turbo run _typecheck","_typecheck":"tsc -p tsconfig.json && tsc -p tsconfig.node.json","test:smoke":"turbo run _test:smoke","_test:smoke":"vitest run --project smoke","test:workers":"turbo run _test:workers","_test:workers":"vitest run --project workers","test:coverage":"turbo run _test:coverage","_test:coverage":"vitest run --project unit --coverage","prepublishOnly":"pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run test:integration && pnpm run build && pnpm run test:smoke && publint && attw --pack","test:integration":"turbo run _test:integration","_test:integration":"vitest run --project integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d7eb3cb5-d633-45a5-ab93-9551baab353f"}},"repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git"},"_npmVersion":"12.0.2","description":"Three-valued predicate and expression evaluation trees, stored as JSON and evaluated against injected resolvers, for domain logic — business rules, eligibility checks, formulas, search filters, and more — that needs to be data instead of code.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"packageManager":"pnpm@11.6.0","devDependencies":{"tsx":"^4.23.13","husky":"^9.1.7","turbo":"^2.10.12","eslint":"^10.9.1","tsdown":"^0.22.14","vitest":"^4.1.11","globals":"^17.11.0","publint":"^0.3.24","prettier":"^3.9.6","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^26.4.0","lint-staged":"^17.4.1","canonicalize":"^4.0.0","@commitlint/cli":"^21.2.2","semantic-release":"^25.0.9","typescript-eslint":"^8.68.0","@vitest/coverage-v8":"^4.1.11","@arethetypeswrong/cli":"^0.18.5","@exadev/eslint-config":"^2.10.2","@semantic-release/git":"^11.0.1","@semantic-release/npm":"^13.1.5","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@semantic-release/github":"^12.0.9","@semantic-release/changelog":"^7.0.0","@cloudflare/vitest-pool-workers":"^0.22.0","@commitlint/config-conventional":"^21.2.2","@semantic-release/commit-analyzer":"^13.0.1","@semantic-release/release-notes-generator":"^14.1.1"},"_npmOperationalInternal":{"tmp":"tmp/trilean_1.3.0_1788417835805_0.8317056551861579","host":"s3://npm-registry-packages-npm-production"}},"1.4.0":{"name":"trilean","version":"1.4.0","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"license":"MIT","_id":"trilean@1.4.0","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"homepage":"https://github.com/ExaDev/trilean#readme","bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"dist":{"shasum":"489ee49384ee41038cc513fb395a22abeb3bb9bf","tarball":"https://registry.npmjs.org/trilean/-/trilean-1.4.0.tgz","fileCount":58,"integrity":"sha512-UuwmpxxIIOZVmDlgRD/RnMC7ipuFqOk1tgffa8qWzIE3qVGUofgEy5spquTu5G8XlJ3nul5E7X0mSWimMOma3w==","signatures":[{"sig":"MEUCIHUoueCUIHa/vWmNLhgSfoeeUR1JuNLzEAT7O5kVpOxDAiEAqAILuXzHnaO44FUkEU9ve5kdAgAhGLRjLk+quyXxcps=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIAwkTQMRuJ0Y/Xld/EYuTZN6Adj+Zu8WDiSRQEwE9C8fAiEA31HriFcr1nAeKKgVivPpdeKXbJZu50LCMxZflcMAgmQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/trilean@1.4.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":337337},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":{"import":"./dist/index.d.ts","require":"./dist/index.d.cts"},"import":"./dist/index.js","require":"./dist/index.cjs"},"./*":{"types":{"import":"./dist/*.d.ts","require":"./dist/*.d.cts"},"import":"./dist/*.js","require":"./dist/*.cjs"},"./schemas/*.schema.json":"./schemas/*.schema.json"},"gitHead":"1af094906e6c9ebb5dd70d1debc32dfde286540a","scripts":{"lint":"turbo run _lint","test":"turbo run _test","_lint":"eslint . --fix --cache --max-warnings 0","_test":"vitest run --project unit","build":"turbo run _build","_build":"tsdown && tsx scripts/generate-json-schema.ts","prepare":"husky","prepush":"turbo run _prepush","release":"semantic-release","_prepush":"true","typecheck":"turbo run _typecheck","_typecheck":"tsc -p tsconfig.json && tsc -p tsconfig.node.json","test:smoke":"turbo run _test:smoke","_test:smoke":"vitest run --project smoke","test:workers":"turbo run _test:workers","_test:workers":"vitest run --project workers","test:coverage":"turbo run _test:coverage","_test:coverage":"vitest run --project unit --coverage","prepublishOnly":"pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run test:integration && pnpm run build && pnpm run test:smoke && publint && attw --pack","test:integration":"turbo run _test:integration","_test:integration":"vitest run --project integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d7eb3cb5-d633-45a5-ab93-9551baab353f"}},"repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git"},"_npmVersion":"12.0.2","description":"Three-valued predicate and expression evaluation trees, stored as JSON and evaluated against injected resolvers, for domain logic — business rules, eligibility checks, formulas, search filters, and more — that needs to be data instead of code.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"packageManager":"pnpm@11.6.0","devDependencies":{"tsx":"^4.23.13","husky":"^9.1.7","turbo":"^2.10.12","eslint":"^10.9.1","tsdown":"^0.22.14","vitest":"^4.1.11","globals":"^17.11.0","publint":"^0.3.24","prettier":"^3.9.6","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^26.4.0","lint-staged":"^17.4.1","canonicalize":"^4.0.0","@commitlint/cli":"^21.2.2","semantic-release":"^25.0.9","typescript-eslint":"^8.68.0","@vitest/coverage-v8":"^4.1.11","@arethetypeswrong/cli":"^0.18.5","@exadev/eslint-config":"^2.10.2","@semantic-release/git":"^11.0.1","@semantic-release/npm":"^13.1.5","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@semantic-release/github":"^12.0.9","@semantic-release/changelog":"^7.0.0","@cloudflare/vitest-pool-workers":"^0.22.0","@commitlint/config-conventional":"^21.2.2","@semantic-release/commit-analyzer":"^13.0.1","@semantic-release/release-notes-generator":"^14.1.1"},"_npmOperationalInternal":{"tmp":"tmp/trilean_1.4.0_1788436616946_0.8922070884994062","host":"s3://npm-registry-packages-npm-production"}},"1.4.1":{"name":"trilean","version":"1.4.1","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"license":"MIT","_id":"trilean@1.4.1","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"homepage":"https://github.com/ExaDev/trilean/tree/main/packages/trilean","bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"dist":{"shasum":"85d8e7c887eec06433686e3b7f3b50ae0f2f51f5","tarball":"https://registry.npmjs.org/trilean/-/trilean-1.4.1.tgz","fileCount":58,"integrity":"sha512-yiN3xd1CDt/00g+EG5S/T21cjaXTlkXwlBt7CdDt07f+/KNGvZaf5coo0Pi7jM5itd2vYpDONB1WplV5Agr8Mg==","signatures":[{"sig":"MEQCICCUQbF6iAfxNJ2aX5Irf8WZBITqKDXA88GW5HhxvcI/AiAP3CMUvNRr7mSMVXROCScE6k6UeTk3RyrEUxBh4lNYbw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIBJltj0Kf5f8dtQ/zTfsbimkaXTHxIczxXeCsLEfuXx4AiBT+boZHN0OdPuZY8L5/EpKtovi6OUIlqAvCfc6//v5Zg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/trilean@1.4.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":336873},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":{"import":"./dist/index.d.ts","require":"./dist/index.d.cts"},"import":"./dist/index.js","require":"./dist/index.cjs"},"./*":{"types":{"import":"./dist/*.d.ts","require":"./dist/*.d.cts"},"import":"./dist/*.js","require":"./dist/*.cjs"},"./schemas/*.schema.json":"./schemas/*.schema.json"},"gitHead":"2e9ebbc57916d317bdf614bee00d2333bdf79402","scripts":{"lint":"turbo run _lint","test":"turbo run _test","_lint":"eslint . --fix --cache --max-warnings 0","_test":"vitest run --project unit","build":"turbo run _build","_build":"tsdown && tsx scripts/generate-json-schema.ts","prepush":"turbo run _prepush","_prepush":"true","typecheck":"turbo run _typecheck _typecheck:attw","_typecheck":"tsc -p tsconfig.json && tsc -p tsconfig.node.json","test:smoke":"turbo run _test:smoke","_test:smoke":"vitest run --project smoke","test:workers":"turbo run _test:workers","_test:workers":"vitest run --project workers","test:coverage":"turbo run _test:coverage","_test:coverage":"vitest run --project unit --coverage","prepublishOnly":"pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run test:integration && pnpm run build && pnpm run test:smoke && publint && attw --pack","_typecheck:attw":"attw --pack","test:integration":"turbo run _test:integration","_test:integration":"vitest run --project integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d7eb3cb5-d633-45a5-ab93-9551baab353f"}},"repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git","directory":"packages/trilean"},"_npmVersion":"12.0.2","description":"Three-valued predicate and expression evaluation trees, stored as JSON and evaluated against injected resolvers, for domain logic — business rules, eligibility checks, formulas, search filters, and more — that needs to be data instead of code.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.13","turbo":"^2.10.12","eslint":"^10.9.1","tsdown":"^0.22.14","vitest":"^4.1.11","globals":"^17.11.0","publint":"^0.3.24","prettier":"^3.9.6","typescript":"^6.0.3","@types/node":"^26.4.0","canonicalize":"^4.0.0","typescript-eslint":"^8.68.0","@vitest/coverage-v8":"^4.1.11","@arethetypeswrong/cli":"^0.18.5","@exadev/eslint-config":"^2.10.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@cloudflare/vitest-pool-workers":"^0.22.0"},"_npmOperationalInternal":{"tmp":"tmp/trilean_1.4.1_1788442602528_0.08574340645972822","host":"s3://npm-registry-packages-npm-production"}},"1.5.0":{"name":"trilean","version":"1.5.0","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"license":"MIT","_id":"trilean@1.5.0","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"homepage":"https://github.com/ExaDev/trilean/tree/main/packages/trilean","bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"dist":{"shasum":"b7f181963ef5c8ee65da892e9721efe012177796","tarball":"https://registry.npmjs.org/trilean/-/trilean-1.5.0.tgz","fileCount":58,"integrity":"sha512-UepmFAAJGNLHGruMX5+M1ohnV6yJmYuuNrrTZ5nyEAbjCFbtrQjdjHJ8zmUWrvGJSLEpY3wfzOmOWJT7rhmj7Q==","signatures":[{"sig":"MEYCIQCW+EUMR0i+YJTKC773uBcGtBzYchvPPhMKOFE/rFhstQIhAPMFAOmefZML7WBtxml8vX/vejDLeHplotqR9jlZnZT5","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIHU9NMYdZ8N+uR4eI5v8EqwtP8HyM+fqGuEivaPfORm0AiEAgu6yZzCh3vyO09GGEh6Ic2nVFy3VM40sS3p+sl9sEAc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/trilean@1.5.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":341670},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":{"import":"./dist/index.d.ts","require":"./dist/index.d.cts"},"import":"./dist/index.js","require":"./dist/index.cjs"},"./*":{"types":{"import":"./dist/*.d.ts","require":"./dist/*.d.cts"},"import":"./dist/*.js","require":"./dist/*.cjs"},"./schemas/*.schema.json":"./schemas/*.schema.json"},"gitHead":"ffe7ff619a7b4c3c2b6597fce6052da329169c6b","scripts":{"lint":"turbo run _lint","test":"turbo run _test","_lint":"eslint . --fix --cache --max-warnings 0","_test":"vitest run --project unit","build":"turbo run _build","_build":"tsdown && tsx scripts/generate-json-schema.ts","prepush":"turbo run _prepush","_prepush":"true","typecheck":"turbo run _typecheck _typecheck:attw","_typecheck":"tsc -p tsconfig.json && tsc -p tsconfig.node.json","test:smoke":"turbo run _test:smoke","_test:smoke":"vitest run --project smoke","test:workers":"turbo run _test:workers","_test:workers":"vitest run --project workers","test:coverage":"turbo run _test:coverage","_test:coverage":"vitest run --project unit --coverage","prepublishOnly":"pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run test:integration && pnpm run build && pnpm run test:smoke && publint && attw --pack","_typecheck:attw":"attw --pack","test:integration":"turbo run _test:integration","_test:integration":"vitest run --project integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d7eb3cb5-d633-45a5-ab93-9551baab353f"}},"deprecated":"Uninstallable: published with an unresolved workspace: dependency on trilean-regex. Use trilean@1.6.2 or later.","repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git","directory":"packages/trilean"},"_npmVersion":"12.0.2","description":"Three-valued predicate and expression evaluation trees, stored as JSON and evaluated against injected resolvers, for domain logic — business rules, eligibility checks, formulas, search filters, and more — that needs to be data instead of code.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4","trilean-regex":"workspace:^"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.13","turbo":"^2.10.12","eslint":"^10.9.1","tsdown":"^0.22.14","vitest":"^4.1.11","globals":"^17.11.0","publint":"^0.3.24","prettier":"^3.9.6","typescript":"^6.0.3","@types/node":"^26.4.0","canonicalize":"^4.0.0","typescript-eslint":"^8.68.0","@vitest/coverage-v8":"^4.1.11","@arethetypeswrong/cli":"^0.18.5","@exadev/eslint-config":"^2.10.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@cloudflare/vitest-pool-workers":"^0.22.0"},"_npmOperationalInternal":{"tmp":"tmp/trilean_1.5.0_1788683396449_0.9971839144770698","host":"s3://npm-registry-packages-npm-production"}},"1.5.1":{"name":"trilean","version":"1.5.1","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"license":"MIT","_id":"trilean@1.5.1","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"homepage":"https://github.com/ExaDev/trilean/tree/main/packages/trilean","bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"dist":{"shasum":"8cb24972f837c06bced9dc17d082f0c5037989b8","tarball":"https://registry.npmjs.org/trilean/-/trilean-1.5.1.tgz","fileCount":58,"integrity":"sha512-kKAUqOwrr6NQFH93bQifaBjf5hSNcGUMGPLLjCv5Z3JGJzMcURLHR6NLU1eLCIFfjQ+vKoOh0hI0f3WfkZwvgw==","signatures":[{"sig":"MEUCIAuJdX+45ZEKggVTJdT9t9WgOJkZgmPr4fqDCJO7N5UcAiEA+//wrLNwLSaKSpadP0Ps/VomLSa2L94gl5VgRfkW4gI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQC/LK3McXyrq40/DLbWjr2Nok1u8BKe6X17r27ASME46wIhAITNuxrXZGGg7zgnho8XXCQWHu066ebIalbrcOWUbWut","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/trilean@1.5.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":341707},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":{"import":"./dist/index.d.ts","require":"./dist/index.d.cts"},"import":"./dist/index.js","require":"./dist/index.cjs"},"./*":{"types":{"import":"./dist/*.d.ts","require":"./dist/*.d.cts"},"import":"./dist/*.js","require":"./dist/*.cjs"},"./schemas/*.schema.json":"./schemas/*.schema.json"},"gitHead":"db9917ba73ceaa298808bba335afecfc069f22fc","scripts":{"lint":"turbo run _lint","test":"turbo run _test","_lint":"eslint . --fix --cache --max-warnings 0","_test":"vitest run --project unit","build":"turbo run _build","_build":"tsdown && tsx scripts/generate-json-schema.ts","prepush":"turbo run _prepush","_prepush":"true","typecheck":"turbo run _typecheck _typecheck:attw","_typecheck":"tsc -p tsconfig.json && tsc -p tsconfig.node.json","test:smoke":"turbo run _test:smoke","_test:smoke":"vitest run --project smoke","test:workers":"turbo run _test:workers","_test:workers":"vitest run --project workers","test:coverage":"turbo run _test:coverage","_test:coverage":"vitest run --project unit --coverage","prepublishOnly":"pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run test:integration && pnpm run build && pnpm run test:smoke && publint && attw --pack","_typecheck:attw":"attw --pack","test:integration":"turbo run _test:integration","_test:integration":"vitest run --project integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d7eb3cb5-d633-45a5-ab93-9551baab353f"}},"deprecated":"Uninstallable: published with an unresolved workspace: dependency on trilean-regex. Use trilean@1.6.2 or later.","repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git","directory":"packages/trilean"},"_npmVersion":"12.0.2","description":"Three-valued predicate and expression evaluation trees, stored as JSON and evaluated against injected resolvers, for domain logic — business rules, eligibility checks, formulas, search filters, and more — that needs to be data instead of code.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4","trilean-regex":"workspace:^"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.13","turbo":"^2.10.12","eslint":"^10.9.1","tsdown":"^0.22.14","vitest":"^4.1.11","globals":"^17.11.0","publint":"^0.3.24","prettier":"^3.9.6","typescript":"^6.0.3","@types/node":"^26.4.0","canonicalize":"^4.0.0","typescript-eslint":"^8.68.0","@vitest/coverage-v8":"^4.1.11","@arethetypeswrong/cli":"^0.18.5","@exadev/eslint-config":"^2.10.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@cloudflare/vitest-pool-workers":"^0.22.0"},"_npmOperationalInternal":{"tmp":"tmp/trilean_1.5.1_1788684367747_0.10941073779126742","host":"s3://npm-registry-packages-npm-production"}},"1.6.0":{"name":"trilean","version":"1.6.0","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"license":"MIT","_id":"trilean@1.6.0","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"homepage":"https://github.com/ExaDev/trilean/tree/main/packages/trilean","bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"dist":{"shasum":"fc74b95d432ead04dafa206320fda048d10ccec1","tarball":"https://registry.npmjs.org/trilean/-/trilean-1.6.0.tgz","fileCount":58,"integrity":"sha512-BIOv3E39ZKzeDnU2KBiERb3BseVk3ZWTA/SoC2anrtwBlK8VkGLbhB297aNS5mAripKIVEcadT4I/qWwQpMvUQ==","signatures":[{"sig":"MEUCIQCIKVLfxrONMfsiQgu4luvEUw8m0go2bsYRyahwJgFNWwIgO00Hy811Sfrw+bfTUoU4COy0+GoDY9Y241PDYF2vCY0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDYs7otSC8bckWYWKvykBMHZ/nSpc+3F5c3lM7jZJvzUQIgCspQgfvJW15IIGoE+NFDwWbpp1bCrVRZBMvGjma2tIc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/trilean@1.6.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":352103},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":{"import":"./dist/index.d.ts","require":"./dist/index.d.cts"},"import":"./dist/index.js","require":"./dist/index.cjs"},"./*":{"types":{"import":"./dist/*.d.ts","require":"./dist/*.d.cts"},"import":"./dist/*.js","require":"./dist/*.cjs"},"./schemas/*.schema.json":"./schemas/*.schema.json"},"gitHead":"e05876116e9f1a5b4dc2d5e2f99de37e3a176e58","scripts":{"lint":"turbo run _lint","test":"turbo run _test","_lint":"eslint . --fix --cache --max-warnings 0","_test":"vitest run --project unit","build":"turbo run _build","_build":"tsdown && tsx scripts/generate-json-schema.ts","prepush":"turbo run _prepush","_prepush":"true","typecheck":"turbo run _typecheck _typecheck:attw","_typecheck":"tsc -p tsconfig.json && tsc -p tsconfig.node.json","test:smoke":"turbo run _test:smoke","_test:smoke":"vitest run --project smoke","test:workers":"turbo run _test:workers","_test:workers":"vitest run --project workers","test:coverage":"turbo run _test:coverage","_test:coverage":"vitest run --project unit --coverage","prepublishOnly":"pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run test:integration && pnpm run build && pnpm run test:smoke && publint && attw --pack","_typecheck:attw":"attw --pack","test:integration":"turbo run _test:integration","_test:integration":"vitest run --project integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d7eb3cb5-d633-45a5-ab93-9551baab353f"}},"deprecated":"Uninstallable: published with an unresolved workspace: dependency on trilean-regex. Use trilean@1.6.2 or later.","repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git","directory":"packages/trilean"},"_npmVersion":"12.0.2","description":"Three-valued predicate and expression evaluation trees, stored as JSON and evaluated against injected resolvers, for domain logic — business rules, eligibility checks, formulas, search filters, and more — that needs to be data instead of code.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4","trilean-regex":"workspace:^"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.13","turbo":"^2.10.12","eslint":"^10.9.1","tsdown":"^0.22.14","vitest":"^4.1.11","globals":"^17.11.0","publint":"^0.3.24","prettier":"^3.9.6","typescript":"^6.0.3","@types/node":"^26.4.0","canonicalize":"^4.0.0","typescript-eslint":"^8.68.0","@vitest/coverage-v8":"^4.1.11","@arethetypeswrong/cli":"^0.18.5","@exadev/eslint-config":"^2.10.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@cloudflare/vitest-pool-workers":"^0.22.0"},"_npmOperationalInternal":{"tmp":"tmp/trilean_1.6.0_1789294873137_0.1048381747527809","host":"s3://npm-registry-packages-npm-production"}},"1.6.1":{"name":"trilean","version":"1.6.1","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"license":"MIT","_id":"trilean@1.6.1","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"homepage":"https://github.com/ExaDev/trilean/tree/main/packages/trilean","bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"dist":{"shasum":"ffba452f9e9253a9d0f0f6983a7d46d42d41791a","tarball":"https://registry.npmjs.org/trilean/-/trilean-1.6.1.tgz","fileCount":88,"integrity":"sha512-uJ370l00iRXha57+z1UEZm4VvhSF3bnEvtX65XkrB6z4pKtS2uhH2EJ4BSTukAfJbp9nKxL0h6Tmm4T2eRh3HA==","signatures":[{"sig":"MEQCIEviDadfU3K1i5Qs9FvpM1IavpjnrY67NoReAkz2BxfVAiA3Hz1jZenFz1fx9Ov2hIEEKJyM3yqBTDgt/igOGrhDqA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIEblZhLckd+R6FZjWnKllaUGYMBa05vXImFUTP53UgqfAiAs9HSM43El+fHnhFVlrdyaL4sV65SaFX0gR24/FjaqNw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/trilean@1.6.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1547614},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":{"import":"./dist/index.d.ts","require":"./dist/index.d.cts"},"import":"./dist/index.js","require":"./dist/index.cjs"},"./*":{"types":{"import":"./dist/*.d.ts","require":"./dist/*.d.cts"},"import":"./dist/*.js","require":"./dist/*.cjs"},"./schemas/*.schema.json":"./schemas/*.schema.json"},"gitHead":"766be4ba71b5117ac7f68928f803a883bfbb126c","scripts":{"lint":"turbo run _lint","test":"turbo run _test","_lint":"eslint . --fix --cache --max-warnings 0","_test":"vitest run --project unit","build":"turbo run _build","_build":"tsdown && tsx scripts/generate-json-schema.ts","prepush":"turbo run _prepush","_prepush":"true","typecheck":"turbo run _typecheck _typecheck:attw","_typecheck":"tsc -p tsconfig.json && tsc -p tsconfig.node.json","test:smoke":"turbo run _test:smoke","_test:smoke":"vitest run --project smoke","test:workers":"turbo run _test:workers","_test:workers":"vitest run --project workers","test:coverage":"turbo run _test:coverage","_test:coverage":"vitest run --project unit --coverage","prepublishOnly":"pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run test:integration && pnpm run build && pnpm run test:smoke && publint && attw --pack","_typecheck:attw":"attw --pack","test:integration":"turbo run _test:integration","_test:integration":"vitest run --project integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d7eb3cb5-d633-45a5-ab93-9551baab353f"}},"deprecated":"Uninstallable: published with an unresolved workspace: dependency on trilean-regex. Use trilean@1.6.2 or later.","repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git","directory":"packages/trilean"},"_npmVersion":"12.0.2","description":"Three-valued predicate and expression evaluation trees, stored as JSON and evaluated against injected resolvers, for domain logic — business rules, eligibility checks, formulas, search filters, and more — that needs to be data instead of code.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4","trilean-regex":"workspace:^"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.13","turbo":"^2.10.12","eslint":"^10.9.1","tsdown":"^0.22.14","vitest":"^4.1.11","globals":"^17.11.0","publint":"^0.3.24","prettier":"^3.9.6","typescript":"^6.0.3","@types/node":"^26.4.0","canonicalize":"^4.0.0","typescript-eslint":"^8.68.0","@vitest/coverage-v8":"^4.1.11","@arethetypeswrong/cli":"^0.18.5","@exadev/eslint-config":"2.12.1","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@cloudflare/vitest-pool-workers":"^0.22.0"},"_npmOperationalInternal":{"tmp":"tmp/trilean_1.6.1_1789378403799_0.4860934147361762","host":"s3://npm-registry-packages-npm-production"}},"1.6.2":{"name":"trilean","version":"1.6.2","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"license":"MIT","_id":"trilean@1.6.2","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"homepage":"https://github.com/ExaDev/trilean/tree/main/packages/trilean","bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"dist":{"shasum":"34258484eb38e4676c91f123210bf511db54a468","tarball":"https://registry.npmjs.org/trilean/-/trilean-1.6.2.tgz","fileCount":88,"integrity":"sha512-TvjORUQkIxvMwpJqbKQ3nEbfCPNZ+ljPtxk7GeaTPsUisXFd0xusftPFSol7XhhiK1NqXEcK2ERw93PjJo/A3A==","signatures":[{"sig":"MEUCIQDmXE2nV1wIxXDjIz4M1aPtIFeSA7oU5wXaOmQsvU5ptAIgIZitxIaDRZedGYUgkv7HRHW83Y6mCsAbvPhbnORsLCQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQCh03N9thIoO8uJt0RkBSKmAOMxHwsGmjCPPeOs6+DHwgIgEw20IZx4DOJ8W3tRt99l2YrauaDXcnIxEe+JmNMQmYM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/trilean@1.6.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1547608},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":{"import":"./dist/index.d.ts","require":"./dist/index.d.cts"},"import":"./dist/index.js","require":"./dist/index.cjs"},"./*":{"types":{"import":"./dist/*.d.ts","require":"./dist/*.d.cts"},"import":"./dist/*.js","require":"./dist/*.cjs"},"./schemas/*.schema.json":"./schemas/*.schema.json"},"gitHead":"d993b55340d96d05d3a59d41d2854af38def7d9b","scripts":{"lint":"turbo run _lint","test":"turbo run _test","_lint":"eslint . --fix --cache --max-warnings 0","_test":"vitest run --project unit","build":"turbo run _build","_build":"tsdown && tsx scripts/generate-json-schema.ts","prepush":"turbo run _prepush","_prepush":"true","typecheck":"turbo run _typecheck _typecheck:attw","_typecheck":"tsc -p tsconfig.json && tsc -p tsconfig.node.json","test:smoke":"turbo run _test:smoke","_test:smoke":"vitest run --project smoke","test:workers":"turbo run _test:workers","_test:workers":"vitest run --project workers","test:coverage":"turbo run _test:coverage","_test:coverage":"vitest run --project unit --coverage","prepublishOnly":"pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run test:integration && pnpm run build && pnpm run test:smoke && publint && attw --pack","_typecheck:attw":"attw --pack","test:integration":"turbo run _test:integration","_test:integration":"vitest run --project integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d7eb3cb5-d633-45a5-ab93-9551baab353f"}},"repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git","directory":"packages/trilean"},"_npmVersion":"12.0.2","description":"Three-valued predicate and expression evaluation trees, stored as JSON and evaluated against injected resolvers, for domain logic — business rules, eligibility checks, formulas, search filters, and more — that needs to be data instead of code.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4","trilean-regex":"1.0.2"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.13","turbo":"^2.10.12","eslint":"^10.9.1","tsdown":"^0.22.14","vitest":"^4.1.11","globals":"^17.11.0","publint":"^0.3.24","prettier":"^3.9.6","typescript":"^6.0.3","@types/node":"^26.4.0","canonicalize":"^4.0.0","typescript-eslint":"^8.68.0","@vitest/coverage-v8":"^4.1.11","@arethetypeswrong/cli":"^0.18.5","@exadev/eslint-config":"2.12.1","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@cloudflare/vitest-pool-workers":"^0.22.0"},"_npmOperationalInternal":{"tmp":"tmp/trilean_1.6.2_1789817481409_0.11266782081602122","host":"s3://npm-registry-packages-npm-production"}},"1.6.3":{"_id":"trilean@1.6.3","bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"dist":{"shasum":"a25f69d476793c82e134467a2355aaca32740104","tarball":"https://registry.npmjs.org/trilean/-/trilean-1.6.3.tgz","fileCount":88,"integrity":"sha512-Ly1uveqE4/xDNVzNpumsj5dAOYWcD0R+1zrDZnsvMijOVB5ri4+rfR9BRMoz/fBlhg6KN12iUPMB5M8zhUdhcA==","signatures":[{"sig":"MEUCIDGXW/MecygaSrZhVvmhEq1vgOXip6cU0LiMal2lwKC6AiEA4//ILKbLCYRGAZ3R2Fk+nof/ZRTRZE1j5sorpiHdaLo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCICdzXR2hGKoFnU1/62YpBa/Q9YOxVNDTziLHDqdKTYgmAiBkaCm1Z3ZeXewSw9WJwkj8LEv6rf7TbwHqz9L1b0MOJw=="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/trilean@1.6.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1543945},"main":"./dist/index.cjs","name":"trilean","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":{"import":"./dist/index.d.ts","require":"./dist/index.d.cts"},"import":"./dist/index.js","require":"./dist/index.cjs"},"./*":{"types":{"import":"./dist/*.d.ts","require":"./dist/*.d.cts"},"import":"./dist/*.js","require":"./dist/*.cjs"},"./schemas/*.schema.json":"./schemas/*.schema.json"},"gitHead":"92cfacc635c8c68e610acdabc84a399502e6bfe9","license":"MIT","scripts":{"lint":"turbo run _lint","test":"turbo run _test","_lint":"eslint . --fix --cache --max-warnings 0","_test":"vitest run --project unit","build":"turbo run _build","_build":"tsdown && tsx scripts/generate-json-schema.ts","prepush":"turbo run _prepush","_prepush":"true","typecheck":"turbo run _typecheck _typecheck:attw","_typecheck":"tsc -p tsconfig.json && tsc -p tsconfig.node.json","test:smoke":"turbo run _test:smoke","_test:smoke":"vitest run --project smoke","test:workers":"turbo run _test:workers","_test:workers":"vitest run --project workers","test:coverage":"turbo run _test:coverage","_test:coverage":"vitest run --project unit --coverage","prepublishOnly":"pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run test:integration && pnpm run build && pnpm run test:smoke && publint && attw --pack","_typecheck:attw":"attw --pack","test:integration":"turbo run _test:integration","_test:integration":"vitest run --project integration"},"version":"1.6.3","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d7eb3cb5-d633-45a5-ab93-9551baab353f"}},"homepage":"https://github.com/ExaDev/trilean/tree/main/packages/trilean","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git","directory":"packages/trilean"},"_npmVersion":"12.0.2","description":"Three-valued predicate and expression evaluation trees, stored as JSON and evaluated against injected resolvers, for domain logic — business rules, eligibility checks, formulas, search filters, and more — that needs to be data instead of code.","directories":{},"maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4","trilean-regex":"1.0.3"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.13","turbo":"^2.10.12","eslint":"^10.9.1","tsdown":"^0.23.0","vitest":"^4.1.11","globals":"^17.11.0","publint":"^0.3.24","prettier":"^3.9.6","typescript":"^6.0.3","@types/node":"^26.4.0","canonicalize":"^4.0.0","typescript-eslint":"^8.68.0","@vitest/coverage-v8":"^4.1.11","@arethetypeswrong/cli":"^0.18.5","@exadev/eslint-config":"2.12.1","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@cloudflare/vitest-pool-workers":"^0.22.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/trilean_1.6.3_1789833854988_0.7153180409444317"}}},"time":{"created":"2026-08-31T07:15:28.478Z","modified":"2026-09-19T16:04:15.501Z","0.0.0":"2026-08-31T07:15:28.691Z","1.0.0":"2026-09-01T04:43:17.431Z","1.0.1":"2026-09-01T04:50:51.890Z","1.0.2":"2026-09-01T04:57:14.676Z","1.0.3":"2026-09-01T06:02:10.551Z","1.0.4":"2026-09-01T06:08:50.954Z","1.0.5":"2026-09-01T06:34:34.708Z","1.0.6":"2026-09-01T08:06:22.996Z","1.0.7":"2026-09-01T08:18:21.789Z","1.0.8":"2026-09-01T08:46:01.270Z","1.0.9":"2026-09-01T09:00:42.867Z","1.0.10":"2026-09-01T09:05:13.472Z","1.0.11":"2026-09-01T09:06:51.566Z","1.0.12":"2026-09-01T09:12:43.322Z","1.0.13":"2026-09-01T10:36:58.891Z","1.1.0":"2026-09-01T12:09:23.424Z","1.2.0":"2026-09-01T15:53:15.790Z","1.3.0":"2026-09-03T06:43:55.898Z","1.4.0":"2026-09-03T11:56:57.060Z","1.4.1":"2026-09-03T13:36:42.627Z","1.5.0":"2026-09-06T08:29:56.580Z","1.5.1":"2026-09-06T08:46:07.844Z","1.6.0":"2026-09-13T10:21:13.270Z","1.6.1":"2026-09-14T09:33:23.889Z","1.6.2":"2026-09-19T11:31:21.513Z","1.6.3":"2026-09-19T16:04:15.113Z"},"bugs":{"url":"https://github.com/ExaDev/trilean/issues"},"license":"MIT","homepage":"https://github.com/ExaDev/trilean/tree/main/packages/trilean","keywords":["json","predicate","expression","evaluator","three-valued-logic","zod","rules-engine","isomorphic"],"repository":{"url":"git+https://github.com/ExaDev/trilean.git","type":"git","directory":"packages/trilean"},"description":"Three-valued predicate and expression evaluation trees, stored as JSON and evaluated against injected resolvers, for domain logic — business rules, eligibility checks, formulas, search filters, and more — that needs to be data instead of code.","maintainers":[{"name":"jmearman","email":"joseph@mearman.co.uk"}],"readme":"# trilean\n\n[![GitHub](https://img.shields.io/badge/GitHub-181717?logo=github&logoColor=white)](https://github.com/ExaDev/trilean) [![npm](https://img.shields.io/badge/npm-CB3837?logo=npm&logoColor=white)](https://www.npmjs.com/package/trilean) [![Release](https://img.shields.io/github/v/release/ExaDev/trilean?filter=trilean@*&label=release)](https://github.com/ExaDev/trilean/releases?q=trilean%40) [![CI](https://img.shields.io/github/actions/workflow/status/ExaDev/trilean/ci.yml?branch=main)](https://github.com/ExaDev/trilean/actions)\n\n> /ˈtraɪ.li.ən/ (TRY-lee-ən) — rhymes with \"boolean\".\n>\n> \"Tri-\" for [three-valued logic](https://en.wikipedia.org/wiki/Three-valued_logic) — the three possible outcomes of an evaluation (definitely true, definitely false, or indeterminate — see [The evaluation model](#the-evaluation-model)) — \"-lean\" echoing \"boolean\" itself, George Boole's own two-valued logic.\n\nA serialisable (JSON) representation of two related tree structures — a **predicate tree** (truth-valued) and an **expression tree** (value-valued) — together with an evaluator for both. The package is deliberately domain-agnostic: the schema layer never assumes anything about where data actually comes from. Every point of contact with a consumer's real data is an injected, opaque resolver function supplied by whoever embeds the package.\n\nTypical use: representing business rules, eligibility conditions, formulas, or validation logic as data (JSON) that can be stored, transmitted, edited by non-developers via a UI, and evaluated identically wherever it lands — a browser, a server, a batch job — without recompiling anything.\n\n## Getting started\n\n```sh\nnpm install trilean\n# or\npnpm add trilean\n```\n\nThe package ships as dual ESM and CJS builds, is isomorphic (no assumptions about a Node, browser, or Workers runtime — see [Design principles](#design-principles)), and has zero runtime dependencies beyond [Zod](https://zod.dev).\n\n```ts\nimport { evaluatePredicate, type PredicateNode, type Resolvers } from \"trilean\";\n\nconst node: PredicateNode = {\n  kind: \"compare\",\n  op: \"gt\",\n  left: { kind: \"reference\", key: \"age\" },\n  right: { kind: \"numberLiteral\", value: 18 },\n};\n\nconst resolvers: Resolvers = {\n  async resolveValue(key, context) {\n    const record = context as Record<string, unknown>;\n    return key === \"age\" && \"age\" in record\n      ? { found: true, value: { kind: \"number\", value: record.age as number } }\n      : { found: false };\n  },\n  async resolveLookup() {\n    return { found: false };\n  },\n  async resolveCollection() {\n    return [];\n  },\n};\n\nawait evaluatePredicate(node, { age: 21 }, resolvers);\n// => { status: \"definite\", value: true }\n```\n\nSee [Evaluator entry points](#evaluator-entry-points) and [Resolvers](#resolvers) for the full contract, and the [Worked example](#worked-example) for a larger tree combining boolean logic, a formula, and an aggregation.\n\n### A nested filter for a REST API search endpoint\n\nA search endpoint's filter criteria are exactly the kind of thing this package is for: nested boolean logic, stored as JSON, that a client can construct, a non-developer can edit via a UI, and a server evaluates per record without ever hardcoding the filter or redeploying when it changes. There is no query-string DSL to parse and no ORM query-builder to translate into — the request body already is the tree:\n\n```http\nPOST /orders/search HTTP/1.1\nContent-Type: application/json\n\n{\n  \"filter\": {\n    \"kind\": \"and\",\n    \"left\": {\n      \"kind\": \"textCompare\",\n      \"op\": \"equals\",\n      \"left\": { \"kind\": \"reference\", \"key\": \"status\" },\n      \"right\": { \"kind\": \"textLiteral\", \"value\": \"active\" }\n    },\n    \"right\": {\n      \"kind\": \"or\",\n      \"left\": {\n        \"kind\": \"compare\",\n        \"op\": \"gt\",\n        \"left\": { \"kind\": \"reference\", \"key\": \"orderTotal\" },\n        \"right\": { \"kind\": \"numberLiteral\", \"value\": 100 }\n      },\n      \"right\": {\n        \"kind\": \"memberOf\",\n        \"op\": \"in\",\n        \"operand\": { \"kind\": \"reference\", \"key\": \"category\" },\n        \"candidates\": [\n          { \"kind\": \"textLiteral\", \"value\": \"electronics\" },\n          { \"kind\": \"textLiteral\", \"value\": \"books\" }\n        ]\n      }\n    }\n  }\n}\n```\n\n`status equals \"active\" AND (orderTotal > 100 OR category is a preferred one)` — two levels of nesting: an `or` inside the right branch of an `and`. The server parses that body's `filter` field as a `PredicateNode` and evaluates it, unmodified, against each candidate order:\n\n```ts\nimport { evaluatePredicate, type PredicateNode, type Resolvers } from \"trilean\";\n\ninterface Order {\n  status: string;\n  orderTotal: number;\n  category: string;\n}\n\n// The parsed `filter` field from the request body above.\nconst filter: PredicateNode = {\n  kind: \"and\",\n  left: {\n    kind: \"textCompare\",\n    op: \"equals\",\n    left: { kind: \"reference\", key: \"status\" },\n    right: { kind: \"textLiteral\", value: \"active\" },\n  },\n  right: {\n    kind: \"or\",\n    left: {\n      kind: \"compare\",\n      op: \"gt\",\n      left: { kind: \"reference\", key: \"orderTotal\" },\n      right: { kind: \"numberLiteral\", value: 100 },\n    },\n    right: {\n      kind: \"memberOf\",\n      op: \"in\",\n      operand: { kind: \"reference\", key: \"category\" },\n      candidates: [\n        { kind: \"textLiteral\", value: \"electronics\" },\n        { kind: \"textLiteral\", value: \"books\" },\n      ],\n    },\n  },\n};\n\nconst orderResolvers: Resolvers = {\n  async resolveValue(key, context) {\n    const order = context as Order;\n    switch (key) {\n      case \"status\":\n        return { found: true, value: { kind: \"text\", value: order.status } };\n      case \"orderTotal\":\n        return { found: true, value: { kind: \"number\", value: order.orderTotal } };\n      case \"category\":\n        return { found: true, value: { kind: \"text\", value: order.category } };\n      default:\n        return { found: false };\n    }\n  },\n  async resolveLookup() {\n    return { found: false };\n  },\n  async resolveCollection() {\n    return [];\n  },\n};\n\nconst orders: Order[] = [\n  { status: \"active\", orderTotal: 42, category: \"electronics\" },\n  { status: \"active\", orderTotal: 150, category: \"garden\" },\n  { status: \"cancelled\", orderTotal: 200, category: \"electronics\" },\n];\n\nconst results = await Promise.all(\n  orders.map((order) => evaluatePredicate(filter, order, orderResolvers)),\n);\nconst matching = orders.filter((_, i) => results[i]?.status === \"definite\" && results[i]?.value === true);\n// => the first two orders match; the cancelled one doesn't reach the \"or\" at all, since \"and\" absorbs on its left operand's definite false\n```\n\nSee [`and`/`or`](#not-and-or), [`compare`](#compare), [`textCompare`](#textcompare), and [`memberOf`](#memberof) for the full node-kind reference.\n\n## Build, test, and lint\n\n```sh\npnpm install\npnpm build          # tsdown -> dist/, then generates schemas/trilean.schema.json\npnpm test           # unit suite, against src/\npnpm test:integration # multi-kind composition, schema-pipeline, and function-registry/delegate tests, against src/\npnpm test:smoke     # builds first, then checks dist/ in both ESM and CJS plus the generated JSON Schema\npnpm test:workers   # runs the evaluator inside a real Cloudflare Workers isolate\npnpm lint\npnpm typecheck\n```\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for the git hooks, the release process, and the constraints an implementation change must preserve.\n\n## Design principles\n\nThese hold across every part of the design below, and any implementation change must preserve them:\n\n- **No assumptions about consumer data.** The only places this package touches real data are three named resolver contracts (see [Resolvers](#resolvers)). The schema stores *what to pass* to a resolver, never any resolver logic itself, and never interprets the meaning of an opaque key, table identifier, or collection reference.\n- **Three outcomes, never two.** Every evaluation produces a definite result or an indeterminate result carrying a reason — never a bare `boolean`/`number`, and never a thrown exception for a data-quality problem. See [The evaluation model](#the-evaluation-model).\n- **Derived constructs are compositions, not new logic.** Anything describable as \"some other primitive, wired together\" is implemented that way, so its correctness is inherited rather than requiring separate proof. See [Derived connectives](#derived-connectives), [Derived aggregates](#derived-aggregates), [Derived values](#derived-values), [Pattern-matching builders](#pattern-matching-builders), and [Defining your own named presets](#defining-your-own-named-presets).\n- **One schema, mechanically derived artefacts.** A single canonical type definition produces the runtime validator and the portable wire-format schema; they cannot drift apart because there is only one source. See [Schema strategy](#schema-strategy).\n- **A numeric extension that stays closed-form is in scope; a different kind of computation is not.** When something the current numeric model does not cover comes up, the test is whether evaluating it is still closed-form numeric evaluation — no solving, no simplification, no code execution. If it is, it belongs here, however unlike the existing kinds it looks: [Complex values](#complex-values) were once listed under [Out of scope](#out-of-scope) on a sizing judgement that turned out to be wrong, since complex arithmetic is exactly the closed-form evaluation this evaluator already does for every other kind. What stays behind [`delegate`](#delegate) is a genuinely different *kind* of computation — symbolic algebra, arbitrary external computation — not merely a kind of number the model has not reached yet.\n- **Generic examples only.** Every example in this document uses invented, placeholder field names (`temperature`, `orderTotal`, `isActive`, `x`, `y`, `amount`, `items`) with no resemblance to any particular company, product, or industry's real data model.\n\n## The evaluation model\n\nEvery evaluation — of a predicate node or an expression node — produces exactly one of two outcomes:\n\n```ts\ntype Evaluation<T> =\n  | { status: \"definite\"; value: T }\n  | { status: \"indeterminate\"; reason: IndeterminateReason };\n\ninterface IndeterminateReason {\n  /** Which of the three reason categories applies. */\n  code: \"not-found\" | \"wrong-type\" | \"domain-error\";\n  /** A human-readable explanation, for logging and debugging. */\n  message: string;\n}\n```\n\nThe three reason codes are:\n\n| Code | Meaning |\n|---|---|\n| `not-found` | A value a node needed did not exist in the underlying data at all. |\n| `wrong-type` | A value existed but was not of a kind the operation could use (e.g. non-numeric where a number was required). |\n| `domain-error` | A mathematical operation was attempted outside its valid domain (division by zero, a function given an input outside its allowed range, an aggregation with nothing to aggregate). |\n\n`domain-error` is not a separate error type, exception, or crash — it uses exactly the same `Evaluation`/`IndeterminateReason` mechanism as the other two. This three-outcome model applies uniformly to every node kind in both trees: arithmetic, comparison, and boolean logic alike. It never collapses to a plain boolean or number at any intermediate point inside the tree; only the code that consumes the final top-level `Evaluation` decides what to do with an indeterminate outcome (reject, default, surface to a user, etc.) — that decision is deliberately outside this package's scope.\n\n**Infrastructure failures are a different concern.** If a resolver itself throws (a network error, a database outage), that propagates as an ordinary rejected promise from `evaluatePredicate`/`evaluateValue`, exactly like any other function call failure. The three-outcome model exists to describe *data-quality* states inside the domain being modelled — it does not, and should not, attempt to also model transport-level failure.\n\n### Where an indeterminate outcome can carry more than one candidate reason\n\nSome nodes combine several sub-evaluations that could each independently be indeterminate for a different reason (e.g. an `and` node whose both operands are indeterminate, one `not-found` and one `wrong-type`). This design resolves ties with a single, consistently-applied rule: **take the first indeterminate reason encountered in the node's own declared operand order** (left before right; list order for N-ary/collection operands). This is an implementation decision this document makes explicitly, once, so every node kind's evaluator can apply the same rule without re-deriving it.\n\n## Three-valued propagation rules\n\nLet **U** denote \"indeterminate\" for the purposes of these tables — the specific reason is preserved and reported per the tie-break rule above, but propagation logic itself only cares that an operand is not a definite value. **T** = true, **F** = false.\n\n**Any arithmetic operation or relational comparison with at least one indeterminate operand always produces an indeterminate result.** There is no operand value that can rescue an arithmetic or single relational comparison once one side is indeterminate — arithmetic and single relational comparisons have no absorbing value and no short-circuit.\n\nLogical AND, OR, and NOT behave differently: they have absorbing values, and this absorption must be preserved exactly as specified below. **A design in which any indeterminate operand automatically makes the whole boolean result indeterminate, with no absorption, is a specification defect** — it would silently discard cases where the answer was already determined regardless of the indeterminate side.\n\n**AND** — `false` is absorbing/dominant:\n\n| AND | T | F | U |\n|---|---|---|---|\n| **T** | T | F | U |\n| **F** | F | F | F |\n| **U** | U | F | U |\n\n**OR** — `true` is absorbing/dominant (mirror image of AND):\n\n| OR | T | F | U |\n|---|---|---|---|\n| **T** | T | T | T |\n| **F** | T | F | U |\n| **U** | T | U | U |\n\n**NOT** — negates a definite result; leaves indeterminate as indeterminate, reason unchanged:\n\n| NOT | result |\n|---|---|\n| T | F |\n| F | T |\n| U | U |\n\n**Identity elements for the N-ary and collection forms.** AND is a fold over `true` (the identity for AND), OR is a fold over `false` (the identity for OR) — this is a structural property of the operation, not a separate design choice, so it applies consistently everywhere an AND/OR is taken across a list: an empty `allOf` is definitely `true`; an empty `anyOf` is definitely `false`; a \"some\" quantifier over an empty collection is definitely `false` (no item can satisfy it).\n\n> **Deliberate, settled: `every` over an empty collection is definitely `true`.** This is vacuous truth — the standard convention for universal quantification over an empty set, and exactly the same identity-element reasoning already used for `allOf` above (an empty `allOf`'s `true` and an empty `every`'s `true` are the same fact, stated twice because `every` is a quantifier over resolved items rather than a literal list of sub-nodes). This is worth stating explicitly and prominently, rather than leaving it as something an implementer might reasonably second-guess, because at least one other real, existing tool in this space gets exactly this case wrong — its own \"all\" operator returns `false` for an empty collection, which is simply an incorrect implementation of universal quantification, not an equally valid alternative convention. Nothing about a genuinely empty collection can violate \"every item satisfies X\", so `true` is the only value consistent with what the quantifier claims to mean; this document's `every` must not be \"fixed\" to match that other tool's behaviour.\n\n## Derived connectives\n\nExclusive-or, NAND, NOR, implication, and the biconditional are never implemented as independently-evaluated node kinds. Each is defined purely as a fixed composition of unary NOT and binary AND/OR, expressed as ordinary builder functions that construct a tree of primitive nodes:\n\n```ts\nconst not    = (a: PredicateNode): PredicateNode => ({ kind: \"not\", operand: a });\nconst and    = (a: PredicateNode, b: PredicateNode): PredicateNode => ({ kind: \"and\", left: a, right: b });\nconst or     = (a: PredicateNode, b: PredicateNode): PredicateNode => ({ kind: \"or\", left: a, right: b });\n\nconst xor     = (a: PredicateNode, b: PredicateNode): PredicateNode => or(and(a, not(b)), and(not(a), b));\nconst nand    = (a: PredicateNode, b: PredicateNode): PredicateNode => not(and(a, b));\nconst nor     = (a: PredicateNode, b: PredicateNode): PredicateNode => not(or(a, b));\nconst implies = (a: PredicateNode, b: PredicateNode): PredicateNode => or(not(a), b);\nconst iff     = (a: PredicateNode, b: PredicateNode): PredicateNode => not(xor(a, b));\n\nconst none = (collection: JsonValue, item: PredicateNode, filter?: PredicateNode): PredicateNode =>\n  not({ kind: \"some\", collection, item, filter });\n```\n\nNone of `xor`/`nand`/`nor`/`implies`/`iff` ever appears as a `kind` discriminant on the wire — a serialised tree containing an XOR is indistinguishable from one written out by hand using `or`/`and`/`not`. Three-valued correctness for all five is therefore inherited automatically from the already-verified AND/OR/NOT tables above, never requiring a separate proof for each.\n\nThe same treatment applies to a third quantifier, `none` (\"no item satisfies\") — defined purely as `not(some(...))`, never as its own independently-evaluated node kind, and so never appearing as its own `kind` discriminant either. Its three-valued correctness is inherited automatically from NOT and from `some`'s own already-established correctness (including its absorbing behaviour and its `filter` handling) — no new truth table or worked proof is needed, exactly as for the five connectives above.\n\n### Worked correctness check: exclusive-or\n\nApplying the AND/OR/NOT tables above to `xor(A, B) = or(and(A, not(B)), and(not(A), B))` across all nine combinations of `{T, F, U}` for `A` and `B`:\n\n| A | B | not B | A ∧ ¬B | not A | ¬A ∧ B | result (∨) | expected |\n|---|---|---|---|---|---|---|---|\n| T | T | F | F | F | F | F | F |\n| T | F | T | T | F | F | T | T |\n| T | U | U | U | F | F | U | U |\n| F | T | F | F | T | T | T | T |\n| F | F | T | F | T | F | F | F |\n| F | U | U | F | T | U | U | U |\n| U | T | F | F | U | U | U | U |\n| U | F | T | U | U | F | U | U |\n| U | U | U | U | U | U | U | U |\n\nEvery fully-known input pair produces the correct classical XOR, and every combination with at least one `U` produces `U`. This is the correct three-valued extension specifically for XOR — unlike AND/OR, exclusive-or has no operand value that determines the result on its own (there is no value of `B` for which `xor(anything, B)` is fixed regardless of the other side), so it has no absorbing value and \"any unknown input yields an unknown output\" is exactly right here — even though the identical blanket rule would be *wrong* for AND/OR, where it would ignore real absorption. NAND, NOR, implication, and the biconditional each inherit correct behaviour the same way, purely from being built out of NOT/AND/OR — check any of them the same way, by writing out all nine input combinations and confirming the result matches intuition. As one further spot check: `implies(F, U) = or(not(F), U) = or(T, U) = T` — a false antecedent makes an implication vacuously true regardless of whether the consequent is even knowable, which is the absorbing behaviour correctly carried through from OR.\n\n## Schema strategy\n\nThe canonical definition lives in one place: a [Zod](https://zod.dev) schema per node kind. The TypeScript type is inferred from the schema (`z.infer<...>`), and a portable wire-format schema for documentation or cross-language interoperability is mechanically derived from the same Zod schema via `z.toJSONSchema()`. There is exactly one hand-authored artefact; the runtime validator and the JSON Schema document cannot drift apart because the second is generated from the first, not maintained alongside it.\n\n```ts\nimport { z } from \"zod\";\n\n// A JSON value with no further meaning imposed by this schema — used for every\n// opaque payload (reference keys, table identifiers, collection references,\n// delegation payloads). \"Opaque\" means \"uninterpreted by this package\", not\n// \"untyped\" — every one of these must still be plain, serialisable JSON.\ntype JsonValue = string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue };\nconst JsonValueSchema: z.ZodType<JsonValue> = z.lazy(() =>\n  z.union([z.string(), z.number(), z.boolean(), z.null(), z.array(JsonValueSchema), z.record(z.string(), JsonValueSchema)])\n);\n```\n\nNode schemas are `z.discriminatedUnion(\"kind\", [...])` over per-kind `z.object` shapes, following the concrete definitions below. A generated JSON Schema document (produced once, as a build step, via `z.toJSONSchema(PredicateNodeSchema)` / `z.toJSONSchema(ExpressionNodeSchema)`) is what a non-TypeScript consumer or an authoring UI would target.\n\nThe generated document carries a version-pinned `$id` — a jsDelivr URL naming the exact published version, e.g. `https://cdn.jsdelivr.net/npm/trilean@1.2.3/schemas/trilean.schema.json` — so a consumer's own rule file can point its `$schema` at a fixed target rather than a moving one. The file's bytes are exactly its RFC 8785 (JSON Canonicalization Scheme) canonical form — keys sorted recursively, no whitespace between tokens, no trailing newline — so `canonicalize(JSON.parse(file)) === file` holds under any JCS implementation, and the same input always produces the same bytes. That makes the file's own SHA-256 re-derivable from its parsed content alone, which is what lets a downloaded copy be checked against this package's SBOM and build-provenance attestations (see the release workflow).\n\n### Performance\n\nA consumer that parses and evaluates many trees at high throughput can opt into Zod 4.5's compiled-schema fast path by importing `zod/compile` once, at their own application's entry point:\n\n```ts\nimport \"zod/compile\";\n```\n\nThis package deliberately does **not** import it itself — `zod/compile` has global side effects on the Zod runtime, which would contradict this package's own `sideEffects: false` declaration and could surprise a consumer who never asked for it. Opting in (or not) is left entirely to whoever embeds the package.\n\n## The predicate tree\n\nA `PredicateNode` evaluates to `Evaluation<boolean>` — true, false, or indeterminate-with-reason.\n\n```ts\ntype ComparisonOperator = \"gt\" | \"gte\" | \"lt\" | \"lte\" | \"eq\" | \"neq\";\ntype TextComparisonOperator = \"equals\" | \"notEquals\" | \"matches\" | \"notMatches\" | \"portableMatches\" | \"portableNotMatches\";\ntype MembershipOperator = \"in\" | \"notIn\";\n\ntype PredicateNode =\n  | { kind: \"not\"; operand: PredicateNode }\n  | { kind: \"and\"; left: PredicateNode; right: PredicateNode }\n  | { kind: \"or\"; left: PredicateNode; right: PredicateNode }\n  | { kind: \"allOf\"; operands: PredicateNode[] }\n  | { kind: \"anyOf\"; operands: PredicateNode[] }\n  | { kind: \"compare\"; op: ComparisonOperator; left: ExpressionNode; right: ExpressionNode }\n  | { kind: \"textCompare\"; op: TextComparisonOperator; left: ExpressionNode; right: ExpressionNode }\n  | { kind: \"memberOf\"; op: MembershipOperator; operand: ExpressionNode; candidates: ExpressionNode[] }\n  | { kind: \"exists\"; operand: ExpressionNode }\n  | { kind: \"some\"; collection: JsonValue; item: PredicateNode; filter?: PredicateNode }\n  | { kind: \"every\"; collection: JsonValue; item: PredicateNode; filter?: PredicateNode }\n  | { kind: \"treeReference\"; key: JsonValue };\n```\n\n### `not`, `and`, `or`\n\nThe three primitives. `not` takes exactly one operand — it is never modelled as a two-operand node with an unused second slot. `and`/`or` each take exactly two named operands (`left`/`right`), evaluated per the truth tables above.\n\n### `allOf`, `anyOf`\n\nThe N-ary forms of `and`/`or`: given an ordered list of operands (rather than exactly two), combine all of them with AND, or all of them with OR, respectively. Defined as repeated pairwise application of `and`/`or` — an implementation detail, not a new evaluation rule requiring separate verification. Because resolvers are asynchronous, a reference implementation is free to evaluate every operand concurrently and then apply the absorption rule when combining results, rather than evaluating strictly left-to-right; both strategies produce an identical final `Evaluation` because absorption is a property of the values, not of execution order. The empty-list identity values from [Three-valued propagation rules](#three-valued-propagation-rules) apply: `allOf([])` is definitely `true`; `anyOf([])` is definitely `false`.\n\n### `compare`\n\nA relational-comparison leaf: compares two computed values using `gt`/`gte`/`lt`/`lte`/`eq`/`neq`. **Both `left` and `right` are `ExpressionNode`** — either side may be a plain literal/reference or an arbitrary formula from the expression tree; the comparison is symmetric, and an implementation that only allows a formula on one side is incomplete. Valid operand kinds are `number` (matching units required — see [Units](#units)), `instant`, `duration`, or `boolean`, plus `complex` for `eq`/`neq` only (see [Complex values](#complex-values)); comparing across different computed-value kinds, or comparing two numbers with incompatible units, is `wrong-type`. `boolean` only supports `eq`/`neq` — there is no natural ordering for a truth value, so `gt`/`gte`/`lt`/`lte` are `wrong-type` for a `boolean` operand.\n\n### `textCompare`\n\nA text-matching leaf, symmetric in the same way as `compare`: both `left` and `right` are `ExpressionNode`, and either may be a literal or an arbitrary formula. `equals`/`notEquals` are exact string equality; `matches`/`notMatches` interpret `right` as a pattern (an ECMAScript-style regular expression) tested against `left`'s text. Both operands must resolve to the `text` computed-value kind; anything else is `wrong-type`. A \"small fixed category\" value (e.g. a status label) is simply a `text` computed value from this leaf's point of view — no separate category kind exists.\n\n**`portableMatches`/`portableNotMatches`** answer the same question as `matches`/`notMatches` but interpret `right` as a pattern in [`trilean-regex`](https://www.npmjs.com/package/trilean-regex)'s own grammar instead of ECMAScript's — a genuine regular language (no backreferences, no lookaround), matched by that package's Thompson-construction NFA simulation rather than the host's native `RegExp` engine. Two consequences follow from that restriction, and are the reason to reach for the portable pair instead of the plain one:\n\n- **No catastrophic-backtracking risk.** An NFA simulation runs in time linear in the pattern's compiled state count and the input's length, regardless of the pattern's shape — there is no input a `portableMatches` pattern can be made to hang on the way a pathological ECMAScript pattern can hang `matches`.\n- **Provable pushdown equivalence.** Because the grammar is a true regular language, [`trilean-sql`](https://www.npmjs.com/package/trilean-sql)'s dialect compilers can translate a `portableMatches`/`portableNotMatches` pattern into a database's own `LIKE`/`GLOB`/native-regex operators and prove the translation agrees with this package's own evaluator row for row — the same \"compile and measure agreement against the reference matcher\" discipline `trilean-sql` already applies to everything else it compiles. `matches`/`notMatches` carry no such guarantee: what a SQL engine's own native regex operator accepts is a different language from ECMAScript's, and `trilean-sql` refuses to push either operator down for exactly that reason (see `trilean-sql`'s README).\n\nThis is additive, not a redefinition: `matches`/`notMatches` keep their existing ECMAScript semantics unchanged, and nothing already written against them is affected. Reach for `portableMatches`/`portableNotMatches` specifically when a tree might be compiled to SQL (or when the backtracking-safety guarantee alone is worth the smaller grammar), and keep `matches`/`notMatches` for in-process-only trees that need ECMAScript's full expressiveness. An invalid `trilean-regex` pattern is `wrong-type`, exactly like an invalid ECMAScript pattern under `matches` — see `trilean-regex`'s own README for the grammar's precise definition and what it deliberately excludes.\n\n### Pattern-matching builders\n\n`matches` already covers arbitrary pattern matching, but writing the regular expression by hand is where the common, narrower cases go wrong: getting the escape-then-convert ordering backwards either stops wildcards working or silently reinterprets a literal asterisk in real data as one. Three builder functions compile a pattern string into an ordinary `textCompare` node instead — never a new node kind, never an evaluator branch, exactly the same composition-not-new-logic treatment [Derived connectives](#derived-connectives), [Derived aggregates](#derived-aggregates), and [Derived values](#derived-values) already give `xor`/`sum`/`coalesce`:\n\n```ts\nconst command: ExpressionNode = { kind: \"reference\", key: \"command\" };\nconst path: ExpressionNode = { kind: \"reference\", key: \"path\" };\n\n// Matches \"ls\" and \"ls -la\", never \"lsof\".\nprefixPattern(command, \"ls\");\n// Matches \"git add file\" and, by the trailing-wildcard convenience below, bare \"git\".\nwildcardPattern(command, \"git *\");\n// Matches \"workspace/report.txt\", but not \"workspace/archive/report.txt\".\nhierarchicalGlobPattern(path, \"workspace/*\");\n```\n\nEach returns an ordinary predicate node — `prefixPattern(command, \"ls\")` is exactly `{ kind: \"textCompare\", op: \"matches\", left: command, right: { kind: \"textLiteral\", value: \"^ls(?: [\\\\s\\\\S]*)?$\" } }`. Compilation happens once, when the tree is built, so what is stored and serialised is a `textCompare` tree indistinguishable from one written out by hand — a consumer that never calls a builder loses nothing, and a serialised tree carries no dependency on the builder that produced it.\n\nThe three are separate dialects, deliberately not one function with a mode argument, because they answer different questions and mixing them silently changes what a pattern means:\n\n| Builder | `*` | `**` | `?` | Escapes | Intended for |\n|---|---|---|---|---|---|\n| `prefixPattern` | literal | literal | literal | none — the prefix is a plain literal throughout | Command/label prefixes where `\"ls\"` must match `\"ls\"` and `\"ls -la\"` but never `\"lsof\"` |\n| `wildcardPattern` | any characters | (two wildcards in a row) | literal | `\\*` for a literal asterisk, `\\\\` for a literal backslash | Flat strings with no internal hierarchy |\n| `hierarchicalGlobPattern` | any characters within one `/`-delimited segment | any characters across segments | one character within a segment | none — a backslash is a literal backslash | Path- or category-tree-shaped values |\n\nTwo behaviours in `wildcardPattern` are worth stating rather than leaving to be inferred. Its pattern is trimmed before compiling. And a pattern whose **only** unescaped wildcard is a trailing `\" *\"` also matches the bare prefix, so `\"git *\"` matches `\"git\"` as well as `\"git add file\"` — the convenience does not apply to `\"git * *\"`, where both wildcards are still required.\n\nThe compiled pattern is a fully anchored, flag-free string: \"any character\" is spelled `[\\s\\S]` rather than `.`, because the stored pattern carries no `s` flag and nothing downstream can add one, and the only characters escaped are ECMAScript's own `SyntaxCharacter` set plus `/`, which are exactly the escapes that stay valid under a `u`/`v`-flagged `RegExp` as well as an unflagged one. A compiled pattern is therefore portable in the strongest available sense — it means the same thing wherever it is compiled, including pasted verbatim into a `/.../` literal.\n\nThree-valued behaviour is inherited unchanged from [`textCompare`](#textcompare) and needs no separate proof: an unresolvable subject is indeterminate rather than a non-match, and a non-`text` subject is `wrong-type` — a compiled pattern never turns a data problem into a definite `false`.\n\n### `memberOf`\n\nA membership-test leaf, parallel to `compare` and `textCompare` rather than folded into either one's operator set: `operand` is the `ExpressionNode` being tested; `candidates` is a list of `ExpressionNode`s to test it against, every element of which may independently be an arbitrary formula, not only a literal — the same symmetry principle already applied to `compare` and `textCompare`. `op: \"in\"` asks whether `operand` equals any candidate; `op: \"notIn\"` asks whether it equals none of them.\n\nMembership is decided by value equality between computed values of the same kind, respecting units for numeric values exactly as `compare`'s own `eq` already does — a candidate of an incompatible kind, or a `number` candidate with an incompatible unit, can never be a match, and the comparison for that one element is `wrong-type`, not simply \"not equal\".\n\nEvaluate `operand` first; if it is indeterminate, the whole leaf is indeterminate with that reason. Otherwise, scan `candidates` in order: a candidate that is a **definite match** immediately settles the result — `in` is definitely `true`, `notIn` is definitely `false` — regardless of any not-yet-scanned or indeterminate candidates, mirroring the same absorbing-value discipline already established for OR and `some` elsewhere in this document (a confirmed match cannot be undone by an unrelated element's data problem). If scanning completes with no definite match: the leaf is indeterminate (first indeterminate candidate's reason, per the tie-break rule in [The evaluation model](#the-evaluation-model)) if at least one candidate was itself indeterminate or of an incompatible kind/unit; otherwise every candidate was a definite, comparable non-match, and `in` is definitely `false`, `notIn` is definitely `true`. An empty `candidates` list is never scanned and never indeterminate: `in` is definitely `false` and `notIn` is definitely `true` — the same non-vacuous facts an empty `anyOf`/`allOf` already establishes for OR/AND.\n\n### `exists`\n\nEvaluates `true` if the given `ExpressionNode` can be resolved to some value at all, `false` if it definitely cannot be resolved (the data point is genuinely absent), independent of whether that value would itself be usable in further computation. Concretely: evaluate the operand; if the result is definite, `exists` is `true`; if the result is indeterminate with reason `not-found`, `exists` is `false`; if the result is indeterminate with reason `wrong-type` or `domain-error`, `exists` is still `true` — the underlying data point *did* resolve to something, it merely wasn't usable for whatever computation was attempted around it, which is exactly why section [The evaluation model](#the-evaluation-model) distinguishes \"did not exist\" from \"existed but unusable\" in the first place. `exists` itself is never indeterminate — it always produces a definite boolean.\n\n### `some`, `every`\n\nQuantifiers over a collection, sharing the exact collection-resolution mechanism described in [Collections](#collections). `some` is semantically an OR of `item` evaluated once per participating item; `every` is semantically an AND of `item` evaluated once per participating item — both inherit the absorbing-value propagation from the AND/OR tables applied across the whole collection (e.g. `some` can be definitely `true` from one known-true item even if every other participating item is unresolvable). An optional `filter` narrows which resolved items participate at all before either quantifier runs over them — see [Collections](#collections) for exactly how a `filter` result feeds into this same absorption. The item's own evaluation context (for both `filter` and `item`) is the item itself — see [Collections](#collections). A third quantifier, \"no item satisfies\", is derived from `some` — see [Derived connectives](#derived-connectives).\n\n## The expression tree\n\nAn `ExpressionNode` evaluates to `Evaluation<ComputedValue>`.\n\n```ts\ntype Unit = Record<string, number>; // dimension symbol -> exponent, e.g. { m: 1, s: -1 } for metres per second\ntype DurationUnit = \"ms\" | \"s\" | \"min\" | \"h\" | \"d\";\n\ntype ComputedValue =\n  | { kind: \"number\"; value: number; unit?: Unit }\n  | { kind: \"text\"; value: string }\n  | { kind: \"boolean\"; value: boolean }\n  | { kind: \"instant\"; value: string }   // ISO-8601 timestamp\n  | { kind: \"duration\"; value: number; unit: DurationUnit }\n  | { kind: \"complex\"; re: number; im: number; unit?: Unit };\n\ntype ArithmeticOperator = \"add\" | \"subtract\" | \"multiply\" | \"divide\" | \"power\" | \"modulo\";\n\ntype FoldCombiner =\n  | { mode: \"max\"; item: ExpressionNode }\n  | { mode: \"min\"; item: ExpressionNode }\n  | { mode: \"reduce\"; initial: ExpressionNode; combine: ExpressionNode };\n\ntype HitPolicy = \"first\" | \"unique\";\n\ntype ExpressionNode =\n  | { kind: \"numberLiteral\"; value: number; unit?: Unit }\n  | { kind: \"textLiteral\"; value: string }\n  | { kind: \"booleanLiteral\"; value: boolean }\n  | { kind: \"instantLiteral\"; value: string }\n  | { kind: \"durationLiteral\"; value: number; unit: DurationUnit }\n  | { kind: \"complexLiteral\"; re: number; im: number; unit?: Unit }              // rectangular\n  | { kind: \"complexLiteral\"; magnitude: number; phase: number; unit?: Unit }    // polar -- see Complex values\n  | { kind: \"reference\"; key: JsonValue; unit?: Unit }\n  | { kind: \"arithmetic\"; op: ArithmeticOperator; left: ExpressionNode; right: ExpressionNode }\n  | { kind: \"negate\"; operand: ExpressionNode }\n  | { kind: \"call\"; fn: string; args: ExpressionNode[] }\n  | { kind: \"lookup\"; table: JsonValue; keys: ExpressionNode[] }\n  | { kind: \"conditional\"; hitPolicy?: HitPolicy; cases: { when: PredicateNode; then: ExpressionNode }[]; fallback: ExpressionNode }\n  | { kind: \"fold\"; collection: JsonValue; filter?: PredicateNode; combiner: FoldCombiner }\n  | { kind: \"accumulator\" }\n  | { kind: \"delegate\"; system: string; payload: JsonValue }\n  | { kind: \"treeReference\"; key: JsonValue };\n```\n\nA `textLiteral` kind is included even though it is not separately enumerated as its own top-level construct, because `textCompare`'s symmetry requirement (either side may be an arbitrary computed value, per the section above) is meaningless without a way to write a constant string or pattern — matching a field against the fixed text `\"active\"`, or against a fixed regular expression, needs a text constant on one side. This is a structural consequence of the symmetry already required for text matching, not an added feature.\n\n### Literals\n\n`numberLiteral`, `textLiteral`, `booleanLiteral`, `instantLiteral` (an ISO-8601 timestamp string), `durationLiteral` (a magnitude plus a `DurationUnit`), and `complexLiteral` (either a real and an imaginary component, or a magnitude and a phase, plus an optional `Unit` — see [Complex values](#complex-values)) are always definite by construction — a literal node never itself produces an indeterminate outcome.\n\n### `reference`\n\nA reference to a single external value, identified by an opaque `key` whose meaning is entirely up to the embedding consumer — the schema never interprets it (see [Resolvers](#resolvers), resolver 1). May optionally carry an expected `unit`, validated against whatever the resolver actually returns for a `number` result; a mismatch (or an expectation of a unit on a non-numeric result) is `wrong-type`. If the resolver reports absence, the result is `not-found`.\n\n### `arithmetic`, `negate`\n\nBinary arithmetic (`add`/`subtract`/`multiply`/`divide`/`power`/`modulo`) and unary negation, each over `number` computed values by default, with the temporal exceptions listed under [Temporal values](#temporal-values) and the complex ones under [Complex values](#complex-values) below. `negate` is an explicit node — never sugar for \"zero minus the value\" — because it also applies to `duration` values (negating a duration reverses its direction) where \"zero minus\" has no natural literal-zero counterpart; over a `complex` value it flips both components. Division by zero, or any operator given an operand outside its mathematical domain, is `domain-error`; a non-numeric, non-temporal operand where a number was required is `wrong-type`; any operand that is itself indeterminate makes the whole node indeterminate, with no rescuing value on the other side (see [Three-valued propagation rules](#three-valued-propagation-rules)).\n\n### `call`\n\nA named function applied to an ordered list of `ExpressionNode` arguments. The set of named functions is intentionally open-ended and resolved through a function registry supplied at evaluator construction time — `minimum`, `maximum`, `absoluteValue`, `round`, `squareRoot`, and `logarithm` are starting examples, not an exhaustive list; new functions are added to the registry as concrete need arises. Calling an unregistered function name is `wrong-type` (\"no function registered under this name\"); calling a registered function with an argument outside its domain (e.g. `squareRoot` given a negative number) is `domain-error`.\n\n### Units\n\n`numberLiteral`, `complexLiteral`, and `reference` may carry a `unit`, represented as a dimensional-exponent map (e.g. `{ m: 1, s: -1 }` for metres per second) rather than an opaque string, so that unit combination follows real dimensional analysis instead of string matching. A bare symbol like `\"kg\"` is shorthand for `{ kg: 1 }`.\n\n- `add`/`subtract` between two unit-tagged numbers require **identical** dimensional-exponent maps. A mismatch is `wrong-type` (\"incompatible units\") — units are never silently coerced or dropped.\n- `multiply`/`divide` combine the two operands' unit maps by dimensional analysis: multiplying adds exponents per dimension, dividing subtracts them. An operand with no `unit` is treated as dimensionless (an empty map) for this purpose.\n\n### Temporal values\n\n`instant` (a point in time) and `duration` are computed-value kinds distinct from `number`, even though a duration ultimately carries a numeric magnitude — an instant is never treated as \"a number that happens to represent a date\". The only well-defined cross-kind arithmetic is:\n\n- `instant − instant → duration`\n- `instant + duration → instant` (and `duration + instant → instant`)\n\nAny other arithmetic combination touching an `instant` or `duration` (adding two instants, multiplying a duration by an instant, comparing an instant against a plain number, and so on) is `wrong-type`. A reference implementation normalises `duration` values to a single base unit (milliseconds) internally before combining two durations of different `DurationUnit`s, then reports the result in whichever unit the node's own context calls for.\n\n### Complex values\n\n`complex` is a computed-value kind alongside `number`, for the domains — signal processing, control theory, anything phasor-shaped — where a formula naturally mixes real and complex terms in one expression. It stays inside this evaluator rather than behind [`delegate`](#delegate) because it is closed-form numeric evaluation, exactly what every other kind here already does; see [Design principles](#design-principles) for that scope test in general.\n\n**One canonical representation, rectangular.** A `complex` value is stored as `{ re, im }` and never as a magnitude and a phase, and there is deliberately no `form` discriminant offering both. Three reasons, in order of weight:\n\n1. **A second form would make equality ambiguous.** Polar coordinates do not encode a value uniquely — phase is only defined modulo a full turn, and a zero-magnitude value has no meaningful phase at all — so the same complex number would have unboundedly many polar encodings. `eq` and `memberOf` are exact equality throughout this design (see [`compare`](#compare)); making them work across two forms would mean either normalising on every comparison or introducing an approximate equality for this one kind, and neither belongs in a design where every other kind compares exactly.\n2. **A discriminant would double the branching in every operator** — quadruple it for a binary one — for a choice that changes no value. Every operator would still convert to rectangular internally, because that is where the closed forms live, so the discriminant would buy nothing at evaluation time and cost at every boundary.\n3. **Rectangular is what the operators actually need.** `add`/`subtract` are component-wise in it; `multiply`, `divide`, `negate`, and integer `power` all have standard closed forms in it. Polar's advantage — multiplication and division as one product of magnitudes and one sum of angles — does not extend to addition at all, which would have to convert back and forth.\n\nThe magnitude-and-phase view stays reachable through four exported conversion helpers rather than a second encoding: `complexFromPolar(magnitude, phase, unit?)` and `complexLiteralFromPolar(magnitude, phase, unit?)` build a value or a literal node from polar terms, and `complexMagnitude(value)` and `complexPhase(value)` read them back out — the magnitude as a real number in the value's own unit, the phase as a dimensionless real number of radians. Conversions at the edges, one representation in the middle.\n\n**The wire-format literal accepts either authoring form, structurally discriminated.** `ComputedValue`'s own `complex` kind stays exactly the single rectangular shape described above — nothing about it changes. But the `complexLiteral` *node* is a plain union of two shapes, `{ kind: \"complexLiteral\", re, im, unit? }` and `{ kind: \"complexLiteral\", magnitude, phase, unit? }`, told apart by which fields are present rather than by a `form` tag, since both still share the one literal `kind`. This is not a second encoding of `ComputedValue` reappearing through the back door — it exists only at the authoring boundary, for whichever of the two forms is natural for a given domain to write directly into JSON rather than hand-computing a conversion before ever constructing the tree, and the evaluator normalises whichever form was used to the single rectangular `ComputedValue` immediately, before any arithmetic, comparison, or negation ever runs. A rectangular literal and a polar literal representing the same underlying number are therefore indistinguishable from that point on: they evaluate to the identical `ComputedValue` and compare `eq` to one another exactly as two rectangular literals with the same components would.\n\n**Arithmetic.**\n\n- `add`/`subtract` are component-wise, requiring **identical** dimensional-exponent maps exactly as real numbers do (see [Units](#units)).\n- `multiply`/`divide` are real complex multiplication and division — `(a + bi)(c + di) = (ac − bd) + (ad + bc)i`, and the corresponding quotient — never component-wise. Units combine by the same dimensional analysis real numbers use. A zero divisor means both components zero; a divisor with only a zero real part divides perfectly well.\n- `power` is defined for a **real integer exponent** and evaluated as the repeated multiplication that integer exponentiation is, with a negative exponent the reciprocal of the positive one. Like a real `power`, it requires dimensionless operands. An arbitrary complex exponent is a genuinely bigger question — it needs the complex logarithm, which is multivalued, so it needs a branch-cut convention this design has not chosen — and is deliberately out of scope for now: it is `wrong-type`, as is a non-integer real exponent, on the same reading of that code used throughout (\"an answer exists, but this operator does not accept this operand\" — compare `power`'s existing dimensionless-operands requirement, also `wrong-type`).\n- `modulo` is `domain-error`, not `wrong-type`: a remainder needs a canonical notion of how many whole divisors fit, and the complex plane has no ordering to supply one. There is no answer to accept, which is the same category as division by zero.\n\n**A real operand is promoted, never rejected.** Mixing a `number` with a `complex` in one `arithmetic` node works: every real number *is* a complex number with a zero imaginary part, so the promotion is exact, total, and canonical — unlike the temporal cross-kind combinations above, which had to be enumerated one by one precisely because no such embedding exists between an `instant` and a `duration`. Scaling a complex value by a real one, or offsetting it by a real constant, is the common case, and forcing every real literal in such a formula to be rewritten as a complex one would defeat the point. The result is `complex` whenever either operand is, even when the imaginary part comes out zero: a node's result kind follows its operand kinds, never the values that happen to flow through it.\n\n**Comparison is kind-strict, deliberately unlike arithmetic.** `gt`/`gte`/`lt`/`lte` are `wrong-type` for a `complex` operand — the complex plane carries no total order — exactly as they already are for `text`. `eq`/`neq` work normally, as exact equality across both components under the same unit-compatibility rule numbers already have, and `memberOf` matches the same way. But a `complex` compared against a `number` is `wrong-type`, with no promotion: arithmetic *produces* a value, so promoting a real operand loses nothing, whereas a comparison *consumes* two, and this design already treats a kind difference between them as a modelling error worth surfacing — the same reason an `instant` is never compared against a plain `number` despite being a count of milliseconds underneath.\n\nOrdering a complex quantity therefore goes through whichever real projection the formula actually means — most often its magnitude. This package ships no built-in function set (see [`call`](#call)), so that bridge is an ordinary registry entry, one line over the exported helper:\n\n```ts\nconst functions: FunctionRegistry = {\n  magnitude: (args) =>\n    args[0]?.kind === \"complex\"\n      ? complexMagnitude(args[0])\n      : { domainError: \"expected a complex argument\" },\n};\n```\n\nwhich a tree then calls like any other function, putting a real number back on the left of an ordinary `compare`:\n\n```json\n{\n  \"kind\": \"compare\",\n  \"op\": \"gt\",\n  \"left\": { \"kind\": \"call\", \"fn\": \"magnitude\", \"args\": [{ \"kind\": \"reference\", \"key\": \"x\" }] },\n  \"right\": { \"kind\": \"numberLiteral\", \"value\": 13 }\n}\n```\n\n### `lookup`\n\nResolves a single value from a named external table-like source, keyed by one or more `ExpressionNode` keys, via resolver 2 (see [Resolvers](#resolvers)). The schema never interprets what \"table\" or \"key\" mean to a given consumer; `table` and the resolved key values are passed through verbatim. If any key expression is itself indeterminate, the lookup is indeterminate with that reason (no key evaluation, no lookup attempt). If the resolver reports no match, the result is `not-found`.\n\n### `conditional`\n\nA piecewise/conditional-value node: an ordered, possibly-empty list of `{ when, then }` cases plus a required `fallback`. An optional `hitPolicy` field (`\"first\"` or `\"unique\"`) decides how cases are read; absent is treated as `\"first\"` — the exact, unchanged behaviour of every tree serialised before this field existed, not a masked-bug fallback.\n\n**`hitPolicy: \"first\"`** (the default). Evaluates to the `then` of the first case whose `when` predicate is definitely `true`; if no case matches, evaluates to `fallback`. If evaluating a `when` predicate produces an indeterminate outcome **before any earlier case has matched**, the whole `conditional` node's own result is that same indeterminate outcome (reason preserved) — evaluation does not skip past an unknown guard to try the next one, because doing so could silently pick a later branch that only looks correct because an earlier one couldn't actually be checked.\n\n**`hitPolicy: \"unique\"`** asserts that at most one case is expected to match, and treats two or more matches as a data error rather than silently taking the first. Every case's `when` is evaluated concurrently (there is no \"earlier case\" to short-circuit on), then resolved in this order:\n\n1. **Two or more cases are definitely `true`** — `domain-error` (\"more than one case matched under the 'unique' hit policy\"), regardless of any other case's own indeterminacy. This mirrors `memberOf`/`some`/`every`'s existing absorption: a confirmed outcome (here, \"there is a genuine ambiguity\") cannot be undone by an unrelated case's data problem.\n2. Otherwise, **any case's `when` is indeterminate** — the whole node is indeterminate with that reason (first such candidate, in declared case order, per [The evaluation model](#the-evaluation-model)'s tie-break rule). This is deliberately **not** absorbed by a single already-confirmed match, unlike step 1 above and unlike `memberOf`/`some`/`every`'s own absorption: an unresolved case might still turn out to be a second match, so \"exactly one match so far\" cannot be trusted as final until every other case is known to not also match.\n3. Otherwise, **exactly one case is definitely `true`** — evaluate and return that case's `then`. No other case's `then` is ever evaluated.\n4. Otherwise (zero matches, and nothing indeterminate) — evaluate and return `fallback`, exactly as `\"first\"` already does.\n\n### `fold`\n\nAn aggregation over a collection (see [Collections](#collections)): `collection` is the opaque collection reference; an optional `filter` narrows which resolved items participate (see [Collections](#collections)); `combiner` decides how the participating items' values become one result. There is exactly one general mechanism, `reduce`, and exactly two named forms, `max`/`min`, that cannot be expressed as an instance of it — see [Derived aggregates](#derived-aggregates) for why `sum`, `count`, and `average` need no combiner mode of their own at all.\n\n**`reduce`** is \"fold with an accumulator\": `initial` is evaluated once, in the fold node's own (outer) context, to seed the running result; then, for each participating item in turn, `combine` is evaluated with that item as its evaluation context to produce the new running result from the old one. `combine` reaches the running result through the dedicated [`accumulator`](#accumulator) leaf; the item's own fields are reached the ordinary way, through `reference`/`lookup` nodes resolved against the item context. Over an empty (post-filter) collection, a `reduce` fold evaluates to `initial` without ever touching `combine`.\n\n**`max`/`min`** each carry an `item`, evaluated once per participating item using that item as its evaluation context, and keep the largest/smallest projected value seen. These two are the only combining behaviours that stay as their own directly-specified forms, for a precise mathematical reason rather than an arbitrary exception: `reduce` needs a seed value that is also the identity for `combine` (as `0` is for addition), and there is no largest or smallest real number to seed a running maximum or minimum with — the JSON number model has no literal for an unbounded sentinel. `max`/`min` are still the same underlying mechanism, just its standard *unseeded* variant (sometimes called \"reduce1\" elsewhere): the running result starts as the first participating item's own projected value, and `combine` (the ordinary \"keep the larger\"/\"keep the smaller\" comparison) is applied to each item after that — not an independently-invented special case, only the one variant of the mechanism that a literal `initial` genuinely cannot express. Over an empty (post-filter) collection, both are `domain-error` (undefined over an empty set, the same category as division by zero, per [The evaluation model](#the-evaluation-model)'s explicit allowance for \"any comparable domain violation for any function added later\") — there is no first item to seed from.\n\n**Indeterminacy, both forms.** If any participating item's `filter` evaluation is indeterminate, the whole `fold` is indeterminate with that reason — `fold` has no absorbing value (see [Three-valued propagation rules](#three-valued-propagation-rules)), so unlike a quantifier's OR/AND there is no other item's outcome that can override this (see [Pre-filtering which items participate](#pre-filtering-which-items-participate)). The same is true of any participating item's `item`/`combine` evaluation, and of a `reduce`'s `initial`: if any is indeterminate, the whole `fold` is indeterminate with that reason (first such candidate, in resolved-list order, `initial` counting as evaluated before any item).\n\n### `accumulator`\n\nA zero-field leaf, meaningful only inside the `combine` expression of an enclosing `fold`'s `reduce` form (see [`fold`](#fold) above), where it evaluates to that step's running accumulated result. A nested `fold`'s own `combine` expression introduces its own, separate accumulator scope — `accumulator` always refers to the innermost enclosing reduce fold. Using `accumulator` anywhere else (a `max`/`min` fold's `item`, a `filter` predicate, a quantifier's `item`, or outside any fold at all) is `wrong-type` — there is no running accumulator in scope.\n\n### Derived aggregates\n\n`sum`, `count`, and `average` are never their own `FoldCombiner` mode — each is a builder function that assembles an ordinary `fold` (and, for `average`, one `arithmetic` division of two ordinary folds), exactly the same treatment [Derived connectives](#derived-connectives) already gives `xor`/`nand`/`nor`/`implies`/`iff`/`none`: correctness is inherited from the mechanism they're built from, rather than needing its own independent implementation that could silently drift from it.\n\n```ts\nconst sum = (collection: JsonValue, item: ExpressionNode, filter?: PredicateNode): ExpressionNode => ({\n  kind: \"fold\",\n  collection,\n  filter,\n  combiner: {\n    mode: \"reduce\",\n    initial: { kind: \"numberLiteral\", value: 0 },\n    combine: { kind: \"arithmetic\", op: \"add\", left: { kind: \"accumulator\" }, right: item },\n  },\n});\n\nconst presenceOf = (probe: ExpressionNode): ExpressionNode => ({\n  kind: \"conditional\",\n  cases: [\n    {\n      when: { kind: \"memberOf\", op: \"in\", operand: probe, candidates: [probe] },\n      then: { kind: \"numberLiteral\", value: 1 },\n    },\n  ],\n  fallback: { kind: \"numberLiteral\", value: 0 }, // unreachable: a definite probe is always a member of the single-element list containing only itself\n});\n\nconst count = (collection: JsonValue, filter?: PredicateNode, probe?: ExpressionNode): ExpressionNode => ({\n  kind: \"fold\",\n  collection,\n  filter,\n  combiner: {\n    mode: \"reduce\",\n    initial: { kind: \"numberLiteral\", value: 0 },\n    combine: {\n      kind: \"arithmetic\",\n      op: \"add\",\n      left: { kind: \"accumulator\" },\n      right: probe ? presenceOf(probe) : { kind: \"numberLiteral\", value: 1 },\n    },\n  },\n});\n\nconst average = (collection: JsonValue, item: ExpressionNode, filter?: PredicateNode): ExpressionNode => ({\n  kind: \"arithmetic\",\n  op: \"divide\",\n  left: sum(collection, item, filter),\n  right: count(collection, filter),\n});\n```\n\n`sum` needs no per-item probe beyond `item` itself: it is a literal `reduce` seeded at `0`, adding each participating item's projected value to the running total, and it already goes indeterminate if `item` fails to resolve for any participating item — no separate mechanism needed, since `item`'s value is exactly what gets added.\n\n`count` takes an optional third argument, `probe`, and this is where it matters that `filter` and a probe are not the same thing. `filter` *excludes* an item from participating — a filtered-out item's absence is invisible in the final result, exactly as if it had never been in the collection at all. A `probe` does the opposite: it doesn't decide whether an item participates, it makes the *whole count* indeterminate if it fails to resolve for *any* participating item, surfacing \"I cannot give you a trustworthy count\" rather than silently reporting a smaller, technically-successful count for the same underlying data-quality problem — precisely the distinction the rest of this document's indeterminate-outcome model exists to preserve (see [The evaluation model](#the-evaluation-model)). `count(collection, filter)` with no `probe` is a plain `reduce` seeded at `0` that adds `1` per participating item, with no indeterminacy of its own beyond `filter`'s. `count(collection, filter, probe)` instead adds `presenceOf(probe)` per participating item — a small helper built entirely from already-established primitives, with no restriction on `probe`'s kind: it tests `probe` for membership in the single-element list `[probe]`, so a `memberOf` \"in\" test against itself is trivially true whenever `probe` resolves to a definite value of *any* kind (`memberOf`'s equality is already kind-agnostic across `number`/`text`/`boolean`/`instant`/`duration` — see [`memberOf`](#memberof)), and exactly `probe`'s own indeterminate outcome otherwise, per `memberOf`'s own \"evaluate `operand` first\" rule. A `conditional` then turns that boolean into the number `1`; its `fallback` is never reached, since a definite `probe` always equals itself. (A real implementation may memoise `probe`'s single evaluation rather than running the resolver twice for `operand` and its one `candidates` entry — resolvers are pure functions of their inputs throughout this design, so this is a performance choice, not a correctness one.)\n\n`average` is `sum` divided by `count` over the same `collection`/`filter`, with no `probe` — `sum`'s own `item` already forces every participating item's projected value to resolve, so `average`'s numerator is already indeterminate under exactly the condition a `count` probe exists to detect, with nothing left to duplicate. Nothing new to verify for the empty-collection case either: division's own already-established rule (zero divisor is `domain-error`) is *why* `average` over an empty collection is `domain-error`, since `count` over an empty collection is `0` and `sum(...)/0` already means exactly that.\n\n### Derived values\n\n`coalesce` is never its own evaluated node kind — it is a builder function that assembles an ordinary `conditional`, the same treatment [Derived connectives](#derived-connectives) and [Derived aggregates](#derived-aggregates) already give `xor`/`nand`/`nor`/`implies`/`iff`/`none`/`sum`/`count`/`average`: correctness is inherited from the mechanism it's built from, rather than needing its own independent implementation that could silently drift from it.\n\n```ts\nconst coalesce = (\n  first: ExpressionNode,\n  second: ExpressionNode,\n  ...rest: ExpressionNode[]\n): ExpressionNode =>\n  [first, second, ...rest].reduceRight(\n    (fallback, candidate): ExpressionNode => ({\n      kind: \"conditional\",\n      cases: [{ when: { kind: \"exists\", operand: candidate }, then: candidate }],\n      fallback,\n    }),\n  );\n```\n\nBuilt right-to-left over the full candidate list via `reduceRight`, needing no seed value: `first`/`second` are required arguments (rather than accepting a single `ExpressionNode[]`), which guarantees the list always has at least two elements, so the no-initial-value overload of `reduceRight` never hits an empty array.\n\n**Worked correctness check.** `coalesce`'s only interesting behaviour — whether a given candidate is skipped past or propagated — reduces entirely to what its single `exists` probe reports, per [`exists`](#exists)'s and [`conditional`](#conditional)'s own already-established rules:\n\n| A candidate's own evaluation | `exists(candidate)` | The `conditional` case | `coalesce` evaluates to |\n|---|---|---|---|\n| A definite value | definite `true` | matches | The candidate's value (re-evaluated as `then`, same result) |\n| Indeterminate, `not-found` | definite `false` | does not match | The next candidate (the enclosing `fallback`), evaluated fresh |\n| Indeterminate, `wrong-type` | definite `true` | matches | The candidate's own `wrong-type` result (re-evaluated as `then`) |\n| Indeterminate, `domain-error` | definite `true` | matches | The candidate's own `domain-error` result (re-evaluated as `then`) |\n\nFalling through to the next candidate therefore happens only on `exists`'s own `false` — a genuinely absent value (`not-found`) — never on a candidate that resolved to something merely unusable (`wrong-type`/`domain-error`): `exists` already draws exactly that line, and `coalesce` inherits it unmodified rather than re-deciding it. This is the one behaviour a naive reimplementation is likely to get backwards (treating *any* indeterminate candidate as \"try the next one\"), so it is worth stating explicitly rather than leaving it to be inferred from the composition alone.\n\nA real implementation may memoise a candidate's single evaluation rather than running its resolver twice — once for the `exists` probe, once again for `then` — exactly the same performance caveat [Derived aggregates](#derived-aggregates)'s `presenceOf` already documents for its own `memberOf` probe; resolvers are pure functions of their inputs throughout this design, so this is a performance choice, not a correctness one.\n\n### Defining your own named presets\n\nThis is exactly the same composition-not-new-logic treatment already given to `xor`/`sum`/`coalesce` above — nothing stops application code from defining its own named builder functions the same way, for whatever domain-specific composed queries come up repeatedly in a given consumer's own rules.\n\n```ts\n/** isRecentlyActive(30) reads as \"the item's lastActiveAt instant is within the last 30 days\" — a small, named composition over compare/arithmetic, exactly the same \"assembles ordinary nodes\" treatment sum/coalesce already get above. Built as `now + (-days)` rather than `now - days`: per \"Temporal values\" above, `insta","readmeFilename":"README.md"}