Rules
The Rules block runs decision logic that lives outside your application code: you write rules in GRL, hand the engine facts, and read back what the rules decided. Two things run them:
rules.svc, the service. A product keeps its rules in its ownrules/folder; the service loads them for each tenant, checks every rule when it loads, and answers calls that name a scope. A static scope can read the product’s data and propose writes back.kis rules, the command line, which runs rule files over input files. It also reads documents: the spatial document model below is on the CLI only today.
The model
Section titled “The model”A rule is a condition and an action:
rule ApproveSmallInvoice "auto-approve small invoices" salience 10 { when in.Double("invoice.total", 0.0) < 5000.0 then out.Set("approved", true);}{ "invoice": { "total": 1200.0 } }{ "approved": true }Execution is forward chaining, not a script. Every cycle the engine evaluates the when of every
rule that has not fired yet and fires exactly one rule: the runnable rule with the highest
salience. A rule that fires is retracted for the rest of the execution, so each rule fires at most
once unless it calls agenda.Repeat(). The execution ends when nothing is runnable, a rule calls
Complete(), or it runs out of time or cycles. A later rule sees what earlier rules wrote.
Facts go in as a map; read them with in, by dotted path, with a default for when the fact is
absent: in.Str("invoice.currency", "EUR"). The engine binds these names itself:
| Name | What it is |
|---|---|
in | Reads the facts: in.Has, in.Str, in.Int, in.Double, in.Bool, in.Date, in.Map, in.Rows, by path |
out | The result: out.Set(k, v), and typed reads of what was set |
findings | Severity-graded validation results: findings.Error/Warn/Info/Critical(ruleID, category, message) |
audit | The decision trail: audit.Log(ruleID, msg) |
act | Proposed writes to product data: act |
log | log.Debug/Info/Warn/Error |
strings, num, math, time, date, map, array, to, util, vocab, … | Helpers |
rules.svc refuses a fact named like any of them; under kis rules a fact with such a name is lost
or breaks the helper. See the rules service.
Scopes and data
Section titled “Scopes and data”A call to rules.svc names a scope: a top folder of the product’s rules/, or a static scope of
rules/rules.yaml. A static scope can bound its executions, declare the facts it takes, read
knowledge and records from the product’s data as the caller, and declare the writes its rules may
propose. Then a scope can decide over records (evaluate), over
every record it matches (sweeps), or whenever a record changes
(events). See Scopes and
Rules over data.
Spatial documents
Section titled “Spatial documents”The block also carries a spatial document model: OCR ingest, word merging, line and block
reconstruction, reading order, tables, fields, checkboxes, fuzzy matching and confidence scoring.
Rules reach a document through the bbox namespace, so a rule can ask what is written below this
label rather than parsing text.
Documents run on the CLI: kis rules --bbox <name>=<path> binds an analysed document into the
execution, and rules read it through bbox.Doc().
rules.svc serves no documents today. See Documents.
The rule and document commands (kis rules, kis bbox) run a separately installed plugin,
kis-rules. When it is not installed you get Error: 'rules' is not installed. and nothing
runs. See the CLI.
Continue with
Section titled “Continue with”| Concern | Page |
|---|---|
| One rule set, run end to end | Quickstart |
| Rules, salience, chaining | Writing rules |
| GRL syntax, operators, fact access | The rule language |
| Everything callable from a rule | Functions |
| Rule shapes to copy, and pitfalls | Patterns |
rules/rules.yaml | Scopes |
| Reading and writing product data | Rules over data |
| Proposing writes | act |
| Boxes, words, blocks, lines, reading order | The document model |
| Running rules and documents locally | The CLI |
| Routes, requests, responses | The rules service |
The rules: block, tenants, the system user | Configuration |
| Who may do what | Access |
| Symptoms and fixes | Troubleshooting |
| Error codes and messages | Errors |
Upstream
Section titled “Upstream”The rule language is GRL, from the open-source Grule rule engine. We run a heavily modified and wrapped build of it. The language itself is left largely intact, a rule you have written against upstream GRL will read as familiar, while the enterprise work sits in the layers around it: the namespaces a rule may call, the spatial document surface, tenancy and rule delivery, per-execution isolation, provenance and the audit trail, and the error and termination behaviour described above. Where this documentation and the upstream README disagree, this documentation describes what actually runs.