feat(pumpingStation schema): add holdLevel + deadZoneKeepAlivePercent; slim npm pack

Schema:
- holdLevel (optional, default null → equals startLevel): 0 % ramp foot for
  the levelbased curve. When raised above startLevel, pumps engage at
  startLevel but hold at MGC flow.min across [startLevel, holdLevel] before
  the ramp begins.
- deadZoneKeepAlivePercent (default 1): percent emitted across the
  [stopLevel, startLevel] falling-edge keep-alive band.
- Refreshed startLevel / stopLevel descriptions: hysteresis is no longer
  coupled to inflowLevel (was misleading).

Packaging:
- Add .npmignore mirroring .gitignore plus the dev-only trees (test/,
  wiki/, scripts/, .claude/, …) so npm pack doesn't ship the doc set.
- Extend .gitignore with the standard dev-artifact deny list so both
  files share the same baseline.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
znetsixe
2026-05-19 21:35:49 +02:00
parent 8252a5f898
commit ae30cef89c
3 changed files with 57 additions and 2 deletions

9
.gitignore vendored
View File

@@ -1,5 +1,14 @@
# Repo dev artifacts. Mirrors the deny list in .npmignore so the two stay
# in sync — anything that shouldn't be committed AND shouldn't ship in the
# npm tarball goes in both files.
node_modules/ node_modules/
# Local stub generated by `npm install` in the submodule directory. # Local stub generated by `npm install` in the submodule directory.
# generalFunctions has no production deps of its own. # generalFunctions has no production deps of its own.
package-lock.json package-lock.json
*.tgz
.env
.env.*
.DS_Store
npm-debug.log*

28
.npmignore Normal file
View File

@@ -0,0 +1,28 @@
# === Mirrors .gitignore — items below this block are also excluded from
# the npm tarball. Kept here verbatim so npm pack doesn't fall back to
# the .gitignore inheritance (silent + surprising). ===
node_modules/
package-lock.json
*.tgz
.env
.env.*
.DS_Store
npm-debug.log*
# === Dev-only content the npm tarball doesn't need ===
# Tests + their harness — consumers load index.js, not the test tree.
test/
*.test.js
# Wiki / docs — useful in the repo, big in the pack.
wiki/
# One-off maintenance tooling (wiki generator, etc.) not used at runtime.
scripts/
# Project memory + IDE configs.
.claude/
.codex/
.repo-mem/
CLAUDE.md
CLAUDE.local.md

View File

@@ -498,7 +498,7 @@
"rules": { "rules": {
"type": "number", "type": "number",
"min": 0, "min": 0,
"description": "Pump-on threshold (engagement edge for stopLevel hysteresis). Demand stays at 0 % between startLevel and inflowLevel — the ramp foot is inflowLevel, not startLevel. The ramp itself scales 0 → 100 % across [inflowLevel, maxLevel]. When enableShiftedRamp is on, startLevel also serves as the bottom of the held-then-ramp curve during draining." "description": "Pump-on threshold (rising-edge engagement). Pumps stay off below startLevel until level rises through it; once engaged they remain on until level drops through stopLevel (falling-edge). Also serves as the bottom of the held-then-ramp curve during draining when enableShiftedRamp is on. Independent of basin geometry: NOT clamped against inflowLevel."
} }
}, },
"stopLevel": { "stopLevel": {
@@ -507,7 +507,25 @@
"type": "number", "type": "number",
"nullable": true, "nullable": true,
"min": 0, "min": 0,
"description": "Optional pump-off threshold. When set, PS sends an explicit turnOffAllMachines command to MGC the moment level drops below stopLevel. Independent of the ramp scaling — does NOT shift where the ramp starts. Pair with a startLevel above stopLevel to get hysteresis (pumps engage at startLevel rising, disengage at stopLevel falling). Must be ≥ minLevel and ≤ startLevel. NOTE: schema default stays null so omitting stopLevel keeps the hysteresis inactive (matching levelBased.js); the editor HTML provides a realistic 0.5 m default for drag-in UX." "description": "Optional pump-off threshold. When set, PS sends an explicit turnOffAllMachines command to MGC the moment level drops below stopLevel. Does NOT shape the ramp. Pair with a startLevel above stopLevel to get hysteresis (engage at startLevel rising, disengage at stopLevel falling). Must be ≥ minLevel and ≤ startLevel. NOTE: schema default stays null so omitting stopLevel keeps the hysteresis inactive; the editor HTML provides a realistic 0.5 m default for drag-in UX."
}
},
"holdLevel": {
"default": null,
"rules": {
"type": "number",
"nullable": true,
"min": 0,
"description": "Optional `0 %` ramp foot. When set, pumps engage at startLevel but hold at 0 % (= flow.min via MGC) across [startLevel, holdLevel], then ramp 0 → 100 % across [holdLevel, maxLevel]. Default null → equals startLevel, i.e. no hold band and the ramp starts immediately at startLevel. Must satisfy startLevel ≤ holdLevel ≤ maxLevel."
}
},
"deadZoneKeepAlivePercent": {
"default": 1,
"rules": {
"type": "number",
"min": 0,
"max": 100,
"description": "Percent emitted to MGC across the falling-edge keep-alive band [stopLevel, startLevel] (i.e. once engaged, while draining back below startLevel but still above stopLevel). 0 maps to flow.min; the 1 % default sits just above min so MGC keeps at least one pump rotating instead of resting at the absolute minimum."
} }
}, },
"maxLevel": { "maxLevel": {