From 8d07089eb3c13f53ff01cbd9d8f837bf475d6db8 Mon Sep 17 00:00:00 2001 From: rcourtman Date: Fri, 10 Jul 2026 12:04:03 +0100 Subject: [PATCH] Finish the Assistant & Patrol settings rename to Pulse Intelligence Commit cc948b022 fixed the Patrol preflight strings that gated keyless onboarding; this sweeps the rest. Error messages, readiness checks, and guidance copy that still pointed at the retired Assistant & Patrol settings page now name the real surfaces: Pulse Intelligence settings for the area as a whole, and the Provider & Models settings page for provider-credential guidance, matching the phrasing cc948b022 established. Pinning tests updated in step, including three ai_handlers_test.go assertions cc948b022 had already left stale. --- .../src/api/__tests__/agentProfiles.test.ts | 6 +++--- frontend-modern/src/api/__tests__/ai.test.ts | 2 +- frontend-modern/src/api/agentProfiles.ts | 2 +- .../components/Settings/useAISettingsState.ts | 6 ++---- internal/agentcapabilities/types.go | 2 +- internal/ai/patrol_findings.go | 2 +- internal/ai/patrol_findings_additional_test.go | 6 +++--- internal/ai/patrol_preflight.go | 4 ++-- internal/ai/patrol_preflight_test.go | 4 ++-- internal/ai/patrol_readiness.go | 2 +- internal/ai/patrol_readiness_test.go | 2 +- internal/ai/patrol_runtime_failure.go | 6 +++--- internal/ai/service.go | 2 +- internal/ai/tools/executor_setters_test.go | 2 +- internal/api/ai_handlers.go | 16 ++++++++-------- internal/api/ai_handlers_test.go | 6 +++--- .../tests/52-ai-settings-provider-setup.spec.ts | 6 +++--- 17 files changed, 37 insertions(+), 39 deletions(-) diff --git a/frontend-modern/src/api/__tests__/agentProfiles.test.ts b/frontend-modern/src/api/__tests__/agentProfiles.test.ts index 88461a308..93f24e85d 100644 --- a/frontend-modern/src/api/__tests__/agentProfiles.test.ts +++ b/frontend-modern/src/api/__tests__/agentProfiles.test.ts @@ -406,7 +406,7 @@ describe('AgentProfilesAPI', () => { const mockResponse = { ok: false, status: 503 } as unknown as Response; vi.mocked(apiFetch).mockResolvedValueOnce(mockResponse); vi.mocked(assertAPIResponseOKOrThrowStatus).mockRejectedValueOnce( - new Error('Pulse Intelligence is not available. Please check Assistant & Patrol settings.'), + new Error('Pulse Intelligence is not available. Please check Pulse Intelligence settings.'), ); await expect(AgentProfilesAPI.suggestProfile({ prompt: 'test' })).rejects.toThrow( @@ -415,7 +415,7 @@ describe('AgentProfilesAPI', () => { expect(assertAPIResponseOKOrThrowStatus).toHaveBeenCalledWith( mockResponse, 503, - 'Pulse Intelligence is not available. Please check Assistant & Patrol settings.', + 'Pulse Intelligence is not available. Please check Pulse Intelligence settings.', 'Failed to get suggestion: 503', ); }); @@ -431,7 +431,7 @@ describe('AgentProfilesAPI', () => { expect(assertAPIResponseOKOrThrowStatus).toHaveBeenCalledWith( mockResponse, 503, - 'Pulse Intelligence is not available. Please check Assistant & Patrol settings.', + 'Pulse Intelligence is not available. Please check Pulse Intelligence settings.', 'Failed to get suggestion: 500', ); }); diff --git a/frontend-modern/src/api/__tests__/ai.test.ts b/frontend-modern/src/api/__tests__/ai.test.ts index 3d278202a..68c4b011c 100644 --- a/frontend-modern/src/api/__tests__/ai.test.ts +++ b/frontend-modern/src/api/__tests__/ai.test.ts @@ -243,7 +243,7 @@ describe('AIAPI', () => { cause: 'provider_auth', summary: 'The provider rejected the configured credentials or account access.', recommendation: - 'Check the API key or provider authentication in Assistant and Patrol settings, then retry.', + 'Check the API key or provider authentication on the Provider & Models settings page, then retry.', action: 'open_provider_settings', }; apiFetchJSONMock.mockResolvedValueOnce(diagnostic as any); diff --git a/frontend-modern/src/api/agentProfiles.ts b/frontend-modern/src/api/agentProfiles.ts index f519363d1..04adaffc9 100644 --- a/frontend-modern/src/api/agentProfiles.ts +++ b/frontend-modern/src/api/agentProfiles.ts @@ -378,7 +378,7 @@ export class AgentProfilesAPI { await assertAPIResponseOKOrThrowStatus( response, 503, - 'Pulse Intelligence is not available. Please check Assistant & Patrol settings.', + 'Pulse Intelligence is not available. Please check Pulse Intelligence settings.', `Failed to get suggestion: ${response.status}`, ); diff --git a/frontend-modern/src/components/Settings/useAISettingsState.ts b/frontend-modern/src/components/Settings/useAISettingsState.ts index 66673ccf9..eceeb3e37 100644 --- a/frontend-modern/src/components/Settings/useAISettingsState.ts +++ b/frontend-modern/src/components/Settings/useAISettingsState.ts @@ -110,13 +110,11 @@ const isGenericAISettingsSaveFailure = (error: unknown): boolean => { const message = error instanceof Error ? error.message.trim().toLowerCase() : ''; if (!message) return true; return ( - message === 'failed to save assistant & patrol settings' || + message === 'failed to save pulse intelligence settings' || message === 'failed to save provider & models settings' || - message === 'unable to save assistant & patrol settings.' || - message === 'unable to save assistant & patrol settings' || message === 'unable to save provider & models settings.' || message === 'unable to save provider & models settings' || - message.includes('failed to save assistant & patrol settings') || + message.includes('failed to save pulse intelligence settings') || message.includes('failed to save provider & models settings') || message.startsWith('request failed with status') ); diff --git a/internal/agentcapabilities/types.go b/internal/agentcapabilities/types.go index 4a242202b..889e0e363 100644 --- a/internal/agentcapabilities/types.go +++ b/internal/agentcapabilities/types.go @@ -27,7 +27,7 @@ const ( // ControlToolsDisabledMessage is the stable operator guidance returned when a // caller attempts to run a control-gated Assistant tool while the shared control // level is read-only or otherwise not allowed to expose control tools. -const ControlToolsDisabledMessage = "Control tools are disabled. Open Assistant & Patrol settings, then set Pulse Assistant Permissions > Control mode to Controlled before using action tools." +const ControlToolsDisabledMessage = "Control tools are disabled. Open Pulse Intelligence settings, then set Pulse Assistant Permissions > Control mode to Controlled before using action tools." // DefaultApprovalPolicyDescription returns a concise operator-facing // explanation for a shared approval-policy value. diff --git a/internal/ai/patrol_findings.go b/internal/ai/patrol_findings.go index dc20d5a97..160d05d80 100644 --- a/internal/ai/patrol_findings.go +++ b/internal/ai/patrol_findings.go @@ -32,7 +32,7 @@ func patrolFindingUsesSyntheticRuntimeResource(f *Finding) bool { func patrolRuntimeFindingManualActionError(action string) error { return fmt.Errorf( - "Patrol runtime findings cannot be %s manually; fix Patrol provider configuration in Assistant & Patrol settings and rerun Patrol", + "Patrol runtime findings cannot be %s manually; fix Patrol provider configuration in Pulse Intelligence settings and rerun Patrol", action, ) } diff --git a/internal/ai/patrol_findings_additional_test.go b/internal/ai/patrol_findings_additional_test.go index 649787336..b8239736e 100644 --- a/internal/ai/patrol_findings_additional_test.go +++ b/internal/ai/patrol_findings_additional_test.go @@ -112,8 +112,8 @@ func TestPatrolService_DismissFinding_RejectsPatrolRuntimeFinding(t *testing.T) if got := err.Error(); !strings.Contains(got, "cannot be dismissed manually") { t.Fatalf("unexpected error: %q", got) } - if got := err.Error(); !strings.Contains(got, "Assistant & Patrol settings") { - t.Fatalf("dismissal guidance must point to Assistant & Patrol settings: %q", got) + if got := err.Error(); !strings.Contains(got, "Pulse Intelligence settings") { + t.Fatalf("dismissal guidance must point to Pulse Intelligence settings: %q", got) } stored := ps.findings.Get("runtime-1") @@ -143,7 +143,7 @@ func TestPatrolService_RejectManualActionForRuntimeFindingUsesProviderSettingsGu t.Fatal("expected Patrol runtime finding manual action to be rejected") } got := err.Error() - if !strings.Contains(got, "fix Patrol provider configuration in Assistant & Patrol settings") { + if !strings.Contains(got, "fix Patrol provider configuration in Pulse Intelligence settings") { t.Fatalf("manual action guidance = %q", got) } if strings.Contains(got, "AI settings") { diff --git a/internal/ai/patrol_preflight.go b/internal/ai/patrol_preflight.go index 7f3bc1c87..2daab3ff6 100644 --- a/internal/ai/patrol_preflight.go +++ b/internal/ai/patrol_preflight.go @@ -118,8 +118,8 @@ func (s *Service) RunPatrolToolPreflight(ctx context.Context, providerName, mode if cfg == nil { result.Cause = PatrolFailureCauseSettingsPersistence - result.Title = "Pulse Patrol: Assistant & Patrol settings unavailable" - result.Summary = "Assistant & Patrol settings could not be loaded" + result.Title = "Pulse Patrol: Pulse Intelligence settings unavailable" + result.Summary = "Pulse Intelligence settings could not be loaded" result.Recommendation = "Confirm Pulse settings persistence is healthy, then re-run preflight." result.DurationMs = time.Since(started).Milliseconds() s.recordPatrolPreflight(result, time.Now()) diff --git a/internal/ai/patrol_preflight_test.go b/internal/ai/patrol_preflight_test.go index 381e70945..cd06b48dc 100644 --- a/internal/ai/patrol_preflight_test.go +++ b/internal/ai/patrol_preflight_test.go @@ -277,10 +277,10 @@ func TestRunPatrolToolPreflight_SettingsUnavailableUsesAssistantPatrolCopy(t *te if result.Cause != PatrolFailureCauseSettingsPersistence { t.Fatalf("unexpected cause %q", result.Cause) } - if result.Title != "Pulse Patrol: Assistant & Patrol settings unavailable" { + if result.Title != "Pulse Patrol: Pulse Intelligence settings unavailable" { t.Fatalf("unexpected title %q", result.Title) } - if result.Summary != "Assistant & Patrol settings could not be loaded" { + if result.Summary != "Pulse Intelligence settings could not be loaded" { t.Fatalf("unexpected summary %q", result.Summary) } } diff --git a/internal/ai/patrol_readiness.go b/internal/ai/patrol_readiness.go index 60a652397..f2233949b 100644 --- a/internal/ai/patrol_readiness.go +++ b/internal/ai/patrol_readiness.go @@ -48,7 +48,7 @@ type PatrolConfigReadiness struct { func EvaluatePatrolConfigReadiness(cfg *config.AIConfig) PatrolConfigReadiness { if cfg == nil { - return patrolConfigReadiness("", "", PatrolReadinessNotReady, PatrolFailureCauseSettingsPersistence, "Assistant & Patrol settings could not be loaded from persistence.") + return patrolConfigReadiness("", "", PatrolReadinessNotReady, PatrolFailureCauseSettingsPersistence, "Pulse Intelligence settings could not be loaded from persistence.") } if !cfg.Enabled { return patrolConfigReadiness("", "", PatrolReadinessNotReady, PatrolFailureCauseAssistantDisabled, "Pulse Intelligence is turned off, so Patrol cannot run.") diff --git a/internal/ai/patrol_readiness_test.go b/internal/ai/patrol_readiness_test.go index a9b1ced2b..8e7e1ac84 100644 --- a/internal/ai/patrol_readiness_test.go +++ b/internal/ai/patrol_readiness_test.go @@ -145,7 +145,7 @@ func TestEvaluatePatrolConfigReadiness_NilConfigUsesAssistantPatrolSettingsCopy( if readiness.Cause != PatrolFailureCauseSettingsPersistence { t.Fatalf("cause = %q, want %q", readiness.Cause, PatrolFailureCauseSettingsPersistence) } - if readiness.Summary != "Assistant & Patrol settings could not be loaded from persistence." { + if readiness.Summary != "Pulse Intelligence settings could not be loaded from persistence." { t.Fatalf("summary = %q", readiness.Summary) } } diff --git a/internal/ai/patrol_runtime_failure.go b/internal/ai/patrol_runtime_failure.go index dbc2ac1df..4b8879301 100644 --- a/internal/ai/patrol_runtime_failure.go +++ b/internal/ai/patrol_runtime_failure.go @@ -10,7 +10,7 @@ import ( ) const patrolRuntimeFailureDetailLimit = 2000 -const patrolProviderNotConfiguredReason = "Patrol provider not configured - open Assistant & Patrol provider settings, configure a provider, and choose a Patrol model that supports tools" +const patrolProviderNotConfiguredReason = "Patrol provider not configured - open Pulse Intelligence settings, configure a provider, and choose a Patrol model that supports tools" var patrolRuntimeFailureDetailRedactors = []struct { pattern *regexp.Regexp @@ -181,12 +181,12 @@ func ClassifyProviderConnectionFailure(err error) PatrolRuntimeFailureDiagnostic diagnostic.Title = "Provider authentication issue" diagnostic.Summary = "Provider authentication issue" diagnostic.Description = "The provider rejected the configured credentials or account access." - diagnostic.Recommendation = "Check the API key or provider authentication in Assistant and Patrol settings, then retry." + diagnostic.Recommendation = "Check the API key or provider authentication on the Provider & Models settings page, then retry." case PatrolFailureCauseProviderNotConfigured, PatrolFailureCauseModelNotSelected, PatrolFailureCauseModelProviderUnconfigured, PatrolFailureCauseAssistantDisabled, PatrolFailureCauseSettingsPersistence: diagnostic.Title = "Provider not ready" diagnostic.Summary = "Provider not ready" diagnostic.Description = "Pulse cannot test this provider because the provider runtime is not ready." - diagnostic.Recommendation = "Open Assistant and Patrol provider settings, complete provider configuration, verify the selected model, and retry." + diagnostic.Recommendation = "Open the Provider & Models settings page, complete provider configuration, verify the selected model, and retry." } return diagnostic diff --git a/internal/ai/service.go b/internal/ai/service.go index fddf60f66..939737669 100644 --- a/internal/ai/service.go +++ b/internal/ai/service.go @@ -1033,7 +1033,7 @@ func (s *Service) patrolConfigFromAIConfig(cfg *config.AIConfig) PatrolConfig { patrolCfg := DefaultPatrolConfig() if cfg == nil { patrolCfg.Enabled = false - patrolCfg.RuntimeBlockedReason = "Assistant & Patrol settings could not be loaded from persistence." + patrolCfg.RuntimeBlockedReason = "Pulse Intelligence settings could not be loaded from persistence." patrolCfg.RuntimeBlockedCause = PatrolFailureCauseSettingsPersistence return patrolCfg } diff --git a/internal/ai/tools/executor_setters_test.go b/internal/ai/tools/executor_setters_test.go index 519deb31b..1f17f3bec 100644 --- a/internal/ai/tools/executor_setters_test.go +++ b/internal/ai/tools/executor_setters_test.go @@ -317,7 +317,7 @@ func TestToolRegistry_ExecuteControlToolReadOnlyUsesAssistantAndPatrolGuidance(t require.Len(t, result.Content, 1) text := result.Content[0].Text assert.Equal(t, agentcapabilities.ControlToolsDisabledMessage, text) - assert.Contains(t, text, "Assistant & Patrol settings") + assert.Contains(t, text, "Pulse Intelligence settings") assert.Contains(t, text, "Pulse Assistant Permissions > Control mode") assert.NotContains(t, text, "Settings > Pulse Assistant") } diff --git a/internal/api/ai_handlers.go b/internal/api/ai_handlers.go index fc38a6486..07569c453 100644 --- a/internal/api/ai_handlers.go +++ b/internal/api/ai_handlers.go @@ -2571,8 +2571,8 @@ func (h *AISettingsHandler) HandleGetAISettings(w http.ResponseWriter, r *http.R ctx := r.Context() settings, err := h.loadAIConfig(ctx) if err != nil { - log.Error().Err(err).Msg("Failed to load Assistant & Patrol settings") - http.Error(w, "Failed to load Assistant & Patrol settings", http.StatusInternalServerError) + log.Error().Err(err).Msg("Failed to load Pulse Intelligence settings") + http.Error(w, "Failed to load Pulse Intelligence settings", http.StatusInternalServerError) return } @@ -3029,7 +3029,7 @@ func (h *AISettingsHandler) HandleUpdateAISettings(w http.ResponseWriter, r *htt // Save settings if err := h.getPersistence(r.Context()).SaveAIConfig(*settings); err != nil { log.Error().Err(err).Msg("Failed to save AI settings") - writeErrorResponse(w, http.StatusInternalServerError, "ai_settings_save_failed", "Failed to save Assistant & Patrol settings", nil) + writeErrorResponse(w, http.StatusInternalServerError, "ai_settings_save_failed", "Failed to save Pulse Intelligence settings", nil) return } @@ -3257,8 +3257,8 @@ func newAIProviderTestNotConfiguredResponse(provider string) aiProviderTestRespo Message: "Provider not configured", Provider: provider, Cause: string(ai.PatrolFailureCauseProviderNotConfigured), - Summary: "Pulse cannot test this provider because it is not configured for the current Assistant and Patrol settings.", - Recommendation: "Open Assistant and Patrol provider settings, configure the provider credentials or base URL, choose a model, and retry.", + Summary: "Pulse cannot test this provider because it is not configured for the current Pulse Intelligence settings.", + Recommendation: "Open the Provider & Models settings page, configure the provider credentials or base URL, choose a model, and retry.", Action: "open_provider_settings", } } @@ -4981,7 +4981,7 @@ func (h *AISettingsHandler) HandleOAuthDisconnect(w http.ResponseWriter, r *http } settings, err := h.loadAIConfig(r.Context()) if err != nil { - log.Error().Err(err).Msg("Failed to load Assistant & Patrol settings for OAuth disconnect") + log.Error().Err(err).Msg("Failed to load Pulse Intelligence settings for OAuth disconnect") http.Error(w, "Failed to load settings", http.StatusInternalServerError) return } @@ -5109,10 +5109,10 @@ func (h *AISettingsHandler) buildPatrolReadiness(ctx context.Context, aiService cfg, err := h.loadAIConfig(ctx) if err != nil || cfg == nil { - addCheck("settings", patrolReadinessNotReady, ai.PatrolFailureCauseSettingsPersistence, "Settings persistence", "Assistant & Patrol settings could not be loaded from persistence.", "open_provider_settings") + addCheck("settings", patrolReadinessNotReady, ai.PatrolFailureCauseSettingsPersistence, "Settings persistence", "Pulse Intelligence settings could not be loaded from persistence.", "open_provider_settings") return summarizePatrolReadiness("", "", checks) } - addCheck("settings", patrolReadinessReady, ai.PatrolFailureCauseNone, "Settings persistence", "Assistant & Patrol settings are readable.", "") + addCheck("settings", patrolReadinessReady, ai.PatrolFailureCauseNone, "Settings persistence", "Pulse Intelligence settings are readable.", "") if !cfg.Enabled { addCheck("enabled", patrolReadinessNotReady, ai.PatrolFailureCauseAssistantDisabled, "Assistant enabled", "Pulse Intelligence is turned off, so Patrol cannot run.", "open_provider_settings") diff --git a/internal/api/ai_handlers_test.go b/internal/api/ai_handlers_test.go index bff7ec26f..c025b4b48 100644 --- a/internal/api/ai_handlers_test.go +++ b/internal/api/ai_handlers_test.go @@ -414,7 +414,7 @@ func TestAISettingsHandler_PatrolReadinessBranches(t *testing.T) { wantReady: false, wantCheckID: "enabled", wantCheck: patrolReadinessNotReady, - wantSummary: "disabled", + wantSummary: "turned off", configure: func(aiCfg *config.AIConfig) { aiCfg.Enabled = false aiCfg.Model = "ollama:llama3" @@ -1634,7 +1634,7 @@ func TestAISettingsHandler_TestConnection_NoConfig(t *testing.T) { assert.False(t, resp.Success) assert.Equal(t, "Provider not ready", resp.Message) assert.Equal(t, string(ai.PatrolFailureCauseProviderNotConfigured), resp.Cause) - assert.Contains(t, resp.Recommendation, "provider settings") + assert.Contains(t, resp.Recommendation, "Provider & Models settings page") } // ======================================== @@ -1728,7 +1728,7 @@ func TestAISettingsHandler_TestProvider_NoAIConfig(t *testing.T) { assert.Equal(t, "Provider not configured", resp.Message) assert.Equal(t, "ollama", resp.Provider) assert.Equal(t, string(ai.PatrolFailureCauseProviderNotConfigured), resp.Cause) - assert.Contains(t, resp.Recommendation, "provider settings") + assert.Contains(t, resp.Recommendation, "Provider & Models settings page") assert.Equal(t, "open_provider_settings", resp.Action) } diff --git a/tests/integration/tests/52-ai-settings-provider-setup.spec.ts b/tests/integration/tests/52-ai-settings-provider-setup.spec.ts index c152a3691..4c67f2b85 100644 --- a/tests/integration/tests/52-ai-settings-provider-setup.spec.ts +++ b/tests/integration/tests/52-ai-settings-provider-setup.spec.ts @@ -51,7 +51,7 @@ const baseSettings = (): MockAISettings => ({ available_models: [], }); -test.describe("Assistant & Patrol settings provider setup", () => { +test.describe("Pulse Intelligence settings provider setup", () => { test("OpenRouter setup submits credentials without a hardcoded model and renders backend-selected state", async ({ page, }, testInfo) => { @@ -355,7 +355,7 @@ test.describe("Assistant & Patrol settings provider setup", () => { status: 500, contentType: "application/json", body: JSON.stringify({ - error: "Unable to save Assistant & Patrol settings.", + error: "Failed to save Pulse Intelligence settings", }), }); }); @@ -379,7 +379,7 @@ test.describe("Assistant & Patrol settings provider setup", () => { await expect.poll(() => updateHits).toBe(1); const failureMessage = page.getByText( - /OpenRouter provider.*Provider authentication issue.*Unable to save Assistant & Patrol settings/i, + /OpenRouter provider.*Provider authentication issue.*Failed to save Pulse Intelligence settings/i, ); await expect(failureMessage).toBeVisible(); await expect(failureMessage).toContainText(