Expand description
The semantic view-model over a DiffResult — the one seam every painter reads
(issue #21, design doc Amendment 2026-07-11).
DiffResult (+ the two Runs)
│
▼
amberfork-layout
│
▼
ViewModel
semantic rows (spine / fork / downstream), step summaries,
designed wording (confidence, verdict, absence), attribution
reading order, field-diff evidence
│
┌───────────┴───────────┐
▼ ▼
CLI painter (render.rs) web painter (ui/, Leptos)
columns · glyphs · ANSI SVG/DOM geometryWhat lives here is exactly what every surface must agree on: which alignment move plays
which role, the one-line gist of a step, the wording rules the design locked — confidence
as conf 0.NN with the explicit marginal call at zero (notebook 005), the converged
verdict that only claims “identical” when the alignment earned it (issue #19), the
(no aligned step) absence — plus the attribution reading order (DR5) and the
field-level evidence at the fork.
What deliberately does NOT live here is any painter’s own arithmetic: column widths, truncation, wrapping, gutter glyphs, and ANSI are the CLI painter’s business; pixel geometry is the web painter’s. This crate has zero terminal dependencies, and styling decisions never feed back into it.
For the web painter the view crosses a wire: Document is the serializable form the
server ships (issue #24) — the same ViewModel plus a DOCUMENT_VERSION stamp and
the payload envelope: building the document cuts every payload-derived slot at
SLOT_TEXT_LIMIT bytes with an explicit SlotText::truncated mark the UI must
render visibly.
Structs§
- Aligned
Step - The two sides of one alignment move, resolved for display. Indices are kept separate from the resolved views: a gap move has an index on one side only, and a painter still shows the index even where (malformed hand-built input) it resolves to no step.
- Attribution
View - The attribution answer in DR5’s reading order — mode, origin, propagation, confidence, then the counterfactual verdict when there is one — each part already in its designed wording. The terminal flattens the parts to one line; the web attribution pane renders them as separate elements.
- Deltas
View - Latency / token deltas, already in the designed wording (
+5.20s,-300 tok) so no painter reinvents the sign/units convention. MirrorsAttributionView’s split: the terminal flattens the parts to one line, the web pane can lay them out as separate elements. - Document
- The wire form of the seam: what
amberfork serveships to the web painter. The body is the SAMEViewModelthe terminal paints — the document only adds wire hygiene on top. - Field
Diff View - One field-level difference at the fork, values already in display form (compact JSON).
removed/addedare what a painter shows on the-/+side; an added field has noremoved, a removed field noadded. - ForkRow
- The fork row: the first move of the block the alignment never recovers from.
- Payload
Response - The wire form of one resolved
SlotAddress(issue #30) — deliberately just the text, no echo of the address or thetruncatedmarker: the caller already has both from the document it read the address off, so restating them here would only invite the two copies to drift. Shared byamberfork-server’s handler and the web painter’s fetch, the same wayDocumentis — one wire contract, not one redeclared per consumer. - RunHeader
- A run’s identity as every surface introduces it (terminal header lines, web header bar).
- Slot
Address - A stable pointer to one payload-derived slot, good for the life of one
Document(rows are positional, so this does not survive a re-diff). Round-trips over the wire so the web painter can hand one straight back to the server to ask for the full text (issue #30). - Slot
Text - One payload-derived text slot.
ViewModel::computealways produces the full text; only the payload envelope inDocument::newsetstruncated— so the CLI painter, which reads the view directly, never sees a cut slot. Generated wording (verdicts, confidence, attribution, warnings) is bounded by construction and stays plainString. - StepRow
- Step
View - One side’s step, resolved to what surfaces display.
- View
Model - The full semantic view of one diff: everything a painter needs, nothing it must compute.
- Warning
- A non-fatal diagnostic emitted while building the diff (e.g. unmapped attributes, content absent from a metadata-only trace).
Enums§
- Move
Kind - The class of an alignment move, in the process-mining sense the aligner uses: a synchronous
move pairs a step from each run; a log/model move is a gap present on only one side. By
convention run
bis the “log” (observed/failing) and runais the “model” (reference), so aMoveKind::Logstep is extra inband aMoveKind::Modelstep is missing fromb. - Outcome
- Run-level verdict, if known. Deliberately supplied by the user (an assertion, a label, a gold answer) — amberfork never derives it from trace/span status.
- Row
- One alignment move as a display row.
- RowRole
- Where a non-fork row stands relative to the fork — the role that drives every painter’s styling (sameness recedes, divergence glows).
- RunRole
- Which seat a run occupies in the diff — the
DiffResultcontract’s side convention:ais always the reference,bthe observed/failing run. - Side
- Which of a row’s two runs a slot belongs to — the
DiffResultside convention (ais the reference,bthe observed run), reused here rather than a second vocabulary. - Slot
Kind - Which slot within a row’s
AlignedStep(orForkRow) aSlotAddressnames. - Step
Kind - The structural class of a step. Part of the identity the aligner keys on. This is the
canonical, post-normalization vocabulary:
amberfork-ingestis responsible for mapping the many framework-specific span kinds down onto these four. - Verdict
- The one-line answer every diff ends with.
Constants§
- DOCUMENT_
VERSION - The document version this build emits. A bare wire-hygiene marker (issue #24): the web UI
and the server ship in one binary, lockstep by construction, so there is no read-gate —
bump it when the document’s shape changes so a stale payload is at least identifiable.
0.2: field-level evidence moved fromForkRowonto everyAlignedStep(issue #27) so the content-diff pane can show any selected pair’s diff, not only the fork’s. - SLOT_
TEXT_ LIMIT - The payload envelope’s per-slot byte limit. The threat is multi-MB field-diff payloads (eng review D12+D17): a slot is one display line, so 4 KiB loses nothing any pane shows unexpanded (expand-on-demand is issue #30’s job) while keeping a worst-case document of hundreds of rows around a megabyte. Bytes, not chars, because the guard protects wire size; the cut backs off to a UTF-8 char boundary.
- UI_CSS
- The design system’s stylesheet — the single source both painters dress from.
Functions§
- confidence_
text - Confidence per notebook 005: zero — the designed weak-call state (evidence ≤ τ) — is stated in words, never rendered as a small number.
- kind_
label - The canonical step-kind vocabulary every surface prints.
- move_
label - The canonical move-kind vocabulary; painters add their own framing (the CLI brackets it
into
[sync], the web renders a chip). - outcome_
label - The canonical outcome vocabulary.