You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
Fixed
WASM merge URL lookup now handles normalized URL formats — merge_results in WASM may normalize URLs (strip .html, trailing slash, lowercase) before deduplication, causing the JS result-data lookup to miss and fall back to a stub object. The data map now indexes each result under four key variants (raw, normalized, slash-stripped, both) and falls through them in order; misses are logged as [scolta:merge] WASM URL lookup missed.
Title deduplication threshold lowered to 0.6 Jaccard — the 0.7 threshold was too permissive for short titles and multi-word proper nouns. Threshold is now 0.6, with an additional secondary condition: any pair sharing ≥3 words where the intersection covers ≥60% of the shorter title is also considered duplicate.
AI Overview headings now render as HTML — #, ##, and ### markdown headings in AI summaries were falling through to <p> tags and displaying as raw # text. formatSummary() now maps them to <h3>/<h4>/<h5> elements.
AI summary now describes post-expansion results — summarizeResults() was firing in parallel with the expansion merge, so the AI described the Phase 1 literal-keyword ranking while the displayed results showed the semantically-reordered Phase 2 ranking. Summarization is now deferred until after mergeExpandedSearchResults() completes. A searchVersion staleness check prevents summarizing results from a superseded search.
Relative URLs from pagefind index are absolutized before use — ContentItem normalizes stored URLs to relative paths for portability, but the JS needs absolute URLs in two places: the summarize API call (so the AI can include working links in the overview text) and result card <a> href attributes. Both now prepend window.location.origin when the URL starts with /.
ContentItem normalizes absolute URLs to relative paths — the pagefind index stores URLs verbatim into the binary .pf_fragment files at build time. When a DDEV local URL (https://myapp.ddev.site/path) was passed as ContentItem::$url, that domain was baked into the index and served as the click-through URL on the hosted demo. The constructor now strips scheme and host from any URL that contains ://, leaving only the path (and optional query/fragment). Relative URLs pass through unchanged. All platform adapters benefit automatically; no code changes needed in Drupal, WordPress, or Laravel integrations. Existing indexes must be rebuilt to get correct relative URLs.
stripHtml() now decodes HTML entities — the previous regex-only implementation stripped tags but left entities like ’ intact. escapeHtml() then double-encoded the &, causing titles and excerpts with curly quotes or other encoded characters to display as literal entity strings (e.g. Houston, We’ve Had a Problem). stripHtml() now uses DOM parsing (innerHTML/textContent) to both strip tags and decode entities in one pass.
Added
ContentItem::$filters and PagefindHtmlBuilder extra-filter support — a new optional filters: array<string, string> parameter on ContentItem lets platform adapters attach arbitrary Pagefind filter attributes (e.g. ['base_topic' => 'Cardiology']) that bypass HtmlCleaner and are emitted directly as <span data-pagefind-filter="key:value" hidden> elements in the exported HTML. InvertedIndexBuilder merges these into the page's filters map so the PHP indexer path also exposes them. Use case: topic-family deduplication, faceted navigation, or any per-document filter that should not be derived from body text.
Changed
content_catalog preset gains expand_primary_weight: 0.9 — validation testing showed that intent-based queries ("something about space") return zero raw pagefind results because stop words dominate the query. The AI expands to useful terms ("astronomy, celestial bodies") but at the old weight (default 0.5) those expanded results were diluted by the empty primary set. 0.9 gives AI-expanded results nearly equal weight to primary results, recovering the intent-based query path. Raised from implicit default (0.5) to 0.9.
ecommerce preset expand_primary_weight raised to 0.8 — validation testing showed that natural-language product queries ("sparkly blue gift") succeed with AI expansion but the 0.7 weight left expanded results slightly under-weighted. 0.8 brings better balance for informal shopping queries without sacrificing precision for specific product name queries. Raised from 0.7 to 0.8.