one way to mint a panel id, and a registry that cannot silently lose an app

Two second implementations, both removed rather than fixed.

DashboardPreview minted template panel ids with its own module-level counter,
tpl-1, tpl-2, no entropy, reset every page load. Two dashboards built from
templates in the same page load held panels with identical ids — and a panel id
is not decorative any more: agent_panels addresses an agent by
(dashboardId, panelId), and terminal-conn-<panelId> and file-viewer:<panelId>
key persisted state by it. The templates now call the core uid(), which is
exported from the Workspace barrel for the first time so there is one minter.

metasToRegistry is Object.fromEntries, so two apps sharing a key means one app
stops existing and every panel holding its appType renders the other. The todo
asked for a throw in dev; a throw takes down every dashboard at runtime for a
mistake made at edit time, so this is a test over the real meta list plus a
console.error. All 44 keys are unique, and the test now says so rather than the
doc.

Getting the real list into a test needed test-setup.ts to provide localStorage:
MusicPlayer/useLyricsOpen.ts reads it at import time, so the whole app graph was
unimportable from a test. That unblocks testing anything that pulls in a panel
app.

Also deletes officerdev/src/useAppRegistry.ts — a stub returning {} with a
different shape from the real hook, imported by nothing.
This commit is contained in:
2026-08-07 10:38:52 +00:00
parent 3ab57a5839
commit 6fd60e59c4
9 changed files with 95 additions and 38 deletions
+3
View File
@@ -9,6 +9,9 @@ Object.assign(globalThis, {
navigator: window.navigator,
location: window.location,
history: window.history,
// Several modules read storage at import time, so this must exist before the first import, not first render.
localStorage: window.localStorage,
sessionStorage: window.sessionStorage,
HTMLElement: window.HTMLElement,
Element: window.Element,
Node: window.Node,