Reference
Changelog
All notable changes are recorded here. The format follows Keep a Changelog and the project uses Semantic Versioning.
All notable changes are recorded here. The format follows Keep a Changelog and the project uses Semantic Versioning.
[Unreleased]
Changes go into the 1.0.0-alpha.2 section below until that version is tagged.
[1.0.0-alpha.2] - 2026-10-03 (in progress)
The project is now called Rule Cascade. A ruleset is compiled once into a JSON bundle and evaluated identically by Python, TypeScript, Java and Go, by a single-file command for Linux, macOS and Windows, and by a WebAssembly module. The conformance suite has 1899 cases.
Breaking
- Name. Rule Contract became Rule Cascade. The document key is
ruleCascade(wasruleContract), the schema isspec/v1/rule-cascade.schema.json, the OpenAPI extension isx-rule-cascade, the npm packages are@yarlisaisolutions/rule-cascadeand@yarlisaisolutions/rule-cascade-server, the Maven artifact isrule-cascade-coreand the Java package isio.github.yarlisaisolutions.rulecascade. - Specification: checksums. The resolved ruleset has the new members
types,functionsandoperatorsand the renamed key, so the checksum of every ruleset changes. - Specification: findings.
finding.componentis replaced byfinding.location, an object with thepage,screen,sectionandcomponentthe rule's target names. - Specification: patterns.
matchesaccepts only the portable subset of section 4.4.\sand\b, which alpha.1 allowed, are rejected;.matches line breaks;$is the very end of the string; counts, nested counts multiplied and the pattern length are limited to 1000. - Specification: numbers. A JSON number is the IEEE 754 double nearest to what was written, in every runtime. Every number leaving the engine is rounded to 15 significant digits, whether it was computed or passed through. A number beyond the range of a double is refused on the way in and is an evaluation error on the way out.
- Specification: strictness. An object that is not exactly
{var},{op, args}or{fn, args}is not an expression; an unknown root isnull; list indexes are runs of ASCII digits. Dates are written with ASCII digits and nothing after the value, offsets go up to23:59, and the UTC date lies in the years 0001 to 9999.lowerchanges only the ASCII letters. - Specification: evaluation. A state rule applies all of its effects or none. An evaluation request is shape-checked and refused before anything is evaluated.
- Specification: YAML. A ruleset in YAML is read by the YAML 1.2 core schema: unquoted
no,onand2026-10-03are strings. Scalars that YAML 1.1 and 1.2 read differently must be quoted. - Tools.
rulecheck exportandrulecheck corpusare replaced byrulecheck sync.tools/rulecheck.pyis no longer the reference implementation; it is the command-line front end ofpackages/python. - Rule server: a token is required (breaking for deployers). The server refuses to start without
RULE_SERVER_TOKEN: it logs afatalline and exits 1 before loading any rules. SetRULE_SERVER_ALLOW_OPEN=1to serve every endpoint without a token, on a private network only. Embedded,createRuleServerthrows unless it is giventokenorallowOpen: true. The Kubernetes deployment no longer marks the token Secret optional. - Specification: patterns. A group that repeats must not contain an unbounded quantifier
(
(a+)+,(a*){2,}): such a pattern backtracks exponentially and is refused withPATTERN_NOT_PORTABLE.matchesrefuses a subject longer than 10000 code points with an evaluation error. - Specification: nesting depth. An evaluation request whose
data,original,actororctxis nested more than 64 deep (also every root ofenvin theexpressioncommand) is refused withBAD_REQUESTbefore anything is evaluated, and a rule expression or function body nested more than 128 deep fails the load withEXPRESSION_TOO_DEEP. Depth is checked before recursing, so no runtime can overflow its stack. - TypeScript compiler. Schema validation stops at the first problem (Ajv
allErrors: false): reporting every problem took time exponential in expression depth.compilenow reports the first schema problem only.
Added
- Specification: locale fallback. A message is read from the catalog of the requested locale,
then from each shorter prefix of the tag (
fr-CA,fr), then from the default locale. - Specification: one manifest on its own. Every runtime reads a single manifest
(
RuleSet.from_manifest,fromManifest,FromManifest), which is how a native front end receives rules. In the engine protocolloadaccepts amanifest, reportschannelsandmissingOperators, and a channel the ruleset lacks isCHANNEL_UNAVAILABLE. - Runtimes: start-up check for custom operators. Each runtime reports the custom operators a ruleset needs that the host has not registered.
- TypeScript: the manifest client keeps working through an outage of the manifest endpoint by returning the cached manifest and reporting that it is stale.
- Catalog: a server rule protects the credit limit. The read-only state guides the UI; the new validation rule is what stops the change.
- Specification: targets. A rule may target a
page,screenandsectionin addition to a component and fields, or a semantic datatype. Types are declared undertypesand bound to fields inentities.<Name>.fieldTypes; a rule on a type runs once per bound field withvalueandfieldin scope. A request may carry aviewthat narrows the evaluation to one place. - Specification: functions and custom operators.
functionsdeclares reusable expressions, called with{fn, args}, with lexical scope and no recursion.operatorsdeclaresx-*operators that the host supplies; an operator that is missing or fails makes the rule fail closed. - Specification: operators. Fifteen core operators:
between,mod,abs,min,max,round,upper,trim,concat,substring,text,map,filter,typeOfandyearsBetween. The core profile now has 45. - Specification: bundles. A bundle holds the server and the client manifest of a compiled
ruleset (section 7). Manifests gained
fieldTypes,functionsandoperators. There are two conformance levels: evaluator and compiler (section 11). - Specification: engine protocol. JSON Lines on standard input and output with the commands
version,load,manifest,evaluate,expressionandcompile(section 13). - Specification: authoring in YAML (section 12) and the load codes
TYPE_UNKNOWN,SCOPE_INVALID,FUNCTION_UNKNOWN,FUNCTION_ARITY,FUNCTION_RECURSIVE,FUNCTION_REDEFINED,OPERATOR_UNDECLARED,FIELD_TYPE_REBOUND,BUNDLE_UNSUPPORTEDandBUNDLE_INVALID. The recommended scope levels gainedprojectandmodule. - Evaluation API.
GET /rulesets/{rulesetId}/bundle;viewin the request andlocationin a finding; theBundleandViewschemas. The API description is version 1.1.0. - Conformance. 499 expression cases (were 147), 191 load-error cases (84), five fixtures with 66
golden tests (two with 17), a 1000-case evaluation corpus (300), the five published bundles, and
88 engine-protocol cases. Two rulesets exist only for the suite: conflicts, ordering and failing
closed. Three conformance operators (
x-test-reverse,x-test-sum,x-luhn) test the custom-operator mechanism. - Python.
packages/python, therule_cascadepackage: the reference implementation as an installable library, withload,RuleSet.from_bundle,evaluate,evaluate_expressionand the engine protocol (python -m rule_cascade engine). - TypeScript. Bundles (
RuleSet.fromBundle,bundle()), custom operators,viewandfinding.location,requestProblemandRequestError,missingOperators,patternProblem,jsonFinite, theEngineclass and therule-cascade-node enginecommand. - Java. Bundles (
RuleSet.fromBundle,bundle()),CustomOperator,withOperatorsandrequiredOperators,View, and the engine protocol (Engine,Main engine). The schema validator interprets the embedded schema file instead of mirroring it. - Go. A new runtime, package
rulecascade, at both conformance levels, with no dependencies outside the standard library. - Command.
rule-cascade, built from the Go runtime:version,check,compile,manifest,evaluateandengine.packages/go/scripts/build-all.shbuilds static binaries for Linux, macOS and Windows on amd64 and arm64, with checksums. - WebAssembly. The same command as a WASI preview 1 module,
rule-cascade.wasm, andpackages/go/wasi/run.mjsto run it under Node.js. - Rule server. Serves bundles (
GET /rulesets/{id}/bundle, behind the token) and loads precompiled*.bundle.jsonfiles next to source rulesets.createRuleServertakes custom operators and reports the missing ones; the command logs them at start-up and after a reload. - Tools.
rulecheck compilewrites a bundle.rulecheck conformance --engine "<command>"certifies any engine over the engine protocol.rulecheck sync [--check]regenerates the schema copies, fixtures, bundles, expectations, the evaluation corpus and the example client manifest.rulecheck checkreportsYAML_NOT_PORTABLEandNUMBER_NOT_PORTABLE. - Tools: JSON Logic.
rulecheck jsonlogic import|exportconverts expressions in both directions and refuses what it cannot convert faithfully (docs/json-logic.md). - Tools: OpenAPI.
rulecheck deriveturns the constraints of an OpenAPI component schema into a baseline ruleset with stable finding codes (docs/openapi.md). - Examples. A rule catalog by data type and severity (
examples/catalog, 34 rules, 25 golden tests); two derived rulesets with their tests (examples/derived); the same two evaluations from Python, Node.js, Ruby, PHP, Java, shell, Rust, C# and PowerShell over the engine protocol, and in process with the WebAssembly module from Node.js and Python (examples/engine-clients). The Spring Boot example can start from a bundle and registers a custom operator. - Bindings. The rule-draft response format lists the 45 core operators, function calls, places
and types; the
evaluate_rulestool accepts aview.bindings/README.mdexplains both files. - CI. Every runtime is built and certified on Linux, Windows and macOS, in process and over the
engine protocol. A job cross-compiles the command, certifies the WebAssembly module, runs the
engine clients and uploads the binaries. The tools have unit tests (
tools/tests). - Documentation.
docs/authoring-guidelines.md, ADRs 0005 to 0009,packages/python/README.md. - Examples: services, batch and agents.
examples/backend-node(node:http) andexamples/backend-go(net/http) enforce the payments contract the way the Spring Boot example does: evaluate, refuse with422problem details, persist, run commands once per idempotency key, and serve the client manifest with anETag.examples/batchstreams a CSV or JSON Lines file through any engine over the engine protocol, one decision per line.examples/agent-toolsruns the tools ofbindings/llm-tools.jsonagainst the rule server, with the actor taken from the session; its README maps the same tools onto MCP. - Tests. The React hook and the manifest client of the TypeScript runtime have their own tests.
The container smoke test (
packages/server/test/smoke-image.sh) also checks that the image fails closed without a token, that a broken reload is refused while the previous rules keep serving, and thatSIGTERMdrains. - Cross-runtime version check.
tools/check_versions.py(run bymake contractand the CIcontractjob) fails unless every runtime declares the same version: the TypeScript and serverpackage.json, the Javapom.xml, Go'sversion.go, and Python'spyproject.tomland__init__.py(PEP 4401.0.0a2is read as1.0.0-alpha.2). - CI. One job per new example on Linux, and a job that runs the Go runtime and the Go example on
Go 1.22, the minimum
go.moddeclares, withGOTOOLCHAIN=localso no newer toolchain is used.
Changed
- Specification. Canonical numbers are exact.
abskeeps 34 digits. Members of a protocol request are checked before a ruleset is looked up; optional members may benull. - TypeScript, Java. Both runtimes implement the evaluator and the compiler level and are at
version
1.0.0-alpha.2. - Rule server.
POST /evaluationschecks the body with the shape check every runtime applies and names the problem in its400answer. A ruleset that came from a bundle is listed with its id, version and checksum only.If-None-Matchis compared as RFC 9110 says: a list of entity tags, weak or strong, or*. A path with malformed percent-encoding is400, not500. A body over the limit is413without being read to the end. - Tools.
tools/lint_specs.pyalso checks that every pattern in the schema is portable, that the operator list inbindings/matches the schema, and that all generated files are current. - Makefile.
make verifyalso runs the Python package tests, the Go runtime, the release build, every engine over the protocol and the engine clients. - Documentation.
docs/architecture.md,docs/naming-conventions.md, ADRs 0001 to 0003,CONTRIBUTING.md,SECURITY.mdand the deployment notes describe the current design. The README has a table of supported versions (declared minimum, tested in CI, highest observed; no declared maximum) and says what is not verified: the Kubernetes manifests have never been applied, the WebAssembly module has not run in a browser, and thex-rule-cascadebinding is checked at lint time only. The claim that the runtimes agree beyond the suite now says which part can be repeated from the repository.
[1.0.0-alpha.1]
Added
- Specification 1.0 (draft): ruleset schema, normative semantics, evaluation API.
- Conformance suite: expression cases, load-error cases, fixture checksums and client manifests, golden tests, and a 300-case evaluation corpus.
- Reference implementation and linter in Python (
tools/rulecheck.py). - TypeScript runtime for browsers and Node.js, with a React hook and a manifest client.
- Java runtime with no dependencies.
- Rule server: stateless HTTP service with health probes, graceful shutdown and safe reload.
- Examples: organisation and feature rulesets, an OpenAPI binding, a React form, a Spring Boot API.
- Deployment: Dockerfile and Kubernetes manifests for the rule server.
- Bindings for OpenAI function tools and structured rule drafting.
Rendered from CHANGELOG.md in the repository. Edit it there.