Adds per-panel `meta.emittedFields` to machine.json (rotatingMachine) and
machineGroup.json (MGC) templates. Each non-row panel declares the Influx
field paths it visualizes, so a parent template's composer can filter out
panels already covered by its children (#39 no-data-duplication rule).
- config/machine.json: 13 non-row panels annotated.
- config/machineGroup.json: panels annotated.
- src/specificClass.js: collectEmittedFields(dashboard) helper.
- test/basic/slice37-emitted-fields.basic.test.js: 4 cases (template loads
with annotations, aggregation, missing-meta graceful, null input).
PRD F-6 panel set audit: machine.json already covers all the PRD-required
panels (State/Mode/Ctrl%/Runtime/NCog%/Flow/Efficiency/Pressure/Temperature/
Diagnostics) — substantially more than asked. No new panels added.
PRD F-7 predicted-vs-measured side-by-side: deferred. Current architecture
is "1 dashboard per node" (each child gets its own dashboard, cross-linked
from the parent), not "1 dashboard with N composed panels." Side-by-side
rendering of predicted (rotatingMachine dashboard) + measured (measurement
child dashboard) lives naturally as drill-down navigation today. Refactor
to a single-dashboard composition model would be substantial — flagged in
the issue comment for v2 if the drill-down UX proves insufficient.
Closes#37
Subscribes to Node-RED's flows:started runtime event, caches the {diff}
payload on the dashboardAPI source, and short-circuits the child.register
handler when none of {dashboardAPI id, child id, grandchild ids} appears in
diff.added/changed/removed/rewired. Predicate verified by S1 spike (#32).
- src/nodeClass.js: _attachLifecycleHook subscribes, _attachCloseHandler
cleans up. No-op when RED.events isn't available (unit-test friendly).
- src/specificClass.js: subtreeChanged() predicate + subtreeIdsFor() helper.
- src/commands/handlers.js: registerChild consults predicate before composing;
logs {event:'regen-skipped', outcome:'no-diff'} when skipping.
- test/basic/slice36-diff-predicate.basic.test.js: 8 cases — null/empty diff,
affected/unaffected ids, tab-id over-triggering avoidance, grandchild
inclusion, no-grandchild case.
Cold start (no cached diff yet) always regenerates — safe default. Edge case
documented in #32: when a brand-new child is wired to a registered parent,
the new child's id is in diff.added but not yet in registeredChildren when
flows:started fires. Mitigation (b) per spike findings: one-deploy race
accepted for R&D — next deploy picks up the new registration.
Closes#36
Encrypts the Grafana bearer token via Node-RED credentials block instead of
plain config (F-11). Adds folderUid config field threaded through to the
buildUpsertRequest payload (F-8, resolves PRD O-5). Migration path: legacy
plain bearerToken still loads, with one-time warn() prompting user to re-save.
Composition + URL + headers + per-instance UID were already in place; only
the credentials + folderUid + tests are new.
- dashboardAPI.html: bearerToken moved to credentials block; folderUid added.
- dashboardAPI.js: registerType options pass credentials descriptor.
- src/nodeClass.js: read token from node.credentials; legacy fallback warns.
- src/specificClass.js: buildUpsertRequest emits folderUid when set.
- src/commands/handlers.js: pass folderUid from config to buildUpsertRequest.
- test/basic/slice34-credentials-and-folder.basic.test.js: 5 new tests.
Diff-based regeneration (F-1) and the explicit flows:started lifecycle hook
land in #36 once the S1 spike predicate is wired. Until then, the existing
child.register message trigger continues to drive composition on every
startup-time child registration.
Closes#34
dashboardapiConfig.json declares `logging.enabled.default: true` but:
- dashboardapi.html defaulted `enableLog: false`
- src/specificClass.js `_buildConfig` used `Boolean(...)` which
coerced undefined to false, overriding the schema default.
Aligned both to the schema: HTML default = true; _buildConfig now
uses `?? true` so an unspecified config follows the schema.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Refactor of dashboardAPI to use BaseNodeAdapter + commandRegistry + statusBadge.
dashboardAPI follows the platform refactor plan in .claude/refactor/MODULE_SPLIT.md.
Tests stay green; CONTRACT.md generated; legacy aliases preserved.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>