eval-issue-split¶
M3 of the eval/issue/remark refactor — kill "forum" at the substrate, read-time-SPLIT eval-remark tracks OUT of the issue surfaces (they are the eval scoreboard's data, not the issue drain), and reach U1 (one EventDetail component). One store, two complementary reads by concern key.
raw source¶
An eval-remark thread and a taste issue were living in ONE list and reading as the same kind of thing — both "issues" on the board badge, both in the drain, both in the Issues page's list. But a scenario-scoped concern is a remark, not an issue (I1): it ages a scenario's loss and clears only by the teeth (remark-teeth); it must never be a drainable issue, or the loss signal could be bypassed by resolving it as an issue. So the two must split, read-time, over the one file store — and the word "forum", which still named the local store everywhere in the code, had to go with them: the local store is just where a local Issue lives, not a second concept.
expanded spec¶
Three moves, one milestone — a read-time split. This node killed "forum" from every code identifier; the
on-disk store dir itself was renamed next, in the follow-on issues-store-rename (.spec/.forum →
.spec/.issues, with a one-shot self-migration so no deployment breaks) — so the substrate now carries the
issues name top to bottom, and the old data-dir name is no longer residue but retired.
-
Kill "forum" at the substrate. The local issue store's code no longer speaks "forum": its data-level identifiers are the issues model —
postLocalIssue/replyLocalIssue(the programmatic write entrypoints),localStoreDir/LOCAL_STORE_REL(the venue),withStoreLock/commitStore/writeStoreFile(the write mechanism). The dashboard route is#/issues(not#/forum), the side-nav entry reads Issues, and the user-facing prose says "issues page", never "Forum". local-issues still OWNS the local store's whole mechanism; it is simply named as what it is — the local store of issues. -
Read-time split by concern key. An eval-remark thread's tell is its concern,
eval: <node> · <scenario>(isEvalConcern). Two complementary reads run over the ONE store:mergedIssues(the read every ISSUE surface consumes) excludes eval concerns, andloadEvalRemarkTracks(the read the EVAL surfaces consume) keeps only them. Splitting at the source — insidemergedIssues— frees every issue surface at once, by construction: the issues-view Issues page list, the dashboard-issues board issue badge, and thespex issuesdrain all stop counting eval remarks as issues, with no per-surface filter. The eval-remark tracks instead ride the EVAL side (evals-view): the evals-feed rows and the event-detail pane, through the M2 server overlay. -
One overlay feeds both eval homes. The (node, scenario)↔thread join is lifted server-side onto the reading itself:
evalTimelineattaches the eval thread asEvalEntry.thread, so it is present on every eval home — the issues-page feed folds it in through the board, the session tab through the proof model. event-detail therefore reads its remark track fromentry.thread, never from a resident issues list (which no longer holds eval threads anyway) — the counterpart to splitting them out.
Together these reach U1: ONE EventDetail component (event-detail), store-agnostic, reused in every
home — the issues eval tab AND the session eval tab (whose "no resident issues list" degradation is gone, since
the composer authors remarks through the CLI-parity /api/remarks and needs no list). U2 holds
throughout: scenario and issue stay DISTINCT peer types on DISTINCT surfaces (Evals | Issues) — the split is
exactly what keeps them from collapsing into one super-type.