Skip to content

feat(agent-plugin): visual pass on the decision-review and decision-board canvases (0.11.0) - #282

Merged
mbeacom merged 6 commits into
mainfrom
feat/canvas-visual-pass
Oct 10, 2026
Merged

mbeacom merged 6 commits into
mainfrom
feat/canvas-visual-pass

Conversation

@mbeacom

@mbeacom mbeacom commented Oct 10, 2026 •

Copy link
Copy Markdown
Owner

What and why

I'm about to record a demo of the two Copilot app canvases. They worked, but they looked plain, so this PR is a visual pass on both. Function, routes, actions, the payload, the Content-Security-Policy, and the agent surface are all unchanged. Plugin 0.11.0.

Shared look.

  • Both pages now share one stylesheet, extensions/adrkit/canvas-theme.mjs. Each page's /app.css is that block followed by its own rules, so there's no new route.
  • Every colour still reads the app's injected token first, so theming is still the app's. The built-in fallbacks now follow prefers-color-scheme. Before this, a dark render outside the app kept a white page and dark text; only native form controls followed the system. 16 of my 34 baseline dark/light pairs were byte-identical, and the rest differed only in those controls and in timestamps. In the after set, all 36 pairs differ, with dark page colours.
  • A test checks every fallback text colour at 4.5:1, against the background, the surface, and each status hue's own tint, in both themes.
    • That test failed on the first run: light green on its tint came out at 4.33:1 and dark red at 4.37:1. I moved those hues to fix it.
  • Status is never shown by colour alone. Every badge has a symbol and a word.

decision-review.

  • Each governing record is a card showing its status, its verdict, and its provenance: the affects pattern, or the marker's file:line, exactly as adr check reports it (ADR-0047).
  • Findings are grouped by severity, and notes are collapsed.
  • The review cost appears in plain words under the button.
  • Loading, empty, and error states are distinct. The error state shows the fixed messages, including the not-a-work-tree one.
  • Run review now starts disabled until the first snapshot arrives. Before, it could be clicked while the page was still loading.

decision-board.

  • Pan and zoom work by drag, Ctrl/Cmd+wheel (pinch), the −/+/Fit buttons, or the + - 0 and arrow keys on the focused graph. A plain wheel still scrolls the panel.
  • The zoom math lives in pure viewBox helpers in board-view.mjs. The page embeds them from their own source, and a test runs the embedded copies.
  • Selecting a record dims everything except its neighbours. Labels are clipped, and the full title shows in an SVG <title>. The legend is clearer.
  • Approvals show as dots against the quorum, plus the numbers. Objections show as two labelled counts.
  • The review controls label their three steps. Step 2, the confirm, is its own highlighted box and names step 3, the host's dialog.
  • With recording off, the fixed note appears once above the queue, and each disabled control carries it.
  • Still no readiness wording.

One brief item I could not do: showing who raised each objection. adr queue --format json (QueueReport v1) reports only the unresolved and resolved counts, so there's nothing to allowlist. It needs a CLI field, which I've left out of this PR.

Evidence

  • Spend: 0 AI credits. I opened every canvas in a headless Copilot CLI 1.0.93 SDK host with no prompt and no run_review.
  • I captured each page in Chrome 154 headless over the DevTools protocol, at 900 and 420 px, light and dark.
  • Corpora:
    • this repository (52 records, 255 relationships)
    • a five-record fixture with a proposed record carrying 2/3 approvals, one open and one resolved objection, and an SLA deadline
    • a stale-marker variant of that fixture
    • a clean clone
    • a non-git directory
    • a 320-record synthetic corpus
    • a copy of the adrkit-demo corpus
  • I used the chrome-devtools MCP to check keyboard order and accessible names, and to re-measure a resize after load. That check found a stale-scale bug, which I fixed and tested.
  • Three states can't be reached headlessly, so I rendered them from a stub that serves the shipped page strings with the real headers and a snapshot captured from the host: a finished review, the enabled review controls, and the confirm step. The host has no completed run, and it reports that it cannot ask for confirmation.
  • Everything is unmeasured in the Copilot app. There, the app's own tokens replace the fallback colours.

Before/after pairs: gh can't attach images, so they're described here, with paths in my working notes (U-shots/before/ and U-shots/after/, 68 and 72 PNGs):

  • review-fixture-*: before, flat sections with provenance hidden under "Evidence"; after, cards with status and verdict badges, provenance chips, and the cost line.
  • review-not-a-work-tree-*: before, the message was a bullet under Notes after six "None." sections; after, a red error callout at the top.
  • board-full-*: before, 255 full-weight edges across a horizontally scrolling SVG; after, a zoomable frame with lighter edges, a zoom bar, and a legend grouped by Status and Relationships.
  • board-confirm-*: before, the confirm looked like the idle row with different labels; after, a highlighted "Step 2 of 3" box that names step 3.

