Manifest-backed MCP tools, prompts, and resources with surface affordance contracts; agent capability manifest and governance projection; API contract tests and capability route projection; operations-loop and intelligence-funnel telemetry; release-control subsystem documentation, registry, and tooling; licensing and configuration.
Automates the docs/MSP.md validation checklist and the WEBHOOKS.md
delivery contract against the real server, covering the cross-layer
seams unit tests cannot see (today's two isolation bugs both lived
there):
- org-bound token allowed in its own org, denied 403 in sibling orgs
AND the default org (leaked client-site token must not read the
provider estate)
- dedicated agent-ingest port serves only /api/agents/* (management
paths 404, agent route auth-gated)
- client-org webhook delivery through the instance-wide private-target
allowlist saved in default-org context, with HMAC signature verified
against the documented recipe, X-Pulse-Event-ID idempotency header,
and tenant id/name stamped in the payload
- restart inheritance: after docker restart the persisted allowlist
still applies to lazily recreated tenant monitors (skips when the
docker CLI cannot manage the container)
Compose: pulse-test gains PULSE_AGENT_INGEST_PORT=7656 (+ port map)
and a host-gateway extra_host so the spec's capture listener is
reachable from the container.
golangci-lint run ./... failed on ~190 pre-existing errcheck violations and
5 unformatted files, burying any new regression in noise. Fix all of them:
- Test files that hand-rolled mock-mode set/restore (vmware, truenas, and
friends) now use the canonical setMockModeForTest/testutil.SetMockMode
helper instead of drift copies that ignored SetEnabled errors.
- internal/mock and internal/monitoring tests get package-local
mustSetEnabled/mustSetMockEnabled/mustSetMonitorMockMode helpers that
fail the test on toggle errors.
- pkg/auth/sqlite_manager.go, pkg/metrics/store.go, pkg/server/server.go:
rollbacks in defers use the explicit-discard idiom, migration renames and
rollup commits log failures, the hosted reaper goroutine logs an error
exit, shutdown mock-disable logs failures.
- Remaining test sites check errors with t.Fatalf/t.Errorf or explicitly
discard best-effort calls (restore-chmods, handler-closure unmarshals)
per existing repo style.
- gofmt: internal/api/maintenance_verification.go, internal/ai/demo.go and
three findings test files.
Only dupl findings remain (44 pre-existing production-code duplication
pairs) — those need real refactors, not mechanical fixes.
Full test suites pass for every touched package.
Recognize the current first-run security step in the multi-tenant integration helper and keep the unlock helper from clicking account-creation controls.
Harden bootstrap-token validation as unauthenticated JSON.
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.
Move TrueNAS apps, VMs, and network shares out of the overview stack and into first-class platform sub-tabs.
Update route and shell proof coverage for the expanded native TrueNAS tab set.
Replace the embedded recovery workspace with a TrueNAS-owned snapshots and replication table.
Keep the platform shell proof aligned to the native TrueNAS row contracts.
The "Hosts" tab already rendered the hosts table, the containers
WorkloadsSurface, and the Swarm services table together, so the
separate Containers and Swarm services sub-tabs were strict subset
views of overview. Other platform pages (Proxmox, TrueNAS,
Kubernetes) use sub-tabs for genuinely different data per tab; the
Docker shape was the odd one out.
Drop PlatformSectionTabs from DockerPageSurface and render the
unified hosts + containers + services stack unconditionally. Remove
the now-dead DOCKER_TAB_SPECS / DockerPageTabId / DockerTabSpec /
buildVisibleDockerTabSpecs exports from dockerPageModel. The
DockerPage no longer interprets the URL segment, so legacy
/docker/overview, /docker/containers, /docker/services bookmarks
continue to resolve via the existing /docker/* wildcard route in
App.tsx.
Audit pass on the TrueNAS pages turned up three concrete issues:
1. **TrueNAS system Uptime/Temperature were dashes** even though the
data lives on `truenas.uptimeSeconds` and on the
`agent.temperature` max-sensor projection. The system row is
emitted by `internal/truenas/provider.go::truenasRecordsFromSnapshot`,
which is a separate path from the host/node adapters that the
prior commit (c7bdd11e0) updated. Project the same top-level
`Resource.Uptime` and `Resource.Temperature` here so the canonical
table renders real values (live mock now reports `uptime: 3628800,
temperature: 61.5` on the TrueNAS appliance row).
2. **The Systems tab needed NAS-native columns.** A TrueNAS appliance
is a storage box — operators want at-a-glance pool / dataset /
disk / app counts on the same row as CPU / Memory / Storage /
Temperature / Uptime. New `TrueNASSystemsTable` reuses canonical
shared primitives (Card, Table, SearchInput, FilterButtonGroup,
StatusDot) and computes per-system child counts client-side from
the same TrueNAS scope already fetched by the page.
3. **Physical disks weren't surfaced anywhere on the page**, even
though the canonical TrueNAS adapter emits SMART-instrumented
`physical_disk` rows with model / serial / size / health /
temperature / wearout. Add a `disks` sub-tab (between Storage and
Apps) backed by a new `TrueNASDisksTable` that surfaces those
columns — generic Disk I/O / Uptime / Temperature from the infra
table aren't meaningful for individual disks, but disk-native
columns (model, type, size, health, temp, wearout, serial) are.
Browser verification (Playwright, chromium, live mock-mode dev runtime):
- 9 tests pass. The every-sub-tab operator-controls audit now covers
/truenas/disks too; the search input on every TrueNAS sub-tab is
the canonical SearchInput primitive.
Targeted vitest: `src/features/truenas/__tests__/truenasPageModel.test.ts`
(2 tests) green — covers the four-tab spec and the new `disks`
bucket on the page model.
Targeted Go: `go test ./internal/truenas/...` green.
Contract-neutral bypass: PULSE_ALLOW_CONTRACT_NEUTRAL_COMMIT set.
This completes the platform-page column-fit audit for TrueNAS. New
top-level `Resource.Uptime` / `Resource.Temperature` projection is
strictly additive (already documented as the adapter responsibility
in unified-resources.md by c7bdd11e0). The two new bespoke tables
live inside features/truenas/ and reuse canonical primitives only.
Four documented platform-page gaps from the prior round are closed:
1. **Docker Swarm services canonical projection.** The unified resource
adapter requires `host.Swarm.ClusterID`/`ClusterName` for
`dockerSwarmClusterKey` to produce a stable service source ID; the
mock generator was leaving those fields empty so all generated
services were dropped. Anchor every mock Swarm host to a single named
cluster (`mock-swarm-cluster-1` / `edge-swarm`) so manager and worker
hosts share Swarm identity and their services deduplicate correctly
across managers. Live mock survey now exposes 15 docker-service rows
(was 0).
2. **Docker Swarm services UI restored.** The `/docker/services`
sub-tab is back. `DockerPageSurface` mounts a `PlatformResourceTable`
with the canonical operator toolbar (search + status chips +
counter); `dockerPageModel.ts` re-introduces the services bucket;
the model test asserts the three-tab shape and the services bucket.
3. **TrueNAS Systems / Overview sub-tab restored.** Re-survey of the
canonical adapter confirms `truenas.FixtureRecords` already emits
the top-level TrueNAS appliance as a unified `agent` row tagged
with the `truenas` platform (see `internal/truenas/provider.go::
truenasRecordsFromSnapshot`). TrueNAS now defaults to
`/truenas/overview` and the page model exposes a `systems` bucket.
4. **VMware fixture inventory scaled to a mature SMB lab.**
`internal/vmware/fixtures.go::appendEdgeClusterFixtures`
programmatically appends an Edge DC with 3 more ESXi hosts
(esxi-05..07), 12 more VMs across Tier 1 / Stateful / Workstations /
Observability / Archive tiers (mixed healthy/warning/powered-off,
mixed Linux/Windows guest OS), and 4 more datastores (VMFS / NFS41 /
vSAN / cold-iSCSI). Live mock survey now shows 43 VMs (was 31), 18
agents (was 15), and 60 storage rows (was 55) across two datacenters.
5. **TrueNAS / vSphere Storage source filter chip suppression.**
`StoragePageControls` gains a `suppressSourceFilter` prop and
`Storage.tsx` automatically applies it whenever `forcedSourceFilter`
is set, so platform-page embeds no longer render the now-locked
Source filter chip alongside the operator toolbar.
Resource survey under the new mock baseline (live `/api/resources`):
- TOTAL 342 unique resources (was 307)
- app-container: 75, storage: 60, system-container: 44, vm: 43,
pod: 40, physical_disk: 19, agent: 18, docker-service: 15,
k8s-deployment: 14, docker-host: 5, network-endpoint: 5,
pbs: 2, pmg: 1, k8s-cluster: 1
Browser verification (Playwright, chromium, live mock-mode dev runtime):
- 9 tests pass. Every populated sub-tab — Docker Hosts / Containers /
Swarm services, Kubernetes Clusters / Nodes / Pods / Deployments,
TrueNAS Systems / Storage / Apps, vSphere Hosts / VMs / Storage —
asserts both populated canonical rows AND a visible operator search
input.
Targeted vitest (77 files / 358 tests) + Go tests (./internal/vmware,
./internal/mock, ./internal/monitoring) all green.
Contracts updated:
- `storage-recovery.md` Shared Boundaries: TrueNAS defaults to the
Systems overview now that the canonical adapter emits a TrueNAS-
platform agent row; `suppressSourceFilter` auto-applies under
`forcedSourceFilter`.
- `unified-resources.md` Extension Points: same; the canonical TrueNAS
adapter emits the appliance as a unified resource so the builder
default lands on a populated Systems sub-tab.
- `Storage.test.tsx` extended with the source-filter suppression
contract assertion.
Closes the second half of the v5→v6 affordance bridge. The first commit
in this chain (65b069dbb) brought operator controls to the embedded
Workloads/Storage sub-tabs (Docker Containers, K8s Pods, TrueNAS
Storage/Apps, vSphere VMs/Storage). The UnifiedResourceTable-backed
sub-tabs (Docker Hosts, K8s Clusters/Nodes/Deployments, vSphere Hosts)
were left with the table's built-in sort handles only — no search, no
status chips, no counters — which read as a non-native experience
against the v5 dashboard/storage filter density.
Extend the shared PlatformResourceTable in
`frontend-modern/src/features/platformPage/sharedPlatformPage.tsx`
with a canonical operator toolbar:
- SearchInput (the canonical primitive, with the standard placeholder
+ clear-on-escape semantics) for name/display-name/id/parent/tags
search.
- FilterButtonGroup status chip strip: All / Online / Degraded /
Offline, with the per-platform status vocabulary (running, paused,
stopped, etc.) collapsed through the shared
`mapResourceStatusToTriad` helper.
- Compact "N of M rows" counter on the right of the toolbar so
operators can read total / matching at a glance without spawning a
card grid.
- Client-side filtering via `filterPlatformResources` before resources
reach UnifiedResourceTable, so the canonical table stays the data
surface and the platform page owns the chrome.
Every platform sub-tab now exposes operator controls:
- Docker Hosts (UnifiedResourceTable + new toolbar)
- Docker Containers (WorkloadsSurface canonical toolbar)
- Kubernetes Clusters/Nodes/Deployments (UnifiedResourceTable + new
toolbar)
- Kubernetes Pods (WorkloadsSurface canonical toolbar)
- TrueNAS Storage/Apps (canonical toolbars)
- vSphere Hosts (UnifiedResourceTable + new toolbar)
- vSphere VMs/Storage (canonical toolbars)
Browser verification (Playwright, chromium, live mock-mode):
- Expanded the operator-controls audit to cover every populated sub-tab
route (11 routes total). All assertions pass. 9/9 spec tests green.
Targeted vitest:
- New sharedPlatformPage.test.ts covers filterPlatformResources
(6 tests, all pass) including the status-vocabulary collapse
(online↔running, degraded↔paused, offline↔stopped) and the
search-across-id/displayName/parent/tags contract.
- WorkloadsSurface and Storage surface contract tests continue to
pass.
v5 platform/dashboard pages had a dense filter card with search, status
chips, view-mode toggle, grouping toggle, column picker, and sort
controls (DashboardFilter.tsx, DockerFilter.tsx, StorageFilter.tsx).
v6 platform pages mounted WorkloadsSurface and StorageSurface in
`embedded tableOnly` mode, which hid the entire canonical filter
toolbar alongside the dashboard cards — so /docker/containers,
/kubernetes/pods, /truenas/storage, /truenas/apps, /vmware/vms, and
/vmware/storage shipped without search, status, grouping, or column
controls. Operators had no way to filter inside a platform page short
of navigating to the global Workloads/Storage page.
Bridge those v5 affordances onto the v6 platform pages by extending
the canonical surface contracts:
- WorkloadsSurfaceProps gains `showFilterToolbar` and
`suppressPlatformFilter`. `showFilterToolbar` keeps the canonical
WorkloadsFilter (search input + status chips + view-mode segmented
control + grouping toggle + ColumnPicker + sort handles) visible even
under `tableOnly`. `suppressPlatformFilter` drops the redundant
Platform chip since the platform is already fixed by the owning page,
so the user never sees a removable lock.
- StorageProps gains `showFilterToolbar`. Same idea for the canonical
StoragePageControls (search + status + group-by + sort + node filter
+ view).
Platform pages now mount their embedded surfaces with
`tableOnly + showFilterToolbar` (plus `suppressPlatformFilter` for
WorkloadsSurface):
- Docker > Containers
- Kubernetes > Pods
- TrueNAS > Storage, Apps
- vSphere > VMs, Storage
UnifiedResourceTable-backed sub-tabs (Docker Hosts, K8s Clusters/
Nodes/Deployments, vSphere Hosts) still rely on the table's built-in
sort handles only; a follow-up shared `PlatformInfraControls` row with
search + counters is the next operator-controls bridge.
Browser verification (Playwright, chromium, against live mock-mode
Pulse dev runtime):
- 9 tests, all pass. New assertion confirms that every embedded
Workloads/Storage sub-tab on a platform page now renders the
canonical search input (proving the v5-style operator toolbar is
back).
Targeted vitest:
- WorkloadsSurface.performance.contract.test.tsx adds a platform-page
embed contract assertion (37 tests total, all pass).
- Storage.test.tsx adds the matching StorageProps assertion
(39 tests total, all pass).
Contracts updated:
- performance-and-scalability.md Shared Boundaries: documents the
`showFilterToolbar` + `suppressPlatformFilter` platform-page contract
on WorkloadsSurface.
- storage-recovery.md Shared Boundaries: documents the
`showFilterToolbar` platform-page contract on StorageSurface.
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.
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.
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.
Present stable refusal prefixes through shared frontend helpers and show verification outcomes in resource action history without exposing raw refusal tokens. Extend action audit tests, drawer coverage, and VMware history spec evidence.
Classify Assistant and Patrol provider-test failures through the Patrol runtime failure taxonomy, redact secret-shaped provider evidence, and preserve safe recommendations in the settings shell.
Refs #1463