# Search — Improvement & Growth Plan

> Package: capell-app/search · Kind: package · Tier: premium · Product group: Capell Search & SEO · Bundle: search-seo · Status: Complete

## 1. Snapshot

`capell-app/search` adds a public frontend search surface (`GET /search`, autocomplete JSON, click-tracking beacon) plus an admin analytics layer (Top/Trending/Zero-result widgets, three overview stats, a settings page). Domain logic lives entirely in `src/Actions` behind a `Capell\Search\Contracts\Search` driver contract with three implementations: `DatabaseSearch` (LIKE/FULLTEXT over a flat table, default `pages`), `SiteDiscoverySearch` (canonical-URL registry metadata), and `ScoutSearch` (multi-source Scout). Key Actions: `RunSearchAction` (orchestrator), `ResolveExpandedSearchQueriesAction` (synonyms + Levenshtein/explicit typo correction), `ApplySearchResultEnhancementsAction` (promotions, source weighting, exact-match/recency/click boosts), `SanitizeSearchResultAction` (URL + meta scrubbing), `RecordSearchAction` (hashed query logging). One table `search_logs` (model `SearchLog`), one settings class `SearchSettings`, one command `search:purge` (scheduled monthly). Runtime deps are light: `lorisleiva/laravel-actions`, `spatie/laravel-data`, `spatie/laravel-package-tools`; Scout/Typesense and `capell-app/site-discovery` are `suggest`-only.

Current marketplace summary: _"Production-grade site search for Capell — relevance-tuned results with synonyms, typo tolerance, and curated promotions, plus admin insights into what visitors search for and where you have no answers."_ Manifest now declares the extension card, frontend search results, header search, settings, top-searches, trending-searches, zero-result widget captures in light and dark mode, plus an annotated curation screenshot for synonyms, typo corrections, and promoted results.

## 2. Improvements (existing functionality)

Prioritized; effort S/M/L.

1. **Done — Fix the outdated `Search` contract example in docs** — `docs/drivers-and-logging.md` "Swap the Search Driver" now imports `SearchFilterData`, shows the full six-argument `Search::search()` signature (`$siteId, $languageId, $filters`), and demonstrates a public-safe escaping `highlight()` implementation. Evidence: `docs/drivers-and-logging.md`, `src/Contracts/Search.php`. — **Shipped**

2. **Shipped: expanded query search is bounded and first-page only.** `RunSearchAction` now caps synonym/typo expansion breadth through `capell-search.query_expansion.max_queries` and uses the primary driver’s native paginator for page 2+ instead of refetching `perPage * page` rows for every expanded query. First-page expansion still merges and de-dupes the bounded result window; deeper pages keep accurate driver totals/current page state and avoid multiplicative DB/Scout round-trips. Evidence: `config/capell-search.php`, `src/Actions/RunSearchAction.php`, `tests/Feature/Actions/SearchFeatureGapSliceTest.php`. — **M**

3. **Shipped: click-count boosts use scoped cache and a collapsed enhancement pass.** `ApplySearchResultEnhancementsAction` now caches `clicked_result_url` aggregates behind a short TTL scoped by site/language, invalidates affected scopes when clicks are recorded, and applies type labels, weights, exact-match, recency, and click boosts in one enhancement pass after promotion de-dupe/sanitization. Evidence: `src/Actions/ApplySearchResultEnhancementsAction.php`, `src/Actions/RecordSearchResultClickAction.php`, `tests/Feature/Actions/SearchFeatureGapSliceTest.php`. — **M**

4. **Shipped: public result Blade receives hydrated highlight data.** `SearchController` resolves the configured `Search` driver, builds `highlightedResults`, and passes that hydrated collection into the public result view; `resources/views/components/results.blade.php` no longer resolves `Search` from Blade. Evidence: `src/Http/Controllers/SearchController.php`, `resources/views/components/results.blade.php`, `tests/Feature/Http/SearchControllerTest.php`. — **M**

