Skip to content

Ship the side-highlight prototype: a rail means nesting now - #2404

Merged
jonathanKingston merged 6 commits into
mainfrom
claude/copse-threads-prototype-c5c83c
Sep 9, 2026
Merged

jonathanKingston merged 6 commits into
mainfrom
claude/copse-threads-prototype-c5c83c

Conversation

@jonathanKingston

Copy link
Copy Markdown
Collaborator

prototypes/side-highlight (#2350) landed as prototype files only — 3,138 lines of
workshop, and nothing in src/. Its inventory of ten accent rails still matched the
source line-for-line, so none of its proposal had been implemented. This implements
M — the mix, the design it proposed.

The design

The rail used to do three unrelated jobs, and looked the same doing all of them:
containment in the transcript, selection in the sidebar, nesting under a tool card.
One device serving three meanings is what made it read as repetition rather than as
signal. Only nesting keeps it, which is literally what a nesting guide depicts.

Block Treatment
GitHub alerts, blockquotes flat plate — prose the agent wrote, part of the answer
Thinking, review, comparison hatched plate — Copse annotating its own turn
VNC pane gutter — its status hue has to survive on one line, where a plate would just box three of them
Tool rollup, subagent timeline unchanged — structure, not decoration
Thread rows, Settings nav, VNC tabs fill alone — the full-bleed wash already says "current"

Alerts and blockquotes are styled by @copse/streaming-markdown, so they are
overridden locally in styles/global/markdown.css: renderer/main.ts imports the
package's default.css before global.css, so rules at the package's own specificity
win on source order. No upstream change was needed.

The prototype's open questions

  • Moiré — settled by the number. A repeating gradient beats against the pixel grid
    when its period lands near an integer count of device pixels. 8 is a multiple of 4,
    so at every quarter-step scale Windows offers (1.25×, 1.5×, 1.75×, 2×) the period is a
    whole number of device pixels and there is no beat frequency. The pitch is now load
    bearing; base.css says so where it is declared.
  • Reduced transparency / high contrast — done. The hatch lines go to nothing and the
    wash comes up to the plate's weight, so commentary keeps a surface and loses only its
    distinction from content.
  • Two new hues. Five alert kinds need five and the palette had three. --info and
    --important join the semantic tokens with derived light values. --important is
    pushed bluer than a true violet so it does not read as the pink accent — a user
    whose custom accent is itself purple still collapses that
    , which is written down
    rather than fixed (the fix is to derive --important away from --accent).
  • Callout glyphs are solid — the only filled shapes in an otherwise outline set, so
    docs/ui-taste.md now states the house rule outright: filled marks transcript status,
    outline is chrome. That is also what scopes the two warning triangles rather than
    retiring one. The optical-centring nudges are baked into each mask's viewBox,
    measured once by the prototype and not recomputed at runtime.

For a reviewer

  • The bug worth knowing about. The finished backgrounds were first put in shared
    custom properties. A custom property is substituted where it is declared, so
    --callout-plate froze :root's grey into its computed value and inherited that grey
    everywhere — every plate came out the same neutral. A screenshot did not catch it; the
    new callout-surfaces e2e spec did. The tuning now lives in base.css and the colour
    is mixed at each use site.
  • .thread-proposal keeps its rail. It landed in Let the agent propose whole new threads #2334, after this inventory was
    taken, and its rail marks a standing ask — a fourth job the bar was not doing when
    the prototype surveyed it. Allowlisted with the reason rather than converted silently.
    Worth deciding deliberately.
  • accent-rails.test.ts now holds the list closed. It kept the "a rail never curves"
    contract and gained a second rule: a rail may only mean nesting. A trailing-edge
    border is out of scope there, because that is how the app walls one pane off from
    the next.
  • docs/ui-taste.md contradicted this in three places — "Accent rails never curve",
    "Sidebar selections", and "Transcript status callouts", which used to forbid a tinted
    block outright. All three are rewritten with the reasoning, not just the new rule.

Verification

  • pnpm run check passes end to end (8544 pass / 0 fail / 7 skipped).
  • New focused spec tests/e2e/callout-surfaces.e2e.ts seeds every affected surface on
    one screen and asserts the plate resolves per severity, the hatch actually hatches, the
    selected row has neither border nor shadow, and all five glyphs are distinct — with
    dark and light workbench screenshots.
  • Strong forest tint checked by hand: the plate and hatch are color-mix over live
    theme tokens, so they follow it without re-derivation.
  • The 536 committed reference screenshots are stale. check:screenshots flags them,
    and the sanctioned path is the CI e2e candidate artifact — hence the
    update-screenshots and ci-full labels on this PR.

🤖 Generated with Claude Code

@jonathanKingston jonathanKingston added update-screenshots ci-full Force the full e2e suite (bypass the test-oracle thinning) on this PR labels Sep 6, 2026
@jonathanKingston
jonathanKingston force-pushed the claude/copse-threads-prototype-c5c83c branch from 90c49f1 to c93fbe0 Compare September 6, 2026 03:43
github-actions Bot added a commit that referenced this pull request Sep 6, 2026
@github-actions

github-actions Bot commented Sep 6, 2026 •

Copy link
Copy Markdown
Contributor

🖥️ PR preview

@copse-release-bot

copse-release-bot Bot commented Sep 6, 2026 •

Copy link
Copy Markdown
Contributor

Reference screenshots ready for review

Review GitHub’s image diffs in screenshot PR #2572.
Merge it (or enable auto-merge) to apply the accepted PNGs to claude/copse-threads-prototype-c5c83c.

Rendered for 2c1eb06c756b by CI run 34157525663; the immutable artifact is reference-screenshot-candidates-34157525663.

If this source branch moves, a later successful render closes the stale review PR and replaces this link.

jonathanKingston and others added 2 commits September 6, 2026 09:06
`prototypes/side-highlight` inventoried ten accent rails across six
stylesheets doing three unrelated jobs — containment in the transcript,
selection in the sidebar, nesting under a tool card — and proposed "M, the
mix", split by what each block *is* rather than by what it looks like. This
implements it. Only nesting keeps the bar, which is literally what a nesting
guide depicts; `accent-rails.test.ts` now holds that list closed.

Containment becomes a plate, in two materials (base.css):

- **Flat** — GitHub alerts and blockquotes. Prose the agent wrote is part of
  the answer, so it gets a plain surface and the hue moves to the title. These
  are styled by `@copse/streaming-markdown`, so markdown.css overrides at the
  package's own specificity and wins on source order; no upstream change.
- **Hatched** — thinking, review, comparison. Copse annotating its own turn,
  and a texture says so without spending a fourth hue or a fourth shape. It
  degrades to the flat plate under `prefers-reduced-transparency` and
  `prefers-contrast: more`.

The VNC pane takes the gutter instead: a separate pane whose status hue has to
survive on one line, where a plate would just box three of them. Selection —
chat rows, Settings nav, VNC tabs — becomes the full-bleed fill plus weight.

Answering the prototype's open questions:

- **Moiré is settled by the number.** 8 is a multiple of 4, so at every
  quarter-step display scale the hatch period lands on a whole count of device
  pixels and there is no beat frequency. The pitch is load bearing.
- **Two new hues.** Five alert kinds need five, and the palette had three.
  `--info` and `--important` join the semantic tokens with derived light values.
  `--important` is pushed bluer than a true violet so it does not read as the
  pink accent; a user whose accent *is* purple still collapses that, which is
  written down rather than fixed.
- **Callout glyphs are solid**, the only filled shapes in an outline set, with
  distinct silhouettes so the kind reads before the hue. Their optical-centring
  nudges are baked into each mask's viewBox — measured once by the prototype,
  not recomputed at runtime.

The tuning lives in base.css but the colour is mixed at each use site, because
a custom property is substituted where it is *declared*: one holding the whole
`color-mix(… var(--sev) …)` freezes the root's grey into its computed value and
inherits that grey everywhere, whatever each block sets --sev to. Every plate
came out the same neutral, and a screenshot is not how you catch that — the new
`callout-surfaces` e2e spec is, and it did.

`.thread-proposal` (#2334) landed after the prototype's inventory and keeps its
rail, allowlisted with the reason: a standing offer is an *ask*, a fourth job
the bar was not doing when this was surveyed. Worth revisiting deliberately.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CI's full e2e tier found what the stylesheet-level guard could not: four specs
assert the old design directly, so removing the rails made them fail rather than
pass. Each is repointed at what the surface means now, not just at a new number.

- `conversation-visual-hierarchy` pinned review and comparison to a 2px left
  border, a zero radius and a fading `linear-gradient` wash. They take the
  hatched plate now, and the radius is the part a rail could never have had —
  it would have bowed around the corner.
- `markdown-streaming-blockquote` used the rail's width as its proof that the
  stylesheet had reached a *pending* quote at all. That proof is the plate now:
  a filled background and a radius, plus an explicit `0px` border so the rail
  cannot creep back on the streaming path alone.
- `thread-sidebar-selection` and `ui-polish` both asserted a rail — trailing on
  a chat row, leading on Settings nav. Both are the full-bleed fill plus weight,
  and in `ui-polish` the two now being *identical* is the assertion: one
  selection gesture wherever the list sits, where the old spec required them to
  differ.

Unrelated: `thread-terminal-rename-archive` also failed on shard 8 with
"expected renamed terminal label", a wait on the terminal tab's rename. It
passes locally against this build and touches nothing this branch changed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jonathanKingston
jonathanKingston force-pushed the claude/copse-threads-prototype-c5c83c branch from c93fbe0 to c66defc Compare September 6, 2026 09:18
github-actions Bot added a commit that referenced this pull request Sep 6, 2026
@jonathanKingston
jonathanKingston marked this pull request as ready for review September 6, 2026 16:13
One conflict, in `styles/global/markdown.css`, and it was two appends to the
same end of file rather than a disagreement: this branch adds the callout plate
and its glyph masks, `main` adds the light-theme `.hljs-*` palette (#2565, issue
#2486). No shared selectors, so both are kept, ours first.

`docs/ui-taste.md` merged cleanly but the two sides then said different things.
#2565 added "carry a fill (--bg-selected) or a rail as well, so the signal
survives both themes", and on this branch a rail no longer means selection at
all. Reworded to name the fill alone and point at "A rail means nesting, and
nothing else" — which sharpens rather than weakens #2565's point: with the rail
gone, the fill's own contrast is the entire signal for a selected row.

The two changes are otherwise complementary. #2565 rederived light's
`--bg-selected` off `--accent-fill`, which is exactly the token this branch now
leans on harder.

`pnpm run check` passes on the merged tree (8733 tests, 0 failures), including
the `light-contrast.test.ts` that arrived with #2565, and the five e2e specs
that cover the changed surfaces pass against a fresh build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
github-actions Bot added a commit that referenced this pull request Sep 7, 2026
github-actions Bot added a commit that referenced this pull request Sep 9, 2026
@jonathanKingston
jonathanKingston merged commit 4e85b00 into main Sep 9, 2026
23 checks passed
@jonathanKingston
jonathanKingston deleted the claude/copse-threads-prototype-c5c83c branch September 9, 2026 01:59
github-actions Bot added a commit that referenced this pull request Sep 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-full Force the full e2e suite (bypass the test-oracle thinning) on this PR update-screenshots

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant