docs: standards cleanup — single front-door CONTRACTS.md + archive stale plan artifacts

Establish CONTRACTS.md at the EVOLV root as the canonical map of where every
contract, rule, and standard lives. Surface it from CLAUDE.md so every fresh
agent or colleague lands there first.

Reshape .claude/refactor/ to reflect that the platform refactor is done:
live standards stay at the top level; the plan artifacts (CONTINUE_HERE.md,
TASKS.md) move into Archive/ with WARNING banners.

Drop content that drifted out of date or duplicated the new standards stack:
- docs/DEVELOPER_GUIDE.md (pre-refactor walkthrough; superseded by
  wiki/Architecture, wiki/Getting-Started, .claude/rules/node-architecture,
  .claude/refactor/MODULE_SPLIT + per-node CONTRACT.md + src/commands/).
- .agents/decisions/ (15 DECISION files): load-bearing decisions belong in
  commit messages and PR descriptions; live open items in OPEN_QUESTIONS.md.
- .agents/improvements/TOP10_*.md: moved to Archive/.

Bump generalFunctions to 49c77f2 — adds CONTRACT.md inside the library:
different shape from per-node CONTRACT.md files (library API, not msg.topic),
with stability tags and pointers to .claude/refactor/CONTRACTS.md §N.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Rene De Ren
2026-05-18 15:48:46 +02:00
parent 560cc2f39a
commit 253ac93896
26 changed files with 210 additions and 1278 deletions

View File

@@ -71,17 +71,11 @@ Current owner-approved defaults (February 16, 2026):
- Breaking `msg.topic`/payload changes are allowed only with explicit migration/deprecation notes.
- Safety posture: `availability-first`
- Prefer continuity of operation with bounded safeguards over early protective trips.
- Decision logging: `required for all decision-gate changes`
- Every decision-gate outcome must be recorded in `.agents/decisions/`.
Decision log:
- Record important decisions in `.agents/decisions/DECISION-YYYYMMDD-<slug>.md`.
- Include context, options, decision, consequences, and rollback/migration notes.
- Decision logging: record load-bearing decisions in the commit message and PR description. Live open items belong in `.claude/refactor/OPEN_QUESTIONS.md`. Superseded plan artifacts live in `.agents/improvements/Archive/` and `.claude/refactor/Archive/`.
Functional/architectural improvements backlog:
- Track deferred functional/runtime/architecture improvements in `.agents/improvements/IMPROVEMENTS_BACKLOG.md`.
- If an improvement is discovered during non-functional work, add it to this backlog before closing the task.
- Keep the top priority review list in `.agents/improvements/TOP10_PRODUCTION_PRIORITIES_YYYY-MM-DD.md` when requested.
- When an item is implemented after review, remove it from `.agents/improvements/IMPROVEMENTS_BACKLOG.md` and note the fix in session notes/PR context.
## Agent Routing Table

View File

@@ -1,38 +0,0 @@
# DECISION-20260216-agent-harness-defaults
## Context
- Task/request: Adapt EVOLV agents/skills using Harness Engineering patterns and set owner-controlled operating defaults.
- Impacted files/contracts: `.agents/AGENTS.md`, `.agents/skills/*/SKILL.md`, `.agents/skills/*/agents/openai.yaml`, decision-log policy.
- Why a decision is required now: New harness workflow needs explicit defaults for compatibility, safety bias, and governance discipline.
## Options
1. Compatibility posture
- Option A: strict backward compatibility
- Option B: controlled compatibility breaks with migration notes
2. Safety posture
- Option A: protection-first
- Option B: availability-first
3. Decision logging scope
- Option A: required only for breaking/risky changes
- Option B: required for all decision-gate outcomes
## Decision
- Selected option: Compatibility `controlled`; Safety `availability-first`; Decision logging `required for all decision-gate changes`.
- Decision owner: User
- Date: February 16, 2026
- Rationale: Maintain delivery and operational continuity while preserving governance through mandatory, durable decision records.
## Consequences
- Compatibility impact: Breaking contract changes are permissible only when migration/deprecation is explicit.
- Safety/security impact: Control changes should bias toward continuity with bounded safeguards; critical protections still require explicit constraints.
- Data/operations impact: Decision traceability improves cross-turn consistency and auditability.
## Implementation Notes
- Required code/doc updates: Set defaults in `.agents/AGENTS.md` and orchestrator skill instructions; keep decision-log template active.
- Validation evidence required: Presence of defaults in policy docs and this decision artifact under `.agents/decisions/`.
## Rollback / Migration
- Rollback strategy: Update defaults in `.agents/AGENTS.md` and orchestrator SKILL; create a superseding decision log entry.
- Migration/deprecation plan: For any future hard-break preference, require explicit migration plan and effective date in a new decision entry.

