docs(ui): design global search over the board and chat corpora (RIG-1621) - #1001
Open
rigel-mintaka wants to merge 1 commit into
Open
docs(ui): design global search over the board and chat corpora (RIG-1621)#1001rigel-mintaka wants to merge 1 commit into
rigel-mintaka wants to merge 1 commit into
Conversation
|
Merging to
After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here |
rigel-mintaka
marked this pull request as ready for review
September 8, 2026 00:35
|
Compass engineering docs preview: https://compass-ux-1621-global-searc.compass-eng-docs.pages.dev Deployed from Changed pages: |
…621) Adds the design record for RIG-1621: a persistent center-of-top-bar search input alongside the D5-frozen Cmd+K palette, covering agents, issues, PRs and chat messages. Both surfaces feed ONE provider set, so neither can drift from the other, and the corpus stays server-side per Matt's ruling that the client cannot hold the full text. Scope is the whole board, not the caller's assigned slice. Chat search is nearly free: the server already ships `rpc SearchMessages` with a tsvector index, and no UI code references it. Issue search is the real new work — a generated `search_tsv` column, a GIN index, and a `SearchIssues` RPC mirroring the messages pipeline. Two schema findings, both measured against PostgreSQL 18.4 rather than reasoned about, and both of which would have shipped a broken gate: The obvious spelling of the column does not compile: ERROR: generation expression is not immutable A STORED generation expression must be IMMUTABLE, and `array_to_string` is only STABLE (`labels::text` fails the same way — `array_out` is STABLE too). The cause is polymorphism, not arrays: `anyarray` must stay conservative for element types whose output reads a GUC. So labels route through a `compass_labels_text` wrapper declared IMMUTABLE with a pinned `search_path` — honest, because for TEXT[] the concrete element output function `textout` is itself IMMUTABLE. The one alternative that both compiles and is genuinely immutable, `array_to_tsvector`, bypasses the parser: labels land as raw lexemes, so a search for `triage` against a `Needs-Triage` label matches NOTHING. It fails silently, which is worse than the error. T1 therefore requires a label-only test. And the column must weight its fields with `setweight`. Unlike the messages column it spans a 40-character title and a multi-kilobyte body, and `ts_rank` applies no length normalization by default: flat concatenation scores a title hit and a hit buried in 10 KB of body EXACTLY equal (0.06079 vs 0.06079; weighted 0.60793 vs 0.24317). The task list already asserted 'title hit above body hit', which was unsatisfiable as specified. The column is STORED, so deferring this would cost a table rewrite. PR results are scoped honestly as fixture-only at v1: `Issue.prs` has zero Go writers, so PR search looks complete against fixtures and returns nothing in production. Not worse than today's PRs tab, but no live-mode PR assertion may gate the release. Review found three executability gaps, all fixed here rather than left for an executor to hit: providers cannot reach an RPC client at all today (the `AppStore` exposes none, and hanging one on it is forbidden by DL-128), so the seam is now OQ-7; the message destination cannot navigate through `store.openTopic`, which no-ops on any topic outside the client-held set, so it routes on wire data; and the debounce moved from T6 to T4, where the effect it wraps is written, removing a T4-T6 ordering knot. Ledger citations dropped their line numbers — DECISIONS.md is append-only, so a line number into it rots, and four were already off by three rows. Mints DL-346 (DL-344/345 were already claimed by open PR #984, six hours ahead of this one — allocated, not merged, so main's max would not have shown them). Leaves DL-233's assigned-issue scope for Matt as OQ-6, and whether the palette itself re-scopes as OQ-8: this design reverses a frozen decision, and frozen decision prose is never edited in place.
rigel-mintaka
force-pushed
the
compass-ux/1621-global-search-design
branch
from
September 8, 2026 02:27
e223359 to
7060fed
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds the design record for RIG-1621: a persistent center-of-top-bar search
input alongside the D5-frozen Cmd+K palette, covering agents, issues, PRs and
chat messages. Both surfaces feed ONE provider set, so neither can drift from
the other, and the corpus stays server-side per Matt's ruling that the client
cannot hold the full text. Scope is the whole board, not the caller's
assigned slice.
Chat search is nearly free: the server already ships
rpc SearchMessageswith a tsvector index, and no UI code references it.Issue search is the real new work — a generated
search_tsvcolumn, a GINindex, and a
SearchIssuesRPC mirroring the messages pipeline.Two schema findings, both measured against PostgreSQL 18.4 rather than
reasoned about, and both of which would have shipped a broken gate:
The obvious spelling of the column does not compile:
ERROR: generation expression is not immutable
A STORED generation expression must be IMMUTABLE, and
array_to_stringisonly STABLE (
labels::textfails the same way —array_outis STABLEtoo). The cause is polymorphism, not arrays:
anyarraymust stayconservative for element types whose output reads a GUC. So labels route
through a
compass_labels_textwrapper declared IMMUTABLE with a pinnedsearch_path— honest, because for TEXT[] the concrete element outputfunction
textoutis itself IMMUTABLE. The one alternative that bothcompiles and is genuinely immutable,
array_to_tsvector, bypasses theparser: labels land as raw lexemes, so a search for
triageagainst aNeeds-Triagelabel matches NOTHING. It fails silently, which is worsethan the error. T1 therefore requires a label-only test.
And the column must weight its fields with
setweight. Unlike the messagescolumn it spans a 40-character title and a multi-kilobyte body, and
ts_rankapplies no length normalization by default: flat concatenationscores a title hit and a hit buried in 10 KB of body EXACTLY equal
(0.06079 vs 0.06079; weighted 0.60793 vs 0.24317). The task list already
asserted 'title hit above body hit', which was unsatisfiable as specified.
The column is STORED, so deferring this would cost a table rewrite.
PR results are scoped honestly as fixture-only at v1:
Issue.prshas zeroGo writers, so PR search looks complete against fixtures and returns nothing
in production. Not worse than today's PRs tab, but no live-mode PR assertion
may gate the release.
Review found three executability gaps, all fixed here rather than left for
an executor to hit: providers cannot reach an RPC client at all today (the
AppStoreexposes none, and hanging one on it is forbidden by DL-128), sothe seam is now OQ-7; the message destination cannot navigate through
store.openTopic, which no-ops on any topic outside the client-held set,so it routes on wire data; and the debounce moved from T6 to T4, where the
effect it wraps is written, removing a T4-T6 ordering knot. Ledger
citations dropped their line numbers — DECISIONS.md is append-only, so a
line number into it rots, and four were already off by three rows.
Mints DL-344. Leaves DL-233's assigned-issue scope for Matt as OQ-6, and
whether the palette itself re-scopes as OQ-8: this design reverses a frozen
decision, and frozen decision prose is never edited in place.