review-surfaces¶
Evals and Issues are ONE paged-review product rendered twice — the two page families plus the shared chrome, filter engine, and thread that keep them from drifting into near-identical dialects.
#/evals and #/issues are two rail destinations, but they are one product read twice: a GitHub-grammar
LIST page whose whole state is a visible token query in its URL, rows that are real anchors, a click that
PUSHES onto a standalone DETAIL page, and browser Back as the return path. That pair already proved the
drift risk once, as two master-detail copies of the same idea. So the shared middle is not an
afterthought that happened to be extracted — it is why this group exists, and it is why either page reads
correctly only beside it.
- evals-view — the Evals pages: the Fail/Pass/Unmeasured loss axis over the measured record, the
evidence detail workspace, and the
scope:token that sources one session's worktree loss through the same route family. - issues-view — the Issues pages: Open/Closed lifecycle over the merged store, a detail whose writes route to the issue's own store, and a routed compose page with the same standing as reading one.
- review-chrome — the ONE contract both render: the paged-review request/response shape, the ListView
query/section/facet/pagination chrome, the row and state primitives, and the standalone
DetailShell. - review-filters — the ONE pure filter engine with domain adapters, the single home of field semantics, serving the canonical lists and the compact embedded panes from the same predicates.
- reply-thread — the ONE thread both details render, so an issue thread and an eval's remark thread are the same component carrying the same marks.
The line this group holds: a change to list rhythm, query grammar, detail geometry, field meaning, or the thread lands once, in the shared node, and both pages move together. What stays in a page is only what genuinely differs — Issues has a lifecycle, Evals has a verdict and a data-source axis. Neither page may grow a near-copy of the shared middle, and the shared middle may not grow a per-page domain branch; an empty abstraction that exists only to be parameterized by which page called it is the same failure from the other side.
This node owns no source of its own — each child keeps its files, [links](/reference/spec-forge/links/), and drift.