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.