Skip to content

review-filters

Provenance

  • Source: .spec/spexcode/spec-dashboard/dashboard-ui/review-surfaces/review-filters/spec.md
  • Source SHA-256: 9ec824a9b57d4aa86bb216753cdb16d8783d8e033947c002110ec8a4ab38156e

review-filters

Issues and Evals travel through one filtering mechanism wherever they are listed. Its pure module lives at @spexcode/spec-core/review, the browser-safe package entry shared by the server and dashboard; that entry contains no Node, React, store, endpoint, or service dependency. A domain adapter is data: it names searchable fields, real facets, section membership (with honest concrete-status spellings), absent-field behavior, option labels, and the one source-session PRESENCE join ([[live-session-filter]] — session:present|missing, never liveness). The engine normalizes state, applies every active dimension conjunctively — q is one substring or an array of them (the token text's bare words/phrases) — derives section counts UNDER the rest of the query and data-backed options, and keeps a vanished active value clearable. It invents no field and silently omits a facet with no meaningful choice.

A section count is ONE number unless its adapter declares that section SPLIT. A split is a BINARY predicate over that section's own matched rows, so its two named buckets always re-add to the section's whole population: splitting reports structure inside a count, it can never shrink one. The Eval adapter splits its MEASURED verdicts on the same freshness axis its freshness: facet reads — counts.pass and counts.fail are {fresh,stale} — so the remeasurement debt travels WITH the population instead of being recomputed per surface; unmeasured owns no reading, therefore no freshness axis, and stays one number. The split is derived exactly once, where every other count is, and a compact/menu face of the same sections reads the whole count through the one sectionTotal rule, so a chip and the popup radio it filters cannot disagree. Because freshness is an ordinary dimension, freshness:fresh empties the stale half through the rest of the query — no surface special-cases the token.

The consumers own different state homes, not different semantics. [[paged-review]] imports this SAME pure module on the server, applies it before slicing, and returns the resulting full-population counts/facets; the canonical pages render that result and never re-match a current-page subset. [[issues-view]] and [[evals-feed]] own ONE visible token text ([[review-query]] parses it; [[review-chrome]] renders it): the canonical bridge maps parsed tokens into engine state — duplicate qualifiers last-wins, scope: to no predicate (it picks the data source upstream), and any qualifier outside the page's map to the IMPOSSIBLE state, so an unknown token stays verbatim in the text and honestly matches nothing. Every human change remains a history push and browser Back replays it. [[node-popup]] and [[eval-tab]] keep plain structured state only for the lifetime of the open Spec Information surface, surviving tab switches without minting a second address. Their compact face is one shallow sticky search row plus the shared accessible facet overflow. It uses the same adapter options, radio groups, keyboard/Escape behavior, and honest filtered-empty result as the full ListViews.

The Issue adapter exposes forge label names as the exact-match high-cardinality label: dimension. It is not a second client-only tag filter: token parsing, matching, options, counts, and the bounded server slice all travel through this engine. A local issue has no label values and therefore honestly cannot match one.

Surface defaults may differ where the products already differ: canonical Issues opens on outstanding work, while canonical Evals opens on its complete bound record with the evidence default all (a plain enum default, never data-dependent). Evals derives Fail/Pass/Unmeasured as its non-exhaustive verdict section counts (unmeasured means a declared scenario with no reading, not an unscored reading; the two measured verdicts carry the freshness split above) and derives human review (current / reviewed) as a separate fixed-value facet; the fixed lifecycle choices remain editable even when one currently has zero rows. A node popup also initially shows its complete bound record. Once a value is active, parsing and matching are identical. A node-local list naturally omits node and scope facets because they have no choice; this is absence of data, not a special-case branch. Eval consumers present one tagged set to the adapter: a filed measurement is a result, while blind, unmeasured, and dangling rows are distinct non-result kinds. That shared kind enum is the only discriminator; the canonical list and embedded node pane do not carry a parallel legacy boolean or dual-name fallback. Blind non-result rows belong to the Unmeasured section, remain present in the no-verdict default, and may match Needs review; selecting a measured verdict excludes them honestly. Other non-result kinds do not become unmeasured merely because they carry no scored verdict.