🌈 feat(notes): tint inline notes per agent author#294
Conversation
Confidence Score: 4/5Safe to merge; color logic is well-tested with WCAG contrast assertions and all paths fall back to existing theme defaults. The implementation is thorough and the fallback chain is correctly handled at every call site. The only noteworthy items are two style-level observations: duplicate title-formatting functions across AgentInlineNote and agentPopover that will need coordinated updates if the format ever changes, and the mutable string[] type on noteAccentPalette where readonly string[] would better reflect the intent. Neither affects runtime behaviour. No files require special attention; src/ui/lib/agentColor.test.ts has a minor WCAG threshold inaccuracy but it does not affect any of the assertions for the current palette values. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["annotation.author (string | undefined)"] --> B["resolveAuthorAccent(author, theme.noteAccentPalette)"]
B -- "null (no author / empty palette)" --> C["theme.noteBorder / theme.accent fallback"]
B -- "accent hex string" --> D["AgentInlineNote border + sides"]
B -- "accent hex string" --> E["deriveAuthorBackground(accent, appearance)"]
B -- "accent hex string" --> F["deriveAuthorTitleBackground(accent, appearance)"]
E -- "HSL: fix lightness, cap saturation" --> G["noteBackground tint"]
F -- "HSL: fix lightness+1 step, cap saturation" --> H["noteTitleBackground tint"]
B -- "accent hex string" --> I["reviewRenderPlan: Map(side → author)"]
I --> J["PlannedRow note-guide-cap { author }"]
J --> K["PierreDiffView → AgentInlineNoteGuideCap accent prop"]
|
3f32dcf to
cd11527
Compare
The AgentAnnotation schema has carried an optional `author` field end-to-end (sidecar JSON, session daemon, wire protocol) but the TUI never surfaced it. Render it in the note title bar and the matching agent popover so reviewers can tell which agent left which note when multiple agents annotate the same diff. Falls back to "AI note" when author is absent for backward compat.
When an annotation carries `author`, derive a stable accent color from a new per-theme `noteAccentPalette` via FNV-1a hash and tint the entire inline note card from that accent — top/side/bottom borders, the title row's right-edge bar, the trailing `╵` guide cap below a multi-row range, and the body/title backgrounds (derived in HSL with low saturation and theme-appropriate lightness so `theme.text` / `theme.muted` body copy stays legible). The cap accent is threaded through the planned `note-guide-cap` row and resolved in PierreDiffView, with first-author-wins when two notes share a row+side. Background tint falls back to `theme.noteBackground` / `theme.noteTitleBackground` when no author is set, palette resolution returns null, or accent parsing fails; unauthored notes keep `theme.noteBorder`. Contrast-ratio tests guard the dark and light theme palettes against `theme.text`. Also spread the `3-agent-review-demo` example across all five accent slots (llama, grok, phi, gemini, sonnet) so one screenshot captures the full palette.
cd11527 to
9a2a460
Compare
Summary
Tint inline agent notes per author so reviews with multiple agents are visually distinct at a glance. The author name in the title bar (added in the linked PR) tells the reviewer which agent wrote a note; this PR makes that distinction readable without reading the label, by giving each agent a stable colour across the diff.
I personally want this because I'm doing crazy agent orchestration for laughs and I'd like to know which agent is saying what.
Implementation:
noteAccentPaletteonthemes.ts(five accents per appearance) tuned for dark + light themes.src/ui/lib/agentColor.tsresolves an annotation's author to a stable palette slot via FNV-1a hash, then derives:╵glyph below a multi-row annotation rangetheme.text/theme.mutedbody copy stays legible.note-guide-caprow inreviewRenderPlan.tsand resolves inPierreDiffView.tsx. First-author-wins when two notes share a row+side.theme.noteBackground/theme.noteTitleBackgroundwhenever no author is set, palette resolution returnsnull, or accent parsing fails. Unauthored notes also keeptheme.noteBorder.3-agent-review-demoacross all five accent slots (llama,grok,phi,gemini,sonnet) so one screenshot captures the full palette.Tests include contrast-ratio assertions against
theme.textfor both palettes, so accidentally introducing an illegible accent fails CI.Screenshot
Verified
bun run typecheckbun run lintbun test— same baseline failures asupstream/main, no new failures. +21 net passing tests from the new colour/render-plan/ui suites.bun run test:integration(PTY)bun run test:tty-smokeexamples/3-agent-review-demo/change.patchwith--agent-context examples/3-agent-review-demo/agent-context.json— five distinct tints visible on the demo.Related
Depends on #293. The colour tests in this PR assert title text like
"sonnet · ▶ new 2-4", which is rendered by the title-bar change in #293. Please merge #293 first; this PR's diff will collapse to its own commit once the base lands onmain.