Follow-up to #53 (layout work). Reported after visual review: node rectangle size varies inconsistently, including between two nodes of the identical role (e.g. campus-leaf1 vs campus-leaf2).
Observation from live dashboard data
No node has an explicit size field (width/height) — every node shares identical padding: {horizontal:12, vertical:6}. Rendered size is therefore computed by the plugin, not stored. Working hypothesis: it scales with anchors[<side>].numLinks (link count per side) combined with useConstantSpacing: false / compactVerticalLinks: false, both currently false on every generated node.
Supporting evidence: campus-leaf1 (3 total links) and campus-leaf2 (4 total links) render at different sizes despite being the same device role — link count, not role, appears to drive size.
Task: confirm root cause against real plugin source, don't assume
Same caution as #48 (where the documented schema turned out to differ from the actually-installed tamirsuliman-weathermap-panel fork — anchors handling was a real surprise, not theoretical). Before changing anything:
Pull the real module.js (or source, if buildable) from the installed plugin and confirm what actually drives node width/height at render time — useConstantSpacing, compactVerticalLinks, anchors[*].numLinks, or something else entirely
Confirm whether there IS an explicit size override field the fork supports that isn't in the schema doc from #48 (worth a specific grep, given the fork has already diverged from documented schema once)
Fix — consistent sizing per role tier
Once confirmed, make node size deterministic and consistent by role (all leafs same size, all spines same size, etc.), decoupled from link count:
If useConstantSpacing: true achieves this cleanly, set it uniformly on generation
If an explicit size field exists in the real plugin, set it explicitly per role instead of relying on auto-sizing
Role tiers to use: same classification as #53's layout work (spine / core / border-leaf / leaf / access) — reuse that parsing, don't reimplement
Validation
Regenerate, confirm every node of the same role renders at the same size regardless of link count (spot-check campus-leaf1 vs campus-leaf2 specifically, since that's the reported case)
Confirm this doesn't break the live-position-preservation logic from #53 — size and position are independent fields, changing size defaults shouldn't touch position
Visual check in Grafana UI (still no image-renderer / browser access on the agent side — flag if still true, ask for a human look)
Document
What actually controls size in the installed plugin (ground truth, not the schema doc's guess)
Final size values chosen per role tier, and why
Follow-up to #53 (layout work). Reported after visual review: node rectangle size varies inconsistently, including between two nodes of the identical role (e.g. `campus-leaf1` vs `campus-leaf2`).
## Observation from live dashboard data
No node has an explicit size field (`width`/`height`) — every node shares identical `padding: {horizontal:12, vertical:6}`. Rendered size is therefore computed by the plugin, not stored. Working hypothesis: it scales with `anchors[<side>].numLinks` (link count per side) combined with `useConstantSpacing: false` / `compactVerticalLinks: false`, both currently `false` on every generated node.
Supporting evidence: `campus-leaf1` (3 total links) and `campus-leaf2` (4 total links) render at different sizes despite being the same device role — link count, not role, appears to drive size.
## Task: confirm root cause against real plugin source, don't assume
Same caution as #48 (where the documented schema turned out to differ from the actually-installed `tamirsuliman-weathermap-panel` fork — `anchors` handling was a real surprise, not theoretical). Before changing anything:
1. Pull the real `module.js` (or source, if buildable) from the installed plugin and confirm what actually drives node width/height at render time — `useConstantSpacing`, `compactVerticalLinks`, `anchors[*].numLinks`, or something else entirely
2. Confirm whether there IS an explicit size override field the fork supports that isn't in the schema doc from #48 (worth a specific grep, given the fork has already diverged from documented schema once)
## Fix — consistent sizing per role tier
Once confirmed, make node size deterministic and consistent by role (all leafs same size, all spines same size, etc.), decoupled from link count:
- If `useConstantSpacing: true` achieves this cleanly, set it uniformly on generation
- If an explicit size field exists in the real plugin, set it explicitly per role instead of relying on auto-sizing
- Role tiers to use: same classification as #53's layout work (spine / core / border-leaf / leaf / access) — reuse that parsing, don't reimplement
## Validation
- Regenerate, confirm every node of the same role renders at the same size regardless of link count (spot-check `campus-leaf1` vs `campus-leaf2` specifically, since that's the reported case)
- Confirm this doesn't break the live-position-preservation logic from #53 — size and position are independent fields, changing size defaults shouldn't touch `position`
- Visual check in Grafana UI (still no image-renderer / browser access on the agent side — flag if still true, ask for a human look)
## Document
- What actually controls size in the installed plugin (ground truth, not the schema doc's guess)
- Final size values chosen per role tier, and why
Root cause (confirmed against the real plugin, not the #48 doc)
Pulled the actual bundle from the installed plugin ($GRAFANA_URL/public/plugins/tamirsuliman-weathermap-panel/module.js, ~177KB minified) rather than trusting the #48 schema research, per the issue's own caution. Found the two functions that compute the rendered rectangle dimensions directly (z() = width, L() = height, both fed straight into the SVG rect via useMemo):
Width (z()): label_width + 2*padding.horizontal when useConstantSpacing is false (our current/unchanged setting) — label_width itself is always recomputed fresh from the actual label text via canvas.measureText() at render time (i.labelWidth = I(i.label, fontSize).width inside the node-normalization function). There is no explicit width override field anywhere in the schema — nothing we set in JSON for width would ever be read. useConstantSpacing: true would only pull in a term based on Top/Bottom anchor link count, which this generator never populates (links always attach Right/Left, per the existing anchor_counts comment) — so it's a dead lever for our topology either way, width is purely a function of label string length + font. This confirms width was never actually the bug: campus-leaf1/campus-leaf2 have identical-length labels, so their widths were already identical.
Height (L()) — the actual bug: max(anchors[Left].numLinks, anchors[Right].numLinks) directly scales a link-stack height term, and return !compactVerticalLinks && c > s ? c : s means that term wins over the constant font-based height s whenever compactVerticalLinks is false (the value every node had, generated by #48/#52/#53) and the link-count term is larger. campus-leaf1 (3 links) vs campus-leaf2 (4 links) is exactly max(anchors[Left], anchors[Right]) differing → different c → different rendered height. Confirmed by reading the numLinks/numFilledLinks accounting in the bundle, not by inference.
So the issue's own hypothesis named the wrong flag (useConstantSpacing) for the actual defect — compactVerticalLinks is the real lever, and it fully explains the reported symptom.
Fix
compactVerticalLinks: True on every node (was False). Per the confirmed formula this makes height an unconditional constant — fontSize + 2*padding.vertical — for every node, since padding and fontSize are already uniform fabric-wide (no per-node override exists in the generator). This isn't just "consistent per role tier" as asked, it's consistent across every node regardless of role, which satisfies the requirement without needing per-role values (there's nothing to differentiate by, since the plugin gives us no size field to key off role in the first place — only this one boolean).
useConstantSpacing left false (unchanged) — confirmed it has no bearing on this bug given our anchor usage pattern, so touching it would be a no-op dressed up as a fix.
Validation
Diffed the full merged output against the previous commit, isolated to exactly the fields that changed across all 28 nodes: {'position', 'compactVerticalLinks'}. No other field (statusQuery, anchors, colors, padding, label, etc.) touched.
position: unrelated drift, not from this change — the live Grafana dashboard had already moved between the #53 and #54 sessions (x roughly preserved per node, y snapped into a few discrete bands — looks like the plugin's own auto-arrange, likely from the manual UI pass requested at the end of #53). This is exactly #53's live-position-preservation mechanism doing its job correctly: whatever was live got carried over untouched by this run, regardless of source. Confirms size and position stayed fully independent, as required.
campus-leaf1/campus-leaf2 spot-check: both now have compactVerticalLinks: true, identical padding, no fontSize override → guaranteed identical rendered height by the confirmed formula, regardless of their differing per-side link counts (max(1,3)=3 vs max(2,2)=2).
Provisioned to Grafana.
Outstanding
Still no image-renderer plugin / browser access on my end — I can't screenshot the result. Please do a visual pass to confirm the rectangles actually look uniform now; the source-level analysis is solid but a render-level confirmation from a human is still the right final check here, same caveat as #49/#52/#53.
Implemented in `9b53ab0` (branch `feat/telemetry`).
## Root cause (confirmed against the real plugin, not the #48 doc)
Pulled the actual bundle from the installed plugin (`$GRAFANA_URL/public/plugins/tamirsuliman-weathermap-panel/module.js`, ~177KB minified) rather than trusting the #48 schema research, per the issue's own caution. Found the two functions that compute the rendered rectangle dimensions directly (`z()` = width, `L()` = height, both fed straight into the SVG rect via `useMemo`):
**Width (`z()`)**: `label_width + 2*padding.horizontal` when `useConstantSpacing` is false (our current/unchanged setting) — `label_width` itself is **always recomputed fresh from the actual label text** via `canvas.measureText()` at render time (`i.labelWidth = I(i.label, fontSize).width` inside the node-normalization function). There is **no explicit width override field** anywhere in the schema — nothing we set in JSON for width would ever be read. `useConstantSpacing: true` would only pull in a term based on `Top`/`Bottom` anchor link count, which this generator never populates (links always attach `Right`/`Left`, per the existing `anchor_counts` comment) — so it's a dead lever for our topology either way, width is purely a function of label string length + font. This confirms width was never actually the bug: `campus-leaf1`/`campus-leaf2` have identical-length labels, so their widths were already identical.
**Height (`L()`)** — the actual bug: `max(anchors[Left].numLinks, anchors[Right].numLinks)` directly scales a link-stack height term, and `return !compactVerticalLinks && c > s ? c : s` means that term wins over the constant font-based height `s` whenever `compactVerticalLinks` is `false` (the value every node had, generated by #48/#52/#53) and the link-count term is larger. `campus-leaf1` (3 links) vs `campus-leaf2` (4 links) is exactly `max(anchors[Left], anchors[Right])` differing → different `c` → different rendered height. Confirmed by reading the `numLinks`/`numFilledLinks` accounting in the bundle, not by inference.
So the issue's own hypothesis named the wrong flag (`useConstantSpacing`) for the actual defect — `compactVerticalLinks` is the real lever, and it fully explains the reported symptom.
## Fix
`compactVerticalLinks: True` on every node (was `False`). Per the confirmed formula this makes height an unconditional constant — `fontSize + 2*padding.vertical` — for every node, since `padding` and `fontSize` are already uniform fabric-wide (no per-node override exists in the generator). This isn't just "consistent per role tier" as asked, it's consistent across *every* node regardless of role, which satisfies the requirement without needing per-role values (there's nothing to differentiate by, since the plugin gives us no size field to key off role in the first place — only this one boolean).
`useConstantSpacing` left `false` (unchanged) — confirmed it has no bearing on this bug given our anchor usage pattern, so touching it would be a no-op dressed up as a fix.
## Validation
- Diffed the full merged output against the previous commit, isolated to exactly the fields that changed across all 28 nodes: `{'position', 'compactVerticalLinks'}`. No other field (`statusQuery`, `anchors`, `colors`, `padding`, `label`, etc.) touched.
- `position`: unrelated drift, not from this change — the live Grafana dashboard had already moved between the #53 and #54 sessions (x roughly preserved per node, y snapped into a few discrete bands — looks like the plugin's own auto-arrange, likely from the manual UI pass requested at the end of #53). This is exactly #53's live-position-preservation mechanism doing its job correctly: whatever was live got carried over untouched by this run, regardless of source. Confirms size and position stayed fully independent, as required.
- `campus-leaf1`/`campus-leaf2` spot-check: both now have `compactVerticalLinks: true`, identical `padding`, no `fontSize` override → guaranteed identical rendered height by the confirmed formula, regardless of their differing per-side link counts (`max(1,3)=3` vs `max(2,2)=2`).
- Provisioned to Grafana.
## Outstanding
Still no image-renderer plugin / browser access on my end — I can't screenshot the result. Please do a visual pass to confirm the rectangles actually look uniform now; the source-level analysis is solid but a render-level confirmation from a human is still the right final check here, same caveat as #49/#52/#53.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Follow-up to #53 (layout work). Reported after visual review: node rectangle size varies inconsistently, including between two nodes of the identical role (e.g.
campus-leaf1vscampus-leaf2).Observation from live dashboard data
No node has an explicit size field (
width/height) — every node shares identicalpadding: {horizontal:12, vertical:6}. Rendered size is therefore computed by the plugin, not stored. Working hypothesis: it scales withanchors[<side>].numLinks(link count per side) combined withuseConstantSpacing: false/compactVerticalLinks: false, both currentlyfalseon every generated node.Supporting evidence:
campus-leaf1(3 total links) andcampus-leaf2(4 total links) render at different sizes despite being the same device role — link count, not role, appears to drive size.Task: confirm root cause against real plugin source, don't assume
Same caution as #48 (where the documented schema turned out to differ from the actually-installed
tamirsuliman-weathermap-panelfork —anchorshandling was a real surprise, not theoretical). Before changing anything:module.js(or source, if buildable) from the installed plugin and confirm what actually drives node width/height at render time —useConstantSpacing,compactVerticalLinks,anchors[*].numLinks, or something else entirelyFix — consistent sizing per role tier
Once confirmed, make node size deterministic and consistent by role (all leafs same size, all spines same size, etc.), decoupled from link count:
useConstantSpacing: trueachieves this cleanly, set it uniformly on generationValidation
campus-leaf1vscampus-leaf2specifically, since that's the reported case)positionDocument
Implemented in
9b53ab0(branchfeat/telemetry).Root cause (confirmed against the real plugin, not the #48 doc)
Pulled the actual bundle from the installed plugin (
$GRAFANA_URL/public/plugins/tamirsuliman-weathermap-panel/module.js, ~177KB minified) rather than trusting the #48 schema research, per the issue's own caution. Found the two functions that compute the rendered rectangle dimensions directly (z()= width,L()= height, both fed straight into the SVG rect viauseMemo):Width (
z()):label_width + 2*padding.horizontalwhenuseConstantSpacingis false (our current/unchanged setting) —label_widthitself is always recomputed fresh from the actual label text viacanvas.measureText()at render time (i.labelWidth = I(i.label, fontSize).widthinside the node-normalization function). There is no explicit width override field anywhere in the schema — nothing we set in JSON for width would ever be read.useConstantSpacing: truewould only pull in a term based onTop/Bottomanchor link count, which this generator never populates (links always attachRight/Left, per the existinganchor_countscomment) — so it's a dead lever for our topology either way, width is purely a function of label string length + font. This confirms width was never actually the bug:campus-leaf1/campus-leaf2have identical-length labels, so their widths were already identical.Height (
L()) — the actual bug:max(anchors[Left].numLinks, anchors[Right].numLinks)directly scales a link-stack height term, andreturn !compactVerticalLinks && c > s ? c : smeans that term wins over the constant font-based heightswhenevercompactVerticalLinksisfalse(the value every node had, generated by #48/#52/#53) and the link-count term is larger.campus-leaf1(3 links) vscampus-leaf2(4 links) is exactlymax(anchors[Left], anchors[Right])differing → differentc→ different rendered height. Confirmed by reading thenumLinks/numFilledLinksaccounting in the bundle, not by inference.So the issue's own hypothesis named the wrong flag (
useConstantSpacing) for the actual defect —compactVerticalLinksis the real lever, and it fully explains the reported symptom.Fix
compactVerticalLinks: Trueon every node (wasFalse). Per the confirmed formula this makes height an unconditional constant —fontSize + 2*padding.vertical— for every node, sincepaddingandfontSizeare already uniform fabric-wide (no per-node override exists in the generator). This isn't just "consistent per role tier" as asked, it's consistent across every node regardless of role, which satisfies the requirement without needing per-role values (there's nothing to differentiate by, since the plugin gives us no size field to key off role in the first place — only this one boolean).useConstantSpacingleftfalse(unchanged) — confirmed it has no bearing on this bug given our anchor usage pattern, so touching it would be a no-op dressed up as a fix.Validation
{'position', 'compactVerticalLinks'}. No other field (statusQuery,anchors,colors,padding,label, etc.) touched.position: unrelated drift, not from this change — the live Grafana dashboard had already moved between the #53 and #54 sessions (x roughly preserved per node, y snapped into a few discrete bands — looks like the plugin's own auto-arrange, likely from the manual UI pass requested at the end of #53). This is exactly #53's live-position-preservation mechanism doing its job correctly: whatever was live got carried over untouched by this run, regardless of source. Confirms size and position stayed fully independent, as required.campus-leaf1/campus-leaf2spot-check: both now havecompactVerticalLinks: true, identicalpadding, nofontSizeoverride → guaranteed identical rendered height by the confirmed formula, regardless of their differing per-side link counts (max(1,3)=3vsmax(2,2)=2).Outstanding
Still no image-renderer plugin / browser access on my end — I can't screenshot the result. Please do a visual pass to confirm the rectangles actually look uniform now; the source-level analysis is solid but a render-level confirmation from a human is still the right final check here, same caveat as #49/#52/#53.