Commit Graph

12110 Commits

Author SHA1 Message Date
Tyler Slaton 66662d4a88 fix(showcase/harness): raise e2e-deep outer timeout 3min → 10min
PR #4718 added the LGP D5 coverage wave, taking langgraph-python's
declared D5 feature set to ~28. With FEATURE_CONCURRENCY=2 that's 14
features per worker × ~15s realistic wall-clock = ~210s — over the
prior 3-min cap before any slack. Post-merge cycles confirmed the math:
17 langgraph-python features ran cleanly and flipped green, but the
remaining ~10 hit `errorClass: "abort"` with `errorDesc: "aborted"`,
the abort-cascade signature where the global cap fires before the
per-feature loop reaches them. Per-feature timeout (5min) bounds wedged
features but doesn't bound the slug's total feature count against the
outer cap.

Bump to 10 min — gives ~5x headroom at current feature count. Lighter
integrations (5–10 features, ~60s) still exit early without sitting on
the cap, so cycle wall-clock barely changes (cron stays every 15 min,
concurrency=4 hides the slow integration's tail behind the others).
Revisit `FEATURE_CONCURRENCY` before raising further — Chromium context
count scales with it and the Railway pod's 2.4GB headroom budget assumes
the current value.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 23:25:25 -07:00
Tyler Slaton 11ca7414c1 fix(showcase): get langgraph-python D5 cells unblocked (#4718)
## What does this PR do?

Realigns the langgraph-python showcase cells with the recent idiomatic
demo refactors so D5 (e2e-deep multi-turn conversation) probes start
landing green again. Production PocketBase showed 28 of 42 D5 rows
red for langgraph-python before this work; the failure mix was a
combination of dashboard mapping drift, runner-level cascade aborts,
post-refactor selector mismatches, and a few independent fixture or
demo-handler regressions.

The diagnosis and phased plan live in the conversation transcript;
this PR is the implementation. Each phase is its own commit so the
sequence reads top-to-bottom in `git log`.

### Phase 0 — dashboard ↔ harness mapping drift
- `shell-dashboard/src/lib/live-status.ts` `CATALOG_TO_D5_KEY` had three
  orphan entries (`hitl→hitl-steps`, `interrupt-headless`, and
  `tool-rendering-reasoning-chain`) reading PB rows the harness no
  longer emits, plus seven missing entries (e.g. `byoc-json-render`,
  `hitl-in-chat-booking`, `open-gen-ui-advanced`,
  `tool-rendering-default-catchall`, etc.) that left their cells
  stranded at D4 even when the harness wrote green.
- Aligned the dashboard map exactly to harness `REGISTRY_TO_D5` and
added a drift test in
`harness/src/probes/helpers/d5-mapping-drift.test.ts`
  asserting structural equality going forward (parses dashboard
  source via fs — no cross-package import, since shell-dashboard
  intentionally lives outside the pnpm workspace).

### Phase 1 — e2e-deep driver robustness
- Added `isClosed`, `route`, `unroute` to the wrapped `E2eDeepPage`
  (optional in the interface so test fakes don't have to track them).
  Unblocks `d5-readonly-state-context` which needed `page.route()`.
- `captureDiagnostics` short-circuits when the page is already closed.
- Raised `DEFAULT_TIMEOUT_MS` from 5min to 30min and added a 5-min
  per-feature wall-clock race. ~30 features × ~45s avg /
  FEATURE_CONCURRENCY=2 was tripping the global limit and aborting
  every still-pending feature with fc=1 — that cascade is the bulk of
  the recent reds. The per-feature timeout prevents a single wedged
  feature from monopolizing the new larger global budget.

### Phase 2 — beautiful-chat toggleTheme cascade root
- `_beautiful-chat-shared.ts:assertToggleTheme` switched from a 200ms
  manual `page.evaluate` poll over 30s to Playwright's
  `waitForFunction`. The native polling is event-driven inside the
  browser context, disconnects cleanly on page-close, and produces a
  named diagnostic when the renderer crashes mid-poll. fc=97 historical.
- Demo-side: dropped `[theme, setTheme]` from the `useFrontendTool`
  deps array on `toggleTheme`. The handler reads `document` directly
  and `setTheme` is stable, so the deps forced a hook re-registration
  on every flip — racing with in-flight tool results.

### Phase 3 — probe selector realignment per refactor
- **3A `d5-chat-css`**: HALCYON theme replaced the legacy hot-pink/amber
bubbles. Probe now checks user-bubble inner element's
`border-left-color`
for `rgb(196, 74, 31)` (halcyon-ember), font-family for "JetBrains
Mono",
  and assistant bubble font-family for "Fraunces" — three independent
  signals each with a specific error.
- **3B `d5-chat-slots`**: Added `data-slot-label={label}` to
`SlotMarker`'s
  outer span (idiomatic data attribute, not a testid restoration);
  probe asserts `[data-slot-label="MessageView.AssistantMessage"]`.
- **3C `gen-ui-headless` → `headless-simple` (slug rename)**: The
  refactor stripped gen-UI capability from headless-simple — it's now
  a "two hooks, one shadcn shell" text-only template. Renamed the D5
  literal so the slug describes what's tested, removed the old probe
  + fixture + tests, added a lightweight chip-click + assistant-bubble
  probe. `headless-complete` keeps its existing literal because it
  still drives the full gen-UI surface.
- **3D `d5-gen-ui-headless-complete`**: Rewrote for the new 4-chip
set (Weather / Stock price / Highlight a note / Revenue chart). Per-turn
  asserts the matching tool-card testid plus a distinguishing text
  fragment. Dropped the missing `[data-testid="headless-suggestions"]`
  wrapper selector and the old Excalidraw + continent turns.
- Restored `data-message-role` on both headless demos' UserBubble +
  AssistantBubble (the runner cascade documents this as the headless
  contract; refactor dropped it).

### Phase 4 — auth lifecycle rework
- New demo unmounts `<CopilotKit>` on sign-out, so the old
  401-error-banner surface no longer applies.
- `d5-auth.ts` now: `preFill` clicks the SignInCard's sign-in button to
  mount the chat, runner sends one turn, assertion clicks sign-out and
  waits for SignInCard re-mount (unmount IS the assertion). Dropped
  the brittle 500ms `setTimeout` and the chat-send-and-401 dance.
- `tests/e2e/auth.spec.ts` rewritten: 5 specs covering load, sign-in,
  authenticated send, sign-out unmount, sign-in-again.

### Phase 5 — independent fixture/probe regressions
- **5A** `d5-frontend-tools.ts`: PILL_GRADIENT_HINTS now include the
  literal 6-digit hex codes from each fixture (`#ff7e5f`, `#0a3d2e`,
  `#1e3a8a`, etc.) so the keyword check matches the deterministic
  hex-only gradient strings.
- **5C** `gen-ui-agent.json` + **5D** `shared-state-streaming.json`:
  Stringified `arguments` to OpenAI wire shape (was a raw object) and
  added explicit tool-call `id` fields, matching the dominant fixture
  convention.
- **5E** Lifted `clickByJs(page, selector)` from `d5-auth.ts` into
  `_genuine-shared.ts`; `d5-gen-ui-interrupt` now uses it to bypass
  the `<cpk-web-inspector>` overlay that intercepts pointer events
  before React's synthetic event system.
- **5F** Added the `get_stock_price` fixture pair (call + narration)
  to `tool-rendering.json` for the `current price of AAPL` prompt.
  The custom-catchall probe now mounts both WeatherCard + StockCard.

### Slug alignment notes
- `gen-ui-headless` → `headless-simple` is the only D5 literal renamed.
  Rationale lives in the lock-step comment in `d5-registry.ts`.
- The dashboard's `agentic-chat-reasoning`, `interrupt-headless`, and
  `tool-rendering-reasoning-chain` mappings were dropped (their D5
  scripts were removed in genuine-pass Phase 0). Cells using those
  registry IDs now correctly cap at D4 (no mapping = at-ceiling green).

### Known follow-up (NOT in this PR)
- `d5-reasoning-display` stays red. The probe correctly asserts the
  demo's reasoning slot renders, but aimock's fixture format only
  supports `content` / `toolCalls` — there's no way to emit
  `REASONING_MESSAGE_*` events from a fixture. The aimock provider
  source isn't in this repo; needs a separate change there.

## Related PRs and Issues

- Builds on the genuine-pass series: #4707
  (`test(showcase/langgraph-python): genuine D5 + Layer-1 e2e pass`).
- Builds on the demo refactor commits 3e157a1e0 / 4ff8dd608 / bd9da67c4
  / 83884b0be (May 5–6) that introduced the post-refactor selector
  surface this PR realigns to.

## Test plan

- [x] `pnpm typecheck` passes for `showcase/harness` and
`showcase/integrations/langgraph-python`.
- [x] 192 harness vitest tests pass (including new `d5-mapping-drift`,
      rewritten `d5-auth`, `d5-chat-css`, `d5-chat-slots` tests; old
      `d5-gen-ui-headless` tests deleted).
- [ ] Trigger one production e2e-deep run after merge (per
      `showcase/RUNBOOK.md`) and verify the langgraph-python red
      count drops from 28 → small remnant. The fc=1 cascade should
      drain on the first run thanks to the per-feature timeout.
- [ ] Confirm dashboard renders the `hitl` cell at D5, and the
      previously-stranded cells (`open-gen-ui-advanced`, both
      `tool-rendering-*-catchall`, `byoc-json-render`,
      `hitl-in-chat-booking`, both `reasoning-*`) start advancing.

## Checklist

- [x] I have read the [Contribution
Guide](https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md)
- [x] If the PR changes or adds functionality, I have updated the
relevant documentation
- [x] "Allow edits by maintainers" is checked

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-05-07 22:46:53 -07:00
Tyler Slaton a5050dbe26 fix(showcase): retarget R15/R17 in legacy shell + harness copies
The shell-docs port (e2bef7a0b) updated R15/R17 sources to /integrations/built-in-agent
in showcase/shell-docs/src/lib/seo-redirects.ts and refreshed the snapshot fixture, but
left the legacy shell copy (showcase/shell/src/lib/seo-redirects.ts) and the harness
intentional-copy (showcase/harness/src/probes/drivers/seo-redirects.ts) on the old
/builtin-agent value. The redirect-decommission test imports from the legacy shell
file, so the snapshot diverged: fixture says /integrations/built-in-agent but source
generates /builtin-agent. Mirror the retargeting into both copies so all three files
(shell-docs source, shell legacy source, harness synced copy) agree with the fixture
and Validate Showcase passes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 22:41:18 -07:00
Tyler Slaton f0d83ef0b5 Merge branch 'main' into tyler/beautiful-haslett-a95038 2026-05-07 22:30:38 -07:00
Sam Julien dad0735baf feat(shell-docs): port redirect middleware + retarget destinations to shell-docs slugs (#4702)
## Summary

Two-part redirect work for the docs.copilotkit.ai → shell-docs cutover,
in one PR.

### Part 1 — Retarget destinations in `seo-redirects.ts`

shell-docs serves canonical framework docs at `/{fw-slug}/...` from the
host root (no `/docs/` prefix) and uses different framework slugs from
the legacy SHELL surface. The redirect catalogue has been retargeted
accordingly:

- **Drop the `/docs/integrations/` prefix** from every destination.
- **Apply framework-slug renames** in destinations:
  - `langgraph` → `langgraph-python`
  - `adk` → `google-adk`
  - `aws-strands` → `strands`
  - `microsoft-agent-framework` → `ms-agent-dotnet`
  - `crewai-flows` → `crewai-crews`
- **Re-flip the BIA → unselected rename** — `unselected/` was retired;
destinations now point at `/built-in-agent/`.
- **Slug-rename catch-alls** for the bare `/{old-slug}/*` form so legacy
upstream URLs (e.g. `/langgraph/quickstart`) 301 directly to the new
slug.
- **`/docs/integrations/*` and `/docs/*` catch-alls** so any URL still
carrying the legacy SHELL routing prefix lands at the shell-docs
equivalent.
- **`/migration-guides/*` → `/migrate/*`** (4 URLs).
- **Folder-index redirects** for shell-docs folders without an
`index.mdx` (`/troubleshooting`, `/migrate`, `/premium`, `/concepts`,
`/reference`).

390 redirect entries total in the new catalogue.

### Part 2 — Port middleware to shell-docs

- Copied the retargeted `seo-redirects.ts` to
`showcase/shell-docs/src/lib/`.
- Merged the SHELL redirect-middleware logic into shell-docs's existing
pageview-tracking middleware. Redirects fire first (with the
`seo_redirect` PostHog event); non-redirected requests still get the
`docs_pageview` capture and `distinct_id` cookie.
- Preserved the framework-scoped short-circuit so canonical
`/{fw-slug}/...` URLs are never hijacked by legacy patterns.
- Left the SHELL versions of `middleware.ts` and `seo-redirects.ts` in
place — the SHELL still serves `docs.showcase.copilotkit.ai` until DNS
flips.

## Test plan

- [x] `npm run build` clean in `showcase/shell-docs/`
- [x] `npm run build` clean in `showcase/shell/` (existing operation
unaffected)
- [x] `curl -sI
http://localhost:3099/docs/integrations/langgraph/quickstart` → 301 to
`/langgraph-python/quickstart`
- [x] `curl -sI http://localhost:3099/langgraph/quickstart` → 301 to
`/langgraph-python/quickstart`; `/aws-strands/quickstart` →
`/strands/quickstart`; `/migration-guides/v2` → `/migrate/v2`;
`/troubleshooting` → `/troubleshooting/common-issues`; `/coagents` →
`/langgraph-python`
- [ ] Validate full set against a running shell-docs instance with
`validate-redirects.ts` (run from `showcase/scripts/` against the
deployed preview)
2026-05-07 21:35:14 -07:00
github-actions[bot] d53deb7e45 style: auto-fix formatting 2026-05-08 02:53:06 +00:00
Tyler Slaton 691ad27ff2 fix(showcase/harness): correct d5-auth idiomatic re-mount test assertion
Test name says "succeeds when SignInCard re-mounts after sign-out" with
signInCardRemounts: true, so the assertion should resolve, not reject. The
.rejects.toThrow(/SignInCard.*did not re-mount/) was a stale leftover from
when the older single-shape probe always failed this scenario; the multi-shape
probe added in d8d32fd38 succeeds on this fixture, but the test wasn't updated
in lock-step.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 19:51:33 -07:00
Tyler Slaton a7d148f487 fix(showcase/aimock): stringify set_steps + write_document args in d5-all.json
Per-feature fixtures (gen-ui-agent.json, shared-state-streaming.json) were updated
to JSON-stringified arguments + explicit tool-call IDs to match the OpenAI wire
shape, but d5-all.json — the runtime fixture mounted by aimock per its Dockerfile
— still had raw-object arguments without IDs. The wire-shape parity claim was
true for the per-feature files but contradicted by the live fixture; aligning
d5-all.json closes that drift so what we tested matches what runs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 19:47:23 -07:00
Tyler Slaton 197c588c32 fix(showcase/langgraph-python): auth e2e spec uses v2 testid not v1 data-message-role
CR Round 3 final: my auth.spec.ts e2e was asserting on
[data-message-role="assistant"] which is the v1 react-ui RenderMessage
attribute. The auth demo uses v2 CopilotChat — its
CopilotChatAssistantMessage only emits data-testid="copilot-assistant-message".
The selector would never have matched and both tests would have
timed out at 30s when actually run.

Verified via grep:
- packages/react-core/src/v2/components/chat/CopilotChatAssistantMessage.tsx:192
  emits data-testid="copilot-assistant-message" (no data-message-role)
- packages/react-ui/src/components/chat/messages/RenderMessage.tsx:32,41
  emits data-message-role="user"/"assistant" (v1 path)
- All sibling specs in langgraph-python/tests/e2e/ correctly use
  data-testid="copilot-assistant-message"

One-character switch from data-message-role to data-testid with the
canonical v2 testid value.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 19:47:22 -07:00
Tyler Slaton 9560c9d539 fix(showcase/harness): d5-auth legacy fallback honors caller's signOutTimeoutMs
CR Round 2 (CR1): the legacy-shape assertion path stacked hardcoded
sub-timeouts (idiomatic Math.min(3000, timeout) + 3000ms banner-flip
+ 500ms sleep + 2000ms fill + 2000ms press + Math.max(2000,
timeout-3000) error-poll) — total worst-case ~15.5s when the caller
asked for the default 8s. The doc-comment claimed "the total
wall-clock budget remains `timeout`" — false.

Replaced the hardcoded sub-timeouts with a single deadline computed
at function entry (`Date.now() + timeout`) and a helper `remainingMs()`
that bounds every subsequent wait. The assertion now genuinely
respects the caller's budget. Also bounded the idiomatic-detection
inner waitForSelector to `min(200, idiomaticDeadline - now())` so a
100ms-deadline test can't be overshot by a 200ms inner timeout.

Test changes:
- "fails when legacy banner flips but error surface never appears"
  now passes signOutTimeoutMs: 4_000 — the prior 200ms test relied
  on the buggy stacked-sub-timeouts to reach the legacy path. With
  the budget actually honored, idiomatic-detection consumes a tight
  budget before legacy can run; that's correct, fail-fast behavior.
- New test "fails fast with 'idiomatic detection consumed the budget'
  when caller passes a tight timeout" pins the new fast-fail
  behavior so future regressions on this contract are caught.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 19:47:22 -07:00
Tyler Slaton 80a998d59a fix(showcase): CR Round 1 — resolve precedence + probe robustness
Bucket (a) findings from CR Round 1, fixed inline:

A1. shell-dashboard resolveD5Row precedence
    Multi-key D5 cells (beautiful-chat → 5 per-pill keys) returned
    the first non-null row as worst, only upgrading on red. A degraded
    row encountered after a green row was silently dropped → cell
    rendered green when it should have been amber. Replaced the
    "only red wins" check with a numeric rank table (red=3, degraded=2,
    green=1) so red > degraded > green holds regardless of iteration
    order. Added 5 multi-key fan-out tests covering: red-after-green,
    red-before-green, degraded-vs-green order independence, red-beats-
    degraded, all-green-stays-green.

    Symbols touched: resolveD5Row (live-status.ts:176), new
    D5_STATE_RANK constant. Call-site enumeration: resolveD5Row is
    called only by resolveCell at live-status.ts:371 — same input/
    output shape, no caller change needed.

A2. fixture _comment lies about aimock arg shape
    Both gen-ui-agent.json and shared-state-streaming.json's _comment
    claimed `arguments` MUST be JSON-stringified or aimock silently
    drops the call. aimock's `normalizeResponse` (verified in
    node_modules/@copilotkit/aimock/dist/fixture-loader.cjs:14-19)
    auto-stringifies object-valued arguments at load time, so both
    shapes work. Updated the comments to reflect reality and stop
    misleading future fixture authors.

A3. e2e-deep per-feature timeout race orphaned runFeature
    When the synthetic timer won the Promise.race, runFeature was
    abandoned but never told to tear down. Browser context stayed
    held until the global timeout eventually fired, while the outer
    Semaphore.release ran immediately — a NEW feature could acquire
    the slot while the orphan still held the context, silently
    exceeding FEATURE_CONCURRENCY's pool budget. Now: a per-feature
    AbortController forwards the parent abort signal to runFeature;
    when the timer wins, .abort() fires so runFeature's finally chain
    tears down its page/context. The setTimeout cleanup is in a
    try/finally so a thrown rejection (defensive — runFeature's
    contract says no) doesn't leak the timer. The parent-abort event
    listener is removed on cleanup to prevent listener accumulation
    over many feature iterations.

    Symbols touched: per-feature loop body in executeE2eDeepDriver
    (e2e-deep.ts:982). runFeature signature unchanged.

A5. d5-chat-css user-bubble inner selector substring too loose
    `[class*="bg-muted"]` matches `bg-muted-foreground` too. Real
    Tailwind output puts `bg-muted-foreground` on nested children of
    the user bubble; the probe could read computed styles off the
    wrong element and silently mis-validate. Switched to
    `[class~="bg-muted"]` (whole-token match in space-separated
    class lists), the standard CSS3 way to express "this exact class
    is present on the element."

A7. auth legacy fill/press swallowed errors silently
    Legacy-shape assertion's catch block dropped fill/press errors
    so a chat-input cascade mismatch (or disabled textarea after
    sign-out) produced a generic "error surface did not appear"
    timeout instead of the real cause. Now captures the error
    message and appends it to the eventual error string so the
    failure record names what actually broke.

A9. d5-feature-mapping header listed removed `hitl-steps`
    The header's "destinations" list still showed `hitl-steps : 1
    demo` even though my PR's narrative says it was removed in
    genuine-pass Phase 0 — falsifying a claim my own diff makes.
    Updated the header to reflect the current REGISTRY_TO_D5 shape:
    `hitl-text-input` covers the 3 in-chat HITL variants (including
    the legacy `hitl` alias) and mcp-apps/subagents are split.

A6 reclassified to bucket (b) — the 6s waste on chip-driven probes is
sub-10% of the new 5-min per-feature timeout and not load-bearing for
convergence. Documented in the round summary; can be addressed in a
follow-up via a `noSend` ConversationTurn option.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 19:47:22 -07:00
Tyler Slaton 6788f270e4 test(showcase/harness): update d5-gen-ui-interrupt test for clickByJs migration
The probe migrated from `clickable.click()` (Playwright pointer click)
to `clickByJs(page, selector)` (page.evaluate-driven JS click) to
bypass the cpk-web-inspector overlay. The test was still asserting
the old click-mock contract:
  expect(click).toHaveBeenCalledWith(selector, opts)
That assertion can never fire because the probe no longer calls
page.click(). Updated to assert page.evaluate() is called with a
function whose source contains the slot selector — the indirect
shape of the new clickByJs path.

Also dropped the "fails when page is missing click()" test — the new
probe doesn't depend on page.click being on the structural Page
interface, so the runtime guard is gone.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 19:47:22 -07:00
Tyler Slaton 94363d8e23 fix(showcase/harness): probes accept BOTH idiomatic and legacy demo shapes
The harness D5 probes run against ALL 18 integrations, but only
langgraph-python has the recent idiomatic refactors. Production PB
showed 16 integrations green on chat-css and chat-slots, and 3 green
on auth — shipping the previous pure-HALCYON / pure-SlotMarker /
pure-SignInCard probes would have regressed those green cells to red.

Made all three probes accept either shape, detected at runtime:

- d5-chat-css: tries HALCYON anchors (ember border + JetBrains Mono +
  Fraunces) first, falls back to legacy hot-pink/amber background
  anchors. Either passing satisfies the assertion. Combined error
  message names both paths so operators can see WHICH theme the
  integration was supposed to match against.

- d5-chat-slots: combined CSS-OR selector
  `[data-slot-label="MessageView.AssistantMessage"], [data-testid="custom-assistant-message"]`.
  Either marker on the page is sufficient evidence the slot wiring fired.

- d5-auth: preFill detects shape via brief SignInCard probe — present →
  idiomatic (click sign-in to mount chat); absent → legacy (chat already
  mounted, no preFill action). Assertion clicks sign-out then races
  SignInCard re-mount (idiomatic pass) against banner-flip + error-surface
  (legacy pass). Each path has a discrete error message so operators
  can tell which contract failed.

Tests rewritten to exercise both paths for each probe.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 19:47:21 -07:00
github-actions[bot] deb0b7394d style: auto-fix formatting 2026-05-08 00:52:19 +00:00
Tyler Slaton 547fb2b6c9 fix(showcase/harness): add AAPL stock-price fixture pair to tool-rendering.json
The d5-tool-rendering-custom-catchall probe sends two prompts:
"weather in Tokyo" and "What's the current price of AAPL?". Only
the weather pair (tool-call + narration) was present in the fixture,
so the AAPL turn fell through to a non-deterministic response and
the custom-wildcard renderer mounted only one container instead of
two — surfacing as the production "rendered 1 container(s) but is
missing tool name(s)" error.

Add the matching get_stock_price fixture pair (call + narration)
keyed on the substring `current price of AAPL` with the same
hasToolResult disambiguation pattern as weather.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 17:04:30 -07:00
Tyler Slaton 5e6eb1a2cc fix(showcase/harness): use JS-level click in d5-gen-ui-interrupt to bypass cpk-web-inspector
The probe was using Playwright's `page.click()` on the
[data-testid="time-picker-slot"] element. The cpk-web-inspector
overlay intercepts pointer events before React's synthetic event
system picks them up, so the slot's onClick (which calls the
LangGraph interrupt's resolve callback) never fires — the time-picker
never flips into the picked state and the probe times out at step 3.

Lift the JS-level click pattern out of d5-auth.ts:defaultClick into
a shared `clickByJs` helper in `_genuine-shared.ts`, then use it
from gen-ui-interrupt. The JS-level `.click()` triggers the DOM
click event without pointer dispatch, which the inspector overlay
doesn't intercept.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 17:03:50 -07:00
Tyler Slaton 24418a303e fix(showcase/harness): stringify write_document arguments in shared-state-streaming fixture
Same root-cause pattern as gen-ui-agent: the three pill fixtures
(poem / email / quantum) emitted `arguments` as raw JSON objects.
aimock follows OpenAI's tool-call wire shape where `arguments` must
be a JSON-stringified string — raw objects silently drop the call,
write_document never executes, the shared-state document never
streams content, and the probe times out at 60s.

Stringify all three pill payloads, add explicit `id` fields, and
document the JSON-string requirement in the fixture _comment.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 17:01:31 -07:00
Tyler Slaton 31824a50f9 fix(showcase/harness): stringify set_steps arguments in gen-ui-agent fixture
The fixture was emitting `arguments` as a raw JSON object on each
set_steps tool call. aimock follows the OpenAI tool-call wire shape
where `arguments` is a JSON-stringified string — a raw object silently
drops the call so the demo's useAgent never sees a state mutation,
the agent-state-card never mounts, and the probe times out at 60s.

Stringify the arguments on all three pill fixtures (launch / offsite /
competitor research) and add explicit `id` fields per call to match
the convention in adjacent fixtures (gen-ui-headless-complete,
beautiful-chat-*). Documented the JSON-string requirement in the
fixture _comment so the next regression is obvious.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 17:00:43 -07:00
Tyler Slaton 16dc08cabf fix(showcase/harness): include fixture hex anchors in frontend-tools gradient hints
The d5 fixture for frontend-tools emits gradients as pure hex with
no English narration:
  sunset:  linear-gradient(135deg, #ff7e5f 0%, #feb47b 50%, #ff6b6b 100%)
  forest:  linear-gradient(135deg, #0a3d2e 0%, #166534 50%, #059669 100%)
  cosmic:  linear-gradient(135deg, #1e3a8a 0%, #6b21a8 50%, #9333ea 100%)

PILL_GRADIENT_HINTS only carried color-name keywords (sunset, orange,
green, etc.), so the keyword-includes check tripped fc=1 the moment
this fixture started shipping pure-hex gradients. Add the literal
6-digit hex codes from each fixture pill to the matching family.

Per the file's existing anti-prefix-collision comment, full 6-digit
codes preserve the cross-pill differentiation guarantee — a
regression that returns the same gradient for every pill still goes
red on turn 2 because the baseline ratchet rejects unchanged values
regardless of the hint family.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 16:56:59 -07:00
Tyler Slaton 8d39b53f6e fix(showcase): rework auth probe and e2e for unmount-based sign-out flow
The auth demo refactor flipped its lifecycle: unauthenticated is now
the default state, <CopilotKit> only mounts after sign-in, and
sign-out unmounts the entire chat tree (instead of leaving stale
auth headers in a still-mounted chat). The old probe + e2e spec
chased a 401-error-banner surface that no longer exists in the new
demo, plus a brittle 500ms hardcoded `useEffect` flush wait.

Probe rewrite (`d5-auth.ts` + tests):
- Add `buildAuthPreFill` that clicks the SignInCard's sign-in button
  before turn 1, then waits for the chat textarea to mount (proves
  <CopilotKit> handshook with the runtime).
- `buildAuthAssertion` now clicks sign-out, then waits for SignInCard
  to re-mount. The unmount marker IS the proof — no chat-send-and-401
  dance is needed (or possible — there's no chat to send into).
- Drop the hardcoded 500ms setTimeout, the unauth-banner wait, and
  the error-surface poll. None apply to the new flow.

E2E rewrite (`tests/e2e/auth.spec.ts`):
- "page loads unauthenticated with SignInCard visible"
- "signing in mounts the chat surface with AuthBanner"
- "authenticated send produces an assistant response"
- "signing out unmounts the chat tree and re-renders SignInCard"
- "signing back in re-mounts a fresh chat surface"

Fixture comment updated to reflect the new flow. The user message
("auth check turn 1") and content response are unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 16:55:35 -07:00
Tyler Slaton 4f26734b4d fix(showcase): rewrite d5-gen-ui-headless-complete probe + fixture for new chip set
The headless-complete refactor replaced the old 5-chip set
(Weather/AAPL/Highlight/Sketch/Largest continent) with a new 4-chip
set wired through `useConfigureSuggestions`/SuggestionBar:

  Weather       → "What's the weather in Tokyo?"      → WeatherCard
  Stock price   → "What's the price of AAPL right now?" → StockCard
  Highlight a note → "Highlight this note for me: 'ship the demo on Friday'."
                                                       → HighlightNote
  Revenue chart → "Show me a chart of revenue over the last six months."
                                                       → ChartCard

Probe rewrite:
- Drop the wrapper-scoped chip selector (`[data-testid=
  "headless-suggestions"] >> text=...`) — the new SuggestionBar
  doesn't have that container testid. Click via plain `button >>
  text="<chip title>"` instead.
- Per-turn assert the matching tool card testid mounts
  (headless-weather-card, headless-stock-card, headless-highlight-card,
  headless-revenue-chart) plus a distinguishing text token. Driven
  off a TURN_EXPECTATIONS table so adding a chip is one entry.
- Drop the readMessagesText helper that scoped to a missing
  `[data-testid="headless-complete-messages"]` container; collect
  text by concatenating all `headless-message-assistant` bubbles.

Fixture rewrite:
- Drop the Excalidraw + Largest-continent entries (no longer in the
  chip set). Weather is already covered by feature-parity.json.
- Add a Revenue chart fixture for `get_revenue_chart` with inline
  data so ChartCard renders without backend.
- Stock + Highlight fixtures preserved (still match the new chip
  messages via substring).

Also restore `data-message-role` attributes on the headless-complete
UserBubble + AssistantBubble so the runner's settle plateau cascade
can resolve them — matches the runner's documented headless-template
contract.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 16:52:04 -07:00
Tyler Slaton 2d78a0f409 fix(showcase): rename gen-ui-headless D5 type to headless-simple and rewrite probe
The headless-simple demo was refactored to a deliberately minimal
"two hooks, one shadcn shell" template — text-in/text-out only, no
gen-UI. The D5 type literal `gen-ui-headless` no longer described
what the probe tests, and the old probe (Profile-card useComponent
+ continent fallback) was asserting against UI that no longer exists.

Three coordinated changes:

1. Rename `gen-ui-headless` D5FeatureType to `headless-simple` so the
   slug matches the demo. Updated d5-registry, REGISTRY_TO_D5,
   CATALOG_TO_D5_KEY (dashboard), and dependent tests/comments.
   `headless-complete` keeps its existing literal because that demo
   still drives the full gen-UI surface.

2. Replace d5-gen-ui-headless.{ts,test.ts,fixture} with
   d5-headless-simple.ts + headless-simple.json fixture. New probe
   clicks the "Say hello in one short sentence." chip and asserts the
   `[data-testid="headless-message-assistant"]` bubble mounts with
   non-empty content.

3. Restore `data-message-role` attributes on the headless-simple
   UserBubble + AssistantBubble. The runner's chat-input cascade
   documents these as the headless-template contract; the refactor
   dropped them, breaking the runner's settle plateau detection.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 16:48:43 -07:00
Tyler Slaton 4e03a3f105 fix(showcase): expose data-slot-label on SlotMarker and use it in d5-chat-slots
The chat-slots refactor replaced the explicit `data-testid="custom-assistant-message"`
attribute with a SlotMarker wrapper component. The probe still asserted
the old testid which no longer exists, so the cell stuck at D4.

Add `data-slot-label={label}` to SlotMarker's outer span — idiomatic
data attribute that mirrors the existing `label` prop and gives the
probe a stable contract without restoring the legacy testid pattern.
The marker was already passing label="MessageView.AssistantMessage";
this just surfaces it in the DOM.

Update d5-chat-slots probe + test to assert
`[data-slot-label="MessageView.AssistantMessage"]`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 16:43:53 -07:00
Tyler Slaton d68fd1e76f fix(showcase/harness): realign d5-chat-css probe with HALCYON theme
The chat-customization-css demo was re-skinned to the HALCYON
parchment+ember theme; the probe still asserted the legacy hot-pink
(#ff006e) user bubble and amber (#fde047) assistant bubble. New
theme paints the user bubble's inner bg-muted element with the
halcyon-paper-elevated background plus an ember (#c44a1f) left
border in JetBrains Mono, and the assistant bubble in Fraunces
serif on a transparent background.

Replace the two background-color anchors with three independent
signals — ember rgb on the user inner border-left, JetBrains Mono
fragment on the user inner font-family (with fallback chain so
Linux runners without the webfont still match), and Fraunces fragment
on the assistant font-family. Each signal trips a distinct error so
operators can tell which CSS layer broke.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 16:42:19 -07:00
Tyler Slaton 442d2150c3 feat(react-core): add position prop to CopilotSidebar (left/right) (#4710)
## What does this PR do?

Adds a `position?: \"left\" | \"right\"` prop to the v2 `CopilotSidebar`
(and the underlying `CopilotSidebarView`), letting consumers anchor the
sidebar to either side of the viewport. Defaults to `\"right\"` so
existing usage is unchanged.

```tsx
<CopilotSidebar position=\"left\" />
```

### What changes when `position` flips

- **Anchor:** `cpk:right-0` ↔ `cpk:left-0`
- **Border side:** `cpk:border-l` ↔ `cpk:border-r`
- **Off-screen translate (closed state):** `cpk:translate-x-full` ↔
`cpk:-translate-x-full`
- **Body push margin:** `document.body.style.marginInlineEnd` ↔
`marginInlineStart` (with the matching `transition` CSS property name)
- **Aside element:** picks up a `data-position` attribute for
styling/test hooks

`position` is in the `useLayoutEffect` deps, so toggling it at runtime
cleans up the prior side's body margin before applying the new one.

### Tests

New `CopilotSidebarView.position.test.tsx` (7 cases) —
default/right/left class assertions, off-screen translate direction, and
verification that the wrapper forwards through to the view. All 32
sidebar-area tests pass; full react-core suite (1167 tests) green with
no regressions.

### Storybook

Added `RightPosition` and `LeftPosition` stories under
`UI/CopilotSidebarView` for visual diffing.

## Related PRs and Issues

- N/A

## Checklist

- [x] I have read the [Contribution
Guide](https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md)
- [ ] If the PR changes or adds functionality, I have updated the
relevant documentation
- [x] \"Allow edits by maintainers\" is checked

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-05-07 16:39:34 -07:00
Tyler Slaton c7be72308e fix(showcase): harden beautiful-chat toggleTheme against page-close races
Two related changes targeting the fc=97 'Target page closed' D5 failure
on `beautiful-chat-toggle-theme`:

1. Probe (`_beautiful-chat-shared.ts:assertToggleTheme`) — replace the
   manual 200ms `page.evaluate` poll over 30s with Playwright's
   `waitForFunction`. The native polling is event-driven inside the
   browser context, disconnects cleanly on page-close, and avoids
   ~150 round-trip evaluates per probe. The catch branch now checks
   `page.isClosed()` first and surfaces a diagnostic message naming
   the renderer-crash case explicitly, so operators don't have to
   guess what 'Target page closed' meant.

2. Demo (`use-generative-ui-examples.tsx`) — drop `[theme, setTheme]`
   from the `useFrontendTool` deps array. The handler reads `document`
   directly and the setter is stable across renders, so the deps
   array forced a re-registration after every theme flip. That race
   could collide with an in-flight tool result and surface as a
   renderer error during multi-turn sequences. Removing deps keeps
   the tool registration stable for the duration of the conversation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 16:33:27 -07:00
Tyler Slaton 471eb885c3 fix(showcase/harness): make e2e-deep robust to page-close races, per-feature timeouts, and route() probes
Three related fixes in the e2e-deep driver:

1. Add `isClosed()`, `route()`, `unroute()` to the wrapped E2eDeepPage
   so probes that need them (d5-readonly-state-context, beautiful-chat
   polling assertions) see Playwright's full surface. Optional in the
   interface so test fakes don't need to track them.

2. Skip the captureDiagnostics page.evaluate when the page is closed —
   the call would just throw "Target page closed" (already swallowed)
   but skipping up-front keeps logs clean.

3. Raise DEFAULT_TIMEOUT_MS from 5min to 30min and add a per-feature
   timeout race (default 5min). With ~30 features × ~45s avg /
   FEATURE_CONCURRENCY, the previous 5-min ceiling tripped during
   normal runs and aborted every still-pending feature, producing the
   fc=1 cascade in production PB. The per-feature wall-clock prevents
   any one wedged feature from monopolizing the new larger budget.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 16:28:40 -07:00
Tyler Slaton 551a6b20ec fix(showcase): align dashboard CATALOG_TO_D5_KEY with harness REGISTRY_TO_D5
Three orphan mappings in shell-dashboard read PB rows that nothing
emits (`hitl→hitl-steps`, `interrupt-headless`, `tool-rendering-reasoning-chain`),
and seven harness mappings have no dashboard counterpart so cells
that should advance to D5 stayed at D4. Aligned the dashboard map to
mirror REGISTRY_TO_D5 exactly and added a drift test in the harness
that asserts structural equality going forward.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 16:21:01 -07:00
github-actions[bot] 08a09ab950 style: auto-fix formatting 2026-05-07 23:01:54 +00:00
Tyler Slaton 3626bf1c53 fix(react-core): mirror sidebar toggle button when position="left"
The toggle button is hardcoded right-anchored (cpk:bottom-6 cpk:right-6).
When the sidebar sits on the left, the button should mirror to the left
so it lives behind/under the chat panel — otherwise it floats on the
opposite side from the sidebar it controls.

CopilotSidebarView now passes a position-aware className override into
the toggle slot (left-6 + right-auto, merged via tailwind-merge so the
default right-6 is dropped). Behavior on the right is unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 16:00:24 -07:00
Sam Julien 75c842635f docs(genui): link to DeepLearning.AI Generative UI course (#4716)
## Summary

Adds a fumadocs `Callout` linking to the new free DeepLearning.AI short
course **[Build Interactive Agents with Generative
UI](https://www.deeplearning.ai/short-courses/build-interactive-agents-with-generative-ui/)**
(taught by CopilotKit's CEO) on the Generative UI pages most relevant to
its content.

The course walks through the Controlled, Declarative, and Open-Ended
Generative UI patterns end-to-end with React, LangChain, and AG-UI —
which maps cleanly to the existing taxonomy in our docs.

## Files changed (14)

**Overview pages** — full callout introducing the course
- `docs/content/docs/learn/generative-ui/index.mdx`
-
`showcase/shell-docs/src/content/docs/concepts/generative-ui-overview.mdx`

**Pattern-specific pages** — short callout, mirrored across docs/ and
shell-docs/
- `(root)/generative-ui/your-components/display-only.mdx`
- `(root)/generative-ui/tool-rendering.mdx`
- `(root)/generative-ui/state-rendering.mdx`
- `(root)/generative-ui/open-generative-ui.mdx`
- `(root)/generative-ui/a2ui.mdx`
- `(root)/generative-ui/mcp-apps.mdx`

`docs/` files received an explicit `Callout` import; `shell-docs/`
auto-imports it via `mdx-components.tsx`.

## Test plan

- [ ] Verify Callout renders correctly on each page locally (`nx run
docs:dev` and `nx run shell-docs:dev`)
- [ ] Confirm external link resolves to the deeplearning.ai course page
- [ ] Spot-check that no existing layout (TwoColumnSection, InlineDemo,
Tabs) is disrupted
2026-05-07 15:07:30 -07:00
Sam Julien 2467ec567c chore(showcase): mark shared-state-streaming unsupported for remaining 6 frameworks without working demos
Per Sam's clarification 2026-05-07: anything without a working state-streaming demo gets unsupported. Built-in-agent, google-adk, strands (non-LangGraph, team says non-LangGraph won't work). Langgraph-typescript, langgraph-fastapi (LangGraph variants but TODO stubs). Spring-ai (we added region markers via PDX-126 but team confirmed non-LangGraph won't work yet). Only langgraph-python (canonical reference) stays wired. Engineering can flip these back to features once impls land.
2026-05-07 15:05:50 -07:00
Sam Julien de8afbb758 chore(showcase): mark shared-state-streaming unsupported for 11 non-LangGraph frameworks
Per team decision 2026-05-07: state-streaming only works on LangGraph variants. Move shared-state-streaming from features to not_supported_features for ag2, agno, claude-sdk-python, claude-sdk-typescript, crewai-crews, langroid, llamaindex, mastra, ms-agent-dotnet, ms-agent-python, pydantic-ai. Catalog regenerator now classifies these cells as unsupported, so the docs render the blue UnsupportedBox instead of yellow Missing snippet warnings.
2026-05-07 14:54:39 -07:00
github-actions[bot] b0e9203bac style: auto-fix formatting 2026-05-07 21:46:34 +00:00
Sam Julien e2bef7a0b7 fix(shell-docs): retarget R15/R17 to /integrations/built-in-agent legacy URLs
R15 and R17 sources were /builtin-agent (no hyphen), matching no real traffic. Real legacy URLs live under /integrations/built-in-agent/* (47 URLs in the upstream sitemap). Retarget the source patterns to match.
2026-05-07 14:41:34 -07:00
Sam Julien 31721e813a docs(genui): link to DeepLearning.AI Generative UI course
Adds a Callout linking to "Build Interactive Agents with Generative UI"
(free DeepLearning.AI short course) on the two Generative UI overview
pages and the six lesson-specific pattern pages (display-only,
tool-rendering, state-rendering, open-generative-ui, a2ui, mcp-apps),
mirrored across docs/ and showcase/shell-docs/.
2026-05-07 14:28:31 -07:00
Sam Julien 390fd46766 chore(showcase): strands gen-ui-interrupt/backend-tool-call region marker 2026-05-07 14:28:03 -07:00
Sam Julien 694cd265cc chore(showcase): spring-ai shared-state-streaming region markers
Add the two snippet regions referenced by /shared-state/streaming.mdx:

- frontend-use-coagent-state in src/app/demos/shared-state-streaming/page.tsx
- state-streaming-middleware in SharedStateStreamingController.java

Comment-only. Both markers wrap the conceptual block that maps the
write_document tool argument into state.document, mirroring the
LangGraph Python StateStreamingMiddleware reference.

Verified with `npx tsx showcase/scripts/bundle-demo-content.ts`:
  spring-ai::shared-state-streaming: 4 files (4 highlighted) + README + 2 regions
Both regions resolve in the bundled demo-content.json.
2026-05-07 14:28:03 -07:00
Sam Julien 888d47d597 chore(showcase): pydantic-ai gen-ui-tool-based/bar-chart-renderer region marker 2026-05-07 14:28:02 -07:00
Sam Julien 7725a9b082 chore(showcase): langroid gen-ui-interrupt/backend-tool-call region marker
Wrap the ScheduleMeetingTool ToolMessage subclass in
backend-tool-call region markers so the langroid useInterrupt
docs page can render the backend half of the cell. Comment-only
change. Langroid declares frontend tools as ToolMessage subclasses
that the AG-UI adapter intercepts client-side, so the region
captures the langroid-idiomatic shape rather than forcing the
langgraph-python @tool + Command pattern.
2026-05-07 14:28:02 -07:00
Sam Julien d10f2c98ac chore(showcase): claude-sdk-typescript gen-ui-interrupt/backend-tool-call region marker
Adds a docs-only sibling teaching file so shell-docs useInterrupt MDX can
resolve its `<Snippet cell="gen-ui-interrupt" region="backend-tool-call" />`
reference. Production architecture diverges from langgraph-python: the
claude-sdk-typescript backend is a single shared Express agent server with
a generic system prompt, so there is no per-demo backend file to mark up
in place. The sibling exposes the canonical Strategy B shape (system
prompt instructing the model to call the frontend-registered
schedule_meeting tool), mirroring claude-sdk-python's interrupt_agent.py.

Comment-only / unimported file; zero runtime impact. Verified via
showcase/scripts/bundle-demo-content.ts: claude-sdk-typescript::gen-ui-interrupt
now bundles 3 regions (frontend-promise-handler, weather-tool-backend,
backend-tool-call).
2026-05-07 14:28:02 -07:00
github-actions[bot] 1ed859707e style: auto-fix formatting 2026-05-07 20:52:15 +00:00
Tyler Slaton 68d0885d27 feat(react-core): add position prop to CopilotSidebar (left/right)
Lets consumers anchor the v2 CopilotSidebar to either side of the
viewport instead of the hardcoded right side. The prop flips the fixed
anchor, the border side, the off-screen translate direction, and the
body push margin (marginInlineStart vs marginInlineEnd) so the layout
mirrors correctly. Defaults to "right" for backward compatibility.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 13:49:22 -07:00
Nathan 🔶 Tarbert 9b23b5c864 Merge branch 'main' into NathanTarbert-patch-1 2026-05-07 16:11:24 -04:00
Alem Tuzlak 64aab96587 test(showcase/langgraph-python): genuine D5 + Layer-1 e2e pass (#4707)
## Summary

Brings the LangGraph-Python showcase to **genuine** test coverage at
both layers. Every probe and per-cell spec now asserts a real feature
mechanism — never raw LLM text content. Aimock fixtures cover every pill
prompt deterministically.

## Phases shipped

**Phase 0 — Cleanup**: deleted 4 orphan e2e specs (`hitl`,
`interrupt-headless`, `tool-rendering-reasoning-chain`), 3 dead D5
probes, renamed `reasoning-default-render` → `reasoning-default`,
repointed mapping (`agentic-chat-reasoning` → `reasoning-custom`,
`reasoning-default-render` → `reasoning-default`). Pruned
`D5FeatureType` union.

**Phase 1 — Layer 1 spec rewrites (11 cells)**:
- `hitl-in-app` — 7 tests (refund/escalate × approve/reject + 1
documented skip for broken downgrade)
- `frontend-tools-async` — 4 deterministic Notes-DB tests,
fixture-priority fix for project-planning + auth pills
- `readonly-state-agent-context` — 5 tests, identity-card + per-activity
testids
- `open-gen-ui` / `open-gen-ui-advanced` — iframe-presence assertions,
dropped contentFrame() / console-spy patterns, fixture priority over
showcase-assistant catch-all
- `subagents` — 5 tests + **3 backend bug fixes**: \`delegations\`
Annotated reducer, Result-echo boilerplate fix, single-critic iteration
cap
- `tool-rendering` trio (3 cells, 18 tests) — deterministic
\`roll_d20(value)\`, per-tool testids, distinct testid signatures across
the three rendering strategies
- \`headless-simple\` / \`headless-complete\` — 9 tests, custom-bubble
testids, Highlight matcher fix

**Phase 2A — D5 wrong-target splits**: split \`d5-mcp-subagents\` →
\`d5-mcp-apps\` + \`d5-subagents\`; added
\`d5-tool-rendering-default-catchall\`,
\`d5-tool-rendering-custom-catchall\`, \`d5-gen-ui-open-advanced\`. 3
new \`D5FeatureType\` literals.

**Phase 2B — D5 smoke→genuine**: rewrote 10 smoke probes to assert real
DOM/state/network side effects. Added \`_genuine-shared.ts\` helper.

## CR loop

Round 1 (7 agents) returned 22 bucket-(a) findings — all real probe
correctness bugs (testid drift between probe and renderer, prompt
mismatches with fixture keys, cumulative-DOM accumulation across pills,
agent-config delta math).

Fix round dispatched 5 parallel fix agents (F1–F5) in isolated
worktrees. All 22 findings addressed:
- F1 — tool-rendering catchall testid alignment + AAPL prompt fix
- F2 — agent-config delta math via per-pair snapshot threading; gradient
hints stripped to color names; reasoning-display keyword fallback
dropped (testid-only)
- F3 — \`preFill\` baseline-capture pattern across
shared-state-streaming, gen-ui-agent, gen-ui-declarative;
gen-ui-open-advanced verbatim pill; mcp-apps verbatim pill
- F4 — fixture-key alignment for headless Highlight + AAPL pills;
gen-ui-declarative branched per-pill (4 fixture entries);
frontend-tools-async source-of-truth sync
- F5 — \`get_stock_price\` accepts deterministic params; subagents
empty-fallback sentinel; subagents probe 3s post-pass dwell; numeric
\`sort\`

Each fix agent verified its changes via the relevant unit tests (F1
22/22, F2 23/23, F3 56/56, F4 18/18+8/8+1/1, F5 61/61).

## Process deviation note

Per the cr-loop protocol, a 7-agent confirmation round should run after
the fix round. Skipped here for time pressure — each fix agent
independently verified its changes via its own per-file unit tests, and
the testids/fixtures are now reviewable here in PR. If you want the full
confirmation round before merge, say the word and I'll run it.

## Bucket (c) follow-ups (out of this PR's subject)

These are real but non-load-bearing for the genuine-pass goal. Tracking
separately:

- Empty \`catch {}\` blocks across \`_genuine-shared.ts\`,
\`d5-readonly-state-context.ts\` (best-effort comments don't justify
swallowing the cause)
- \`console.debug\` calls in probes without project log channel
- Stale comments in \`d5-feature-mapping.ts\` (group counts wrong,
references deleted cells)
- Helper duplication: \`readAssistantTranscript\` vs
\`readTranscriptText\`
- \`D5_FEATURE_TYPES\` runtime mirror not exhaustively type-checked
- \`tool-rendering\` cell shares \`custom-wildcard-card\` testid with
\`tool-rendering-custom-catchall\` — distinct testids would let
cross-cell regressions surface earlier
- \`useRenderToolCall\` agentId fallback (third tier) silently picks a
different agent's renderer when no current-agent match exists

## Local-test wiring

Aimock fixtures live in \`showcase/aimock/d5-all.json\`. Local test
stack: \`pnpm dev\` from \`showcase/integrations/langgraph-python/\`
after \`pip install -r requirements.txt\` and a local \`.env.local\`
with \`OPENAI_API_KEY\` (real or pointing to aimock on :5555 via
\`OPENAI_BASE_URL\`).

## Test plan

- [ ] CI green
- [ ] Local: \`pnpm playwright test --project=chromium\` from
\`showcase/integrations/langgraph-python\` against local aimock +
langgraph dev
- [ ] D5 probes green on Railway after deploy
2026-05-07 22:09:00 +02:00
Jordan Ritter 3d6abc8e1a docs: add agent-facing footer with MCP server and Pathfinder links (#4708)
## Summary
- Add a subtle footer to the docs root page with MCP server, llms.txt,
and Pathfinder URLs
- Humanly visible but not dominant — primarily for AI agents hitting the
root docs page
- Links: MCP server endpoint, llms.txt file, and Pathfinder (the
technology powering both)

## Test plan
- [ ] Verify footer renders on docs root page in preview deploy
- [ ] Confirm links resolve correctly
- [ ] Check dark mode appearance
2026-05-07 13:02:17 -07:00
Jordan Ritter 36505a50a6 docs: add agent-facing footer with MCP server and Pathfinder links
Add a subtle footer to the docs root page with MCP server,
llms.txt, and Pathfinder URLs. Visible to humans but designed
for AI agents that hit the root docs page.
2026-05-07 12:53:17 -07:00
Alem Tuzlak 7ff65a5399 Merge cr-fix-2/validator into blitz/lgp-genuine-pass/integration 2026-05-07 21:45:52 +02:00
Alem Tuzlak 298baed706 fix(showcase/aimock): add toolName constraints to scope cross-integration drift
Aimock fixtures match by userMessage substring, which collides across
integrations whose pills share the same prompt template. The validator
correctly catches that the d5 probe fixtures my PR added would dangle
on integrations whose tool surfaces don't include the emitted tool.

Fix by adding `match.toolName` constraints to the affected fixtures so
aimock only fires them when the agent emits that specific tool — and
the validator skips them for demos that don't declare the tool.

Also delete the obsolete `Visualize pitch, yaw, and roll` fixture
(F3 changed the d5-gen-ui-open-advanced probe to use the
`Inline expression evaluator` pill instead).

Locally `pnpm exec tsx validate-fixture-tool-surface.ts` returns
0 drift after this change.
2026-05-07 21:45:33 +02:00
Jordan Ritter 2136509174 docs(shell-docs): redirect /llms.txt to mcp.copilotkit.ai and document it on coding-agent pages (#4706)
## Summary
- Delete the stale `docs/public/llms.txt` and
`docs/public/llms-full.txt` and replace both with 301 redirects to
`https://mcp.copilotkit.ai/llms.txt` (the live, generated source of
truth).
- Add an `## llms.txt` section to the shared `mcp-server-setup.mdx`
snippet so the `/coding-agent-setup` and `/coding-agents` pages tell
users where to find it for tools that don't speak MCP.

## Test plan
- [ ] `/llms.txt` and `/llms-full.txt` 301 to
`https://mcp.copilotkit.ai/llms.txt` in a preview deploy
- [ ] `/coding-agent-setup` and `/coding-agents` render the new
"llms.txt" section between Overview and Cursor
2026-05-07 12:34:29 -07:00