- tools/contract-verify/ — diffs CONTRACT.md ## Inputs table vs src/commands/index.js registry. First run found 3 real drifts: MGC has `set.scaling` in CONTRACT (not in registry); monster + settler registry has `child.register` (not in CONTRACT); pumpingStation registry has `set.outflow` (not in CONTRACT). - tools/flow-lint/ — lints examples/*.flow.json against the rules in .claude/rules/node-red-flow-layout.md. First run flagged the monster/basic flow (4 ui-* at 0,0 + ui-chart missing interpolation property) and rotatingMachine/edge.flow.json (6 ui-* at 0,0). - Both tools are read-only, single-binary npm packages with a `--json` output mode for CI, exit code 1 on drift. Encode the rules so we don't have to re-discover the bugs that motivated them. Per CLAUDE.md tooling doctrine: prefer these over ad-hoc grep/jq. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@evolv/flow-lint
Lint Node-RED flow JSON against the EVOLV flow-layout rule
(.claude/rules/node-red-flow-layout.md).
Usage
# every examples/*.flow.json across all nodes
node tools/flow-lint/bin/flow-lint.js
# one flow
node tools/flow-lint/bin/flow-lint.js nodes/rotatingMachine/examples/01-Basic.flow.json
# CI / JSON output (one line per flow)
node tools/flow-lint/bin/flow-lint.js --json
Exit code 1 on any error-severity finding; 0 otherwise (warnings do
not fail).
Rules
| Rule | Severity | Catches |
|---|---|---|
UI_XY |
error | ui-* nodes with both x and y at 0 — pile up at canvas origin. |
UI_CHART_PROP |
error | ui-chart missing one of the required-or-it-renders-blank properties (interpolation, yAxisProperty, …). |
UI_CHART_TYPE |
warn | width / height as string instead of number. |
UI_CHART_PALETTE |
warn | colors array with fewer than 3 entries. |
INJECT_JSON_PROPS |
error | inject with payloadType:"json" but missing props[] — silently treated as string. |
LINK_CHANNEL_NAME |
warn | link out / link in without a cmd: / evt: / setup: prefix. |
LINK_BROKEN |
error | link out / link in referencing a non-existent node id. |
LINK_PAIR_TYPE |
error | link out paired with anything other than link in, or vice versa. |
LINK_PAIR_ASYMMETRIC |
error | One side references the other but the partner does not link back. |
DEBUG_LOG_IN_FLOW |
warn | enableLog:"debug" shipped in a flow — fills container log. |
SELF_LOOP |
error | Any node wired to itself. |
GROUP_WIDTH_SUM |
warn | ui-group widths on a ui-page summing to non-multiple of 12 — leaves grid gaps. |
Why use it
Every rule corresponds to a bug we've actually hit:
UI_XYandUI_CHART_PROP— the dashboard pile-up + blank-chart bugs.INJECT_JSON_PROPS— the silent-string inject bug.LINK_PAIR_ASYMMETRIC— drift between named channels.SELF_LOOP— the 250k-msg/sreplace_allincident.
Run before committing any flow change.