View File

@@ -1,43 +0,0 @@
# Decision: Shared Modern PID in generalFunctions + PumpingStation Flow-Based Adoption
- Date: 2026-02-23
- Scope: `nodes/generalFunctions/src/pid/*`, `nodes/pumpingStation/src/*`
## Context
Flow-based control in `pumpingStation` needed a production-grade PID with freeze/unfreeze, runtime retuning, and support for cascade/secondary-loop architecture.
## Options Considered
1. Implement PID only inside `pumpingStation`.
2. Implement shared PID in `generalFunctions` and consume it from `pumpingStation`.
3. Keep current heuristic (non-PID) flow controller.
## Decision
Chose option 2.
## Rationale
- PID behavior is cross-domain control functionality and should be reusable across EVOLV nodes.
- `generalFunctions` already serves as shared utility/runtime infrastructure.
- Reuse reduces drift and duplicated control logic.
- PumpingStation can immediately adopt shared PID while preserving existing topic contracts.
## Consequences
- Positive:
- Single, test-covered PID implementation with modern features.
- PumpingStation flow mode becomes true closed-loop control.
- Runtime support for freeze/unfreeze and tuning updates without redeploy.
- Risks:
- Behavioral differences versus prior heuristic flow control.
- Requires conservative tuning per site.
## Safety / Compatibility
- No existing topic names were removed.
- Added optional control topics for PID runtime management.
- Existing non-flowbased modes remain intact.
## Rollback
- Revert `nodes/pumpingStation/src/specificClass.js` flow-based branch to previous heuristic logic.
- Keep shared PID module in `generalFunctions` for future use, or revert `nodes/generalFunctions/src/pid/*` if required.
## Migration Notes
- For `flowbased`, start with low `kp/ki`, verify stability in commissioning, then tune upward.
- Use `freezeFlowPid` and `setFlowPidMode` during maintenance or manual takeover.

View File

@@ -1,33 +0,0 @@
# Decision: Harden NRMSE and Use Metric Profiles in RotatingMachine
- Date: 2026-02-24
- Scope: `nodes/generalFunctions/src/nrmse/*`, `nodes/rotatingMachine/src/specificClass.js`
## Context
Drift analytics were previously single-path and flow-focused with weak input safeguards in NRMSE.
Requirement: make NRMSE architecturally robust and apply it across multiple measurements in rotatingMachine.
## Decision
Adopt a metric-profile drift architecture:
1. Harden `generalFunctions/nrmse` with:
- strict validation for malformed inputs
- timestamp-aware alignment support
- per-metric state
- configurable rolling window and EWMA long-term trend
- point-based API (`assessPoint`) while retaining legacy calls
2. Rewire rotatingMachine to consume NRMSE per metric:
- `flow` model drift
- `power` model drift
- pressure-quality drift as node-specific plausibility/redundancy assessment
3. Expose drift and confidence outputs per metric in node output payload.
## Consequences
- Drift computations are deterministic and safer under bad inputs.
- RotatingMachine confidence now reflects multiple measurement channels.
- Output schema expands with power/pressure drift fields.
## Rollback Notes
- Revert `errorMetrics.js` and rotatingMachine drift wiring to return to legacy flow-only drift behavior.

View File

