Migrate to new Gitea instance (gitea.wbd-rd.nl)
- Update all submodule URLs from gitea.centraal.wbd-rd.nl to gitea.wbd-rd.nl - Add settler as proper submodule in .gitmodules - Add agent skills, function anchors, decisions, and improvements - Add Docker configuration and scripts - Add manuals and third_party docs - Update .gitignore with secrets and build artifacts - Remove stale .tgz build artifact Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>PumpingStation Anchor Map</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg: #f5f7fb;
|
||||
--panel: #ffffff;
|
||||
--line: #9ab0d9;
|
||||
--text: #14233d;
|
||||
--muted: #4d6084;
|
||||
--pump: #0c99d9;
|
||||
--child: #e7faf5;
|
||||
--sensor: #eef8e8;
|
||||
--dash: #fff5e5;
|
||||
}
|
||||
body { margin: 0; font-family: "Segoe UI", sans-serif; background: var(--bg); color: var(--text); }
|
||||
.wrap { max-width: 1100px; margin: 24px auto; padding: 0 16px 24px; }
|
||||
.panel { background: var(--panel); border: 1px solid #dde5f5; border-radius: 12px; padding: 16px; }
|
||||
h1 { margin: 0 0 8px; font-size: 24px; }
|
||||
p { margin: 0 0 12px; color: var(--muted); }
|
||||
.chips { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
|
||||
.chip { border: 1px solid #d1ddf5; border-radius: 999px; padding: 4px 10px; background: #f7faff; font-size: 12px; }
|
||||
svg { width: 100%; height: auto; border-radius: 10px; background: #f9fbff; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
<div class="panel">
|
||||
<h1>PumpingStation Function Anchor</h1>
|
||||
<p>Preparation baseline map. Keep this topology in sync with `ANCHOR-pumpingStation.md` and runtime contracts.</p>
|
||||
<div class="chips">
|
||||
<span class="chip">input: registerChild / calibrate* / q_in / changemode</span>
|
||||
<span class="chip">output[0]: process</span>
|
||||
<span class="chip">output[1]: influx</span>
|
||||
<span class="chip">output[2]: registerChild</span>
|
||||
</div>
|
||||
<svg viewBox="0 0 900 360" role="img" aria-label="PumpingStation integration map">
|
||||
<defs>
|
||||
<marker id="arr" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto">
|
||||
<path d="M0,0 L0,6 L9,3 z" fill="#6f85aa"></path>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect x="360" y="140" width="180" height="72" rx="10" fill="var(--pump)"></rect>
|
||||
<text x="450" y="182" text-anchor="middle" fill="#fff" font-size="16">pumpingStation</text>
|
||||
|
||||
<rect x="40" y="40" width="210" height="56" rx="9" fill="var(--child)" stroke="#9edcca"></rect>
|
||||
<text x="145" y="74" text-anchor="middle" fill="#1e5244" font-size="13">machine / machineGroupControl</text>
|
||||
|
||||
<rect x="40" y="250" width="210" height="56" rx="9" fill="var(--sensor)" stroke="#b7d89e"></rect>
|
||||
<text x="145" y="284" text-anchor="middle" fill="#2e5a22" font-size="13">measurement (level/flow/pressure)</text>
|
||||
|
||||
<rect x="650" y="40" width="210" height="56" rx="9" fill="var(--dash)" stroke="#e9c589"></rect>
|
||||
<text x="755" y="74" text-anchor="middle" fill="#634319" font-size="13">dashboard / manual control</text>
|
||||
|
||||
<rect x="650" y="250" width="210" height="56" rx="9" fill="#e9f1ff" stroke="#aac0ef"></rect>
|
||||
<text x="755" y="284" text-anchor="middle" fill="#244271" font-size="13">parent process / orchestrator</text>
|
||||
|
||||
<line x1="250" y1="68" x2="360" y2="152" stroke="var(--line)" stroke-width="2" marker-end="url(#arr)"></line>
|
||||
<line x1="250" y1="278" x2="360" y2="198" stroke="var(--line)" stroke-width="2" marker-end="url(#arr)"></line>
|
||||
<line x1="650" y1="68" x2="540" y2="150" stroke="var(--line)" stroke-width="2" marker-end="url(#arr)"></line>
|
||||
<line x1="540" y1="202" x2="650" y2="278" stroke="var(--line)" stroke-width="2" marker-end="url(#arr)"></line>
|
||||
|
||||
<text x="268" y="128" fill="var(--muted)" font-size="12">flow.predicted.* / control handoff</text>
|
||||
<text x="260" y="240" fill="var(--muted)" font-size="12">*.measured.<position></text>
|
||||
<text x="566" y="128" fill="var(--muted)" font-size="12">q_in / calibrate / mode</text>
|
||||
<text x="560" y="240" fill="var(--muted)" font-size="12">registerChild + process/influx consumers</text>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,69 @@
|
||||
# Pumping Station Function Anchor (Preparation Baseline)
|
||||
|
||||
## 0) Connection Map (At a Glance)
|
||||
- **Node type**: `pumpingStation` (`nodes/pumpingStation/pumpingStation.js:1`, `nodes/pumpingStation/pumpingStation.html:15`)
|
||||
- **Consumes parent/control topics**: `changemode`, `registerChild`, `calibratePredictedVolume`, `calibratePredictedLevel`, `q_in` (`nodes/pumpingStation/src/nodeClass.js:209`)
|
||||
- **Publishes periodic outputs**:
|
||||
- Output `0`: process payload (`nodes/pumpingStation/src/nodeClass.js:197`)
|
||||
- Output `1`: influx payload (`nodes/pumpingStation/src/nodeClass.js:198`)
|
||||
- Output `2`: parent registration/control plumbing (`registerChild`) (`nodes/pumpingStation/src/nodeClass.js:114`)
|
||||
- **Cross-node integrations (direct observed)**:
|
||||
- Registers `measurement` children and listens for `*.measured.<position>` events (`nodes/pumpingStation/src/specificClass.js:73`)
|
||||
- Registers `machine`, `machinegroup`, `pumpingstation` children and listens for predicted flow (`nodes/pumpingStation/src/specificClass.js:59`)
|
||||
- Commands child machines/stations/groups during control/safety transitions (`nodes/pumpingStation/src/specificClass.js:258`, `nodes/pumpingStation/src/specificClass.js:528`)
|
||||
- **Admin/UI endpoints**:
|
||||
- `GET /pumpingStation/menu.js`
|
||||
- `GET /pumpingStation/configData.js` (`nodes/pumpingStation/pumpingStation.js:22`, `nodes/pumpingStation/pumpingStation.js:33`)
|
||||
|
||||
## 1) Unit Table (Initial Baseline)
|
||||
| Signal/Field | Represents | Default Unit | Source of Truth | Produced By | Consumed By | Fallback/Degraded Behavior |
|
||||
|---|---|---|---|---|---|---|
|
||||
| `flow.measured.*` / `flow.predicted.*` | inflow/outflow streams | `m3/s` preferred | `nodes/pumpingStation/src/specificClass.js:24` | measurement/machine/machinegroup children | net-flow selection + predicted volume integration | falls back to level-rate estimate when unavailable (`nodes/pumpingStation/src/specificClass.js:458`) |
|
||||
| `level.measured.*` / `level.predicted.*` | wet well level | `m` | `nodes/pumpingStation/src/specificClass.js:24` | measurement or pressure conversion path | control decisions + remaining-time estimate | if no level available, remaining time becomes null (`nodes/pumpingStation/src/specificClass.js:487`) |
|
||||
| `volume.predicted.atequipment` | integrated basin volume | `m3` | `nodes/pumpingStation/src/specificClass.js:393` | tick-based integration | safety + status + output | if volume unreadable, station shuts down machines availability-first (`nodes/pumpingStation/src/specificClass.js:503`) |
|
||||
| `volumePercent.*.atequipment` | normalized fill percentage | `%` | `nodes/pumpingStation/src/specificClass.js:424` | level/volume conversion | status + dashboards | not emitted until level/volume is known |
|
||||
| `netFlowRate.*.atequipment` | selected net flow | measured unit or `m3/s` | `nodes/pumpingStation/src/specificClass.js:454` | `_selectBestNetFlow()` | status + remaining-time + safety | defaults to `0` with `steady` direction (`nodes/pumpingStation/src/specificClass.js:466`) |
|
||||
| `timeleft` | estimated seconds to empty/full limit | `s` | `nodes/pumpingStation/src/specificClass.js:470` | `_computeRemainingTime()` | safety logic + output | null if insufficient data |
|
||||
|
||||
## 2) Class Identity
|
||||
- **Runtime registration + endpoints**: `nodes/pumpingStation/pumpingStation.js`
|
||||
- **Node-RED wrapper/routing**: `nodes/pumpingStation/src/nodeClass.js`
|
||||
- **Domain/station logic**: `nodes/pumpingStation/src/specificClass.js`
|
||||
- **Editor UI/defaults**: `nodes/pumpingStation/pumpingStation.html`
|
||||
- **Default config schema/validation rules**: `nodes/generalFunctions/src/configs/pumpingStation.json`
|
||||
|
||||
## 3) Current Gaps To Resolve Before Declaring Anchor Complete
|
||||
1. Topic/mode mismatch:
|
||||
- UI default uses `controlMode: "none"` (`nodes/pumpingStation/pumpingStation.html:59`)
|
||||
- runtime switch expects `manual` not `none` (`nodes/pumpingStation/src/specificClass.js:234`)
|
||||
2. Position token mismatch risk:
|
||||
- code mixes `atEquipment` and `atequipment` variants (`nodes/pumpingStation/src/nodeClass.js:122`, `nodes/pumpingStation/src/specificClass.js:103`)
|
||||
3. Child softwareType mismatch risk:
|
||||
- checks for `'pumpingstation'`/`'machinegroup'` lowercase (`nodes/pumpingStation/src/specificClass.js:61`, `nodes/pumpingStation/src/specificClass.js:63`)
|
||||
- other configs generally use camelCase (`nodes/generalFunctions/src/configs/pumpingStation.json:48`)
|
||||
4. Missing guards in input registration path:
|
||||
- no null check after `RED.nodes.getNode` (`nodes/pumpingStation/src/nodeClass.js:217`)
|
||||
5. Test baseline exists but is not yet full parity:
|
||||
- basic/edge/integration scaffolding is present; additional safety/control math coverage is still pending.
|
||||
|
||||
## 4) Standardization Plan (Mirror RotatingMachine)
|
||||
1. Create `ANCHOR-pumpingStation.html` with:
|
||||
- always-visible topology map
|
||||
- unit/signal catalog table
|
||||
- control and safety flow diagram
|
||||
- known invariants and risk list
|
||||
2. Expand the current unit/integration/edge test suite under `nodes/pumpingStation/test/`:
|
||||
- config defaults/overrides
|
||||
- topic routing and child registration
|
||||
- predicted volume integration and remaining-time math
|
||||
- safety triggers and control actions
|
||||
- regression for string casing mismatches and missing child node IDs
|
||||
3. Add evidence companion doc:
|
||||
- `EVIDENCE-pumpingStation-tests.md` with fail-before/pass-after references.
|
||||
4. Keep this anchor and tests updated on every pumpingStation behavior change.
|
||||
|
||||
## 5) Acceptance Criteria For Completion
|
||||
- Anchor markdown complete to template parity with rotatingMachine.
|
||||
- Anchor HTML visualization added and aligned with actual contracts.
|
||||
- Test suite runnable with `node --test nodes/pumpingStation/test/**/*.test.js`.
|
||||
- Evidence file links each test file to anchored behavior.
|
||||
@@ -0,0 +1,34 @@
|
||||
# PumpingStation Test Evidence (Preparation)
|
||||
|
||||
Status: baseline suite created and executed.
|
||||
|
||||
## Executed
|
||||
- Command:
|
||||
- `node --test test/basic/*.test.js test/edge/*.test.js test/integration/*.test.js`
|
||||
- Working directory:
|
||||
- `nodes/pumpingStation`
|
||||
- Result:
|
||||
- `pass: 4`, `fail: 0`
|
||||
|
||||
## Planned Test Matrix
|
||||
| Planned test file | Scope | Primary contracts anchored |
|
||||
|---|---|---|
|
||||
| `nodes/pumpingStation/test/basic/constructor.basic.test.js` | config initialization, basin property derivation | constructor, `initBasinProperties`, config defaults |
|
||||
| `nodes/pumpingStation/test/basic/nodeClass-routing.basic.test.js` | topic routing and registration handling | `nodeClass._attachInputHandler`, `registerChild`, calibration topics, `q_in` parsing |
|
||||
| `nodes/pumpingStation/test/integration/registration-normalization.integration.test.js` | softwareType/position normalization and listener dedupe | `registerChild`, `_registerPredictedFlowChild`, `_registerMeasurementChild` |
|
||||
| `nodes/pumpingStation/test/edge/mode-alias.edge.test.js` | mode alias normalization | `_normalizeMode`, `changeMode` compatibility path |
|
||||
| `nodes/pumpingStation/test/integration/flow-balance.integration.test.js` | inflow/outflow aggregation and predicted volume update | `_updatePredictedVolume`, `_selectBestNetFlow`, `_computeRemainingTime` |
|
||||
| `nodes/pumpingStation/test/integration/measurement.integration.test.js` | level/pressure measurement handling and conversions | `_onLevelMeasurement`, `_onPressureMeasurement` |
|
||||
| `nodes/pumpingStation/test/integration/safety.integration.test.js` | dry-run/overfill/time threshold behavior | `_safetyController` |
|
||||
| `nodes/pumpingStation/test/integration/control-levelbased.integration.test.js` | level-based machine command dispatch behavior | `_controlLevelBased`, `_applyMachineLevelControl` |
|
||||
| `nodes/pumpingStation/test/edge/status.edge.test.js` | status output formatting under sparse data | `_updateNodeStatus` |
|
||||
|
||||
## Execution Target
|
||||
- Preferred command (after suite exists): `node --test nodes/pumpingStation/test/**/*.test.js`
|
||||
|
||||
## Coverage Goal
|
||||
- Match rotatingMachine discipline:
|
||||
- config contract coverage
|
||||
- topic routing coverage
|
||||
- control/safety path coverage
|
||||
- regression cases for known risk patterns
|
||||
Reference in New Issue
Block a user