Complete self-serve search rollout

This commit is contained in:
master
2026-03-08 08:50:38 +02:00
parent ac22ee3ce2
commit 80257a4538
13 changed files with 1219 additions and 58 deletions

View File

@@ -189,23 +189,21 @@ Each feature folder builds as a **standalone route** (lazy loaded). All HTTP sha
### 3.13 Global Search and Assistant Bridge
* **Search -> assistant handoff**: result cards and synthesis panel expose `Ask AI` actions that route to `/security/triage?openChat=true` and seed chat context through `SearchChatContextService`.
* **Assistant host**: `/security/triage` mounts `SecurityTriageChatHostComponent`, which consumes `openChat` intent deterministically and opens the chat drawer in the primary shell.
* **Assistant -> search return**: assistant responses expose `Search for more` and `Search related` actions; these populate global search query/domain context and focus the search surface.
* **Guided discovery empty state**: when global search is focused with an empty query, the panel renders an 8-domain guide (findings, VEX, policy, docs, API, health, operations, timeline), contextual suggestion chips, and quick actions (`Getting Started`, `Run Health Check`, `View Recent Scans`).
* **Automatic page-open suggestions**: `AmbientContextService` tracks router navigation and updates global-search suggestion chips/placeholders automatically for every opened page without requiring manual refresh.
* **Context rail**: empty-state search also renders a compact rail showing the current page title/description, active domain scope, and last meaningful action on the same page scope when available.
* **Last-action follow-up suggestions**: the same service keeps a per-route scoped last action (search result open/action, Ask AI handoff, chat return actions) with deterministic TTL bounds; empty-state chips prepend a contextual `follow up: ...` suggestion when available.
* **Strategic non-obvious suggestions**: each page scope injects at least one cross-domain guidance query (for example, findings -> policy/VEX impact, policy -> impacted findings, doctor -> release blockers) and switches to action-aware variants after meaningful user actions.
* **Explainable chips**: suggestion queries remain short and executable, while a separate rationale line explains whether a chip comes from page defaults, recent actions, or strategic cross-domain guidance.
* **Shared operator modes**: global search and AdvisoryAI share one persisted mode state (`Find`, `Explain`, `Act`) via `SearchExperienceModeService`; the mode changes chip ordering, Ask-AI prompts, empty-state starters, and structured next-step behavior.
* **Answer-first search**: every non-empty search renders a visible answer panel before raw cards; the panel must resolve to `grounded`, `clarify`, or `insufficient` and never leave the operator with an unexplained blank result area.
* **Page-owned self-serve questions**: priority pages define common questions and clarifying prompts in the shared search context registry; empty-state search uses those as "Common questions" and answer states reuse them as follow-up or clarification buttons.
* **Zero-result rescue loop**: no-result states must expose recovery actions for broadening scope, trying a related pivot, retrying with page context, and opening AdvisoryAI reformulation with the active mode and query context preserved.
* **Search-surface focus rule**: focus movement into controls inside the global-search surface (mode buttons, scope toggle, rescue buttons, filters) must not collapse the panel; the surface behaves like one command workspace rather than a disposable tooltip.
* **AdvisoryAI next-step cards**: assistant responses with citations render structured cards for evidence inspection, context navigation, deeper search, and policy pivots; search-return actions must emit deterministic `chat_next_step_*` metadata back into global search.
* **Ambient payload activation**: each global search request sends ambient context (`currentRoute`, `visibleEntityKeys`, `recentSearches`, `sessionId`, optional `lastAction`) so AdvisoryAI can apply contextual ranking/refinement.
* **Contract governance**: page-owned chip arrays follow `docs/modules/ui/search-chip-context-contract.md`, while answer-first self-serve questions and fallback states follow `docs/modules/ui/search-self-serve-contract.md`; both are implemented in `search-context.registry.ts`.
* **Search-first shell**: the top-bar search field is the primary operator entry. AdvisoryAI is opened from a compact secondary icon beside search or from grounded answer/result actions, not as a competing route-first workflow.
* **Shell-level assistant drawer**: deeper-help opens in a global drawer and keeps the operator on the current page route; focus is restored back to search when the drawer closes.
* **Assistant -> search return**: assistant responses can return the user back into global search with populated query context and deterministic `chat_*` action metadata.
* **Zero-learning empty state**: focused empty-state search renders only current-page context, successful history, and executable starter chips/questions. Domain-teaching cards, scope toggles, and recovery panels are intentionally absent from the primary flow.
* **Automatic page-open suggestions**: `AmbientContextService` tracks router navigation and updates starter chips/placeholders automatically for every opened page without requiring manual refresh.
* **Context rail**: empty-state search renders the current page title plus compact tokens for scope and last meaningful action on the same page scope when available.
* **Last-action follow-up suggestions**: the same service keeps a per-route scoped recent-action history with deterministic TTL bounds; surfaced starters can prepend `follow up: ...` chips when that improves relevance.
* **Implicit route weighting**: global search always prefers current-page evidence first and renders cross-scope overflow as a quiet secondary section only when it materially improves the answer.
* **Answer-first search**: every non-empty search renders a visible answer panel before raw cards; the panel resolves to `grounded`, `clarify`, or `insufficient` and never leaves the operator with a blank result area.
* **Page-owned self-serve questions**: priority pages define common questions and clarifying prompts in the shared search context registry; empty-state search uses those as starter questions and answer states reuse them as follow-up or clarification buttons.
* **Priority route rollout**: mocked end-to-end journeys explicitly cover findings, policy, doctor, timeline, and release-control routes; live ingestion-backed route verification remains required where corpus parity already exists.
* **Suggestion executability gate**: contextual/page starters preflight through backend viability signals before render so dead suggestions are suppressed instead of being taught to the user.
* **Ambient payload activation**: each global search request sends ambient context (`currentRoute`, `visibleEntityKeys`, `recentSearches`, `sessionId`, optional `lastAction`) so AdvisoryAI can apply contextual ranking and answer shaping.
* **Contract governance**: contextual chips follow `docs/modules/ui/search-chip-context-contract.md`, while self-serve questions, rollout ownership, and fallback states follow `docs/modules/ui/search-self-serve-contract.md`; both are implemented in `search-context.registry.ts`.
* **Optional telemetry markers**: global search may emit client-side `search_self_serve_*` markers (`gap`, `reformulation`, `recovery`, `suggestion_suppressed`) for backlog review, but search behavior must remain unchanged when telemetry is disabled or sinks fail.
* **Fallback transparency**: when unified search drops to legacy fallback, global search displays an explicit degraded banner and emits enter/exit telemetry markers for operator visibility.
---