Checklist

  • Commits are DCO signed off.
  • No ADR changes. This is presentation only, within ADR-0046, 0047, 0050, and 0052, and the payload, routes, and actions are unchanged.
  • No schema change.
  • No packages/ci/src or @adrkit/core change.
  • New behaviour is covered by tests, each seen failing first. I wrote test/visual-pass.test.ts (42 tests) and planted 22 mutations, one per behaviour, each restored afterwards. The two contrast tests failed for real on the first run.
  • bun test (4011 pass), typecheck, lint, check:stale-refs, emit:manifest, check:changelog, and check:dco all pass, and claude plugin validate passes for the plugin and for the marketplace.

Notes for reviewers

  • The confirm step is styled with data-step="confirm" rather than a class, because the review tests find the box by its exact className (see AGENTS.md).
  • The graph opens fitted when it fits at 0.6 scale or more. Otherwise it opens at the top, fitted to the width. On the 52-record corpus at 420 px the labels are small; zoom and focus are the way in.

…oard canvases

I gave both Copilot app canvases one shared stylesheet (canvas-theme.mjs)
so their tokens, badges, buttons, and focus ring cannot drift. Colours still
read the app's injected tokens first; the fallbacks now follow
prefers-color-scheme, where before every render outside the app was light.
A test checks every fallback text colour at 4.5:1 in both themes.

decision-review: governing records as cards with status, verdict, and
provenance in view; findings grouped by severity; notes collapsed; the
review cost stated under the button; distinct loading, empty, and error
states, the last showing the fixed messages. The paid button starts
disabled until the first snapshot.

decision-board: pan and zoom through pure viewBox helpers (board-view.mjs,
embedded into the page from their own source), neighbour highlight,
a clearer legend, approvals as dots against quorum, labelled objection
counts, and review controls that label their three steps. With recording
off, the fixed note is shown once above the queue.

Routes, actions, payload, and the CSP are unchanged. No inline style,
no HTML sink, no external asset. A new test bans inline style on both pages.

Signed-off-by: Mark Beacom <m@beacom.dev>
Signed-off-by: Mark Beacom <m@beacom.dev>
…rd after Fit

A plain wheel over the board graph now scrolls the panel; only Ctrl or Cmd
with the wheel zooms, as the hint says. Fit makes the next resize re-open the
graph. I also record the after-load resize I measured through the
chrome-devtools MCP, and fix the README's stacking breakpoint.

Signed-off-by: Mark Beacom <m@beacom.dev>
Copilot AI balanced review requested due to automatic review settings October 10, 2026 02:36
The baseline dark renders kept a white page and dark text; 16 of 34 pairs
were byte-identical and the rest differed only in native form controls and
timestamps. I had written that every pair was identical.

Signed-off-by: Mark Beacom <m@beacom.dev>
@github-actions

github-actions Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

Decisions governing this change

