Align Pro feature catalog names with the new Patrol vocabulary

The public pricing surface and in-app plan-selling copy now say
"Patrol investigates issues and explains the root cause" and
"Patrol applies safe fixes and verifies the result". Rename the
licensing catalog DisplayName/ComparisonName pairs to the title-cased
forms, align the ai_autofix UpgradeReason verbs (apply/verify the
result), regenerate the frontend catalog, and update the Go, vitest,
and Playwright pins plus README and PULSE_PRO docs.
This commit is contained in:
rcourtman
2026-07-11 09:33:47 +01:00
parent 1312da3acb
commit 500d3be2a7
13 changed files with 72 additions and 72 deletions
+2 -2
View File
@@ -209,8 +209,8 @@ Runtime-aligned capability summary:
|---|:---:|:---:|:---:|:---:|
| Pulse Patrol (Background Health Checks) | ✅ | ✅ | ✅ | ✅ |
| Remote Access / Mobile / Push | — | ✅ | ✅ | ✅ |
| Patrol Investigates Issues | — | — | ✅ | ✅ |
| Patrol Handles Safe Fixes | — | — | ✅ | ✅ |
| Patrol Investigates Issues and Explains the Root Cause | — | — | ✅ | ✅ |
| Patrol Applies Safe Fixes and Verifies the Result | — | — | ✅ | ✅ |
| Centralized Agent Profiles | — | — | ✅ | ✅ |
| Update Alerts (Container/Package Updates) | ✅ | ✅ | ✅ | ✅ |
| SSO (OIDC/SAML/Multi-Provider) | ✅ | ✅ | ✅ | ✅ |
+2 -2
View File
@@ -140,8 +140,8 @@ This matrix is derived from the canonical table in `docs/architecture/ENTITLEMEN
|---|---|---|:---:|:---:|:---:|:---:|---|
| `FeatureAIPatrol` | `ai_patrol` | Pulse Patrol (Background Health Checks) | Y | Y | Y | Y | Patrol itself is available on Community with your own provider or local model. Higher-autonomy outcomes and fix execution are separately gated. |
| `FeatureRelay` | `relay` | Remote Access (Mobile Relay) | N | Y | Y | Y | API route gating via `RequireLicenseFeature(..., relay, ...)` for relay settings and onboarding endpoints. |
| `FeatureAIAlerts` | `ai_alerts` | Patrol Investigates Issues | N | N | Y | Y | API route gating via `RequireLicenseFeature(..., ai_alerts, ...)`. |
| `FeatureAIAutoFix` | `ai_autofix` | Patrol Handles Safe Fixes | N | N | Y | Y | Required for governed fix execution and automatic Patrol actions. |
| `FeatureAIAlerts` | `ai_alerts` | Patrol Investigates Issues and Explains the Root Cause | N | N | Y | Y | API route gating via `RequireLicenseFeature(..., ai_alerts, ...)`. |
| `FeatureAIAutoFix` | `ai_autofix` | Patrol Applies Safe Fixes and Verifies the Result | N | N | Y | Y | Required for governed fix execution and automatic Patrol actions. |
| `FeatureKubernetesAI` | `kubernetes_ai` | Kubernetes AI Analysis (Compatibility) | N | N | Y | Y | Legacy compatibility gate for `/api/ai/kubernetes/analyze`; not a primary marketed v6 Pro plan pillar. |
| `FeatureAgentProfiles` | `agent_profiles` | Centralized Agent Profiles | N | N | Y | Y | API route gating via `RequireLicenseFeature(..., agent_profiles, ...)`. |
| `FeatureUpdateAlerts` | `update_alerts` | Update Alerts (Container/Package Updates) | Y | Y | Y | Y | Included in Community tier per `TierFeatures[TierFree]`. |
@@ -398,7 +398,7 @@ describe('ProLicensePanel', () => {
expect(screen.getAllByText('Trial').length).toBeGreaterThan(0);
expect(screen.getByText('7')).toBeInTheDocument();
expect(screen.getByText('Patrol Handles Safe Fixes')).toBeInTheDocument();
expect(screen.getByText('Patrol Applies Safe Fixes and Verifies the Result')).toBeInTheDocument();
});
it('keeps the Patrol mode entry point visible for existing active Pro plans', async () => {
@@ -836,8 +836,8 @@ describe('ProLicensePanel', () => {
),
).toBeInTheDocument();
expect(screen.getByText('Primary capabilities')).toBeInTheDocument();
expect(screen.getByText('Patrol Investigates Issues')).toBeInTheDocument();
expect(screen.getByText('Patrol Handles Safe Fixes')).toBeInTheDocument();
expect(screen.getByText('Patrol Investigates Issues and Explains the Root Cause')).toBeInTheDocument();
expect(screen.getByText('Patrol Applies Safe Fixes and Verifies the Result')).toBeInTheDocument();
expect(screen.getByText('Included extras')).toBeInTheDocument();
expect(screen.getByText('Capability details')).toBeInTheDocument();
expect(screen.getByText('(5 items ready)')).toBeInTheDocument();
@@ -1085,8 +1085,8 @@ describe('ProLicensePanel', () => {
// Verify self-hosted displayable capabilities render with their expected labels.
expect(screen.getByText('Pulse Patrol')).toBeInTheDocument();
expect(screen.getByText('Patrol Investigates Issues')).toBeInTheDocument();
expect(screen.getByText('Patrol Handles Safe Fixes')).toBeInTheDocument();
expect(screen.getByText('Patrol Investigates Issues and Explains the Root Cause')).toBeInTheDocument();
expect(screen.getByText('Patrol Applies Safe Fixes and Verifies the Result')).toBeInTheDocument();
expect(screen.getByText('Update Alerts')).toBeInTheDocument();
expect(screen.getByText('Role-Based Access Control (RBAC)')).toBeInTheDocument();
expect(screen.getByText('Audit Logging')).toBeInTheDocument();
@@ -1195,7 +1195,7 @@ describe('ProLicensePanel', () => {
),
).toBeInTheDocument();
expect(screen.getByText('Available now on this instance')).toBeInTheDocument();
expect(screen.getAllByText('Patrol Handles Safe Fixes').length).toBeGreaterThan(0);
expect(screen.getAllByText('Patrol Applies Safe Fixes and Verifies the Result').length).toBeGreaterThan(0);
expect(screen.getAllByRole('link', { name: 'Choose Patrol mode' })).toHaveLength(1);
const patrolControlLink = screen.getByRole('link', { name: 'Choose Patrol mode' });
expect(patrolControlLink).toHaveAttribute('href', PATROL_CONTROL_STARTER_URL);
@@ -1285,7 +1285,7 @@ describe('ProLicensePanel', () => {
),
).toBeInTheDocument();
expect(screen.queryByText('Select a plan')).not.toBeInTheDocument();
expect(screen.getAllByText('Patrol Handles Safe Fixes').length).toBeGreaterThan(0);
expect(screen.getAllByText('Patrol Applies Safe Fixes and Verifies the Result').length).toBeGreaterThan(0);
expect(screen.queryByText('Available plans')).not.toBeInTheDocument();
expect(screen.queryByRole('link', { name: 'Review plan' })).not.toBeInTheDocument();
});
@@ -1310,7 +1310,7 @@ describe('ProLicensePanel', () => {
),
).not.toBeInTheDocument();
expect(screen.getByText('Current plan: Community')).toBeInTheDocument();
expect(screen.queryByText('Patrol Handles Safe Fixes')).not.toBeInTheDocument();
expect(screen.queryByText('Patrol Applies Safe Fixes and Verifies the Result')).not.toBeInTheDocument();
expect(screen.queryByText('Available now on this instance')).not.toBeInTheDocument();
expect(navigateMock).toHaveBeenCalledWith(SELF_HOSTED_PRO_BILLING_PLAN_HREF, {
replace: true,
@@ -520,7 +520,7 @@ describe('getSelfHostedCurrentPlanPresentation - trial branch', () => {
upgrade_reasons: [],
runtime: { build: 'community', label: 'Pulse Community runtime' },
},
displayableCapabilities: ['Patrol Handles Safe Fixes'],
displayableCapabilities: ['Patrol Applies Safe Fixes and Verifies the Result'],
});
expect(result.title).toBe('Current plan: Pulse Pro Trial');
expect(result.body).toContain('trial entitlement is active');
@@ -581,7 +581,7 @@ describe('getSelfHostedCurrentPlanPresentation - is_lifetime branch', () => {
upgrade_reasons: [],
runtime: { build: 'pro', label: 'Pulse Pro runtime' },
},
displayableCapabilities: ['Pulse Relay (Remote Access)', 'Patrol Handles Safe Fixes'],
displayableCapabilities: ['Pulse Relay (Remote Access)', 'Patrol Applies Safe Fixes and Verifies the Result'],
});
expect(result.supplementalBadges).toContain('Grandfathered lifetime');
expect(result.supplementalSummary).toContain(
@@ -602,7 +602,7 @@ describe('getSelfHostedCurrentPlanPresentation - grace + grandfathered branch',
upgrade_reasons: [],
runtime: { build: 'pro', label: 'Pulse Pro runtime' },
},
displayableCapabilities: ['Pulse Relay (Remote Access)', 'Patrol Handles Safe Fixes'],
displayableCapabilities: ['Pulse Relay (Remote Access)', 'Patrol Applies Safe Fixes and Verifies the Result'],
});
expect(result.supplementalBadges).toContain('Grandfathered price');
});
@@ -655,7 +655,7 @@ describe('getSelfHostedCurrentPlanPresentation - getPatrolControlAction branches
upgrade_reasons: [],
runtime: { build: 'pro', label: 'Pulse Pro runtime' },
},
displayableCapabilities: ['Pulse Relay (Remote Access)', 'Patrol Handles Safe Fixes'],
displayableCapabilities: ['Pulse Relay (Remote Access)', 'Patrol Applies Safe Fixes and Verifies the Result'],
patrolOperatorStatus: {
patrolControlOperationsLoopStarterCount: 1,
patrolControlCompletedOperationsLoopCount: 1,
@@ -811,7 +811,7 @@ describe('getSelfHostedActivationSuccessPresentation - purchase + runtime mismat
upgrade_reasons: [],
runtime: { build: 'community', label: 'Pulse Community runtime' },
},
displayableCapabilities: ['Pulse Relay (Remote Access)', 'Patrol Handles Safe Fixes'],
displayableCapabilities: ['Pulse Relay (Remote Access)', 'Patrol Applies Safe Fixes and Verifies the Result'],
source: 'purchase',
});
expect(result).not.toBeNull();
@@ -883,8 +883,8 @@ describe('getSelfHostedActivationSuccessPresentation - highlights dedup', () =>
runtime: { build: 'pro', label: 'Pulse Pro runtime' },
},
displayableCapabilities: [
'Patrol Investigates Issues',
'Patrol Handles Safe Fixes',
'Patrol Investigates Issues and Explains the Root Cause',
'Patrol Applies Safe Fixes and Verifies the Result',
'90-day metric history',
],
source: 'manual',
@@ -892,7 +892,7 @@ describe('getSelfHostedActivationSuccessPresentation - highlights dedup', () =>
expect(result).not.toBeNull();
const highlights = result?.highlights ?? [];
expect(highlights.length).toBe(new Set(highlights).size);
expect(highlights).toContain('Patrol Investigates Issues');
expect(highlights).toContain('Patrol Investigates Issues and Explains the Root Cause');
expect(highlights).toContain('Role-Based Access Control (RBAC)');
});
});
@@ -335,7 +335,7 @@ describe('licensePresentation', () => {
upgrade_reasons: [],
runtime: { build: 'pro', label: 'Pulse Pro runtime' },
},
displayableCapabilities: ['Pulse Relay (Remote Access)', 'Patrol Handles Safe Fixes'],
displayableCapabilities: ['Pulse Relay (Remote Access)', 'Patrol Applies Safe Fixes and Verifies the Result'],
}),
).toMatchObject({
title: 'Current plan: Pulse Pro',
@@ -357,7 +357,7 @@ describe('licensePresentation', () => {
displayableCapabilities: [
'Pulse Relay (Remote Access)',
'Pulse Mobile Pairing',
'Patrol Handles Safe Fixes',
'Patrol Applies Safe Fixes and Verifies the Result',
],
}),
).toEqual({
@@ -365,8 +365,8 @@ describe('licensePresentation', () => {
body: 'Pulse Pro is active on this instance. It includes Patrol modes (Ask first, Safe auto-fix, Autopilot), 90-day metric history, RBAC, audit logging, reporting, and agent profiles.',
unlockedFeaturesLabel: 'Primary capabilities',
unlockedFeatures: [
'Patrol Investigates Issues',
'Patrol Handles Safe Fixes',
'Patrol Investigates Issues and Explains the Root Cause',
'Patrol Applies Safe Fixes and Verifies the Result',
'90-day metric history',
],
includedExtrasLabel: 'Included extras',
@@ -398,7 +398,7 @@ describe('licensePresentation', () => {
displayableCapabilities: [
'Pulse Relay (Remote Access)',
'Pulse Mobile Pairing',
'Patrol Handles Safe Fixes',
'Patrol Applies Safe Fixes and Verifies the Result',
],
patrolOperatorStatus: {
patrolAutonomyOperationsLoopStarterCount: 1,
@@ -429,7 +429,7 @@ describe('licensePresentation', () => {
displayableCapabilities: [
'Pulse Relay (Remote Access)',
'Pulse Mobile Pairing',
'Patrol Handles Safe Fixes',
'Patrol Applies Safe Fixes and Verifies the Result',
],
patrolOperatorStatus: {
proActivationOperationsLoopStarterCount: 1,
@@ -458,7 +458,7 @@ describe('licensePresentation', () => {
displayableCapabilities: [
'Pulse Relay (Remote Access)',
'Pulse Mobile Pairing',
'Patrol Handles Safe Fixes',
'Patrol Applies Safe Fixes and Verifies the Result',
],
patrolOperatorStatus: {
patrolControlOperationsLoopStarterCount: 1,
@@ -485,7 +485,7 @@ describe('licensePresentation', () => {
displayableCapabilities: [
'Pulse Relay (Remote Access)',
'Pulse Mobile Pairing',
'Patrol Handles Safe Fixes',
'Patrol Applies Safe Fixes and Verifies the Result',
],
patrolOperatorStatus: {
patrolControlOperationsLoopStarterCount: 2,
@@ -512,7 +512,7 @@ describe('licensePresentation', () => {
displayableCapabilities: [
'Pulse Relay (Remote Access)',
'Pulse Mobile Pairing',
'Patrol Handles Safe Fixes',
'Patrol Applies Safe Fixes and Verifies the Result',
],
patrolOperatorStatus: {
patrolControlOperationsLoopStarterCount: 1,
@@ -544,7 +544,7 @@ describe('licensePresentation', () => {
displayableCapabilities: [
'Pulse Relay (Remote Access)',
'Pulse Mobile Pairing',
'Patrol Handles Safe Fixes',
'Patrol Applies Safe Fixes and Verifies the Result',
],
patrolOperatorStatus: {
patrolAutonomyOperationsLoopStarterCount: 1,
@@ -573,7 +573,7 @@ describe('licensePresentation', () => {
displayableCapabilities: [
'Pulse Relay (Remote Access)',
'Pulse Mobile Pairing',
'Patrol Handles Safe Fixes',
'Patrol Applies Safe Fixes and Verifies the Result',
],
patrolOperatorStatus: {
nextAction: 'complete',
@@ -602,7 +602,7 @@ describe('licensePresentation', () => {
displayableCapabilities: [
'Pulse Relay (Remote Access)',
'Pulse Mobile Pairing',
'Patrol Handles Safe Fixes',
'Patrol Applies Safe Fixes and Verifies the Result',
],
patrolOperatorStatus: {
nextAction: 'open_mcp',
@@ -629,15 +629,15 @@ describe('licensePresentation', () => {
upgrade_reasons: [],
runtime: { build: 'pro', label: 'Pulse Pro runtime' },
},
displayableCapabilities: ['Pulse Relay (Remote Access)', 'Patrol Handles Safe Fixes'],
displayableCapabilities: ['Pulse Relay (Remote Access)', 'Patrol Applies Safe Fixes and Verifies the Result'],
}),
).toMatchObject({
title: 'Current plan: Legacy Pulse Pro+',
body: 'Legacy Pulse Pro+ is active on this instance. It includes Patrol modes (Ask first, Safe auto-fix, Autopilot), 90-day metric history, RBAC, audit logging, reporting, and agent profiles.',
unlockedFeaturesLabel: 'Primary capabilities',
unlockedFeatures: [
'Patrol Investigates Issues',
'Patrol Handles Safe Fixes',
'Patrol Investigates Issues and Explains the Root Cause',
'Patrol Applies Safe Fixes and Verifies the Result',
'90-day metric history',
],
});
@@ -660,8 +660,8 @@ describe('licensePresentation', () => {
body: 'Pulse Pro is active on this instance. It includes Patrol modes (Ask first, Safe auto-fix, Autopilot), 90-day metric history, RBAC, audit logging, reporting, and agent profiles.',
unlockedFeaturesLabel: 'Primary capabilities',
unlockedFeatures: [
'Patrol Investigates Issues',
'Patrol Handles Safe Fixes',
'Patrol Investigates Issues and Explains the Root Cause',
'Patrol Applies Safe Fixes and Verifies the Result',
'90-day metric history',
],
includedExtrasLabel: 'Included extras',
@@ -803,7 +803,7 @@ describe('licensePresentation', () => {
upgrade_reasons: [],
runtime: { build: 'pro', label: 'Pulse Pro runtime' },
},
displayableCapabilities: ['Pulse Relay (Remote Access)', 'Patrol Handles Safe Fixes'],
displayableCapabilities: ['Pulse Relay (Remote Access)', 'Patrol Applies Safe Fixes and Verifies the Result'],
}).body,
).toBe(getSelfHostedPlanEntitlementSummary('pro', 'Legacy Pulse Pro+'));
});
@@ -825,7 +825,7 @@ describe('licensePresentation', () => {
upgrade_reasons: [],
runtime: { build: 'pro', label: 'Pulse Pro runtime' },
},
displayableCapabilities: ['Pulse Relay (Remote Access)', 'Patrol Handles Safe Fixes'],
displayableCapabilities: ['Pulse Relay (Remote Access)', 'Patrol Applies Safe Fixes and Verifies the Result'],
}).patrolControlAction,
).toEqual(patrolControlAction);
@@ -839,7 +839,7 @@ describe('licensePresentation', () => {
upgrade_reasons: [],
runtime: { build: 'pro', label: 'Pulse Pro runtime' },
},
displayableCapabilities: ['Patrol Handles Safe Fixes'],
displayableCapabilities: ['Patrol Applies Safe Fixes and Verifies the Result'],
}).patrolControlAction,
).toEqual(patrolControlAction);
@@ -853,7 +853,7 @@ describe('licensePresentation', () => {
upgrade_reasons: [],
runtime: { build: 'community', label: 'Pulse Community runtime' },
},
displayableCapabilities: ['Patrol Handles Safe Fixes'],
displayableCapabilities: ['Patrol Applies Safe Fixes and Verifies the Result'],
}).patrolControlAction,
).toBeUndefined();
@@ -870,7 +870,7 @@ describe('licensePresentation', () => {
'Pulse Relay (Remote Access)',
'Pulse Mobile Pairing',
'Push Notifications',
'Patrol Handles Safe Fixes',
'Patrol Applies Safe Fixes and Verifies the Result',
],
}).patrolControlAction,
).toBeUndefined();
@@ -1234,7 +1234,7 @@ describe('licensePresentation', () => {
'Pulse Relay (Remote Access)',
'Pulse Mobile Pairing',
'Push Notifications',
'Patrol Handles Safe Fixes',
'Patrol Applies Safe Fixes and Verifies the Result',
],
source: 'purchase',
}),
@@ -1244,8 +1244,8 @@ describe('licensePresentation', () => {
body: 'Checkout completed and Pulse Pro is active. Choose Patrol mode.',
highlightsLabel: 'Available now on this instance',
highlights: [
'Patrol Investigates Issues',
'Patrol Handles Safe Fixes',
'Patrol Investigates Issues and Explains the Root Cause',
'Patrol Applies Safe Fixes and Verifies the Result',
'90-day metric history',
'Role-Based Access Control (RBAC)',
'Audit Logging',
@@ -1295,7 +1295,7 @@ describe('licensePresentation', () => {
limits: [],
upgrade_reasons: [],
},
displayableCapabilities: ['Pulse Patrol', 'Patrol Handles Safe Fixes'],
displayableCapabilities: ['Pulse Patrol', 'Patrol Applies Safe Fixes and Verifies the Result'],
source: 'purchase',
}),
).toBeNull();
@@ -1328,7 +1328,7 @@ describe('licensePresentation', () => {
expect(
getSelfHostedActivationSuccessPresentation({
entitlements: proEntitlements,
displayableCapabilities: ['Patrol Handles Safe Fixes'],
displayableCapabilities: ['Patrol Applies Safe Fixes and Verifies the Result'],
patrolOperatorStatus: {
patrolAutonomyOperationsLoopStarterCount: 1,
patrolAutonomyCompletedOperationsLoopCount: 0,
@@ -1346,7 +1346,7 @@ describe('licensePresentation', () => {
expect(
getSelfHostedActivationSuccessPresentation({
entitlements: proEntitlements,
displayableCapabilities: ['Patrol Handles Safe Fixes'],
displayableCapabilities: ['Patrol Applies Safe Fixes and Verifies the Result'],
patrolOperatorStatus: {
proActivationOperationsLoopStarterCount: 1,
proActivationCompletedOperationsLoopCount: 0,
@@ -1365,7 +1365,7 @@ describe('licensePresentation', () => {
expect(
getSelfHostedActivationSuccessPresentation({
entitlements: proEntitlements,
displayableCapabilities: ['Patrol Handles Safe Fixes'],
displayableCapabilities: ['Patrol Applies Safe Fixes and Verifies the Result'],
patrolOperatorStatus: {
patrolControlOperationsLoopStarterCount: 1,
proActivationOperationsLoopStarterCount: 1,
@@ -1382,7 +1382,7 @@ describe('licensePresentation', () => {
expect(
getSelfHostedActivationSuccessPresentation({
entitlements: proEntitlements,
displayableCapabilities: ['Patrol Handles Safe Fixes'],
displayableCapabilities: ['Patrol Applies Safe Fixes and Verifies the Result'],
patrolOperatorStatus: {
nextAction: 'open_mcp',
patrolAutonomyOperationsLoopStarterCount: 1,
@@ -1402,7 +1402,7 @@ describe('licensePresentation', () => {
expect(
getSelfHostedActivationSuccessPresentation({
entitlements: proEntitlements,
displayableCapabilities: ['Patrol Handles Safe Fixes'],
displayableCapabilities: ['Patrol Applies Safe Fixes and Verifies the Result'],
patrolOperatorStatus: {
nextAction: 'complete',
patrolAutonomyOperationsLoopStarterCount: 1,
@@ -1422,7 +1422,7 @@ describe('licensePresentation', () => {
expect(
getSelfHostedActivationSuccessPresentation({
entitlements: proEntitlements,
displayableCapabilities: ['Patrol Handles Safe Fixes'],
displayableCapabilities: ['Patrol Applies Safe Fixes and Verifies the Result'],
patrolOperatorStatus: {
patrolAutonomyOperationsLoopStarterCount: 1,
patrolAutonomyCompletedOperationsLoopCount: 1,
@@ -136,8 +136,8 @@ describe('selfHostedPlans', () => {
);
expect(SELF_HOSTED_PLAN_BY_TIER.pro.comparisonSummary).not.toContain('how much control');
expect(SELF_HOSTED_PLAN_BY_TIER.pro.entitlementHighlights).toEqual([
'Patrol Investigates Issues',
'Patrol Handles Safe Fixes',
'Patrol Investigates Issues and Explains the Root Cause',
'Patrol Applies Safe Fixes and Verifies the Result',
'90-day metric history',
]);
expect(SELF_HOSTED_PLAN_BY_TIER.pro.includedExtras).toEqual([
@@ -131,8 +131,8 @@ export const SELF_HOSTED_FEATURE_CATALOG: readonly GeneratedSelfHostedFeatureCat
},
{
"key": "ai_alerts",
"displayName": "Patrol Investigates Issues",
"comparisonName": "Patrol Investigates Issues",
"displayName": "Patrol Investigates Issues and Explains the Root Cause",
"comparisonName": "Patrol Investigates Issues and Explains the Root Cause",
"showInComparisonTable": true,
"displayableInSelfHostedPlan": true,
"roles": {
@@ -148,8 +148,8 @@ export const SELF_HOSTED_FEATURE_CATALOG: readonly GeneratedSelfHostedFeatureCat
},
{
"key": "ai_autofix",
"displayName": "Patrol Handles Safe Fixes",
"comparisonName": "Patrol Handles Safe Fixes",
"displayName": "Patrol Applies Safe Fixes and Verifies the Result",
"comparisonName": "Patrol Applies Safe Fixes and Verifies the Result",
"showInComparisonTable": true,
"displayableInSelfHostedPlan": true,
"roles": {
+1 -1
View File
@@ -7244,7 +7244,7 @@ func TestContract_SelfHostedCommunityEntitlementsJSONSnapshot(t *testing.T) {
{"key":"push_notifications","reason":"Get Relay so important alerts reach you immediately on mobile instead of waiting for you to reopen Pulse.","action_url":"https://pulserelay.pro/pricing?utm_source=pulse\u0026utm_medium=app\u0026utm_campaign=upgrade\u0026feature=push_notifications"},
{"key":"relay","reason":"Get Relay so Pulse stays reachable securely from anywhere instead of only on the local dashboard.","action_url":"https://pulserelay.pro/pricing?utm_source=pulse\u0026utm_medium=app\u0026utm_campaign=upgrade\u0026feature=relay"},
{"key":"long_term_metrics","reason":"Get Relay for 14 days of history, or Pro for 90 days, so you can see what changed before and after an incident.","action_url":"https://pulserelay.pro/pricing?utm_source=pulse\u0026utm_medium=app\u0026utm_campaign=upgrade\u0026feature=long_term_metrics"},
{"key":"ai_autofix","reason":"Upgrade to Pro so Patrol can investigate issues, handle safe fixes within Patrol mode, and verify the outcome.","action_url":"https://pulserelay.pro/pricing?utm_source=pulse\u0026utm_medium=app\u0026utm_campaign=upgrade\u0026feature=ai_autofix"},
{"key":"ai_autofix","reason":"Upgrade to Pro so Patrol can investigate issues, apply safe fixes within Patrol mode, and verify the result.","action_url":"https://pulserelay.pro/pricing?utm_source=pulse\u0026utm_medium=app\u0026utm_campaign=upgrade\u0026feature=ai_autofix"},
{"key":"ai_alerts","reason":"Upgrade to Pro so Patrol can investigate issues instead of handing you a stack of symptoms.","action_url":"https://pulserelay.pro/pricing?utm_source=pulse\u0026utm_medium=app\u0026utm_campaign=upgrade\u0026feature=ai_alerts"},
{"key":"rbac","reason":"Upgrade to Pro when more than one operator needs safe access boundaries around infrastructure changes.","action_url":"https://pulserelay.pro/pricing?utm_source=pulse\u0026utm_medium=app\u0026utm_campaign=upgrade\u0026feature=rbac"},
{"key":"agent_profiles","reason":"Upgrade to Pro to standardize agent behavior across systems without reconfiguring every install by hand.","action_url":"https://pulserelay.pro/pricing?utm_source=pulse\u0026utm_medium=app\u0026utm_campaign=upgrade\u0026feature=agent_profiles"},
+2 -2
View File
@@ -78,8 +78,8 @@ func TestGetFeatureDisplayNameCoversKnownFeaturesAndFallback(t *testing.T) {
want string
}{
{feature: FeatureAIPatrol, want: "Pulse Patrol (Background Health Checks)"},
{feature: FeatureAIAlerts, want: "Patrol Investigates Issues"},
{feature: FeatureAIAutoFix, want: "Patrol Handles Safe Fixes"},
{feature: FeatureAIAlerts, want: "Patrol Investigates Issues and Explains the Root Cause"},
{feature: FeatureAIAutoFix, want: "Patrol Applies Safe Fixes and Verifies the Result"},
{feature: FeatureKubernetesAI, want: "Kubernetes AI Analysis (Compatibility)"},
{feature: FeatureUpdateAlerts, want: "Update Alerts (Container/Package Updates)"},
{feature: FeatureRBAC, want: "Role-Based Access Control (RBAC)"},
+2 -2
View File
@@ -371,8 +371,8 @@ func TestGetFeatureDisplayName(t *testing.T) {
want string
}{
{FeatureAIPatrol, "Pulse Patrol (Background Health Checks)"},
{FeatureAIAlerts, "Patrol Investigates Issues"},
{FeatureAIAutoFix, "Patrol Handles Safe Fixes"},
{FeatureAIAlerts, "Patrol Investigates Issues and Explains the Root Cause"},
{FeatureAIAutoFix, "Patrol Applies Safe Fixes and Verifies the Result"},
{FeatureKubernetesAI, "Kubernetes AI Analysis (Compatibility)"},
{FeatureUpdateAlerts, "Update Alerts (Container/Package Updates)"},
{FeatureRBAC, "Role-Based Access Control (RBAC)"},
+5 -5
View File
@@ -147,8 +147,8 @@ var featureMetadataCatalog = map[string]FeatureMetadata{
},
FeatureAIAlerts: {
Key: FeatureAIAlerts,
DisplayName: "Patrol Investigates Issues",
ComparisonName: "Patrol Investigates Issues",
DisplayName: "Patrol Investigates Issues and Explains the Root Cause",
ComparisonName: "Patrol Investigates Issues and Explains the Root Cause",
ShowInComparisonTable: true,
DisplayableInPlanUI: true,
SelfHostedRoles: SelfHostedFeatureRoles{
@@ -161,8 +161,8 @@ var featureMetadataCatalog = map[string]FeatureMetadata{
},
FeatureAIAutoFix: {
Key: FeatureAIAutoFix,
DisplayName: "Patrol Handles Safe Fixes",
ComparisonName: "Patrol Handles Safe Fixes",
DisplayName: "Patrol Applies Safe Fixes and Verifies the Result",
ComparisonName: "Patrol Applies Safe Fixes and Verifies the Result",
ShowInComparisonTable: true,
DisplayableInPlanUI: true,
SelfHostedRoles: SelfHostedFeatureRoles{
@@ -170,7 +170,7 @@ var featureMetadataCatalog = map[string]FeatureMetadata{
Relay: SelfHostedFeatureRoleHidden,
Pro: SelfHostedFeatureRolePrimaryPillar,
},
UpgradeReason: "Upgrade to Pro so Patrol can investigate issues, handle safe fixes within Patrol mode, and verify the outcome.",
UpgradeReason: "Upgrade to Pro so Patrol can investigate issues, apply safe fixes within Patrol mode, and verify the result.",
UpgradePriority: 3,
},
FeatureKubernetesAI: {
+1 -1
View File
@@ -96,7 +96,7 @@ func TestOperatorOutcomeUpgradeReasonsRemainCanonical(t *testing.T) {
FeatureRelay: "Get Relay so Pulse stays reachable securely from anywhere instead of only on the local dashboard.",
FeatureLongTermMetrics: "Get Relay for 14 days of history, or Pro for 90 days, so you can see what changed before and after an incident.",
FeatureAIAlerts: "Upgrade to Pro so Patrol can investigate issues instead of handing you a stack of symptoms.",
FeatureAIAutoFix: "Upgrade to Pro so Patrol can investigate issues, handle safe fixes within Patrol mode, and verify the outcome.",
FeatureAIAutoFix: "Upgrade to Pro so Patrol can investigate issues, apply safe fixes within Patrol mode, and verify the result.",
}
for _, entry := range UpgradeReasonMatrix {
@@ -535,7 +535,7 @@ test.describe("Self-hosted upgrade return flow", () => {
),
).toBeVisible();
await expect(activationSummary.getByText("Available now on this instance")).toBeVisible();
await expect(activationSummary.getByText("Patrol Handles Safe Fixes")).toBeVisible();
await expect(activationSummary.getByText("Patrol Applies Safe Fixes and Verifies the Result")).toBeVisible();
await expect(page.getByRole("link", { name: "Review usage" })).toHaveCount(0);
await expect(page.getByRole("link", { name: "Review plan" })).toHaveCount(0);
});
@@ -572,7 +572,7 @@ test.describe("Self-hosted upgrade return flow", () => {
page.getByText("Checkout completed and this instance is now running Pulse Pro."),
).toHaveCount(0);
await expect(page.getByText("Current plan: Community")).toBeVisible();
await expect(page.getByText("Patrol Handles Safe Fixes")).toHaveCount(0);
await expect(page.getByText("Patrol Applies Safe Fixes and Verifies the Result")).toHaveCount(0);
await expect.poll(() => requestCounts.inactive.entitlements).toBeGreaterThan(0);
expect(requestCounts.activated.entitlements).toBe(0);
});
@@ -655,7 +655,7 @@ test.describe("Self-hosted upgrade return flow", () => {
),
).toBeVisible();
await expect(activationSummary.getByText("Available now on this instance")).toBeVisible();
await expect(activationSummary.getByText("Patrol Handles Safe Fixes")).toBeVisible();
await expect(activationSummary.getByText("Patrol Applies Safe Fixes and Verifies the Result")).toBeVisible();
await expect(page.getByRole("link", { name: "Review plan" })).toHaveCount(0);
await expect(page.getByRole("link", { name: "Review usage" })).toHaveCount(0);
});