5. **Shipped: `DatabaseSearch::canUseFullText()` memoizes schema detection per connection/table/column set.** The `information_schema.STATISTICS` lookup now runs once per compatible driver/database/table/column combination and caches both positive and fallback results. Evidence: `src/Drivers/DatabaseSearch.php`, `tests/Unit/Search/DatabaseSearchTest.php`. — **S/M**

6. **Shipped: FULLTEXT index matching now accepts covering indexes regardless of order.** Configured search columns only need to be present in one FULLTEXT index, so indexes with additional columns or different ordering no longer silently fall back to LIKE; incomplete indexes still fall back. Evidence: `src/Drivers/DatabaseSearch.php`, `tests/Unit/Search/DatabaseSearchTest.php`. — **M**

7. **Shipped: autocomplete uses a lightweight driver path.** `RunAutocompleteSearchAction` now calls the configured `Search` driver directly with normalized query, filters, site, and language, then applies only cheap response mapping/type-label hydration. It skips promotions, click-count aggregates, recency boosts, and the rest of `RunSearchAction`'s enhancement pipeline for keystroke traffic. Evidence: `src/Actions/RunAutocompleteSearchAction.php`, `tests/Feature/Http/SearchControllerTest.php`. Query-suggestion UX remains a separate §3 roadmap item. — **M**

8. **Shipped: result type labels resolve through translations with config overrides.** The default config no longer ships hardcoded English labels; `ResolveSearchResultTypeLabelAction` honors site-configured labels first, then `capell-search::types.*`, then a headline fallback for unknown types. Search results and autocomplete both use the same resolver. Evidence: `src/Actions/ResolveSearchResultTypeLabelAction.php`, `resources/lang/en/types.php`, `src/Actions/ApplySearchResultEnhancementsAction.php`, `src/Actions/RunAutocompleteSearchAction.php`, `tests/Feature/Actions/ResolveSearchResultTypeLabelActionTest.php`. — **S/M**

9. **Shipped: click tracking uses a token-first log match.** `GenerateSearchClickTokenAction` emits an encrypted per-render token with normalized query/site/language context, result links echo it through the beacon, and `RecordSearchResultClickAction` resolves the latest matching log from the token before falling back to the legacy visitor tuple. Proxy IP or user-agent churn no longer drops result-page clicks, while old markup/autocomplete payloads remain compatible. Evidence: `src/Actions/GenerateSearchClickTokenAction.php`, `src/Actions/RecordSearchResultClickAction.php`, `resources/views/components/results.blade.php`, `tests/Feature/Actions/RecordSearchActionTest.php`, `tests/Feature/Http/SearchControllerTest.php`. — **M**

10. **Shipped curation UI; advanced ranking/driver tuning remains config-only.** `SearchSettingsSchema` now exposes synonyms, typo corrections/terms, typo max distance, and promoted results as admin-editable runtime settings. Source weights, ranking boosts, database column mapping, and database column weights still live in `config/capell-search.php`; those lower-level tuning knobs can remain a later admin polish item. Evidence: `src/Filament/Settings/SearchSettingsSchema.php`, `src/Settings/SearchSettings.php`, `config/capell-search.php`, `tests/Unit/Filament/SearchSettingsSchemaTest.php`, `tests/Feature/Actions/SearchCurationSettingsTest.php`. — **L**

## 3. Missing Features (gaps)

Tied to `capabilities[]` (`search`, `search-admin/console/frontend`, `search-synonyms`, `search-promoted-results`, `search-typo-corrections`, `search-source-weighting`, `search-zero-result-reporting`, `search-site-discovery-indexing`) and search-category norms.

