Rule Cascade
Get started

Rules from an existing project

Find the business rules already in your code, derive the schema rules automatically, have an AI agent draft the rest as proposals, and replace the code checks one at a time.

Most projects already have business rules: in validation libraries, in API schemas, and in if ... throw checks spread over services and front ends. This page turns them into rulesets without a big-bang rewrite. Nothing is changed in your code base until a person accepts a proposal.

Two kinds of work, two kinds of tool:

WorkDone byDeterministic
Find where decisions are made: schemas, validation libraries, hand-written checksrcas analyzeyes: the same code gives the same inventory
Constraints an API schema states (required, enum, length, pattern, range)rcas deriveyes: byte for byte, re-run it when the schema changes
What a check in code actually decides, and why; rules across fields, state transitions, limits that depend on parameters, approvalsan AI agent through rcas mcp, or a personno: so it is always a proposal, checked by rcas check and accepted by a person

Initialize from the code

At the root of the repository:

rcas init --from . --agent all --mcp claude

This creates the project files (new project), writes the inventory to .rcas/analysis.md, and proposes one baseline ruleset per API schema it found. For a payments service with two schemas, the output looks like this:

Analyzing .
412 files, 2 schemas, 37 decisions in code -> .rcas/analysis.md
  proposed derive-transfer                      Transfer (pending)
  proposed derive-customer                      Customer (pending)
2 proposal(s). Review: rcas proposals list

analyze reads TypeScript, JavaScript, Python, Java, Kotlin, Go, C#, Ruby, PHP and Rust, and skips dependencies and build output (node_modules, vendor, dist, target, .venv ...). It recognises Zod, Joi, Yup, class-validator, Pydantic, marshmallow, Django validators, Bean Validation, Spring validators, Go validate: tags, ozzo-validation, FluentValidation, data annotations, Rails, Laravel, the Rust validator crate, rule engines already in use, and hand-written checks that throw or return a validation error. Narrow it with --include / --exclude, or analyze.exclude in rcas.yaml.

Review the derived rules

rcas proposals list
rcas proposals show derive-transfer
rcas proposals accept derive-transfer
rcas check

Derived rulesets are generated files: when the schema changes, derive again (rcas derive api/openapi.yaml --schema Transfer --id acme.payments.transfer-generated -o rules/transfer.generated.ruleset.yaml) and review the difference. Put hand-written rules in a ruleset that extends the derived one.

Let an agent draft the rest

With the MCP server registered, ask your agent, for example in Claude Code:

Use the rcas-analyst agent on src/payments, then have rcas-author propose rules for the
transfer limits and the approval checks it finds. Cite the code each rule replaces.

The agent reads .rcas/analysis.md and the code around each hit, checks its draft with the check tool until it passes, and submits it with propose_ruleset. It cannot write your rulesets: the proposal waits in .rcas/proposals/ with its rationale, the file:line it came from, and any problem check found. You review it with rcas proposals show <id> --diff and accept it, or reject it with a reason. The same works in Codex, Cursor, Copilot, Gemini CLI and Windsurf: see AI coding tools.

Replace the checks in code, one at a time

For each rule that takes over a check in code:

  1. Keep the code check, and evaluate the rule next to it. Log when they disagree.
  2. Add a parity test that feeds the same inputs to both (the rcas-tester agent writes one).
  3. When they agree, delete the code check and enforce the rule's decision instead: on the backend for every state-changing operation, and in the form for immediate feedback.

The playbook covers the engineering rules for this in detail.

Without init

Each step is its own command, so you can run them on any project:

rcas analyze src --format md -o rules-inventory.md   # the inventory, for people
rcas analyze src --format json                       # the same, for tools
rcas derive api/openapi.yaml --schema Order --id acme.orders.generated --propose
rcas derive schemas/order.schema.json --pointer /$defs/Order --id acme.orders.generated --propose

What analyze cannot do: understand what code means. Matching finds where decisions are made; a person or an agent reads the code to learn what each one decides, and whether it is a business rule at all (a check that a configuration file exists is not).

On this page