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:
119
.claude/refactor/Archive/CONTINUE_HERE.md
Normal file
119
.claude/refactor/Archive/CONTINUE_HERE.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# Continue here (fresh-context entry point) — ARCHIVED
|
||||
|
||||
> [!WARNING]
|
||||
> **ARCHIVED — the refactor described here landed on `development` in May 2026.**
|
||||
> This file describes the *plan* and the *deferred work as of 2026-05-11*. It is
|
||||
> retained for history. For current work, start at [`../../../CONTRACTS.md`](../../../CONTRACTS.md)
|
||||
> (EVOLV root) and the live standards in [`../`](../).
|
||||
|
||||
Original intro: read this file first if you're picking up the EVOLV refactor
|
||||
in a fresh session. It points at the durable plan and lists what's left.
|
||||
|
||||
## Read in order
|
||||
|
||||
1. `README.md` — refactor overview + the 11-phase plan
|
||||
2. `CONVENTIONS.md` — code style, file/function size, naming, testing
|
||||
3. `CONTRACTS.md` — the API shapes (BaseNodeAdapter, BaseDomain, commandRegistry, ChildRouter, UnitPolicy, statusBadge, LatestWinsGate, HealthStatus)
|
||||
4. `MODULE_SPLIT.md` — per-node module layout
|
||||
5. `TASKS.md` — phased plan; **Phases 1-11 are done** as of 2026-05-11
|
||||
6. `OPEN_QUESTIONS.md` — the live decisions log; most entries are RESOLVED
|
||||
7. `WIKI_TEMPLATE.md` + `WIKI_HOME_TEMPLATE.md` — the wiki shape every node uses
|
||||
|
||||
## Current state (verify with `npm run test:platform` from EVOLV root)
|
||||
|
||||
- **823 platform tests pass, 0 fail** across 12 submodules.
|
||||
- All 12 submodules + parent EVOLV are on `development` branches at
|
||||
`gitea.wbd-rd.nl/RnD/*` — never merged to `main` yet.
|
||||
- Docker stack runs natively in WSL via `docker compose up -d` (compose v2
|
||||
plugin installed at `~/.docker/cli-plugins/docker-compose`).
|
||||
- Every node has `wiki/Home.md` with the 14-section visual-first template;
|
||||
topic-contract + data-model sections auto-regenerate via
|
||||
`npm run wiki:all` in each submodule.
|
||||
|
||||
## What's NOT done (deferred, in priority order)
|
||||
|
||||
### 1. B5 — `reactor` `boundary-conditions` feature branch merge (BIG)
|
||||
|
||||
`origin/boundary-conditions` in `nodes/reactor/` is **8 commits ahead** of
|
||||
main, never merged before the refactor. Carries improved upstream/downstream
|
||||
boundary-condition handling, multi-parent support, and grid-position refactor.
|
||||
50 files changed, +2570 / -4151 lines. Conflicts heavily with the post-refactor
|
||||
`kinetics/{cstr,pfr,baseEngine}.js` structure.
|
||||
|
||||
**Approach:** same pattern that worked for pumpingStation `basin-docs-update`:
|
||||
- `cd nodes/reactor && git merge --no-commit --no-ff origin/boundary-conditions`
|
||||
- Resolve the ~4-6 conflicting files by keeping the refactor's BaseDomain +
|
||||
kinetics/ structure, porting the boundary-condition behavior into
|
||||
`kinetics/baseEngine.js` (BC application) + `kinetics/pfr.js` (grid).
|
||||
- All 46 reactor tests must stay green; ideally pick up any new tests the
|
||||
branch added.
|
||||
|
||||
Domain owner: needs to be in the loop. mathjs load means each test pass takes
|
||||
~15s — budget accordingly.
|
||||
|
||||
### 2. Phase 8 — `development → main` PRs (human review)
|
||||
|
||||
12 submodules + parent. Suggested merge order:
|
||||
- `generalFunctions` first (everything depends on it)
|
||||
- All 11 node submodules (any order)
|
||||
- Parent `EVOLV` last (carries the submodule pointers)
|
||||
|
||||
Each PR opened via gitea UI. Confirm Docker E2E per-node before merging
|
||||
(load `examples/0X-*.json` flows, verify behaviour). Squash or rebase per
|
||||
your team convention.
|
||||
|
||||
### 3. Small follow-ups still in `OPEN_QUESTIONS.md`
|
||||
|
||||
These are individually small (≤ half-day each):
|
||||
|
||||
| Entry | Action |
|
||||
|---|---|
|
||||
| pumpingStation `overfillVol` alias | Drop the parallel `overfillVol → highVolumeSafetyVol` alias in `src/basin/thresholdValidator.js`. Same shape as the already-done `overfillLevel` drop. |
|
||||
| MGC `calcGroupEfficiency.maxEfficiency` naming | `maxEfficiency` actually returns the mean. Rename to `meanEfficiency` everywhere; update call sites + downstream telemetry consumers (search the platform for the key). |
|
||||
| `predictionHealth` migration in rotatingMachine | Decide where `confidence` (numeric 0..1) lives now that HealthStatus is standardised. Default chosen: keep as sibling field on the drift container, not inside HealthStatus. Implement the migration if/when rotatingMachine drift output gets a v2 contract. |
|
||||
| dashboardAPI no BaseDomain | Documented in OPEN_QUESTIONS. dashboardAPI is a passive HTTP server; doesn't fit BaseDomain. Confirm with team whether to revisit. |
|
||||
| measurement legacy property mirrors | The new specificClass kept some legacy `inputValue`/`outputAbs` getter/setter mirrors for back-compat. Decide if any can be removed in a v2. |
|
||||
| measurement `handleScaling` mutates `config.scaling` | Channel's `_applyScaling` mutates its own config copy when input range collapses; bridged via a 2-line mirror-back to `config.scaling`. Decide if Channel should not mutate at all, OR if the bridge is the right contract. |
|
||||
| MGC `calcAbsoluteTotals` pressure-key coupling | Implicitly assumes flow.inputCurve and power.inputCurve keys are paired. Add a guard or document. |
|
||||
| rotatingMachine `_pendingExtras` constructor workaround | The 3-positional-arg constructor (`machineConfig, stateConfig, errorMetricsConfig`) is bridged via a `Machine._pendingExtras` static stash from buildDomainConfig. Cleaner approach: include state + errorMetrics in the validated config schema directly. |
|
||||
| reactor schema enum lowercases `reactor_type` | The validator lowercases enum values; `_buildEngine` upper-cases before switching as a guard. Standardise schema enum casing — drop the guard. |
|
||||
| reactor mathjs runtime (~13s per test file) | Hoist a single mathjs instance at module top OR switch to tree-shaken mathjs subset. Drops test suite runtime from ~3 min to ~10 s. |
|
||||
| valveGroupControl `set.position` placeholder | Currently a debug-logged no-op. Implement or remove. |
|
||||
|
||||
### 4. Phase 9 follow-ups (wiki cosmetics)
|
||||
|
||||
These came up during the wiki rollout:
|
||||
|
||||
- **Header banner auto-stamping**: `WIKI_TEMPLATE.md` instructs writers to put the
|
||||
git short hash + regen date in the header. `wikiGen.js` doesn't currently
|
||||
rewrite that banner. Either add a banner-rewrite or change the template to
|
||||
"manually set when authoring".
|
||||
- **Curve-data-model auto-gen warnings**: rotatingMachine + valve emit
|
||||
`Asset 'Unknown' not found` to stderr when wikiGen instantiates the domain
|
||||
with no curve. Either suppress the noise (catch in wikiGen) or document.
|
||||
- **Data-model AUTOGEN "sample value" placeholder**: Most nodes' `getOutput()`
|
||||
is trivially small in a stub-construction context (no children registered).
|
||||
Template should explicitly tell authors to supplement with a hand-curated
|
||||
concrete sample block under the markers.
|
||||
|
||||
## How to verify nothing has rotted
|
||||
|
||||
```bash
|
||||
# From /mnt/d/gitea/EVOLV:
|
||||
|
||||
# 1. fetch latest from origin
|
||||
git fetch --recurse-submodules
|
||||
|
||||
# 2. confirm everything still green
|
||||
npm run test:platform # expect 823 / 0
|
||||
|
||||
# 3. confirm Docker still healthy (if compose stack is running)
|
||||
docker compose ps
|
||||
curl -sf http://localhost:1880/nodes | wc -c # > 0 means Node-RED is up
|
||||
|
||||
# 4. confirm submodule branches are still development
|
||||
git submodule foreach --quiet 'echo "$name $(git rev-parse --abbrev-ref HEAD)"'
|
||||
```
|
||||
|
||||
If any of those drift from the expected state, that's the first thing to
|
||||
investigate before touching new work.
|
||||
299
.claude/refactor/Archive/TASKS.md
Normal file
299
.claude/refactor/Archive/TASKS.md
Normal file
@@ -0,0 +1,299 @@
|
||||
# Task list — ARCHIVED
|
||||
|
||||
> [!WARNING]
|
||||
> **ARCHIVED — Phases 1–11 landed on `development` in May 2026.**
|
||||
> This file is the original phased plan and is retained for history. For
|
||||
> deferred / open work, see [`../OPEN_QUESTIONS.md`](../OPEN_QUESTIONS.md).
|
||||
> For current standards, start at [`../../../CONTRACTS.md`](../../../CONTRACTS.md) (EVOLV root).
|
||||
|
||||
Phased and ordered. The TaskCreate tracker mirrors this list and is the
|
||||
active, mutable view; this file is the durable plan.
|
||||
|
||||
A task is **done** when:
|
||||
- The code matches the contracts in `CONTRACTS.md`.
|
||||
- All the affected node's tests are green (`node --test test/basic
|
||||
test/integration test/edge`).
|
||||
- A short note is appended in the task tracker if anything was deferred
|
||||
to `OPEN_QUESTIONS.md`.
|
||||
|
||||
## Phase 1 — `generalFunctions` additive infra
|
||||
|
||||
Goal: add the new platform pieces. Nothing is removed; nothing existing
|
||||
changes shape. All existing nodes continue to work unchanged.
|
||||
|
||||
| # | Task | Notes |
|
||||
|---|---|---|
|
||||
| 1.1 | Add `src/domain/UnitPolicy.js` + tests | Extracted from `rotatingMachine._buildUnitPolicy`. |
|
||||
| 1.2 | Add `src/domain/ChildRouter.js` + tests | Built on existing `childRegistrationUtils`. |
|
||||
| 1.3 | Add `src/domain/LatestWinsGate.js` + tests | Extracted from MGC `_dispatchInFlight`/`_delayedCall`. |
|
||||
| 1.4 | Add `src/domain/HealthStatus.js` + tests | Standardise the `{level, flags, message, source}` shape. |
|
||||
| 1.5 | Add `src/domain/BaseDomain.js` + tests | Constructor boilerplate; calls subclass `configure()`/`_init()`. |
|
||||
| 1.6 | Add `src/nodered/commandRegistry.js` + tests | Topic dispatch + alias warnings. |
|
||||
| 1.7 | Add `src/nodered/statusBadge.js` + tests | `compose`, `error`, `idle`, `byState` helpers. |
|
||||
| 1.8 | Add `src/nodered/statusUpdater.js` + tests | 1 Hz poller calling `source.getStatusBadge()`. |
|
||||
| 1.9 | Add `src/nodered/BaseNodeAdapter.js` + tests | The thing every nodeClass extends. |
|
||||
| 1.10 | Add `src/stats/index.js` + tests | Promote mean/stdDev/median/mad/lerp from `measurement`. |
|
||||
| 1.11 | Update `generalFunctions/index.js` (additive) | New exports under existing pattern. |
|
||||
| 1.12 | Run all 12 nodes' tests against the bumped `generalFunctions` | Sanity gate before phase 2. |
|
||||
|
||||
Phase-1 commit cadence: one commit per task on the `development` branch
|
||||
of `generalFunctions`. Submodule pointer in parent EVOLV bumps **once**
|
||||
at end of phase.
|
||||
|
||||
## Phase 2 — pumpingStation pilot
|
||||
|
||||
Goal: prove the new infrastructure end-to-end. Pumping station is a
|
||||
mid-complexity node — bigger than measurement, smaller than the
|
||||
curve-driven nodes.
|
||||
|
||||
| # | Task | Notes |
|
||||
|---|---|---|
|
||||
| 2.1 | Move standalone demo from `specificClass.js` to `examples/standalone-demo.js` | Pure deletion + move; tests unchanged. |
|
||||
| 2.2 | Extract `basin/` (BasinGeometry + thresholdValidator) | Pure functions. |
|
||||
| 2.3 | Extract `measurement/flowAggregator.js` (incl. `_updatePredictedVolume`) | Centerpiece of the tick loop. |
|
||||
| 2.4 | Extract `measurement/measurementRouter.js` + `measurement/calibration.js` | |
|
||||
| 2.5 | Extract `control/` strategies + dispatcher | levelBased, flowBased (stub), manual. |
|
||||
| 2.6 | Extract `safety/safetyController.js` | dryRunRule + overfillRule split internally. |
|
||||
| 2.7 | Add `getStatusBadge()` on `PumpingStation`; remove badge logic from nodeClass | |
|
||||
| 2.8 | Convert `nodeClass.js` to extend `BaseNodeAdapter` | |
|
||||
| 2.9 | Convert `specificClass.js` to extend `BaseDomain` | Use `ChildRouter`, `UnitPolicy`. |
|
||||
| 2.10 | Extract `commands/` registry + handlers | Old topic names become aliases. |
|
||||
| 2.11 | Extract `editor.js` from `pumpingStation.html` (the SVG redraw logic) | Served via a `/pumpingStation/editor.js` admin endpoint. |
|
||||
| 2.12 | Generate `CONTRACT.md` from `commands/` + handwritten events section | |
|
||||
| 2.13 | Tests: 3-tier per extracted module + the existing suite still green | Add edge tests for any regression discovered. |
|
||||
| 2.14 | Docker E2E (deploy `01-basic`/`02-integration`/`03-dashboard` flows on a running Node-RED) | Required for "trial-ready" claim. |
|
||||
|
||||
## Phase 3 — measurement
|
||||
|
||||
| # | Task | Notes |
|
||||
|---|---|---|
|
||||
| 3.1 | Promote stats helpers to `generalFunctions/src/stats/` (already done in 1.10) | |
|
||||
| 3.2 | Convert analog mode to use `Channel` internally (with `key=null`) | Removes the ~400-line inline pipeline duplication. |
|
||||
| 3.3 | Extract `simulation/simulator.js` | |
|
||||
| 3.4 | Extract `calibration/calibrator.js` | |
|
||||
| 3.5 | Add `getStatusBadge()` on `Measurement` | |
|
||||
| 3.6 | Convert `nodeClass.js` to `BaseNodeAdapter`; `specificClass.js` to `BaseDomain` | |
|
||||
| 3.7 | Extract `commands/` | |
|
||||
| 3.8 | `CONTRACT.md` | |
|
||||
| 3.9 | Tests + Docker E2E | |
|
||||
|
||||
## Phase 4 — machineGroupControl
|
||||
|
||||
| # | Task | Notes |
|
||||
|---|---|---|
|
||||
| 4.1 | Extract `groupOps/` (groupOperatingPoint + groupCurves) | The cluster of `_group*` helpers. |
|
||||
| 4.2 | Extract `totals/totalsCalculator.js` | |
|
||||
| 4.3 | Extract `combinatorics/pumpCombinations.js` | |
|
||||
| 4.4 | Extract `optimizer/bestCombination.js` + `optimizer/bepGravitation.js` | |
|
||||
| 4.5 | Extract `efficiency/groupEfficiency.js` | |
|
||||
| 4.6 | Extract `dispatch/demandDispatcher.js` using `LatestWinsGate` | Replaces `_dispatchInFlight`/`_delayedCall` directly. |
|
||||
| 4.7 | Add `getStatusBadge()` | |
|
||||
| 4.8 | Convert nodeClass + specificClass to base classes; use `ChildRouter` | |
|
||||
| 4.9 | `commands/` + `CONTRACT.md` | |
|
||||
| 4.10 | Tests + Docker E2E | |
|
||||
|
||||
## Phase 5 — rotatingMachine
|
||||
|
||||
| # | Task | Notes |
|
||||
|---|---|---|
|
||||
| 5.1 | Extract `curves/` (loader + normalizer + reverseCurve) | |
|
||||
| 5.2 | Extract `prediction/` (predictors + groupPredictors + operatingPoint) | |
|
||||
| 5.3 | Extract `drift/` using `HealthStatus` | |
|
||||
| 5.4 | Extract `pressure/` (virtual children + initialization + router) | |
|
||||
| 5.5 | Extract `state/stateBindings.js` (adapter to existing `generalFunctions/state`) | |
|
||||
| 5.6 | Extract `measurement/measurementHandlers.js` | |
|
||||
| 5.7 | Extract `flow/flowController.js` | |
|
||||
| 5.8 | Extract `display/workingCurves.js` | |
|
||||
| 5.9 | Add `getStatusBadge()` (replaces the 100-line nodeClass version) | |
|
||||
| 5.10 | Convert nodeClass + specificClass | |
|
||||
| 5.11 | `commands/` + `CONTRACT.md` | |
|
||||
| 5.12 | Tests + Docker E2E | |
|
||||
|
||||
## Phase 6 — remaining nodes
|
||||
|
||||
For each: skeleton refactor only — extend `BaseNodeAdapter` + `BaseDomain`, use `ChildRouter`, move the input switch to `commands/`, add
|
||||
`getStatusBadge()`. Domain-specific module split only if `specificClass` > 300 lines after the platform refactor.
|
||||
|
||||
| # | Task |
|
||||
|---|---|
|
||||
| 6.1 | `valve` |
|
||||
| 6.2 | `valveGroupControl` |
|
||||
| 6.3 | `diffuser` |
|
||||
| 6.4 | `monster` |
|
||||
| 6.5 | `settler` |
|
||||
| 6.6 | `reactor` |
|
||||
| 6.7 | `dashboardAPI` (special — likely no `BaseDomain`, it's a passive HTTP server) |
|
||||
|
||||
These are parallelisable — each can be its own agent.
|
||||
|
||||
## Phase 7 — remove legacy topic aliases
|
||||
|
||||
> **Note:** canonical names (`set.*`, `cmd.*`, `data.*`, `child.*`,
|
||||
> `query.*`, `evt.*`) are used **from Phase 1 onwards** — see
|
||||
> `CONTRACTS.md §1`. Each `commands/index.js` declares the canonical
|
||||
> name as `topic` and lists pre-refactor names in `aliases`. So Phase 7
|
||||
> is just the deprecation-window sweep.
|
||||
|
||||
| # | Task | Notes |
|
||||
|---|---|---|
|
||||
| 7.1 | Audit aliases across all `commands/` files; confirm one release cycle has elapsed | If any alias was added recently, defer that node's removal another cycle. |
|
||||
| 7.2 | Remove `aliases` entries; canonical name only | Each removal is a single PR. |
|
||||
| 7.3 | Update example flows that still used legacy names | Should already have been updated in their phase. |
|
||||
| 7.4 | Document the removal in each `CONTRACT.md` | "Removed legacy topic X (replaced by canonical Y) on YYYY-MM-DD". |
|
||||
|
||||
## Phase 8 — promotion to main
|
||||
|
||||
When every node is on the new infra and Docker E2E green:
|
||||
1. Bump submodule pointers in parent EVOLV `development`.
|
||||
2. Open a PR per submodule (`development` → `main`).
|
||||
3. Open the parent EVOLV PR last (`development` → `main`).
|
||||
4. Merge in dependency order (`generalFunctions` first, then nodes that
|
||||
depend on it, finally `EVOLV`).
|
||||
|
||||
## Phase 8.5 — `generalFunctions` deprecated path cleanup
|
||||
|
||||
Removes the deprecated paths flagged in `OPEN_QUESTIONS.md`. Runs after
|
||||
promotion to `main` (so callers have stopped depending on the old
|
||||
paths via the platform's own consumers).
|
||||
|
||||
### Targets to remove
|
||||
|
||||
| Path | Replaced by | First flagged |
|
||||
|---|---|---|
|
||||
| `src/helper/menuUtils_DEPRECATED.js` | `src/menu/` (the active menu manager) | pre-refactor |
|
||||
| `loadCurve` export (in `index.js` + `datasets/assetData/curves/`) | `loadModel` | pre-refactor |
|
||||
| Any `*_DEPRECATED.*` file added during the refactor | (per-file note) | refactor |
|
||||
|
||||
### Tasks
|
||||
|
||||
| # | Task | Notes |
|
||||
|---|---|---|
|
||||
| 8.5.1 | Audit consumers of `loadCurve` across all nodes | Should be zero after Phase 5 (rotatingMachine) — verify. |
|
||||
| 8.5.2 | Remove `loadCurve` export + the underlying file | Single PR. Test all nodes. |
|
||||
| 8.5.3 | Remove `menuUtils_DEPRECATED.js` | Verify zero imports first. |
|
||||
| 8.5.4 | Sweep `generalFunctions/src/` for `_DEPRECATED.*` files; remove with consumer audit | One PR per file. |
|
||||
| 8.5.5 | Update `generalFunctions` README to drop deprecated references | |
|
||||
|
||||
## Phase 9 — wiki cleanup (post-refactor)
|
||||
|
||||
Goal: each node's gitea wiki becomes **visual-first**, scannable, and
|
||||
follows one shared template. Today's wiki has lots of prose and varies
|
||||
per node — once the platform is uniform, the wiki should be too.
|
||||
|
||||
Don't start phase 9 until phase 8 is done (the wiki documents the
|
||||
post-refactor shape, not the in-flight transition).
|
||||
|
||||
### Standard wiki template (one file per node, this is the spec)
|
||||
|
||||
```
|
||||
1. One-paragraph "what is this node" (≤ 60 words).
|
||||
2. Position in the platform — a Mermaid block showing the node and its
|
||||
typical neighbours (parent + child types, with arrows for
|
||||
data direction).
|
||||
3. Capability matrix — small table of "what this node can do" with
|
||||
✅ / ❌ / partial.
|
||||
4. Topic contract — auto-generated from src/commands/index.js
|
||||
(set.* / cmd.* / evt.* / data.* — payload schema and example).
|
||||
5. Output payload — a Mermaid sequence-diagram of a typical tick
|
||||
(parent → child → measurement → tick → port-0 emit).
|
||||
6. Configuration — a Mermaid block diagram of the editor form sections
|
||||
plus a table mapping each form field to the config key it lands at.
|
||||
7. Examples — links to examples/01-basic, 02-integration, 03-dashboard
|
||||
with one screenshot each.
|
||||
8. State / mode chart — Mermaid stateDiagram for any node with
|
||||
non-trivial states (rotatingMachine, pumpingStation, MGC).
|
||||
9. "When you would NOT use this node" — explicit non-goals.
|
||||
10. Issues / known limitations — single-line items with links to
|
||||
repo issues.
|
||||
```
|
||||
|
||||
### Tasks
|
||||
|
||||
| # | Task | Notes |
|
||||
|---|---|---|
|
||||
| 9.1 | Author the canonical wiki template at `.claude/refactor/WIKI_TEMPLATE.md` (or the repo-mem rule path) | Source of truth. |
|
||||
| 9.2 | Build the auto-generator: `commands/index.js` → "Topic contract" markdown section | Run via a small `npm run wiki:contract` script per node. |
|
||||
| 9.3 | Pilot on `pumpingStation` wiki: replace existing pages with the new template | Visual-first, prune prose. |
|
||||
| 9.4 | Apply to other 3 core nodes (`measurement`, `MGC`, `rotatingMachine`) | |
|
||||
| 9.5 | Apply to remaining nodes (one per repo) | |
|
||||
| 9.6 | Update parent EVOLV wiki: top-level platform overview with a Mermaid block of all 13 nodes and how they connect (S88 hierarchy + data direction) | |
|
||||
| 9.7 | Add a wiki style guide (max prose per section, where Mermaid is required, screenshot conventions) | |
|
||||
| 9.8 | Audit pass: every page renders, every Mermaid block compiles, every link resolves | |
|
||||
|
||||
### Visual primitives we'll lean on (Mermaid)
|
||||
|
||||
- `flowchart LR` — node connections (parent ↔ child, data direction).
|
||||
- `sequenceDiagram` — tick-to-port-0 lifecycle.
|
||||
- `stateDiagram-v2` — rotatingMachine / pumpingStation state machines.
|
||||
- `erDiagram` — only if a node has a complex internal data model worth
|
||||
visualising.
|
||||
|
||||
Skip: classDiagram (we don't expose classes to users); gantt (no
|
||||
schedules in a node's docs).
|
||||
|
||||
### Hard rules
|
||||
|
||||
- Every page leads with the Mermaid platform-position block. No "intro
|
||||
paragraph then later a diagram" — diagram first.
|
||||
- Each section opens with the diagram or table; prose annotates the
|
||||
visual, not the other way round.
|
||||
- No more than 60 words of unbroken prose anywhere on a page.
|
||||
- One canonical source of truth for the topic contract: `commands/index.js`.
|
||||
The wiki page is generated from it. No hand-written drift.
|
||||
|
||||
## Phase 10 — test-suite refactor (post-wiki)
|
||||
|
||||
Goal: bring every node's test layout in line with `CONVENTIONS.md §Testing`
|
||||
now that the platform is uniform. Pre-existing test debt logged in
|
||||
`OPEN_QUESTIONS.md` gets cleaned up here.
|
||||
|
||||
### Tasks
|
||||
|
||||
| # | Task | Notes |
|
||||
|---|---|---|
|
||||
| 10.1 | Audit each node: basic / integration / edge split, naming, helpers | One pass; produce a per-node punch list. |
|
||||
| 10.2 | Convert any Mocha-style tests (`describe`/`it`) to `node:test` | Specifically `dashboardAPI/test/basic/structure-module-load.basic.test.js`. |
|
||||
| 10.3 | Address `reactor` mathjs load (per OPEN_QUESTIONS): tree-shake or hoist | If hoisted, document the pattern as a CONVENTION addition. |
|
||||
| 10.4 | Promote shared test helpers to `generalFunctions/test/helpers/` | Common fakes: fake Node-RED node, fake child, fake RED. |
|
||||
| 10.5 | Add missing edge tests for each refactored module flagged during P2-P5 | Edge cases discovered during refactor land here. |
|
||||
| 10.6 | Make every basic-test runner exit cleanly in batch (`node --test test/basic/`) | No leaked timers, no real `setInterval` outliving the assertions. Mirrors the BaseNodeAdapter test fix. |
|
||||
| 10.7 | Standard CI shape: each node has `npm run test:basic`, `test:integration`, `test:edge` (consistent across nodes) | Allows uniform CI invocation. |
|
||||
| 10.8 | Audit pass: every node's test suite green in batch under one wall-clock budget (≤ 60 s for basic) | The new platform-wide gate. |
|
||||
|
||||
## Phase 11 — unit-aware commands
|
||||
|
||||
Goal: every numeric setter / data topic carries an explicit unit; the user
|
||||
can supply any compatible unit and the commandRegistry normalises before
|
||||
the handler runs. Unknown units warn + list accepted alternatives.
|
||||
|
||||
### Tasks
|
||||
|
||||
| # | Task | Notes |
|
||||
|---|---|---|
|
||||
| 11.1 | `generalFunctions/src/convert/`: add `possibilities(measure)` helper | Returns the list of accepted unit names for a measure (`volumeFlowRate`, `pressure`, etc.). |
|
||||
| 11.2 | `generalFunctions/src/nodered/commandRegistry.js`: handle `descriptor.units` | Normalisation pipeline: extract value+unit from msg, validate against `units.measure`, convert to `units.default`, warn + fall back on bad input. Tests for all 4 paths (no-unit / valid / wrong-measure / unknown). |
|
||||
| 11.3 | `generalFunctions/src/nodered/BaseNodeAdapter.js`: auto-wire `query.units` topic | Returns `{ topic → { measure, default, accepted: [...] } }` from the registry. No per-node wiring needed. |
|
||||
| 11.4 | `generalFunctions/scripts/wikiGen.js`: render `units` column | Topic-contract auto-gen table grows a Unit column showing `measure (default <unit>)`. |
|
||||
| 11.5 | Per-node `src/commands/index.js`: declare `units` on every numeric setter | ~10 nodes. See proposed default-units table in interview reply. |
|
||||
| 11.6 | Regenerate every `CONTRACT.md` + wiki `Home.md` via `npm run wiki:all` | Automated. |
|
||||
| 11.7 | Tests: commandRegistry unit-handling paths | 4 scenarios per the validation table. |
|
||||
|
||||
### Default units per topic (proposed)
|
||||
|
||||
| Topic | Default | Why |
|
||||
|---|---|---|
|
||||
| pumpingStation `set.inflow` | `m3/h` | Operator-friendly scale |
|
||||
| pumpingStation `set.demand` | `m3/h` | same |
|
||||
| pumpingStation `set.outflow` | `m3/h` | symmetric |
|
||||
| pumpingStation `cmd.calibrate.volume` | `m3` | basin volume |
|
||||
| pumpingStation `cmd.calibrate.level` | `m` | basin height |
|
||||
| MGC `set.demand` | `m3/h` | matches PS |
|
||||
| rotatingMachine `set.setpoint` | `%` | control% |
|
||||
| rotatingMachine `set.flow-setpoint` | `m3/h` | flow target |
|
||||
| rotatingMachine `data.simulate-measurement` | per `payload.type` | dispatch by sensor type |
|
||||
| valve `set.position` | `%` | valve open-% |
|
||||
| measurement `data.measurement` | mode-dependent | analog → Channel scaling; digital → per-channel cfg |
|
||||
| monster `data.flow` | `m3/h` | already enforced |
|
||||
| reactor `data.influent` | flow=m3/h, concentrations=mg/L | engine internals |
|
||||
| settler `data.influent` | flow=m3/h, concentrations=mg/L | matches reactor |
|
||||
| diffuser `data.flow` | `m3/h` | air flow scale |
|
||||
Reference in New Issue
Block a user