- **Shipped: faceted filtering UI with live counts.** `BuildSearchFacetGroupsAction` builds type/source facet groups from enabled searchable sources, computes counts through the configured `Search` driver with the active site/language/filter context, and `pages/search.blade.php` renders neutral public filter links before results. Evidence: `src/Actions/BuildSearchFacetGroupsAction.php`, `src/Data/SearchFacetGroupData.php`, `src/Data/SearchFacetOptionData.php`, `resources/views/components/facets.blade.php`, `resources/views/pages/search.blade.php`, `tests/Feature/Actions/SearchFacetGroupsActionTest.php`, `tests/Feature/Http/SearchControllerTest.php`.
- **Shipped: admin settings manage synonyms, promoted results, and typo dictionaries.** `SearchSettingsSchema` now exposes curation controls for synonyms, explicit typo corrections, typo dictionary terms/max distance, and promoted best-bet results. The curation actions read persisted `SearchSettings` through `ResolveSearchSettingAction` before config fallbacks, so admin changes affect runtime behavior. Evidence: `src/Filament/Settings/SearchSettingsSchema.php`, `src/Settings/SearchSettings.php`, `src/Actions/ResolveExpandedSearchQueriesAction.php`, `src/Actions/ResolveCorrectedSearchQueryAction.php`, `src/Actions/ResolvePromotedSearchResultsAction.php`, `tests/Unit/Filament/SearchSettingsSchemaTest.php`, `tests/Feature/Actions/SearchCurationSettingsTest.php`.
- **Shipped: zero-result terms can become persisted curation rules.** `CreateSynonymFromZeroResultSearchAction` turns a zero-result query into a synonym alias for an existing target query, and `CreatePromotedResultFromZeroResultSearchAction` creates or replaces a promoted best-bet result for that zero-result query. Both update `SearchSettings`, so the existing expansion/promotion runtime consumes the fix immediately. Evidence: `src/Actions/CreateSynonymFromZeroResultSearchAction.php`, `src/Actions/CreatePromotedResultFromZeroResultSearchAction.php`, `tests/Feature/Actions/ZeroResultCurationActionsTest.php`.
- **Shipped: autocomplete includes query suggestions from search logs.** `BuildAutocompleteQuerySuggestionsAction` returns popular normalized-query completions by prefix, scoped by site/language, and `RunAutocompleteSearchAction` exposes them as `querySuggestions` alongside result hits. The header autocomplete renders query suggestions before result rows. Evidence: `src/Actions/BuildAutocompleteQuerySuggestionsAction.php`, `src/Data/AutocompleteQuerySuggestionData.php`, `src/Actions/RunAutocompleteSearchAction.php`, `resources/views/components/header/search-dialog.blade.php`, `tests/Feature/Actions/SearchSuggestionActionsTest.php`, `tests/Feature/Http/SearchControllerTest.php`.
- **Shipped: did-you-mean correction metadata is surfaced.** `ResolveCorrectedSearchQueryAction` resolves explicit and dictionary typo corrections, `RunAutocompleteSearchAction` exposes `metadata.corrected`, and the header autocomplete renders the corrected query as a selectable suggestion. Evidence: `src/Actions/ResolveCorrectedSearchQueryAction.php`, `src/Data/SearchQueryMetadataData.php`, `resources/views/components/header/autocomplete-results.blade.php`, `tests/Feature/Actions/SearchSuggestionActionsTest.php`, `tests/Feature/Http/SearchControllerTest.php`.
- **Shipped: Scout honors engine scores and totals where available.** `ScoutSearch` now reads common engine relevance fields (`_rankingScore`, `_score`, `scout_score`, `text_match`) before falling back to its local substring score, and preserves Scout paginator totals when the engine reports more matches than the fetched window. Public visibility filtering still shrinks totals when hidden payloads are dropped locally. Evidence: `src/Drivers/ScoutSearch.php`, `tests/Unit/Search/ScoutSearchTest.php`.
- **Shipped: Scout index maintenance commands and freshness ownership docs.** `search:index` imports enabled Scout-backed searchable sources via `makeAllSearchable()` using the configured/default chunk size, and `search:flush` removes configured sources via `removeAllFromSearch()`. Both commands support `--source` for targeted maintenance, are listed in `capell.json`, and `docs/drivers-and-logging.md` now documents that source packages own public payloads, observers, queue setup, and external index freshness. Evidence: `src/Actions/IndexScoutSearchSourcesAction.php`, `src/Actions/FlushScoutSearchSourcesAction.php`, `src/Console/Commands/IndexSearchCommand.php`, `src/Console/Commands/FlushSearchCommand.php`, `docs/drivers-and-logging.md`, `tests/Feature/Actions/SearchScoutMaintenanceActionsTest.php`, `tests/Feature/Console/SearchScoutMaintenanceCommandsTest.php`.
- **Shipped: Database fallback ranking supports field weights.** `DatabaseSearch` now accepts `capell-search.database.column_weights` and orders `LIKE` fallback results by a generated `search_score`, so title/excerpt/body relevance can be tuned without a custom driver. Global boosts (exact, recency, click) remain config scalars, and Scout delegates field relevance to the engine/source config. Evidence: `config/capell-search.php`, `src/Drivers/DatabaseSearch.php`, `src/Providers/SearchServiceProvider.php`, `tests/Unit/Search/DatabaseSearchTest.php`.
- **Shipped: runtime health probes cover driver resolution and search-log writes.** `SearchHealthCheck` verifies the configured `Search` driver resolves, the search log table exists, `SearchLog` is registered, a synthetic query-log write/delete succeeds, and logging configuration is sane. Evidence: `src/Health/SearchHealthCheck.php`, `tests/Feature/Health/SearchHealthCheckTest.php`.

