Commit Graph

360 Commits

Author SHA1 Message Date
Jordan Ritter d815831a60 fix(shell-dashboard): update composed-cell test for docs dedup behavior 2026-04-28 15:48:47 -07:00
Jordan Ritter 1c7bead053 fix(shell-dashboard): center-align cell content to match X marks
The "no demo" X marks are text-center while depth chips and overlay
content were text-left, causing visual misalignment across all overlay
views. Center both the td and the ComposedCell flex column.
2026-04-28 15:45:27 -07:00
Jordan Ritter a322656e3d Merge branch 'blitz/dashboard-ux-fixes/b6' into blitz/dashboard-ux-fixes/integration 2026-04-28 15:45:08 -07:00
Jordan Ritter 9583b0b62b Merge branch 'blitz/dashboard-ux-fixes/b3' into blitz/dashboard-ux-fixes/integration 2026-04-28 15:45:05 -07:00
Jordan Ritter 6caa4a6e95 Merge branch 'blitz/dashboard-ux-fixes/b7' into blitz/dashboard-ux-fixes/integration 2026-04-28 15:45:01 -07:00
Jordan Ritter 8352ebe83d Merge branch 'blitz/dashboard-ux-fixes/b5' into blitz/dashboard-ux-fixes/integration 2026-04-28 15:44:58 -07:00
Jordan Ritter 1529b93392 Merge branch 'blitz/dashboard-ux-fixes/b4' into blitz/dashboard-ux-fixes/integration 2026-04-28 15:44:55 -07:00
Jordan Ritter 4f41f3aef5 feat(shell-dashboard): reorder toggle bar — presets before individual overlays 2026-04-28 15:36:19 -07:00
Jordan Ritter 1c2c81ebae fix(shell-dashboard): deduplicate docs row when health and docs overlays both active 2026-04-28 15:32:04 -07:00
Jordan Ritter 1d5fbd3ad3 feat(shell-dashboard): restore collapsible category rows in feature grid 2026-04-28 15:31:43 -07:00
Jordan Ritter 0c8d0ef71b feat(shell-dashboard): restore cell drilldown popup on depth chip click 2026-04-28 15:30:24 -07:00
Jordan Ritter 09ed887eba feat(shell-dashboard): sticky-pin overlay toggle bar to viewport top on scroll 2026-04-28 15:26:29 -07:00
Jordan Ritter d14dc2d003 feat(shell-dashboard): sticky-pin adaptive legend footer to viewport bottom 2026-04-28 15:26:09 -07:00
Jordan Ritter c789f43bbf chore(shell-dashboard): formatting and lint fixes
Split inline type imports into separate import-type statements per
oxlint consistent-type-specifier-style rule. Prefix unused connection
parameter. Apply oxfmt formatting.
2026-04-28 14:18:37 -07:00
Jordan Ritter 1332c10dec feat(shell-dashboard): wire overlays into page and feature grid
Collapse 5 tabs to 2 (Matrix | Ops). Page uses useOverlays for
composable state, passes overlays through to FeatureGrid and
ComposedCell. Grid gains overlay-aware column headers, ref-depth
column, and category separator colspan. Tab-shell gets deprecation
comment for future removal.
2026-04-28 14:18:36 -07:00
Jordan Ritter abb23516ac feat(shell-dashboard): adaptive stats bar and legend
Stats bar shows health/parity/docs summary counts that appear/hide
based on active overlays. Legend renders color-coded keys for each
active overlay layer.
2026-04-28 14:18:36 -07:00
Jordan Ritter 14974c1ada feat(shell-dashboard): overlay-aware column headers and ref-depth column
OverlayColumnHeader shows health strip, parity badge, and tally based
on active overlays. RefDepthColumn is a frozen column pinned after the
feature name that appears when the parity overlay is active.
2026-04-28 14:18:36 -07:00
Jordan Ritter ec99bbd587 feat(shell-dashboard): composed cell renderer
Stacks 4 overlay content layers (Links, Depth, Health, Docs) into a
single matrix cell. Each layer renders only when its overlay is active,
driven by the shared overlays Set from useOverlays.
2026-04-28 14:18:35 -07:00
Jordan Ritter a41d350b6e feat(shell-dashboard): overlay toggle bar with preset buttons
Pill-style toggle bar for 5 overlay layers with 3 presets (Default,
Developer, Ops). Each pill shows active state; presets apply curated
overlay combinations with one click.
2026-04-28 14:18:35 -07:00
Jordan Ritter f4ed2dd51e feat(shell-dashboard): overlay type system, state hook, and tests
Overlay model with 5 composable layers (links, depth, health, parity,
docs), URL hash persistence (#matrix:links,depth,...), localStorage
fallback, preset support, legacy tab-hash redirects, and minimum-one
enforcement. Uses replaceState to avoid polluting browser history.
2026-04-28 14:18:35 -07:00
Jordan Ritter d3bf61ef96 refactor(showcase): update shell-dashboard references for harness rename
Update comment references in next.config.ts, ops-api.ts,
ops-api.test.ts, live-status.ts, status-tab.tsx,
use-probes.integration.test.tsx, and Dockerfile.
2026-04-28 13:48:25 -07:00
Jordan Ritter 6404ced036 fix: reorder cell drilldown DIMENSIONS to show highest depth first 2026-04-28 13:04:54 -07:00
Jordan Ritter a5c5174ece fix: update useLiveStatus test to match INITIAL_CAP=2000 2026-04-28 12:10:51 -07:00
Jordan Ritter 3c71b9721a refactor: remove stale starter references from CI workflows and shell-dashboard types
- Update collision-avoidance comment in showcase_deploy.yml to remove
  starter-specific examples (service/starter collision no longer possible)
- Fix showcase_keep-alive.yml description: pings showcase services, not starters
- Remove "starter" from catalog-types.ts manifestation union type
- Remove dead starter cell skip logic from cell-matrix.tsx cellIndex builder
- Update depth-utils.ts comment (defensive null guard, not starter-specific)
- Remove starter-specific test cases from depth-utils and cell-matrix tests
2026-04-28 12:04:05 -07:00
Jordan Ritter 438161e2e2 fix(showcase): raise PocketBase initial fetch cap from 500 to 2000
The status collection now has ~1300+ records across all probe
dimensions. The paginated getList fetches in rowid order, so
the 500 cap loaded smoke/health/agent/d5/chat/tools records
but truncated all e2e per-cell records (created later by the
6-hourly e2e-demos probe). Without e2e records in the
LiveStatusMap the depth ladder stopped at D2 for every cell.
2026-04-28 09:40:06 -07:00
Jordan Ritter d4736a911a fix(showcase): update CI workflows, Dockerfiles, and configs
for integrations/ rename

Update GitHub Actions workflows to reference
showcase/integrations/ instead of showcase/packages/.
Fix Dockerfiles to dereference symlinks during COPY.
Remove obsolete showcase_template-drift workflow.
Update docker-compose, shell Dockerfiles, and registry paths.
2026-04-28 07:51:06 -07:00
github-actions[bot] 9019477e5f style: auto-fix formatting 2026-04-28 05:37:06 +00:00
Jordan Ritter 199ecef079 fix(showcase): prevent click-outside handler racing with cell button toggle
The mousedown-based click-outside handler fired before the cell button's
onClick, clearing selectedCell and preventing the toggle-close path from
executing. Now the handler checks if the click target is inside a cell
button and defers to the button's own onClick for toggle logic.
2026-04-27 22:27:47 -07:00
Jordan Ritter 12fbe96fc3 feat(shell-dashboard): add per-cell drilldown panel, enhance gaps filter, add failure count stat
Add clickable cell drilldown showing all 5 badge dimensions (health,
e2e, smoke, d5, d6) with tone, label, tooltip, and failure metadata
(fail_count, first_failure_at, signal payload) for red/amber badges.

Enhance Gaps filter to surface cells with RED probes as functional
gaps alongside structural gaps (unshipped cells).

Add Failures stat to StatsBar counting cells with red rollup.

Pass connection status through to CellMatrix for drilldown rendering.
2026-04-27 22:10:39 -07:00
Jordan Ritter 3b7f76c1b7 feat(shell-dashboard): wire up regression detection in depth ladder and regressions tab
Compare live achieved depth against CatalogCell.max_depth to detect
regressions. Wire the Regressions filter chip to actually filter rows,
compute real regression count in stats bar, and remove the hardcoded
empty state placeholder.
2026-04-27 22:01:48 -07:00
Jordan Ritter 866ee6641e fix(showcase): move built-in-agent column to last in dashboard matrix
Its manifest had sort_order: 0 which put it first. Pin it to 900
in the dashboard sort map so the REF column (langgraph-python)
stays first.
2026-04-27 11:48:03 -07:00
Jordan Ritter ca62be1035 fix(showcase): align Feature type field with data — shell_docs_url → shell_docs_path
The Feature interface declared `shell_docs_url` but all JSON
data files use `shell_docs_path` after the docs-green PR.
2026-04-27 11:36:20 -07:00
Jordan Ritter ac15a347cd feat(showcase-dashboard): add UWCT legend to Packages tab (#4296)
## Summary

Surface the U/W/C/T tier mapping inline next to the L1-L4 Status column
header on the Packages tab, so operators can read the strip without
cross-referencing docs.

| Letter | Label | Probe dimension |
|--------|-------|-----------------|
| U | Up | `health:<slug>` |
| W | Wired | `agent:<slug>` |
| C | Chats | `chat:<slug>` |
| T | Tools | `tools:<slug>` |

## Test plan

- [x] New test asserts the legend renders with exact text `(U=Up,
W=Wired, C=Chats, T=Tools)` and `data-testid="packages-uwct-legend"`
- [x] All 6 packages-section tests pass
- [x] `npx tsc --noEmit` clean
2026-04-26 17:25:07 -07:00
Jordan Ritter ecc506610d feat(showcase-dashboard): add UWCT legend to Packages tab L1-L4 header
Surface the U/W/C/T tier mapping inline next to the L1-L4 Status column

header so operators don't need to cross-reference docs to read the strip.

Maps to the underlying probe dimensions per level-strip.tsx:

  U = Up    (health:<slug>)

  W = Wired (agent:<slug>)

  C = Chats (chat:<slug>)

  T = Tools (tools:<slug>)
2026-04-26 17:04:26 -07:00
Jordan Ritter 747b446c8d fix(showcase/shell-dashboard): proxy contract hardening — build-arg, normalization, empty-env, tests
CR R1 follow-ups on top of the /api/ops proxy fix.

Bucket (a) — must-fix:

- Dockerfile: declare ARG/ENV OPS_BASE_URL in the builder stage. next.config.ts
  evaluates rewrites() at build time and throws if OPS_BASE_URL is unset, which
  aborted `next build` in CI. Mirrors the existing NEXT_PUBLIC_SHELL_URL /
  NEXT_PUBLIC_POCKETBASE_URL pattern.

- showcase_deploy.yml: pipe OPS_BASE_URL through to docker build for the
  shell-dashboard matrix entry, defaulting to the production
  showcase-ops-production.up.railway.app URL.

- next.config.ts: strip trailing slashes from OPS_BASE_URL before constructing
  the rewrite destination, matching the same normalization in
  src/lib/ops-api.ts:resolveBaseUrl so server-side rewrite and client-side
  fetch agree on the URL shape.

- src/lib/ops-api.ts: treat empty / whitespace NEXT_PUBLIC_OPS_BASE_URL as
  "no override". `??` only short-circuits on null/undefined, so an env var set
  to "" silently produced baseUrl="" and URLs of the form "/probes" with no
  /api/ops prefix.

- use-probes.integration.test.tsx: snapshot+restore process.env.NEXT_PUBLIC_OPS_BASE_URL
  in beforeEach/afterEach so tests never leak env state. Strengthen the proxy
  contract assertions: lock toHaveBeenCalledTimes(1), assert method=GET,
  cache=no-store, accept JSON header, and signal is an AbortSignal. Tighten
  the 404 regression to assert the canonical ensureOk message shape so a
  refactor that changes the format trips the test.

Bucket (b) — applied since the diff stayed focused:

- triggerProbe: add cache:"no-store" for parity with the GET fetches.
- fetchProbeDetail / triggerProbe: throw early when id is empty so callers
  get a clean error instead of a request to /probes//... .
- ensureOk: bump body-truncation cap from 200 to 500 chars and append a
  `[truncated, N bytes total]` marker so operators can see they're missing
  tail bytes when the server returns a long HTML/stack-trace body.
- ops-api.ts: drop dev-loop review-cycle tag prefixes (R2-C.3, R3-C, R3-D.1)
  from comments. Keep the actual rationale.
- ops-api.ts header docstring: clarify that NEXT_PUBLIC_OPS_BASE_URL is read
  live at runtime in this codebase (SSR + tests), not just statically inlined
  into the client bundle.

Verified:

- Tests: vitest run — 26 files, 293 passed, 1 skipped (no test count change).
- Typecheck: tsc --noEmit clean.
- Lint + format: oxlint + oxfmt clean on changed files.
- Local Docker build: `docker build --build-arg OPS_BASE_URL=https://...` succeeds.
  Without --build-arg the build fails with "OPS_BASE_URL must be set" as
  expected, confirming the fix is load-bearing.
2026-04-26 17:04:00 -07:00
Jordan Ritter c666deca65 fix(showcase/shell-dashboard): proxy /api/ops/* to showcase-ops via Next rewrite
Status tab was rendering "All probes idle. No upcoming runs scheduled."
even though showcase-ops `/api/probes` returns 9 probes.

Root cause:

* `lib/ops-api.ts` falls back to `/api/ops` when no explicit baseUrl and no
  `NEXT_PUBLIC_OPS_BASE_URL` is set. `NEXT_PUBLIC_OPS_BASE_URL` is not
  set on Railway shell-dashboard.
* `next.config.ts` was empty — there was no rewrite forwarding
  `/api/ops/*` to the showcase-ops service. So the browser hit
  `dashboard.showcase.copilotkit.ai/api/ops/probes` and got a 404 from
  the dashboard origin itself.
* Direct cross-origin fetch from the browser was not an option either:
  showcase-ops has no CORS allowlist.

Fix:

* Add a Next.js rewrite that forwards `/api/ops/:path*` to
  `${OPS_BASE_URL}/api/:path*` server-side. The browser only ever sees
  same-origin calls, and `OPS_BASE_URL` stays out of the client bundle.
* `OPS_BASE_URL` is required at build/start — fail loudly if unset
  rather than silently rendering an empty status table.
* Update `lib/ops-api.ts` doc comment to reflect that `/api/ops` is now
  the deterministic same-origin proxy path (contract), not a "guess".
* Add `src/hooks/use-probes.integration.test.tsx` — exercises the hook
  through the real `lib/ops-api` client to a mocked `fetch`. Asserts the
  default URL is exactly `/api/ops/probes`, parses real probe data, and
  surfaces a useful error when the proxy 404s. The pre-existing
  `lib/ops-api.test.ts` and `use-probes.test.ts` each mock at a different
  layer, so neither caught this contract gap.

Operational follow-up: `OPS_BASE_URL` set on Railway shell-dashboard service
points to `https://showcase-ops-production.up.railway.app`. Auto-update
will pick up the rewrite on the next image rebuild.
2026-04-26 17:03:20 -07:00
github-actions[bot] 6912a0720c style: auto-fix formatting 2026-04-26 21:36:10 +00:00
Jordan Ritter a2a82aaf45 Merge remote-tracking branch 'origin/main' into feat/d5-d6-probes
# Conflicts:
#	showcase/ops/src/probes/loader/probe-loader.test.ts
2026-04-26 14:34:18 -07:00
Jordan Ritter 544fb5794d feat(showcase-dashboard): add 'what do these chips mean?' explainer to Cells tab
Small, collapsible disclosure panel above StatsBar on the Cells tab with
plain-English definitions of the D0–D6 chip layers. Default collapsed;
open/closed state persists across navigations via
localStorage["chip-explainer-open"]. Footer link points to the Notion
plain-English page for deeper detail.

The Cells tab is consulted dozens of times a day by operators who already
know what the chips mean; the explainer is for first-time viewers and
rare refreshers, so the trigger is a small text button and the default
is collapsed to keep the layout clean.
2026-04-26 10:50:00 -07:00
Jordan Ritter b1c835ee5c fix(shell-dashboard): clear data on baseUrl change and honor supersession after fetch resolves
R4-B.1: useProbes effect now calls setData(null) on dep change to mirror
useProbeDetail's CR-B1.4 behavior. Without this, the dashboard renders
stale list data from the previous baseUrl until the new fetch resolves.

R4-B.6: useTriggerProbe checks controller.signal.aborted after the await
resolves. If a back-to-back trigger aborted the controller after the
fetch already returned, honor the R3-C.1 supersession contract and
resolve to null instead of returning the stale TriggerResponse.
2026-04-25 21:17:33 -07:00
github-actions[bot] 40610bbf35 style: auto-fix formatting 2026-04-26 03:10:52 +00:00
Jordan Ritter df88298429 merge: r3-fix-D 2026-04-25 20:09:42 -07:00
Jordan Ritter 8e061df87c merge: r3-fix-C 2026-04-25 20:09:42 -07:00
Jordan Ritter 38c8236aa2 fix(shell-dashboard): align status-table partial-pass tone with runs-list
R3-B.1: status-table lastRunTone() returned green for partial-pass runs
(failed=0, passed<total), reintroducing the misread that R2-D.4 fixed in
status-runs-list. Schedule table is the most-viewed surface, so this is
the highest-impact regression. Mirror runs-list semantics: amber tone +
"P/T (S skipped)" result text. Also explicit "P/T pass (F fail)" for
failed runs so the column reads consistently with the tone.

R3-B.2: StatusDetailPanel durations filter used \`typeof d === "number"\`
which admits NaN/Infinity (typeof NaN === "number"). The sparkline then
computed Math.min(...durations) = NaN and emitted "NaN,NaN" coords in
the polyline. Switch to Number.isFinite() so non-finite durations are
dropped.

Tests added (red-green TDD):
- status-table: amber tone + "skipped" text for partial pass; explicit
  "pass (N fail)" text for failed; "N/N pass" for fully-passed
- status-detail-panel: NaN/Infinity durations don't appear in sparkline
2026-04-25 20:02:43 -07:00
Jordan Ritter df5fa2d499 fix(showcase-dashboard): tighten error semantics and trigger return type in ops hooks
R3-C.1: useTriggerProbe.trigger now returns Promise<TriggerResponse | null>.
The supersession path resolves to `null` (typed) instead of the previous
`undefined as unknown as TriggerResponse` cast, which lied about the
return shape and would crash any caller that read fields off the result.

R3-C.2: useProbeDetail clears `error` on id change so the detail panel no
longer renders a stale error message under a freshly-selected probe header.

R3-C.3: useProbes clears `error` on dep change (e.g. baseUrl swap) so a
prior dep tuple's failure does not persist under the new one.

R3-C.4: useTriggerProbe clears `error` at the start of each trigger call
so a successful retry leaves no sticky error from the prior failure.

Bonus: parseJson now attaches the original parse error as `cause` on the
wrapper so debuggers can walk back to the SyntaxError name/stack without
re-parsing the wrapped message.

Tests: red-green tests added for each behavior; full file suite 49/49.
2026-04-25 20:02:02 -07:00
Jordan Ritter f2a7e73d4b fix(shell-dashboard): unify StatusTriggerButton close paths
R3-D.2: the toggle-close branch on the Trigger button forgot to reset
pickerOpen and selected, while outside-click and Escape both did. So
toggling the menu closed and reopening it showed ghost checks from a
prior session. Extract a closeMenu() helper used by all three close
paths so the invariant is structural, not duplicated.

Bonus: add aliveRef guard so async rejections from onTrigger that
resolve after unmount don't trigger setState-on-unmounted warnings.
2026-04-25 20:01:42 -07:00
Jordan Ritter 9eb20d7de1 fix(shell-dashboard): add cache: no-store to ops-api GET fetches
R3-D.1: fetchProbes and fetchProbeDetail are polled every ~10s for live
status data. Without an explicit cache directive the browser and Next.js
App Router fetch wrapper may serve stale responses, defeating the poll.
Add cache: 'no-store' to both GET call sites and cover with tests.
2026-04-25 20:01:35 -07:00
Jordan Ritter 4861ee043f fix(showcase-dashboard): correct misleading 'last pass' tooltip copy for degraded state
The degraded-state tooltip read "stale — last pass @ <observed_at>", but
observed_at is the most recent producer tick (when the row was last
*seen* in any state) — for a degraded row that is when degradation was
last observed, NOT when it last went green. Operators reading "last
pass @ ..." would mis-triage by treating that timestamp as the last
green tick.

Change copy to "stale — last seen @ <observed_at>" and add a covering
test asserting the new wording (and the absence of "last pass").
2026-04-25 19:54:07 -07:00
Jordan Ritter 17edaccee1 merge: origin auto-format 2026-04-25 19:50:54 -07:00
Jordan Ritter 3980bb1b61 merge: r2-fix-D R2 CR fixes 2026-04-25 19:48:01 -07:00