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:
znetsixe
2026-03-04 21:07:04 +01:00
parent fbd9e6ec11
commit 6a6c04d34b
169 changed files with 21332 additions and 1512 deletions

View File

@@ -0,0 +1,74 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Monster Anchor Map</title>
<style>
:root {
--bg: #f5f7fb;
--panel: #ffffff;
--line: #9ab0d9;
--text: #14233d;
--muted: #4d6084;
--monster: #4f8582;
--sensor: #eef8e8;
--api: #fff5e5;
--ops: #e9f1ff;
}
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>Monster Function Anchor</h1>
<p>External APIs are orchestrated by surrounding flows; the `monster` node computes sampling state and report fields.</p>
<div class="chips">
<span class="chip">input: input_q / i_start / monsternametijden / rain_data</span>
<span class="chip">output: pulse, m3Total, m3PerPuls, bucketVol, running</span>
<span class="chip">report path: Z-Info import + operator m3/pulse reference</span>
</div>
<svg viewBox="0 0 980 380" role="img" aria-label="Monster integration topology">
<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="390" y="150" width="190" height="80" rx="10" fill="var(--monster)"></rect>
<text x="485" y="192" text-anchor="middle" fill="#fff" font-size="16">monster</text>
<rect x="40" y="45" width="220" height="56" rx="9" fill="var(--sensor)" stroke="#b7d89e"></rect>
<text x="150" y="79" text-anchor="middle" fill="#2e5a22" font-size="13">PLC/measurement flow input</text>
<rect x="40" y="290" width="220" height="56" rx="9" fill="var(--api)" stroke="#e9c589"></rect>
<text x="150" y="324" text-anchor="middle" fill="#634319" font-size="13">Open-Meteo + Aquon schedule</text>
<rect x="720" y="45" width="220" height="56" rx="9" fill="var(--ops)" stroke="#aac0ef"></rect>
<text x="830" y="79" text-anchor="middle" fill="#244271" font-size="13">Dashboard / Influx / Grafana</text>
<rect x="720" y="290" width="220" height="56" rx="9" fill="#e7faf5" stroke="#9edcca"></rect>
<text x="830" y="324" text-anchor="middle" fill="#1e5244" font-size="13">PLC pulse + Z-Info report tooling</text>
<line x1="260" y1="73" x2="390" y2="160" stroke="var(--line)" stroke-width="2" marker-end="url(#arr)"></line>
<line x1="260" y1="318" x2="390" y2="220" stroke="var(--line)" stroke-width="2" marker-end="url(#arr)"></line>
<line x1="580" y1="160" x2="720" y2="75" stroke="var(--line)" stroke-width="2" marker-end="url(#arr)"></line>
<line x1="580" y1="220" x2="720" y2="318" stroke="var(--line)" stroke-width="2" marker-end="url(#arr)"></line>
<text x="294" y="125" fill="var(--muted)" font-size="12">input_q / i_start / registerChild</text>
<text x="285" y="277" fill="var(--muted)" font-size="12">rain_data / monsternametijden</text>
<text x="610" y="124" fill="var(--muted)" font-size="12">process + influx streams</text>
<text x="607" y="278" fill="var(--muted)" font-size="12">pulse + m3Total + m3PerPuls</text>
</svg>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,85 @@
# Monster Function Anchor (Baseline)
## 0) Connection Map (At a Glance)
- **Node type**: `monster` (`nodes/monster/monster.js:1`, `nodes/monster/monster.html:5`)
- **Consumes control/input topics**: `input_q`, `i_start`, `monsternametijden`, `rain_data`, `registerChild` (`nodes/monster/src/nodeClass.js:202`)
- **Publishes periodic outputs**:
- Output `0`: process payload (`nodes/monster/src/nodeClass.js:185`)
- Output `1`: influx payload (`nodes/monster/src/nodeClass.js:186`)
- Output `2`: parent registration (`registerChild`) (`nodes/monster/src/nodeClass.js:158`)
- **Cross-node integrations**:
- Accepts measurement children of type `flow` (`nodes/monster/src/specificClass.js:300`)
- Common external orchestration pattern around this node:
- Open-Meteo -> `rain_data`
- Aquon schedule feed -> `monsternametijden`
- PLC/MQTT pulse sink fed by `output.pulse`
- Z-Info/report tooling fed by `m3Total` + `m3PerPuls`
- Dashboard API/Grafana and Influx consumers
- **Admin/UI endpoints**:
- `GET /monster/menu.js`
- `GET /monster/configData.js` (`nodes/monster/monster.js:17`, `nodes/monster/monster.js:27`)
## 1) Unit Table (Always First Data Section)
| Signal/Field | Represents | Asset Type | Default Unit | Source of Truth | Produced By | Consumed By | Fallback/Degraded Behavior |
|---|---|---|---|---|---|---|---|
| `input_q.payload.value` | influent flow command | manual/control input | `m3/h` (normalized in wrapper) | `nodes/monster/src/nodeClass.js:216` | upstream control flow | sampling calculation loop | invalid/unit conversion failure is warned and ignored |
| `flow.measured.*` | measured flow from child sensors | measurement child | `m3/h` | `nodes/monster/src/specificClass.js:300` | measurement nodes | effective flow selection | if missing, manual flow or 0 is used |
| `q` | effective flow used by model | derived | `m3/h` | `nodes/monster/src/specificClass.js:775` | `tick()` | pulse and volume progression | defaults to `0` if no measured/manual flow |
| `m3PerPuls` | reporting conversion factor for sampler pulse | derived/report field | `m3/pulse` | `nodes/monster/src/specificClass.js:660` | `sampling_program()` | Z-Info/report tooling, operations | `0` when not running |
| `m3Total` | accumulated volume during active run | derived/report field | `m3` | `nodes/monster/src/specificClass.js:687` | `sampling_program()` | Z-Info/report tooling | reset to `0` when sampling window ends |
| `pulse` | pulse command signal | control output | boolean | `nodes/monster/src/specificClass.js:707` | `sampling_program()` | PLC/MQTT pulse output paths | forced `false` under cooldown/capacity/end-of-run |
| `bucketVol` | sampled bucket fill volume | derived/state | `L` | `nodes/monster/src/specificClass.js:712` | pulse accumulation | dashboard/operator checks | reset to `0` after run |
| `predictedRateM3h` | rain-scaled prediction reference | derived | `m3/h` | `nodes/monster/src/specificClass.js:367` | `getOutput()` | dashboards/diagnostics | falls back to measured/manual effective rate |
## 2) Class Identity
- **Runtime registration + endpoints**: `nodes/monster/monster.js`
- **Node-RED wrapper/routing**: `nodes/monster/src/nodeClass.js`
- **Domain sampling logic**: `nodes/monster/src/specificClass.js`
- **Editor UI/defaults**: `nodes/monster/monster.html`
- **Default config schema**: `nodes/generalFunctions/src/configs/monster.json`
## 3) Configuration Contract (Key)
| UI Field | Runtime Path | Default | Behavior Impact | Source |
|---|---|---|---|---|
| `samplingtime` | `constraints.samplingtime` | `0` | sampling window hours | `nodes/monster/monster.html:16`, `nodes/monster/src/nodeClass.js:68` |
| `minvolume` | `constraints.minVolume` | `5` | min valid sample volume | `nodes/monster/monster.html:17`, `nodes/monster/src/nodeClass.js:69` |
| `maxweight` | `constraints.maxWeight` | `22` | max bucket load before invalid sample | `nodes/monster/monster.html:18`, `nodes/monster/src/nodeClass.js:70` |
| `nominalFlowMin` / `flowMax` | `constraints.nominalFlowMin` / `constraints.flowMax` | `0` / `0` | prediction bounds and start guard | `nodes/monster/monster.html:19`, `nodes/monster/src/specificClass.js:226` |
| `minSampleIntervalSec` | `constraints.minSampleIntervalSec` | `60` | pulse cooldown protection | `nodes/monster/monster.html:22`, `nodes/monster/src/specificClass.js:693` |
| `emptyWeightBucket` | `asset.emptyWeightBucket` | `3` | max bucket volume derivation | `nodes/monster/monster.html:23`, `nodes/monster/src/specificClass.js:378` |
| `aquon_sample_name` | `aquonSampleName` | `"112100"` internal default | schedule selector key | `nodes/monster/monster.html:24`, `nodes/monster/src/nodeClass.js:96` |
## 4) I/O and Integration Notes
- Node-level output is process/influx/parent only.
- External APIs are normally handled by surrounding flows, not by the node class itself.
- Report tooling integration should read from process payload fields:
- `m3Total`
- `m3PerPuls`
- `running`
- `pulse`
- Reference examples:
- dashboard baseline: `nodes/monster/examples/monster-dashboard.flow.json`
- full API + dashboard template: `nodes/monster/examples/monster-api-dashboard.flow.json`
## 5) Current Gaps / Risks
1. Wrapper exposes topics (`setMode`, `execSequence`, `execMovement`, `flowMovement`, `emergencystop`) that are not implemented in `Monster.handleInput` contract.
2. `showWorkingCurves`/`CoG` routes in wrapper call methods that are not present in `Monster`.
3. Existing legacy tests were not organized in required `basic/integration/edge` folders before this update.
4. External API credentials/tokens must remain outside committed example flows.
## 6) Test Evidence Matrix (Current Baseline)
| Test file | What is covered | Methods/contracts anchored |
|---|---|---|
| `nodes/monster/test/basic/constructor.basic.test.js` | constructor + output field contract | `constructor`, `set_boundries_and_targets`, `getOutput` |
| `nodes/monster/test/integration/flow-and-schedule.integration.test.js` | flow averaging, rain/schedule ingestion | `registerChild`, `handleInput`, `tick`, `updateRainData`, `regNextDate` |
| `nodes/monster/test/edge/sampling-guards.edge.test.js` | invalid-bound guard + cooldown behavior | `validateFlowBounds`, `sampling_program`, cooldown gate |
## 7) Change Checklist
- When `monster` behavior changes, update:
- `nodes/monster/src/nodeClass.js`
- `nodes/monster/src/specificClass.js`
- `nodes/monster/monster.html`
- `nodes/monster/test/basic|integration|edge/*`
- `.agents/function-anchors/monster/ANCHOR-monster.md`
- `.agents/function-anchors/monster/ANCHOR-monster.html`
- `.agents/function-anchors/monster/EVIDENCE-monster-tests.md`