@@ -1,34 +0,0 @@
# Decision: RotatingMachine Hydraulic Efficiency Correction and Prediction Confidence
- Date: 2026-02-24
- Scope: `nodes/rotatingMachine/src/specificClass.js`, rotatingMachine integration tests
## Context
Hydraulic efficiency calculation in `rotatingMachine` was dimensionally inconsistent and could over/under-report efficiency KPIs.
At the same time, prediction drift tooling (`nrmse`) existed but was not actively connected to rotatingMachine output confidence.
## Options Considered
1. Keep existing formula and only tune thresholds.
2. Replace formula with standard hydraulic power/efficiency equations and expose prediction confidence from live pressure source + drift.
## Decision
Adopt option 2.
- Hydraulic power now follows standard engineering relation:
- `P_h = Q * Δp` (equivalent to `ρ g Q H`)
- `η_h = P_h / P_in`
- RotatingMachine now computes flow drift via `nrmse` from measured vs predicted flow windows.
- RotatingMachine now exposes prediction confidence fields in output:
- `predictionQuality`
- `predictionConfidence`
- `predictionPressureSource`
- `predictionFlags`
## Consequences
- Efficiency KPIs become physically interpretable and traceable to pressure/flow/power inputs.
- Prediction trust is now observable by downstream control/dashboard layers.
- Output schema is expanded with new prediction confidence fields.
## Rollback / Migration Notes
- Rollback path: revert `specificClass.js` hydraulic block and prediction-health integration.
- No mandatory migration required for existing flows unless they choose to consume new prediction confidence fields.

View File

@@ -1,38 +0,0 @@
# Decision: Canonical Unit Anchoring and Curve Unit Normalization in RotatingMachine
- Date: 2026-02-24
- Scope: `nodes/rotatingMachine/*`, `nodes/generalFunctions/src/measurements/MeasurementContainer.js`, `nodes/generalFunctions/src/configs/rotatingMachine.json`
## Context
RotatingMachine previously relied on node-local defaults for measurement storage units, with implicit assumptions that loaded machine curves used the same units as runtime configuration. This made unit drift likely when model curves, simulated inputs, and runtime settings differed.
Owner decision direction:
- use a single unit anchor strategy
- treat node/UI units as ingress/egress only
- add explicit curve unit metadata
- reject or flag blank/invalid measurement units
## Decision
1. Extend `MeasurementContainer` with optional canonical-anchor mode:
- per-type canonical unit mapping
- strict unit validation and required-unit policy
- compatibility checks by measure family
- requested-unit conversion at flattened output stage
2. Apply canonical policy in `rotatingMachine` runtime:
- internal storage and calculations anchored to SI-like canonical units (`Pa`, `m3/s`, `W`, `K`)
- egress payloads converted back to configured output units
- ingress `simulateMeasurement` path requires explicit valid units
3. Add explicit curve unit metadata (`asset.curveUnits`) and normalize loaded curves into canonical units before predictor initialization.
## Consequences
- Unit handling is centralized and deterministic for RotatingMachine.
- Curve/model-unit mismatch risk is reduced by explicit metadata plus normalization.
- Existing output topic/field names remain stable; values are emitted in configured output units while internals stay canonical.
- This establishes a migration template for remaining EVOLV nodes.
## Rollback Notes
- Revert `MeasurementContainer` canonical/validation extensions.
- Revert RotatingMachine unit-policy and curve-normalization wiring.
- Remove `asset.curveUnits` schema entry and restore previous node-local default-unit behavior.

View File

@@ -1,37 +0,0 @@
# Decision: Unit-Anchor Rollout Phase 1 (MachineGroup, PumpingStation, Valve, ValveGroupControl)
- Date: 2026-02-24
- Scope:
- `nodes/machineGroupControl/src/nodeClass.js`
- `nodes/machineGroupControl/src/specificClass.js`
- `nodes/pumpingStation/src/nodeClass.js`
- `nodes/pumpingStation/src/specificClass.js`
- `nodes/valve/src/nodeClass.js`
- `nodes/valve/src/specificClass.js`
- `nodes/valveGroupControl/src/nodeClass.js`
- `nodes/valveGroupControl/src/specificClass.js`
## Context
After adopting canonical-unit anchoring in `rotatingMachine`, adjacent controller nodes still mixed local units, unitless writes, and implicit conversions. That left cross-node behavior sensitive to registration order and source-unit assumptions.
## Decision
1. Apply the same canonical storage policy per node:
- internal storage in canonical units (`Pa`, `m3/s`, `W`, `K` where relevant),
- preferred/output units for operator-facing status and output payloads.
2. Enable strict measurement ingress discipline on migrated nodes:
- `strictUnitValidation: true`,
- `throwOnInvalidUnit: true`,
- required unit for physically dimensional types (`flow`, `pressure`, `power`, `temperature`, and node-specific equivalents).
3. Replace unitless runtime writes/reads with explicit-unit helpers in each nodes domain class, including child-machine/child-valve interactions.
## Consequences
- Cross-node calculations now run against a deterministic unit anchor in phase-1 nodes.
- Status/output values remain in preferred/output units, while internal math stays canonical.
- Legacy paths that send dimensional values without units now fail fast instead of silently coercing.
## Rollback Notes
- Revert the eight files listed in scope.
- Restore previous `MeasurementContainer` initialization (non-canonical, non-strict behavior) in each node.
- Remove helper-based explicit unit reads/writes and revert to prior direct chain usage.

