harness-workers runs the SAME showcase-harness GHCR image as the harness
scheduler but has ciBuilt:false (it has no build slot of its own), and the
CI staging redeploy scope was derived purely from ciBuilt — so a main-merge
rebuild of showcase-harness:latest only bounced the scheduler while the
workers silently kept running the stale image (PR #5352's worker-side fixes
never reached staging).
Model image consumption explicitly in the SSOT instead:
- railway-envs.ts: new optional `imageOf` field on ServiceEntry — the SSOT
key of the ciBuilt service whose image this entry runs. Set
`imageOf: "harness"` on harness-workers. New module-load invariant
`assertImageConsumersValid` (fail-loud, same style as
assertDispatchNamesUnique): imageOf must name an existing SSOT key, the
target must be ciBuilt, and the consumer itself must not be ciBuilt.
- redeploy-env.ts: new `expandImageConsumers(names, env)` applied inside
runRedeploy — the redeploy set becomes the resolved scope PLUS any
service whose imageOf points at a service already in scope. Env-aware:
a consumer only joins envs it declares, so the staging-only worker
never enters a prod redeploy (prod behavior unchanged).
No workflow change needed: showcase_build.yml keeps passing the
built-and-successful dispatch_names; the script expands them. Gate
behavior (gateIgnore / image-ref gate), the generated JSON
(emit --check passes byte-identical), and the promote dropdown are all
untouched. harness-legacy deliberately gets no imageOf (pinned pre-fleet
digest; must not follow rebuilds).
## Summary
- fix shell-docs heading anchors so docs headings remain block-level
rows
- prevent adjacent headings, like `## What the runtime provides`
followed by `### Authentication & security`, from rendering on the same
line
- add a `globals.css` regression guard against bringing back
`inline-flex` on `.docs-heading`
## Verification
- `npm run test -- src/app/__tests__/globals-css.test.ts` in
`showcase/shell-docs`
- `npm run lint` in `showcase/shell-docs`
- `npm run test` in `showcase/shell-docs`
- `npm run typecheck` in `showcase/shell-docs`
- `npm run build` in `showcase/shell-docs`
- local visual check at `http://localhost:3003/backend/copilot-runtime`
with Playwright: the H2 and H3 render as separate full-width rows
- lefthook pre-commit passed `check-binaries`, `lint-fix`,
`test-and-check-packages`, and commitlint
## Notes
- `npm run lint` still reports existing warnings unrelated to this
change.
- `npm run build` still emits the existing Turbopack/NFT warning from
`next.config.ts` / `llms-mdx`, but completes successfully.
## Summary
Root-caused and fixed the staging dashboard's red↔green flapping.
Empirical investigation separated it into three mechanisms:
1. **PRIMARY (recurring flap): aimock fixture-sequence desync.** Harness
drivers sent a stable `d6-<slug>` `X-Test-Id` shared across runs.
aimock's stateful strict-mode matching (sequenced fixtures match only
when per-test-id matchCount === sequenceIndex) drifts via replay
exhaustion and 500-test-id FIFO eviction, so whole integrations 503'd
together (~2,200/hr) and recovered — the flap.
2. **SECONDARY (one-off reds): worker restart mid-job.** In-flight
`driver.run` was un-cancellable; redeploys SIGKILL'd workers mid-run,
leaving partial results that fleet-health painted red
(`worker-crashed-mid-job`).
3. **COSMETIC (red floor): dead roster rows.** 22 dead-container
registry rows were never GC'd; the restart hook is a no-op stub, so
`restartsAttempted` over-counted on rows nothing would ever restart.
## Fixes
- **Per-run-unique X-Test-Id** — fold the existing per-run `mintRunId()`
into the test id via exported `buildE2eTestId(slug, runId)` (injectable
`idFactory` for tests) in the d6/d5 and d4 drivers, so every run gets a
fresh aimock sequence cursor.
- **Graceful worker drain** — on SIGTERM the worker aborts in-flight
runs, suppresses red side-emits (`drainReason === "shutdown"` live
getter + abort conjunction), **abandons** partial results (skips
`queue.report`; the 300s lease sweeper synthesizes neutral
`worker-reclaimed-pending`), and deregisters via a latched,
`lastWrite`-chained roster delete so late heartbeats cannot resurrect
the row. Stop bounded by `WORKER_DRAIN_GRACE_MS` (25s default); order
`worker.stop → registration.stop → deregister → pool.shutdown`.
- **Fleet-health GC** — roster rows dead longer than
`DEFAULT_WORKER_GC_AFTER_MS` (24h) are deleted (`gcDeleted` counter),
malformed rows are GC'd by age before the worker_id guard,
`restartsAttempted` is demoted when the restart hook is a no-op, and
`createFleetHealthMonitor` fails loud when `gcAfterMs <= staleAfterMs`.
Companion PR: CopilotKit/aimock#259 (strict-mode no-match diagnostics,
1.30.0) makes the PRIMARY mechanism observable instead of a bare 503.
## Review
- 3 unbiased CR rounds (8 reviewer agents each, verbatim non-leading
prompt) converged to **zero actionable findings**; round-1 criticals
(drain-suppression of genuine timeouts, deregister/heartbeat
resurrection race, vacuous tests, GC-skipped malformed rows) were fixed
with red-green proofs and confirmed in byte-identical follow-up rounds.
- Bucket-(c) promotion audit: 0 promotions to actionable; 3 trivial
consistency items deferred to the follow-up backlog with ~25
pre-existing harness findings.
## Test plan
- [x] Full harness suite: 122 files / 2146 tests green
- [x] `tsc --noEmit` on both tsconfigs; build green
- [x] oxfmt clean on all 14 changed files
- [x] Red-green discipline on every behavioral fix (failures observed
before fixes)
- [x] CI green on this PR
- [ ] Staging promotion (explicitly out of scope here; separate step)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
The global CopyTracker already emits the generic cli_command_copied on
any clipboard copy, but it cannot distinguish which hero card was used.
Each card now also captures hero_command_copied with command_id
(create | onboard), the full command string, and clipboard_blocked, so
create-vs-onboard funnels are queryable per landing page.
Validated locally against a live PostHog client: each click POSTs one
$autocapture, one cli_command_copied, and one hero_command_copied to
/ingest/e (HTTP 200) with the expected properties.
Review follow-up: bring back the quickstart button alongside the two
recommended commands, and render the identical <HeroStartActions> block
on the home hero and every framework landing hero.
- Quickstart returns in its original accent treatment: the framework
dropdown on home, a direct guide link on framework pages; bespoke-init
frameworks (a2a, ms-agent-dotnet) get back the old button + chip row.
- One layout everywhere: cards are always two-up from sm (no more
stacked framework variant); commands wrap balanced at token boundaries
instead of truncating, so long framework-pinned commands stay fully
readable at every width.
Follow-up to #5345 per review feedback:
- Propagate the provider change to all remaining skills: every example,
props table, eval check, and prose mention now recommends CopilotKit
imported from @copilotkit/react-core/v2 (the compatibility bridge and
strict superset) instead of CopilotKitProvider. Migration docs in
copilotkit-upgrade now point at the /v2 import path as the target and
explicitly warn against migrating to CopilotKitProvider.
- Scrub CopilotCloud / Copilot Cloud / CopilotKit Cloud branding from
skills, replacing it with CopilotKit Intelligence where the hosted
platform is meant. Literal endpoint URLs and real identifiers like
MissingPublicApiKeyError are unchanged.
- Fix react-core provider-setup.md which claimed publicApiKey was the
canonical prop; publicLicenseKey is canonical and publicApiKey is a
deprecated alias, matching #5345.
- Edits made in the packages/*/skills source dirs for the three mirrored
skills, with skills/ regenerated via pnpm sync:plugin-skills (this also
re-pins the plugin version fields to 1.59.5).
Per review feedback: CopilotKit from @copilotkit/react-core/v2 is the
compatibility bridge across v1 and v2 and a strict superset of both the
legacy root CopilotKit and CopilotKitProvider. Switch all provider
examples, the props table, references, the page asset, and eval checks
to it, and finish the licenseKey -> publicLicenseKey rename in
telemetry-setup.md.
Previously the EXIT-trap restore_isolation always tore down the isolated
stack, ignoring --keep. Now restore_isolation reads a keep flag (set in
cmd-test.sh when --keep is parsed): when kept it skips compose down, the run-dir
removal, and the slot release, and instead prints a survival notice with the
project, slot, the three offset host ports, and the exact manual teardown
command. The kept stack's live containers keep its slot from being reaped.
Persist the compose project name into each claimed slot dir, and at claim time
reap any slot whose recorded project has no live containers (queried via
docker ps --filter label=com.docker.compose.project). This correctly leaves a
--keep'd stack's slot alone since its containers are still up. The existing
PID/age heuristics remain as a fallback for slots predating the project file.
Move the --isolate slot registry and per-run scratch dir off /tmp (wiped on
reboot, world-writable) to $XDG_STATE_HOME/copilotkit/showcase (slots/ and
runs/<name>). The run dir is now keyed by the finalized project name instead
of the PID so a kept run is locatable for manual teardown. Adds a bats suite
covering the new state-base helper and run-dir location.
Replaces the "Install as a Claude Code plugin" section and its
skill-inventory table with our recommended one-line install:
```bash
npx copilotkit@latest skills install
```
**Why:**
- The hand-maintained skill table goes stale fast. It already listed 9
skills and 6 lifecycle slugs that no longer exist (there are 11 skills
now).
- `npx copilotkit@latest skills install` is our new recommended way to
install the skills. It works across Claude Code, Codex, Cursor, Gemini,
and others, and always pulls the latest.
**Two commits, reviewed separately:**
1. `style: format README with oxfmt`. README has failed `oxfmt` on main
since 1e70dae97 widened the lint-fix glob to cover markdown but never
backfilled existing files. This runs the formatter once so the file
conforms, which also keeps the content change below from being buried
under whole-file reformat noise. Render-neutral: only emphasis markers
and table column padding, which GitHub renders identically.
2. `docs: simplify README agent-skills section`. The actual content
change. Surgical, one section.
RUNBOOK.md + DEBUGGING.md establish `bin/showcase test <slug> --d6 --isolate <name>` as the default way to verify a slug's d6 state (isolated stack on offset ports, own compose project, doesn't touch the shared stack), replacing the stale isolated-run sections.
host CLI loads no env file so isolated runs use the config.ts default superuser; that default (admin@localhost.dev) mismatched the compose-seeded admin@example.com (docker-compose.local.yml POCKETBASE_SUPERUSER_EMAIL), so a fresh isolated PB 400'd pb-auth → 0 jobs enqueued → d6-all-pills no-op. Aligned the default to admin@example.com (password already matched). Added config.test.ts deriving the expected value from docker-compose.local.yml so host CLI and container seed can't drift. Verified llamaindex+agno --isolate: no 400, Enqueued 1 job, worker runs d6-all-pills per-pill.
Replace the Claude-Code-specific plugin instructions and the stale skill
inventory table (wrong skill count, renamed lifecycle slugs that no longer
exist) with a single agent-agnostic install command that works across Claude
Code, Codex, Cursor, Gemini, and others:
npx copilotkit@latest skills install
Drops the hand-maintained table that drifts out of sync with the skills on
disk.
README was never backfilled when 1e70dae97 widened the lint-fix glob to
cover markdown, so it has failed oxfmt on main since. Run the formatter once
to make it conform. Changes are render-neutral (emphasis markers and table
column padding); GitHub renders the file identically. Isolated in its own
commit so the content change in the next commit stays easy to review.
<!--
Thank you for sending the PR! We appreciate you spending the time to
work on these changes.
Help us understand your motivation by explaining why you decided to make
this change.
**Please PLEASE reach out to us first before starting any significant
work on new or existing features.**
By the time you've gotten here, you're looking at creating a pull
request so hopefully we're not too late.
We love community contributions! That said, we want to make sure we're
all on the same page before you start.
Investing a lot of time and effort just to find out it doesn't align
with the upstream project feels awful, and we don't want that to happen.
It also helps to make sure the work you're planning isn't already in
progress.
As described in our contributing guide, please file an issue first:
https://github.com/ag-ui-protocol/ag-ui/issues
Or, reach out to us on Discord: https://discord.com/invite/6dffbvGU3D
You can learn more about contributing to copilotkit here:
https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md
Happy contributing!
-->
## What does this PR do?
(Describe the changes introduced in this PR)
## Related PRs and Issues
- (Direct link to related PR or issue, if relevant)
## Checklist
- [ ] 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
- [ ] "Allow edits by maintainers" is checked (lets us help iterate on
your PR directly — faster turnaround for everyone)
Bump @ag-ui/core, @ag-ui/client, @ag-ui/encoder from 0.0.53 to 0.0.56
across all packages.
@ag-ui/client 0.0.56 changed runHttpRequest from (url, requestInit) to a
fetch-thunk signature (() => Promise<Response>). Update the single-route
and connect transport paths in ProxiedCopilotRuntimeAgent to wrap the
request in () => this.fetch(url, init), restoring the broken envelope
transports.
Add @ag-ui/core, client, encoder, proto to minimum-release-age-exclude
in .npmrc so the freshly published 0.0.56 (under the 24h release-age
gate) installs in CI.
@ag-ui/client 0.0.56 changed runHttpRequest to a thunk signature, breaking
@copilotkit/core's ProxiedCopilotRuntimeAgent. OSS-248 only needs
@ag-ui/langgraph 0.0.41; keep that, revert the unrelated core/client/protocol
'latest' bump. Adopting client 0.0.56 is a separate migration.
## What & why
A fresh **Angular 21** + CopilotKit setup (validated this week against
an enterprise eval that was blocked on it) hits avoidable friction. This
PR fixes the two issues that are unambiguously correct, and documents a
third for follow-up.
### Fixed here
- **Peer-dep `ERESOLVE`** — `@angular/*` peer range was `^19.0.0`, so a
clean install on Angular 20/21 failed and required `--legacy-peer-deps`.
Widened to `^19.0.0 || ^20.0.0 || ^21.0.0`. (The library is built with
ng-packagr 19 but runs fine on 20/21.)
- **README points at a package that 404s** — install/import examples
referenced `@copilotkit/angular`, which does not exist on npm. The
package is `@copilotkitnext/angular`. Corrected the install command and
all import examples.
### Documented, not fixed (needs a maintainer call)
- **`TS7016` missing types** — the published `exports` map has no
`types` condition, so TS (`moduleResolution: bundler`/`node16`) can't
find declarations. Adding `"types": "./dist/index.d.ts"` to `exports`
makes **bundler** resolution green (what Angular apps use), but trips
the `attw` **node16** gate by exposing a pre-existing
internal-resolution issue in the generated `.d.ts` files (on `main`,
attw passes only because `untyped-resolution` is in its ignore list).
Properly fixing this means addressing the ng-packagr exports/`.d.ts`
output, so it's left out of this PR. The README now documents the
`tsconfig paths` workaround so users aren't blocked in the meantime.
## Testing
- Lefthook green (format, `check:packages` incl. `publint`/`attw`,
commitlint).
- Empirically verified: bare-minimum app on Angular 21.2.16 builds, dev
server boots, and `<copilot-chat>` renders.
Originating real-world report:
https://copilotkit.slack.com/archives/C08LNPSE5CM/p1781015696972179🤖 Generated with [Claude Code](https://claude.com/claude-code)
A fresh Angular 21 setup hit two blockers: a clean install failed with
ERESOLVE, and the README pointed at @copilotkit/angular, which 404s on npm.
Widen the @angular/* peer range to 19-21 and correct the README package name,
install command, and the TS7016 types workaround.
Added quick start section with commands for new and existing projects.
<!--
Thank you for sending the PR! We appreciate you spending the time to
work on these changes.
Help us understand your motivation by explaining why you decided to make
this change.
**Please PLEASE reach out to us first before starting any significant
work on new or existing features.**
By the time you've gotten here, you're looking at creating a pull
request so hopefully we're not too late.
We love community contributions! That said, we want to make sure we're
all on the same page before you start.
Investing a lot of time and effort just to find out it doesn't align
with the upstream project feels awful, and we don't want that to happen.
It also helps to make sure the work you're planning isn't already in
progress.
As described in our contributing guide, please file an issue first:
https://github.com/ag-ui-protocol/ag-ui/issues
Or, reach out to us on Discord: https://discord.com/invite/6dffbvGU3D
You can learn more about contributing to copilotkit here:
https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md
Happy contributing!
-->
## What does this PR do?
(Describe the changes introduced in this PR)
## Related PRs and Issues
- (Direct link to related PR or issue, if relevant)
## Checklist
- [ ] 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
- [ ] "Allow edits by maintainers" is checked (lets us help iterate on
your PR directly — faster turnaround for everyone)
## Problem
The "CopilotKit Intelligence" indicator's icon (spinner → checkmark)
rendered **blank in Safari and Firefox**. Its geometry was defined
through the CSS `d:` property, which is Blink-only (Chrome/Edge) — so in
any other engine the stylesheet-driven path drew nothing.
## Fix
- **Geometry in the `d` attribute, not CSS `d:`** — renders in every
browser.
- **Two overlaid paths instead of one morphing path.** A spinning
**arc** that fades out, and a **checkmark** that draws itself in via
`stroke-dashoffset`, upright. Cross-fading two static shapes is more
robust than path-morphing (the old `d:` morph was Chrome-only anyway).
- **Arc spins via `transform-box: fill-box; transform-origin: center`**
— the Safari-safe way to rotate an SVG sub-element about its center.
(`transform-box: view-box` is mis-resolved by WebKit and spins
off-center; a SMIL `<animateTransform>` fixes Safari but stalls for a
beat on first paint in Chrome — `fill-box` + `center` is correct and
instant in both.)
- **Spin isolated to the arc**, so the checkmark always renders upright
regardless of where the spin was when the turn finished, and the arc
keeps spinning as it fades (no abrupt stop / snap-back).
- **`pathLength="1"` on both paths** so dashes are expressed as plain
fractions — one consistent, self-documenting idiom for both shapes.
- **`prefers-reduced-motion` support** added: the arc doesn't spin and
the in-progress → finished states swap instantly.
- Both stale design docblocks rewritten to describe the actual
implementation.
## Scope
Two files — `IntelligenceIndicatorView.tsx` and `globals.css`. No
behavior/runtime changes; purely the indicator's presentation. The
settle choreography (glass chrome, hue shift, faux-italic label) is
unchanged.
## Testing
- `nx test react-core` — 24 intelligence-indicator tests pass (the suite
asserts DOM structure/behavior; cross-browser rendering itself isn't
observable in jsdom and was verified manually in Chrome + Safari).
- oxlint / oxfmt clean; type-check clean for the changed files.
- Manually verified in **Chrome and Safari**: icon renders, spins
centered, fades out mid-spin, checkmark draws in upright; no Chrome
startup stall, no Safari wobble.
ag-ui-langgraph's tool factory now takes one A2UIToolParams object (model
inside) and folds composition_guide into the guidelines bag.
- sdk-js middleware: getA2UITools(params) + type A2UIToolParams import;
pin @ag-ui/langgraph 0.0.40 (the JS release carrying the new API).
- sdk-python middleware: get_a2ui_tools(params) + guarded A2UIToolParams
import; pin ag-ui-langgraph >=0.0.41 (the py release with the new API).
- Update the a2ui injection test skip-reason wording.
## Summary
- polish the Showcase shell docs merged in #5306 so headings, related
links, and prose match the rest of the site
- clarify AgentRunner telemetry wording for the v2 runtime architecture
- fix the shell-docs sidebar banner key warning and update stale
shell-docs test expectations
## Verification
- `git diff --name-only | xargs pnpm exec oxfmt --check`
- `npm run lint` in `showcase/shell-docs`
- `npm run typecheck` in `showcase/shell-docs`
- `npm run test` in `showcase/shell-docs`
- `npm run build` in `showcase/shell-docs`
- pre-commit hook passed `check-binaries`, `lint-fix`,
`test-and-check-packages`, and `commitlint`
## Notes
- Root `pnpm run check-format` still reports unrelated formatting issues
on fresh `main`; the changed-file formatter check passes.
- `npm run build` still emits the existing Turbopack NFT warning from
`next.config.ts` / `llms-mdx`, but completes successfully.
## Summary
Fills documentation gaps that Pathfinder (our docs-indexing /
gap-analysis system) flagged in `showcase/shell-docs` — new backend,
Microsoft Agent Framework / Mastra integration, reference-hook,
troubleshooting, and shared-state pages, plus accuracy corrections to
existing v1/v2 pages. 43 files, 6 by-area commits, rebased onto current
`main`.
## Corrections (source-verified across two review passes)
- **.NET MAF samples:** tool names now match the frontend (`Name =
"get_weather"` / `"step_progress"`) so the renderer/middleware actually
fire.
- **v1/v2 provider identity:** v2-specific examples (e.g.
`showDevConsole="auto"`) now use `<CopilotKitProvider>` — `<CopilotKit>`
exported from `@copilotkit/react-core/v2` is the v1 backward-compat
component, which has no `"auto"` mode.
- **Imports / snippets:** added missing `useRenderTool` / `z` /
`useAgent` imports + `"use client"`; removed a nonexistent
`mcpApps.serverId` field; fixed an off-by-2 code-highlight range.
- **API accuracy:** Express legacy factory is
`copilotRuntimeNodeExpressEndpoint`; v1 `useAgent` `runAgent` signature
+ `UseAgentProps` type name; `useRenderToolCall` falls back to the
default renderer (not `null`); `useComponent` also registers a tool; v1
`enableInspector` localhost/`0.0.0.0` default vs v2 `"auto"` nuance.
- **Nav / icons:** registered `lucide/Map`; wired new pages into
`meta.json`.
- **Deletion:** removed the orphaned
`content/docs/reference/v2/hooks/useAgent.mdx` — verified safe (the
canonical `content/reference/hooks/useAgent.mdx` is intact and all
inbound links resolve).
## Notes for reviewer
- The working tree had no `node_modules`, so the docs build was **not
run locally — relying on CI** for the build / lint / commitlint gate.
- Deferred polish (follow-up): state-rendering "in the chat" framing,
decorative `AgentState` types, `agentId`-key explanation,
`useFrontendTool` migration example, error-reference dev-warn nuance.
## Test plan
- [ ] CI green (shell-docs build, lint, commitlint)
## Summary
Follow-up to #5323. That PR made **llamaindex, agno, claude-sdk-python**
emit AG-UI `REASONING_MESSAGE_*`, but only bumped
**claude-sdk-typescript**'s `@ag-ui/client` to `0.0.48` — leaving the
other three on `^0.0.43`, whose `@ag-ui/core` discriminated-union lacks
`REASONING_MESSAGE_*`. On staging the frontend threw
`invalid_union_discriminator` on the new event and the reasoning demos
broke (assistant never responded). This bumps `@ag-ui/client` (+
transitive `@ag-ui/core`/`@ag-ui/encoder`) to exact `0.0.48` on those
three, matching claude-sdk-typescript.
## Verification (local-first, staging-equivalent)
Proven GREEN on the local built-image rig (real Docker image + HTTP
entrypoint + d5/d6 aimock fixtures + Playwright browser — not a dev
server): for llamaindex, agno, claude-sdk-python — D5 reasoning 2/2, D6
`reasoning-display` pass, `[data-testid="reasoning-block"]` mounts,
`invalid_union_discriminator = 0`.
## validate-pins
The 3 caret `@ag-ui/client` pins become exact → FAIL count ratcheted
down accordingly in `fail-baseline.json`.
## Follow-ups (separate, not in this PR)
- Isolate-rig PocketBase pb-auth seeding mismatch (`admin@localhost.dev`
vs `admin@example.com`).
- agno reasoning demo uses `gpt-4o-mini` (no native `reasoning_content`)
— fine under aimock, non-deterministic on a real model; route to a
reasoning model or harden the `<reasoning>`-tag fallback.
- Staging sweep probe-config still references old route names
(`agentic-chat-reasoning`/`reasoning-default-render` → 404); the
reasoning-custom/reasoning-default cells won't be probed until that
propagates.
## Test plan
- [ ] CI green
- [ ] Post-merge: rebuild `:latest` + confirm staging d5/d6
reasoning-display green for the 3 backends