The four ReadDeadline(time.Now().Add(2 * time.Second)) calls in
router_integration_test.go (lines 1496, 1543, 1573, 1682) were
producing 'read tcp: i/o timeout' failures in CI under -race while
passing locally. The 2-second window is enough to read the welcome
+ initialState messages on a quiet dev workstation but too tight
once the runner is loaded with cumulative test work and the race
detector overhead. rc.5 cleared the same tests in CI but recent
fixture-size growth (k8s clusters 1->3 in 7938f28de plus the SMART
disk-temperature mock data added in 23ea4e487) pushed the
end-to-end server-start-to-welcome-message latency past the 2s
budget. Bumping to 15s gives CI breathing room without affecting
local test duration (the deadline only takes effect when the read
is genuinely stuck).
vi.resetModules() drops the module cache but the freshly-imported
sessionPresentationPolicy module-level Solid signal still starts at
its default value only in isolation. In the CI parallel test runner,
a sibling test that imports the same module path can leave the
signal in a demoMode=true state that survives across beforeEach
because the running test's loadOrganizations closure already
captured a reference to the policy module before our doMock chain
ran. When that happens, useAppRuntimeState.loadOrganizations takes
the presentationPolicyHidesOrganizationSurfaces() early-return
branch instead of the multi-tenant branch, and the three sub-tests
that assert setOrgID('default') / orgs.list() behavior count zero
calls because the mocked code path never executes.
Explicitly reset the policy via syncSessionPresentationPolicy(null)
both at the end of beforeEach (after our doMock + dynamic import
of useAppRuntimeState) and in afterEach (before vi.resetModules)
so the signal is at defaults regardless of sibling pollution.
Tests pass locally before and after; failure was reproducible only
in CI parallelism.
KubernetesCluster RBAC slices were not deep-cloned
cloneKubernetesCluster cloned Nodes, Namespaces, Pods, Deployments,
and 20+ other slices via dedicated helpers but left Roles,
ClusterRoles, RoleBindings, and ClusterRoleBindings aliased to the
source slice through the dest := src shallow copy. The final
dest.NormalizeCollections() call then iterates over those four
slices and writes c.Roles[i] = c.Roles[i].NormalizeCollections()
via index assignment, which races with any concurrent clone (or
read of the same source). The race detector caught it once the
k8s cluster count was bumped from 1 to 3 in 7938f28de, which made
the contention window wide enough to hit under -race. Fix by
deep-cloning the four RBAC slices with append([]T(nil), src...)
following the same pattern as the inline slice copies elsewhere
in cloneKubernetesCluster.
SECURITY.md sensor-wrapper alignment
The SMART/SSH feature shipped in 8769f07ee updated the shipped
public security doc at frontend-modern/public/docs/SECURITY.md to
document the new Pulse-owned /usr/local/sbin/pulse-sensors wrapper
forced-command shape for the legacy SSH temperature collection
flow, but the source SECURITY.md at the repo root still described
the prior command="sensors -j" forced command. The docsLinks
test (which compares the two for byte equality) flagged the drift.
Align root SECURITY.md and re-sync the shipped copy so both
describe the wrapper contract that the setup-script and runtime
collector now own.
The docs/MIGRATION_UNIFIED_NAV.md edit in df7934936 added the
post-rc.6 revert banner but did not refresh the shipped copy at
frontend-modern/public/docs/MIGRATION_UNIFIED_NAV.md that the
in-product docs route serves. The
src/utils/__tests__/docsLinks.test.ts 'keeps shipped docs content
synced with repo docs' assertion caught the drift in CI even
though the docs-route runtime itself was unaffected. Re-running
frontend-modern/scripts/sync-public-docs.mjs brings the shipped
copy back in line.
Two real bugs that surfaced once the 20m test timeout let the
internal/api and internal/monitoring packages run to completion.
cloneVMwareInventoryMetrics omitted four fields:
Commit 23ea4e487 (Surface vSphere VM uptime and guest disk usage)
added UptimeSeconds, DiskUsedBytes, DiskTotalBytes, and DiskPercent
to vmware.InventoryMetrics but did not extend
cloneVMwareInventoryMetrics. The clone left those pointer fields
aliased to the source struct, so the mock fixture refresh path
(refreshVMwareInventoryMetrics writing through metrics.UptimeSeconds
via ensureInt64Ptr) and the snapshot read path
(inventoryUptimeSeconds dereferencing metrics.UptimeSeconds) raced
on the same heap-allocated int64.
TestMonitorBuildBroadcastFrontendStateUsesCanonicalMockUnifiedResources
exemption:
The test asserts broadcast state does not publish the lowercase-
hyphenated legacy docker host label so canonical docker hosts
surface their human-readable DisplayName. Commit 89abed099
(2026-05-24) added the docker-swarm-node resource type whose Name
is the swarm node hostname (matching how Docker Swarm identifies
node members), which collided with the legacy-label rejection.
Refine the assertion to apply only to host-type resources
(docker-host, agent, node).
TestAgentlessAvailabilityTargetKindStaysCanonical was pinning the
former agentless-machine classification in
frontend-modern/src/features/standalone/standalonePageModel.ts
(resource.availability?.targetKind,
availabilityTargetKindFor(resource) === 'machine'). Commit 1e16cf34f
intentionally narrowed the Machines surface to Pulse Agent resources
only, removing that classification, but did not update the test. The
server-side contract for availability targetKind across
config/availability.go, monitoring/availability_poller.go, types.go,
and frontend-modern/src/api/availabilityTargets.ts is preserved and
still pinned by the same test for any future consumer.
Makefile go test timeout bumped from 10m to 20m. The rc.5 backend
test run cleared 10m with slack; the rc.6 backend test run hit 13m
in internal/api before the binary panic-killed itself. 20m gives
headroom without hiding regressions for the rc.6 release path while
the package-size growth is tracked separately.
docker-compose.yml and scripts/install-docker.sh both still pinned
rcourtman/pulse:6.0.0-rc.5. The TestDeploymentDefaultsPinVersionedImagesAndHelmDocsChecksum
/ TestRepoDockerComposeDefaultPinsCurrentVersion / TestInstallDockerScript*
tests in scripts/installtests/ read VERSION (now 6.0.0-rc.6) and
require these install entry points to match.
Drop the four deleted-page entries (Ceph, Infrastructure, Recovery,
Workloads) from REQUIRED_PAGE_HEADERS since those pages were retired
in the rc.6 IA revert.
Add PlatformSectionTabs to HEADER_PRIMITIVES. The post-rc.6
platform-shaped top-level pages (Proxmox, Docker, Kubernetes,
TrueNAS, Vmware, Standalone) use PlatformSectionTabs from
features/platformPage/sharedPlatformPage as their canonical chrome
rather than PageHeader; the audit was missing this recognition,
causing Docker/Kubernetes/Standalone/TrueNAS to fail with 'must use
at least one shared header primitive' while Proxmox and Vmware
passed only by accidentally reaching SectionHeader through their
WorkloadsSurface->WorkloadsTable->ErrorBoundary import chain.
Two cleanups left over from the rc.6 IA revert that lived as
untracked scratch in the working tree until now.
Rename infrastructureNavigation -> platformNavigation
The internal feature name infrastructureNavigation predates the rc.6
revert and assumed an Infrastructure top-level page existed. Post-
revert the frontend is platform-shaped (Proxmox / Docker / Kubernetes
/ TrueNAS / vSphere / Standalone) and the model's purpose is to gate
visibility of each *platform* nav slot from resource evidence, not
gate visibility into a unified Infrastructure surface.
- frontend-modern/src/features/infrastructureNavigation/ -> .../platformNavigation/
- buildPrimaryInfrastructureNavigationVisibility -> buildPrimaryPlatformNavigationVisibility
- PrimaryInfrastructureNavId -> PrimaryPlatformNavId
- InfrastructureNavigationVisibility -> PlatformNavigationVisibility
- PRIMARY_INFRASTRUCTURE_NAV_IDS / _SCOPE_IDS -> PRIMARY_PLATFORM_NAV_IDS / _SCOPE_IDS
- primaryInfrastructureNavigationIsVisible -> primaryPlatformNavigationIsVisible
- selectFirstVisiblePrimaryInfrastructureNavigationId -> selectFirstVisiblePrimaryPlatformNavigationId
- filterInfrastructureNavigationShortcuts -> filterPlatformNavigationShortcuts
- createEmptyInfrastructureNavigationVisibility -> createEmptyPlatformNavigationVisibility
- infrastructureNavigationVisibilityFromResources -> platformNavigationVisibilityFromResources
- buildNavigableResourceInfrastructureScopeSet -> buildNavigableResourcePlatformScopeSet
Callers updated: App.tsx, AppLayout.tsx, useKeyboardShortcuts,
commandPaletteModel, useCommandPaletteState, KeyboardShortcutsModal,
CommandPaletteModal test, App.architecture test. Local variable and
prop names (infrastructureVisibility -> platformVisibility,
infrastructureNavigationVisibility -> platformNavigationVisibility,
infrastructureNavigationResolved -> platformNavigationResolved)
renamed for consistency.
The standalone visibility key is preserved. Standalone (Machines)
is a real evidence-gated nav slot in this model: AppLayout and
commandPaletteModel both consume isVisible('standalone') to hide
the Machines nav item when no Pulse Agent resources or availability
endpoints exist.
Visual crawl spec restored at tests/integration/tests/99-visual-crawl.spec.ts
The previous version of this spec crawled the unified IA routes
(/workloads, /infrastructure, /storage, /recovery, /operations) that
were retired in the rc.6 revert. Restored with a refreshed URL list
that targets the platform-shaped top-level pages and their
representative sub-routes (Proxmox PVE/PBS/Backups/Storage/Ceph,
Kubernetes nodes/deployments/config), plus Alerts, Patrol, and the
existing Settings routes. The DOM analysis body (headings, inputs,
tables, raw-color violations, screenshots, JSON report) is
unchanged.
Stages the doc-only subset of rc.6 packet prep work on top of
df7934936. Holds VERSION bump and the registry/contract governance
reconciliation back for a focused later pass since the IA revert
created broader subsystem-contract debt than the packet prep can
absorb.
- docs/releases/V6_RC6_OPERATOR_SUPPORT_PACK_DRAFT.md: new 300-line
operator support brief mirroring the rc.5 pack with rc.6 themes:
pre-release for testing framing, platform-shaped frontend revert
explanation, vSphere as a first-class platform, Machines surface,
TrueNAS native detail UX, FilterBar adoption, Patrol capacity-
forecast and PDM bridge, free-first self-hosted posture, install.sh
smoke gate. Carries the rc.5 free-first paid-continuity wording
through unchanged so the operator-support-pack policy test holds.
- docs/releases/RELEASE_NOTES_v6_RC6_DRAFT.md,
docs/releases/V6_CHANGELOG_RC6_DRAFT.md: fill in the SHA audit
numbers (v6.0.0-rc.5..df7934936, 616 commits, 1379 files / 139185
insertions / 67870 deletions). Add the licensing-continuity
paragraph carrying the rc.5 Pulse Mobile pairing for handoff
copy through unchanged so the discovered-packet policy test holds.
- docs/RELEASE_NOTES.md: link the rc.6 draft packet as current, push
rc.5 to historical.
- docs/UPGRADE_v6.md: round out the prerelease packet pointer block
with the rc.6 operator support pack path alongside the release
notes and changelog already pointed at in df7934936.
- docs/releases/V6_PRERELEASE_RUNBOOK.md: add 6.0.0-rc.6 to the
version-examples list and bump the RC_VERSION export shown in the
RC release steps to rc.6.
Out of scope for this commit and intentionally held back until
governance reconciliation can land coherently:
- VERSION bump to 6.0.0-rc.6 (triggers deployment-installability
shape-guard which cascades into registry/contract audits against
72 dead-file references left over from the rc.6 IA revert).
- docs/release-control/v6/internal/status.json,
docs/release-control/v6/internal/subsystems/registry.json, and the
10 subsystem contract .md files that need post-IA-revert cleanup.
- scripts/release_control test fixture refreshes.
- The rc-to-ga-promotion-readiness-blocked record regen (gated on
VERSION bump landing).
Working copies of the held-back files are preserved at
/tmp/rc6-prep-backup-2026-05-27/ with a MANIFEST.md describing each.
rc.1-rc.5 shipped a unified /infrastructure /workloads /storage
/recovery top-level layout; rc.6 reverts the frontend to platform-
shaped pages (Proxmox / Docker / Kubernetes / TrueNAS / vSphere /
Standalone) on the same unified resource backend.
Updates the shipped v6 release docs to match:
- RELEASE_NOTES_v6.md and V6_CHANGELOG.md rewritten to describe the
v6 layout as platform-shaped on a unified backend, with a paragraph
in each explaining the rc.6 revert and the operator feedback that
drove it.
- UPGRADE_v6.md prerelease packet pointer bumped from rc.5 to rc.6.
- MIGRATION_UNIFIED_NAV.md gets a top-of-file revert banner that
redirects bookmarks targeting the unified routes to their platform-
shaped equivalents; the original content is preserved below as a
Historical Context section so the 19 tracked references into that
doc still resolve.
Also adds the rc.6 draft packet:
- docs/releases/RELEASE_NOTES_v6_RC6_DRAFT.md
- docs/releases/V6_CHANGELOG_RC6_DRAFT.md
Validation SHAs in both drafts are left as <populate at packet
finalisation> markers; they fill in when the release-control packet
runs.
The cleanup effects in useWorkloadUrlSync removed a URL-set
containerRuntime or kubernetesNamespace whenever the value wasn't in
the options list. Before guests load that list is empty, so the
cleanup wrongly wiped perfectly valid URL values — including those
applied by a saved view or a deep link.
Skip cleanup when the candidates list is empty. Once a non-empty list
arrives, the existence check runs as before and a value not present
in the loaded options is cleared.
The remaining edge case (runtime carried into a view that genuinely
has no runtime options, e.g. Proxmox LXC) leaves a harmless dangling
URL param; filterWorkloads only consults runtime when relevant.
The star toggle that sets a view as the default-on-landing was
opacity-0 unless the row was hovered. Users had to discover the
feature by accident.
Show the star at idle on every row: filled amber for the current
default, outline grey otherwise. Hovering a grey star tints it amber
so the intent is clear before clicking. The X (delete) stays
hover-only because it's a destructive action that should be gated by
intent; toggling default is not.
Replace the bespoke filter form (FormSelects + free-text user input +
manual chip strip) with the canonical FilterBar. The user filter
becomes the search box, the three category filters become chips, and
the page-size selector moves into the view-options trailing slot.
Wire savedViewsKey='audit' so the Saved menu attaches to this surface.
Filter state has already moved to the URL (preceding commit), so saved
views capture exactly what location.search holds.
Drops the unused clearFilterChip from the panel; FilterBar handles
chip clear inline.
Replace the staged-then-Apply audit filter form with the live-apply
model the rest of Pulse uses (Workloads, Alerts, Storage). Filter state
moves from localStorage into URL search params so the page is
shareable and ready for SavedViews.
Behavior changes:
- eventFilter, successFilter, verificationFilter, userFilter are URL
params (?event, ?success, ?verification, ?user). Default values are
omitted from the URL.
- Server-side filters (event, success) refetch the first page
immediately when changed.
- userFilter debounces refetch by 300ms so typing 'alice' doesn't
send five requests.
- verificationFilter is purely client-side and only retriggers the
filteredEvents memo.
- The Apply button is gone; clearFilters and clearFilterChip drop the
explicit refetch (the live-apply effects handle it).
Legacy localStorage values for the four filters migrate into the URL
once on first mount; pageSize, pageOffset, and the autoVerify prefs
stay in localStorage because they are page state, not view state.
Update the audit log architecture boundary test to expect the new
shape (useLocation/useNavigate, no createLocalStorageStringSignal).
Derive a platform-scoped savedViewsKey from forcedPlatform inside
useWorkloadsState (workloads-<platform-id>, e.g. workloads-proxmox-pve,
workloads-vmware-vsphere) and pipe it through WorkloadsSurface ->
WorkloadsFilter -> FilterBar. Saved views never leak across platforms
because every live consumer locks platform scope.
Only the embedded WorkloadsFilter inside WorkloadsSurface receives the
key. The shared filter toolbar mounted directly by ProxmoxPageSurface /
VmwarePageSurface is a slim scope picker for the hosts table on top of
the page; the bottom embedded filter is the fuller per-table row and
the natural home for the SavedViews menu.
Both fields are already URL-mirrored by useWorkloadUrlSync; the
usePersistentSignal wrapping was a redundant second source of truth
that broke SavedViews' default-view auto-apply.
The auto-apply path checks window.location.search === ''. With the
persistent backup, a returning user's last viewMode would seed the URL
through the state -> URL effect before SavedViews onMount ran, so the
default view never landed. Dropping the persistent wrap leaves URL as
the only source.
Legacy localStorage values (workloadsViewMode, workloadsContainerRuntime)
are migrated to URL on first mount when the URL has no matching param;
runtime migration may be dropped by the pre-existing
containerRuntimeOptions cleanup effect when options haven't loaded
yet, matching the prior persistent-signal behavior.
Move two filter-state fields out of in-memory / localStorage into
URL search params:
- search -> ?q
- statusMode -> ?status (default 'all' omitted)
The remaining filter-shaped state on the workloads surface (viewMode,
containerRuntime, scope: node/platform/context/namespace/agent) was
already URL-mirrored via useWorkloadUrlSync; only these two were
unreachable from a query string. With this commit the workloads filter
state is fully captured by location.search, which is the prerequisite
for wiring savedViewsKey on workload surfaces.
On first mount each surface migrates the legacy scoped
workloadsStatusMode[:<scope>] localStorage value into ?status if URL is
clean. Legacy key left in place; harmless once URL takes over.
Test mocks @solidjs/router so useLocation/useNavigate resolve under
createRoot.
ApprovalSection.test.tsx: the assistant briefing was refactored — title
changed from "Operator briefing attached" to "Patrol finding attached",
actionLabel was dropped (now undefined), and detailLines was reduced to
a single concatenated "Existing action artifact" line whose prior
multi-line content moved into handoffContext. Three of the five tests
asserted the old shape and failed. Update each one to assert the new
title, drop the stale detailLines/actionLabel matchers, and reassert
the semantic intent against the new handoffContext / commandSummary /
safetyNote / status string. All safety-critical "no raw command text
leaks into context" assertions are preserved.
CONFIGURATION.md: the repo source was updated with three
PULSE_ENABLE_PROXMOX_GUEST_DOCKER_* env vars and two TrueNAS rows
that never made it into the shipped public/docs copy, so docsLinks
guardrail flagged the divergence. Sync the file.
Pre-existing SECURITY.md sync mismatch (other agent's in-progress
edit) is unchanged.
Final tail of the orphan cleanup. The InteractiveSparkline component
and its state hook + model file were deleted in earlier rounds, but
two more `?raw` guardrail imports lingered:
- frontendResourceTypeBoundaries.test.ts (2)
- SharedPrimitives.guardrails.test.ts (2)
Strips them and the assertions that referenced them. Programmatic
orphan + stale-?raw sweep both return clean afterward.
TableCardHeader wrapped its entire body in a Show-when-actions gate, so
every title-only caller silently rendered nothing — Docker Images,
Docker Secrets, TrueNAS Apps/Services/Storage/Virtual Machines/Network
Shares/Health Alerts/Systems, and the Service Infrastructure dual-table
section all lost their section title. Render the title whenever it's
provided and only suppress the actions row when no actions exist. The
header bar still collapses entirely when both title and actions are
absent.
While there, fix three stale test assertions exposed by the same
sweep:
- ResourceDetailDrawer.identity-runtime: expected the host detail
disclosure to say "Host" / "Show host", but Pulse-agent resources
now use "Machine" / "Show machine".
- settingsArchitecture: matched the old zero-arg signature for
buildAvailabilityTargetAddPath, which now takes an optional
targetKind parameter.
- UnifiedResourceTable.performance.contract: the grouped Profile S
render reliably brushed the 5s default waitFor timeout; bump to the
same 15s the neighbouring row-windowing contracts use, plus a 30s
test-level timeout, so it stops flaking under load.
Three frontend tests asserted against shapes the runtime no longer
produces:
- proxmoxHostTableModel.test.ts expected uptime before the CPU/Memory/
Disk bar block on compact layouts. Commit 300af4312 ("Move Uptime
after the bar block in platform top tables") canonicalized uptime to
sit after the diagnostic Temp column, but the test wasn't updated.
- platformOverviewLayout.guardrails.test.ts asserted that
AgentsMachinesTable's source contained literal "Machine"/"CPU"/etc
next to getPlatformTableHeadClassForKind calls. AgentsMachinesTable
now uses a column-config pattern where labels live in
agentMachineTableModel.ts; redirect the assertions to the model file
so they continue to enforce kind/label alignment.
- useStoragePoolDetailModel.test.ts expected the linkedDisks shape with
five fields. The model now also exposes errorCount, ioLabel, role,
sizeLabel, spunDown, and state. Update the expectation to include
them.
After the orphan-source ?raw imports were stripped from these guardrail
tests in earlier cleanups, the it() blocks that exercised those
primitives ended up with no assertions. Removing the husks:
SharedPrimitives.guardrails.test.ts:
- keeps scroll-to-top button on shell, runtime, and model owners
- keeps infrastructure summary table on shell, runtime, and model owners
- keeps infrastructure selector on shell, runtime, and model owners
- keeps density map on shell, runtime, and model owners
- keeps infrastructure details drawer on shell, runtime, and model
owners
- keeps sticky summary breakpoint behavior on the shared primitive
- keeps collapsible search input on shell, runtime, and model owners
UnifiedResourceTable.performance.contract.test.tsx:
- keeps infrastructure summary fetch runtime out of the render shell
Last leaf. utils/timeRange.ts exported `timeRangeToMs` with no live
consumer; only its own test referenced it. Drops the helper + its
direct test + the time-range conversion describe block from
charts.test.ts that exercised it through the API layer.
Final leaf — these two files were only consumed by InteractiveSparkline.tsx
which was deleted in Cleanup N. Nothing else imports them.
- components/shared/useInteractiveSparklineState.ts
- components/shared/interactiveSparklineModel.ts
Baseline 10 pre-existing failures unchanged.
Last leaves after Cleanup L+M:
- api/agentDeploy.ts and types/agentDeploy.ts — agent-deploy API client
+ types, only ever consumed by the deleted deploy wizard hooks/
components.
- components/shared/InteractiveSparkline.tsx + test — chart primitive
only rendered by the deleted summary surfaces.
Strips the remaining stale ?raw guardrail imports + assertions from
apiErrorStatus.guardrails.test.ts, SharedPrimitives.guardrails.test.ts,
and frontendResourceTypeBoundaries.test.ts for every file deleted in
the recent rounds (collapsibleSearchInputModel, densityMapModel,
scrollToTopButtonModel, useCollapsibleSearchInputState,
useDensityMapState, useScrollToTopButtonState,
infrastructureDetailsDrawerModel, useInfrastructureDetailsDrawerState,
MonitoredSystemDefinitionDisclosure, InteractiveSparkline,
useDiskLiveMetricModel, useZFSHealthMapModel, MailGateway,
PMGInstancePanel, ServiceHealthBadge, pmgPresentation,
pmgThreatPresentation, pmgQueuePresentation, deployStatusPresentation,
deployFlowPresentation, DeployStatusBadge, diskLiveMetricPresentation,
zfsHealthMapPresentation, recoveryIssuePresentation, hostedSignup).
Iterative pass — deleting Cleanup L's parents revealed these as the
new leaves with no consumer. Same verification (static-import grep
+ JSX grep + lazy-import scan) before each removal.
Storage feature utils:
- features/storageBackups/zfsHealthMapPresentation.ts + test
- features/storageBackups/diskLiveMetricPresentation.ts + test
Stores:
- stores/diskMetricsHistory.ts + test (only ever fed the deleted
metricsCollector)
PMG (sibling of deleted PMGInstancePanel / MailGateway / ServiceHealthBadge):
- utils/pmgPresentation.ts + test
- utils/pmgQueuePresentation.ts + test
- utils/pmgThreatPresentation.ts + test
- components/PMG/ServiceHealthBadge.tsx
Deploy wizard tail:
- utils/deployStatusPresentation.ts + test
- hooks/useDeployStream.ts + test
Hosted-signup tail:
- api/hostedSignup.ts + test
Shared component models orphaned with their parents:
- components/shared/collapsibleSearchInputModel.ts
- components/shared/scrollToTopButtonModel.ts
- components/shared/densityMapModel.ts
Baseline 10 pre-existing test failures still flat.
Twelfth cleanup round. The Explore audit surfaced a further batch of
files with zero non-test consumers. Each was verified by static-import
grep + JSX-usage grep + lazy-import scan before deletion.
Pages (defined but never wired into App.tsx routing):
- pages/HostedSignup.tsx + test
- pages/CloudPricing.tsx + test
Stores (re-export wrapper + dead utility):
- stores/demoMode.ts (re-export shim around sessionPresentationPolicy)
- stores/metricsCollector.ts + test (retired with the live-metrics
collector decision — App.architecture.test.ts still enforces that
App.tsx must not re-import it)
Hooks / state:
- hooks/useDeployWizard.ts + test (consumed only by deleted deploy
wizard steps in Cleanup K)
- components/shared/useInfrastructureDetailsDrawerState.ts and
infrastructureDetailsDrawerModel.ts (only consumed by the deleted
InfrastructureDetailsDrawer)
- components/shared/useCollapsibleSearchInputState.ts,
useDensityMapState.ts, useScrollToTopButtonState.ts (model files
for shared components deleted in Cleanup K)
- components/Storage/useZFSHealthMapModel.ts + test,
useDiskLiveMetricModel.ts + test (models for Storage components
deleted in Cleanup K)
Shared primitives:
- components/shared/PageControls.tsx + test + guardrails test —
the legacy filter UI fully replaced by FilterBar across every
surface; no consumer remains
- components/shared/responsive/ResponsiveHeader.tsx and
useGridTemplate.ts (no consumer)
Other components:
- components/PMG/PMGInstancePanel.tsx and MailGateway.tsx (PMG
surface superseded by ProxmoxMailGatewayDrawer in the inline-drawer
unification)
- components/Commercial/MonitoredSystemDefinitionDisclosure.tsx + test
(only used by the deleted MonitoredSystemLedgerPanel)
- components/Infrastructure/deploy/ErrorDetail.tsx + test and
DeployStatusBadge.tsx + test (deploy wizard step helpers)
Utils:
- utils/deployFlowPresentation.ts + test (deploy wizard presentation)
- utils/recoveryLocationPresentation.ts + test,
recoveryIssuePresentation.ts + test (Recovery surface utils)
- utils/snooze.ts (no consumer)
Updates useAppRuntimeState.test.ts to import demo-mode helpers
directly from sessionPresentationPolicy now that the demoMode wrapper
is gone.
Eleventh round of orphan deletion. The platform-first IA migration
left many UI components and presentation utilities behind whose only
consumers were already-deleted aggregate surfaces, deploy wizard, or
recovery pages.
Storage:
- ZFSHealthMap.tsx — diagnostic indicator only used by the deleted
Storage standalone summary
- DiskLiveMetric.tsx — live metric bar only used by deleted summary
- storageSourceOptions.ts + test — options helper for deleted controls
Infrastructure:
- resourceBadges.ts + test — badge helpers only used by deleted
ConfiguredNodeTables / MonitoredSystemLedgerPanel
- deploy/CandidatesStep, ConfirmStep, DeployingStep, PreflightStep,
ResultsStep + their tests — the deploy wizard retired with
AgentDeployModal
Shared:
- DensityMap, SparklineSkeleton, InfrastructureDetailsDrawer (and
tests) — primitives only consumed by deleted summary chrome
- CollapsibleSearchInput.tsx — collapsing search variant with no
current consumer
- ScrollToTopButton.tsx + test — only used by deleted WorkloadsSurface
chrome
Utils:
- clusterEndpointPresentation, recoveryTablePresentation,
configuredNodeCapabilityPresentation, configuredNodeStatusPresentation
(with tests) — all consumed only by deleted surfaces
Hooks:
- useRecoveryPointsSeries / useRecoveryPointsFacets /
useRecoveryRollups — recovery hooks for the retired aggregate surface
- useDebouncedValue + test — generic debounce with no consumer
Test files:
- DeployStepComponents.test.tsx — entire file tested deleted wizard
- SearchInput.test.tsx — dropped 3 tests that exercised
CollapsibleSearchInput plus the now-unused focusActiveTypeToSearch
import
Strips ?raw guardrail imports + assertions for every deleted file from
SharedPrimitives.guardrails and frontendResourceTypeBoundaries.
Final tail of the platform-first IA cleanup. These shared summary
primitives were rendered by the deleted aggregate summary surfaces
(InfrastructureSummary, WorkloadsSummary, StoragePageSummary) and have
no remaining consumers post-cleanup:
- components/shared/SummaryJumpToRowButton.tsx — the "jump to active
row" affordance that surfaced in the dead summary chrome
- components/shared/SummaryMetricCard.tsx — metric-card primitive used
by the deleted summary chrome
- components/shared/SummarySynchronizedReadout.tsx — chart/value
readout used by the deleted summary chart cards
Strips the remaining `?raw` guardrail imports + assertions for these
sources from SharedPrimitives.guardrails.test.ts.
Tail of the post-IA-migration cleanup. The Ceph summary card stack and
the storage status-banner helpers were only ever rendered by the
deleted Storage standalone summary section + banners surface.
Deletes:
- components/Storage/StorageCephSummaryCard.tsx (+ model + test)
- components/Storage/useStorageCephSummaryCardModel.ts
- features/storageBackups/cephSummaryCardPresentation.ts (+ test)
Drops the now-dead exports from features/storageBackups/storagePagePresentation.ts:
- StoragePageBannerKind type
- STORAGE_BANNER_ACTION_BUTTON_CLASS / STORAGE_PAGE_BANNER_ROW_CLASS /
STORAGE_PAGE_BANNER_TEXT_CLASS
- shouldShowCephSummaryCard / getCephSummaryClusterCountLabel /
getCephSummaryHeading / getCephSummaryTotalLabel /
getCephSummaryUsageLabel / getCephClusterCardTitle
- getStoragePageBannerMessage / getStoragePageBannerActionLabel
- Unused imports of formatBytes/formatPercent/StorageRecord/CephSummaryStats
Drops getStoragePageBannerKind + StoragePageBannerStateInput from
features/storageBackups/storagePageStatus.ts; isStoragePoolLoading
remains for the live loading indicator.
Tightens useStoragePageStatus to just return isLoadingPools (drops
hasFetchError + activeBannerKind + their inputs). useStoragePageModel
no longer destructures activeBannerKind and stops passing reconnecting,
error, connected, initialDataReceived through.
Tightens the StoragePageControls prop comment (was still referencing
WorkloadsFilter contract by name and "standalone /storage" which no
longer exists).
Rewrites storagePagePresentation / storagePageStatus / useStoragePageStatus
tests to cover just the surviving behavior. Strips remaining stale ?raw
imports of the deleted SummaryPanel / MigrationNoticeBanner / AgentDeployModal
/ storageSummaryTrendCache / StorageCephSummaryCard /
useStorageCephSummaryCardModel / cephSummaryCardPresentation sources
from frontendResourceTypeBoundaries + SharedPrimitives guardrails.