## 4. Issues / Risks

- **Runtime health probe now covers local failures.** `SearchHealthCheck` now runs diagnostics for storage table presence, model registration, configured driver resolution, synthetic log write/delete, and logging configuration. — `src/Health/SearchHealthCheck.php`
- **Shipped guardrail — Site Discovery is now the safe default driver.** New installs default to `site_discovery` through config, settings defaults, settings migration, and provider fallback, so the package searches Capell's canonical public URL registry instead of assuming public page content lives in flat `pages.title/excerpt/body` columns. The database driver remains available as an explicit opt-in for flat index tables/views. Evidence: `config/capell-search.php`, `src/Settings/SearchSettings.php`, `database/settings/2026_05_10_190869_01_add_search_settings.php`, `src/Providers/SearchServiceProvider.php`, `tests/Feature/Providers/SearchServiceProviderTest.php`, `docs/drivers-and-logging.md`.
- **Shipped guardrail — Scout drops common non-public payload markers.** `ScoutSearch` now filters indexed payloads marked draft, unpublished, private, restricted, or non-public before mapping public results, and focused tests cover those leak paths. Model-specific `toSearchableArray()` implementations should still avoid indexing sensitive fields, and site/language scoping remains best-effort through Scout `where()` support. Evidence: `src/Drivers/ScoutSearch.php`, `tests/Unit/Search/ScoutSearchTest.php`.
- **Shipped guardrail — public result meta is now explicit allow-list output.** `SanitizeSearchResultAction::safeMeta()` only preserves keys listed in `capell-search.public_urls.allowed_meta_keys` and drops nested object/array payloads, so internal IDs, owner references, admin URLs, signed preview tokens, and arbitrary model metadata cannot ride through `SearchResultData->meta`. URL sanitization blocks configured private path prefixes and strips signed/preview query keys. Evidence: `config/capell-search.php`, `src/Actions/SanitizeSearchResultAction.php`, `tests/Feature/Actions/SanitizeSearchResultActionTest.php`.
- **Shipped guardrail — `highlight()` must escape before adding markup.** `results.blade.php:53-57` prints `{!! $search->highlight(...) !!}`. All three built-in drivers `htmlspecialchars`/`e()` the text before wrapping `<mark>`, tests assert escaping, and `src/Contracts/Search.php` now documents that custom implementations must escape the full input text and only add trusted `<mark>` markup. Evidence: `src/Contracts/Search.php`, `docs/drivers-and-logging.md`, `tests/Unit/Search/DatabaseSearchTest.php`, `tests/Unit/Search/ScoutSearchTest.php`, `tests/Unit/Search/SiteDiscoverySearchTest.php`.
- **Shipped: click-tracking beacon no longer depends on cached-page CSRF state.** `search/click` is now explicitly CSRF-exempt and throttled through `capell-search.click_tracking.rate_limiter`; the header and result click beacons post without a meta CSRF token, and the result component owns a guarded beacon listener so search-result pages still track clicks when the header search modal is absent. Evidence: `routes/web.php`, `config/capell-search.php`, `resources/views/components/header/search-dialog.blade.php`, `resources/views/components/results.blade.php`, `tests/Feature/Http/SearchControllerTest.php`.
- **Shipped guardrail — search log writes are deferred after response.** `capell.json` sets `frontendRenderBudgetMs: 20` and `adminQueryBudget: 40`. The frontend path still does driver query work, but expanded queries are bounded/first-page only, click-count aggregates are cached per site/language, and the analytics insert is no longer inline: `SearchController` now calls `RecordSearchAction::dispatchAfterResponse()` with scalar visitor metadata, and `RecordSearchAction` still owns the actual write. Evidence: `src/Http/Controllers/SearchController.php`, `src/Actions/RecordSearchAction.php`, `tests/Feature/Http/SearchControllerTest.php`, `tests/Feature/Actions/RecordSearchActionTest.php`, `tests/Feature/Actions/SearchFeatureGapSliceTest.php`. `cacheSafety.cacheable=false` is correct (per-query).
- **Shipped i18n guardrail — Site Discovery titles flow into Search.** Result type labels resolve through translations/config overrides, root URL titles translate through `capell-search::generic.site_discovery_home_title`, and `SiteDiscoverySearch` now prefers `PublicUrlRegistryEntryData::title` before deriving a slug title. The core CMS Site Discovery contributor passes localized discoverable page titles into the registry, and non-CMS Blog, Events, Knowledge Base, and Campaign Studio public URL contributors now populate `PublicUrlData::title` from their localized/model titles. Evidence: `packages/site-discovery/src/Data/PublicUrlData.php`, `packages/site-discovery/src/Data/PublicUrlRegistryEntryData.php`, `packages/site-discovery/src/Support/PublicUrls/CmsPagePublicUrlContributor.php`, `packages/blog/src/Support/PublicUrls/BlogPublicUrlContributor.php`, `packages/events/src/Support/PublicUrls/EventsPublicUrlContributor.php`, `packages/knowledge-base/src/Support/PublicUrls/KnowledgeBasePublicUrlContributor.php`, `packages/campaign-studio/src/Support/PublicUrls/CampaignLandingPagePublicUrlContributor.php`, `src/Drivers/SiteDiscoverySearch.php`, `tests/Unit/Search/SiteDiscoverySearchTest.php`, `packages/site-discovery/tests/Integration/Discovery/PublicUrlRegistryActionTest.php`.
- **Test coverage — covered:** `DatabaseSearch` (escape, clamp, site/lang/status filter, pagination, highlight, FULLTEXT index compatibility), `ScoutSearch` (registry merge, weight, absolute URL, highlight) via in-memory fakes, `SiteDiscoverySearch` (indexability, metadata match, paginate/highlight), `RecordSearchAction`/`RecordSearchResultClickAction`, `PurgeSearchLogsAction`, `ResolveExpandedSearchQueries` (synonyms + typos), `ApplySearchResultEnhancements` (promotions + weights + dedupe), `RunSearchAction` (synonym dedupe), `SearchController` (autocomplete limits, blank query, normalized passthrough, configured-page view, frontend-shell view, click POST endpoint, click rate limiter, "no package identifiers in markup"), click-beacon route CSRF exemption and tokenless header/results markup, provider binding/driver selection, settings defaults, manifest requirements, generated-output coverage source, insights actions, widgets, and non-CMS Site Discovery title propagation.
- **Manifest alignment shipped.** `BuildTopClickedResultsQueryAction` is now listed in `capell.json` `actions[]` and covered by `ManifestRequirementsTest`; `drivers-and-logging.md` now lists `site_discovery` as a first-class driver.