View File

@@ -1,36 +0,0 @@
# DECISION-20260323-architecture-layering-resilience-and-config-authority
## Context
- Task/request: refine the EVOLV architecture baseline using the current stack drawings and owner guidance.
- Impacted files/contracts: architecture documentation, future wiki structure, telemetry/storage strategy, security boundaries, and configuration authority assumptions.
- Why a decision is required now: the architecture can no longer stay at a generic "Node-RED plus cloud" level; several operating principles were clarified by the owner and need to be treated as architectural defaults.
## Options
1. Keep the architecture intentionally broad and tool-centric
- Benefits: fewer early commitments.
- Risks: blurred boundaries for resilience, data ownership, and security; easier to drift into contradictory implementations.
- Rollout notes: wiki remains descriptive but not decision-shaping.
2. Adopt explicit defaults for resilience, API boundary, telemetry layering, and configuration authority
- Benefits: clearer target operating model; easier to design stack services and wiki pages consistently; aligns diagrams with intended operational behavior.
- Risks: some assumptions may outpace current implementation and therefore create an architecture debt backlog.
- Rollout notes: document gaps clearly and treat incomplete systems as planned workstreams rather than pretending they already exist.
## Decision
- Selected option: Option 2.
- Decision owner: repository owner confirmed during architecture review.
- Date: 2026-03-23.
- Rationale: the owner clarified concrete architecture goals that materially affect security, resilience, and platform structure. The documentation should encode those as defaults instead of leaving them implicit.
## Consequences
- Compatibility impact: low immediate code impact, but future implementations should align to these defaults.
- Safety/security impact: improved boundary clarity by making central the integration entry point and keeping edge protected behind site/central mediation.
- Data/operations impact: multi-level InfluxDB and smart-storage behavior become first-class design concerns; `tagcodering` becomes the intended configuration backbone.
## Implementation Notes
- Required code/doc updates: update the architecture review doc, add visual wiki-ready diagrams, and track follow-up work for incomplete `tagcodering` integration and telemetry policy design.
- Validation evidence required: architecture docs reflect the agreed principles and diagrams; no contradiction with current repo evidence for implemented components.
## Rollback / Migration
- Rollback strategy: return to a generic descriptive architecture document without explicit defaults.
- Migration/deprecation plan: implement these principles incrementally, starting with configuration authority, telemetry policy, and site/central API boundaries.

View File