View File

@@ -0,0 +1,30 @@
# Monster Test Evidence
## Executed Baseline
- Command:
- `node --test test/basic/*.test.js test/integration/*.test.js test/edge/*.test.js`
- Working directory:
- `nodes/monster`
- Result:
- `pass: 6`, `fail: 0`
## Test Matrix
| Test file | Scope | Contracts anchored |
|---|---|---|
| `nodes/monster/test/basic/constructor.basic.test.js` | initialization and output field contract | constructor, boundary setup, report output fields |
| `nodes/monster/test/basic/structure-module-load.basic.test.js` | required structure/module load guard | baseline architecture compliance |
| `nodes/monster/test/integration/flow-and-schedule.integration.test.js` | flow aggregation + rain/schedule ingestion | measured/manual flow merge, `handleInput`, schedule update path |
| `nodes/monster/test/integration/structure-examples.integration.test.js` | required examples contract guard | example flow presence/shape |
| `nodes/monster/test/edge/sampling-guards.edge.test.js` | sampling safety guards | invalid flow bounds guard, cooldown pulse throttling |
| `nodes/monster/test/edge/structure-examples-node-type.edge.test.js` | node-type structure guard | example includes `monster` node usage |
## Coverage Notes
- Structure guards now require both dashboard examples:
- `nodes/monster/examples/monster-dashboard.flow.json`
- `nodes/monster/examples/monster-api-dashboard.flow.json`
- Focused on the most operationally critical report fields:
- `m3Total`
- `m3PerPuls`
- `pulse`
- `running`
- Additional contract tests are still recommended for wrapper topic routes that currently map to unsupported domain handlers.