## 5. Marketplace & Selling

**Shipped copy refresh.** `composer.json`, `capell.json`, and `resources/lang/en/package.php` now lead with the production search value proposition instead of the old feature-dump copy. Evidence: composer description _"Production-grade site search for Capell with relevance-tuned results, synonyms, typo tolerance, curated promotions, and admin search insights."_ Marketplace summary _"Production-grade site search for Capell — relevance-tuned results with synonyms, typo tolerance, and curated promotions, plus admin insights into what visitors search for and where you have no answers."_

**Improved one-sentence summary:**

> Production-grade site search for Capell — relevance-tuned results with synonyms, typo tolerance, and curated promotions, plus admin insights into what visitors search for and where you have no answers.

**Improved 3–4 sentence description:**

> Search gives every Capell site a fast, themeable search experience: a results page, header search field, and type-ahead autocomplete, backed by a pluggable driver contract (database, Site Discovery URL registry, or Laravel Scout/Meilisearch/Typesense). Curate results with synonyms, typo corrections, and promoted "best bet" answers, and tune ranking with source weighting plus exact-match, recency, and click-through boosts. The admin dashboard surfaces top searches, trending terms, and — critically — zero-result queries, so editors see exactly where content is missing. Privacy-first by default: visitor identifiers are hashed and query logs auto-purge on a configurable retention window.