@@ -1,36 +0,0 @@
# DECISION-20260323-compose-secrets-via-env
## Context
- Task/request: harden the target-state stack example so credentials are not stored directly in `temp/cloud.yml`.
- Impacted files/contracts: `temp/cloud.yml`, deployment/operations practice for target-state infrastructure examples.
- Why a decision is required now: the repository contained inline credentials in a tracked compose file, which conflicts with the intended security posture and creates avoidable secret-leak risk.
## Options
1. Keep credentials inline in the compose file
- Benefits: simplest to run as a standalone example.
- Risks: secrets leak into git history, reviews, copies, and local machines; encourages unsafe operational practice.
- Rollout notes: none, but the risk remains permanent once committed.
2. Move credentials to server-side environment variables and keep only placeholders in compose
- Benefits: aligns the manifest with a safer deployment pattern; keeps tracked config portable across environments; supports secret rotation without editing the compose file.
- Risks: operators must manage `.env` or equivalent secret injection correctly.
- Rollout notes: provide an example env file and document that the real `.env` stays on the server and out of version control.
## Decision
- Selected option: Option 2.
- Decision owner: repository owner confirmed during task discussion.
- Date: 2026-03-23.
- Rationale: the target architecture should model the right operational pattern. Inline secrets in repository-tracked compose files are not acceptable for EVOLV's intended OT/IT deployment posture.
## Consequences
- Compatibility impact: low; operators now need to supply environment variables when deploying `temp/cloud.yml`.
- Safety/security impact: improved secret hygiene and lower credential exposure risk.
- Data/operations impact: deployment requires an accompanying `.env` on the server or explicit `--env-file` usage.
## Implementation Notes
- Required code/doc updates: replace inline secrets in `temp/cloud.yml`; add `temp/cloud.env.example`; keep the real `.env` untracked on the server.
- Validation evidence required: inspect compose file for `${...}` placeholders and verify no real credentials remain in tracked files touched by this change.
## Rollback / Migration
- Rollback strategy: reintroduce inline values, though this is not recommended.
- Migration/deprecation plan: create a server-local `.env` from `temp/cloud.env.example`, fill in real values, and run compose from that environment.

View File

@@ -1,43 +0,0 @@
## Context
The single demo bioreactor did not reflect the intended EVOLV biological treatment concept. The owner requested:
- four reactor zones in series
- staged aeration based on effluent NH4
- local visualization per zone for NH4, NO3, O2, and other relevant state variables
- improved PFR numerical stability by increasing reactor resolution
The localhost deployment also needed to remain usable for E2E debugging with Node-RED, InfluxDB, and Grafana.
## Options Considered
1. Keep one large PFR and add more internal profile visualization only.
2. Split the biology into four explicit reactor zones in the flow and control aeration at zone level.
3. Replace the PFR demo with a simpler CSTR train for faster visual response.
## Decision
Choose option 2.
The demo flow now uses four explicit PFR zones in series with:
- equal-zone sizing (`4 x 500 m3`, total `2000 m3`)
- explicit `Fluent` forwarding between zones
- common clocking for all zones
- external `OTR` control instead of fixed `kla`
- staged NH4-based aeration escalation with 30-minute hold logic
- per-zone telemetry to InfluxDB and Node-RED dashboard charts
For runtime stability on localhost, the demo uses a higher spatial resolution with moderate compute load rather than the earlier single-reactor setup.
## Consequences
- The flow is easier to reason about operationally because each aeration zone is explicit.
- Zone-level telemetry is available for dashboarding and debugging.
- PFR outlet response remains residence-time dependent, so zone outlet composition will not change instantly after startup or inflow changes.
- Grafana datasource query round-trip remains valid, but dashboard auto-generation still needs separate follow-up if strict dashboard creation is required in E2E checks.
## Rollback / Migration Notes
- Rolling back to the earlier demo means restoring the single `demo_reactor` topology in `docker/demo-flow.json`.
- Existing E2E checks and dashboards should prefer the explicit zone measurements (`reactor_demo_reactor_z1` ... `reactor_demo_reactor_z4`) going forward.

View File

