docs: standards cleanup — single front-door CONTRACTS.md + archive stale plan artifacts

Establish CONTRACTS.md at the EVOLV root as the canonical map of where every
contract, rule, and standard lives. Surface it from CLAUDE.md so every fresh
agent or colleague lands there first.

Reshape .claude/refactor/ to reflect that the platform refactor is done:
live standards stay at the top level; the plan artifacts (CONTINUE_HERE.md,
TASKS.md) move into Archive/ with WARNING banners.

Drop content that drifted out of date or duplicated the new standards stack:
- docs/DEVELOPER_GUIDE.md (pre-refactor walkthrough; superseded by
  wiki/Architecture, wiki/Getting-Started, .claude/rules/node-architecture,
  .claude/refactor/MODULE_SPLIT + per-node CONTRACT.md + src/commands/).
- .agents/decisions/ (15 DECISION files): load-bearing decisions belong in
  commit messages and PR descriptions; live open items in OPEN_QUESTIONS.md.
- .agents/improvements/TOP10_*.md: moved to Archive/.

Bump generalFunctions to 49c77f2 — adds CONTRACT.md inside the library:
different shape from per-node CONTRACT.md files (library API, not msg.topic),
with stability tags and pointers to .claude/refactor/CONTRACTS.md §N.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Rene De Ren
2026-05-18 15:48:46 +02:00
parent 560cc2f39a
commit 253ac93896
26 changed files with 210 additions and 1278 deletions

141
CONTRACTS.md Normal file
View File

@@ -0,0 +1,141 @@
# 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/<n>/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 / routing** | [`.agents/AGENTS.md`](./.agents/AGENTS.md) + [`.agents/skills/`](./.agents/skills/) | When deciding which specialist to invoke |
| **Improvements backlog** | [`.agents/improvements/IMPROVEMENTS_BACKLOG.md`](./.agents/improvements/IMPROVEMENTS_BACKLOG.md) | When deferring functional work |
| **Repo-memory MCP rule** | [`.claude/rules/repo-mem.md`](./.claude/rules/repo-mem.md) | Before any concept-search — use `repo_search` instead of `grep` |
### 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/`](./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 and `.claude/rules/repo-mem.md`.
2. `.claude/rules/*.md` auto-load by `paths:` frontmatter when editing matching files.
3. `nodes/<n>/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 the `repo-mem` MCP server (`repo_search`, `repo_similar_fixes`) — it's faster and more targeted than `grep`. See `.claude/rules/repo-mem.md`.
---
## 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/<n>/<n>.js` |
| 2 — Adapter | `BaseNodeAdapter` (from `generalFunctions`) | [`.claude/refactor/CONTRACTS.md §2`](./.claude/refactor/CONTRACTS.md) | `nodes/<n>/src/nodeClass.js` |
| 3 — Domain | `BaseDomain` (from `generalFunctions`) | [`.claude/refactor/CONTRACTS.md §3`](./.claude/refactor/CONTRACTS.md) | `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`](./.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.
---
## 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.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-18. If something in this map is wrong, fix this file
in the same PR as the change that made it wrong.*