Skip to content

Add a guided-review mode to trust-map explainers - #27

Merged
theclaymethod merged 34 commits into
mainfrom
claude/guided-review
Oct 12, 2026
Merged

theclaymethod merged 34 commits into
mainfrom
claude/guided-review

Conversation

@theclaymethod

@theclaymethod theclaymethod commented Oct 11, 2026 •

Copy link
Copy Markdown
Owner

A trust-map explainer can now be a guided review. The page teaches the change first. Then it ends in a checklist that the reviewer completes before the merge.

Chapters

The page has nine chapters, ch-0 to ch-8. With JavaScript, one chapter shows at a time. Without JavaScript, all chapters show in order.

Chapter It answers
Start What does the PR do, and can it merge?
The problem and the change What was wrong, and what changed?
How it works How does one finding move through the loop?
What changed What changed, file by file?
Reading the evidence How do you read the evidence?
The checks Which checks back each claim?
Check yourself Three questions, answered at once.
The review What must you review before it can merge?
The verdict Can it merge, and what is left?

Components

  • ExplainerShell paged: one chapter at a time, Previous and Next, a "you are here" rail and "Read as one page".
  • WorkedExample: real values from synthetic sources go through the flow, one step at a time, with provenance for each value. It comes before the abstract diagram.
  • DiffSpine: the chapters of the change, with the files that need attention first.
  • EvidenceGuide, VerifierView, UnderstandingCheck, ReviewChecklist, ReviewVerdict and ApproveChecks.
  • Shared rows: ClaimRow, CheckRow, BarCard and ChangedCode.
  • Typed diagrams (sequence, state, schema, flow and file map), each in Before and After, and in Simple and Detailed.
  • Breakable: a path wraps only after a /, and a name wraps only after a _ or a -.

Export checks

The export fails on each of these:

  • Copy: a slogan, a label run-in, or a sentence that shows two times.
  • STE: a hard violation of the asd-ste100 lint, for example a sentence of more than 25 words.
  • Examples: a how-it-works chapter with no worked example, an example after its diagram, or a step with no provenance.
  • Title-joins: two titles that a bare word joins.
  • Bare lists: an opener whose body is only a long list.

Type, navigation and highlighting

  • Fonts: Newsreader for prose, Public Sans for the UI and Commit Mono for code. The export embeds the subsets in the page, so the page works offline. Each font has the SIL Open Font License 1.1. The licence texts are in visual-explainer-mdx/fonts/.
  • Type scale: one scale in rem tokens. Prose is at 1.6. UI text is 15 and 14 px, labels are 13 px, and both are at 1.4. Code is 14 px at 1.5. The weights are 400 and 600 only.
  • Code: code does not wrap. A long line scrolls to the side, and the line gutter stays in its position.
  • Calm navigation: each jump is instant and happens one time. A control that the reader clicks stays in its position on the screen.
  • Highlighting: Shiki tokens use the syntax colours of the preset. Each changed line has a +, ~ or - sign, so the page does not use colour alone.
  • Credit: some patterns come from the MIT guided-review plugin (GUIDED-REVIEW-NOTICE.md).

Verification

Check Result
npm run check pass in 41.3 s, in the 120 s budget (parallel lanes from main)
Guided-review and worked-example browser tests 20 of 20 pass
End-to-end rebuild of the #489 page (understando explain into a copy, then export) pass, with all export checks
understando tests/e2e.sh each step passes. The last isolation check failed: a review session on the real #489 run wrote 4 of its files while the suite ran
understando learn/e2e.sh 17 browser tests and the smoke run pass. The same isolation check failed for the same reason
Screenshots: each chapter, the worked example and a code ref, at 1280 and 375 px, light and dark 44 shots, no sideways scroll, no console error

🤖 Generated with Claude Code

theclaymethod and others added 30 commits October 11, 2026 14:25
…page, StepThrough, and independent diagram modes

