Commit graph

6227 commits

Author SHA1 Message Date
rcourtman
f81490ca4f Keep discovery manual refresh visible 2026-05-15 23:55:22 +01:00
rcourtman
b0c4faa4a0 frontend(platforms): drop platform sub-tabs whose canonical projection is missing
Audit pass against the live mock backend (PULSE_MOCK_MODE=true) revealed
three platform sub-tabs that could never populate from canonical
resources today, even with a mature fixture environment:

- Docker > Swarm services: no `docker-service` resource is emitted by
  the unified resource adapter at the /api/resources boundary.
- Kubernetes > Services: no `k8s-service` resource type is defined in
  internal/unifiedresources; only k8s-cluster, k8s-node, pod, and
  k8s-deployment are projected.
- TrueNAS > Hosts: TrueNAS connections produce storage, datasets,
  physical disks, and app-containers but no top-level `agent` row
  tagged with the `truenas` platform.

Per the platform-pages goal ("if a platform lacks enough canonical data
model support to make a useful page even after fixture work, do not
invent speculative UI — report the data-model gap and skip or gate
that surface deliberately"), the three sub-tabs are removed from the
page navigation and the resource queries are tightened to drop the
unused types. TrueNAS now defaults to /truenas/storage as the first
canonical operator entry point.

Kubernetes Nodes now also includes agent rows whose `sources` array
reports `kubernetes`, because the backend registry merges Pulse-Agent-
linked Kubernetes nodes onto the linked agent row. The merged agents
are the canonical projection of K8s nodes when an agent is installed
on them; treating them as Nodes makes the tab populate against mock
mode and live agent fleets alike.

Browser verification (Playwright, chromium, against live mock-mode
Pulse dev runtime):
- 8 tests, all pass. Every declared platform sub-tab now asserts at
  least one canonical row populates under mock mode:
  - docker: /docker/overview (2 hosts), /docker/containers
  - kubernetes: /kubernetes/overview (1 cluster),
    /kubernetes/nodes (3 merged agents), /kubernetes/pods (10),
    /kubernetes/deployments (4)
  - truenas: /truenas/storage (9), /truenas/apps (5)
  - vmware: /vmware/overview (4 ESXi hosts), /vmware/vms (8),
    /vmware/storage (datastores)

Targeted tests:
- dockerPageModel, kubernetesPageModel, truenasPageModel suites
  updated and passing.
- resourceLinks.test.ts asserts the new TrueNAS default sub-tab.

Contracts updated:
- unified-resources.md Extension Points: platform default sub-tab must
  land on a canonical surface that actually populates.
- storage-recovery.md Shared Boundaries: same; calls out TrueNAS
  defaulting to /truenas/storage today.

Remaining canonical data-model gaps (intentionally not surfaced as
empty platform sub-tabs in the UI):
- internal/unifiedresources does not emit `docker-service` resources
  even though mock.generateDockerServicesAndTasks() generates them in
  the StateSnapshot; revisit when adding a docker-service projection.
- internal/unifiedresources does not define ResourceTypeK8sService;
  revisit when k8s-service rows are added to the canonical model.
- internal/unifiedresources does not project a top-level TrueNAS
  system as an `agent` row; revisit when the TrueNAS adapter promotes
  the connection target into a canonical infrastructure row.
2026-05-15 23:49:23 +01:00
rcourtman
cfc3fd1606 frontend(platforms): resolve resource platform family via sources fallback
The unified resource projection returned by /api/resources leaves
`platformType` empty on several canonical resource types (storage,
agent, pbs, app-container, vm, k8s-deployment, pod, etc.) under the
mock fixture path and parts of the live backend. Platform-first pages
were filtering on `resource.platformType` directly, so Docker /
Kubernetes / TrueNAS / vSphere pages rendered empty under mock mode
even though the resources existed and were tagged with the right
`sources` array (['docker'], ['kubernetes'], ['truenas'], ['vmware']).

Introduce `resolveResourcePlatformType(resource)` in
`frontend-modern/src/utils/sourcePlatforms.ts` as the canonical reader
for "what platform family does this unified resource belong to". It
prefers `resource.platformType` when present and falls back to the
resource's `sources` array via the existing
`resolvePlatformTypeFromSources` normalization, so client-side family
grouping behaves identically against mock fixtures and live backends.

Each platform page model now buckets resources through that helper:
- dockerPageModel.ts
- kubernetesPageModel.ts
- truenasPageModel.ts
- vmwarePageModel.ts

Browser verification (Playwright, chromium, against live mock-mode
Pulse dev runtime):
- 4 no-data tests (stubbed empty /api/resources): all 4 pages render
  sub-tab chrome and surface empty state.
- 4 populated tests (live mock backend): each platform asserts at
  least one canonical row renders on its data-bearing sub-tabs:
  - docker: /docker/overview (Hosts), /docker/containers
  - kubernetes: /kubernetes/pods, /kubernetes/deployments
  - truenas: /truenas/storage
  - vmware: /vmware/vms, /vmware/storage
  All 8 tests pass.

Verification artifacts staged:
- sourcePlatforms.test.ts extended with resolveResourcePlatformType
  cases (19 tests pass).
- 68-platform-pages-shell.spec.ts extended with populated-state
  assertions per platform.

Contracts updated:
- unified-resources.md Shared Boundaries: resolveResourcePlatformType
  is the canonical reader for unified-resource platform family.
- frontend-primitives.md Extension Points: same.

Remaining mock fixture gaps (intentionally not asserted populated in
this commit; tracked for fixture extension):
- docker/services: default mock fixtures do not expose docker-service
  resources at the /api/resources boundary.
- kubernetes/overview, kubernetes/nodes, kubernetes/services:
  KubernetesClusters are generated but k8s-cluster, k8s-node, and
  k8s-service resource projections are not surfaced.
- truenas/overview, truenas/apps: no TrueNAS agent or TrueNAS-scoped
  app-container resources in default fixtures.
- vmware/overview: no VMware ESXi-host agent resources in default
  fixtures.
2026-05-15 23:38:40 +01:00
rcourtman
976e7c6b42 Add settings discovery refresh action
- expose a manual discovery sweep API

- wire Assistant & Patrol settings to run new, changed, and stale workload refreshes
2026-05-15 23:27:08 +01:00
rcourtman
2fbeb14541 frontend(platforms): make primary nav platform-first; demote infra/workloads/storage/recovery
Complete the platform-first navigation shift started in cdaeb3b84.
Primary navigation now enumerates exactly the supported platform
families (Proxmox, Docker, Kubernetes, TrueNAS, vSphere) and removes
Infrastructure, Workloads, Storage, and Recovery as equal top-level
tabs. Their tables continue to render inside each platform page via
the embedded tableOnly canonical surfaces; their routes remain wired
in App.tsx for deep-link compatibility, but they are not duplicated
in primary nav.

First-run UX decision: all supported platform tabs are alwaysShow:true
so first-run operators can discover what Pulse monitors. Unconnected
platforms render in a disabled tone (enabled/live derive from
canonical resource presence in state.resources), and the empty-state
inside the platform page itself surfaces the setup affordance. This
favors discoverability over hiding-until-connected, and is the
canonical decision recorded in the contract delta below.

Routing follow-up:
- routePreload.ts adds ROUTE_PRELOADERS entries for Docker, Kubernetes,
  TrueNAS, and vSphere so platform navigation stays warm on first paint.
- mobileNavBarModel.ts MOBILE_NAV_PLATFORM_PRIORITY mirrors the new
  platform-first primary set; legacy entries are removed.

Contracts updated:
- cloud-paid.md: records the platform-first primary-nav decision and
  the alwaysShow + presence-derived enabled/live contract; explicitly
  forbids reintroducing infra/workloads/storage/recovery as equal
  primary tabs without a governed contract decision.
- frontend-primitives.md: PlatformTab and MOBILE_NAV_PLATFORM_PRIORITY
  must mirror the supported-platform set; legacy entries intentionally
  absent.
- performance-and-scalability.md: every supported platform must be in
  the app-shell route preload registry; presentation-only platforms
  must not be registered.
- ai-runtime.md: demotion does not affect Patrol or Assistant
  addressability; platform pages must not replicate Patrol findings,
  Assistant prompts, or AI launcher affordances inside their chrome.

Verification:
- App.architecture.test.ts extended to assert the platform-first
  AppLayout structure (no infrastructure/workloads tabs, no
  buildStorageRecoveryTabSpecs call) and the new routePreload entries.
- MobileNavBar.test.tsx extended to assert the platform-first
  MOBILE_NAV_PLATFORM_PRIORITY ordering and the absence of legacy IDs.
- 68-platform-pages-shell.spec.ts (Playwright, chromium) re-run
  post-demotion: all 4 platform pages still render with sub-tab chrome
  against the live Pulse dev runtime in empty-resource state, proving
  the first-run / no-data nav stays discoverable.
- vitest sweep across src/features, src/__tests__,
  src/routing/__tests__ (351 tests) green. Pre-existing
  PageControls.guardrails failure is unrelated (verified by stashing).

Unrelated dirty files (other-agent work in internal/ai/, status.json,
ai-runtime.md further edits) intentionally left untouched.
2026-05-15 23:19:02 +01:00
rcourtman
6f37c8d0ef Align discovery prompt governance
- keep fallback Assistant governance aligned with discovery run support

- describe Patrol discovery as read-or-refresh evidence access
2026-05-15 23:11:59 +01:00
rcourtman
cdaeb3b84d frontend(platforms): add Docker, Kubernetes, TrueNAS, vSphere platform pages
Introduce a shared platform-page primitive and four new top-level family
pages that mirror the v5-style Proxmox surface: chrome only, embedding
the canonical WorkloadsSurface, StorageSurface, RecoverySurface, and
UnifiedResourceTable in tableOnly/embedded mode with forced platform or
source filters. No dashboard cards, no fake data, no bespoke per-family
tables.

Pages added:
- /docker      Hosts / Containers / Swarm services
- /kubernetes  Clusters / Nodes / Pods / Deployments / Services
- /truenas     Hosts / Storage / Apps
- /vmware      Hosts / VMs / Storage (vSphere, first-lab-ready)

Top-level navigation entries are gated on platform presence in
state.resources, so empty platforms stay hidden by default; Proxmox
remains alwaysShow. Infrastructure, Workloads, Storage, and Recovery
remain available unchanged. Routing, navigation tab IDs, and the
document-title map are extended to match. Route preload and mobile-nav
priority changes are deliberately deferred to a follow-up commit to
avoid wider entanglement with parallel-agent edits to those shared
shell files.

Contracts extended for the new platform-page boundary:
- cloud-paid.md
- unified-resources.md
- storage-recovery.md
- ai-runtime.md
- frontend-primitives.md

Tests:
- dockerPageModel, kubernetesPageModel, truenasPageModel, vmwarePageModel
  vitest suites (12 new tests).
- resourceLinks.test.ts extended for the new platform path builders.
- App.architecture.test.ts extended for the new lazy imports and routes.
- 68-platform-pages-shell.spec.ts Playwright smoke covering all four
  pages and every sub-tab link against the live Pulse dev runtime.
- App.architecture, proxmox model, and Workloads suites continue to pass.

Skipped (canonical model not ready):
- Unraid as a top-level page: an agentHostProfile, no platform
  projections; already surfaces through the Pulse-managed Hosts / Storage
  views.
- Synology DSM, Microsoft Hyper-V, AWS, Azure, GCP:
  governanceState=presentation-only, no canonical projections.
2026-05-15 23:09:17 +01:00
rcourtman
6aad1118cd Align discovery with tool-led AI runtime
- add a forced run action to pulse_discovery for known resources

- make discovery progress describe model-backed evidence analysis rather than a live Assistant chat

- keep shared select hydration stable for persisted discovery intervals
2026-05-15 23:05:36 +01:00
rcourtman
6e8a7ae5fc Checkpoint current workspace progress 2026-05-15 22:45:48 +01:00
rcourtman
bfaa1aa596 Put storage view controls in table header 2026-05-15 22:33:55 +01:00
rcourtman
fbf9adb419 Keep storage view selector in table-only embeds 2026-05-15 22:26:44 +01:00
rcourtman
b33c29a82c Make discovery scan action visible 2026-05-15 22:15:48 +01:00
rcourtman
f987e11107 Let host drawer replace guest drawer 2026-05-15 21:56:40 +01:00
rcourtman
185e17daab Let drawer history charts fill cards 2026-05-15 21:48:14 +01:00
rcourtman
f2077c61fe Move workload links into name cells 2026-05-15 21:40:42 +01:00
rcourtman
526549dea1 Add Proxmox node thermal history 2026-05-15 21:27:39 +01:00
rcourtman
e882ce3a5d Refine workload history hover interaction 2026-05-15 20:28:45 +01:00
rcourtman
0b11a29727 Compact workload history charts 2026-05-15 18:49:42 +01:00
rcourtman
d213ea3e29 Add Proxmox platform table metrics 2026-05-15 18:13:27 +01:00
rcourtman
303a8e2fe8 Remove Assistant handoff decision guidance 2026-05-15 16:57:25 +01:00
rcourtman
482b84e219 Remove Assistant pre-model context heuristics 2026-05-15 16:28:17 +01:00
rcourtman
a50d9457bc Refine prototype row density cues 2026-05-15 16:19:12 +01:00
rcourtman
d4d3621a8b Refine unified monitoring prototype structure 2026-05-15 16:12:41 +01:00
rcourtman
14d3284233 Remove Assistant prompt routing heuristics 2026-05-15 16:10:58 +01:00
rcourtman
f3417d1bcc Add live unified monitoring prototype 2026-05-15 15:42:56 +01:00
rcourtman
99fce8e5a3 Remove Assistant status routing residue 2026-05-15 15:19:26 +01:00
rcourtman
0561a1b5fa Remove Assistant and Patrol tool-routing heuristics 2026-05-15 14:51:15 +01:00
rcourtman
2b9b1ec573 Fix TrueNAS system info buildtime decoding
Fixes #1469
2026-05-15 14:21:39 +01:00
rcourtman
eac7dfe9ef Make Patrol reasoning model-owned 2026-05-15 12:22:52 +01:00
rcourtman
895b78bd89 Make Assistant tool choice model-owned 2026-05-15 11:27:15 +01:00
rcourtman
348582df66 Fix Assistant chat model-owned routing 2026-05-15 10:50:23 +01:00
rcourtman
376b2f80fc Simplify Patrol Assistant handoffs 2026-05-15 10:17:10 +01:00
rcourtman
44d9f1d9d5 Simplify Patrol assessment hierarchy 2026-05-15 09:43:59 +01:00
rcourtman
f932bc841d Collapse Patrol assessment readout 2026-05-15 00:00:09 +01:00
rcourtman
0de1ebb3c2 Simplify Patrol assessment summary 2026-05-14 23:24:56 +01:00
rcourtman
f3885dc128 Clarify recovery verification evidence 2026-05-14 23:00:40 +01:00
rcourtman
66aa9f7c8c Clarify recovery drawer target details 2026-05-14 22:54:01 +01:00
rcourtman
5fdf80cfd9 Polish recovery drawer secondary details 2026-05-14 22:47:41 +01:00
rcourtman
247dc3f389 Tighten recovery point drawer hierarchy 2026-05-14 22:36:04 +01:00
rcourtman
8632e39595 Remove recovery drawer restore action path 2026-05-14 22:22:46 +01:00
rcourtman
a36bb254d5 Fix storage trend metrics targets 2026-05-14 22:12:16 +01:00
rcourtman
fbcb77d635 Stabilize managed hot-dev startup 2026-05-14 21:40:07 +01:00
rcourtman
7d6b447c59 Simplify recovery presentation and type contracts 2026-05-14 21:08:54 +01:00
rcourtman
3580a5ed6d Clarify storage topology and recovery guards 2026-05-14 20:51:32 +01:00
rcourtman
4622df523d Harden unified resource refresh races 2026-05-14 15:26:08 +01:00
rcourtman
92a5cb68ec Harden Workloads refresh retention 2026-05-14 15:18:34 +01:00
rcourtman
22ea442ed7 Fix default agent rollout status noise 2026-05-14 14:37:24 +01:00
rcourtman
439e252a64 Harden infrastructure workload identity regressions 2026-05-14 12:49:16 +01:00
rcourtman
eaa9269bec Add animated numeric metric readouts 2026-05-14 12:32:28 +01:00
rcourtman
a4d29fa92d Repair Proxmox workload parent identity 2026-05-14 12:12:06 +01:00