- Delete .mcp.json + .claude/rules/repo-mem.md; drop .repo-mem from .gitignore - Remove repo-mem / substrate_score / repo_search references from all .md - Move 15 EVOLV skills from .agents/skills/ to .claude/skills/ so they are auto-discovered by the Claude Code harness and invokable via the Skill tool - Retire .agents/skills/evolv-orchestrator (duplicate of the subagent at .claude/agents/evolv-orchestrator.md); orchestrator lives as a subagent only - Drop OpenAI-format agent yaml metadata from each skill (not needed for CC) - Update CLAUDE.md, CONTRACTS.md, AGENTS.md to point at the new locations and disambiguate skills (.claude/skills/) vs subagents (.claude/agents/) - Fix CLAUDE.md tick-loop wording (opt-in per-node, not a fixed 1000ms) - Widen .claude/rules/ paths frontmatter so node-architecture and telemetry rules trigger on more relevant files; add frontmatter to flow-layout rule - Bump CONTRACTS.md review date to 2026-05-19; add step 7 to the contract- change workflow (review example flows when topic usage changes) - Bump nodes/generalFunctions pin (Home.md substrate_score reference removed) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8.6 KiB
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 |
Auto-loaded by Claude Code |
| Active rules | .claude/rules/ (7 files) |
Triggered by paths: frontmatter or referenced from CLAUDE.md |
| Platform API contracts | .claude/refactor/CONTRACTS.md |
Before changing generalFunctions exports or any base class |
| Code conventions | .claude/refactor/CONVENTIONS.md |
Before writing or editing any file |
| Per-node concern layout | .claude/refactor/MODULE_SPLIT.md |
When adding files to nodes/<n>/src/ |
| Wiki page templates | .claude/refactor/WIKI_TEMPLATE.md + WIKI_HOME_TEMPLATE.md |
When editing a per-node wiki page |
| Live decisions log | .claude/refactor/OPEN_QUESTIONS.md |
When you spot an ambiguity — append, don't invent |
| Top-level 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/ (15 domain skills, auto-discovered, invokable via Skill tool) |
When you need domain reasoning |
| Spawnable subagents | .claude/agents/ (10 Claude Code subagents) |
When you want to delegate independent work |
| Routing table | .agents/AGENTS.md |
When deciding which specialist to invoke |
| Improvements backlog | .agents/improvements/IMPROVEMENTS_BACKLOG.md |
When deferring functional work |
Per-node (nodes/<nodeName>/)
| What | Where | Read when |
|---|---|---|
| Node entry instructions for agents | nodes/<n>/CLAUDE.md |
Auto-loaded when touching files in that subtree |
| Node API contract | nodes/<n>/CONTRACT.md |
Before changing msg.topic inputs/outputs/events |
| Command registry (source of truth) | nodes/<n>/src/commands/index.js |
When adding/removing an accepted topic |
| Domain logic | nodes/<n>/src/specificClass.js |
Pure JS; no RED.* allowed |
| Node-RED adapter | nodes/<n>/src/nodeClass.js |
Bridge to runtime; ≤ 25 lines, extends BaseNodeAdapter |
| Per-node wiki | nodes/<n>/wiki/ — Home.md, Reference-{Architecture,Contracts,Limitations,Examples}.md |
Topic-contract + data-model sections autogen via npm run wiki:all |
| Tests | nodes/<n>/test/{basic,integration,edge}/ |
Required for every change |
| Example flows | nodes/<n>/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/ (20 files) |
Historical reference; each has ⚠️ ARCHIVED — Do not update |
| Refactor plan artifacts | .claude/refactor/Archive/ — CONTINUE_HERE.md, TASKS.md |
The May-2026 refactor plan; phases all done |
| Old priority lists | .agents/improvements/Archive/ |
Pre-refactor production priorities |
2. Discovery chain — how a fresh agent finds the rules
CLAUDE.mdauto-loads → points at this file..claude/rules/*.mdauto-load bypaths:frontmatter when editing matching files.nodes/<n>/CLAUDE.mdauto-loads when working under that submodule.- This file (
CONTRACTS.md) is the human-facing map of everything in step 1-3. - Concept lookup: use
grep/findor theExploresubagent — anchor on the canonical sources listed in §1 (commands registry, CONTRACT.md, base classes ingeneralFunctions/).
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 |
nodes/<n>/<n>.js |
| 2 — Adapter | BaseNodeAdapter (from generalFunctions) |
.claude/refactor/CONTRACTS.md §2 |
nodes/<n>/src/nodeClass.js |
| 3 — Domain | BaseDomain (from generalFunctions) |
.claude/refactor/CONTRACTS.md §3 |
nodes/<n>/src/specificClass.js |
Plus the commands registry (nodes/<n>/src/commands/index.js) declares
the msg.topic inputs; BaseNodeAdapter dispatches by topic lookup. See
.claude/refactor/CONTRACTS.md §4.
4. Output and telemetry contract
Three output ports per node. Source of truth: .claude/refactor/CONTRACTS.md §10 and 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.
5. When a contract changes — the rule
- Update the source file (
src/commands/index.js,src/specificClass.js, orgeneralFunctions/index.js). - Update the per-node
CONTRACT.md(Inputs table is partially autogenerated; the rest is hand-maintained). - Run
npm run wiki:allinside the submodule to regenerate the topic-contract + data-model sections inwiki/. - If the change touched a platform shape (a base class or shared utility), update
.claude/refactor/CONTRACTS.mdandnodes/generalFunctions/CONTRACT.md. - If the change introduced a deprecation, add an alias to
commands/index.jsand a one-line note to the per-nodeCONTRACT.md. - Append unresolved questions to
.claude/refactor/OPEN_QUESTIONS.md. Don't invent answers. - If topic usage in an example flow changed, regenerate or review the per-node
wiki/Reference-Examples.mdand theexamples/*.flow.jsonset.
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.<noun> for
idempotent setters, cmd.<verb> for triggers, evt.<noun> 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/<n> && node --test test/basic test/integration test/edge). CONTRACT.mdupdated for any added / removed / renamed topic, port-0 key, or event.npm run wiki:allre-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.