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:
141
CONTRACTS.md
Normal file
141
CONTRACTS.md
Normal 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.*
|
||||
Reference in New Issue
Block a user