ExplainerShell paged shows one Section at a time after hydration, with previous and next
links, a 'You are here' marker in the rail and a Read as one page switch; without script
every chapter renders in sequence. A fragment link shows the chapter that holds its
target; Section aliases keep old anchors working. StepThrough shows a numbered run one
step at a time and lights the matching station. DiagramModes takes modes: 'independent'
so the Simple mode is laid out for its own labels, with no dead space.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The guided-review components render understando's derived data: the start (merge state,
progress, the riskiest three), the chapters of the change with their look-closely flags,
Reviewed boxes and the changed-file map, the evidence guide (promise to claim to check,
surface to bar, one bug with two results), the checks by promise with tests shown as the
checks they provide, data-built questions, the checklist (blockers, then risks to
accept, in derive.py's order, with calls stored locally under the PR head and the
trust-map hash and a copy-only Markdown export), the verdict with concrete checks before
approval, and every changed file in GitHub's order.

One claim row and one check row are reused everywhere; each claim's full detail renders
once. Typed diagrams (sequence, state, schema, flow, the file map) follow Diagram
Design's grammar in the host tokens, with Before/After, Simple/Detailed and chapter links.
Fixes: no tier numbers in reader text, no Cheapest fix that repeats its action.
Patterns adapted from the MIT guided-review plugin (GUIDED-REVIEW-NOTICE.md).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The card describes the ten chapters, the new explain.json keys (change.chapters,
verdict.checks, typed diagrams) and the derived values (merge.accept, spine, checks,
tests). The fixture becomes a guided review. The e2e tests cover the chapters and their
navigation, one-page mode, the no-JS render, the checklist order against derive.py, the
local calls and their key, the Markdown export, each claim's detail once, the questions,
the old anchors, the chapters of the change, the check rows and AA contrast at 375px.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Lead: no run-in label ("In plain words.") and no label CSS. Aside
  needs its own label (no default "Why this matters").
- Review controls: drop "Saved in this browser only. Nothing is sent."
  under each call, "It only copies. Nothing is posted." and "Your
  answers stay on this page. Nothing is graded, saved or sent." The
  button says "Copy as Markdown". The storage fact goes once in the
  ch-7 Lead of the MDX.
- Stock phrases and editorial tails: "only as strong as its weakest
  claim", "as a good check must", "This is the good result", "You
  decide if it is important", "Each gate passes or fails", "Why you can
  trust it", "One bug. Two different results.".
- The checks chapter no longer repeats the result line of the evidence
  chapter; the backend control row counts the planted checks instead.
- Hard STE fixes in component strings: no semicolons, verdict meanings
  and glossary words of 25 words or fewer, one verb per action.
- Fixture: a ch-7 Lead with the storage fact; STE fixes in explain.json
  and its derived copy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d STE

checkTrustMapPage now fails the export on:
- a sentence that matches a slogan rule of scripts/ve-mdx/copy-rules.mjs
  (reassurance openers such as "Nothing", "It only", "Saved in", and
  stock phrases), outside code, diagrams, quotes and Term tooltips;
- a bold run-in label such as "In plain words." at the start of a
  paragraph or list item, and any run-in label in a Lead;
- a sentence of four or more words shown twice, when the narrative
  repeats it or a component repeats it outside its records. Controls,
  links, navigation, pills, the merge state, screen-reader text, no-JS
  twins, tables and the glossary are out of scope by role; the same
  value in two records (claims, checks, files, items) is data;
- a hard violation of the asd-ste100 ste-lint.py over the narrative and
  the component text (one lint process per export). --ste-lint <path>
  or VE_STE_LINT points at another lint, "off" turns it off; a missing
  python3 or script fails with the fix.

The card's writing guidance gains a Copy section with bad -> good
examples and tells agents to write with the asd-ste100 skill. The e2e
test plants a slogan and a run-in, a repeated sentence, a semicolon and
a missing lint in copies of the fixture and checks each export error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A trust-map explainer now embeds its own fonts as subset woff2 data URLs (Latin, Latin-1 and
the punctuation the pages use; 400 and 600, code 400) and loads nothing from a font service, so
it reads the same offline. explainer-type.mjs holds three pairings and one token,
EXPLAINER_TYPE, that picks the default (VE_EXPLAINER_TYPE overrides it for one export):
Source Serif 4 (renamed Reading Serif, for its Reserved Font Name) with IBM Plex Sans and Mono,
the default; Literata with Atkinson Hyperlegible Next and JetBrains Mono; Newsreader with
Public Sans and Commit Mono. Each face has a metric-matched local fallback (size-adjust and
ascent/descent overrides). Decks, posters and charts keep their preset fonts. The OFL texts
and fonts/NOTICE.md record each font's source, copyright and the subsetting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e change chapters