@@ -1,54 +0,0 @@
# DECISION-20260422-pumpingstation-5-threshold-naming
## Context
- Task/request: Re-draw the pumpingStation basin model and rename the configuration fields so they match the conceptual model used in the wiki.
- Impacted files/contracts:
- `generalFunctions/src/configs/pumpingStation.json` (schema keys)
- `nodes/pumpingStation/src/specificClass.js` (internal state + comments)
- `nodes/pumpingStation/src/nodeClass.js` (config ingestion mapping)
- `nodes/pumpingStation/pumpingStation.html` (editor field IDs + labels)
- `nodes/pumpingStation/test/*` (test fixtures)
- `examples/pumpingstation-3pumps-dashboard/{build_flow.py, flow.json, README.md}`
- saved production flows that reference the old field names (breaking change)
- Why a decision is required now: The old names (`stopLevel`, `maxFlowLevel`, `minFlowLevel`, `heightInlet/Outlet/Overflow`) conflated geometry with control thresholds and had a redundant field (`minFlowLevel` always had to equal `startLevel`).
## Options
1. Keep old names; just document them better
- Benefits: Zero breaking change.
- Risks: Naming keeps confusing new contributors; docs continue drifting from code.
2. Adopt the 5-threshold naming from the wiki basin diagram (selected)
- Benefits: Clear semantic split — two safety thresholds (`dryRunLevel`, `overflowLevel`), three control thresholds (`minLevel`, `startLevel`, `maxLevel`) — plus three physical pipe heights (`inflowLevel`, `outflowLevel`, basin `height`). Drops the redundant `minFlowLevel`. Matches the diagram in the functional description.
- Risks: Breaking change for saved flows; node editor fields must be re-entered.
- Rollout notes: RnD/trial node — no compat shim. Breaking change documented in commit bodies and wiki.
## Decision
- Selected option: Option 2.
- Decision owner: User
- Date: 2026-04-22
- Rationale: The names should reflect the model. The diagram came first; the code should match the diagram, not the other way around. Compat posture is "controlled" (per DECISION-20260216) — breaking changes are permitted with migration notes.
## Mapping
| Old | New |
|---|---|
| `heightInlet` | `inflowLevel` |
| `heightOutlet` | `outflowLevel` |
| `heightOverflow` | `overflowLevel` |
| `stopLevel` | `minLevel` |
| `maxFlowLevel` | `maxLevel` |
| `minFlowLevel` | removed (collapsed into `startLevel`) |
| `minVolIn/Out` (internal) | `minVolAtInflow/Outflow` |
| `maxVolOverflow` (internal) | `maxVolAtOverflow` |
## Consequences
- Compatibility impact: Existing flows break; editor fields must be re-entered.
- Safety/security impact: Safety thresholds (`dryRunLevel`, `overflowLevel`) now have first-class names — guardrail validation can reason about them explicitly.
- Data/operations impact: InfluxDB payload field names change (`maxVolOverflow``maxVolAtOverflow` etc.). Downstream Grafana dashboards referencing the old names must update.
## Implementation Notes
- Required code/doc updates: Done in commits pumpingStation@a218945, generalFunctions@4252292, EVOLV@b885f29.
- Validation evidence required: Unit tests (`node --test test/basic/*.test.js`) pass; `grep -r` confirms zero residual old names in pumpingStation/ + generalFunctions/pumpingStation.json + examples/.
## Rollback / Migration
- Rollback strategy: revert the three commits; the renames are isolated.
- Migration/deprecation plan: None — RnD node, breaking change is acceptable.

View File

@@ -1,46 +0,0 @@
# DECISION-20260422-pumpingstation-mode-tier-template
## Context
- Task/request: Document each pumpingStation control mode uniformly so operators can compare them and contributors can add new ones from a template.
- Impacted files/contracts: `wiki/modes/*.md`, `wiki/diagrams/modes/*.drawio.svg`.
- Why a decision is required now: The initial `levelbased.md` used a 2D `demand-vs-level` transfer-function plot. That plot form works for static memoryless control but misleads for modes whose curve shape changes at runtime (e.g. `powerBased`) or where there is no curve at all (`mpc`). We need one template that stretches to cover all cases.
## Options
1. One template, transfer-function only
- Benefits: Uniformity.
- Risks: Silently misleading for Tier-2/Tier-3 modes where the "curve" is not well-defined.
2. Per-mode ad-hoc diagrams
- Benefits: Each mode gets the best visual for itself.
- Risks: No common vocabulary — comparing modes becomes harder.
3. Three-tier template (selected)
- Benefits: Classifies every mode into one of three buckets, each with a dedicated diagram type. Still one template — only the diagram section branches.
- Risks: Some modes don't fit cleanly; will need judgement.
## Tier definitions
| Tier | Control surface | Example modes | Diagrams |
|---|---|---|---|
| 1 | Static: `demand = f(x)` memoryless | `levelbased`, `manual` | Single-curve transfer function |
| 2 | Parameterised: shape fixed, curve moves with `θ(t)` | `flowbased` (PID), `pressureBased`, `percentageBased`, `powerBased` | Transfer function + parameter-overlay / family-of-curves |
| 3 | Optimisation / horizon: no fixed curve | `hybrid-optimal`, `mpc`, weather-aware | Block diagram of signal flow + scenario time-series |
## Decision
- Selected option: Option 3 — three-tier classification with diagram type per tier.
- Decision owner: User
- Date: 2026-04-22
- Rationale: Keeps the mode pages comparable (same six sections) while being honest about what's actually drawable. Tier-3 modes get scenario-based analysis (via the `eval/` harness) instead of a fictitious static curve.
## Consequences
- Compatibility impact: None — this is doc-level.
- Safety/security impact: None.
- Data/operations impact: New modes get a template to follow; reviews have a shared vocabulary.
## Implementation Notes
- Required code/doc updates: `wiki/modes/README.md` lists the tiers and template; `wiki/modes/{flowbased, powerbased, mpc}.md` are worked templates covering Tier 2 (×2) and Tier 3 (×1) respectively.
- Validation evidence required: A reviewer reading a mode page can identify which tier it is within 10 seconds without scrolling.
## Rollback / Migration
- Rollback strategy: Delete `wiki/modes/`; revert the table in `wiki/README.md`.
- Migration/deprecation plan: N/A — adding a tier later (e.g. Tier 4 — RL-based) is trivially additive.

