feat(dashboardapi): manual regen via msg.topic == regenerate-dashboard (#41)

Adds an explicit topic for operators (and the dashboardAPI v2 manual escape
hatch from PRD F-12). On `regenerate-dashboard`, dashboardAPI iterates every
child source cached by prior `child.register` messages and re-emits Grafana
upsert messages — bypassing the diff-skip predicate from #36.

- src/specificClass.js: light state cache (recordChild / cachedChildSources).
- src/commands/handlers.js: refactor shared emit path; emitDashboardsFor()
  used by both child.register and regenerateDashboard; meta.trigger
  distinguishes the two for downstream filtering.
- src/commands/index.js: register 'regenerate-dashboard' (alias 'regen').
- CONTRACT.md: document the new topic.
- test/basic/slice41-manual-regen.basic.test.js: 5 cases covering cache
  semantics, no-op for empty cache, bypass-predicate, trigger stamp on both
  paths, registry exposure.

Closes #41
This commit is contained in:
2026-05-26 18:05:31 +02:00
parent 8964b0b638
commit 3c8427ed7a
4 changed files with 163 additions and 30 deletions

View File

@@ -75,6 +75,20 @@ class DashboardApi {
this.config.general.logging.logLevel,
this.config.general.name
);
// Light state cache for manual regen (#41). Stores the latest child
// source object per child id so `regenerate-dashboard` can re-emit
// dashboards without waiting for children to re-register.
this._lastChildSources = new Map();
}
recordChild(childSource) {
const id = childSource?.config?.general?.id;
if (id) this._lastChildSources.set(id, childSource);
}
cachedChildSources() {
return Array.from(this._lastChildSources.values());
}
_templatesDir() {