- 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>
6.8 KiB
EVOLV - Claude Code Project Guide
READ FIRST, BEFORE ANY OTHER WORK:
CONTRACTS.md— front-door map: where every contract, rule, and standard lives, and how to find them.
What This Is
Node-RED custom nodes package for wastewater treatment plant automation. Developed by Waterschap Brabantse Delta R&D team. Follows ISA-88 (S88) batch control standard.
Architecture
Each node follows a three-layer pattern:
- Node-RED wrapper (
<nodeName>.js) - registers the node type, sets up HTTP endpoints - Node adapter (
src/nodeClass.js) - bridges Node-RED API with domain logic, handles config loading, tick loops, events - Domain logic (
src/specificClass.js) - pure business logic, no Node-RED dependencies
Folder & File Layout (READ BEFORE CREATING NEW FILES)
Every per-node file MUST use the folder name exactly (case-sensitive). No abbreviations. Quick reference:
| Path | Required name |
|---|---|
| Entry file | nodes/<nodeName>/<nodeName>.js |
| Editor HTML | nodes/<nodeName>/<nodeName>.html |
| Node adapter | nodes/<nodeName>/src/nodeClass.js |
| Domain logic | nodes/<nodeName>/src/specificClass.js |
| Editor JS modules | nodes/<nodeName>/src/editor/*.js (extract when inline editor JS exceeds ~50 lines) |
| Tests | nodes/<nodeName>/test/{basic,integration,edge}/*.test.js |
| Example flows | nodes/<nodeName>/examples/*.flow.json |
Full rule + serving recipe for src/editor/: .claude/rules/node-architecture.md.
Legacy drift to rename when the file is next touched (do not introduce new mismatches in the meantime):
| Node | Currently | Should be |
|---|---|---|
machineGroupControl |
mgc.{js,html} |
machineGroupControl.{js,html} |
valveGroupControl |
vgc.{js,html} |
valveGroupControl.{js,html} |
dashboardAPI |
dashboardapi.{js,html} |
dashboardAPI.{js,html} |
Key Shared Library: nodes/generalFunctions/
logger- structured logging (use this, NOT console.log)MeasurementContainer- chainable measurement storage (type/variant/position)configManager- loads JSON configs fromsrc/configs/MenuManager- dynamic UI dropdownsoutputUtils- formats messages for InfluxDB and process outputschildRegistrationUtils- parent-child node relationshipscoolprop- thermodynamic property calculations
Conventions
- Nodes register under category
'EVOLV'in Node-RED - S88 color scheme: Area=#0f52a5, ProcessCell=#0c99d9, Unit=#50a8d9, Equipment=#86bbdd, ControlModule=#a9daee
- Config JSON files in
generalFunctions/src/configs/define defaults, types, enums per node - Tick loop is opt-in per node — default cadence 1000 ms, but each node sets
static tickInterval(or skips it). See.claude/refactor/OPEN_QUESTIONS.md(2026-05-10 entry) for the design decision - Output ports + 3-tier architecture + file-naming +
src/editor/layout: see.claude/rules/node-architecture.md - Multi-tab demo flows: see
.claude/rules/node-red-flow-layout.mdfor the tab/link-channel/spacing rule set used byexamples/ - Output coverage (every output, every state, every layer): see
.claude/rules/output-coverage.md— manifest + populated/degraded tests are mandatory for any change that touches Port 0/1/2 keys, function-node fan-outs, telemetry fields, or dashboard widget sources
Agents and Skills (use them — don't reinvent)
- Skills at
.claude/skills/evolv-*/SKILL.md(15 domain skills) — auto-discovered, invoke via theSkilltool. Load them when you need domain reasoning (rotating equipment, biology, telemetry, security, instrumentation, hydraulics, alarms, OT integration, regulatory, quality, commissioning, frontend, …). - Subagents at
.claude/agents/*.md(10 Claude Code subagents) — spawnable viaAgent(subagent_type: '<name>'). Use for independent work:evolv-orchestrator(multi-domain decomposition +teamworkflows),mechanical-process-engineer,biological-process-engineer,instrumentation-measurement,node-red-runtime,telemetry-database,quality-test-engineer,commissioning-compliance,ot-security-integration,general-functions-library. - Routing table:
.agents/AGENTS.mdmaps task patterns → which skill/subagent to invoke. teamkeyword: when the user says "team", spawnevolv-orchestrator(subagent) — it picks specialists, runs an alignment pass, returns one integrated answer.
Tooling (Docker-first, local now, central later)
Custom EVOLV tooling lives in tools/ and is intended to run inside the local Docker compose stack (tools/docker-compose.yml). Always prefer these tools over ad-hoc grep/curl/manual checks — they encode the rules in .claude/rules/ and catch regressions the human review would miss:
tools/flow-lint/— validatesexamples/*.flow.jsonagainst.claude/rules/node-red-flow-layout.md. Run before committing any flow change.tools/output-manifest-verify/— diffs declared Port 0/1/2 keys vs. runtime emissions. Run on any output-shape change.tools/contract-verify/— diffsnodes/<n>/CONTRACT.mdvs.src/commands/index.js. Run after touching a command registry.tools/wiki-gen/— regenerates topic-contract + data-model sections ofnodes/<n>/wiki/. Run after a CONTRACT change.tools/physics-sanity/— cross-node mass/hydraulic/energy balance assertions. Run as part ofnode --testfor cross-node changes.- MCP services (Node-RED admin, InfluxDB, headless browser) live under
tools/mcp/as Docker services. Migration note: these will move to a central MCP server later; the local stack is interim. The Dockerfile + compose entry stays in this repo as the canonical definition. - Why use them: every tool encodes a rule that we've previously discovered through a bug (η-null crash, ui-chart blank renders, output-key drift). Skipping them re-opens those bugs.
Sources of truth (the canonical files)
- Front-door map:
CONTRACTS.md— read first; lists every standard and where it lives - Platform API shapes (BaseDomain, BaseNodeAdapter, commands registry, UnitPolicy, …):
.claude/refactor/CONTRACTS.md - Code conventions (file/function size, comments, naming):
.claude/refactor/CONVENTIONS.md - Per-node module layout:
.claude/refactor/MODULE_SPLIT.md - Per-node API contract:
nodes/<n>/CONTRACT.md+nodes/<n>/src/commands/index.js(source of truth for acceptedmsg.topicvalues) - Shared library API:
nodes/generalFunctions/CONTRACT.md(exported classes + utilities) - Live decisions log:
.claude/refactor/OPEN_QUESTIONS.md— append, don't invent
Development Notes
- No build step required - pure Node.js
- Install:
npm installin root - Submodule URLs were rewritten from
gitea.centraal.wbd-rd.nltogitea.wbd-rd.nlfor external access - Dependencies: mathjs, generalFunctions (git submodule)