View File

@@ -1,57 +0,0 @@
# DECISION-20260422-pumpingstation-simulations-harness
## Context
- Task/request: Provide a way to fluctuate inputs to the pumpingStation and observe the system's response over time, in a readable form suitable for post-hoc analysis (operator review, Grafana, or ad-hoc debugging).
- Impacted files/contracts: `nodes/pumpingStation/simulations/*`, `test/basic/*`.
- Why a decision is required now: Unit tests (`node --test`) verify individual functions in isolation. They can't ergonomically show "what does the level look like over 20 minutes of storm surge". That's a different artefact.
## Options
1. Extend unit tests to cover scenarios
- Benefits: Single testing surface.
- Risks: Unit tests are assertion-heavy and slow to read; scenario output (tables, events) gets lost in TAP.
2. Separate `simulations/` folder with a scenario runner (selected)
- Benefits: Scenarios read as narratives ("steady state", "storm surge", "safety dry-run"); output is human-friendly (ASCII table + events + expectation checks); JSONL per-tick log enables Grafana streaming or offline analysis.
- Risks: Second test surface to maintain.
3. Real-time Node-RED deployment + observe
- Benefits: Closest to production.
- Risks: Slow, requires infrastructure, irreproducible.
## Decision
- Selected option: Option 2.
- Decision owner: User
- Date: 2026-04-22
- Rationale: Unit tests answer "is this function correct?"; scenarios answer "how does the system behave under this input profile?". Two distinct questions — two distinct tools. The split also matches the .claude/rules/testing.md 3-tier convention (basic/integration/edge) which is for asserted behaviours, not scenario replay.
### Addendum (same-day rename)
Folder was initially named `eval/`. Renamed to `simulations/` in commit pumpingStation@3e13512`eval` and `test` are near-synonyms so the split implied a conceptual difference that doesn't really exist. `simulations/` is more honest about what's happening (scripted plant inputs driving a physics sim, recorded for analysis). Rationale above is unchanged; only the folder name is.
## Architecture
```
test/
basic/ integration/ edge/ — node:test + assertions
simulations/
run.js — scenario driver
scenarios/*.js — each exports { name, config, setup, inputs(t,ps), expectations }
formatters/table.js — ASCII summary
logs/*.jsonl — one-line-per-tick output
README.md — usage + how to pipe into Grafana
```
Driver monkey-patches `Date.now()` so the volume integrator sees 1 second per tick regardless of wall-clock. Every tick records a state snapshot (level, volume, direction, netFlow, flowSource, demand, mode, safetyActive) to JSONL for streaming.
## Consequences
- Compatibility impact: None.
- Safety/security impact: None — read-only simulation.
- Data/operations impact: Running `node simulations/run.js --all` produces artefacts that can be checked into CI for regression (e.g. "did the storm scenario's max level rise compared to last release?"). The JSONL format is friendly to InfluxDB/Grafana for interactive review.
## Implementation Notes
- Required code/doc updates: Driver + three starter scenarios (`levelbased-steady`, `levelbased-storm`, `safety-dry-run-trip`) + README in `simulations/`.
- Validation evidence required: `node simulations/run.js --all` exits 0; manual inspection of JSONL confirms per-tick records make physical sense.
## Rollback / Migration
- Rollback strategy: Delete `simulations/`. Unit tests continue to work.
- Migration/deprecation plan: N/A.

