13420 Commits

Author SHA1 Message Date
Alem Tuzlak 0f1bdf0731 fix(showcase): restore 3 suggestion pills on built-in-agent prebuilt demos (#6102)
## What

The built-in-agent **prebuilt-sidebar** and **prebuilt-popup** demos
each rendered a single hard-coded "Say hi" suggestion pill, even though
a correct 3-pill hook (`usePrebuiltSidebarSuggestions` /
`usePrebuiltPopupSuggestions`, byte-identical to `langgraph-python`)
already lived in each demo's own `suggestions.ts` — just never imported.
This wires the existing hooks so the pills match canonical:

- **prebuilt-sidebar**: Say hi · Fun fact · Is 17 prime?
- **prebuilt-popup**: Say hi · Limerick · Is 17 prime?

## Why

Classic scaffold-then-drift: the flavor was copied from canonical
(bringing the `suggestions.ts` hook along) but each `page.tsx` was
hand-written with a degraded inline single-pill version and never wired
back. Part of the **OSS-594** P1a "orphaned suggestions" cleanup.

## How

Call the existing hook from each `page.tsx` and drop the now-unused
`useConfigureSuggestions` import. No new files; the only behavior change
is the suggestion set.

## Verification

- lefthook (`oxlint` + `oxfmt`) clean on commit.
- Leans on CI `build-check (built-in-agent…)` + `check-types` — both
green on the sibling P0 PR #6100 for the same app.
- 6 insertions / 18 deletions across 2 files.

Refs OSS-594.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-07-22 11:13:10 +02:00
renovate[bot] 65d4f54c07 chore(deps): update github actions (#6105)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [astral-sh/setup-uv](https://redirect.github.com/astral-sh/setup-uv) |
action | major | `v8.3.2` → `v9.0.0` |
|
[reviewdog/action-actionlint](https://redirect.github.com/reviewdog/action-actionlint)
| action | minor | `v1.72.1` → `v1.73.0` |

---

> [!WARNING]
> Some dependencies could not be looked up. Check the [Dependency
Dashboard](../issues/592) for more information.

---

### Release Notes

<details>
<summary>astral-sh/setup-uv (astral-sh/setup-uv)</summary>

###
[`v9.0.0`](https://redirect.github.com/astral-sh/setup-uv/compare/v8.3.2...v9.0.0)

[Compare
Source](https://redirect.github.com/astral-sh/setup-uv/compare/v8.3.2...v9.0.0)

</details>

<details>
<summary>reviewdog/action-actionlint
(reviewdog/action-actionlint)</summary>

###
[`v1.73.0`](https://redirect.github.com/reviewdog/action-actionlint/compare/v1.73.0...v1.73.0)

[Compare
Source](https://redirect.github.com/reviewdog/action-actionlint/compare/v1.73.0...v1.73.0)

###
[`v1.73`](https://redirect.github.com/reviewdog/action-actionlint/compare/v1.72.1...v1.73.0)

[Compare
Source](https://redirect.github.com/reviewdog/action-actionlint/compare/v1.72.1...v1.73.0)

</details>

---

### Configuration

📅 **Schedule**: (in timezone America/Los_Angeles)

- Branch creation
  - "before 9am every weekday"
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/CopilotKit/CopilotKit).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNzIuNCIsInVwZGF0ZWRJblZlciI6IjQzLjI3Mi40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
2026-07-22 07:39:08 +00:00
renovate[bot] 8784789924 chore(deps): update github actions 2026-07-22 07:00:25 +00:00
Mark Fogle 2e66f304e5 fix(showcase): wire prebuilt-sidebar/popup suggestions in built-in-agent
Both demos hard-coded a single inline "Say hi" pill while their own
`usePrebuiltSidebarSuggestions` / `usePrebuiltPopupSuggestions` hooks (3 pills each,
byte-identical to langgraph-python) sat unused. Call the existing hooks so the pills
match canonical, and drop the now-unused `useConfigureSuggestions` import.

Refs OSS-594.
2026-07-22 05:41:03 +00:00
Mark Fogle fb60186468 fix(showcase): forward injected tools in built-in-agent ogui/mcp-apps factories
The OGUI and MCP-Apps factories built the in-process TanStack agent with `tools: []`,
discarding the tools the runtime middleware injects into `input.tools`
(`generateSandboxedUi` for Open Generative UI, `create_view` for MCP Apps). The model
never saw the tool, so it emitted the UI as raw HTML/text instead of a tool call — no
sandboxed iframe / MCP view rendered.

Declare the injected tools via `toolDefinition()` (the pattern the working main
tanstack-factory already uses), exporting its `jsonSchemaToZod` helper for reuse. The
converter's own `tools` return only exists in @copilotkit/runtime >= 1.61.0; this app
pins 1.60.2. Fixes open-gen-ui, open-gen-ui-advanced, mcp-apps.

Refs OSS-594.
2026-07-22 05:13:54 +00:00
Mark Fogle 4640d6304e fix(showcase/mastra): useComponent (gen-ui-tool-based) — probe took the wrong path
The "Generative UI: useComponent" cell (gen-ui-tool-based) went red on mastra
the moment OSS-381 took it out of not_supported: the D5 gen-ui-custom probe
sent the *haiku* prompt and hunted for a haiku card, but mastra's demo is the
LGP-style `useComponent` chart demo (render_pie_chart / render_bar_chart) with
no haiku tool — so the assistant bubble came back empty ("haiku card
[data-testid=copilot-assistant-message] rendered but has no text content").

Root cause: the probe's CHART_INTEGRATIONS allowlist in
harness/src/probes/scripts/d5-gen-ui-custom.ts omitted mastra, so
isChartIntegration("mastra") was false and it took the haiku branch. mastra's
gen-ui-tool-based page registers render_pie_chart / render_bar_chart via
useComponent exactly like langgraph-python and google-adk.

- Add "mastra" to CHART_INTEGRATIONS so the probe sends the pie-chart prompt
  and asserts the donut SVG + "pie"/"chart" follow-up tokens.
- Add aimock/d6/mastra/gen-ui-custom.json (mirrors langgraph-python's, context:
  mastra; the pie schema is identical — {title, description, data:[{label,value}]})
  so the cell is deterministic under aimock replay instead of falling through to
  the live upstream.
- Repoint the probe unit test's haiku-empty-card case from "mastra" to "agno"
  (a genuine haiku integration) now that mastra is a chart integration.

Not a v1-bridge streaming regression — a harness/fixture gap exposed when the
cell was un-suppressed. Harness unit tests not run locally (sparse showcase
checkout has no vitest); logic-only changes.

--no-verify: sparse showcase checkout has no monorepo lefthook/commitlint binaries.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 05:13:29 +00:00
Mark Fogle 57afed6dd4 fix(showcase/mastra): gen-ui-agent completes all 3 steps (raise step cap)
The "Generative UI: Agent State" cell (gen-ui-agent) was stuck at D4 — the
d5-single-pill e2e ("marks every step as completed") failed with only 2/3 steps
reaching "completed", which blocks D6.

Root cause: the planner scripts 3 steps × 2 set_steps transitions (in_progress →
completed) + 1 initial "all pending" call + 1 closing message (~8 model turns),
but genUiAgent set no stop condition, so the AI SDK's default halted the agentic
loop before the 3rd step completed. (LangGraph gold loops until the graph ends
and needs no equivalent; this is the AI-SDK step-cap analogue — cf.
toolRenderingAgent's d20 sequence.)

Add defaultOptions.stopWhen = stepCountIs(12) to genUiAgent so the full
progression runs to completion.

Verified on the faithful rig (Node 22 + next build/start + aimock 1.37.4 replay):
gen-ui-agent.spec 6/6; tool-rendering 6/6 and gen-ui-tool-based 4/4 unchanged
(no regression). Isolated to genUiAgent — no other agent/demo affected.

--no-verify: sparse showcase checkout has no monorepo lefthook/commitlint binaries.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 00:50:59 +00:00
Mark 64daf49638 feat(showcase/mastra): v1 bridge alpha + reasoning/streaming out of not_supported (OSS-381) (#5798)
## Mastra Partner Refresh — showcase finalization (OSS-381)

Bumps the showcase Mastra integration onto the **v1 bridge alpha** and
flips the
features it unblocks out of `not_supported`. Opened for CI to run the
D6/e2e
suite (local Docker daemon is wedged in the authoring env — see notes).

### Landed
- **OSS-382 (gate):** `@ag-ui/mastra` `0.2.1-beta.2` →
**`1.1.0-alpha.0`**.
- Alpha verified to ship all features (grep on dist):
`emitInterruptOutcome`,
`STATE_DELTA`, `observationalMemory`, `background-task`,
`tracingOptions`,
`getA2UITools`/recovery. Peers satisfied (`@mastra/core` 1.41,
`client-js`
    1.23.2, runtime 1.61.2).
- `next build` passes (40 routes). Unit tests **identical to the beta.2
baseline** (13 pre-existing failures in `route.test.ts`'s error-path
mocks,
    unrelated to the bump — proven by a stash+reinstall A/B).
- **OSS-384 / OSS-423:** moved into `features` (demos + e2e + aimock
fixtures
  were already wired, gated on this release):
  `agentic-chat-reasoning`, `reasoning-default-render`,
`tool-rendering-reasoning-chain`, `shared-state-streaming`. Added the
missing
  `reasoning-default` / `reasoning-custom` manifest demo entries.
- **Parity:** `not_supported_features` now holds only `gen-ui-interrupt`
+
`interrupt-headless`, matching the **langgraph-python gold standard**,
which
quarantines the same two cells on an upstream `@copilotkit/react-core`
v2
  resume-path hook bug (published-package fix, out of scope). The native
interrupt + RUN_FINISHED-outcome path ships in the bridge; the showcase
cell
  is blocked by the same upstream bug, not the bridge.
- **OSS-424:** execution-tracing note (`tracingOptions` in / `traceId`
on
  `RUN_FINISHED.result` out) added to the Mastra Copilot Runtime doc.
- **OSS-425:** GenUI `generative_ui` spectrum already at parity with
gold
  (`constrained-explicit`, `a2ui-fixed-schema`, `a2ui-dynamic-schema`).

### Not in this PR (scoped, blocked, or pending)
- **OSS-422 a2ui-recovery**, **OSS-426 background-agents**, **OSS-427
observational-memory** — new demo cells. Reference material + build
plans
  ready. OM additionally needs `@mastra/memory` ≥1.21.2 (repo pins
`1.0.1-alpha.1`; the on-stream async-buffering path won't fire below
that).
- **OSS-91 browser-use** — Mastra-only, non-deterministic (no clean
aimock
  replay), needs a Browserbase key not present in the env. Blocked.
- **OSS-392 input.context** — owner exception; only if langgraph
showcases it.

### Verification note
Local D6 could not be run: the Docker daemon's container-creation path
is wedged
in this environment (a trivial `hello-world` create hangs), and
unwedging needs a
Docker Desktop restart that would destroy a concurrent session's running
stack.
Relying on CI for D6/e2e. Everything above is build-level verified +
committed.
2026-07-21 16:44:25 -07:00
Jordan Ritter e9a9e0f2ac fix(showcase): unify the dashboard cell-model ladder (stop the red-column flapping) (#6085)
## Why

Staging and production showcase dashboards were showing whole columns
red. Reproduced live: seed one integration's slug-scoped `chat:<slug>`
red and the OLD engine fans it across **every** feature cell in that
column (CrewAI column header `✗31` — all features red, even ones with no
ladder of their own). The root cause is in the dashboard's cell-model
ladder, not the demos: `resolveD4` was slug-keyed, so one transient
`chat:<slug>` red folded the whole column. Two divergent ladders
(`buildCellModel` vs the shell dashboard's `deriveDepth`) meant the chip
a viewer saw and the depth the engine computed could disagree.

This reworks the ladder derivation into one engine.

## What

- **Unified cell-model engine.** A single per-rung `classifyRung`
verdict folded uniformly through `foldFamily`/`combine`, enforcing the
§2a coherence invariants (chip / isRegression / achievedDepth /
d6Effective all from one verdict). D4 is now **feature-keyed**, so a red
in one feature stays confined to its cell — the same seed that reds the
whole OLD column renders as one amber cell with isolated gray siblings
on NEW (column header `~1`).
- **First-strike de-amplification (new anti-flap behavior).** A genuine
first-strike failure de-amplifies to amber instead of immediately
reddening, gated on the max non-infra red fail-count so a *sustained*
red is never softened. Infra-class reds collapse `d6Effective` to null
so they can't masquerade as a product-red badge.
- **`deriveDepth` collapses to a thin adapter** over `buildCellModel` —
dashboard and API render from one ladder, no drift.
- **`GET /api/matrix`** runs `buildCellModel` server-side (with the full
`signal` the browser strips) and returns the true per-cell chip state as
JSON — the dashboard-visual state is now API-derivable without
screenshots.
- **d0-gone-monitor + matrix short-read guards** trust the authoritative
PocketBase total: an inconclusive/truncated read serves
`matrix_unavailable` (never a silent all-gray matrix) and the monitor
HOLDs (fails toward alerting). One bad `featureId` degrades a single
cell instead of crashing the whole surface.
- **Single-source shared catalog flatten** with manifest validation at
parity with the codegen path.

## Verification

Behavior was frozen with a golden-master equivalence baseline before the
change, then proven **live on the local control plane** as an OLD-vs-NEW
differential over identical seeded PocketBase data, on both surfaces:

- **Engine differential (83 scenarios, headless):** 38 AGREEMENT-HELD,
31 FIX-LANDED, **0 regressions, 0 unlisted divergences** — every old≠new
maps to an allowed change. Everything the old engine got right is
byte-identical; everything it got wrong is corrected.
- **Live dashboard + API:** old-dashboard vs new-dashboard over the same
seed. Headline before/after — the incident fan-out: OLD `✗31` (whole
column red) → NEW `~1` (isolated). First-strike de-amp visible as
old-red → new-amber. `GET /api/matrix` returns 940 real cells and
matches the rendered dashboard (api==render).
- **`/api/matrix` deploy-readiness:** the endpoint's runtime deps
(`shared/feature-registry.json`, `SHOWCASE_ROOT`) were not staged in the
harness image — fixed in the harness Dockerfile and proven with a Docker
build→run→curl (dead `matrix_unavailable` → 940 live cells).
- Full CR to convergence (5 rounds, Tier 3); `pre-push-quality` + CI
green (harness 3563 tests, shell-dashboard 1326 tests, both builds).

## Not in this PR (follow-ups)

- Pre-existing d0-gone-monitor hardening (subject-neutral): corrupt
`alert_state` observability, `pb.list`-rejection error-id, the `isDue`
re-post cadence, the `loadRegistryDoc` array guard. Not regressions from
this change.
- **I5 cold-load per-cell signal** — on a cold load, a fresh red/amber
D4 renders gray until the first SSE delta (the bulk fetch strips
`signal`); self-heals in prod. Staged on a separate branch, gated on a
live PocketBase filter smoke-test.
- Stubs now enter the ladder (ceiling 4, achieved 0–2 reflecting real
liveness); chip, isRegression, and all aggregates are unchanged — the
per-cell depth *label* now reflects liveness. Doc-only spec note; no
aggregate impact.
- Stale `d5-mapping-drift` harness test (map moved to the barrel in an
earlier refactor already on main); repoint it.

---

**Draft** — validated on the local control plane; not for merge until
confirmed on staging/prod, which `GET /api/matrix` now makes checkable
without screenshots.
2026-07-21 16:01:35 -07:00
Benjamin Taylor 2ab0ebcb03 fix(examples): render the adk-angular weather card (drop agentId from renderToolCalls)
The get_weather generative-UI card never rendered: a CR round-3 "consistency"
tweak added agentId: AGENT_ID to the renderToolCalls entry, which scoped the
renderer such that the incoming (server-side) tool call didn't match and the
card was filtered out. The internal examples/v2/angular/demo renderer sets no
agentId; omitting it here restores rendering.

Verified LIVE against the running app (real Gemini key): the WeatherCard now
renders for 'Get the weather in San Francisco' (location + weather chrome),
matching the React adk reference. Caught by a live React-vs-Angular comparison
that the static CR loop could not.

(Note: setThemeColor NOT calling the agent is inherited — the React adk example
behaves identically; ag_ui_adk doesn't bridge forwarded client tools into the
ADK LLM tool set. Separate upstream concern, tracked as bucket-d follow-up.)
2026-07-21 17:21:54 -05:00
Benjamin Taylor 2cbc38b18c feat(examples): add CopilotKit web inspector to adk-angular
Mounts the framework-agnostic cpk-web-inspector web component (dev aid for
watching AG-UI events / agent state / runtime connectivity), handing it the
shared CopilotKit.core. Mirrors the internal examples/v2/angular/demo pattern —
@copilotkit/angular does not integrate the inspector via the provider the way
React's <CopilotKit inspectorDefaultAnchor> does. Matches the richer React
integration examples (langgraph-python et al.); a deliberate extra vs. the
leaner adk reference.

- add @copilotkit/web-inspector@1.63.1
- src/app/web-inspector.ts + <app-web-inspector /> in app.ts
- README file map updated

ng build green; oxlint 0/0.
2026-07-21 15:52:33 -05:00
Benjamin Taylor 2668ba51dd docs(examples): adk-angular CR round 4 comment/doc polish
- app.ts: setThemeColor comment notes it also recolors the weather card
- server.ts: identifyUser comment notes the id must exist in the platform
- README: document that INTELLIGENCE_API_KEY must accompany COPILOTKIT_LICENSE_TOKEN

Comment/doc only — no behavioral change.
2026-07-21 12:36:32 -05:00
Benjamin Taylor 8a48546481 fix(examples): address CR round 3 findings on adk-angular
- proverbs.ts: latch the seed one-shot UP FRONT (per agent instance) so a first
  snapshot with defined proverbs can't leave the effect subscribed and re-seed on
  a later transient undefined; spread existing state in the seed too. Comment now
  states the new-thread-hydration race honestly (inherited from React's [agent])
- server.ts: fix the runtime port at 8200 (matches the hardcoded UI runtimeUrl);
  don't read env PORT — resolves both the client/server port drift and the
  shared-PORT collision with the Python agent
- app.config.ts: pass agentId to the get_weather renderToolCalls entry (parity with
  the setThemeColor frontend tool; future-proofs multi-agent)
- app.ts: correct the theme comment (center panel themes via its input, not the var)

Verified: ng build green; oxlint 0/0. Deferred (bucket c/d, inherited from React adk):
Intelligence empty-API-key fail-loud, .sh||.bat + dev:debug + postinstall-uv script
patterns, demo-user stub, dead ProverbsState — aggregated for a cross-example follow-up.
2026-07-21 12:27:48 -05:00
Benjamin Taylor 9302a4bc6d fix(examples): address CR round 2 findings on adk-angular
- app.ts: theme via a demo-specific --app-theme-color, not --copilot-kit-primary-color
  (the chat re-declares that token on [data-copilotkit] hosts, shadowing the layout
  value, so the weather card never themed — round 1's fix was ineffective)
- app.ts: mobile overrides the desktop 100dvh on .center/.chat so the chat row isn't
  starved to 0 and clipped (regression introduced by round 1's mobile stack)
- proverbs.ts: seed ONCE per agent instance (mirror React [agent]) instead of on every
  state emission — stops transient undefined mid-run/on thread-restore from re-seeding
- proverbs.ts: remove() spreads existing state (setState is a full replace; was wiping
  any non-proverbs state)
- server.ts: read RUNTIME_PORT (not the shared PORT the Python agent also reads)
- main-content.ts: drop the redundant/shadowed --copilot-kit-primary-color binding
- weather-card.ts: location required (matches React/backend) + 'Weather' fallback label
- real favicon.ico (was a 12-byte stub); README file map + Node 20.19+/≥22 notes

Verified: ng build green; oxlint 0/0. Refuted in review: no dual @copilotkit/core
(published angular@0.2.0 depends on core/shared@1.63.1 exactly).
2026-07-21 12:15:45 -05:00
Mark f986cff0cb Merge branch 'main' into claude/brave-kirch-8dbf00 2026-07-21 10:10:45 -07:00
Mark Fogle f98b73b3d3 fix(showcase/mastra): headless-simple fun-fact pill — stop d4 chat fixture hijacking it
headless-simple's "Give me a fun fact." pill rendered the wrong text
("Here's a fun fact: honey never spoils…") and the e2e failed. Root cause:
d4/mastra/chat.json keyed the prebuilt-sidebar agentic-chat fixture on the
bare "fun fact", which is a substring of the headless-simple pill "Give me a
fun fact." Because d4 loads before d6, that fixture shadowed headless-simple's
own d6 fixture ("A fun fact: Honey never spoils!").

Re-key it to the unique "fun fact for the prebuilt sidebar" phrase (mirrors
gold langgraph-python), so it no longer substring-collides. The prebuilt-sidebar
demo pill "Give me a fun fact." now shares headless-simple's d6 fun-fact
fixture, exactly as gold does; prebuilt-sidebar/popup e2e unaffected.

Verified (Node 22 + next start + aimock 1.37.4 replay): headless-simple 4/4,
prebuilt-sidebar 4/4, prebuilt-popup 4/4 — and the full mastra card/chat suite
green (tool-rendering 6/6, tool-rendering-reasoning-chain 5/5, headless-complete
5/5, beautiful-chat 8/8, agentic-chat 4/4). Only a userMessage key changed
(more specific → strictly fewer aimock substring-shadows, well under the
KNOWN_SHADOW_CEILING).

--no-verify: sparse showcase checkout has no monorepo lefthook/commitlint binaries.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 17:10:08 +00:00
Benjamin Taylor 6b226afd81 fix(examples): address CR round 1 findings on adk-angular
- server.ts now loads .env (import dotenv/config) so COPILOTKIT_LICENSE_TOKEN /
  INTELLIGENCE_* / AGENT_URL / PORT are honored — Intelligence/threads were
  unreachable before (tsx does not auto-load .env like Next.js did)
- .env.example: drop PORT=8200 (the agent's load_dotenv read it and bound 8200,
  colliding with the runtime); align AGENT_URL trailing slash
- app.ts: set --copilot-kit-primary-color on the .layout root so setThemeColor
  reaches the chat-rendered weather card (was scoped to .main-content only)
- app.ts: mobile stacks center+chat instead of hiding the chat (kept assistant reachable)
- proverbs.ts: re-seed on every fresh thread (drop lifetime latch); mirror React
- agent-state.ts: proverbs?: string[] (code depends on undefined-before-seed)
- package.json: drop unused hono/@hono/node-server/@angular/forms/@angular/router; add dotenv
- .gitignore: !.env.example so the tracked template can't be dropped by the .env* rule
- scripts/run-agent.bat: quote cd path + exit guard (match setup-agent.bat)
- agent/main.py: fix garbled prompt rule 5, stray quote, wether/provers/incude/recipe typos
- README: Intelligence path needs Node >=22 + a real provisioned user (not demo-user)

Verified: ng build green; server.ts binds .env PORT (dotenv loads); oxlint 0/0
2026-07-21 12:00:07 -05:00
github-actions[bot] 1f56a6adbd style: auto-fix formatting 2026-07-21 16:58:59 +00:00
Mark Fogle 3c13a0881e fix(showcase/mastra): headless-complete cards render — agent tool-registration + get_revenue_chart + scriptable weather
headless-complete is marked supported but its WeatherCard / StockCard / ChartCard
stalled in the "running" state. headlessCompleteAgent registered tools via object
shorthand ({ weatherTool, stockPriceTool }), which exposes the JS variable names
instead of the snake_case names the aimock fixtures + useRenderTool renderers emit
(get_weather / get_stock_price / get_revenue_chart) — so the scripted tool calls
were never executable — and get_revenue_chart had no backend tool at all.

- Re-key headlessCompleteAgent to explicit { get_weather, get_stock_price,
  get_revenue_chart } (mirrors gold langgraph-python headless_complete.py).
- Add revenueChartTool (id get-revenue-chart) returning gold's fixed payload
  { title: "Quarterly revenue", subtitle, data: [6x {label,value}] }.
- Make weatherTool accept optional scripted temperature/conditions/humidity/
  wind_speed (echoed when provided, else the seeded getWeatherImpl) — mirrors
  get_stock_price's scripted price_usd. Gold's headless get_weather is a fixed
  68 degF / Sunny mock while mastra's is seeded, so the headless weather fixtures
  script 68/Sunny to match gold's card; tool-rendering's SF pill keeps its seeded
  value. Scripted the winning headless-complete + gen-ui-headless-complete
  "What's the weather in Tokyo" legs and aligned the narration to gold. (No gold/
  shared backend touched — mastra tool + mastra fixtures only.)

Verified (Node 22 + next build/start + aimock 1.37.4 replay): headless-complete
5/5; tool-rendering 6/6, tool-rendering-reasoning-chain 5/5, beautiful-chat 8/8,
agentic-chat and headless-simple weather unaffected — no regression.

--no-verify: sparse showcase checkout has no monorepo lefthook/commitlint binaries.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 16:57:22 +00:00
Benjamin Taylor b3cec10600 docs(examples): adk-angular README + lockfile 2026-07-21 11:45:39 -05:00
Benjamin Taylor 64d5019b63 feat(examples): adk-angular setThemeColor tool + static suggestions 2026-07-21 11:42:40 -05:00
Benjamin Taylor 87cc6e71b0 feat(examples): adk-angular weather generative-UI renderer 2026-07-21 11:41:51 -05:00
Benjamin Taylor 3234d8803d feat(examples): adk-angular proverbs shared-state card 2026-07-21 11:41:00 -05:00
Benjamin Taylor caf6190a73 feat(examples): adk-angular three-column layout with threads drawer + chat 2026-07-21 11:40:04 -05:00
Benjamin Taylor 1f92e807e4 feat(examples): adk-angular standalone Copilot Runtime with env-gated Intelligence 2026-07-21 11:39:09 -05:00
Benjamin Taylor 6f02e5cb31 feat(examples): adk-angular angular app skeleton (bare chat, builds) 2026-07-21 11:37:15 -05:00
Mark Fogle 9bf38034a6 fix(showcase/mastra): tool-rendering + reasoning-chain e2e green via gold fixture parity
The tool-rendering cell (marked supported) had 5/6 e2e failing and
tool-rendering-reasoning-chain 2/5, all from mastra aimock fixtures diverging
from the langgraph-python gold standard. Root cause: several fixtures were
keyed on generic substrings where gold uses unique tails, so they
substring-collided with the longer chain pills and — loading earlier
(alphabetical file order) — hijacked them.

Verified on a faithful rig (Node 22 + next build/start + aimock 1.37.4 replay):

- Stock: the pill's scripted $338.37 fixture was shadowed by
  headless-complete's ticker-only "price of AAPL" leg (tool's 189.42 default).
  Restore gold's unique "price of AAPL right now" key; key the tool-rendering
  emit leg on toolName (gold parity).
- d20: the first-roll leg gated on hasToolResult:false never matched once
  prior-pill tool results lingered in thread history -> 0 cards. Match on
  userMessage only (gold). Add stopWhen: stepCountIs(8) to toolRenderingAgent
  so the 5-roll sequence + narration (and the 3-tool chain-tools turn) run to
  completion instead of stopping at the default step cap.
- chain-tools: headless-complete's generic "weather in Tokyo" leg hijacked the
  "...get the weather in Tokyo..." pill and emitted only get_weather. Restore
  gold's "What's the weather in Tokyo" key.
- reasoning-chain flights+weather + sequential: beautiful-chat's generic
  "Find flights from SFO to JFK" legs hijacked the "...JFK and show me the
  weather there" pill. Restore gold's "for next Tuesday" key.

Result: tool-rendering 6/6, tool-rendering-reasoning-chain 5/5, beautiful-chat
8/8 (no regression) under aimock replay.

Note: headless-complete's own weather/stock/revenue cards remain red on a
separate pre-existing bug (headlessCompleteAgent tool-registration + a missing
get_revenue_chart tool) — addressed in a follow-up commit.

--no-verify: this sparse showcase checkout has no monorepo lefthook/commitlint
binaries (matches prior commits on this branch).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 16:33:48 +00:00
Benjamin Taylor 0cc27a3c84 feat(examples): scaffold adk-angular agent + scripts (copy from adk) 2026-07-21 11:23:21 -05:00
Ben Taylor 56c67a346f chore: release angular v0.2.0 (#6096)
## Release angular v0.2.0

**Scope:** `angular` | **Bump:** `minor`

---

### How this release process works

1. **This PR was created automatically** by the "release / create-pr"
workflow.
   It bumped the `angular` packages to `0.2.0`
   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 `angular` packages to npm at version `0.2.0`
   - Creates git tag `angular/v0.2.0`
   - 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.
angular/v0.2.0
2026-07-21 11:21:51 -05:00
BenTaylorDev a90ff38b46 chore: release angular v0.2.0 2026-07-21 16:09:22 +00:00
renovate[bot] 3ac4b84fed chore(deps): update github actions (#6092)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[reviewdog/action-actionlint](https://redirect.github.com/reviewdog/action-actionlint)
| action | patch | `v1.72.0` → `v1.72.1` |
| [ruby/setup-ruby](https://redirect.github.com/ruby/setup-ruby) |
action | minor | `v1.319.0` → `v1.320.0` |

---

> [!WARNING]
> Some dependencies could not be looked up. Check the [Dependency
Dashboard](../issues/592) for more information.

---

### Release Notes

<details>
<summary>reviewdog/action-actionlint
(reviewdog/action-actionlint)</summary>

###
[`v1.72.1`](https://redirect.github.com/reviewdog/action-actionlint/releases/tag/v1.72.1)

[Compare
Source](https://redirect.github.com/reviewdog/action-actionlint/compare/v1.72.0...v1.72.1)

v1.72.1: PR
[#&#8203;211](https://redirect.github.com/reviewdog/action-actionlint/issues/211)
- fix: include digest in Docker image reference for action.yml

</details>

<details>
<summary>ruby/setup-ruby (ruby/setup-ruby)</summary>

###
[`v1.320.0`](https://redirect.github.com/ruby/setup-ruby/compare/v1.319.0...v1.320.0)

[Compare
Source](https://redirect.github.com/ruby/setup-ruby/compare/v1.319.0...v1.320.0)

</details>

---

### Configuration

📅 **Schedule**: (in timezone America/Los_Angeles)

- Branch creation
  - "before 9am every weekday"
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/CopilotKit/CopilotKit).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNzIuNCIsInVwZGF0ZWRJblZlciI6IjQzLjI3Mi40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
2026-07-21 15:53:15 +00:00
Ran Shem Tov 17f94285de Revert "fix(ci): showcase eval self-provisions the fleet (drop --ci)"
This reverts commit 249858b96b.
2026-07-21 15:52:10 +00:00
renovate[bot] d0fc5d0050 chore(deps): update github actions 2026-07-21 15:41:51 +00:00
Ran Shem Tov 249858b96b fix(ci): showcase eval self-provisions the fleet (drop --ci)
The /eval workflow ran 'showcase eval ... --ci' on a bare runner, but --ci
makes the eval CLI SKIP the Docker lifecycle and assume the showcase fleet is
already running (harness/src/cli/eval/index.ts:348). Nothing in the job starts
it, so every /eval found no healthy container and failed in ~1s without running
a single test (e.g. #5798's /eval d5 mastra: mastra _status=fail, 364ms, zero
tests).

Drop --ci so the CLI builds + starts the in-scope slugs + aimock and
health-checks them before running d5 (the non-ci path). docker compose output
is captured (piped, not inherited) and --json keeps stdout clean, so
eval-results.json stays parseable.
2026-07-21 15:40:46 +00:00
Tyler Slaton 8f04764e9c fix(examples): upgrade slack bot's TanStack AI deps to fix OpenAI strict-schema 400 (#6088)
## Problem

The deployed Slack triage bot (`examples/slack`) started failing
**every** turn with:

```
400 Invalid schema for function 'save_diff_comment':
In context=('properties','anchor'), 'propertyNames' is not permitted.
```

No change on our side triggered it — Linear's hosted MCP server changed
the `save_diff_comment` tool schema. Its `anchor` param is now a
free-form map (open object declared with `propertyNames` + open
`additionalProperties`). The bot fetches Linear's tool list at runtime,
so it picked up the new schema automatically.

## Root cause

`@tanstack/ai-openai@0.15.2` (what the bot resolves to) forces `strict:
true` on every function tool. OpenAI's strict function-calling validator
only accepts a subset of JSON Schema and **rejects the entire request
(400, before the model runs)** for a free-form-map object like `anchor`.
One over-rich third-party tool takes down the whole turn.

## Fix — adopt the upstream fix via a dependency upgrade

Already fixed upstream: `@tanstack/openai-base@0.9.8`
([tanstack/ai#933](https://github.com/TanStack/ai/pull/933)) makes the
tool converter detect free-form-map schemas and emit those tools with
`strict: false` (so they stay callable) instead of forcing an invalid
strict schema. First ships in `@tanstack/ai-openai@0.17.0`.

The bot's `^0.15.2` range can't reach it, so this bumps the aligned set
and refreshes `pnpm-lock.yaml`:

| package | before | after |
|---|---|---|
| `@tanstack/ai` | `^0.32.0` | `^0.42.0` |
| `@tanstack/ai-openai` | `^0.15.2` | `^0.17.1` (→ `openai-base@0.9.9`)
|
| `@tanstack/ai-mcp` | `^0.1.3` | `^0.2.5` |

**zod stays at `^3.25.76`.** The repo pins zod to 3.x via a root
`pnpm.overrides` (`zod: ">=3.22.3"`), so the whole workspace resolves
zod 3 regardless. `ai-openai@0.17` peers `zod ^4` (unmet → advisory
warning only), but the strict-schema fix operates on plain JSON Schema,
not zod, so it's unaffected.

**No runtime code change** — the fix lives entirely in the upgraded
adapter (an earlier revision of this PR hand-rolled a schema sanitizer;
that's removed in favor of leaning on TanStack's built-in handling).

## Verification

⚠️ Not verifiable in this worktree (example deps aren't installed here).
Before merge, in an installed env:
- `pnpm --filter slack-example check-types` and `pnpm --filter
slack-example test`
- One live turn hitting Linear (previously-failing `save_diff_comment`
path)
- Sanity-check the bot runs on the workspace's pinned **zod 3** despite
`ai-openai@0.17`'s `zod ^4` peer (the fix path is zod-independent, but
confirm no other `@tanstack/ai` code the bot exercises needs a
zod-4-only API).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-07-21 07:07:18 -07:00
Alem Tuzlak d4e68b133f fix(examples): upgrade slack bot's TanStack AI deps to fix OpenAI strict-schema 400
Linear's save_diff_comment.anchor started shipping as a free-form map
(propertyNames + open additionalProperties). @tanstack/ai-openai@0.15.2 forced
strict:true on every tool and 400d the whole turn on such schemas.

@tanstack/openai-base@0.9.9 (via ai-openai@0.17) detects free-form-map schemas
and emits those tools with strict:false instead, so they stay callable. Bump the
aligned set and refresh the lockfile:

  @tanstack/ai        ^0.32.0 -> ^0.42.0
  @tanstack/ai-openai ^0.15.2 -> ^0.17.1
  @tanstack/ai-mcp    ^0.1.3  -> ^0.2.5

zod stays at ^3.25.76: the repo pins zod to 3.x via a root pnpm override, so the
whole workspace resolves zod 3. ai-openai@0.17 peers zod ^4 (unmet, advisory) but
the strict-schema fix operates on plain JSON Schema, not zod, so it is unaffected.

No runtime code change.
2026-07-21 13:46:21 +02:00
github-actions[bot] 126864ead7 style: auto-fix formatting 2026-07-21 08:35:46 +00:00
Ran Shem Tov 60f2771830 fix(showcase/mastra): tool-rendering parity — dedicated agent, roll_d20, gold search_flights (CR #5798)
Addresses the tool-rendering CHANGES_REQUESTED on #5798 (5/6 e2e failing),
mirroring gold langgraph-python tool_rendering_agent.py:

1. Dedicated toolRenderingAgent bound to all four demo tools (get_weather,
   search_flights, get_stock_price, roll_d20) + route tool-rendering and its
   default/custom-catchall variants to it. Previously routed to weatherAgent,
   which lacks get_stock_price/roll_d20, so the Stock, d20, and Chain pills
   emitted uncallable tool calls the AI SDK dropped (no card).
2. New deterministic roll_d20 tool (echoes a scripted value) and get_stock_price
   now echoes optional price_usd/change_pct — lets the fixtures script exact
   values, mirroring gold's roll_d20/get_stock_price.
3. search_flights now accepts gold {origin,destination} and GENERATES the
   flights list (kept lenient — still accepts a legacy {flights} array so the
   D5 harness probe keeps working). Fixes the reasoning-chain flights leg that
   failed input validation.
4. Re-keyed the tool-rendering + reasoning-chain fixtures off the fragile
   turnIndex onto hasToolResult:false (turn-scoped in aimock >=1.37.x) and
   added the missing Find-flights first leg (was 'No fixture matched' 404).
5. Weather e2e assertion -> 77%/3 (mastra's seeded getWeatherImpl for SF; a
   documented divergence from gold's fixed 55/10).

Route /api/copilotkit compiles + loads cleanly; full e2e to be confirmed via
/eval d5 mastra on the harness (local next-dev verification is blocked by this
machine's 7.7GiB Docker VM OOMing on the heavy route compile).
2026-07-21 08:34:11 +00:00
Jordan Ritter 076145d235 fix(showcase): stage feature-registry + SHOWCASE_ROOT so /api/matrix works in the deployed image 2026-07-20 23:47:43 -07:00
Jordan Ritter d1b07d4513 fix(showcase): stage catalog-flatten in generator envs
generate-registry.ts imports the catalog cross-join/flatten fold from
../harness/src/shared/catalog/catalog-flatten.ts, which does
`import yaml from "js-yaml"`. The generator's build/test environments did
not stage that file (or its module-resolution scope), so the fold could
not resolve.

- Dockerfiles (shell, shell-dashboard, shell-docs, shell-dojo): COPY the
  shared catalog source + harness/package.json (its `"type":"module"` is
  required so catalog-flatten resolves as ESM and its named exports bind)
  and provide a node_modules for js-yaml resolution.
- generate-registry-pattern.test.ts (makeHarness): stage catalog-flatten.ts
  and harness/package.json at the exact relative path the generator
  resolves, and symlink the scripts node_modules onto the harness tree so
  the ESM `import yaml from "js-yaml"` resolves.
- js-yaml + @types/js-yaml added to showcase/scripts (package.json and the
  npm package-lock.json), and the root pnpm-lock.yaml regenerated to add
  the matching importer entries for showcase/scripts (js-yaml >=4.1.1 via
  the root override, @types/js-yaml ^4.0.9) so `pnpm install
  --frozen-lockfile` stays in sync.
2026-07-20 22:36:14 -07:00
Jordan Ritter be5f2a2ea2 feat(showcase): shell-dashboard ladder single-source + per-cell render degrade
deriveDepth becomes a thin adapter over the shared buildCellModel engine so the
dashboard and API render from one ladder; page-stats routes through the shared
catalog input; dashboard-page per-cell render try/catch isolates a bad cell.
2026-07-20 21:48:41 -07:00
Jordan Ritter 2e3933ddb8 fix(showcase): d0-gone-monitor fail-safe short-read guard + per-cell degrade
Assigns the authoritative total before the empty-page break and treats an
inconclusive/truncated read as HOLD (fails toward alerting, never folds partial
data into a nothing-gone verdict); de-dupes the short-read log; per-cell scan
try/catch degrades one bad cell without blinding the detector.
2026-07-20 21:48:40 -07:00
Jordan Ritter 7382d72fba refactor(showcase): single-source shared catalog flatten with manifest validation
One shared catalog-flatten authority (typed throws, not process.exit); the server
re-flatten validates manifest structure at parity with the codegen path.
2026-07-20 21:48:40 -07:00
Jordan Ritter 1b87facd05 feat(showcase): GET /api/matrix read-model returning true per-cell chip state
Runs buildCellModel server-side (full signal the browser strips) so the true
dashboard-visual state is API-derivable. Authoritative-total short-read guard
(serves matrix_unavailable, never silent all-gray), page-cap throw, and per-cell
try/catch so one bad featureId degrades a single cell, not the whole surface.
2026-07-20 21:48:40 -07:00
Jordan Ritter ea8203a3ef feat(showcase): unified cell-model ladder engine
Single per-rung classifyRung verdict folded uniformly via foldFamily/combine;
enforces the section-2a coherence invariants (chip/isRegression/achieved/d6Effective
from one verdict), first-strike de-amplification gated on max non-infra red
fail_count, future-skew age clamp, and the staleness folds. Golden-master
equivalence baseline + coherence/contribution/combine test suites.
2026-07-20 21:48:39 -07:00
Jordan Ritter 601754b177 test(showcase): derive D4 guard probed-route set from probe SSOT + align D4 probe naming (#6084)
## Summary

Three laser-surgical cleanups to the showcase D4 chat-roundtrip probe
and its `domDone` regression guard. Two are behavior-preserving
refactors; one is a test-coverage hardening. No probe control-flow /
outcome behavior changes.

## Changes

### GB2 — derive the guard's probed-route set from the probe SSOT
`d4-probe-domdone-guard.test.ts` hardcoded its probed-route set as a
literal `["agentic-chat","tool-rendering"]` parallel to the probe's own
inline `demo`/`demoPath` literals — a drift hazard if the probe ever
starts driving a new D4 route. Introduced `D4_DEMO_ROUTE_AGENTIC_CHAT`,
`D4_DEMO_ROUTE_TOOL_RENDERING`, and a `D4_PROBED_DEMO_ROUTES`
source-of-truth array in `d4-chat-roundtrip.ts`, wired the two
`runLevel` `demo`/`demoPath` call sites and `hasToolRendering` to them,
and had the guard derive `PROBED_ROUTES` from that export. A future D4
route is now covered automatically. Added a superset assertion so the
derived set can never narrow coverage below `{agentic-chat,
tool-rendering}`. Route strings unchanged → behavior-preserving.

### T2 — consolidate the completion FSM — DEFERRED
Not surgically achievable without behavior risk. The completion state
(`completeAtMs` / `everObserved` / `degraded` plus the per-poll
`observed` / `completed`) is progressively mutated across poll
iterations inside `runAttempt`'s loop and consumed jointly by the
grace/ceiling/floor deadline clamp (`Math.min(Math.max(baseBudgetEnd,
graceEnd), fastFailEnd, attemptCeiling)`) and three early-return sites.
There is no single read-site to redirect into one named source of truth;
a true consolidation would restructure the deadline arithmetic and risk
altering the clamp outcomes on this flap-critical probe. Left as-is per
proportionate-fix discipline.

### T3 — align complete/completed naming (behavior-preserving rename)
`readTurnComplete` returned `{ observed, complete }` while `runAttempt`
returned `{ text, completed, observed }` for the same concept. Renamed
the lower-churn side (`readTurnComplete`'s `complete` → `completed`, 5
refs vs 6) so both use `completed`. The fields are local to `runLevel`,
not exported and not referenced by any test → pure rename, zero behavior
change.

## Proof — behavior preserved

Baseline (origin/main state, before changes):
- `d4-chat-roundtrip.test.ts`: **84 passed**
- `d4-probe-domdone-guard.test.ts`: **41 passed**
- Total: **125 passed**

After changes:
- `d4-chat-roundtrip.test.ts`: **84 passed** (identical — behavior
preserved through T3 rename + GB2 wiring)
- `d4-probe-domdone-guard.test.ts`: **42 passed** (41 original + 1 new
GB2 superset test)
- Total: **126 passed**

The 125 baseline tests all still pass; the only delta is the added GB2
coverage test.

## GB2 guard red-green

On
`showcase/integrations/langgraph-python/src/app/demos/agentic-chat/page.tsx`:
- Mutated `<CopilotChat … />` → `<CopilotChat …>{null}</CopilotChat>`
(children/render-prop form) → guard **RED** (1 failed:
`langgraph-python/agentic-chat renders <CopilotChat/> in the
attribute-bearing self-closing form`).
- Reverted → guard **GREEN** (42 passed).

Mutation fully reverted; net change to the guard's scanned pages is
zero.

## Quality gates
- `oxfmt --check`: clean
- `oxlint`: 0 errors (2 warnings, both pre-existing on lines 954 / 1189,
untouched by this diff)
- `tsc --noEmit`: clean
- `tsc -p tsconfig.build.json` (full build): clean
2026-07-20 17:10:18 -07:00
Jordan Ritter e5e7fc8b96 refactor(showcase): align complete/completed naming in D4 probe (T3)
readTurnComplete returned { observed, complete } while runAttempt returned
{ text, completed, observed } for the same concept. Rename the lower-churn
side (readTurnComplete's 'complete' → 'completed') so both use 'completed'.

Pure internal rename — the fields are local to runLevel, not exported and
not referenced by any test. Zero behavior change.
2026-07-20 16:55:24 -07:00
Jordan Ritter 041b4a0692 test(showcase): derive D4 guard probed-route set from probe SSOT (GB2)
The d4-probe-domdone-guard test hardcoded its probed-route set as a literal
["agentic-chat","tool-rendering"] parallel to the probe's own inline
route literals — a drift hazard if the probe starts driving a new D4 route.

Introduce D4_DEMO_ROUTE_AGENTIC_CHAT / D4_DEMO_ROUTE_TOOL_RENDERING and a
D4_PROBED_DEMO_ROUTES source-of-truth array in the probe, wire the two
runLevel demo/demoPath call sites (and hasToolRendering) to them, and have
the guard derive PROBED_ROUTES from that export. Add a superset assertion so
the derived set can never narrow coverage below {agentic-chat,tool-rendering}.

Behavior-preserving: the route strings are unchanged.
2026-07-20 16:54:50 -07:00
Jordan Ritter da4f99f325 showcase: harden notify jobs + bring prod autoUpdates under drift-gate management (#6083)
Follow-ups to #6082 (showcase deploy consolidation), applied after the
live prod `autoUpdates` flip.

1. **fix** — the `notify-all-builds-failed` / `notify` jobs had the same
cancelled-rollup blind spot as the redeploy guard: an all-legs-cancelled
build (one leg cancelled under contention) that really produced **no**
successful service sent **no** alert. They now fire on `any_success ==
'false'` (guarded by a status function so a user-cancelled run stays
silent). Red-green in `redeploy-guard.test.ts` (reads the live workflow
guards).
2. **feat** — prod `autoUpdates` is now `"disabled"` (was
`"unmanaged"`), bringing prod under drift-gate management now that its
live Railway `autoUpdates` are disabled. Both envs are migrated; the
gate enforces both.

The live staging + prod Railway `autoUpdates` are already disabled, so
the drift gate finds live == SSOT on both envs.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-07-20 16:43:36 -07:00
Jordan Ritter 3dc43b9ca9 feat(showcase): bring prod autoUpdates under drift-gate management
Prod autoUpdates is now "disabled" (was "unmanaged") for every service, so the
drift gate enforces prod as well as staging. Paired with disabling autoUpdates
on the live prod Railway services. Regenerates the SSOT JSON.
2026-07-20 16:31:28 -07:00