tools: add physics-sanity + Docker MCP scaffolding + tools/README
- tools/physics-sanity/ — JS library of cross-node balance helpers
(mass / hydraulic / hydraulic-power / oxygen-transfer / energy) with
7 unit tests + a CLI demo. Designed for `require()` from per-node
integration tests where shape-based unit tests miss physically-
impossible plant states.
- tools/docker-compose.yml + tools/mcp/{node-red-admin,influxdb,browser}
scaffolding — placeholder Dockerfiles + a ROADMAP.md for the Node-RED
admin MCP. Compose file is the target shape for the Q3-2026 migration
to the central MCP server; the per-service Dockerfile stays in this
repo as the canonical definition either way. Implementations are TODO.
- tools/README.md — top-level tooling index; documents the CI order for
running every tool on a PR.
- .gitignore: ignore tools/.env (developer-specific MCP endpoints).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
80
tools/physics-sanity/README.md
Normal file
80
tools/physics-sanity/README.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# @evolv/physics-sanity
|
||||
|
||||
Cross-node physical-balance helpers. Import from any node's test files
|
||||
to assert that scenario states close mass, hydraulic, hydraulic-power,
|
||||
oxygen-transfer, or energy balances within a stated tolerance.
|
||||
|
||||
## Why
|
||||
|
||||
Per-node unit tests verify shape and behaviour. They don't catch
|
||||
physically impossible plant states that arise from cross-node coupling
|
||||
— e.g. a pumpingStation reporting outflow > inflow + accumulation, or a
|
||||
diffuser reporting OTR inconsistent with its KLa × ΔC × V.
|
||||
|
||||
These helpers don't replace per-node tests. They sit on top of an
|
||||
integration scenario and assert the closing balance.
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const sanity = require('../../../tools/physics-sanity');
|
||||
|
||||
test('three-pump station closes the hydraulic balance', () => {
|
||||
// … drive the scenario, take a snapshot …
|
||||
const r = sanity.assertHydraulicBalance({
|
||||
headerSuctionPa: ps.suctionPressurePa,
|
||||
headerDischargePa: ps.dischargePressurePa,
|
||||
pumpHeadPa: sumOfPumpHeads,
|
||||
frictionPa: pipeFrictionEstimate,
|
||||
});
|
||||
assert.equal(r.ok, true, sanity.reportToString(r));
|
||||
});
|
||||
```
|
||||
|
||||
## Helpers exported
|
||||
|
||||
| Function | Asserts |
|
||||
|---|---|
|
||||
| `assertMassBalance({ inflowKgPerS, outflowKgPerS, accumulationKgPerS })` | `in - out - accumulation ≈ 0` |
|
||||
| `assertHydraulicBalance({ headerSuctionPa, headerDischargePa, pumpHeadPa, frictionPa, staticHeadPa })` | `ΔP_headers ≈ pumpHead - friction - static` |
|
||||
| `assertHydraulicPower({ flowM3PerS, headPa, shaftPowerW, efficiency })` | `shaft ≈ Q·H / η` |
|
||||
| `assertOxygenTransfer({ klaPerS, csMgPerL, cMgPerL, otrKgPerS, volumeM3 })` | `OTR ≈ KLa · (Cs - C) · V` |
|
||||
| `assertEnergyBalance({ heatInW, workInW, heatOutW, workOutW, accumulationW })` | `Q_in + W_in ≈ Q_out + W_out + ΔE` |
|
||||
|
||||
Each returns `{ ok, label, ...residuals }`. `reportToString(r)` formats
|
||||
for human-readable failure messages.
|
||||
|
||||
## CLI demo
|
||||
|
||||
```bash
|
||||
node tools/physics-sanity/bin/physics-sanity.js
|
||||
```
|
||||
|
||||
Runs four sanity-check scenarios against the helpers (smoke-test for
|
||||
the library itself).
|
||||
|
||||
## Tolerance defaults
|
||||
|
||||
| Domain | Absolute | Relative |
|
||||
|---|---|---|
|
||||
| mass | 1e-6 kg/s | 0.1 % |
|
||||
| hydraulic ΔP | 50 Pa (0.5 mbar) | 0.1 % |
|
||||
| hydraulic power | 1 W | 0.5 % |
|
||||
| OTR | 1e-4 kg/s | 0.5 % |
|
||||
| energy | 1 W | 0.1 % |
|
||||
|
||||
Override per call with `absTol` / `relTol`.
|
||||
|
||||
## Where to use this
|
||||
|
||||
Out-of-the-box destinations:
|
||||
|
||||
| Scenario | Where to add | Calls |
|
||||
|---|---|---|
|
||||
| pumpingStation hydraulic closure | `nodes/pumpingStation/test/integration/` | `assertHydraulicBalance`, `assertHydraulicPower` |
|
||||
| reactor → settler mass balance | `nodes/reactor/test/integration/` | `assertMassBalance` |
|
||||
| diffuser OTR vs reactor uptake | `nodes/diffuser/test/integration/` | `assertOxygenTransfer` |
|
||||
| machineGroupControl efficiency sanity | `nodes/machineGroupControl/test/integration/` | `assertHydraulicPower` |
|
||||
|
||||
A future tool can scan integration tests and report which scenarios do
|
||||
or don't have a closing-balance assertion.
|
||||
Reference in New Issue
Block a user