View File

@@ -1,41 +0,0 @@
# DECISION-20260422-pumpingstation-wiki-in-code-repo
## Context
- Task/request: Document pumpingStation functional behaviour (basin model, control modes, safety). Initial draft went into the Gitea wiki repo (`pumpingStation.wiki.git`).
- Impacted files/contracts: location of all pumpingStation documentation; how docs, diagrams, and code stay in sync; wiki UI vs repo browsing UX.
- Why a decision is required now: Wiki repo + code repo diverge silently. When `specificClass.js` renames a field, nothing forces the wiki to follow. User preference is "single package" — clone once, edit together, review together.
## Options
1. Keep docs in `pumpingStation.wiki.git` (Gitea's native wiki)
- Benefits: Gitea wiki UI (Pages dropdown, `?edit=1`, dedicated URL).
- Risks: Two separate repos; code and doc drift silently.
- Rollout notes: Status quo as of 2026-04-22.
2. Move docs + diagrams into `pumpingStation.git/wiki/` (selected)
- Benefits: Single package — `git clone pumpingStation` gets code + docs + diagrams. Atomic commits can change code + doc + diagram together. Diagrams version-lock with the class they describe.
- Risks: Lose the Gitea wiki Pages dropdown. Browsing is via the repo tree.
- Rollout notes: Shrink the `.wiki.git` to a pointer at the new location.
3. Hybrid — diagrams only in code repo, Markdown pages in `.wiki.git`
- Benefits: Keep Gitea wiki UI.
- Risks: Image URLs break silently on rename; still two repos to sync.
- Rollout notes: Not pursued.
## Decision
- Selected option: Option 2 — everything under `pumpingStation/wiki/`.
- Decision owner: User (r.de.ren@brabantsedelta.nl)
- Date: 2026-04-22
- Rationale: Single package > Gitea wiki UI convenience. Review-as-one-PR pattern is worth more than the Pages dropdown. `wiki/README.md` acts as the index instead.
## Consequences
- Compatibility impact: Anyone bookmarking `RnD/pumpingStation/wiki/Functional-Description` lands on a one-line pointer. Breaking but low-impact.
- Safety/security impact: None.
- Data/operations impact: Future contributors must know to edit `wiki/` inside the code repo, not the wiki repo. Pointer page on the Gitea wiki explains.
## Implementation Notes
- Required code/doc updates: `pumpingStation/wiki/{functional-description.md, README.md, modes/, diagrams/}` populated; `.wiki.git` Home shrunk.
- Validation evidence required: Raw Gitea URLs resolve; `https://gitea.wbd-rd.nl/RnD/pumpingStation/src/branch/main/wiki/` browses cleanly.
## Rollback / Migration
- Rollback strategy: Reverse — copy `pumpingStation/wiki/*.md` back into `.wiki.git`, update `.wiki.git` Home to point at itself.
- Migration/deprecation plan: The pointer page stays indefinitely.

View File

@@ -1,36 +0,0 @@
# DECISION-YYYYMMDD-<slug>
## Context
- Task/request:
- Impacted files/contracts:
- Why a decision is required now:
## Options
1. Option A
- Benefits:
- Risks:
- Rollout notes:
2. Option B
- Benefits:
- Risks:
- Rollout notes:
## Decision
- Selected option:
- Decision owner:
- Date:
- Rationale:
## Consequences
- Compatibility impact:
- Safety/security impact:
- Data/operations impact:
## Implementation Notes
- Required code/doc updates:
- Validation evidence required:
## Rollback / Migration
- Rollback strategy:
- Migration/deprecation plan:

View File

@@ -1,15 +0,0 @@
# EVOLV Decision Log
Use this folder to store high-impact agent/user decisions that affect compatibility, safety, security, schema, or rollout risk.
Naming:
- `DECISION-YYYYMMDD-<slug>.md`
When to log:
- topic/payload/API contract changes
- safety envelope or fail-safe strategy changes
- security posture/default changes
- Influx retention/backfill/schema tradeoffs
- explicit acceptance of deferred high-risk debt
Start from `DECISION_TEMPLATE.md` for new entries.