diff --git a/docker-compose.yml b/docker-compose.yml index c79b722b7..08ca9a157 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: '3.8' services: pulse: - image: ${PULSE_IMAGE:-rcourtman/pulse:6.0.0-rc.4} + image: ${PULSE_IMAGE:-rcourtman/pulse:6.0.0-rc.5} container_name: pulse restart: unless-stopped logging: diff --git a/docs/release-control/v6/internal/PLATFORM_SUPPORT_MODEL.md b/docs/release-control/v6/internal/PLATFORM_SUPPORT_MODEL.md index b91f87904..a18b6d541 100644 --- a/docs/release-control/v6/internal/PLATFORM_SUPPORT_MODEL.md +++ b/docs/release-control/v6/internal/PLATFORM_SUPPORT_MODEL.md @@ -260,7 +260,7 @@ Support floor fields are recorded in this order: `setup`, `visibility`, | Profile | Family | Governance | Readiness | Host identity tokens | Runtime platform | Storage family | Support floor | | --- | --- | --- | --- | --- | --- | --- | --- | -| `unraid` | `Unraid` | `supported` | `supported` | `unraid` | `linux` | `onprem` | `setup=supported`; `visibility=supported`; `workloads=n/a`; `storage=supported`; `recovery=n/a`; `alerts=supported`; `assistant_read=supported`; `assistant_control=read-only` | +| `unraid` | `Unraid` | `supported` | `supported` | `unraid`, `unraid-os`, `unraid os` | `linux` | `onprem` | `setup=supported`; `visibility=supported`; `workloads=n/a`; `storage=supported`; `recovery=n/a`; `alerts=supported`; `assistant_read=supported`; `assistant_control=read-only` | ### Current support rows diff --git a/internal/api/contract_test.go b/internal/api/contract_test.go index c1dea3bf9..8a28d5517 100644 --- a/internal/api/contract_test.go +++ b/internal/api/contract_test.go @@ -1247,7 +1247,8 @@ func TestContract_AISettingsBYOKOverrideDoesNotExposeQuickstartInventoryJSONSnap "configured_providers":["openai"], "control_level":"read_only", "protected_guests":[], - "discovery_enabled":false + "discovery_enabled":false, + "patrol_readiness":{"status":"not_ready","ready":false,"cause":"service_unavailable","summary":"Pulse Patrol service is not available.","checks":[{"id":"service","status":"not_ready","cause":"service_unavailable","label":"Patrol service","message":"Pulse Patrol service is not available.","action":"restart_service"}]} }` assertJSONSnapshot(t, rec.Body.Bytes(), want) @@ -3225,7 +3226,8 @@ func TestContract_HostedAISettingsDoesNotAutoBootstrapQuickstartJSONSnapshot(t * "configured_providers":[], "control_level":"read_only", "protected_guests":[], - "discovery_enabled":false + "discovery_enabled":false, + "patrol_readiness":{"status":"not_ready","ready":false,"cause":"service_unavailable","summary":"Pulse Patrol service is not available.","checks":[{"id":"service","status":"not_ready","cause":"service_unavailable","label":"Patrol service","message":"Pulse Patrol service is not available.","action":"restart_service"}]} }` assertJSONSnapshot(t, rec.Body.Bytes(), want) @@ -3284,7 +3286,8 @@ func TestContract_AISettingsRetiredQuickstartAliasJSONSnapshot(t *testing.T) { "configured_providers":[], "control_level":"read_only", "protected_guests":[], - "discovery_enabled":false + "discovery_enabled":false, + "patrol_readiness":{"status":"not_ready","ready":false,"cause":"service_unavailable","summary":"Pulse Patrol service is not available.","checks":[{"id":"service","status":"not_ready","cause":"service_unavailable","label":"Patrol service","message":"Pulse Patrol service is not available.","action":"restart_service"}]} }` assertJSONSnapshot(t, rec.Body.Bytes(), want) @@ -3348,7 +3351,8 @@ func TestContract_AISettingsOllamaAuthJSONSnapshot(t *testing.T) { "configured_providers":["ollama"], "control_level":"read_only", "protected_guests":[], - "discovery_enabled":false + "discovery_enabled":false, + "patrol_readiness":{"status":"not_ready","ready":false,"cause":"service_unavailable","summary":"Pulse Patrol service is not available.","checks":[{"id":"service","status":"not_ready","cause":"service_unavailable","label":"Patrol service","message":"Pulse Patrol service is not available.","action":"restart_service"}]} }` assertJSONSnapshot(t, rec.Body.Bytes(), want) @@ -3397,11 +3401,11 @@ func TestContract_ReportingCatalogJSONSnapshot(t *testing.T) { "description":"Generate performance reports and current-state exports across infrastructure and workloads.", "lockedState":{ "title":"Advanced Reporting", - "description":"Generate PDF and CSV performance reports plus current-state VM inventory exports across infrastructure and workload resources on paid self-hosted and hosted plans." + "description":"AI-narrated performance reports for a single resource or your full fleet, with an executive summary, outlier callouts, and period-over-period changes. PDF and CSV formats, plus current-state VM inventory exports. AI narration uses Pulse Assistant when configured; reports fall back to a deterministic summary otherwise. Available on paid self-hosted and hosted plans." }, "guidance":{ "title":"Advanced Insights", - "description":"Performance reports come from the historical metrics store, while VM inventory export captures the current runtime state for spreadsheet-friendly fleet reviews. Use reports for trends and the inventory export for current allocation and usage snapshots." + "description":"Performance reports include an AI-narrated executive summary, fleet outliers, and period-over-period comparison. They draw from the historical metrics store and Patrol findings within the window. The VM inventory export captures current runtime state for spreadsheet-friendly fleet reviews. Use reports for retrospective trends and the inventory export for current allocation snapshots." }, "performanceReport":{ "id":"performance_reports", @@ -3841,7 +3845,8 @@ func TestContract_HostedTenantAISettingsDoesNotAutoBootstrapQuickstartJSONSnapsh "configured_providers":[], "control_level":"read_only", "protected_guests":[], - "discovery_enabled":false + "discovery_enabled":false, + "patrol_readiness":{"status":"not_ready","ready":false,"cause":"service_unavailable","summary":"Pulse Patrol service is not available.","checks":[{"id":"service","status":"not_ready","cause":"service_unavailable","label":"Patrol service","message":"Pulse Patrol service is not available.","action":"restart_service"}]} }` assertJSONSnapshot(t, rec.Body.Bytes(), want) diff --git a/internal/mock/platform_support_contract_test.go b/internal/mock/platform_support_contract_test.go index c55efa1e3..f0fc637fa 100644 --- a/internal/mock/platform_support_contract_test.go +++ b/internal/mock/platform_support_contract_test.go @@ -19,7 +19,7 @@ var ( numberedPlatformListRE = regexp.MustCompile("^\\d+\\.\\s+`([^`]+)`") currentSupportMatrixRE = regexp.MustCompile("^\\|\\s+`([^`]+)`\\s+\\|") currentSupportSetupRowRE = regexp.MustCompile("^\\|\\s+`([^`]+)`\\s+\\|\\s+([^|]+?)\\s+\\|") - agentHostProfileTableRowRE = regexp.MustCompile("^\\|\\s+`([^`]+)`\\s+\\|\\s+`([^`]+)`\\s+\\|\\s+`([^`]+)`\\s+\\|\\s+`([^`]+)`\\s+\\|\\s+`([^`]+)`\\s+\\|\\s+`([^`]+)`\\s+\\|\\s+`([^`]+)`\\s+\\|") + agentHostProfileTableRowRE = regexp.MustCompile("^\\|\\s+`([^`]+)`\\s+\\|\\s+`([^`]+)`\\s+\\|\\s+`([^`]+)`\\s+\\|\\s+`([^`]+)`\\s+\\|\\s+(.+?)\\s+\\|\\s+`([^`]+)`\\s+\\|\\s+`([^`]+)`\\s+\\|") ) type platformSupportManifest struct { @@ -265,7 +265,7 @@ func TestUnraidRemainsInPresentationOnlyVocabularyAndAgentHostProfiles(t *testin if profile.ReadinessStage != "supported" { t.Fatalf("unraid readiness stage = %q, want supported", profile.ReadinessStage) } - if diff := diffPlatformSets([]string{"unraid"}, profile.HostIdentityTokens); diff != "" { + if diff := diffPlatformSets([]string{"unraid", "unraid-os", "unraid os"}, profile.HostIdentityTokens); diff != "" { t.Fatalf("unraid host identity tokens drifted from the host-profile model:\n%s", diff) } if profile.RuntimePlatform != "linux" { @@ -285,7 +285,7 @@ func TestUnraidRemainsInPresentationOnlyVocabularyAndAgentHostProfiles(t *testin } if !strings.Contains( model, - "| `unraid` | `Unraid` | `supported` | `supported` | `unraid` | `linux` | `onprem` |", + "| `unraid` | `Unraid` | `supported` | `supported` | `unraid`, `unraid-os`, `unraid os` | `linux` | `onprem` |", ) { t.Fatal("expected platform support model to keep the unraid host-profile row") } diff --git a/scripts/install-docker.sh b/scripts/install-docker.sh index 6c026af8c..38aed45bc 100755 --- a/scripts/install-docker.sh +++ b/scripts/install-docker.sh @@ -6,7 +6,7 @@ set -euo pipefail SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)" DOCKER_IMAGE_REPO="${DOCKER_IMAGE_REPO:-rcourtman/pulse}" -CANONICAL_DEFAULT_PULSE_VERSION="6.0.0-rc.4" +CANONICAL_DEFAULT_PULSE_VERSION="6.0.0-rc.5" resolve_default_pulse_version() { if [ -n "${PULSE_IMAGE_VERSION:-}" ]; then