- Glossary marks: a chapter marks each term once, at its first use, and at most eight terms;
  everyday words (glossary-policy.mjs) are never marked; each abbreviation is spelled out once on
  the page. The mark is a faint dotted underline set low, full ink on hover or focus. The export
  fails on a chapter with more marks, a mark on an everyday word, or a term marked twice.
- Type roles: prose in the reading face (--ve-font-prose), rows, labels and controls in the UI
  face; headings by weight and size.
- Measure: every prose block and each definition-list value is capped at --ve-measure; the label
  column is 9rem and stacks below a 900px column (a container query on the section body).
- Rhythm: one unlayered flow rule on the 4px scale, so a component's margin reset cannot undo it:
  16px between blocks and definition rows, 32px after the lead, 48px around a figure or stepper.
  A paged chapter has no orphaned rule above it.
- The Simple/Detailed and Before/After switches are quiet segmented controls in the figure's
  header, beside its title.
- Dark mode on explainer pages: off-white text on a lifted ground; every text pair keeps AA.
- What changed: each chapter of the change is an opener with its title, first sentence and file
  and flag counts; only the first starts open, and a link into a chapter opens it.
- Quieter checklist rows: outlined order numbers, "To review" as plain text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	scripts/ve-mdx/trust-map-checks.mjs
#	visual-explainer-mdx/trust-map.tsx
…hange

