docs: lock in 12 decisions from the 2026-05-11 interview + add Phase 11

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) <noreply@anthropic.com>
This commit is contained in:
znetsixe
2026-05-11 17:03:28 +02:00
parent 351e889918
commit e691551ddd
2 changed files with 59 additions and 0 deletions

View File

@@ -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 or resolve an entry. Anyone (human or agent) discovering an unclear
decision during refactor work writes it here rather than guessing. 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: Format:
``` ```

View File

@@ -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.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.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. | | 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 |