**Shipped screenshot/media promotion.** `capell.json.marketplace.screenshots` now promotes the extension card plus frontend search, header search, search settings, top-searches, trending-searches, zero-result widget captures in light and dark mode, and an annotated curation screenshot for synonyms, typo corrections, and promoted results.

**Pricing / tier / bundle positioning.** `premium` tier in the `search-seo` bundle is right: search + SEO is a natural "growth" pairing. Position Search as the **demand-side** half (what visitors look for) against `seo-suite` as the **supply-side** half (how content is found by engines). Cross-sell is already wired: `suggest` lists `capell-app/site-discovery` (URL-registry indexing + generated-output coverage) and `docs/README.md` "Read Next" points at `seo-suite` and `site-discovery`. Make the bundle explicit: **Search + SEO Suite + Site Discovery = "Findability"**. Zero-result analytics is the upsell hook into content strategy because zero-result terms can become synonyms or promoted best-bet results.

**Differentiators / value props / target buyer.** Differentiators vs. table-stakes CMS search: (1) editable result _curation_ (synonyms, promotions, typo dictionaries) — most CMS search can't do this; (2) zero-result + trending analytics that turn search into a content-strategy signal; (3) driver-agnostic contract so a site starts on DB search and graduates to Typesense without touching the frontend. Target buyer: agencies and content teams running multi-site Capell installs who treat on-site search as a conversion/retention surface, not a checkbox.

**Keywords/tags (8–12):** `site search`, `full-text search`, `laravel scout`, `meilisearch`, `typesense`, `autocomplete`, `synonyms`, `typo tolerance`, `search analytics`, `zero-result tracking`, `promoted results`, `faceted search`.

## 6. Prioritized Roadmap

