- 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>
88 lines
3.8 KiB
Markdown
88 lines
3.8 KiB
Markdown
---
|
|
paths:
|
|
- "nodes/*/*.js"
|
|
- "nodes/*/*.html"
|
|
- "nodes/*/src/**"
|
|
---
|
|
|
|
# Node Architecture Rules
|
|
|
|
## 3-Tier Structure
|
|
Every node follows entry → nodeClass → specificClass:
|
|
|
|
1. **Entry file** (`nodes/<nodeName>/<nodeName>.js`): Registers with Node-RED via `RED.nodes.registerType`, exposes admin HTTP endpoints.
|
|
2. **nodeClass** (`nodes/<nodeName>/src/nodeClass.js`): Handles Node-RED runtime concerns — message routing, output formatting, tick loops, status updates, `RED.*` API calls.
|
|
3. **specificClass** (`nodes/<nodeName>/src/specificClass.js`): Pure domain logic — physics, control algorithms, state machines.
|
|
|
|
## Separation Rules
|
|
- **specificClass must never call `RED.*` directly** — all Node-RED interaction goes through nodeClass.
|
|
- specificClass is the source of truth for domain behavior.
|
|
- nodeClass is the adapter between Node-RED and domain logic.
|
|
- Entry file is minimal — registration and admin endpoints only.
|
|
|
|
## Output Port Convention
|
|
- Port 0: Process data (control outputs, state, setpoints)
|
|
- Port 1: InfluxDB telemetry payload
|
|
- Port 2: Registration/control plumbing (parent-child handshakes)
|
|
|
|
## File-Naming Convention
|
|
The folder name is the canonical node name and every per-node file MUST match it
|
|
exactly (case-sensitive). No abbreviations.
|
|
|
|
| Path | Required name |
|
|
|---|---|
|
|
| Folder | `nodes/<nodeName>/` |
|
|
| Entry file | `nodes/<nodeName>/<nodeName>.js` |
|
|
| Editor HTML | `nodes/<nodeName>/<nodeName>.html` |
|
|
| nodeClass | `nodes/<nodeName>/src/nodeClass.js` |
|
|
| specificClass | `nodes/<nodeName>/src/specificClass.js` |
|
|
| Editor JS modules | `nodes/<nodeName>/src/editor/*.js` |
|
|
|
|
`machineGroupControl/mgc.js`, `valveGroupControl/vgc.js`, and
|
|
`dashboardAPI/dashboardapi.js` are legacy drift. New nodes MUST use the full
|
|
folder name; legacy nodes get renamed when next touched (rename = update entry
|
|
file, HTML file, `package.json#node-red.nodes`, and any test imports in one
|
|
commit).
|
|
|
|
## Editor JS Layout — `src/editor/`
|
|
Editor-side JavaScript that exceeds a couple of dozen lines lives in modular
|
|
files under `nodes/<nodeName>/src/editor/`, served by the entry file via:
|
|
|
|
```js
|
|
const path = require('path');
|
|
RED.httpAdmin.get(`/${nameOfNode}/editor/:file`, (req, res) => {
|
|
const safe = String(req.params.file || '').replace(/[^a-zA-Z0-9._-]/g, '');
|
|
if (!safe.endsWith('.js')) return res.status(400).send('// invalid');
|
|
res.type('application/javascript');
|
|
res.sendFile(path.join(__dirname, 'src', 'editor', safe), (err) => {
|
|
if (err && !res.headersSent) res.status(404).send('// editor module not found');
|
|
});
|
|
});
|
|
```
|
|
|
|
The HTML file then loads them as plain `<script src="/<nodeName>/editor/<file>.js">`
|
|
tags. Conventional modules:
|
|
|
|
| File | Purpose |
|
|
|---|---|
|
|
| `index.js` | Namespace setup (`window.EVOLV.nodes.<nodeName>.editor = …`), shared helpers |
|
|
| `oneditprepare.js` | Implementation called from the `.html`'s `oneditprepare` hook |
|
|
| `oneditsave.js` | Implementation called from the `.html`'s `oneditsave` hook |
|
|
| Feature modules | One per visual concern, e.g. `basin-diagram.js`, `mode-cards.js`, `timing-donut.js`, `hover-couple.js` |
|
|
|
|
The `.html` shrinks to: register defaults, declare HTML template, delegate
|
|
`oneditprepare`/`oneditsave` to the modules. Inline JS in the `.html` is fine
|
|
for **trivial** nodes (≤ ~50 lines of editor JS); past that, extract.
|
|
|
|
Reference implementations: `pumpingStation/src/editor/` and
|
|
`machineGroupControl/src/editor/`. `rotatingMachine` is currently inline and
|
|
should be migrated when the editor JS next grows.
|
|
|
|
## Admin Endpoints
|
|
- `GET /<nodeName>/menu.js` — Dynamic menu configuration for editor
|
|
- `GET /<nodeName>/configData.js` — Runtime configuration for editor
|
|
- `GET /<nodeName>/editor/:file` — (when present) editor JS modules from `src/editor/`
|
|
|
|
## Submodule Awareness
|
|
Most `nodes/*` directories are git submodules. Keep edits scoped to the target node's directory.
|