# EVOLV — Contracts, Rules, and Standards > **Front door for humans and agents working in this repo.** > If you only read one file before touching code, read this one. It maps every > contract, rule, and standard in the EVOLV stack and tells you where each > lives. Everything else here is a link to a more specific file. EVOLV is a Node-RED node library for wastewater treatment plant automation, built by Waterschap Brabantse Delta R&D. All work happens on the `development` branch across 12 submodules; promotion to `main` is gated by Docker E2E. --- ## 1. Where everything lives ### Platform-wide (EVOLV root) | What | Where | Read when | |---|---|---| | **This map** | `CONTRACTS.md` (this file) | First time, or when orienting | | **Agent entry-point instructions** | [`CLAUDE.md`](./CLAUDE.md) | Auto-loaded by Claude Code | | **Active rules** | [`.claude/rules/`](./.claude/rules/) (7 files) | Triggered by `paths:` frontmatter or referenced from `CLAUDE.md` | | **Platform API contracts** | [`.claude/refactor/CONTRACTS.md`](./.claude/refactor/CONTRACTS.md) | Before changing `generalFunctions` exports or any base class | | **Code conventions** | [`.claude/refactor/CONVENTIONS.md`](./.claude/refactor/CONVENTIONS.md) | Before writing or editing any file | | **Per-node concern layout** | [`.claude/refactor/MODULE_SPLIT.md`](./.claude/refactor/MODULE_SPLIT.md) | When adding files to `nodes//src/` | | **Wiki page templates** | [`.claude/refactor/WIKI_TEMPLATE.md`](./.claude/refactor/WIKI_TEMPLATE.md) + [`WIKI_HOME_TEMPLATE.md`](./.claude/refactor/WIKI_HOME_TEMPLATE.md) | When editing a per-node wiki page | | **Live decisions log** | [`.claude/refactor/OPEN_QUESTIONS.md`](./.claude/refactor/OPEN_QUESTIONS.md) | When you spot an ambiguity — append, don't invent | | **Top-level wiki** | [`wiki/`](./wiki/) (Home, Architecture, Getting-Started, Telemetry, Topology-Patterns, Topic-Conventions, Glossary, Functional-Overview) | When you need a process-level or architecture-level view | | **Agent skills** | [`.claude/skills/`](./.claude/skills/) (15 domain skills, auto-discovered, invokable via `Skill` tool) | When you need domain reasoning | | **Spawnable subagents** | [`.claude/agents/`](./.claude/agents/) (10 Claude Code subagents) | When you want to delegate independent work | | **Routing table** | [`.agents/AGENTS.md`](./.agents/AGENTS.md) | When deciding which specialist to invoke | | **Improvements backlog** | [`.agents/improvements/IMPROVEMENTS_BACKLOG.md`](./.agents/improvements/IMPROVEMENTS_BACKLOG.md) | When deferring functional work | ### Per-node (`nodes//`) | What | Where | Read when | |---|---|---| | Node entry instructions for agents | `nodes//CLAUDE.md` | Auto-loaded when touching files in that subtree | | **Node API contract** | `nodes//CONTRACT.md` | Before changing `msg.topic` inputs/outputs/events | | **Command registry (source of truth)** | `nodes//src/commands/index.js` | When adding/removing an accepted topic | | **Domain logic** | `nodes//src/specificClass.js` | Pure JS; no `RED.*` allowed | | **Node-RED adapter** | `nodes//src/nodeClass.js` | Bridge to runtime; ≤ 25 lines, extends `BaseNodeAdapter` | | **Per-node wiki** | `nodes//wiki/` — `Home.md`, `Reference-{Architecture,Contracts,Limitations,Examples}.md` | Topic-contract + data-model sections autogen via `npm run wiki:all` | | **Tests** | `nodes//test/{basic,integration,edge}/` | Required for every change | | **Example flows** | `nodes//examples/{basic,integration,edge}.flow.json` | Required artifact per node | ### Shared library (`nodes/generalFunctions/`) | What | Where | |---|---| | **Library API contract** | `nodes/generalFunctions/CONTRACT.md` | | **Public exports** | `nodes/generalFunctions/index.js` (barrel) | | **Source** | `nodes/generalFunctions/src/{domain,nodered,measurements,convert,configs,…}/` | ### Archives (don't take as authoritative) | What | Where | Why kept | |---|---|---| | Pre-refactor wiki pages | [`wiki/Archive/`](./wiki/Archive/) (20 files) | Historical reference; each has `⚠️ ARCHIVED — Do not update` | | Refactor plan artifacts | [`.claude/refactor/Archive/`](./.claude/refactor/Archive/) — `CONTINUE_HERE.md`, `TASKS.md` | The May-2026 refactor plan; phases all done | | Old priority lists | [`.agents/improvements/Archive/`](./.agents/improvements/Archive/) | Pre-refactor production priorities | --- ## 2. Discovery chain — how a fresh agent finds the rules 1. `CLAUDE.md` auto-loads → points at this file. 2. `.claude/rules/*.md` auto-load by `paths:` frontmatter when editing matching files. 3. `nodes//CLAUDE.md` auto-loads when working under that submodule. 4. This file (`CONTRACTS.md`) is the human-facing map of everything in step 1-3. 5. **Concept lookup**: use `grep` / `find` or the `Explore` subagent — anchor on the canonical sources listed in §1 (commands registry, CONTRACT.md, base classes in `generalFunctions/`). --- ## 3. The three contracts every node honours Every EVOLV node is a three-tier sandwich. Each tier has a contract: | Tier | Class | Contract source | Per-node implementation | |---|---|---|---| | 1 — Entry | `RED.nodes.registerType` | [`.claude/rules/node-architecture.md`](./.claude/rules/node-architecture.md) | `nodes//.js` | | 2 — Adapter | `BaseNodeAdapter` (from `generalFunctions`) | [`.claude/refactor/CONTRACTS.md §2`](./.claude/refactor/CONTRACTS.md) | `nodes//src/nodeClass.js` | | 3 — Domain | `BaseDomain` (from `generalFunctions`) | [`.claude/refactor/CONTRACTS.md §3`](./.claude/refactor/CONTRACTS.md) | `nodes//src/specificClass.js` | Plus the **commands registry** (`nodes//src/commands/index.js`) declares the `msg.topic` inputs; `BaseNodeAdapter` dispatches by topic lookup. See [`.claude/refactor/CONTRACTS.md §4`](./.claude/refactor/CONTRACTS.md). --- ## 4. Output and telemetry contract Three output ports per node. Source of truth: [`.claude/refactor/CONTRACTS.md §10`](./.claude/refactor/CONTRACTS.md) and [`wiki/Telemetry.md`](./wiki/Telemetry.md). | Port | Carries | Formatter | |---|---|---| | 0 | Process data (delta-compressed) | `outputUtils.formatMsg(..., 'process')` | | 1 | InfluxDB line protocol | `outputUtils.formatMsg(..., 'influxdb')` | | 2 | Registration / control plumbing | hand-shaped on the parent-child handshake | Output-coverage testing (manifest + populated + degraded states) is **mandatory** for any change touching Port 0/1/2 keys, function-node fan-outs, or dashboard widgets. See [`.claude/rules/output-coverage.md`](./.claude/rules/output-coverage.md). --- ## 5. When a contract changes — the rule 1. Update the source file (`src/commands/index.js`, `src/specificClass.js`, or `generalFunctions/index.js`). 2. Update the per-node `CONTRACT.md` (Inputs table is partially autogenerated; the rest is hand-maintained). 3. Run `npm run wiki:all` inside the submodule to regenerate the topic-contract + data-model sections in `wiki/`. 4. If the change touched a platform shape (a base class or shared utility), update [`.claude/refactor/CONTRACTS.md`](./.claude/refactor/CONTRACTS.md) and `nodes/generalFunctions/CONTRACT.md`. 5. If the change introduced a deprecation, add an alias to `commands/index.js` and a one-line note to the per-node `CONTRACT.md`. 6. Append unresolved questions to [`.claude/refactor/OPEN_QUESTIONS.md`](./.claude/refactor/OPEN_QUESTIONS.md). Don't invent answers. 7. If topic usage in an example flow changed, regenerate or review the per-node `wiki/Reference-Examples.md` and the `examples/*.flow.json` set. --- ## 6. Conventions in one paragraph (the rest is in `CONVENTIONS.md`) Files ≤ 200 lines (300 hard cap); functions ≤ 30 lines (60 hard cap). Default to no comments — add one only when *why* is non-obvious. `specificClass` **never** imports `RED.*`. Logger from `generalFunctions`, never `console.log`. S88 colour scheme is mandatory in diagrams. Topic prefixes: `set.` for idempotent setters, `cmd.` for triggers, `evt.` for events. Tests live in `test/{basic,integration,edge}/`. Submodule commits go in the submodule first, then the superproject bumps the pin. --- ## 7. Verification checklist before merge - [ ] Per-node tests green (`cd nodes/ && node --test test/basic test/integration test/edge`). - [ ] `CONTRACT.md` updated for any added / removed / renamed topic, port-0 key, or event. - [ ] `npm run wiki:all` re-run in the touched submodule(s). - [ ] Output-coverage manifest + tests updated if any output shape changed. - [ ] Submodule pin bumped in the superproject. - [ ] Commit message captures *why* — load-bearing decisions go in the commit body and PR description. --- *Last reviewed: 2026-05-19. If something in this map is wrong, fix this file in the same PR as the change that made it wrong.*