9 accepted decisions govern this change · 5 active proposals

  • 0007 — Isolate integrations as optional adapters and build only against public surfaces
    • via path: packages/adapters/**
  • 0016 — Require every check to be observed failing before it counts as coverage
    • via path: packages/adapters/*/test/**
  • 0028 — Ship decision memory as a portable agent plugin, and omit the MCP wiring hosts cannot honor
    • via path: .claude-plugin/**
    • via path: packages/adapters/agent-plugin/**
  • 0030 — Keep extension surfaces that carry a dependency tree outside this repository
    • via path: packages/adapters/**
  • 0034 — Extend the portable agent plugin with decision backfill
    • via path: .claude-plugin/**
    • via path: docs/reference-verification-agent-plugin.md
    • via path: packages/adapters/agent-plugin/**
  • 0038 — Offer the bootstrap decision record as an offer rather than a backfill candidate
    • via path: docs/reference-verification-agent-plugin.md
    • via path: packages/adapters/agent-plugin/**
  • 0040 — Keep derived surfaces in lockstep with three mechanisms matched to three classes of drift
    • via path: AGENTS.md
  • 0045 — Ship an advisory adr-review dynamic workflow in the portable agent plugin
    • via path: docs/reference-verification-agent-plugin.md
    • via path: packages/adapters/agent-plugin/extensions/**
  • 0046 — Ship a read-only decision-review canvas for the GitHub Copilot app in the portable agent plugin
    • via path: docs/reference-verification-agent-plugin.md
    • via path: packages/adapters/agent-plugin/extensions/**
Active proposals touching this change (5)

These are not yet ratified and do not bind this change:

  • 0047 — Show provenance, review cost, and a read-only proposal queue in the decision-review canvas (proposed)
    • via path: docs/reference-verification-agent-plugin.md
    • via path: packages/adapters/agent-plugin/extensions/**
  • 0048 — Supply read-only adrkit tools to GitHub Copilot through the plugin extension instead of MCP wiring (proposed)
    • via path: docs/reference-verification-agent-plugin.md
    • via path: packages/adapters/agent-plugin/extensions/**
  • 0049 — Add advisory session hooks that never block to the portable agent plugin (proposed)
    • via path: docs/reference-verification-agent-plugin.md
    • via path: packages/adapters/agent-plugin/extensions/**
  • 0050 — Ship a read-only decision-board canvas that maps the corpus from adr graph and adr queue (proposed)
    • via path: docs/reference-verification-agent-plugin.md
    • via path: packages/adapters/agent-plugin/extensions/adrkit/board*.mjs
  • 0052 — Record review from the decision board only after the host's own confirmation (proposed)
    • via path: packages/adapters/agent-plugin/extensions/adrkit/board*.mjs

Links point at 41f18d4, this run's GITHUB_SHA. Run adr explain <path> locally to see why a file is governed.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Dimmed graph labels fail contrast requirements, while fitting and Unicode truncation have concrete edge-case defects.

3 open findings
What changed in this PR

Adds the 0.11.0 visual refresh for both agent-plugin canvases.

Changes:

  • Introduces shared theming, responsive states, and accessibility styling.
  • Adds decision-board pan, zoom, highlighting, and review-control presentation.
  • Updates tests, documentation, packaging, and version metadata.

ADR MCP compliance could not be independently verified because the server was unavailable.

File Description
.claude-plugin/​marketplace.json Bumps marketplace versions.
AGENTS.md Documents canvas invariants.
CHANGELOG.md Records the visual release.
bun.lock Aligns workspace version.
docs/​reference-verification-agent-plugin.md Records headless verification.
packages/​adapters/​agent-plugin/​.claude-plugin/​plugin.json Bumps plugin version.
packages/​adapters/​agent-plugin/​README.md Documents the refreshed interfaces.
packages/​adapters/​agent-plugin/​apm.yml Bumps APM version.
packages/​adapters/​agent-plugin/​extensions/​adrkit/​board-page.mjs Implements the board UI refresh.
packages/​adapters/​agent-plugin/​extensions/​adrkit/​board-view.mjs Adds pure pan/zoom helpers.
packages/​adapters/​agent-plugin/​extensions/​adrkit/​canvas-page.mjs Implements review-canvas states and cards.
packages/​adapters/​agent-plugin/​extensions/​adrkit/​canvas-theme.mjs Adds the shared theme.
packages/​adapters/​agent-plugin/​package.json Bumps package version.
packages/​adapters/​agent-plugin/​skills/​decision-backfill/​SKILL.md Bumps skill version.
packages/​adapters/​agent-plugin/​skills/​decision-memory/​SKILL.md Bumps skill version.
packages/​adapters/​agent-plugin/​test/​packaging.test.ts Includes new modules in packaging checks.
packages/​adapters/​agent-plugin/​test/​visual-pass.test.ts Tests visual states, contrast, and navigation.

🧠 Review effort: Balanced

Comment thread packages/adapters/agent-plugin/extensions/adrkit/board-page.mjs Outdated
Comment thread packages/adapters/agent-plugin/extensions/adrkit/board-page.mjs Outdated
Comment thread packages/adapters/agent-plugin/extensions/adrkit/board-view.mjs Outdated
Mark Beacom and others added 2 commits October 9, 2026 22:44
…r, and keep dimmed labels legible

Three findings from review on #282:
- Fit may now go below the 0.2 zoom minimum, so a tall graph is shown whole,
  and zooming out stops at that fit.
- A clipped title is cut by grapheme (code point where segmenting is
  unavailable), so an emoji at the cutoff is never split.
- Dimming fades the record's box and stripe only; the label and the focus
  ring stay at full opacity.

Signed-off-by: Mark Beacom <markbeacom@Marks-MacBook-Pro.local>
…measured

Signed-off-by: Mark Beacom <m@beacom.dev>
@mbeacom
mbeacom merged commit d6ac16d into main Oct 10, 2026
17 checks passed
@mbeacom mbeacom self-assigned this Oct 10, 2026
@mbeacom
mbeacom deleted the feat/canvas-visual-pass branch October 10, 2026 03:02
@mbeacom mbeacom added the enhancement New feature or request label Oct 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants