docs(wiki): full 5-page wiki matching the rotatingMachine reference format
Replaces the prior stub/partial wiki with a Home + Reference-{Architecture,
Contracts,Examples,Limitations} + _Sidebar structure. Topic-contract and
data-model sections wrapped in AUTOGEN markers for the future wiki-gen tool.
Source-vs-spec contradictions surfaced and flagged inline (not silently
fixed). Pending-review notes mark sections that need a full node review.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
217
wiki/Reference-Limitations.md
Normal file
217
wiki/Reference-Limitations.md
Normal file
@@ -0,0 +1,217 @@
|
||||
# Reference — Limitations
|
||||
|
||||

|
||||
|
||||
> [!NOTE]
|
||||
> What `generalFunctions` does not do, current rough edges, stability/versioning rules, and open questions. For an intuitive overview, return to [Home](Home).
|
||||
|
||||
---
|
||||
|
||||
## When NOT to depend on this library
|
||||
|
||||
- **Passive HTTP gateway nodes** (e.g. `dashboardAPI`) may skip `BaseDomain` and `BaseNodeAdapter` entirely if they hold no domain state. A plain Node-RED node with HTTP endpoints needs only `logger`, `outputUtils`, and `configManager`. See the `dashboardAPI` wiki for the rationale.
|
||||
- **External scripts or standalone tools** that need only unit conversion can import just `const { convert } = require('generalFunctions')` without pulling in the full domain stack.
|
||||
- **Nodes at a different S88 level** that inherit from a third-party base class must not import from `src/domain/` or `src/nodered/` internal paths — they may only use root-level exports.
|
||||
|
||||
---
|
||||
|
||||
## Known limitations
|
||||
|
||||
### 1. `loadCurve` is deprecated
|
||||
|
||||
`loadCurve(modelId)` is kept as a thin shim over `assetResolver.resolve('curves', modelId)` so legacy consumers don't have to change in one go. New code should use `assetResolver` directly. Replacement `loadModel` exists but not every node has migrated.
|
||||
|
||||
- **Tracked in**: `OPEN_QUESTIONS.md` — Phase 8.5 cleanup.
|
||||
|
||||
### 2. `outlierDetection` (`DynamicClusterDeviation`) prints to `console.log`
|
||||
|
||||
The dynamic-cluster outlier detector emits diagnostic lines via `console.log` directly, bypassing the structured `logger`. This means its output cannot be silenced per-node and doesn't honour `logLevel`. Fix is routing through `logger` like the rest of the library.
|
||||
|
||||
- **Tracked in**: Code review backlog.
|
||||
|
||||
### 3. `configUtils.initConfig` silently strips unknown keys
|
||||
|
||||
When the user config carries a key that isn't in the schema, `configUtils.initConfig` (via `validationUtils.validateSchema`) silently drops it. This means a typo in an editor field name or a missed schema entry results in the default value being used — with no error, no warning, no log line.
|
||||
|
||||
Workaround: the schema must include every key the domain reads, with a sensible default. The 2026-05-11 monster schema fix was a direct consequence of this gotcha.
|
||||
|
||||
- **Tracked in**: `OPEN_QUESTIONS.md` — e.g. monster schema fix.
|
||||
|
||||
### 4. `state` (FSM) and `predict` are not yet integrated with `BaseDomain` lifecycle
|
||||
|
||||
The state machine and the prediction class are exported but not lifecycle-managed by `BaseDomain`. Consumer nodes wire them manually in `configure()` — constructor, event subscriptions, teardown. A second wave of refactor work will move them under the `BaseDomain` umbrella so subclasses get them for free.
|
||||
|
||||
- **Tracked in**: Architecture backlog.
|
||||
|
||||
### 5. `menuUtils` / `MenuManager` bypass the Node.js import path
|
||||
|
||||
These are served as browser JavaScript via the admin `endpointUtils` and run in the Node-RED editor's iframe. Deep changes require testing in both environments (Node-side schema validation, browser-side editor form rendering). There is no automated test harness for the browser side.
|
||||
|
||||
- **Tracked in**: `endpointUtils.js` comments.
|
||||
|
||||
### 6. `CascadePIDController` has no dedicated test suite
|
||||
|
||||
`PIDController` is unit-tested; the cascade variant is not. Adding tests is on the backlog.
|
||||
|
||||
- **Tracked in**: Test backlog.
|
||||
|
||||
### 7. Wiki autogen is hand-maintained
|
||||
|
||||
The API surface section is hand-maintained between the `<!-- BEGIN/END AUTOGEN: api-surface -->` markers in `CONTRACT.md`. There is no `npm run wiki:all` script (yet); when an export is added or changed, the table must be edited by hand. Mitigation: the source-of-truth is the barrel (`index.js`); when in doubt, trust the barrel.
|
||||
|
||||
- **Tracked in**: Phase 9 follow-up.
|
||||
|
||||
### 8. Single-side pressure handling lives in consumers
|
||||
|
||||
Consumer-node concerns like single-side pressure degradation, residue handling, and sequence-abort semantics are NOT centralised in this library — each consumer (`rotatingMachine`, `valveGroupControl`, …) implements its own variant. Cross-node consistency is by convention, not by enforcement. A future `BaseDomain` extension could pull common pressure-routing patterns up.
|
||||
|
||||
- **Tracked in**: Internal architecture notes.
|
||||
|
||||
### 9. Asset registry backends are not fully symmetric
|
||||
|
||||
`FileBackend` is the production default (sync, in-process JSON). `HttpBackend` is provided for remote-resolver scenarios but has fewer call sites and less test coverage. If you switch to `HttpBackend` in production, expect to find edge-case differences.
|
||||
|
||||
- **Tracked in**: Internal — not yet ticketed.
|
||||
|
||||
### 10. No editor form
|
||||
|
||||
`generalFunctions` is never placed in a flow. It has no Node-RED type registration, no `.html`, no admin endpoint of its own. Consumer nodes expose their own editor forms; each form field writes into a config key that `configManager.buildConfig` validates against the node's schema in `src/configs/<nodeName>.json`. This is a deliberate design choice, not a limitation — documented here for visitors searching for "where's the editor form".
|
||||
|
||||
---
|
||||
|
||||
## Stability + versioning
|
||||
|
||||
Source of truth: [`.claude/rules/general-functions.md`](https://gitea.wbd-rd.nl/RnD/EVOLV/src/branch/development/.claude/rules/general-functions.md) in the superproject.
|
||||
|
||||
| Category | Rule |
|
||||
|:---|:---|
|
||||
| **Safe to add** | New named exports. New optional methods on existing classes. New config keys with defaults in the schema. |
|
||||
| **Requires decision-gate interview** | Removing or renaming any export. Changing a method signature. Changing the output key format of `MeasurementContainer.getFlattenedOutput()`. Changing the `formatMsg` delta-compression behaviour. |
|
||||
| **Forbidden without migration** | Breaking the 4-segment key shape (`type.variant.position.childId`). Changing Port 0/1/2 payload envelope. Changing the [CONTRACTS.md](https://gitea.wbd-rd.nl/RnD/EVOLV/src/branch/development/.claude/refactor/CONTRACTS.md) §1–§9 shapes. |
|
||||
|
||||
### Cross-node impact
|
||||
|
||||
`generalFunctions` is a git submodule shared by all 12 node repos. **Any change here can break any node.** Before modifying any module:
|
||||
|
||||
```bash
|
||||
# Identify all consumers of the symbol you're touching.
|
||||
grep -r "require('generalFunctions')" nodes/*/
|
||||
|
||||
# Or for a specific export:
|
||||
grep -rn "BaseDomain\|UnitPolicy\|MeasurementContainer" nodes/*/src/
|
||||
```
|
||||
|
||||
After changes, run the test suites of every affected consumer node, not just `generalFunctions/test/`.
|
||||
|
||||
### Canonical units
|
||||
|
||||
`MeasurementContainer` and all internal processing assume canonical units:
|
||||
|
||||
| Quantity | Canonical |
|
||||
|:---|:---|
|
||||
| Pressure | `Pa` |
|
||||
| Flow | `m3/s` |
|
||||
| Power | `W` |
|
||||
| Temperature | `K` |
|
||||
|
||||
Unit conversion happens at system boundaries (input via `CommandRegistry.units` normalisation, output via `UnitPolicy.output` rendering) — never in core logic. Code that assumes anything else is a bug.
|
||||
|
||||
---
|
||||
|
||||
## Deprecations
|
||||
|
||||
| Symbol | Status | Replacement | Plan |
|
||||
|:---|:---|:---|:---|
|
||||
| `loadCurve(modelId)` | deprecated | `assetResolver.resolve('curves', modelId)` | Remove after every consumer migrates. Tracked in Phase 8.5. |
|
||||
|
||||
When a symbol is marked deprecated:
|
||||
|
||||
1. The row in `CONTRACT.md` flips to `deprecated` and gains a "removed-in" line.
|
||||
2. Consumers in `nodes/*` are updated to the replacement.
|
||||
3. Each touched node's submodule pin is bumped in the superproject.
|
||||
4. After one release on `development` with no consumers, the export and its row are removed.
|
||||
|
||||
---
|
||||
|
||||
## Open questions (tracked)
|
||||
|
||||
| Question | Where it lives |
|
||||
|:---|:---|
|
||||
| Phase 8.5: complete `loadCurve` → `assetResolver` migration | Internal |
|
||||
| Route `DynamicClusterDeviation` log lines through `logger` | Code review backlog |
|
||||
| Surface a warning when `configUtils.initConfig` strips a key not in schema | `OPEN_QUESTIONS.md` |
|
||||
| Move `state` (FSM) and `predict` under `BaseDomain` lifecycle | Architecture backlog |
|
||||
| Browser-side test harness for `menuUtils` | `endpointUtils.js` |
|
||||
| Test suite for `CascadePIDController` | Test backlog |
|
||||
| Wiki autogen script (`npm run wiki:all`) for the API surface section | Phase 9 follow-up |
|
||||
| `HttpBackend` test coverage parity with `FileBackend` | Internal |
|
||||
| Centralised single-side-pressure handling pattern in `BaseDomain` | Internal architecture notes |
|
||||
|
||||
---
|
||||
|
||||
## Migration notes
|
||||
|
||||
### Pre-refactor: per-node `registerChild` switch
|
||||
|
||||
The `ChildRouter` replaces hand-written `registerChild(child)` methods. The mechanical migration:
|
||||
|
||||
```js
|
||||
// Before:
|
||||
registerChild(child) {
|
||||
switch (child.softwareType) {
|
||||
case 'measurement':
|
||||
if (child.config.asset.type === 'pressure' && child.positionVsParent === 'upstream') {
|
||||
this._onUpstream(child);
|
||||
} else if (child.config.asset.type === 'flow') {
|
||||
this._onFlow(child);
|
||||
}
|
||||
break;
|
||||
case 'machinegroup':
|
||||
this._onMgcChild(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// After (in configure()):
|
||||
this.router
|
||||
.onMeasurement('measurement', { type: 'pressure', position: 'upstream' }, (data, child) => this._onUpstream(child))
|
||||
.onMeasurement('measurement', { type: 'flow' }, (data, child) => this._onFlow(child))
|
||||
.onRegister('machinegroup', (child) => this._onMgcChild(child));
|
||||
```
|
||||
|
||||
Behaviour is identical (the underlying `childRegistrationUtils` calls are unchanged); the wiring is just declarative.
|
||||
|
||||
### Pre-refactor: per-node `getStatusBadge` duplication
|
||||
|
||||
The `statusBadge` pure-function helpers replaced 12 copies of slightly different status-text formatters. New domains should use `statusBadge.compose(parts, opts)`, `statusBadge.error(msg)`, `statusBadge.idle(label)` instead of building `{fill, shape, text}` by hand. Text is clipped to 60 chars to fit the Node-RED editor.
|
||||
|
||||
### Pre-AssetResolver: `loadCurve` shim
|
||||
|
||||
Old code:
|
||||
|
||||
```js
|
||||
const { loadCurve } = require('generalFunctions');
|
||||
const curve = loadCurve('SomeModel');
|
||||
```
|
||||
|
||||
New code (preferred):
|
||||
|
||||
```js
|
||||
const { assetResolver } = require('generalFunctions');
|
||||
const curve = assetResolver.resolve('curves', 'SomeModel');
|
||||
```
|
||||
|
||||
The shim still works, but the next API-surface review may remove it. Migrate when next touching the file.
|
||||
|
||||
---
|
||||
|
||||
## Related pages
|
||||
|
||||
| Page | Why |
|
||||
|:---|:---|
|
||||
| [Home](Home) | Intuitive overview |
|
||||
| [Reference — Contracts](Reference-Contracts) | Full public API surface, per-export stability tags |
|
||||
| [Reference — Architecture](Reference-Architecture) | Three-tier rule, `src/` layout, consumer responsibilities |
|
||||
| [Reference — Examples](Reference-Examples) | Usage patterns: extending base classes, registering commands, declaring child routes |
|
||||
| [Platform CONTRACTS.md](https://gitea.wbd-rd.nl/RnD/EVOLV/src/branch/development/.claude/refactor/CONTRACTS.md) | The authoritative platform base-class + protocol spec |
|
||||
| [`.claude/rules/general-functions.md`](https://gitea.wbd-rd.nl/RnD/EVOLV/src/branch/development/.claude/rules/general-functions.md) | Stability + change-impact rules |
|
||||
Reference in New Issue
Block a user