Files
EVOLV/.claude/refactor/Archive/TASKS.md
Rene De Ren 253ac93896 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>
2026-05-18 15:48:46 +02:00

16 KiB
Raw Blame History

Task list — ARCHIVED

Warning

ARCHIVED — Phases 111 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. For current standards, start at ../../../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 (developmentmain).
  3. Open the parent EVOLV PR last (developmentmain).
  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