The STE check uses the installed asd-ste100 skill, else a vendored copy of ste-lint.py (MIT,
with its licence and provenance), so CI and a run with its own HOME (understando's e2e) lint the
same copy. A change with three chapters or fewer opens each of them; with more, only the first
starts open (DiffSpine open="first" | "all" overrides it). The card states the glossary-mark
rules and that each spelled-out abbreviation counts against the sentence cap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eir place

- No smooth scrolling (the rail CSS set scroll-behavior: smooth on html).
- A chapter switch in the page shows the chapter and lands on it in the same task
  (flushSync + one scrollIntoView): no frame paints it at the old, clamped position,
  and no ResizeObserver re-places the target for 1.5s after.
- A deep link on load lands once, after document.fonts.ready and two frames; before
  the page runs, CSS (scripting: enabled + :target) already shows the linked chapter,
  so the browser's own fragment jump lands where the page lands it.
- A block that the browser opens around a fragment keeps the address on the
  fragment (it rewrote it to the parent, so #claim-… landed on its promise).
- A summary click or a view switch keeps the control at its place on the screen;
  closing a block near the foot adds room below instead of pulling the page down.
- Read as one page / by chapter keeps the chapter at the reading line in place,
  and reading by chapter opens that chapter.
- The narrow chapter menu lies over the page, so opening it moves nothing; the
  scroll-spy only runs in one-page mode and never scrolls.
- Each page fills the screen and the pager labels hold two lines, so Previous and
  Next sit in the same place on every chapter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
At 1280px and 375px with motion allowed: Next and Previous land at the chapter
top in one scroll with no second; the pager sits in the same place on every
chapter; an in-page link and a deep link on load each scroll once and open only
the target's blocks; Read as one page and back keep the chapter in place;
opening, closing (also at the page foot) and the view switches keep the clicked
control in place; the rail follows the scroll and never scrolls.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	visual-explainer-mdx/components.tsx
…drated page keeps it

Before the page runs, the chapter that the address names now has the paged spacing (no rule,
32px above its heading), so the browser's own fragment jump and the page's single landing agree.
The deep-link test leaves out the chapters of a short change, which start open by design.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…calm-scroll.ts

The four navigation e2e runs share no state, so they run as concurrent subtests (the explainer
test file drops from about 38 s to 19 s) and the canonical check stays inside its budget. The
copyable content leaf now carries calm-scroll.ts, which Disclosure imports.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Clayton chose the editorial pairing after he compared the three in dark mode.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The export highlighted refs.resolved.json only for schema 1, so the schema 2 refs of a guided
review showed plain code. It now highlights any schema at export time, in the pre-render and in
the bundle.

Each CodeRef and ChangedCode shows its lines with a gutter: the line number at the head and a sign
(+ added, ~ changed, - removed). The removed base lines show inline with their base numbers,
highlighted in their base context. The line status comes from the new `changes` field of each
resolved ref (understando explain); an older refs file marks diff.added only. The added and
removed tints keep each syntax token at AA in light and dark (the light keyword ink is darker
for it), and a "look closely" flag still marks its line on top.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…view state

The rail now uses Public Sans at one size, with a muted number column in tabular
figures, and each title wraps under its own text. The current chapter is accent
text in weight 600 with no tint, and aria-current="page" names it; the visible
"You are here" line is gone. Rows are 44px targets on the 4px scale.
In-chapter targets show only under the current chapter, smaller and muted.

Each chapter shows its review state in the mark language. The start and verdict
chapters show the merge state; it is static, so the page without script shows it.
The review chapter shows "N of M", and a chapter gets a check once its boxes or
items are all done. The marks read the same local calls as the page. A block
gives its chapter a mark through a static chapterMark(props), which the shell
collects.

"Read as one page" becomes a quiet "Read by chapter / as one page" switch at the
foot of the rail. The top bar on mobile gets the same type and a drawn caret,
and its menu still lies over the page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every block answers a reader question. What changed loses the file map
and its list of every import link (chapter titles joined by "imports"),
the chapter list that repeated the openers, the side list of flags that
the file cards show again, the per-chapter file counts, and each "Show N
more files" dump: a chapter shows the files to act on, and the rest is one
line with a link to the diff. A file card lists only the claims that no
card above it lists. The every-changed-file chapter (FullDiff) goes. The
checks chapter keeps the count of tests that back no claim, without the
list of their names, the second grouping by test file or the table of
every check. The evidence chapter loses the checks-per-kind count line and
says what a planted bug is instead of the result line again; evals with
the same finding show as one line. The verdict says "1 verified bug." and
drops a rating bracket that says only "not rated".

The export now fails on a title join ("<Title> imports <Title>") and on an
opener whose body is only a list of more than 10 items with no
explanation. The trust-map card states the rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The term cap holds for the whole chapter, also for blocks that start from
the same snapshot (the promises chapter marked nine). The planted-bug line
no longer repeats the result line. The merge items after the first three
show behind an opener, each with its reason, not as one long sentence of
labels. An invariant is "accepted" by the user, as derive.py says, and the
list of invariants says what the reader learns from it. The glossary shows
only the words of the page, with no "Show all N words" toggle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…od/artifacture into claude/guided-review-cut

# Conflicts:
#	plugins/visual-explainer/cards/trust-map.md
…chapter

WorkedExample shows one run of real data, one row per step: in, the decision and out with
the values in code, the reason, the diff and the line that decided. The values come from
refs.resolved.json examples (understando scripts/example.py), each step with its source
pointers. With JavaScript one row at a time and the station lit; without it, every row.
A checklist item shows the examples of its claims. The export fails on a how-it-works
chapter with no example, an example after the diagram, or a step with no provenance.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…od/artifacture into claude/guided-review

# Conflicts:
#	plugins/visual-explainer/cards/trust-map.md
#	scripts/ve-mdx/fixtures/trust-map/explainer.mdx
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…uild the skill runtime

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
theclaymethod and others added 4 commits October 11, 2026 16:56
… runtime

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ly at joints

One type scale in rem tokens: prose 1.6, UI 15 and 14px and labels 13px at
1.4, code 14px at 1.5, h2 to h4 by size and weight, weights 400 and 600 only,
tabular figures in the UI face, balanced headings and pretty paragraphs.

Code never wraps: a code block scrolls sideways and the CodeRef line gutter
stays in place. An item that holds code or a table takes the column; only its
text keeps the prose measure.

Breakable: a path wraps only after a slash, a name only after _ or -. Code
captions, DataTable ID cells, file paths and worked-example values use it.

Worked examples: the table sizes its columns to content; tool text for a
person is a quote in the UI face with a 1px rule; In, Decision and Out are
sentence-case labels; the station is a muted line under the step name; the
stations and controls share one height; Next is quiet, like Previous.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@theclaymethod
theclaymethod marked this pull request as ready for review October 12, 2026 00:46
@theclaymethod
theclaymethod merged commit 27f82e7 into main Oct 12, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant