@calltelemetry/dsh-review-float
v0.16.0
Published
Floating PR/review status bar for DeepSeek Harness: a shell.overlay bar with a docked detail pane and an exploded review board.
Maintainers
Readme
dsh-review-float
A frame-wide floating PR / review status bar for DeepSeek Harness (dsh).
dsh plugin --profile ctweb add @calltelemetry/dsh-review-floatPublished to npm under the @calltelemetry scope, so it installs by version. No
git credential is required to consume it.
Listing the package in dsh.profile.bundles is the entire mount, because it
ships its own cordis.patch.yml (dsh.bundle.patch):
"bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "@calltelemetry/dsh-review-float"]No hand-edited profile patch is ever required — a - id: review-float row would
duplicate the loader entry and crash boot. In the Call Telemetry workspace this
mount is owned by DSH_THIRD_PARTY_PLUGIN_PINS in scripts/ct-meta/sync.py,
which renders the pin and installs it in one change (ADR 0656). Restart the
profile afterwards.
What it does
It registers one additive entry into the shell.overlay list slot — the
seat the layout package documents as "a badge, a toast stack or a status pill
… the layer itself is click-through — entries opt back into pointer events."
| State | Surface |
|---|---|
| Bar | Always-on pill above the composer: N running · M need you, then per-PR chips |
| Docked pane | Click a chip → 460px panel with exact head SHA, verdict, CI, progress, findings |
| Exploded board | Click Board → four columns: Running / Ready to merge / Needs you / Queued |

Live, not mocked: 14 real open PRs with the Review Yeti verdict read from each
head's check run. docs/shots/ also has the docked pane and the exploded board;
docs/prototype.html is the standalone design prototype.
Development
npm install # TypeScript only; no bundler required
npm run build # tsc -> src/ transpile -> module-loader bundle in lib/
npm run check # exits 1 if the committed lib/ has drifted from src/src/ is the source of truth. lib/ is committed on purpose: a link: or
git install consumes the built bundle directly, and dsh-client-modules requires
lib/client.js to exist before launch. npm run check is what keeps that
trustworthy.
Layout
src/client.ts browser half — the bar, pane, and board
src/index.ts host half — empty apply, so the package owns a Loader row
src/types/platform.d.ts ambient `react` (a PLATFORM_MODULES baseline module)
src/types/harness.d.ts ambient client context (slots + effect)
scripts/build.mjs real build: tsc transpile + module-loader envelope
cordis.patch.yml dsh.bundle.patch — the self-mounting loader rowNo bundler. tsc transpiles src/ and scripts/build.mjs wraps the output
in the window.__ModuleLoader__.load({id, factory}) envelope that every shipped
@deepseek-ai/dsh-client-ui-* package uses (they use tsdown for the same job).
The plugin requires only react, which the shell provides from its frozen
PLATFORM_MODULES baseline — so there is no second React copy and no
dsh.client.external entry.
Design constraints honoured
- Additive, not a takeover.
shell.overlayis a list slot; the entry carries a plugin-owned id (review-float), never a core row id. - Click-through. The root stays
pointer-events: none; only the bar, the pane and the board opt back in, so the app underneath is never blocked. - Theme-native. Every colour is a
--dsw-alias-*token with a literal fallback, so it follows light/dark automatically. - Read-only viewer. It renders review status and never dispatches review
work, opens a second reviewer, or posts to GitHub. The detail pane carries a
visible
policynote saying so, and it deliberately does not compete with the official Review Yeti action.
Data sources
The bar is fed by the host half, which serves one read-only snapshot on the
shared /api channel (/api/review-float.snapshot). The browser half polls it
every 20s through connection.rpc. The browser never holds a credential and
never talks to GitHub directly.
Two independent sources, deliberately:
| Source | Supplies | Required? | |---|---|---| | GitHub GraphQL | PR identity, exact head, CI ratio, and the Review Yeti verdict | yes | | Review Yeti MCP | The live phase of in-flight reviews, and per-finding severity (P0/P1/P2) for the detail pane | optional |
Where live progress actually comes from
get_review_status reads review_runs.stage from Postgres and returns a live
phase — queued, evaluating_personas, arbitration, completed. In-flight
rows are enriched from it, so the bar shows real state while a review is running
(observed live: #5149queued, #3414queued).
This is deliberately not an event stream. The bot's LiveStreamBus is a
process-local singleton fed only by the worker execution path, and review workers
run as separate pods, so no SSE route can deliver their progress across a process
boundary. The phase above is durable Postgres state, which is why it works
without any event plane.
The query is bounded: running rows only (typically 1–6, not the full list), fanned out in parallel. If the MCP is unreachable the row keeps the phase parsed from the check-run summary rather than losing the field.
The Review Yeti verdict is a GitHub check run named Review Yeti on the
exact head, so verdict and CI arrive in one call — no extra dependency. That is
why the surface still renders fully when the MCP token is absent: rows simply
carry no finding severities, and the snapshot says so.
| Env | Effect |
|---|---|
| CT_AGENT_GH_TOKEN / GH_TOKEN / GITHUB_TOKEN | GitHub credential, most explicit first |
| (none set) | falls back to gh auth token — the operator's existing login |
| REVIEW_YETI_MCP_AUTH_TOKEN | overrides the Doppler-resolved finding-severity token; never required |
An absent GitHub credential renders review feed unavailable with the reason,
never fabricated rows. An org with zero open PRs renders no open PRs — a
distinct state from an unreachable feed.
No token setup required
REVIEW_YETI_MCP_AUTH_TOKEN is a first-class entry in ct-meta's MCP catalog
(ct-meta/mcp-servers.json), whose canonical source is the Doppler project
review-yeti / config prd. Agents get it through that catalog; this plugin
resolves it directly from the same source, so nothing has to be exported.
Order: an explicit REVIEW_YETI_MCP_AUTH_TOKEN in the environment (a caller
override), then doppler secrets get … --project review-yeti --config prd.
Memoised on success only, so a doppler login performed after the page opened
starts working without a restart.
If neither resolves, the bar still renders every verdict and CI ratio (those come from the GitHub check run); only finding severities go away, and the detail pane names both sources it tried rather than showing an empty list.
Verified
Built and checked against [email protected] / [email protected] / Node 24.21.0 / tsc 5.
Live phase verified end-to-end: with no credential in the environment, the bar rendered
#5149queued,#706queued,#3416queued,#3414queuedand#786queuedwhile those reviews were running, matchingget_review_status.Published artifact verified:
0.1.2was extracted from the registry and a clean unauthenticated consumer install was confirmed to carry the live-phase code — the check is a symbol grep, not a version string.dsh-plugin-check(strict): 19/20 pass, 0 checks failed. The single non-pass isnot-in-hub, an external catalog-intake check that a private repository cannot satisfy.Live data verified against GitHub truth:
cisco-cdr#5144readsBLOCKEDwhere itsReview Yeticheck isfail;ct-meta#3384readsSHIPwhere it ispass. 14 open PRs across the org render with real head SHAs and CI ratios.Booted a full
ctwebclone: bundle servedHTTP 200, plugin self-mounted fromdsh.profile.bundleswith no manual patch row.Rendered in a real browser (headless Chrome over CDP, DOM assertions not screenshots): bar mounted, 14 chips, lead
3 running · 2 need you; clicking a chip opened the pane with the real head SHA (cisco-cdr#5144→b9e6cc6); Board opened all four columns. Zero console errors.Load: snapshot steady at ~2.5-3s over 5 sequential calls; 5 concurrent calls did not serialize destructively (3.4-3.9s each). A 30-poll soak run back-to-back returned 200 on every call with zero RSS growth, and GitHub's GraphQL limit was still
5000/5000afterwards — one call per poll is ~180/hour against a 5000/hour ceiling, so a single tab has ~28x headroom.Degradation is honest: with the MCP token absent,
sources.yetireadsfalseand the findings endpoint returnsfinding detail off — set REVIEW_YETI_MCP_AUTH_TOKENrather than an empty list. With it present,ct-release#1718andct-infrastructure#657both returned real["P2"]severities.Headless-browser verified: bar mounts (
pointer-events: autoover anonelayer), chip click opens the pane at 462px with the head SHA shown, Board explodes to 4 columns, zero console errors.
