CONTRACTS.md §4: full payloadSchema.type table including 'none', plus
the optional description field example. Matches the B3.2 implementation.
WIKI_TEMPLATE.md §5: Unit column appears with explanatory paragraph.
Matches the P11.4 wikiGen output.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Single doc capturing the 'what's not done' at the end of the
2026-05-11 sprint, in priority order: B5 reactor boundary-conditions
merge, Phase 8 PR cycle, a handful of small open-questions follow-ups,
plus the wiki cosmetics list. README.md links to it from the top.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
All 11 nodes' wiki/Home.md regenerated with the Unit column +
per-topic descriptions. rotatingMachine + reactor private-method
test files rewritten to the public BaseNodeAdapter surface.
OPEN_QUESTIONS: rotatingMachine + reactor private-test entries
marked RESOLVED.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The original Dockerfile switched to USER node-red before WORKDIR
/data/evolv, so the auto-created parent directory ended up root-owned
and `RUN npm install` failed with EACCES trying to mkdir node_modules.
Fix: mkdir + chown explicitly as root, then WORKDIR + USER node-red.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
scripts/test-platform.js iterates each submodule, runs npm test, shows
a per-node pass/fail summary, exits non-zero if any node fails.
Wired as `npm run test:platform` in the parent package.json.
Submodule pointer bumps:
dashboardAPI 2874608 → 92d7eba (Mocha → node:test conversion for edge+integration)
diffuser 0ec9dd1 → 15cfb22 (P10.7a test script fix)
generalFunctions 8ebf31d → 95c5e68 (P10.7a test script fix + remove 5 broken Mocha dupes)
pumpingStation 52d3889 → d2384b1 (P10.7a test script fix)
Current platform-wide gate: 729 pass / 5 fail across 12 submodules
(5 failures are all pre-existing AssertionErrors logged in
OPEN_QUESTIONS.md for Phase 10.5).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
WIKI_TEMPLATE.md — extend the canonical per-node page from 9 to 14 sections:
+ Header band (commit hash + regen date)
+ Code map (flowchart TB w/ subgraphs over concern modules)
+ Child registration (mirrors ChildRouter declarations)
+ Data model — getOutput() (abstract schema + optional concrete sample)
+ Debug recipes (symptom → first thing to check)
+ AUTOGEN markers around topic-contract + data-model schema so the
Phase 9 regen script can rewrite in place.
+ 'Picking a visual' table: Mermaid is default, plots/SVG/screenshots
allowed where they serve the data.
+ Archive banner snippet.
WIKI_HOME_TEMPLATE.md (new) — Home.md + Archive.md templates:
- Platform-wide Mermaid graph of 11 active nodes, S88-coloured.
- Navigation table grouped by S88 level.
- Standards-pointer table to .claude/rules + .claude/refactor docs.
- Live refactor-status table for returning visitors.
- Archive index template with archival-date column.
No wiki pages written yet — next step is one worked example
(pumpingStation) before any change to the Gitea wiki repo.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Defines the 9-section template every node's wiki page follows:
1. Position in the platform (mermaid flowchart, S88-coloured)
2. Capability matrix (≤ 10 rows)
3. Topic contract (auto-generated from src/commands/index.js)
4. Lifecycle (mermaid sequenceDiagram)
5. Configuration (mermaid flowchart + form-to-config table)
6. Examples (basic/integration/dashboard tiers)
7. State chart (stateDiagram-v2, only for stateful nodes)
8. When you would NOT use this node
9. Known limitations / current issues
Hard rules: diagrams before prose, ≤ 60 words of unbroken prose
anywhere, topic contract auto-generated (no hand-written drift).
Per-node application is the next step (P9.3-P9.6 in TASKS.md).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Resolves the 5 open questions answered during Phase 1 setup:
- Topic naming: canonical from Phase 1 (set/cmd/data/child/query/evt),
with full glossary in CONTRACTS.md §1.
- Parent EVOLV branch lineage: rebased onto origin/main.
- Deprecated paths: tracked as Phase 8.5 in TASKS.md.
- Child storage: registry-as-truth + named getters via
declareChildGetter.
- Tick: opt-in via static tickInterval; default is event-driven via
source.emitter 'output-changed'. statusInterval (always-on, 1Hz)
is separate.
Plus two new pre-existing-issue notes from the sanity gate:
- dashboardAPI uses Mocha-style describe() under node:test (broken).
- reactor tests are mathjs-bound (~13s/file load).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Platform-wide refactor plan: README, CONVENTIONS, CONTRACTS,
MODULE_SPLIT, TASKS, OPEN_QUESTIONS. Source of truth for the
phased refactor across all 12 submodules.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pump-shutdown deadlock fix split across two submodules:
- rotatingMachine@8f9150e: shutdown sequence clears state.delayedMove
so the abort-and-return-to-operational path doesn't auto-pickup the
queued setpoint and re-engage the pump.
- machineGroupControl@ea2857f: turnOffAllMachines clears MGC's
_delayedCall and serializes per-pump shutdown so PS's 2 s tick loop
can't interrupt an in-flight shutdown.
Live verification on pumpingstation-complete-example demo: basin now
shuts pumps off at stopLevel cleanly, reverses to fill, completes the
hysteresis cycle.
Also disable the trends page in the demo flow (build_flow.py + regen
flow.json). FlowFuse ui-chart's per-series server-side history buffer
(7 charts × ~20 series × 3600-point retention) was saturating the
Node-RED event loop at 129% CPU, making the dashboard freeze on every
click. Trends remain available — just disabled by default; flip the
ui_page_trends "d" key to false to re-enable.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
WARN now fires only when force-aborting an actually in-flight pump
movement (gate-bypass safety net), not on every no-op tick.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the _dispatchInFlight gate that mirrors rotatingMachine
state.delayedMove. Before this, PS at 1 Hz overran in-flight pump
ramps via concurrent handleInput entries, producing the live thrash:
120 aborts / 2 min, pump_b clamped at minFlow.
Includes regression test:
test/mgc-overactive-demand-serialization.integration.test.js
covering concurrent-burst serialization (30 calls → ≤ 5 aborts) and
latest-wins semantic.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- nodes/machineGroupControl@69bdf11 makes DOWNSTREAM single-writer
(handlePressureChange = live aggregate; optimizer target moved to
AT_EQUIPMENT). Closes the ps-mgc-flow-contract failure.
- test/inflow-overcapacity-stability now starts the basin at maxLevel
so PS percControl is immediately 100 % (the actual storm condition)
and uses real-time waits between ticks so movementManager intervals
fire — the previous setImmediate yield was too fast for moves to
progress, making pumps look perma-parked even when behaviour was OK.
Park observations dropped from 83 to 3 across the sim window; final
ctrl converges to ~88 % across all 3 pumps.
All 82 cross-node + node integration tests now pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- ps-mgc-flow-contract: asserts PS's view of MGC outflow equals the live
per-pump aggregate at every tick. Currently FAILS — exposes that
MGC's flow.predicted.downstream reverts to optimalControl's bestFlow
target after handlePressureChange writes the correct flow.act, leaving
PS with stale outflow values. The mirror added in dc27a56 is necessary
but not sufficient.
- dead-zone-signal: asserts the Schmitt-trigger transitions
(engaged 100% → keep-alive 1% → off 0%) across startLevel↓/stopLevel↓
with proper rising-edge re-arm. Currently PASSES.
- inflow-overcapacity-stability: 45 s sim at 2× station capacity;
asserts pumps don't thrash or park in accelerating residue. Currently
FAILS — pumps end up at ctrl=0 in 'accelerating' state, suggesting
the residue-unpark fix doesn't fully cover steady-state over-capacity.
- realistic-startup-timing: re-runs the varying-demand-during-startup
scenario with PRODUCTION-default state.time (starting=10s, warm=5s)
instead of the 1-2 s used elsewhere. Currently PASSES — confirms the
dispatch-reorder fix holds under realistic transition windows.
Honest summary: 2 pass, 2 fail. The two failures expose genuine
remaining defects in the PS↔MGC measurement contract and the
residue-unpark policy. They're committed FAILING so the bugs are
captured under version control until the underlying fixes land.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Submodule bumps land the deadlock fix (state.js residue unpark + MGC
optimalControl dispatch reorder) and pumpingStation stopLevel hysteresis.
- Renames examples/pumpingstation-3pumps-dashboard →
pumpingstation-complete-example with regenerated flow.json. New
dashboard groups, demand-broadcast wiring, S88 placement rule
applied, ui-chart trend-split and link-channel naming follow
.claude/rules/node-red-flow-layout.md.
- New cross-node test harness under test/: end-to-end-pumpingstation
drives PS + MGC + 3 pumps + physics simulator end-to-end and
verifies the ~5/15 min cycle.
- Adds Grafana provisioning dashboards (pumping-station.json) and a
helper sync-example.sh script for export/import to live Node-RED.
- Docker entrypoint + settings + compose tweaks for the persistent
user dir layout used by the demo.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- package.json: remove @tensorflow/tfjs and @tensorflow/tfjs-node.
Monster's TF code was already stripped; the deps were stale and kept
pulling a heavy native binary back into every install.
- .gitignore: ignore .repo-mem/ regenerable indexes and per-session
.claude/*.lock runtime files.
- CLAUDE.md: prepend READ-FIRST pointer to .claude/rules/repo-mem.md;
collapse the 'three outputs' bullet to a pointer at node-architecture.
- .claude/rules/telemetry.md: drop Port 0/1/2 duplication; reference
node-architecture.md.
- .claude/rules/testing.md: stop requiring a separate test/edge tier and
the basic/integration/edge example flow trio. Reflects what nodes
actually do.
- .claude/rules/repo-mem.md (new): when-to-call-which guide for the
per-repo memory MCP, anti-patterns, refresh model.
- .mcp.json (new): wire repo-mem stdio server.
- docs/DEVELOPER_GUIDE.md (new): step-by-step guide for adding a new
EVOLV node under the three-layer pattern.
- Bump nodes/pumpingStation to 6ab585b (docs + simulations refresh,
spill-flow path renames consistent with d8490aa).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
pumpingStation: predicted-volume hard-floor at 0; spill flow refactored
from flow.predicted.out.<child=overflow> to its own position
flow.predicted.overflow. Drops the spillPrev self-subtraction. New
underflowVolume diagnostic for flow-balance errors. 70/70 tests pass.
generalFunctions: MeasurementContainer.get() strict-resolves explicit
.child(name) — missing named child now returns null instead of falling
through to a sibling. Persistent setChildId remains a hint (no
behavioural change for registered children).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Integrator now clamps predicted volume to [dryRunSafetyVol,
maxVolAtOverflow], records cumulative spill as overflowVolume and
exposes a synthetic flow.predicted.out.overflow rate so net flow
balances to ~0 while pinned. _selectBestNetFlow holds the last
level-rate net flow during overflow so dashboards keep a usable
reading. Top-level predictedOverflowVolume / predictedOverflowRate
fields added to getOutput.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- bounds.js sets HTML5 min/max on every level + percent input so the
spinner can't push values past the basin hierarchy.
- Basin-level violations now surface in a visible ribbon above the
basin diagram and block Deploy via oneditsave.
- Layout polish: widened side panel, tightened basin viewBox, dropped
mode-preview axis labels, moved datum below the tank.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- pumpingStation: hold-then-ramp shift hysteresis driven by
shiftArmPercent (% output threshold for arming) instead of by level.
New e2e integration test exercises the full fill→arm→hold→ramp-down
cycle. Editor preview gains the arming-% horizontal line.
- generalFunctions: add shiftArmPercent to the pumpingStation schema;
add prominent doc block on MeasurementContainer documenting the
`${type}.${variant}.${position}.${childId}` flatten format and the
implicit 'default' childId convention so dashboards don't drop it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- rotatingMachine@399e0a8: editor hygiene (name default, status
clear on close), remove redundant idle-position clamp in
flow/power predictions.
- machineGroupControl@9c79dac: bug fix — stale flow/power cache
now cleared on MGC shutdown so parent pumpingStation sees the
drop immediately. Also awaits shutdown promises correctly and
corrects the NCog integration tests to match centrifugal-pump
physics (Q/P monotonic → NCog=0 → fallback to equal distribution).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>