The platform has 12 nodes that all share the same architectural skeleton (BaseDomain + BaseNodeAdapter + ChildRouter + commands registry). The wiki should mirror that uniformity: a reader flips between nodes and finds the same 14 sections in the same order. Diagrams lead. Tables annotate. Prose only fills gaps.
The default is Mermaid (Gitea renders it natively). It's the right tool for graph-shaped things — neighbours, lifecycles, state machines, file maps. But Mermaid doesn't render data: when a section is about *what a curve looks like* or *what the predicted vs measured signal does over time*, use:
| Need | Tool | Where the artifact lives |
|---|---|---|
| Graph (nodes + edges, hierarchy, state) | Mermaid `flowchart` / `sequenceDiagram` / `stateDiagram-v2` | inline in the wiki page |
| XY data (pump curves, prediction trace, drift over time) | Generated PNG/SVG via a small `npm run wiki:plots` script | committed under `wiki/_partial-plots/<NodeName>/*.svg` |
Lead with the visual that serves the section. Don't gate it on "is this Mermaid".
## Section list
Sections 1–9 and 11–14 are mandatory for every node. Section 10 (State chart) is mandatory for stateful nodes (`rotatingMachine`, `valve`, `pumpingStation`, …) and skipped for pure aggregators (`measurement`, `dashboardAPI`).
| 7 | Lifecycle | Mermaid `sequenceDiagram` | no |
| 8 | Data model — `getOutput()` | table + concrete sample | **yes** (`wiki:datamodel`) |
| 9 | Configuration — form ↔ config | Mermaid `flowchart TB` | no |
| 10 | State chart (stateful only) | Mermaid `stateDiagram-v2` | no |
| 11 | Examples | table + screenshots | no |
| 12 | Debug recipes | table | no |
| 13 | When NOT to use this node | bullets | no |
| 14 | Known limitations | table | no |
## Template — copy the block below as the seed for each node's wiki
(The block uses standard markdown syntax. The outer fence below is for visual delimitation in this README only; when seeding a new wiki page, copy the *content* between the `BEGIN TEMPLATE` / `END TEMPLATE` markers verbatim.)
> **Reflects code as of `<git short hash>` · regenerated `<YYYY-MM-DD>` via `npm run wiki:all`**
> If this banner is stale, the page may be out of date. Treat as informative, not authoritative.
## 1. What this node is
One paragraph, ≤ 60 words. Plain English. State the *role*, not the *implementation*.
> Example: "**rotatingMachine** models a single pump or compressor. It takes pressure measurements from upstream and downstream, predicts the resulting flow + power from supplier-provided characteristic curves, and drives a state machine for startup/shutdown sequences. Used as a child of `machineGroupControl` when grouped, or directly under a `pumpingStation`."
S88 colours are mandatory **inside hierarchy diagrams** (Mermaid `classDef`, flow.json group `style.fill`). They are NOT the node-palette swatch hexes shown in the Node-RED sidebar — those are domain-hue per node. Map (hierarchy use): Process Cell `#0c99d9`, Unit `#50a8d9`, Equipment `#86bbdd`, Control Module `#a9daee`. Source of truth: `.claude/rules/node-red-flow-layout.md` (§10.0 for palette, §10.1 for groups/lanes).
The **Unit** column reflects the descriptor's `units: { measure, default }` declaration, rendered as `<measure> (default <unit>)`. Topics without a `units` field (non-quantity payloads — mode strings, child ids, sequence triggers) show `—`. The default unit is what the commandRegistry coerces incoming `msg.unit` values to before the handler runs. The **Effect** column is sourced from the descriptor's `description` field; topics without one fall back to a generic per-prefix sentence.
What children this node accepts and what it does with each event the child can emit. Mirrors the `ChildRouter` declarations in `specificClass.js` → `configure()`.
**Concrete sample** (include only when the *shape* is hard to grok from the schema — e.g. nested objects, sparse keys, or unit conventions a newcomer would get wrong):
1. Section 2 (Position in the platform) appears **before any prose**. Diagrams lead.
2. Every section opens with a diagram, table, or chart. Prose annotates the visual; never the other way round.
3.**Max 60 words per paragraph.** A paragraph longer than that splits into bullets or moves into a table.
4. The topic contract (section 5) and data-model schema (section 8) are **auto-generated** between the `BEGIN AUTOGEN` / `END AUTOGEN` markers. Don't hand-edit between markers.
5. Mermaid is the default for graph structures. Use generated SVG/PNG for XY data (curves, time series). Use tables for facts.
6. Skip `classDiagram` (we don't expose classes to users) and `gantt` (no schedules in node docs).
7.**Concrete sample payloads must come from a known-good test run.** Made-up numbers rot silently.
8. S88 colour codes are non-negotiable in section 2. Match the palette in `.claude/rules/node-red-flow-layout.md`.
## Archive banner — paste at the top of every archived page
Archived pages move to `Archive/<NodeName>-pre-refactor.md` in the Gitea wiki repo. After moving, the page is read-only — corrections go on the current page, not the archive.
- **`generate-contract.js`** walks `src/commands/index.js`, emits one table row per descriptor between the topic-contract markers.
- **`generate-datamodel.js`** instantiates the domain with the default config, calls `getOutput()`, emits the abstract schema between the datamodel-schema markers. If `wiki/sample-output.fixture.json` exists, the concrete-sample block below the markers is also overwritten.
-`describeSchema` walks the lightweight `{type, properties}` schema and produces a one-line readable form.
| Gitea wiki UI | mirror — re-rendered from `wiki/` on push | No |
| Archived pre-refactor pages | `Archive/<NodeName>-pre-refactor.md` in the wiki repo | No (read-only after archival) |
The Gitea wiki repo is separate from each node's source repo. The `wiki/` directory in each node's repo is canonical; a `wiki-sync` workflow (not yet built) mirrors it into the Gitea wiki repo on each push to `development` / `main`.