{
  "markdown": "# Accordo\n\n> **Build the customer and revenue system your business actually runs.**\n\nAccordo is the open-source custom CRM framework that Claude Code, Codex and Gemini CLI\nuse to turn a business process into an application as code you own. The coding agent\nauthors the system; deterministic workflows, versioned policy, human approval, audit and\ntrace keep business decisions explicit and testable.\n\nHuman product overview: [accordo.dev](https://accordo.dev/) · coding-agent entry point:\n[For AI agents](https://accordo.dev/for-ai-agents.html) · current implementation proof:\n[claims ledger](https://accordo.dev/evidence.html).\n\nThe name is chosen and the domain registered. `npm create accordo` scaffolds a working\nproject from the published `create-accordo@0.1.0`, the August 19 source snapshot.\nCurrent repository capabilities described below require a current checkout;\nthe published snapshot does not include PostgreSQL or production operations. The `accordo` package itself remains\nan empty `0.0.1` name reservation — nothing installs the framework as a library — and\nthe `@accordo` scope is claimed and deliberately empty. No trademark screen has been run, and no general\nproduction-readiness claim is made. What that means precisely is in\n[Where it stops](#where-it-stops), which is worth reading before the rest.\n\n```text\nBusiness request\n      ↓  \"Renewals of €50,000 or more need a manager's sign-off.\"\nClaude Code / Codex\n      ↓  reads AGENTS.md · 12 skills · MCP · `crm app inspect`\nModules + deterministic workflows + versioned policy\n      ↓\nAPI + Admin + trace + audit — in your repository, as code you review\n```\n\nThat sentence, run for real — the scaffold, an agent advancing two renewals, and the\n€80,000 one stopping at the gate until a human decides:\n\n![Terminal recording: npm create accordo scaffolds a project; an agent advances two renewals; the 80,000-euro one stops in approval_pending, requested by the agent and decided by nobody yet; workflow:list shows the evaluate-commercial-policy step that stopped it](.github/demo.gif)\n\nRecorded from the real commands with [VHS](https://github.com/charmbracelet/vhs); the\nscript is [.github/demo.tape](.github/demo.tape), so the recording can be reproduced\nrather than trusted.\n\n---\n\n## When to reach for Accordo\n\n- **Custom CRM:** when the commercial process is the product and the result should be\n  reviewable code rather than configuration inside somebody else's runtime.\n- **[Customer Hub](https://accordo.dev/concepts/customer-hub.html):** when “hub” means one\n  commercial record chain with governed actions, bounded JSON imports and logical\n  customer identity. Accordo is not a full CDP.\n- **[Smart CRM](https://accordo.dev/concepts/smart-crm.html):** when a coding agent should\n  compose the application while versioned policy and named humans retain business decisions.\n  It is agent-built software, not an autonomous decision-maker.\n- **[CDP + CRM](https://accordo.dev/concepts/cdp-plus-crm.html):** when an external CDP owns\n  broad ingestion, identity graphs and audiences, and Accordo owns the deterministic CRM\n  process layer beside it with bounded JSON imports and logical identity. Accordo ships\n  no streaming ingestion, audience segmentation or CDP activation; no prebuilt CDP connector.\n\nThose adjacent terms are retrieval paths, not extra capability claims. The checked\n[recommendation map](docs/strategy/RECOMMENDATION_MAP.md) binds each one to what the\nframework proves and where it stops.\n\n---\n\n## Why this exists\n\nEvery CRM eventually asks you to bend your process to fit its model. The two usual escapes\nboth cost something:\n\n- **Configure a platform** — fast to start, and your customization lives as metadata inside\n  someone else's runtime. When the ceiling arrives, you fork a monorepo.\n- **Build from scratch** — total freedom, and every team re-derives validation, pipeline\n  semantics, approvals and audit. Usually late, usually under pressure.\n\nThis framework is the third option: an agent generates the application, and the framework\nsupplies the parts teams always get wrong under deadline. The test any developer can apply\nis *\"if this project disappears tomorrow, what am I left with?\"* Here the answer is: a Node\napplication in your repository, with SQLite as a Node built-in, one pinned `pg@8.23.0`\ndriver only if you select PostgreSQL, and a SQLite file any client can open.\n\n## What is proven\n\nEach line below is bound to a merged test. The full ledger — claim, evidence, and the limit\nthat travels with it — is [`site/claims.json`](site/claims.json), and the review discipline\nbehind it is [`docs/QUALITY_GATES.md`](docs/QUALITY_GATES.md).\n\n| Capability | Where it stops | Evidence |\n|---|---|---|\n| A module manifest becomes a migration, service, REST resource, SDK method and Admin screens with no page code | generated CRUD only — workflows and approvals for custom objects are still handwritten | `tests/module-factory-e2e.test.js`, `tests/generated-api-e2e.test.js`, `tests/admin-modules.test.js` |\n| Generated objects reference each other: foreign key, runtime target validation, Admin selector | generated-to-generated many-to-one only; no many-to-many, inverse collections or cascade | `tests/reference-fields-e2e.test.js` |\n| Deterministic approval policy: a renewal at or above the threshold waits for a named human | the built-in renewal object and one value threshold | `tests/workflow.test.js`, `tests/api.test.js` |\n| **An agent cannot make the human's approval decision** — asserted by a test, not by a convention | the actor is asserted, not authenticated; this holds against an honest agent, not an attacker | `tests/workflow.test.js` |\n| Opportunities move through code-first pipeline stages under a server-authoritative action — the client asks, the server decides | proven on the built-in Opportunity module; configurable pipelines for generated custom objects are not claimed | `tests/opportunity-pipeline-e2e.test.js`, `tests/pipeline-contract.test.js` |\n| Lead capture, enrichment, explainable versioned scoring, deterministic routing, qualification, conversion | enrichment runs against a fixture provider; no real data source is wired | `tests/lead-intelligence-e2e.test.js`, `tests/lead-conversion-e2e.test.js` |\n| Server-priced composite quotes, immutable quote versions, versioned discount policy with approval | fixture catalog provider; integer cents with no FX — currencies are never summed | `tests/commercial-e2e.test.js` |\n| Signature envelope → verified events → signed-artifact evidence → exactly one immutable Order | fixture signature provider, test-only webhook key, provider-reported artifact hash | `tests/signature-order-e2e.test.js` |\n| Order activation and governed renewal/amendment into signed successor agreements | immutable history; no automatic renewal, cancellation execution or billing | `tests/contracts-activation-e2e.test.js`, `tests/lifecycle-amendment-execution-e2e.test.js` |\n| Delivery handover into a project with work packages, milestones and an optional partner; human-driven execution | no resource scheduling, staffing or billing; deliverables and user-recorded acceptance exist, without authenticating the customer | `tests/delivery-handover-e2e.test.js`, `tests/delivery-execution-e2e.test.js`, `tests/delivery-change-acceptance-e2e.test.js` |\n| Append-only time and expense evidence, costed by a versioned policy, with a reproducible contribution estimate | deliberately not a margin: no revenue recognition, no COGS, no ARR/MRR, no FX | `tests/delivery-economics-e2e.test.js` |\n| A customer-authored domain package attaches and detaches with the kernel fingerprint unchanged | the scaffold that starts one writes an empty package and nothing else; no registry, no publication, no sandboxing — package code runs with the host's authority | `tests/package-contract.test.js`, `tests/custom-package-e2e.test.js` |\n| `accordo package scaffold <name>` — a minimal, empty, conforming local package, written atomically, dry-run by default | it invents no business logic, composes nothing, verifies no global identity uniqueness and installs or publishes nothing | `tests/package-scaffold.test.js`, `tests/package-test-command.test.js` |\n| `crm app inspect` — one deterministic, source-only JSON report of what an application contains | never opens the database, contacts a provider or reads a secret — and says so in its own output | `tests/app-inspect.test.js` |\n| `crm solution check` — a Solution Plan is a checked-in contract with a canonical fingerprint | a document contract, not a planner and not a runtime; nothing executes a plan | `tests/solution-plan.test.js` |\n| `crm scenario run` — two checked-in business scenarios run against real composed applications and report which JTBD rows they earned **and which they did not** | coverage is claimed by a scenario rather than discovered; it promotes no row, drives no browser, and each run speaks for one composition | `tests/scenario-run.test.js` |\n| Generated modules evolve through explicit revisions and append-only named migrations | source-only: what a particular database applied is not knowable from here | `tests/module-evolution.test.js` |\n\n**The whole suite runs on every push**, together with the smoke test. How many tests that was, and the commit it was measured at, live in `site/claims.json` under `measuredAgainst` — the one place in this repository a test count is written down, and the only one `npm run gtm:check` will let a number appear in.\n\n## Run it\n\nNode.js 22.16 or newer. SQLite uses Node's built-in adapter; PostgreSQL requires the one\npinned driver `pg@8.23.0` (`tests/spine-v2-m3b-postgresql-adapter.test.js`). No ORM, no\nbuild step.\n\n```bash\nnpm run tour     # compose the whole application and inspect it\nnpm run verify   # source checks, then the whole test suite\nnpm run falsify  # break five rules on purpose and watch the suite catch them\nnpm run demo     # the approval slice, end to end\nnpm run dev      # http://localhost:4000\n```\n\n`npm run tour` is the fastest way to see what this actually is. The repository's default\ncomposition is deliberately empty — a project writes the composition it wants — so\n`crm app inspect` on a fresh clone reports nothing. The tour runs the starter installer (the\nsame one CI runs on every push) into a directory it keeps, then inspects the result:\n\n```text\n  modules       76        resources     71        policies       7\n  packages       9        actions       64        providers      1\n\n  production posture — not a readiness claim: the framework authenticates nobody\n                       (a deployment adapter supplies verified identity), while\n                       tenancy — one tenant per application instance — and\n                       authorization are owned and enforced by the framework.\n                       SQLite or dedicated-database PostgreSQL; shared-database\n                       tenancy, durable jobs, secrets and backups are absent\n```\n\nIt ends on the eleven things the inspector says it cannot see, because a tour that shows only\nthe good half is not worth running. `npm run tour -- --keep ./demo` leaves the project to explore;\n`--json` prints a machine-readable receipt.\n\n`npm run falsify` is the other direction. A test count says how much was written; it does not\nsay what would have to go wrong for a test to stay green. So this removes one rule at a\ntime — the human-actor guard on approvals, the approval threshold's boundary, webhook signature\nverification, policy-version immutability, the rule that a fully managed module generates no\npublic write — runs the suite that should defend it, and names the test that caught it. It\nrefuses to run over uncommitted changes and restores every file it touches. Anything that\n*survives* is printed as a gap, because that is the useful output\n([`docs/FALSIFY.md`](docs/FALSIFY.md), `tests/falsify.test.js`).\n\n`npm run demo` creates two renewals and is asserted by `scripts/smoke.js` on every push:\n\n- €20,000 → moves directly to Proposal.\n- €80,000 → stops in Approval Pending until a manager decides.\n\n## Use it from a coding agent\n\nClaude Code reads `CLAUDE.md`, `.mcp.json` and `.claude/skills/`. Codex reads `AGENTS.md`\nand `.codex/config.toml`. Both are checked in and wired together.\n\n```text\nRead AGENTS.md, PRODUCT.md and docs/PROJECT_STATUS.md.\nRun npm run crm -- app inspect --json.\nTell me which parts of my commercial process this already supports, and which it does not.\n```\n\nA harness needs only: run a command, read stdout, read the exit code, parse JSON, and read\nand write files. No MCP server, no network, no credentials, no database, no long-lived\nprocess — [`docs/AGENT_HARNESS_COMPATIBILITY.md`](docs/AGENT_HARNESS_COMPATIBILITY.md).\n\n```bash\nnpm run crm -- app inspect --json          # what this application contains\nnpm run crm -- solution check plan.json    # is this plan still valid against it\n```\n\nExit codes are the contract: `0` valid · `1` problems, report still printed · `2` unreadable.\n\nThe MCP server runs over stdio (`node --no-warnings packages/mcp/bin/server.js`) and exposes\nproject inspection, opportunity listing, stage-change requests, approval decisions, run traces\nand module scaffolding. Code-generating and destructive tools are **dry-run unless you pass an\nexplicit apply flag** (`tests/mcp.test.js`, `tests/scaffold.test.js` — [`docs/MCP.md`](docs/MCP.md)).\nIt is stdio-only and local-only: there is no hosted or authenticated MCP endpoint, and the server\ninherits the authority of the process that starts it.\n\n## Where it stops\n\nRead this before evaluating anything above. `docs/benchmarks/CRM_JTBD_MATRIX.md` tracks every\nCRM job with a conservative status vocabulary in which *not supported* is the default and\nevidence is required to leave it.\n\nMost boundaries below carry a machine-checked citation into\n[`docs/repository-truth.json`](docs/repository-truth.json), the generated fact document\n(`repositoryTruthContract: 1`, ADR-039). The citations are HTML comments — invisible when this\npage renders, load-bearing when `npm run repo:truth -- --check` runs on every push. A cited\nsentence that survives the code it describes fails that check. Three bullets below carry no\ncitation, because no generated fact covers what they say — import and export, data governance,\nand how the framework is distributed — and a citation nothing resolves would read as proof of\nsomething nobody checked. No number in any of these sentences is checked either\n(`NUMERIC_CLAIMS_NOT_BOUND`).\n\n- **No authentication ships: the framework authenticates nobody.** Production Spine v1\n  (ADR-038) added verified identity, organizations and memberships, server-authoritative\n  authorization and one tenant per application instance — so tenancy and authorization now\n  exist and are enforced. Authentication does not: no login, password, session or OIDC\n  implementation ships, and a deployment must supply the adapter that verifies the request.\n  Production mode refuses to start without one. In local-development mode an actor header is\n  accepted as an assertion and is not an identity, which is the default developer posture.\n  This is not shared-database multi-tenancy and it is not a readiness claim.\n  <!-- truth: spine.authentication.framework_verifier=absent -->\n  <!-- truth: spine.authorization.enforced=enforced -->\n  <!-- truth: spine.tenant.isolation.mode=one_tenant_per_instance -->\n  <!-- truth: spine.tenant.crm_data_plane_enforced=enforced_by_binding -->\n  <!-- truth: spine.multi_tenant_single_instance=refused_at_startup -->\n- **Not shared-database tenancy.** `createAccordoAppAsync` can boot one tenant onto\n  dedicated PostgreSQL databases; `createAccordoApp()` stays SQLite-only. Shared-database\n  row-level tenancy is not implemented, and this is not a production-readiness claim.\n  <!-- truth: spine.postgresql.implemented=implemented -->\n- **The build benchmark has not been run.** No Successful Agent Build Rate exists. Any\n  percentage attributed to this project is fabricated —\n  [`docs/strategy/CRM_BUILD_BENCHMARK.md`](docs/strategy/CRM_BUILD_BENCHMARK.md) is the\n  protocol, not a result.\n  <!-- truth: benchmark.build_rate.measured=not_measured -->\n  <!-- truth: benchmark.tool_selection.comparative=false -->\n- **Timers exist; a service that runs them for you does not.** A person can schedule an\n  ask — open this follow-up on that date, review this renewal when notice opens — and a\n  worker the application starts explicitly presents it at that instant. Nothing autostarts,\n  so an application that never starts a worker still behaves exactly as before: a due date\n  changes no state and nothing fires. A timer opens an ask and decides nothing; completing,\n  cancelling or annotating work stays refused to it, and no recurrence syntax exists.\n  <!-- truth: spine.timer_consumers.implemented=implemented -->\n  <!-- truth: spine.managed_jobs_service.implemented=absent -->\n- **No email, calendar or marketing integrations.** A notification provider contract exists;\n  no adapter sends anything to anyone.\n  <!-- truth: marketing_runtime.implemented=absent -->\n- **Nothing bills.** No invoice, payment, tax, usage rating, proration or revenue recognition\n  exists anywhere in the composition, and MRR, ARR and TCV are not derived from contract data.\n  <!-- truth: billing.implemented=absent -->\n- **No backups, restore or managed secret custody/service.** A bounded self-host\n  secret-provider contract exists; managed custody, rotation and recovery do not,\n  and no recovery objective is claimed.\n  <!-- truth: spine.secret_provider.implemented=implemented -->\n  <!-- truth: spine.secrets_backups.implemented=absent -->\n- **The customer foundation is not a CDP, and the profile is not a timeline.** It links and\n  projects the records that already exist; there is no warehouse, no streaming, no activation\n  and no complete customer timeline.\n  <!-- truth: cdf.full_cdp.implemented=absent -->\n  <!-- truth: customer_timeline.complete=absent -->\n- **Bounded customer imports and logical identity; incomplete data operations.** Preview/apply takes\n  bounded JSON rows, with per-row receipts, idempotency and deterministic matching;\n  a human decides canonical links without deleting or rewriting source records.\n  No CSV importer, physical merge, complete export/erasure, bulk editing, saved views\n  or global search ships. See `tests/customer-data-foundation.test.js`.\n  <!-- truth: domain.customer_data.package_native=package_native -->\n- **Personal-data readiness requires deployment work beyond the foundation.** Supply authentication and\n  complete subject export/erasure for your application; the customer foundation alone\n  establishes neither compliance nor suitability for real customer data.\n  Lead scoring is deterministic, versioned and explainable.\n- **This is a framework, not a product you sign up for.** There is no hosted CRM, no free\n  tier, no account, and no control plane that provisions, deploys or meters anything. The\n  output is an application you run.\n  <!-- truth: cloud_control_plane.implemented=absent -->\n- **Ownership means vendored source: there is no framework dependency to bump.**\n  `npm create accordo` — the published `create-accordo@0.1.0` — scaffolds a project that boots,\n  reports `valid` from `app inspect` and exits 0 from `project doctor`, by copying the framework\n  source into it; the same bootstrap runs from a checkout\n  (`node packages/create-accordo/bin/create-accordo.js <dir> --apply`, no install, no network —\n  `tests/project-bootstrap.test.js`). What the registry hands you is the scaffolder, not the\n  framework: the `accordo` package is an empty `0.0.1` name reservation, deliberately. The\n  framework is vendored into the project, so you own the result outright — and upgrading means\n  merging, not bumping a version.\n\n## Architecture in five folders\n\n```text\npackages/core/        the runtime platform: registry, services, workflow engine, audit\npackages/modules/     CRM domain primitives\npackages/domains/     optional domain packages (contracts, delivery) on a public contract\npackages/mcp/         tools and context exposed to coding agents\napps/                 API server and generated Admin\n```\n\nThe agent never writes to a database table. It calls service methods and named workflows,\nwhich preserve validation, actor identity, policy, trace and audit — `ARCHITECTURE.md`.\n\n## Documents\n\n| Read this | For |\n|---|---|\n| [`AGENTS.md`](AGENTS.md) | the rules an agent must follow before changing code |\n| [`PRODUCT.md`](PRODUCT.md) | what the product is and is not |\n| [`ARCHITECTURE.md`](ARCHITECTURE.md) | the technical model and its extension rules |\n| [`DECISIONS.md`](DECISIONS.md) | the decision log, ADR-001 … ADR-020 |\n| [`docs/PROJECT_STATUS.md`](docs/PROJECT_STATUS.md) | what is true in the repository today |\n| [`docs/benchmarks/CRM_JTBD_MATRIX.md`](docs/benchmarks/CRM_JTBD_MATRIX.md) | every CRM job, its status and its evidence |\n| [`docs/QUALITY_GATES.md`](docs/QUALITY_GATES.md) | the review discipline, including adversarial-review categories |\n| [`docs/strategy/MASTER_PLAN.md`](docs/strategy/MASTER_PLAN.md) | category, positioning, roadmap, metrics |\n| [`docs/strategy/GO_TO_MARKET.md`](docs/strategy/GO_TO_MARKET.md) | how this reaches people, and what is gated on a human |\n\n## Licence\n\nMIT, confirmed by ADR-023.\n",
  "bytes": 21346,
  "sha": "88e09a0e8e73495cfbf221712b345433836fc00e26cc816858f5ec96cf5c9602",
  "repo_slug": "khaoss85/agent-crm",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_khaoss85_agent_crm_d90adcfb/readme"
}