6728 Commits

Author SHA1 Message Date
Tyler Slaton 2596e8d932 chore: release monorepo v1.56.3 (#4138)
## Release monorepo v1.56.3

**Scope:** `monorepo` | **Bump:** `patch`

---

### How this release process works

1. **This PR was created automatically** by the "release / create-pr"
workflow.
   It bumped the `monorepo` packages to `1.56.3`
   and generated AI-enhanced release notes.

2. **CI runs on this PR** — the full test suite (unit tests, lint, type
checks, build)
   must pass before merging. This is the review gate.

3. **Review the release notes** in `release-notes.md` in this PR.
If a Notion draft was created, you can edit the release notes there
before merging.

4. **When this PR is merged**, the `release / publish` workflow
automatically:
   - Builds all packages
   - Publishes the `monorepo` packages to npm at version `1.56.3`
   - Creates git tag `monorepo/v1.56.3`
   - Creates a GitHub Release with the final release notes

### Before merging

- [ ] CI is green (tests, lint, types, build)
- [ ] Version bumps look correct
- [ ] Release notes are accurate (edit in Notion if a draft was created)

---

> **Do not merge until CI is fully green.** The full test suite runs
automatically on this PR.
v1.56.3
2026-04-22 13:59:09 -07:00
Ben Taylor 08f48a2c58 fix(react-core): Restore welcome screen when a generated thread UUID is pass from wrappers (#4172)
<!--
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?

Fresh empty chats were hitting `/connect` against thread IDs the backend
had never seen (404s) and the
welcome screen stayed hidden. Root cause: the v1 `<CopilotKit>` wrapper
pipes a
`ThreadsProvider`-minted UUID down as `threadId`, and downstream
consumers were treating `!!threadId`
as "caller-chosen," so an auto-minted placeholder looked identical to a
real thread.

Fix: introduce an explicit `hasExplicitThreadId` signal and plumb it
end-to-end, so consumers that only
make sense against a real backend thread (`/connect`, switch-flash
suppression, welcome-screen gating)
   can distinguish a caller-chosen thread from an internal placeholder.

 ## Changes

- **`ThreadsProvider`** — exposes `isThreadIdExplicit`. True when the
`threadId` prop is supplied or
`setThreadId()` has been called; false for the first-mount auto-minted
UUID. Explicitness via
  `setThreadId` is sticky across prop churn.
- **`CopilotChatConfigurationProvider`** — accepts an optional
`hasExplicitThreadId` prop (overrides
inference), otherwise infers from `!!threadId`. OR-inherits from parent
config so explicitness
  propagates through nested/bare providers.
- **v1 `CopilotKit` bridge** (`copilotkit.tsx`) — reads
`isThreadIdExplicit` from `useThreads()` and
forwards it to `CopilotChatConfigurationProvider`, so the auto-minted
UUID no longer masquerades as
  caller-chosen.
- **`CopilotChat`** — `isConnecting` and the `/connect` effect now gate
on `hasExplicitThreadId`
instead of `!!providedThreadId`, so a caller-chosen thread from a
wrapping provider is honored while a
  leaked auto-UUID is not.

  ## Test plan

- [x] `threads-context.test.tsx` — `isThreadIdExplicit` transitions:
auto→explicit via `setThreadId`,
  prop-driven explicitness, stickiness after prop removal
- [x] `CopilotChatConfigurationProvider.test.tsx` — inference, explicit
`false` override (v1 bridge
  case), OR-inheritance through nested chains
- [x] `v1-explicit-threadid-bridge.test.tsx` (new) — regression coverage
for the v1 wrapper
  specifically
- [x] `CopilotChat.welcomeGate.test.tsx` (new) — welcome screen stays
visible on a bare mount;
  `/connect` is not called without an explicit thread
  - [x] `packages/react-core` full test suite passes (1149 tests)
- [ ] Manual smoke in `examples/integrations/langgraph-python-threads`:
fresh app → welcome screen
  shows → first message starts a real thread

## 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
2026-04-22 15:53:00 -05:00
Jordan Ritter ae13b15909 feat(showcase-ops): L1-L4 coverage on all 34 services (packages + starters) (#4178)
## Summary

Extends showcase-ops to run all four health levels against every
showcase service (17 packages + 17 starters = 34). Auto-discovered via
the `railway-services` source so new services are monitored without YAML
edits.

Supersedes #4173, #4175, #4177 — consolidated here.

## Coverage matrix

| Level | Signal | Driver | Cadence | How |
|---|---|---|---|---|
| L1 health | `health:<slug>` | smoke (existing) | */15 | GET `/health`
|
| L1 liveness | `smoke:<slug>` | smoke | */15 | GET `/smoke` |
| L2 agent | `agent:<slug>` | smoke (extended) | */15 | POST
`/api/copilotkit/`, assert non-404 |
| L3 chat | `chat:<slug>` | e2e-smoke (new) | */30 | Playwright chat
round-trip on `/demos/agentic-chat` |
| L4 tools | `tools:<slug>` | e2e-smoke | */30 | Playwright tool
rendering on `/demos/tool-rendering` (gated by `demos.includes`) |

Each cycle produces up to 34 × 5 = 170 signal rows (L4 only fires for
slugs with the demo). Alert rules fire per-key on red-tick transitions.

## Fixes

- **smoke driver extended for L2**:
`showcase/ops/src/probes/drivers/smoke.ts` emits a third side-channel
`agent:<slug>` from a non-404 POST check against the copilotkit
endpoint. 98.55% line coverage.
- **e2e-smoke driver implemented**:
`showcase/ops/src/probes/drivers/e2e-smoke.ts` wires Playwright
in-process. Launches headless chromium per invocation, runs L3 +
(optionally) L4, aborts cleanly on `ctx.abortSignal`. Registered in
`orchestrator.ts`.
- **Dockerfile**: installs `playwright chromium --with-deps` in the
runner stage; bundles `registry.json` to `/app/data/` so the e2e driver
can look up each slug's `demos` array.
- **Discovery auto-filter**: `railway-services.ts` gets a `nameExcludes:
string[]` filter field applied after `namePrefix`. Both `smoke.yml` and
`e2e-smoke.yml` switch to discovery — future services auto-picked up.
- **Alert rules**: `agent-red-tick.yml`, `chat-red-tick.yml`,
`tools-red-tick.yml` — modeled on `smoke-red-tick.yml` (green→red /
sustained_red / red→green triggers, `!channel` escalation, 20-min
`minDeployAgeMin` guard). `DIMENSIONS` enum in `src/types/index.ts`
extended with `agent`, `chat`, `tools`.

## Commit layout (7 grouped commits)

1. `feat(showcase/ops): L1-L4 alert rules for agent/chat/tools depth
signals` (#4173)
2. `feat(showcase-ops): smoke probe L2 agent check + railway-services
auto-discovery` (#4175)
3. `Add Playwright in-process e2e-smoke driver for L3 + L4 coverage`
(#4177 pt 1)
4. `Add nameExcludes filter to railway-services discovery` (#4177 pt 2)
5. `Register e2e-smoke driver with the probe registry` (#4177 pt 3)
6. `Bundle registry.json + install Playwright chromium in ops image`
(#4177 pt 4)
7. `Add e2e-smoke probe config` (#4177 pt 5)

## Test plan

- [x] `pnpm -F @copilotkit/showcase-ops typecheck` — clean
- [x] `pnpm -F @copilotkit/showcase-ops test` — 704 tests passing across
37 files
- [x] `pnpm -w format` — no drift
- [x] Docker build of showcase/ops/Dockerfile — succeeds; chromium 147.x
bundled; registry.json at `/app/data/`
- [ ] After merge + redeploy, verify PB `status_history` contains
non-deploy rows for all 4 signals (`smoke:*`, `health:*`, `agent:*`,
`chat:*`, `tools:*` where applicable) within one */30 cycle.
- [ ] Railway container memory stays under 8GB during L3+L4 cycles
(`max_concurrency: 2`).

## Caveats

- Playwright browser lifecycle = ~400MB memory spike per run.
`max_concurrency: 2` + serial L3→L4 per slug keeps peak bounded. If
Railway OOMs we'll need to reduce concurrency or split to a dedicated
runner service.
- L4 is gated by `demos.includes("tool-rendering")` against the bundled
registry.json — slugs without that demo produce no `tools:*` row
(correct).
- aimock routing verified for all 34 services (30 × `OPENAI_BASE_URL`, 4
× `ANTHROPIC_BASE_URL`). L3/L4 responses are deterministic
fixture-driven.
2026-04-22 13:52:03 -07:00
Jordan Ritter c68a0e519c Add e2e-smoke probe config
30-minute schedule (half the smoke cadence — L3+L4 per tick pulls a
real chromium page so we trade freshness for memory + bandwidth
headroom). 180s outer timeout covers two 60s page timeouts plus
chromium launch overhead. max_concurrency 2 caps peak memory at ~600MB
(each chromium ~300MB RSS) to fit the orchestrator's Railway footprint.
Discovery uses the railway-services source with namePrefix + the new
nameExcludes filter to hit every user-facing showcase without the
7 infra services.
2026-04-22 13:44:38 -07:00
Jordan Ritter e90c4a385c Bundle registry.json + install Playwright chromium in ops image
Runtime stage needs two things for e2e-smoke: chromium (headless) and
the shell registry so the driver can gate L4 on demos membership.
Build stage pulls the single registry.json file through rather than
fetching at probe-tick time, keeping the image hermetic. Runtime
stage is already on Debian-slim (needed by Playwright's glibc-linked
chromium); `playwright install --with-deps chromium` runs as root
before the USER node drop so apt-get succeeds. /ms-playwright is
chown'd to node so the runtime user can read the browser tree.
2026-04-22 13:44:38 -07:00
Jordan Ritter 2ca7ea1be3 Register e2e-smoke driver with the probe registry
Wire the in-process Playwright driver so probe ticks resolving to
kind: e2e_smoke dispatch to it. Drops the 'deliberately NOT
registered yet' placeholder that flagged the driver as scaffold-only.
2026-04-22 13:44:38 -07:00
Jordan Ritter 0f0e95334c Add nameExcludes filter to railway-services discovery
The e2e-smoke probe needs to discover every user-facing showcase
service without enumerating infra (aimock, ops, pocketbase, shell,
shell-{dashboard,docs,dojo}). Extend the discovery filter schema
with an optional nameExcludes array so a single namePrefix can pull
in all 34 services and explicitly drop the 7 that don't expose user
demos, rather than maintaining 27 separate namePrefix entries.
2026-04-22 13:44:32 -07:00
Jordan Ritter d29e39b1cb Add Playwright in-process e2e-smoke driver for L3 + L4 coverage
Replace the JSON-reporter scaffold with an in-process Playwright
driver. Each invocation launches one headless chromium, runs L3
against /demos/agentic-chat (any non-empty response) and, when the
service registry entry includes tool-rendering, runs L4 against
/demos/tool-rendering (weather vocabulary check). Primary return is
e2e-smoke:<slug>; chat:<slug> and tools:<slug> side-emit via
ctx.writer. AbortSignal is wired end-to-end so timeout teardown
kills the browser cleanly. Launcher + demos resolver are dep-injected
for unit testability.

Input schema accepts { key, backendUrl?, publicUrl?, name?, demos? }
with a zod refine requiring at least one URL. Slug derivation strips
the "showcase-" prefix so Railway service names align with registry
entries (bare slugs). The default demos resolver memoises a read of
/app/data/registry.json at first use, keeping probe-tick overhead at
a single JSON parse across the orchestrator lifetime.
2026-04-22 13:44:19 -07:00
Jordan Ritter 7b8bbc64d5 feat(showcase-ops): smoke probe L2 agent check + railway-services auto-discovery
Extends the smoke probe driver to emit a third side-emission per target:
`agent:<slug>` — POST `${backendUrl}/api/copilotkit/` with `{}` body,
green on non-404 response (runtime is mounted), red on 404 or transport
failure. Matches the `checkAgentEndpoint` contract in the e2e helpers
(integration-smoke.spec.ts L2 `@agent` assertion).

Switches `config/probes/smoke.yml` from a static 17-target list to the
`railway-services` discovery source with `namePrefix: "showcase-"` and
an explicit `nameExcludes` for infra services (aimock/ops/pocketbase/
shell*). New showcase services are picked up automatically on the next
tick without YAML edits.

- src/probes/discovery/railway-services.ts: add `nameExcludes: string[]`
  filter field, applied AFTER the prefix check so excluded services skip
  per-service env fetch entirely.
- src/probes/drivers/smoke.ts: accept both static (`{key,url}`) and
  discovery (`{key,name,publicUrl,imageRef,env}`) input shapes. Derive
  slug by stripping `showcase-` prefix from `name` (discovery) or
  splitting key on `:` (static fallback). Rewrite primary result key to
  `smoke:<slug>` in discovery mode so existing alerts keyed on
  `smoke:ag2` / `smoke:starter-ag2` stay intact.
- Sequential probes kept for socket-count bound: at max_concurrency=6 *
  34 services * 3 endpoints, parallel would push 612 inflight sockets.
- Coverage: smoke driver 98.55% lines, exceeds 95% gate.
2026-04-22 13:44:19 -07:00
Jordan Ritter cbb4d5d382 feat(showcase/ops): L1-L4 alert rules for agent/chat/tools depth signals
Adds three new alert-rule YAMLs modeled on smoke-red-tick.yml so the
per-starter depth signals side-emitted by the smoke + e2e-smoke drivers
(agent:<slug>, chat:<slug>, tools:<slug>) produce Slack alerts on
green_to_red / sustained_red / red_to_green transitions with the same
!channel 1-hour escalation + 15-minute rate limit + 20-minute deploy
grace as the L1 smoke rule.

Also extends the DIMENSIONS enum with the three new closed values so
rule-side typos continue to fail at load with a listed-valid-members
Zod error instead of silently never matching any probe key.

No driver or discovery changes in this commit — pure rule YAML + the
single enum entry each rule's `signal.dimension` resolves against.
2026-04-22 13:44:19 -07:00
Jordan Ritter 1b2fd1e70b fix(showcase): install curl in TS runtime stages — watchdog probes were silently exiting rc=127 (#4174)
## Summary
- Add `curl` to the runtime `apt-get install` line in:
  - `showcase/starters/template/dockerfiles/Dockerfile.typescript`
-
`showcase/packages/{claude-sdk-typescript,langgraph-typescript,mastra}/Dockerfile`
  - 3 starter Dockerfiles (regenerated from template)

## Why
Multi-stage Docker refactor (#4147) moved TS showcase services to
`node:22-slim` runtime. That base image doesn't include `curl`. The
watchdog's liveness probe invokes `curl -sS --max-time 5
http://127.0.0.1:8124/ok` — which exits `rc=127 "command not found"`
every cycle. After 180s grace + 3×30s strikes the watchdog kills the
agent. Railway auto-restarts. Loop forever.

Verified via `railway ssh`:
```
sh: 1: curl: not found
rc=127
```
while `ss -tlnp` on the same container confirmed both :8123
(langgraph-api) and :8124 (liveness.mjs) LISTEN. The agent was always
healthy — the probe was broken.

## Test plan
- [ ] Local amd64 docker build for starter+package variants succeeds
- [ ] `docker run ... sh -c "which curl"` prints `/usr/bin/curl`
- [ ] After Railway redeploy of langgraph-typescript, steady-state: no
kill-loop, `/api/health` green
2026-04-22 13:38:08 -07:00
Jordan Ritter 575360cd54 fix(showcase): install curl in TS runtime stages — watchdog probe was silently exiting rc=127
The multi-stage Docker refactor (#4147) moved TypeScript showcase services
to `node:22-slim` runtime. That base image does NOT include `curl`.

entrypoint.sh's watchdog runs `curl -sS --max-time 5 http://127.0.0.1:8124/ok`
every 5s to probe the liveness endpoint. Without curl the probe exits
rc=127 "command not found" every cycle. After 180s grace + 3x30s strikes
the watchdog kills the agent process. Railway auto-restarts. Kill-loop
forever.

Verified via `railway ssh --service showcase-langgraph-typescript`:

    sh: 1: curl: not found
    rc=127

while `ss -tlnp` on the same container confirmed BOTH 0.0.0.0:8123
(langgraph-api) and 0.0.0.0:8124 (liveness.mjs) LISTEN. The agent
servers were healthy the whole time — the probe tool was missing.

Fix: add `apt-get install -y --no-install-recommends curl` to the
runtime stage of:

  - showcase/starters/template/dockerfiles/Dockerfile.typescript (source)
  - showcase/packages/claude-sdk-typescript/Dockerfile
  - showcase/packages/langgraph-typescript/Dockerfile
  - showcase/packages/mastra/Dockerfile

3 starter Dockerfiles regenerated from the template via
`pnpm -C showcase/scripts generate-starters`.

Python/Java/.NET services already install curl (they need it for
NodeSource or similar) and are unaffected.

Smoke: local `docker build --platform linux/amd64` for both
starter + package variants succeeded; `docker run ... sh -c "which curl"`
prints /usr/bin/curl in both.
2026-04-22 13:33:34 -07:00
github-actions[bot] b587d71165 style: auto-fix formatting 2026-04-22 20:29:40 +00:00
Benjamin Taylor 771879c35a chore: drop stray a2ui-theme background + bump generated cli version
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 15:28:05 -05:00
Benjamin Taylor 9a3552bd4d fix(react-core): gate /connect and welcome screen on explicit threadId
Threads-minted UUIDs were leaking through as if caller-chosen, so fresh
empty chats fired /connect against a backend that had never seen the
thread (404) and the welcome screen stayed hidden. Plumb an explicit
hasExplicitThreadId signal through ThreadsProvider,
CopilotChatConfigurationProvider, and the v1 CopilotKit bridge so
consumers can distinguish an auto-minted placeholder from a real
caller-supplied thread.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 15:28:05 -05:00
Jordan Ritter 4b94922bee fix(ci): shell-dojo build context — use repo root + explicit dockerfile path (#4170)
## Summary
- Change `shell-dojo` matrix entry: `context: "."` + `dockerfile:
"showcase/shell-dojo/Dockerfile"`. Matches shell-dashboard pattern.

## Why
Build fails with `failed to walk /tmp/buildkit-mount.../showcase: no
such file or directory`. `showcase/shell-dojo/Dockerfile` has `COPY
showcase/scripts/...`, `COPY showcase/shared/...`, `COPY
showcase/packages/...` — expects repo root as build context. Matrix had
`context: showcase/shell-dojo` which scopes the context to just
shell-dojo's own directory, making those COPYs fail.

## Test plan
- [ ] Next deploy of shell-dojo succeeds
2026-04-22 13:09:56 -07:00
Jordan Ritter 9e389bdf65 fix(ci): inline Slack payload on test_smoke-starter to stop silent alert suppression (#4169)
## Summary

- Replace `jq -n --rawfile text … > \$(mktemp)` + `payload-file-path`
with inline `payload:` + `toJSON(format(...))` on the scheduled
Slack-alert step in `test_smoke-starter.yml`.
- Pattern already in use in `test_smoke-starter-deployed.yml` (PR #4068)
and `showcase_validate.yml` — this brings the last holdout in line.

## Why

Every scheduled run of `test / smoke / starter` that legitimately fails
a matrix leg (upstream outage, floating-dep breakage, etc.) has been
crashing the downstream alert step with:

```
##[error]Invalid input! Failed to parse contents of the provided payload file
```

Two compounding causes:

1. `slackapi/slack-github-action@v2.1.0` rejects payload files whose
name does not end in `.json`/`.yaml`/`.yml`. `mktemp` produces
extensionless files.
2. `jq -n --rawfile text "$SLACK_MSG"` under `set -e` can abort on
edge-case summary input (missing tmpfile, non-UTF-8 bytes surviving the
sanitizer), leaving an empty or missing payload.

Either way, the notifier failed before firing, so genuine outages went
unreported in `#oss-alerts`. The user reported this as "Showcase: Drift
Detection" — that specific workflow was already retired to showcase-ops
on 2026-04-22 (commit `89eb0734b`), but the same
jq-rawfile-then-payload-file-path pattern still lived in
`test_smoke-starter.yml`.

Inline `payload:` with `toJSON(format(...))` sidesteps both failure
modes: quotes, backslashes, and newlines in the sanitized summary are
safely JSON-encoded at template-eval time, and there is no intermediate
file to mishandle.

Audit of remaining file-based payloads left intentionally unchanged:
- `test_smoke-starter-deployed.yml` recovery step writes to
`/tmp/starter-smoke-recovery.json` (valid extension, simple `jq --arg`
scalar) — safe.
- `showcase_docs-sync.yml` writes to `slack-payloads/*.json` (valid
extensions, `jq --arg` scalars) — safe.

## Test plan

- [ ] `actionlint .github/workflows/test_smoke-starter.yml` reports no
new findings (confirmed locally — one pre-existing line-64 warning
unrelated to this diff)
- [ ] Next scheduled run on `main` that has a genuinely failing matrix
leg posts a well-formed red alert to `#oss-alerts` instead of `Invalid
input! Failed to parse contents of the provided payload file`
- [ ] A scheduled run where all matrix legs pass remains silent (no
behavior change on the green path)
2026-04-22 13:03:50 -07:00
github-actions[bot] 9b1c42b19c style: auto-fix formatting 2026-04-22 20:01:27 +00:00
Jordan Ritter 4ec348d6ba fix(ci): shell-dojo build context — use repo root + explicit dockerfile path
Dockerfile COPYs reference showcase/scripts, showcase/shared, showcase/packages
from repo root, but matrix entry had context scoped to showcase/shell-dojo.
Match shell-dashboard pattern: context "." + explicit dockerfile path.
2026-04-22 12:59:55 -07:00
github-actions[bot] e38c00ca54 style: auto-fix formatting 2026-04-22 19:54:39 +00:00
Jordan Ritter 351eca0266 fix(ci/test-smoke-starter): build Slack payload inline to avoid payload-file-path parse failures
The failure-alert Slack step crashed every scheduled run with
'Invalid input! Failed to parse contents of the provided payload file'.
Two compounding causes: slackapi/slack-github-action@v2.1.0 rejects
payload files without a .json/.yaml/.yml extension (mktemp produces
extensionless files), and 'jq -n --rawfile' under 'set -e' can abort
on edge-case summary input, leaving an empty/missing payload.

Switch to the inline 'payload:' + toJSON(format(...)) pattern already
used in test_smoke-starter-deployed.yml (PR #4068) and
showcase_validate.yml. Summary text is sanitized into $GITHUB_ENV via
heredoc (handles embedded =, quotes, newlines), then JSON-encoded by
toJSON at template-eval time — no intermediate file, no jq crash path,
genuine outages surface in #oss-alerts instead of being silently
suppressed by a broken notifier.

test_smoke-starter-deployed.yml recovery path (/tmp/...-recovery.json,
jq --arg) and showcase_docs-sync.yml (static slack-payloads/*.json)
use safe patterns already — left unchanged.
2026-04-22 12:52:43 -07:00
Jordan Ritter 1ddea47c37 fix: main CI recovery after #4113 — consolidated shell-docs + shell-dashboard + langgraph-fastapi + commitlint + capture-previews fixes (#4167)
## Summary

Consolidates the 5 independent fixes needed to return main CI to green
after #4113 (showcase-ops) merged. Supersedes individual PRs #4160,
#4161, #4162, #4163, #4164, #4165 — closing those in favor of this one.

## Fixes (5 grouped commits, one per area of concern)

1. **`fix(shell-docs): resolve findFrameworksWithCell + SidebarLink
scope type errors`**
- Exports shared 3-arg `findFrameworksWithCell` from `docs-render.tsx`,
drops dead 1-arg locals in both `[[...slug]]/page.tsx` files (the root
copy was unused and referenced an undeclared `demos`).
- Makes `SidebarLink.scope` optional (was already effectively unused
internally — destructured as `_scope`). Step-2 cards on the overview
page now typecheck.
- Supersedes #4160 (missing `demos` import) — the underlying dead-code
removal makes the import unnecessary.

2. **`chore(commitlint): skip merge commits from subject validation`**
   - `commitlint.config.js` ignore for `Merge ` prefix.
- `.github/workflows/static_quality.yml` guard: `git rev-list --parents
-n 1 HEAD` short-circuit when parent count >1. Catches GitHub's "Create
merge commit" flow where the subject is the PR title but the body pulls
markdown list lines that commitlint reads as additional subjects.

3. **`fix(shell-dashboard): resync scripts lockfile + unsilence npm
ci`**
- `showcase/scripts/package-lock.json` drifted from `package.json`
(pinned old `vitest@4.1.4`, missing `@vitest/coverage-v8@4.1.5`) —
regenerated via `npm install --package-lock-only`.
- Removes `--silent` from the Dockerfile's builder-stage `npm ci` calls
so next same-class failure surfaces the error directly.

4. **`fix(showcase/scripts): capture-previews skips demos without a
route`**
- `langgraph-python/cli-start` has no `route` field (it's a CLI
copy-paste card, not a navigable page). Script was building
`${backendUrl}undefined` → 45s DNS timeout. 10-line guard in
`buildTargets` + visible `[SKIP]` log.

5. **`fix(showcase/langgraph-fastapi): pre-create .langgraph_api dir
with app ownership`**
- Commit `b9bcf2e6b` added `USER app` to the Dockerfile.
`langgraph_runtime_inmem/store.py` calls `os.makedirs(".langgraph_api")`
at import time against CWD=`/app` — the `app` user can't write →
`PermissionError [Errno 13]` → Next.js stays alive so `wait -n` never
fires → watchdog restart-loops until the 600s budget expires.
- #4113 was the first rebuild that actually ran the new image (other 16
starters kept their pre-USER-app cached containers via paths-filter).

## Test plan

- [x] Each fix was verified individually in its original PR (all 6 PRs
were green).
- [x] `npm run build` in `showcase/shell-docs` — clean (26 static pages
generated).
- [x] `docker build -f showcase/shell-dashboard/Dockerfile .` through
`--target builder` — clean on Depot.
- [ ] CI on this PR will reverify all four Docker builds + commitlint.
2026-04-22 12:52:28 -07:00
Mike Ryan b1da4c7a4a feat(examples/langgraph-python-threads): use intelligence composite image (#4120)
## Summary

Replaces the four separate intelligence containers (`db-migrations`,
`app-api`, `realtime-gateway`, `thread-culler`) in the
langgraph-python-threads example with a single `intelligence` composite
container that runs all of them under `s6-overlay` supervision. Compose
file drops from six services to three (`postgres`, `redis`,
`intelligence`). README updated to match.
2026-04-22 12:25:38 -07:00
github-actions[bot] f5b66a4088 style: auto-fix formatting 2026-04-22 19:20:30 +00:00
Jordan Ritter c05c83be9a fix(showcase/langgraph-fastapi): pre-create .langgraph_api dir with app ownership
Railway deploys on and after main@5ed233f01 failed health within 600s with:

  PermissionError: [Errno 13] Permission denied: '.langgraph_api'

First deploy of langgraph-fastapi since the b9bcf2e6b USER app change.
langgraph_runtime_inmem/store.py does `os.makedirs(".langgraph_api", exist_ok=True)`
at import time, resolving against CWD (/app). WORKDIR creates /app as root;
--chown=app:app on COPY only chowns contents. USER app (uid 1001) can't write
to /app, the agent subprocess crashes, Next.js stays alive so wait -n never
fires, and Railway / the watchdog restart loops until the 600s budget elapses.

Pre-create /app/.langgraph_api (and chown /app itself) so the first-import
makedirs is a no-op.

Verified locally:
- docker build + --load clean
- agent /ok → 200
- next /api/health → 200
- no PermissionError in logs
2026-04-22 12:16:40 -07:00
Jordan Ritter 4ef7a1fe31 fix(showcase/scripts): capture-previews skips demos without a route
Non-navigable manifest entries (e.g. langgraph-python/cli-start, a CLI
copy-paste card) have no `route` field. The old code concatenated
`${backendUrl}${undefined}` producing URLs like
`...railway.appundefined/`, which Playwright chased until the 45s
response timeout, wasting CI budget and emitting a noisy
`ERR_NAME_NOT_RESOLVED` FAIL line per run.

Skip those entries with a visible `[SKIP]` log so they drop out of the
capture set entirely. Only effect on target composition: cli-start no
longer appears in the `Failed: N/158` tally.

Verified by running the script locally with `--slug langgraph-python
--demo cli-start` (prints `[SKIP]`, exits clean) and `--slug
langgraph-python --demo agentic-chat` (still captures the MP4).
2026-04-22 12:16:39 -07:00
Jordan Ritter c1360c4bcc fix(shell-dashboard): resync scripts lockfile + unsilence npm ci
showcase/scripts/package.json bumped vitest to ^4.1.5 and added
@vitest/coverage-v8 ^4.1.5, but package-lock.json still carried vitest
4.1.4 and was missing the coverage package entirely. Docker builder
stage runs `npm ci`, which refuses to reconcile drift and fails with:

    Missing: @vitest/coverage-v8@4.1.5 from lock file
    Invalid: lock file's vitest@4.1.4 does not satisfy vitest@4.1.5

Regenerated showcase/scripts/package-lock.json with
`npm install --package-lock-only` to bring it back in sync.

Also removed --silent from the builder-stage `npm ci` calls so the
next same-class lockfile drift surfaces the real error in CI instead
of a bare 'exit code: 1'. Kept --silent on the prod-deps stage (that
one wasn't masking anything here).

Verified: `docker build -f showcase/shell-dashboard/Dockerfile .`
completes end-to-end locally.
2026-04-22 12:16:39 -07:00
Jordan Ritter daa248388f chore(commitlint): skip merge commits from subject validation
GitHub's "Create a merge commit" merge option builds the commit message
from the PR body. When the body contains markdown lists or blank lines
(e.g. PR #4113 → merge 5ed233f01), commitlint parses subsequent
paragraphs as additional commit subjects and fails with subject-empty /
type-empty.

Two-layer fix:
  - commitlint.config.js: ignore standard "Merge " prefixed messages.
  - static_quality.yml: guard the push-path `--last` step with a
    parent-count check so true merge commits (which keep the PR-title
    header and thus don't match the "Merge " prefix) are skipped
    before commitlint runs at all.
2026-04-22 12:16:39 -07:00
Jordan Ritter 8db7b211a4 fix(shell-docs): resolve findFrameworksWithCell + SidebarLink scope type errors
Two pre-existing type errors from commit 9b05ed41 surfaced on main's
Docker build:

1. `unscoped-docs-page.tsx` imports `findFrameworksWithCell` from
   `@/lib/docs-render`, but the helper was only declared locally in the
   two page.tsx routes with a 1-arg signature (and referenced an
   undeclared `demos` in one case — dead code). Export a 3-arg shared
   version from docs-render.tsx that accepts the integration slug list
   and demo map as parameters (keeps the lib free of registry imports),
   drop the dead local in `[[...slug]]/page.tsx`, and rewire the live
   caller in `[framework]/[[...slug]]/page.tsx` through the shared
   export.

2. The Step-2 section cards on the overview call `<SidebarLink>`
   without the required `scope` prop. The prop was already ignored
   internally (destructured as `_scope`) so relaxing it to optional is
   the minimal fix and keeps the call-site intent documented.

`npm run build` in showcase/shell-docs now compiles cleanly.
2026-04-22 12:16:38 -07:00
Max Korp 8e6a3205f9 feat(examples/langgraph-python-threads): use intelligence composite image 2026-04-22 12:10:42 -07:00
devops-bot[bot] 432345485f Update preview URLs in registry 2026-04-22 18:53:07 +00:00
Jordan Ritter 5ed233f01f showcase-ops: replace GH Actions cron/alert workflows with in-cluster Railway service (#4113)
## Summary

New in-cluster Railway service `showcase-ops` replaces four GitHub
Actions cron/alert workflows for the CopilotKit showcase.
PocketBase-backed state, declarative YAML alert DSL, a reusable
probe-driver architecture, and server-side-filtered SSE into the
dashboard.

## Why

The legacy showcase alert stack was four ad-hoc cron workflows
(`showcase_smoke-monitor.yml`, `showcase_drift-detection.yml`,
`showcase_drift-report.yml`, `showcase_redirect-report.yml`) each
persisting state via `actions/cache` + loose JSON + scattered `jq -n
--rawfile` message assembly. This PR replaces that with:

- One alert-state store (PocketBase) instead of four ad-hoc persistence
mechanisms.
- One structured-payload renderer (two-phase filter extraction,
triple-brace safe-field allow-list) instead of ~20 scattered `jq` /
`toJSON(format())` / `printf '%b'` sites.
- One typed PB client with unified 401 re-auth, 429 `Retry-After`,
network/5xx backoff.
- One transition detector (pure function) — state-machine logic exists
in exactly one place.
- One probe-driver contract (`ProbeDriver<Input, Signal>`) +
discovery-source contract (`DiscoverySource<Output>`) so every future
probe shares one loader + invoker + typed-error taxonomy, configured
declaratively via YAML.

Adding a new dimension is now: add a driver + YAML + registry line. No
core changes required.

## Dimensions covered

`health`, `smoke`, `image_drift`, `version_drift`, `pin_drift`,
`e2e_smoke` (scaffolded, runner deferred), `redirect_decommission`,
`aimock_wiring`, `deploy`.

## Deleted in this PR

- `.github/workflows/showcase_smoke-monitor.yml`
- `.github/workflows/showcase_drift-detection.yml`
- `.github/workflows/showcase_drift-report.yml`
- `.github/workflows/showcase_redirect-report.yml`
- `showcase/scripts/generate-status.ts`
- `showcase/shell/src/data/status.json`
- `showcase/shell-dashboard/src/lib/status.ts`
- The `notify:` job of `showcase_deploy.yml` (replaced by a signed POST
to `/webhooks/deploy`)

## Commit layout (12)

Each commit is a coherent area; commit-by-commit review works cleanly.

1. \`chore(repo)\` — root workspace config + top-level showcase docs
2. \`feat(examples/v2)\` — rename interrupts-langraph →
interrupts-langgraph + integration cleanup
3. \`chore(showcase/packages)\` — QA markdown parity across all packages
+ integration tooling
4. \`feat(showcase/shell-docs)\` — error-boundary consolidation + docs
components
5. \`feat(showcase/shell-dashboard)\` — live PocketBase status wiring +
tests
6. \`refactor(showcase/scripts)\` — extract pure-TS cores for pin-drift
+ redirect-decommission
7. \`feat(showcase/pocketbase)\` — service (migrations + hooks + Docker)
8. \`feat(showcase/ops)\` — core service (HTTP + HMAC + metrics +
orchestrator + rules + render + storage + scheduler + targets)
9. \`feat(showcase/ops)\` — alert rule DSL + engine + YAML configs
10. \`feat(showcase/ops)\` — probe driver architecture + 6 drivers + 2
discovery sources + YAML configs
11. \`feat(showcase/ops)\` — Dockerfile + README + rotation drill
12. \`ci\` — retire legacy cron workflows + \`test_*\` rename +
showcase_deploy webhook wiring

## Test plan

- [x] \`pnpm -F @copilotkit/showcase-ops typecheck\` — clean
- [x] \`pnpm -F @copilotkit/showcase-ops test\` — 692 tests passing
across 37 files
- [x] \`pnpm -F @copilotkit/showcase-ops build\` — clean
- [x] \`showcase/shell-dashboard\` typecheck + test + build — clean
- [x] \`docker build -f showcase/ops/Dockerfile .\` — builds clean
(Playwright chromium included)
- [x] \`docker build -f showcase/pocketbase/Dockerfile
showcase/pocketbase/\` — builds clean
- [x] \`docker build -f showcase/shell-dashboard/Dockerfile .\` — builds
clean
- [ ] Deploy \`showcase-ops\` + \`showcase-pocketbase\` to Railway and
observe one red→red and one red→green transition
- [ ] Fire deploy webhook with valid HMAC — alert lands in
\`#oss-alerts\`
- [ ] Fire deploy webhook with stale timestamp (>300s) or wrong
signature — request rejected, \`webhook_rejections\` counter increments
- [ ] Playwright visual regression at iPhone SE (375×667), iPhone 14 Pro
Max (430×932), Desktop (1440×900) under all-green, mixed, and
all-unknown states

## Design spec

[Notion: showcase-ops design
spec](https://www.notion.so/3493aa381852811aa21bf09b2efa4a2d) · [Probe
drivers design](https://www.notion.so/34a3aa38185281bf8066f107401b2979)
2026-04-22 11:24:58 -07:00
Jordan Ritter 89eb0734bd ci: retire legacy cron workflows + test_* rename + showcase_deploy webhook wiring
Retire 4 cron-based GH Actions workflows now replaced by showcase-ops
probe drivers:
- showcase_drift-detection.yml
- showcase_drift-report.yml
- showcase_redirect-report.yml
- showcase_smoke-monitor.yml

Standardise workflow naming (test_* prefix):
- e2e_dojo.yml → test_e2e-dojo.yml
- e2e_examples.yml → test_e2e-legacy-v1.yml
- showcase_aimock-e2e.yml → test_e2e-showcase-on-demand.yml
- test_doc-examples.yml → test_integration-docs.yml
- test_runtime-servers.yml → test_integration-runtime.yml
- starter_deployed_smoke.yml → test_smoke-starter-deployed.yml
- starter-smoke.yml → test_smoke-starter.yml

showcase_deploy.yml: POST deploy-result webhook to showcase-ops after
every deploy so the alert engine ingests the outcome (replaces the
inline Slack curl + GitHub status update).

static_check-binaries.yml: minor refresh for the new workflow names.
2026-04-22 11:00:48 -07:00
Jordan Ritter 0c1baa8ecf feat(showcase/ops): Dockerfile + README + rotation drill
Multi-stage Dockerfile built on bookworm-slim with Playwright chromium
pre-installed (e2e-smoke runner) + pnpm-workspace.yaml + every
workspace package.json COPYd so the runtime stage resolves workspace:*
deps. README organised operate-first / build-second so an on-call
operator can configure + inspect the service before needing to rebuild
it. Rotation drill doc captures the weekly / monthly schedule for
pin-drift + redirect-decommission audits.
2026-04-22 11:00:47 -07:00
Jordan Ritter c69aeca835 feat(showcase/ops): probe driver architecture + 6 drivers + 2 discovery sources + YAML configs
Split the probe system into reusable contracts so every future probe
can share one loader + invoker + discovery enumeration path:
- ProbeDriver<Input, Signal> + DiscoverySource<Output> contracts
  (src/probes/types.ts)
- ProbeConfigSchema Zod union (static targets / discovery-driven /
  single-target) + chokidar-watched probe-loader + probe-invoker with
  AbortController-based per-target timeout + bounded concurrency
  (src/probes/loader/*)
- DiscoverySource typed error classes (Auth / Backend / Transport /
  Schema) + railway-services + pnpm-packages discovery sources
  (src/probes/discovery/*)
- 6 probe drivers: smoke (paired health side-emit), aimock-wiring,
  image-drift, pin-drift, version-drift, redirect-decommission.
  e2e-smoke driver scaffolded but unregistered pending runner wiring.
  redirect-decommission ships an inlined hermetic copy of the CLI
  formatter + seo-redirects catalogue to avoid runtime dynamic imports
  (src/probes/drivers/*)
- 6 probe YAML configs: smoke.yml, aimock-wiring.yml, image-drift.yml,
  pin-drift.yml, version-drift.yml, redirect-decommission.yml.
  Orchestrator registers these at boot; YAML edits hot-reload via
  chokidar + reloads/failures emit on the event bus.

Tests: 95% line-coverage floor on drivers + discovery, fixtures for
every driver's happy + error paths.
2026-04-22 11:00:47 -07:00
Jordan Ritter 8c0e2e07c2 feat(showcase/ops): alert rule DSL + engine + YAML configs
Alert rule DSL with Mustache templates, trigger-flags + transition
matching, closed-enum registries for kind/dimension/signal-filter/
action, triple-brace safe-field allow-list enforcement, escalation +
suppress guards. Ships 8 alert YAML rules:
- _defaults.yml (shared template + severity)
- smoke-red-tick, aimock-wiring-drift, image-drift, deploy-result,
  pin-drift-weekly, version-drift-weekly,
  redirect-decommission-monthly, e2e-smoke-failure

Each rule maps 1:1 onto a retired GH Actions cron workflow + keeps the
existing Slack message shape so #oss-alerts consumers are unchanged.
2026-04-22 11:00:47 -07:00
Jordan Ritter 9d04bdffb0 feat(showcase/ops): core service (HTTP + HMAC + metrics + orchestrator + rules + render + storage + scheduler + targets)
In-cluster Railway service replacing the legacy cron-based GH Actions
workflows. Core pieces:
- Hono HTTP server with HMAC-signed webhook ingress + Prometheus
  metrics + deploy webhook handler (src/http/*)
- structured logger with log-level filtering (src/logger.ts)
- event bus + transition detector (src/events/*)
- orchestrator wiring rule + probe + target registries and the
  scheduler loop (src/orchestrator.ts)
- rule loader + Zod schema for alert YAML (src/rules/*)
- Mustache renderer + regex filter helpers with triple-brace
  safe-field allow-list (src/render/*)
- scheduler loop + bounded concurrency (src/scheduler/*)
- PocketBase client + alert-state store + S3 backup (src/storage/*)
- Slack webhook target (src/targets/*)
- shared types (src/types/index.ts)
- legacy probes (aimock-wiring, smoke, pin-drift, redirect-decommission,
  deploy-result) kept as authoritative signal shapes; drivers wrap these
Plus load-test + notify-ops-jq scripts + valid/invalid rule test
fixtures.
2026-04-22 11:00:47 -07:00
Jordan Ritter 6faf41b8ab feat(showcase/pocketbase): service (migrations + hooks + Docker)
PocketBase backend for showcase-ops: Dockerfile + entrypoint for the
Railway-hosted instance, JSVM main.pb.js hook for CORS + request
shaping, migration sequence creating status / status_history /
alert_state collections, CORS config, and the recreate_collections
v1/v2 + drop_history_fail_count schema drift corrections.
2026-04-22 11:00:47 -07:00
Jordan Ritter 6c77593f83 refactor(showcase/scripts): extract pure-TS cores for pin-drift + redirect-decommission
Extract drift-comparison logic out of validate-pins.ts into
validate-pins-core.ts (pure module, CLI re-exports + remains thin
orchestrator) and extract the formatter out of
redirect-decommission-report.ts into redirect-decommission-core.ts.
Add vitest coverage for both cores with baseline fixtures so
showcase-ops ProbeDrivers can reuse the same logic without forking.
Drop legacy generate-status.ts — superseded by showcase-ops live
status feed.
2026-04-22 11:00:46 -07:00
Jordan Ritter 7f3fab47b2 feat(showcase/shell-dashboard): live PocketBase status wiring + tests
Replace the static status.json feed with a live PocketBase subscription
(useLiveStatus / useLastTransition hooks + live-status lib + pb client),
add vitest + playwright visual test setup, wire feature-grid + cell
pieces + badges to the live data model. Adds Dockerfile + .dockerignore
for Railway deployment of the dashboard.
2026-04-22 11:00:46 -07:00
Jordan Ritter 9b05ed41b3 feat(showcase/shell-docs): error boundary consolidation + docs components
Drop error-boundary-card in favour of Next.js error.tsx at each route,
refresh docs components (brand-nav, docs-callout, docs-page-view,
docs-steps, docs-tabs, framework-provider/selector/tabs,
property-reference, router-pivot, sidebar-link, snippet), update
docs-render + mdx-registry + reference-items for the new QA shape.
2026-04-22 11:00:46 -07:00
Jordan Ritter af35569d7d chore(showcase/packages): QA markdown parity + integration tooling
Rename hitl.md → hitl-in-chat.md across all 17 showcase packages,
add shared-state-read / shared-state-write / shared-state-streaming /
gen-ui-agent / subagents QA docs where missing, update demos/hitl
README cross-links. Refresh showcase/shell + shell-dojo registry +
demo-content JSON to match new QA shape. Update integration tooling
(audit, create-integration, bundle-demo-content, generate-registry,
validate-parity, capture-previews, manifest lib) + e2e tests to the
new parity contract.
2026-04-22 11:00:46 -07:00
Jordan Ritter 96e29c886b feat(examples/v2): rename interrupts-langraph→interrupts-langgraph + integration cleanup
Fix the long-standing typo across the example directory name + module
identifiers, align imports + package names. Also touches examples/integrations/adk
docker-compose fixtures and examples/e2e agents reference doc.
2026-04-22 10:50:10 -07:00
Jordan Ritter 78a4a6d0a6 chore(repo): root workspace config + top-level showcase docs
Bump pnpm-lock / package.json / pnpm-workspace / lefthook.yml for the
showcase-ops branch, add FRONTEND-STRATEGY / TESTING / QA-COVERAGE /
INTEGRATION-CHECKLIST top-level showcase docs + aimock README, refresh
showcase/.gitignore + showcase/shared/constraints.yaml.
2026-04-22 10:50:09 -07:00
Mike Ryan 81a757adab chore(ent-251): bump @copilotkit/license-verifier to 0.2.0 (#4141)
## Summary

Bumps the internal `@copilotkit/license-verifier` dependency from
`0.0.1-a1` to `0.2.0` in `@copilotkit/runtime` and `@copilotkit/shared`.

The new `license-verifier` release adds a required `telemetry_id` field
to the signed `LicensePayload` — see the intelligence repo ENT-251 PR
for motivation (per-license analytics correlation ID, enables reverse
lookup from inbound Scarf events to the HubSpot Contact that issued the
license).

## Scope

- `packages/runtime/package.json`: bump dep.
- `packages/shared/package.json`: bump dep.
- `.changeset/bump-license-verifier-ent-251.md`: changeset (patch bump
on runtime + shared; propagates to all \`@copilotkit/*\` via fixed:
config).

(closes ENT-251)
2026-04-22 10:26:34 -07:00
Martha Kelly Schumann 9e9fdc9d45 test: LangGraph integration unit tests + dead code audit (#3616)
## Summary

- **Python SDK**: 18 new tests for `LangGraphAGUIAgent` — custom event
handling (`manually_emit_message/tool_call/state`, `copilotkit_exit`),
independent emit filtering, `langgraph_default_merge_state` (copilotkit
namespace with actions + context), unknown event passthrough
- **TypeScript SDK**: 25 new tests for `copilotkitCustomizeConfig` (all
emit flags, `emitAll`, `emitIntermediateState` snake_case conversion,
validation) and `convertActionsToDynamicStructuredTools` (happy path,
`{type:"function"}` wrapper, validation errors)
- **TypeScript Runtime**: 27 new tests for event-source helpers
(`shouldEmitToolCall`, `getCurrentMessageId`,
`getCurrentToolCallChunks`, `getResponseMetadata`, `getCurrentContent` —
both kwargs and Platform layouts)
- **TypeScript Runtime**: 9 new tests expanding
`dispatch-event-filtering.test.ts` with custom event dispatch and
`langGraphDefaultMergeState` (tools from ag-ui, context, deduplication,
missing keys)
- **Dead code annotations**: `LangGraphAgent` class and
`use_function_call=True` branch annotated with `TODO(ran-review)` after
grep confirmed no active callers

## Test plan

- [x] Python SDK: `pytest tests/ -v` — 26 passed (18 new + 8 existing)
- [x] TypeScript SDK: `nx test sdk-js` — 44 passed (25 new + 19
existing)
- [x] TypeScript Runtime: `nx test runtime` — 689 passed (36 new + 653
existing)
- [x] Pre-commit hooks (lint-fix, test-and-check-packages, commitlint)
all passed

https://claude.ai/code/session_01BPMn7zhadhapfyyD8kYeAH
2026-04-22 10:19:12 -07:00
Max Korp 9f37a9f0f0 chore(ent-251): update pnpm override and lockfile for license-verifier 0.2.0
Missed on the first pass — root package.json had a pnpm.overrides pin on
@copilotkit/license-verifier@0.0.1-a1 that forced the lockfile to keep the
old version even after packages/runtime + packages/shared dep bumps.
2026-04-22 10:14:52 -07:00
Max Korp 00fd1dff83 chore(ent-251): bump @copilotkit/license-verifier to 0.2.0
New license verifier release adds a required telemetry_id field to the
signed LicensePayload. Runtime consumes verified payloads unchanged;
shared re-exports the widened type. See the intelligence repo ENT-251
PR for the motivation (per-license analytics correlation ID).
2026-04-22 10:14:01 -07:00
Jordan Ritter e270f9ee3b fix(ci): capture-previews uses devops-bot token to bypass main branch protection (#4159)
## Summary
- `.github/workflows/showcase_capture-previews.yml` generates a
devops-bot (app-id 1108748) token via
`actions/create-github-app-token@v2` and uses it for both
`actions/checkout` and the subsequent `git push`.
- Commit identity switches to `devops-bot[bot]` to match the token.

## Why
Every run since main branch protection landed has been silently failing
on the `git push registry.json` step: `remote: GH013: Repository rule
violations found for refs/heads/main. Changes must be made through a
pull request.` The devops-bot is a bypass actor on the PROTECT_OUR_MAIN
ruleset, so using its token lets the auto-commit land. Mirrors the fix
in `CopilotKit/internal-skills`'s `sync-versions.yml`.

## Test plan
- [ ] actionlint clean
- [ ] Post-merge: next capture-previews run commits to main without
`GH013` error
2026-04-22 10:11:36 -07:00
Jordan Ritter 466cbcebfe style: auto-fix formatting 2026-04-22 10:06:51 -07:00