| Item                                                                                                                                                                                                                                                                                                                                            | Bucket | Effort | Impact                             | Section ref |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ------ | ---------------------------------- | ----------- |
| Shipped: Fix outdated 3-arg `Search` contract example in driver docs                                                                                                                                                                                                                                                                            | Done   | S      | Med (prevents broken integrations) | §2.1        |
| Shipped: Promote real Search frontend/header/widget screenshots and an annotated curation screenshot in marketplace media.                                                                                                                                                                                                                      | Done   | S      | Med (free conversion lift)         | §5          |
| Shipped: Rewrite composer `description` + marketplace `summary`                                                                                                                                                                                                                                                                                 | Done   | S      | Med                                | §5          |
| Shipped: Document/guarantee `highlight()` must escape                                                                                                                                                                                                                                                                                           | Done   | S      | High (XSS guardrail)               | §4          |
| Shipped: Add Scout unpublished/private-exclusion test + DB no-`status`-column leak test. Evidence: `ScoutSearch` drops indexed payloads marked draft/private/restricted; `DatabaseSearch` fails closed when the configured published-status guard column is missing; driver tests cover both leak paths.                                        | Done   | M      | High (result-visibility safety)    | §4          |
| Shipped: Cache `clickCounts()` aggregate + collapse enhancement map chain. Evidence: click-count boosts use a short TTL cache scoped by site/language, click recording invalidates the affected scopes, promoted-result conversion no longer remaps promotions twice, and focused action tests prove cached aggregates preserve scoped ranking. | Done   | M      | High (frontend budget)             | §2.3        |
| Shipped: Move `RecordSearchAction` write to after-response dispatch. Evidence: `SearchController` dispatches after response; `RecordSearchAction` receives scalar visitor metadata; controller/action tests cover deferred dispatch and write behavior.                                                                                         | Done   | M      | High (20ms render budget)          | §4          |
| Shipped: Fix click beacon CSRF on cached pages. Evidence: `search/click` is CSRF-exempt + throttled, header/results beacons post without CSRF meta state, and controller tests cover the route middleware plus tokenless markup.                                                                                                                | Done   | M      | High (analytics actually works)    | §4          |
| Shipped: Memoize FULLTEXT detection and accept covering indexes regardless of column order. Evidence: `DatabaseSearch` caches schema compatibility by connection/database/table/columns and unit tests cover covering vs incomplete index sets.                                                                                                 | Done   | M      | Med (DB driver perf + correctness) | §2.5, §2.6  |
| Shipped: Resolve driver in controller and pass hydrated highlight data into Blade. Evidence: `SearchController` now supplies `highlightedResults`; public result Blade no longer resolves `Search`; controller tests assert highlighted view data/rendered markup.                                                                              | Done   | M      | Med (convention compliance)        | §2.4        |
| Shipped: Lightweight autocomplete path skips enhancement pipeline. Evidence: autocomplete calls the driver directly and focused controller coverage proves promoted results are not injected into type-ahead responses.                                                                                                                         | Done   | M      | Med (public endpoint load)         | §2.7, §3    |
| Shipped: Translate result type labels with config overrides. Evidence: both search results and autocomplete use `ResolveSearchResultTypeLabelAction`; tests cover configured, translated, and fallback labels.                                                                                                                                  | Done   | S/M    | Med (localized result chips)       | §2.8        |
| Shipped: Did-you-mean surface + query-completion suggestions from logs. Evidence: autocomplete exposes `metadata.corrected` and `querySuggestions`; header autocomplete renders corrected/popular query rows; focused action/controller tests cover corrections and scoped log-backed suggestions.                                              | Done   | M      | High (search norm + UX)            | §3          |
| Shipped: Admin UI for synonyms / promoted results / typo dictionaries. Evidence: settings schema exposes editable curation fields and curation actions read persisted settings before config fallback; focused tests cover schema fields and runtime overrides.                                                                                 | Done   | L      | High (premium differentiator)      | §2.10, §3   |
| Shipped: Faceted-filter frontend with live counts. Evidence: type/source facet groups compute counts through the active search driver and render as public-safe filter links on the search page; action/controller tests cover counts, selected toggles, URLs, and markup safety.                                                               | Done   | L      | High (table-stakes surface)        | §3          |
| Shipped: Honor Scout engine scores/`total` where available, and document Scout source freshness ownership.                                                                                                                                                                                                                                      | Done   | L      | High (premium Scout story)         | §3          |
| Shipped: Runtime health probe for driver resolution and search-log writes. Evidence: health checks now resolve the configured `Search` driver and perform a synthetic query-log write/delete; tests cover successful probes and failure cases.                                                                                                  | Done   | M      | Med (priority-support SKU)         | §3, §4      |
| Shipped: Zero-result → create synonym/promotion curation actions. Evidence: actions persist zero-result terms into synonym aliases or promoted best-bet results consumed by runtime expansion/promotion logic; focused tests cover dedupe and runtime effects.                                                                                  | Done   | M      | High (cross-sell + stickiness)     | §3, §5      |