Render clarify search prompts as guidance only

This commit is contained in:
master
2026-03-08 11:50:34 +02:00
parent e01a499df9
commit abbfe64bd7
10 changed files with 224 additions and 124 deletions

View File

@@ -342,6 +342,26 @@ test.describe('Unified Search - Experience Quality UX', () => {
await expect(page.locator('.search__group').filter({ hasText: 'Recent' })).toHaveCount(0);
});
test('renders release clarify guidance as non-executable hints on /releases/versions', async ({ page }) => {
await mockSearchResponses(page, () => emptyResponse('mystery release blocker'));
await page.goto('/releases/versions');
await expect(page.locator('aside.sidebar')).toBeVisible({ timeout: 15_000 });
await typeInSearch(page, 'mystery release blocker');
await waitForResults(page);
await expect(page.locator('[data-answer-status="clarify"]')).toBeVisible();
await expect(page.locator('[data-answer-guidance="clarify"]').filter({
hasText: /add the environment or release you want to inspect\./i,
})).toHaveCount(1);
await expect(page.locator('[data-answer-guidance="clarify"]').filter({
hasText: /add whether you need blockers, approvals, or policy impact\./i,
})).toHaveCount(1);
await expect(page.getByRole('button', { name: 'Add the environment or release you want to inspect.' })).toHaveCount(0);
await expect(page.locator('app-global-search input[type="text"]')).toHaveValue('mystery release blocker');
});
test('uses backend answer framing and shows overflow as secondary results without manual filters', async ({ page }) => {
await mockSearchResponses(page, (query) =>
query.includes('critical findings')

View File

@@ -230,48 +230,6 @@ const doctorGroundedResponse = buildResponse(
},
);
const timelineGroundedResponse = buildResponse(
'Which deployment, incident, or time window should I narrow this to?',
[
timelineCard({
eventId: 'incident-db-spike',
title: 'Database latency spike before promotion',
snippet: 'A deployment preceded the incident and introduced the latency spike that now blocks the rollout.',
}),
],
undefined,
{
contextAnswer: {
status: 'grounded',
code: 'retrieved_scope_weighted_evidence',
summary: 'The timeline shows a deployment immediately before the incident that introduced the blocking latency spike.',
reason: 'Timeline evidence became grounded once the time window was narrowed.',
evidence: 'Grounded in 1 source across Timeline.',
citations: [
{
entityKey: 'timeline:incident-db-spike',
title: 'Database latency spike before promotion',
domain: 'timeline',
},
],
},
coverage: {
currentScopeDomain: 'timeline',
currentScopeWeighted: true,
domains: [
{
domain: 'timeline',
candidateCount: 1,
visibleCardCount: 1,
topScore: 0.9,
isCurrentScope: true,
hasVisibleResults: true,
},
],
},
},
);
const releasesGroundedResponse = buildResponse(
'What blocked this promotion?',
[
@@ -437,7 +395,7 @@ test.describe('Unified Search - Priority Route Self-Serve Journeys', () => {
}).first()).toBeVisible();
});
test('recovers a timeline search from clarify to grounded with the route-owned narrowing question', async ({ page }) => {
test('shows timeline narrowing guidance instead of a runnable clarify prompt', async ({ page }) => {
await mockPriorityRouteSearch(page);
await openRoute(page, '/ops/timeline');
@@ -445,14 +403,12 @@ test.describe('Unified Search - Priority Route Self-Serve Journeys', () => {
await waitForResults(page);
await expect(page.locator('[data-answer-status="clarify"]')).toBeVisible();
await page.getByRole('button', { name: 'Which deployment, incident, or time window should I narrow this to?' }).click();
await waitForResults(page);
await waitForEntityCards(page, 1);
await expect(page.locator('app-global-search input[type="text"]')).toHaveValue(
'Which deployment, incident, or time window should I narrow this to?',
);
await expect(page.locator('[data-answer-status="grounded"]')).toContainText(/deployment immediately before the incident/i);
await expect(page.locator('[data-answer-guidance="clarify"]')).toContainText([
'Add the deployment, incident, or time window you want to inspect.',
'Add whether you need causes, impacts, or follow-up events.',
]);
await expect(page.getByRole('button', { name: 'Add the deployment, incident, or time window you want to inspect.' })).toHaveCount(0);
await expect(page.locator('app-global-search input[type="text"]')).toHaveValue('spike');
});
test('reruns a policy next-search inside the current policy route context', async ({ page }) => {
@@ -557,10 +513,6 @@ function resolvePriorityRouteResponse(currentRoute: string, query: string): unkn
}
if (currentRoute.includes('/ops/timeline')) {
if (query.includes('which deployment, incident, or time window should i narrow this to')) {
return timelineGroundedResponse;
}
if (query.includes('spike')) {
return emptyResponse('spike');
}

View File

@@ -46,25 +46,6 @@ const groundedFindingResponse = {
},
};
const narrowedFindingResponse = buildResponse(
'Which CVE, workload, or package should I narrow this to?',
[
findingCard({
cveId: 'CVE-2023-38545',
title: 'CVE-2023-38545 in edge-router',
snippet: 'A narrowed finding result is now grounded and ready for review.',
severity: 'high',
}),
],
{
summary: 'Narrowing the question exposed a grounded finding answer.',
template: 'finding_overview',
confidence: 'high',
sourceCount: 1,
domainsCovered: ['Findings'],
},
);
test.describe('Unified Search - Self-Serve Answer Panel', () => {
test.beforeEach(async ({ page }) => {
await setupBasicMocks(page);
@@ -103,12 +84,8 @@ test.describe('Unified Search - Self-Serve Answer Panel', () => {
await expect(answerPanel.locator('[data-answer-citation]')).toContainText(['CVE-2024-21626 in api-gateway']);
});
test('uses clarify questions to rerun search and recover a grounded answer', async ({ page }) => {
test('shows clarify guidance without rendering dead clarify prompts as buttons', async ({ page }) => {
await mockSearchResponses(page, (query) => {
if (query.includes('which cve, workload, or package should i narrow this to?')) {
return narrowedFindingResponse;
}
if (query.includes('mystery issue')) {
return emptyResponse('mystery issue');
}
@@ -122,17 +99,18 @@ test.describe('Unified Search - Self-Serve Answer Panel', () => {
await typeInSearch(page, 'mystery issue');
await waitForResults(page);
await expect(page.locator('[data-answer-status="clarify"]')).toBeVisible();
await page.getByRole('button', { name: 'Which CVE, workload, or package should I narrow this to?' }).click();
await waitForResults(page);
await waitForEntityCards(page, 1);
await expect(page.locator('app-global-search input[type="text"]')).toHaveValue(
'Which CVE, workload, or package should I narrow this to?',
);
await expect(page.locator('[data-answer-status="grounded"]')).toContainText(
'Narrowing the question exposed a grounded finding answer.',
);
await expect(
page.locator('[data-answer-guidance="clarify"]').filter({
hasText: /Add the CVE, workload, or package you want to inspect\./i,
}),
).toHaveCount(1);
await expect(
page.locator('[data-answer-guidance="clarify"]').filter({
hasText: /Add the part of the finding that matters most right now\./i,
}),
).toHaveCount(1);
await expect(page.getByRole('button', { name: 'Add the CVE, workload, or package you want to inspect.' })).toHaveCount(0);
await expect(page.locator('app-global-search input[type="text"]')).toHaveValue('mystery issue');
});
test('opens AdvisoryAI from the answer panel with grounded answer context', async ({ page }) => {