{"id":35267868,"url":"https://github.com/tomymaritano/criterionx","last_synced_at":"2026-01-13T21:49:05.045Z","repository":{"id":330926973,"uuid":"1124450320","full_name":"tomymaritano/criterionx","owner":"tomymaritano","description":"A universal, deterministic, and explainable decision engine for business-critical systems.","archived":false,"fork":false,"pushed_at":"2025-12-30T06:36:18.000Z","size":595,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-01T00:40:14.833Z","etag":null,"topics":["audit","business-logic","compl","decision-engine","deterministic","explainable-ai","rules-engine","typescript","validation","zod"],"latest_commit_sha":null,"homepage":"https://tomymaritano.github.io/criterionx/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tomymaritano.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["tomymaritano"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"lfx_crowdfunding":null,"polar":null,"buy_me_a_coffee":null,"thanks_dev":null,"custom":null}},"created_at":"2025-12-29T03:34:15.000Z","updated_at":"2025-12-30T06:36:23.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/tomymaritano/criterionx","commit_stats":null,"previous_names":["tomymaritano/criterion"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/tomymaritano/criterionx","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomymaritano%2Fcriterionx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomymaritano%2Fcriterionx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomymaritano%2Fcriterionx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomymaritano%2Fcriterionx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tomymaritano","download_url":"https://codeload.github.com/tomymaritano/criterionx/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomymaritano%2Fcriterionx/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28401077,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-13T14:36:09.778Z","status":"ssl_error","status_checked_at":"2026-01-13T14:35:19.697Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["audit","business-logic","compl","decision-engine","deterministic","explainable-ai","rules-engine","typescript","validation","zod"],"created_at":"2025-12-30T11:08:36.550Z","updated_at":"2026-01-13T21:49:05.040Z","avatar_url":"https://github.com/tomymaritano.png","language":"TypeScript","funding_links":["https://github.com/sponsors/tomymaritano"],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"criterion.jpg\" alt=\"Criterion\" width=\"100%\" /\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eA universal, deterministic, and explainable decision engine for business-critical systems.\u003c/strong\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@criterionx/core\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/@criterionx/core.svg?label=@criterionx/core\" alt=\"core version\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@criterionx/server\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/@criterionx/server.svg?label=@criterionx/server\" alt=\"server version\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@criterionx/react\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/@criterionx/react.svg?label=@criterionx/react\" alt=\"react version\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/tomymaritano/criterionx/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/npm/l/@criterionx/core.svg\" alt=\"license\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://tomymaritano.github.io/criterionx/\"\u003e\u003cimg src=\"https://img.shields.io/badge/docs-vitepress-brightgreen.svg\" alt=\"docs\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n## What is Criterion?\n\nCriterion helps you encode business decisions as **pure, testable functions** with built-in validation and explainability.\n\nInstead of scattering `if/else` statements across your codebase, you define decisions declaratively:\n\n- **\"Should this transaction be flagged as high-risk?\"**\n- **\"Is this user eligible for a premium tier?\"**\n- **\"What discount applies to this order?\"**\n\nEvery decision returns not just a result, but a complete explanation of *why* that result was reached — perfect for audits, debugging, and compliance.\n\n## Packages\n\n### Core\n\n| Package | Description |\n|---------|-------------|\n| [@criterionx/core](./packages/core) | Pure decision engine — no I/O, no side effects |\n| [@criterionx/server](./packages/server) | HTTP server with auto-generated docs, rate limiting |\n\n### Integrations\n\n| Package | Description |\n|---------|-------------|\n| [@criterionx/react](./packages/react) | React hooks (`useDecision`, `CriterionProvider`) |\n| [@criterionx/express](./packages/express) | Express \u0026 Fastify middleware |\n| [@criterionx/trpc](./packages/trpc) | tRPC procedures with full type safety |\n\n### Tools\n\n| Package | Description |\n|---------|-------------|\n| [@criterionx/opentelemetry](./packages/opentelemetry) | Tracing \u0026 metrics instrumentation |\n| [@criterionx/generators](./packages/generators) | Generate decisions from declarative specs |\n| [@criterionx/testing](./packages/testing) | Test utilities and mocks |\n| [@criterionx/devtools](./packages/devtools) | Debug and inspect decisions |\n| [@criterionx/cli](./packages/cli) | Command-line interface |\n| [@criterionx/mcp](./packages/mcp) | Model Context Protocol server for LLMs |\n\n## Installation\n\n```bash\n# Core engine only\nnpm install @criterionx/core zod\n\n# With HTTP server\nnpm install @criterionx/server zod\n\n# React integration\nnpm install @criterionx/react @criterionx/core\n\n# Express/Fastify middleware\nnpm install @criterionx/express @criterionx/core\n\n# tRPC integration\nnpm install @criterionx/trpc @criterionx/core @trpc/server\n```\n\n## Quick Start\n\n### Using the Core Engine\n\n```typescript\nimport { Engine, defineDecision } from \"@criterionx/core\";\nimport { z } from \"zod\";\n\nconst riskDecision = defineDecision({\n  id: \"transaction-risk\",\n  version: \"1.0.0\",\n  inputSchema: z.object({ amount: z.number() }),\n  outputSchema: z.object({ risk: z.enum([\"HIGH\", \"MEDIUM\", \"LOW\"]) }),\n  profileSchema: z.object({ threshold: z.number() }),\n  rules: [\n    {\n      id: \"high-risk\",\n      when: (input, profile) =\u003e input.amount \u003e profile.threshold,\n      emit: () =\u003e ({ risk: \"HIGH\" }),\n      explain: (input, profile) =\u003e `Amount ${input.amount} \u003e ${profile.threshold}`,\n    },\n    {\n      id: \"low-risk\",\n      when: () =\u003e true,\n      emit: () =\u003e ({ risk: \"LOW\" }),\n      explain: () =\u003e \"Amount within acceptable range\",\n    },\n  ],\n});\n\nconst engine = new Engine();\nconst result = engine.run(\n  riskDecision,\n  { amount: 15000 },\n  { profile: { threshold: 10000 } }\n);\n\nconsole.log(result.data);  // { risk: \"HIGH\" }\nconsole.log(engine.explain(result));\n// Decision: transaction-risk v1.0.0\n// Status: OK\n// Matched: high-risk\n// Reason: Amount 15000 \u003e 10000\n```\n\n### Using React Hooks\n\n```tsx\nimport { CriterionProvider, useDecision } from \"@criterionx/react\";\n\nfunction App() {\n  return (\n    \u003cCriterionProvider\n      decisions={[riskDecision]}\n      profiles={{ \"transaction-risk\": { threshold: 10000 } }}\n    \u003e\n      \u003cRiskChecker /\u003e\n    \u003c/CriterionProvider\u003e\n  );\n}\n\nfunction RiskChecker() {\n  const { result, evaluate } = useDecision(\"transaction-risk\");\n\n  return (\n    \u003cbutton onClick={() =\u003e evaluate({ amount: 15000 })}\u003e\n      Check Risk: {result?.data?.risk ?? \"—\"}\n    \u003c/button\u003e\n  );\n}\n```\n\n### Using Express Middleware\n\n```typescript\nimport express from \"express\";\nimport { createDecisionRouter } from \"@criterionx/express\";\n\nconst app = express();\napp.use(express.json());\napp.use(\"/api/decisions\", createDecisionRouter({\n  decisions: [riskDecision],\n  profiles: { \"transaction-risk\": { threshold: 10000 } },\n}));\n\napp.listen(3000);\n// POST /api/decisions/transaction-risk\n```\n\n### Using the HTTP Server\n\n```typescript\nimport { createServer } from \"@criterionx/server\";\n\nconst server = createServer({\n  decisions: [riskDecision],\n  profiles: { \"transaction-risk\": { threshold: 10000 } },\n});\n\nserver.listen(3000);\n// Server running at http://localhost:3000\n// Docs at http://localhost:3000/docs\n```\n\n## Features\n\n- **Pure \u0026 Deterministic** — Same input always produces the same output\n- **Fully Explainable** — Every decision includes a complete audit trail\n- **Contract-First** — Zod schemas validate inputs, outputs, and profiles\n- **Profile-Driven** — Parameterize decisions by region, tier, or environment\n- **Zero Side Effects** — No I/O, no database, no external calls\n- **Testable by Design** — Pure functions are trivial to test\n- **Framework Agnostic** — Works with React, Express, Fastify, tRPC, and more\n- **Observable** — OpenTelemetry integration for tracing and metrics\n\n## Documentation\n\nFull documentation available at **[tomymaritano.github.io/criterionx](https://tomymaritano.github.io/criterionx/)**\n\n- [Getting Started](https://tomymaritano.github.io/criterionx/guide/getting-started)\n- [Core Concepts](https://tomymaritano.github.io/criterionx/guide/core-concepts)\n- [HTTP Server](https://tomymaritano.github.io/criterionx/guide/server)\n- [API Reference](https://tomymaritano.github.io/criterionx/api/engine)\n- [React Integration](https://tomymaritano.github.io/criterionx/api/react)\n- [Express/Fastify](https://tomymaritano.github.io/criterionx/api/express)\n- [Examples](https://tomymaritano.github.io/criterionx/examples/currency-risk)\n\n## Core Concepts\n\n### Decisions\n\nA decision is a unit of business logic with:\n- **Input schema** — What data is required\n- **Output schema** — What the decision returns\n- **Profile schema** — What can be parameterized\n- **Rules** — The evaluation logic\n\n### Rules\n\nRules are evaluated in order. First match wins:\n\n```typescript\nrules: [\n  { id: \"rule-1\", when: (i) =\u003e i.x \u003e 100, emit: ..., explain: ... },\n  { id: \"rule-2\", when: (i) =\u003e i.x \u003e 50, emit: ..., explain: ... },\n  { id: \"default\", when: () =\u003e true, emit: ..., explain: ... },\n]\n```\n\n### Profiles\n\nProfiles parameterize decisions without changing logic:\n\n```typescript\n// Same decision, different thresholds\nengine.run(decision, input, { profile: usProfile });\nengine.run(decision, input, { profile: euProfile });\n```\n\n## What Criterion Is NOT\n\n- A workflow/BPMN engine\n- A machine learning framework\n- A data pipeline\n- A plugin marketplace\n\nCriterion is a **micro engine**: small core, strict boundaries.\n\n## License\n\n[MIT](LICENSE)\n\n## Author\n\n**Tomas Maritano** — [@tomymaritano](https://github.com/tomymaritano)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomymaritano%2Fcriterionx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftomymaritano%2Fcriterionx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomymaritano%2Fcriterionx/lists"}