@criterionx/core 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +119 -46
- package/package.json +11 -5
package/README.md
CHANGED
|
@@ -1,70 +1,143 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="criterion.jpg" alt="Criterion" width="100%" />
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
<p align="center">
|
|
6
|
+
<strong>A universal, deterministic, and explainable decision engine for business-critical systems.</strong>
|
|
7
|
+
</p>
|
|
4
8
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
<p align="center">
|
|
10
|
+
<a href="https://www.npmjs.com/package/@criterionx/core"><img src="https://img.shields.io/npm/v/@criterionx/core.svg" alt="npm version"></a>
|
|
11
|
+
<a href="https://github.com/tomymaritano/criterionx/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/@criterionx/core.svg" alt="license"></a>
|
|
12
|
+
<a href="https://tomymaritano.github.io/criterionx/"><img src="https://img.shields.io/badge/docs-vitepress-brightgreen.svg" alt="docs"></a>
|
|
13
|
+
</p>
|
|
9
14
|
|
|
10
|
-
|
|
15
|
+
---
|
|
11
16
|
|
|
12
|
-
## What Criterion
|
|
17
|
+
## What is Criterion?
|
|
13
18
|
|
|
14
|
-
Criterion
|
|
15
|
-
It runs decisions against a provided **Context**.
|
|
19
|
+
Criterion helps you encode business decisions as **pure, testable functions** with built-in validation and explainability.
|
|
16
20
|
|
|
17
|
-
|
|
18
|
-
- inputs (schema)
|
|
19
|
-
- outputs (schema)
|
|
20
|
-
- rules (ordered)
|
|
21
|
-
- explanations (trace)
|
|
21
|
+
Instead of scattering `if/else` statements across your codebase, you define decisions declaratively:
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
- **"Should this transaction be flagged as high-risk?"**
|
|
24
|
+
- **"Is this user eligible for a premium tier?"**
|
|
25
|
+
- **"What discount applies to this order?"**
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
- a workflow/BPMN engine
|
|
27
|
-
- an enterprise rules platform
|
|
28
|
-
- a plugin marketplace
|
|
29
|
-
- a data pipeline
|
|
30
|
-
- a forecasting system
|
|
27
|
+
Every decision returns not just a result, but a complete explanation of *why* that result was reached — perfect for audits, debugging, and compliance.
|
|
31
28
|
|
|
32
|
-
|
|
29
|
+
## Installation
|
|
33
30
|
|
|
34
|
-
|
|
31
|
+
```bash
|
|
32
|
+
npm install @criterionx/core zod
|
|
33
|
+
```
|
|
35
34
|
|
|
36
|
-
|
|
35
|
+
## Quick Start
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { Engine, defineDecision } from "@criterionx/core";
|
|
39
|
+
import { z } from "zod";
|
|
40
|
+
|
|
41
|
+
const riskDecision = defineDecision({
|
|
42
|
+
id: "transaction-risk",
|
|
43
|
+
version: "1.0.0",
|
|
44
|
+
inputSchema: z.object({ amount: z.number() }),
|
|
45
|
+
outputSchema: z.object({ risk: z.enum(["HIGH", "MEDIUM", "LOW"]) }),
|
|
46
|
+
profileSchema: z.object({ threshold: z.number() }),
|
|
47
|
+
rules: [
|
|
48
|
+
{
|
|
49
|
+
id: "high-risk",
|
|
50
|
+
when: (input, profile) => input.amount > profile.threshold,
|
|
51
|
+
emit: () => ({ risk: "HIGH" }),
|
|
52
|
+
explain: (input, profile) => `Amount ${input.amount} > ${profile.threshold}`,
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: "low-risk",
|
|
56
|
+
when: () => true,
|
|
57
|
+
emit: () => ({ risk: "LOW" }),
|
|
58
|
+
explain: () => "Amount within acceptable range",
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const engine = new Engine();
|
|
64
|
+
const result = engine.run(
|
|
65
|
+
riskDecision,
|
|
66
|
+
{ amount: 15000 },
|
|
67
|
+
{ profile: { threshold: 10000 } }
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
console.log(result.data); // { risk: "HIGH" }
|
|
71
|
+
console.log(engine.explain(result));
|
|
72
|
+
// Decision: transaction-risk v1.0.0
|
|
73
|
+
// Status: OK
|
|
74
|
+
// Matched: high-risk
|
|
75
|
+
// Reason: Amount 15000 > 10000
|
|
76
|
+
```
|
|
37
77
|
|
|
38
|
-
|
|
78
|
+
## Features
|
|
39
79
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
80
|
+
- **Pure & Deterministic** — Same input always produces the same output
|
|
81
|
+
- **Fully Explainable** — Every decision includes a complete audit trail
|
|
82
|
+
- **Contract-First** — Zod schemas validate inputs, outputs, and profiles
|
|
83
|
+
- **Profile-Driven** — Parameterize decisions by region, tier, or environment
|
|
84
|
+
- **Zero Side Effects** — No I/O, no database, no external calls
|
|
85
|
+
- **Testable by Design** — Pure functions are trivial to test
|
|
86
|
+
|
|
87
|
+
## Documentation
|
|
88
|
+
|
|
89
|
+
Full documentation available at **[tomymaritano.github.io/criterion](https://tomymaritano.github.io/criterionx/)**
|
|
90
|
+
|
|
91
|
+
- [Getting Started](https://tomymaritano.github.io/criterionx/guide/getting-started)
|
|
92
|
+
- [Core Concepts](https://tomymaritano.github.io/criterionx/guide/core-concepts)
|
|
93
|
+
- [API Reference](https://tomymaritano.github.io/criterionx/api/engine)
|
|
94
|
+
- [Examples](https://tomymaritano.github.io/criterionx/examples/currency-risk)
|
|
95
|
+
|
|
96
|
+
## Core Concepts
|
|
43
97
|
|
|
44
|
-
|
|
98
|
+
### Decisions
|
|
45
99
|
|
|
46
|
-
|
|
100
|
+
A decision is a unit of business logic with:
|
|
101
|
+
- **Input schema** — What data is required
|
|
102
|
+
- **Output schema** — What the decision returns
|
|
103
|
+
- **Profile schema** — What can be parameterized
|
|
104
|
+
- **Rules** — The evaluation logic
|
|
47
105
|
|
|
48
|
-
|
|
49
|
-
- `examples/` — decision specs in declarative formats (no code required)
|
|
50
|
-
- `diagrams/` — Mermaid diagrams for architecture (optional early)
|
|
51
|
-
- `src/` — future minimal TS implementation (later)
|
|
106
|
+
### Rules
|
|
52
107
|
|
|
53
|
-
|
|
108
|
+
Rules are evaluated in order. First match wins:
|
|
54
109
|
|
|
55
|
-
|
|
56
|
-
|
|
110
|
+
```typescript
|
|
111
|
+
rules: [
|
|
112
|
+
{ id: "rule-1", when: (i) => i.x > 100, emit: ..., explain: ... },
|
|
113
|
+
{ id: "rule-2", when: (i) => i.x > 50, emit: ..., explain: ... },
|
|
114
|
+
{ id: "default", when: () => true, emit: ..., explain: ... },
|
|
115
|
+
]
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Profiles
|
|
119
|
+
|
|
120
|
+
Profiles parameterize decisions without changing logic:
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
// Same decision, different thresholds
|
|
124
|
+
engine.run(decision, input, { profile: usProfile });
|
|
125
|
+
engine.run(decision, input, { profile: euProfile });
|
|
126
|
+
```
|
|
57
127
|
|
|
58
|
-
|
|
59
|
-
- `examples/eligibility/user-tier-eligibility/` — user tier eligibility decision
|
|
128
|
+
## What Criterion Is NOT
|
|
60
129
|
|
|
61
|
-
|
|
130
|
+
- A workflow/BPMN engine
|
|
131
|
+
- A machine learning framework
|
|
132
|
+
- A data pipeline
|
|
133
|
+
- A plugin marketplace
|
|
62
134
|
|
|
63
|
-
|
|
64
|
-
- `docs/04-decision-profiles.md`
|
|
65
|
-
- `examples/finance/currency-exposure-risk/decision.xml`
|
|
66
|
-
- `examples/eligibility/user-tier-eligibility/decision.xml`
|
|
135
|
+
Criterion is a **micro engine**: small core, strict boundaries.
|
|
67
136
|
|
|
68
137
|
## License
|
|
69
138
|
|
|
70
|
-
MIT
|
|
139
|
+
[MIT](LICENSE)
|
|
140
|
+
|
|
141
|
+
## Author
|
|
142
|
+
|
|
143
|
+
**Tomas Maritano** — [@tomymaritano](https://github.com/tomymaritano)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@criterionx/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Universal decision engine for business-critical decisions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -22,7 +22,11 @@
|
|
|
22
22
|
"test:watch": "vitest",
|
|
23
23
|
"test:coverage": "vitest run --coverage",
|
|
24
24
|
"typecheck": "tsc --noEmit",
|
|
25
|
-
"
|
|
25
|
+
"benchmark": "tsx benchmarks/run.ts",
|
|
26
|
+
"prepublishOnly": "npm run build",
|
|
27
|
+
"docs:dev": "vitepress dev docs",
|
|
28
|
+
"docs:build": "vitepress build docs",
|
|
29
|
+
"docs:preview": "vitepress preview docs"
|
|
26
30
|
},
|
|
27
31
|
"keywords": [
|
|
28
32
|
"decision-engine",
|
|
@@ -42,16 +46,18 @@
|
|
|
42
46
|
"license": "MIT",
|
|
43
47
|
"repository": {
|
|
44
48
|
"type": "git",
|
|
45
|
-
"url": "https://github.com/tomymaritano/
|
|
49
|
+
"url": "https://github.com/tomymaritano/criterionx.git"
|
|
46
50
|
},
|
|
47
51
|
"bugs": {
|
|
48
|
-
"url": "https://github.com/tomymaritano/
|
|
52
|
+
"url": "https://github.com/tomymaritano/criterionx/issues"
|
|
49
53
|
},
|
|
50
|
-
"homepage": "https://github.com/tomymaritano/
|
|
54
|
+
"homepage": "https://github.com/tomymaritano/criterionx#readme",
|
|
51
55
|
"devDependencies": {
|
|
52
56
|
"@vitest/coverage-v8": "^2.0.0",
|
|
53
57
|
"tsup": "^8.0.0",
|
|
58
|
+
"tsx": "^4.7.0",
|
|
54
59
|
"typescript": "^5.3.0",
|
|
60
|
+
"vitepress": "^1.6.4",
|
|
55
61
|
"vitest": "^2.0.0",
|
|
56
62
|
"zod": "^3.22.0"
|
|
57
63
|
},
|