From e691551dddc1630b52d5f3a16a867a377cd96255 Mon Sep 17 00:00:00 2001 From: znetsixe Date: Mon, 11 May 2026 17:03:28 +0200 Subject: [PATCH] docs: lock in 12 decisions from the 2026-05-11 interview + add Phase 11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OPEN_QUESTIONS.md: summary table of every decision (ramp foot, naming, isStable fix, monster guard, plain-dicts→declareChildGetter, VGC→ ChildRouter, LatestWinsGate fireAndWait, drop mAbs, per-listener fan-out, commandRegistry 'none' + description, UnitPolicy dual-shape, Phase 10 test rewrites). TASKS.md §Phase 11: unit-aware commands. Every numeric setter declares units: { measure, default }. commandRegistry normalises msg.payload + msg.unit; warns + lists accepted units for bad input; falls back to default. New query.units topic returns the spec per node. Co-Authored-By: Claude Opus 4.7 (1M context) --- .claude/refactor/OPEN_QUESTIONS.md | 21 +++++++++++++++++ .claude/refactor/TASKS.md | 38 ++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/.claude/refactor/OPEN_QUESTIONS.md b/.claude/refactor/OPEN_QUESTIONS.md index 9cf94c0..cb23688 100644 --- a/.claude/refactor/OPEN_QUESTIONS.md +++ b/.claude/refactor/OPEN_QUESTIONS.md @@ -4,6 +4,27 @@ Things deferred. Append, don't rewrite history. Add a date when you add or resolve an entry. Anyone (human or agent) discovering an unclear decision during refactor work writes it here rather than guessing. +--- + +## 2026-05-11 — Interview round — resolved decisions + +| Topic | Decision | +|---|---| +| Ramp foot for run-zone curve (control/levelBased) | `inflowLevel` (current). startLevel is the 0% minimum, not the curve foot. | +| `overfillLevel` vs `highVolumeSafetyLevel` | **`highVolumeSafetyLevel` canonical**; drop the legacy alias. | +| measurement `isStable` tautology | Fix now with a config-driven absolute threshold (`stabilityThreshold` in scaling-units). Add to schema + editor UI. | +| monster cooldown-guard pre-existing fail | Debug + fix the sampling-pulse logic. | +| pumpingStation plain child dicts | Migrate to `declareChildGetter`; rewrite affected tests. | +| VGC custom `registerChild` overload | Adopt ChildRouter; rewrite disambiguation tests. | +| MGC inline dispatch gate vs LatestWinsGate | Extend LatestWinsGate with `fireAndWait(value)` returning the per-fire settlement promise. Migrate MGC. | +| measurement legacy `'mAbs'` event | Remove now. | +| ChildRouter wildcard emit-patch | Per-listener fan-out using canonical POSITIONS. No more emit patching. | +| commandRegistry payload schema | Add `'none'` type + per-command `description` field (wikiGen consumes). | +| UnitPolicy property-vs-method shape | Expose both. Frozen property bags alongside the methods. Drop `_unitView` workarounds. | +| rotatingMachine + reactor private-method-pinning tests (13 files) | Rewrite all to drive only the public BaseNodeAdapter surface. Phase 10. | +| **Unit-aware commands (new)** | Each numeric setter declares `units: { measure, default }`. commandRegistry normalises + warns + lists accepted units. `query.units` topic returns spec. Phase 11. | + + Format: ``` diff --git a/.claude/refactor/TASKS.md b/.claude/refactor/TASKS.md index dc17a2f..8f60265 100644 --- a/.claude/refactor/TASKS.md +++ b/.claude/refactor/TASKS.md @@ -253,3 +253,41 @@ now that the platform is uniform. Pre-existing test debt logged in | 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 )`. | +| 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 |