View File

@@ -20,6 +20,22 @@
- concise, operator-facing wording
- no tenant secrets or volatile IDs in fallback copy
## Priority rollout ownership
| Context ID | Route family | Page ownership rule | Verification floor |
| --- | --- | --- | --- |
| `findings` | `/security/triage`, `/security/findings` | Security triage pages own the findings questions and clarifiers. | Mocked Playwright journey + shared search regressions |
| `policy` | `/ops/policy` | Policy workspace owns the questions and recovery prompts for rules, gates, and exceptions. | Mocked Playwright journey + shared search regressions |
| `doctor` | `/ops/operations/doctor`, `/ops/operations/system-health` | Doctor pages own the health-check questions and release-readiness follow-ups. | Mocked Playwright journey + live Doctor route pack |
| `timeline` | `/ops/timeline`, `/audit`, `/evidence/audit-log` | Timeline/Audit pages own time-window clarifiers and causal follow-ups. | Mocked Playwright journey |
| `releases` | `/releases`, `/mission-control` | Release-control pages own approval/blocker/next-step questions. | Mocked Playwright journey |
## Page team checklist
1. Add or update the route entry in `SEARCH_CONTEXT_DEFINITIONS`.
2. Define bounded `commonQuestions[]` and `clarifyingQuestions[]`.
3. Keep copy operator-facing; do not expose Stella internals or scoring jargon.
4. Verify the page still works with telemetry disabled or OTLP unset.
5. Add/update unit coverage for route-specific questions and a Playwright journey for the page family.
## Answer-first UX contract
- Every non-empty search must render one visible answer state before raw results:
- `grounded`
@@ -40,6 +56,22 @@
- `clarifyingQuestions[]` when no grounded answer exists
- "Related searches" remains driven by contextual chip logic so pages do not need to define a second parallel action system.
## Optional telemetry hooks
- Search may emit optional client-side telemetry markers for backlog triage:
- `search_self_serve_gap`
- `search_self_serve_reformulation`
- `search_self_serve_recovery`
- `search_self_serve_suggestion_suppressed`
- These markers are additive only. If telemetry is disabled or the sink is unavailable, search behavior, history, and assistant handoffs must remain unchanged.
- Marker payloads must avoid raw query text. Use route, answer state, counts, and reformulation depth instead.
## Gap review workflow
1. Review repeated `search_self_serve_gap` and `search_self_serve_reformulation` events by route family.
2. Compare them with visible no-result/clarify journeys from Playwright and operator feedback.
3. Update the page-owned question set or starter chips for the affected route.
4. Add or tighten a Playwright journey before marking the gap closed.
5. Record the adjustment in the active sprint `Execution Log` so the change is traceable.
## Source of truth
- Page registry and interfaces:
- `src/Web/StellaOps.Web/src/app/core/services/search-context.registry.ts`
@@ -55,6 +87,7 @@
- grounded answer
- clarify recovery
- answer-to-AdvisoryAI handoff
- priority-route rollout journeys (`findings`, `policy`, `doctor`, `timeline`, `releases`)
4. Keep route and API behavior mocked/deterministic; no live network dependencies.
## Relationship to chip contract

View File

@@ -124,6 +124,8 @@
- Implemented from the operator-correction pass: FE search contracts no longer depend on hidden `Find / Explain / Act` metadata, starter chips wait for backend viability before rendering, `Did you mean` is the first in-panel cue under the search field, and successful recent history now uses a structured `stella-successful-searches-v3` contract that ignores legacy bare-string entries on load.
- Implemented from the final correction pass: the primary surface now uses secondary "deeper help/details" assistant language instead of presenting a separate AdvisoryAI product, overflow results read as supporting context, and starter chips that execute to no useful result are suppressed from the current page until context changes.
- Implemented from the final live verification pass: the supported live route matrix now covers Doctor, Security triage, Policy governance, and Advisories/VEX with corpus rebuild preflight plus end-to-end suggestion execution on ready routes.
- Implemented from the self-serve rollout pass: mocked operator-journey coverage now explicitly covers findings, policy, doctor, timeline, and releases route families end to end, including grounded, clarify, overflow, and deeper-help handoffs.
- Implemented from the self-serve rollout pass: optional browser telemetry markers now capture low-coverage journeys (`gap`, `reformulation`, `recovery`, `suggestion_suppressed`) without changing search behavior when telemetry is disabled.
- Still pending from the corrective phases: an explicit client-side telemetry opt-out control if product needs a visible switch. Current behavior is already failure-tolerant when analytics endpoints or sinks are unavailable.
## Execution phases - operator correction pass