The docs-sync workflow flagged these two files as having showcase-local
modifications that blocked the automated transform pipeline:
- docs/content/docs/integrations/langgraph/generative-ui/your-components/interrupt-based.mdx
- docs/content/docs/integrations/langgraph/human-in-the-loop/interrupt-flow.mdx
Upstream docs/ changes pending sync to showcase/:
- Add useInterrupt `agentId: "starterAgent"` to all four examples per file
- Add <Callout type="warn"> explaining that a mismatched agentId silently
never fires the interrupt
- Update stale model name gpt-5.2 -> gpt-5.4 in code snippets
Showcase-local divergence present before this PR:
- Leftover import fragment at the top of each file (bytes from an
incomplete multi-line import strip by an older version of the sync
script, not deliberate content)
- Prettier-style reformatting applied ad hoc (line wrapping in the
Callout info block and the last useInterrupt handler example)
- Stale model name gpt-5.2 (pre-dates the upstream bump to gpt-5.4)
- interrupt-flow.mdx never received the agentId / Callout additions
that interrupt-based.mdx received in 63a6a2733 and 90d1869ea
Resolution: rebuild both showcase files as a clean transform of the
current upstream source. None of the showcase-local changes were
intentional additive content — they were stripping bugs, formatter
drift, and pre-sync staleness — so dropping them and taking the full
upstream reconciles both files cleanly.
Also bumps showcase/shell/.docs-sync-sha to the current main tip so the
next docs-sync run does not re-flag the same files.
## Summary
Adds 5 missing QA markdown files (gen-ui-agent,
shared-state-{read,write,streaming}, subagents) to bring
`showcase/packages/ag2/qa/` from 4 files to 9, matching
`langgraph-python/qa/`.
Part of the QA-parity blitz (Bundle 0 in the action inventory).
### Detail
- `gen-ui-agent.md` and `shared-state-read.md` describe the full
implementations — selectors (`task-progress`, `task-step-text`,
`recipe-card`, `add-ingredient-button`, `improve-button`), labels (`AI
Recipe Assistant`), and suggestion button names match the ag2 page
sources verbatim (they mirror LG-py's implementations word-for-word).
- `shared-state-write.md`, `shared-state-streaming.md`, and
`subagents.md` follow the "Note: Stub Demo" pattern from LG-py — the ag2
pages for these demos are stubs identical to LG-py's stubs, so the QA
coverage is identical.
## Test plan
- [ ] Verify `showcase/packages/ag2/qa/` now contains 9 files matching
the file set in `showcase/packages/langgraph-python/qa/`
- [ ] Spot-check selectors in `gen-ui-agent.md` and
`shared-state-read.md` against the ag2 page sources
## Summary
Follow-up hardening to #3971. aimock supports fixture schema validation
at startup via `--validate-on-load`, but the flag is **opt-in** and the
showcase Dockerfile was not passing it. That meant fixtures with
unrecognized response keys (e.g. `"text"` instead of `"content"`) loaded
silently and only surfaced as HTTP 500s at request time — which is
exactly what crashed crewai-crews and triggered #3971.
This PR wires up two independent safety nets so a broken fixture can't
ship again:
1. **Dockerfile (fail-fast at container boot)** —
`showcase/aimock/Dockerfile` now passes `--validate-on-load`. If any
fixture fails the aimock schema, the container exits non-zero instead of
starting and serving 500s. Railway will not promote a bad build.
2. **CI test (fail-fast in PR review)** — new vitest spec at
`showcase/scripts/__tests__/aimock-fixtures.test.ts` imports
`loadFixtureFile` + `validateFixtures` from `@copilotkit/aimock` and
asserts zero errors against both `feature-parity.json` and `smoke.json`.
Runs inside the existing ` Showcase: Validate` workflow
(`showcase/scripts` vitest suite) on every PR that touches
`showcase/**`.
## Verification
**Red-green on the vitest spec:**
- Rebased onto the tip of main *before* #3971 merged: the spec fails
with 5 errors — exactly the 5 broken `"text"` fixtures (`plan`, `steps`,
`mars`, `dashboard`, `report`) that #3971 repaired.
- Rebased forward onto main *after* #3971: spec passes with 0 errors,
all 549 showcase/scripts tests green.
**Red-green on the Dockerfile:**
- Current fixtures + `--validate-on-load`: container boots cleanly, logs
`Loaded 39 fixture(s) from /fixtures`.
- Injecting an intentionally broken fixture (`response: { "text": "..."
}`): container fails to start with `[aimock] Fixture 0: response is not
a recognized type (must have content, toolCalls, error, or embedding)` /
`Validation failed: 1 error(s), 0 warning(s)` and non-zero exit.
## Test plan
- [x] Local: full `showcase/scripts` vitest suite passes (549/549)
- [x] Local: `pnpm run test` (monorepo) passes
- [x] Docker: image builds and starts with `--validate-on-load` against
current fixtures
- [x] Docker red-green: broken fixture fails container start with
non-zero exit
- [ ] CI: ` Showcase: Validate` job runs the new test file on PR
## Summary
Updates LangGraph human-in-the-loop interrupt documentation so
`useInterrupt`
examples set `agentId: "starterAgent"` and readers see a warning that
`agentId`
must match a runtime-registered agent (default assumption is
`"default"`).
## Changes
-
**`docs/content/docs/integrations/langgraph/human-in-the-loop/interrupt-flow.mdx`**
— warning callout; `agentId` on basic, conditional (`enabled`), and
`handler` snippets.
-
**`docs/content/docs/integrations/langgraph/generative-ui/your-components/interrupt-based.mdx`**
— same.
-
**`showcase/shell/src/content/docs/integrations/langgraph/generative-ui/your-components/interrupt-based.mdx`**
— same content alignment; adds the `useInterrupt` import line in the
primary code block for consistency with main docs.
## Notes
- Production apps should replace `"starterAgent"` with the id their
runtime actually registers.
- If you also want showcase `human-in-the-loop/interrupt-flow.mdx`, hook
reference docs, or a longer callout (e.g. `/info`, example error text),
those are not part of this staged set—add them in a follow-up or stage
them before merge.
## Test plan
- [ ] Open the three MDX pages in the docs/showcase preview and confirm
the callout and snippets render as expected.
Brings showcase/packages/ag2/qa/ from 4 files to 9, matching langgraph-python.
Adds: gen-ui-agent, shared-state-read, shared-state-write, shared-state-streaming, subagents.
Content is adapted from the LG-py templates with titles changed to AG2. The
three stub demos (shared-state-write, shared-state-streaming, subagents) keep
the LG-py 'Note: Stub Demo' pattern since the ag2 implementations are stubs
identical in shape to LG-py's. gen-ui-agent and shared-state-read describe
the full implementations (which mirror LG-py's selectors and labels
verbatim).
## Summary
CrewAI's `ChatWithCrewFlow.__init__` (invoked from
`ag_ui_crewai.endpoint.add_crewai_crew_fastapi_endpoint` at module
import in `ag-ui-crewai <= 0.1.5`) makes synchronous blocking LLM calls
via `crewai.cli.crew_chat.generate_input_description_with_ai` and
`generate_crew_description_with_ai`. ANY LLM hiccup — aimock regression,
OpenAI outage, network blip, DNS failure — crashes the Python process
BEFORE uvicorn can bind its port, causing Railway/Kubernetes health
checks to fail and deploys to roll back.
This was the direct cause of the crewai-crews Railway crash fixed
server-side in #3971. That fix patched the aimock response schema, but
the underlying fragility in upstream CrewAI / ag-ui-crewai remained — a
future blip would crash us again.
This PR adds a defensive monkey-patch in `agent_server.py` that replaces
both generator functions with static-string returns BEFORE
`ag_ui_crewai` is imported. The AI-generated descriptions are only
surfaced in the CrewAI chat UI (which the CopilotKit runtime does not
use), so static defaults are functionally equivalent for our showcase.
Upstream issue filed: https://github.com/crewAIInc/crewAI/issues/5510
The long-term fix is deferred construction in `ag-ui-crewai`, which has
landed on ag-ui `main` but is not yet released. Remove this shim once
`ag-ui-crewai > 0.1.5` ships.
## Why a monkey-patch and not lazy-init
`add_crewai_crew_fastapi_endpoint` is the entry point and internally
constructs `ChatWithCrewFlow(crew)` synchronously in `ag-ui-crewai <=
0.1.5`. Deferring that call would require either vendoring the endpoint
function or reimplementing it. The monkey-patch is two lines and removes
cleanly when the upstream fix ships.
## Test plan
Verified locally via Docker build + run with an intentionally broken LLM
endpoint (`OPENAI_BASE_URL=http://invalid-host/v1`):
**Unhardened (negative control):**
```
File "/app/agent_server.py", line 27, in <module>
add_crewai_crew_fastapi_endpoint(app, LatestAiDevelopment(), "/")
File ".../ag_ui_crewai/endpoint.py", line 250, in add_crewai_crew_fastapi_endpoint
add_crewai_flow_fastapi_endpoint(app, ChatWithCrewFlow(crew=crew), path)
File ".../ag_ui_crewai/crews.py", line 56, in __init__
self.crew_chat_inputs = crew_chat_generate_crew_chat_inputs(...)
File ".../crewai/cli/crew_chat.py", line 387, in generate_crew_chat_inputs
description = generate_input_description_with_ai(input_name, crew, chat_llm)
File ".../crewai/cli/crew_chat.py", line 481, in generate_input_description_with_ai
response = chat_llm.call(...)
APIError
```
Container exits with code 1, never binds a port.
**Hardened (this PR):**
```
INFO: Started server process [7]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
```
`curl http://localhost:PORT/api/health` ->
`{"status":"ok","integration":"crewai-crews","agent":"ok","timestamp":"..."}`
(HTTP 200).
### Checklist
- [x] Docker build succeeds locally
- [x] Unhardened build crashes on import with broken LLM endpoint
(negative control)
- [x] Hardened build starts cleanly with broken LLM endpoint and
responds 200 on `/api/health`
- [x] Upstream issue filed on crewAIInc/crewAI
## Summary
- The Mastra showcase package registers only `weatherAgent` in its
Mastra config, but the demo pages request names like `agentic_chat`,
`human_in_the_loop`, `tool-rendering`, etc.
`MastraAgent.getLocalAgents({ mastra })` returns agents keyed by
registration name, so the runtime cannot resolve the demo-requested
names. This was causing the L3 mastra chat test to fail.
- Mirror the pattern used in
`showcase/packages/crewai-crews/src/app/api/copilotkit/route.ts`: wrap
`MastraAgent.getLocalAgents` and expose the underlying `weatherAgent`
under every name the demo pages ask for. `weatherAgent` itself is
preserved so the internal `/api/smoke` route (which calls `agentId:
"weatherAgent"`) keeps working.
## Agent names now exposed on the backend
- `weatherAgent` (original Mastra registration — preserved for smoke
test)
- `agentic_chat`
- `human_in_the_loop`
- `tool-rendering`
- `gen-ui-tool-based`
- `gen-ui-agent`
- `shared-state-read`
- `shared-state-write`
- `shared-state-streaming`
- `subagents`
The starter (`showcase/starters/mastra`) was checked and is not affected
— its route uses `LangGraphAgent` and already registers `sample_agent`,
which matches what the starter's page requests.
## Test plan
- [ ] CI L3 mastra chat test passes (the failure this PR targets)
- [ ] `/api/smoke` route still returns 200 (uses `weatherAgent` which is
preserved)
- [ ] Demo pages (`/demos/agentic-chat`, `/demos/hitl`,
`/demos/tool-rendering`, etc.) can reach the runtime without 404
Addresses CR R1 CRITICAL finding on PR #3974.
setattr() on a Python module always succeeds regardless of prior
attribute existence. Without a guard, an upstream rename of
generate_input_description_with_ai or generate_crew_description_with_ai
in a future crewai release would silently no-op the patch, leaving the
real functions in place. The pre-bind LLM crash bug would quietly
reappear in production with a green PR.
Changes:
- Add hasattr() guard in both agent_server.py files that raises
RuntimeError with an actionable drift message if either symbol
disappears upstream.
- Add post-assignment assert to defend against import-order weirdness
or module re-imports shadowing the reference.
- Add an info-level log line so operators can see the shim is active
and know to remove it after adoption.
- Add upstream issue link (crewAIInc/crewAI#5510) and explicit ag-ui-crewai
release status to the comment block.
- Pin ag-ui-crewai upper bound to <0.1.6 in both requirements.txt files
so the shim's applicability window is enforced by pip — upgrading past
0.1.5 forces the engineer to confront the version mismatch and remove
the shim.
Applied to both showcase/packages/crewai-crews/src/agent_server.py and
showcase/starters/crewai-crews/agent_server.py to keep the demo and
starter trees in sync.
Verified locally:
- Docker build succeeds (showcase/packages/crewai-crews).
- Hardened container starts cleanly with OPENAI_BASE_URL set to an
unreachable host; /health returns 200 on both agent (8000) and
Next.js (10000) ports.
- Negative case: deleting generate_input_description_with_ai from the
installed crewai module inside the container and re-importing
agent_server raises RuntimeError with the upstream-drift message, as
expected.
- Add --validate-on-load to all aimock invocations (4 workflows/scripts
+ 13 integration docker-compose files)
- Replace hardcoded 2-file fixture list with dynamic discovery across
showcase/, examples/integrations/*/, scripts/doc-tests/ (16 fixtures)
- Add sanity check to prevent silent zero-test pass when discovery fails
- Extend showcase_validate.yml path filter to trigger on
examples/integrations/**/fixtures/** and scripts/doc-tests/fixtures/**
- Import and use ValidationResult type for callback parameters
- Fix scripts/doc-tests/fixtures/default.json to use { fixtures: [...] }
envelope shape
Add a sentence to the warning callout explaining that if agentId doesn't
match a runtime-registered agent, the interrupt will silently never fire.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CrewAI's ChatWithCrewFlow.__init__ (called by ag_ui_crewai's
add_crewai_crew_fastapi_endpoint at module import) makes blocking
synchronous LLM calls via generate_input_description_with_ai and
generate_crew_description_with_ai in crewai/cli/crew_chat.py. Any LLM
hiccup (aimock regression, OpenAI outage, network blip) crashes the
Python process before uvicorn can bind, causing Railway healthcheck
failure and deploy rollback.
Patch both functions to return static strings before ag_ui_crewai is
imported. The AI-generated descriptions are only used by the CrewAI
chat UI (not the CopilotKit runtime), so static defaults are
functionally equivalent for our showcase.
Verified via docker build: unhardened image crashes on import with
APIError at crew_chat.py:481; hardened image starts cleanly with an
invalid OPENAI_BASE_URL and responds on /api/health.
Upstream fix (deferred construction) landed on ag-ui main but is not
yet released in ag-ui-crewai > 0.1.5. Remove shim when released.
Upstream issue: https://github.com/crewAIInc/crewAI/issues/5510
Follow-up to #3971. aimock supports fixture schema validation at startup via
--validate-on-load, but it's opt-in. The showcase Dockerfile did not pass
the flag, so fixtures with unrecognized response keys (e.g. "text" instead
of "content") loaded silently and only failed at request time with HTTP 500.
That's what crashed crewai-crews on startup.
Changes:
- showcase/aimock/Dockerfile: pass --validate-on-load so broken fixtures
fail the container boot, not individual requests.
- showcase/scripts/__tests__/aimock-fixtures.test.ts: new vitest spec that
loads feature-parity.json and smoke.json via @copilotkit/aimock's
loadFixtureFile + validateFixtures and asserts zero errors. Runs as part
of the existing showcase-validate CI workflow.
- showcase/scripts/package.json: add @copilotkit/aimock dependency for the
validator import.
Verified red-green: with the pre-#3971 broken "text" fixtures, validateFixtures
flags 5 errors; post-#3971 it returns zero. Docker red-green: container with
an intentionally broken fixture fails to start with "Validation failed: 1
error(s)" and non-zero exit.
The showcase aimock feature-parity fixture had five entries that used the
unrecognized field "text" instead of "content" in the response body.
aimock's /v1/chat/completions handler validates the response shape through
discriminators (isTextResponse, isToolCallResponse, etc.) and when none
match, returns 500 "Fixture response did not match any known type".
When CrewAI's ChatWithCrewFlow.__init__ calls generate_input_description_with_ai,
it sends a prompt containing "Reporting Analyst" / "reports" text (from the
LatestAiDevelopment crew definition). aimock substring-matches this against
the "report" fixture, which had the broken "text" shape, and returned 500.
CrewAI treats that as an InternalServerError, the crewai-crews container
crashes during module import (before uvicorn binds), Railway healthchecks
fail, and the deployment rolls back to the previous ACTIVE build.
Fix:
- Convert the 5 fixtures with "text" (plan, steps, mars, dashboard, report)
to the valid "content" field so they return 200 OK.
- Add a targeted fixture that matches CrewAI's exact startup prompt prefix
("Based on the following context, write a concise") and returns a clean
text description. This catches generate_input_description_with_ai and
generate_crew_description_with_ai before they can fall through to the
more generic fixtures, providing a more predictable response for CrewAI
startup.
Verified locally against @copilotkit/aimock@1.10.0:
- Before: the CrewAI-style prompt returns 500 with the exact error message
seen in Railway logs.
- After: returns 200 with a valid chat.completion envelope.
Note: CrewAI's blocking LLM call at module import remains fragile (any
aimock hiccup crashes the container before it can bind a port). That is
an upstream issue and will be tracked separately.
The Mastra showcase package registers a single local agent
(`weatherAgent`), but the demo pages request names like `agentic_chat`,
`human_in_the_loop`, `tool-rendering`, etc. `MastraAgent.getLocalAgents`
returns the agents under their registration keys, so the runtime could
not resolve the demo-requested names and the L3 mastra chat test
failed.
Mirror the crewai-crews pattern: wrap the local agents map and expose
`weatherAgent` under every demo-expected name. `weatherAgent` itself is
preserved so the internal smoke route keeps working.
## Summary
Addresses all findings from 7-agent MSAL code review of the starter
crash fix PRs (#3933, #3941, #3943).
**Agent server (claude-sdk-typescript):**
- Remove 6 unnecessary `as any` casts — use TypeScript discriminated
union narrowing on `msg.role`
- Add `ANTHROPIC_API_KEY` validation on startup (exit if missing)
- Add `console.warn` logging to empty catch blocks (tool args + schema
parse failures)
- Sanitize error messages sent to client — no raw `err.message` in SSE
stream
- Fix misleading comment about system/developer role handling
- Set explicit 2MB JSON body limit on Express
- Remove unused `assistantMsgId` variable
**Generation script:**
- Remove dead `_agentDir` parameter from `rewritePythonImports`
- Add warning when `PIN_OVERRIDES` dep not found in framework
dependencies
**Tests (3 new):**
- Context-aware import rewriting for files inside `tools/` directory
- `from agents.X import` relative import rewriting
- `PIN_OVERRIDES` integration test for mastra version pinning
## Test plan
- [x] 254 generate-starters tests pass (3 new)
- [x] Drift check passes
- [x] Pre-commit hooks pass
- Guard TOOL_CALL_ARGS emission with if(toolCallId) check, matching
the existing guard on TOOL_CALL_END
- Wrap catch-block emit() in nested try/catch to handle client
disconnect during error reporting
The Round 2 fixes made tools.py rename and langgraph import
rewriting recursive, changing output for langgraph-python and
langgraph-fastapi tools/ subdirectory files. Committed starters
were stale.
Generation script:
- Make tools.py rename and langgraph import rewrite recursive via
forEachPyFile helper (was only processing top-level .py files)
- Fix from-src.agents regex to use [\w.]+ for dotted sub-paths,
matching the from-agents regex
- Simplify isInsideToolsDir branch to computed prefix variable
- Safe import-os removal: keep if os is used elsewhere in file
- Fix extractUvicornModule JSDoc example to match actual output
Agent server (claude-sdk-typescript):
- Remove dead ternary branches after API key guard
- Remove unreachable ?? "" fallback
Agent server (claude-sdk-typescript):
- Remove 6 unnecessary as-any casts, use TS discriminated union narrowing
- Add ANTHROPIC_API_KEY validation on startup (exit if missing)
- Add logging to empty catch blocks (tool args + schema parse)
- Sanitize error messages sent to client (no raw err.message in SSE)
- Fix misleading comment about system/developer role handling
- Set explicit 2MB JSON body limit
- Remove unused assistantMsgId variable
Generation script:
- Remove dead _agentDir parameter from rewritePythonImports
- Add warning when PIN_OVERRIDES dep not found in dependencies
Tests:
- Add context-aware import rewriting test (files inside tools/)
- Add from-agents.X relative import rewriting test
- Add PIN_OVERRIDES integration test for mastra version pinning
## Summary
- Remove the Open GenUI rendering strategy from all 17 showcase starters
- Clean up all supporting files: feature registries, constraints, e2e
tests, Python middleware, docs
- Regenerate all starters from updated template
### What was removed
The "open-genui" render mode allowed agents to generate arbitrary HTML
rendered in a sandboxed iframe. This is being extricated from starters
into a separate project. The core SDK `OpenGenerativeUIRenderer`
component is **not** affected — only the showcase starter UI option.
### Files changed
- **Template**: Deleted `open-genui/` renderer, updated types.ts,
page.tsx, suggestions hook
- **Registry**: Removed `open-gen-ui` and `byoc-opengenui` features from
all registries (shell, shell-dojolike, shared)
- **Constraints**: Removed "open" constraint block and open-gen-ui
references
- **E2E tests**: Removed Open GenUI test cases from starter-e2e,
screenshots, renderer-selector specs
- **Python middleware**: Removed OPEN_GENUI_INSTRUCTION and open-genui
handling from render_mode.py
- **Starters**: Regenerated all 17 via generate-starters.ts
- **Docs**: Updated QA-COVERAGE.md pill count from 5 to 4
### Local verification
- Docker build of langgraph-python starter: success
- Rendered page shows exactly 4 render modes (Tool-Based, A2UI,
json-render, HashBrown)
- Zero "open-genui" references in rendered HTML
- 521 validation tests pass
## Test plan
- [x] Docker build succeeds locally
- [x] Rendered starter shows 4 modes, no Open GenUI
- [x] Zero grep matches for open-genui across showcase/
- [x] 521 vitest validation tests pass
- [ ] CI green
🤖 Generated with [Claude Code](https://claude.com/claude-code)
## Summary
Fixes the last 2 crashing starters (claude-sdk-typescript + mastra)
after PR #3933 resolved 5/7.
1. **ESM resolution failure** (claude-sdk-typescript) — nested
`agent/package.json` in Docker runner stage creates a separate package
boundary that confuses tsx module resolution. Fix: `rm -f
agent/package.json` in Dockerfile template after COPY.
2. **Recursive chown** (all templates) — `chown app:app /app` only
changed the directory, not contents. Mastra needs to create
`/app/src/mastra/public` at runtime. Fix: `chown -R app:app /app` in all
Dockerfile templates.
3. **Mastra version drift** (mastra) — floating `beta` dist-tags resolve
to incompatible versions between `mastra` CLI and `@mastra/core`. Fix:
generation script pins mastra ecosystem deps to stable versions via
`PIN_OVERRIDES` map.
All fixes verified locally with Docker builds before pushing.
## Test plan
- [x] Docker build + run claude-sdk-typescript locally — agent starts on
port 8123
- [x] Docker build + run mastra locally — `mastra 1.6.0 ready in 675 ms`
- [x] 502 generate-starters tests pass
- [x] Drift check passes
- [ ] Deploy to Railway and verify all 17 starters return 200
The source package's src/agent/ was just committed — regenerating
the starter now correctly copies agent/index.ts and agent/package.json
into the starter directory, fixing the drift check.
The src/agent/ directory was never committed to the repo, causing
the drift-check to fail in CI. The starter was generated from a
local-only copy of this directory.
1. Remove nested agent/package.json in TypeScript Dockerfile template to
prevent ESM module resolution failure (claude-sdk-typescript)
2. Use chown -R for /app in all Dockerfile templates so runtime-created
dirs (e.g. /app/src/mastra/public) are writable by non-root user
3. Pin mastra ecosystem deps to stable versions (1.6.0/1.25.0) in
generation script — floating beta tags caused version drift between
mastra CLI and @mastra/core
Support retries with configurable delay in checkHealth() for Railway
cold-start scenarios. Captures last error from retry loop instead of
making a redundant final request.
Add a `deployed` boolean to all 17 starter sub-objects. 14 marked
true (healthy on Railway), 3 marked false (mastra, crewai-crews,
claude-sdk-typescript — currently down). Used by smoke tests to
gate which starters are tested.
1. EACCES on /home/app: Dockerfile templates now create home dir for
non-root user before USER app (langgraph-ts, claude-sdk-ts, mastra)
2. IndexError Path.parents[4]: search_flights.py schema fallback now
guards against shallow Docker paths (agno, claude-sdk-py, ms-agent-py)
3. Wrong import path: rewritePythonImports() now converts
from agents.X to relative imports in starter agent dirs (langroid, crewai)
## Summary
- The `generate-starters.ts` script was flattening
`src/main/{java,resources}` into `agent/{java,resources}`, breaking
Maven builds which expect the standard `src/main/` layout
- Added a post-copy restructure step that moves `agent/java/` to
`agent/src/main/java/` and `agent/resources/` to
`agent/src/main/resources/`
- Removed the now-redundant explicit resources copy that was duplicating
work
- Updated tests to verify the correct Maven layout and assert the
flattened directories no longer exist
## Test plan
- [x] `npx vitest run
showcase/scripts/__tests__/generate-starters.test.ts` — all 251 tests
pass
- [x] Verified regenerated `showcase/starters/spring-ai/agent/` has
`src/main/java/` and `src/main/resources/` (not flattened `java/` and
`resources/`)
- [x] Verified Dockerfile `COPY agent/ ./` is compatible with the new
layout (no changes needed)
## Summary
- Replace TODO placeholders in all 73 QA checklist files across 17
showcase packages with specific, actionable test steps derived from
reading actual demo page source code
- Each checklist now references real data-testid selectors, hook names
(useFrontendTool, useRenderTool, useLangGraphInterrupt,
useHumanInTheLoop, useAgent, useConfigureSuggestions), expected UI
states, and interaction flows
- Stub demos (shared-state-write, shared-state-streaming, subagents) are
marked as stubs with basic chat verification steps
- Add `showcase/QA-COVERAGE.md` with a comprehensive test coverage
matrix covering manual QA, Vitest unit tests, Playwright E2E (smoke +
interaction), per-package E2E, aimock fixtures, and CI automation for
all 9 demos plus the Sales Dashboard starter hero
## Test plan
- [ ] Verify QA checklist files no longer contain generic "TODO: Add
checks specific to X" placeholders
- [ ] Verify each checklist references the correct demo-specific
features (e.g., agentic-chat mentions background change + weather card,
hitl mentions step selector + accept/reject)
- [ ] Verify QA-COVERAGE.md matrix entries are accurate by
cross-referencing with actual test files
- [ ] Verify framework names in titles are preserved correctly across
all 17 packages
The generate-starters script was flattening src/main/{java,resources} into
agent/{java,resources}, breaking Maven builds. Add a post-copy step that
moves them to agent/src/main/{java,resources} as Maven expects.
The agent's system prompt didn't mention pieChart/barChart frontend
tools, so gpt-4o-mini would call query_data repeatedly instead of
rendering charts. Updated the system prompt to explicitly instruct
the agent to call query_data once then use pieChart/barChart, and
updated the query_data tool description to reinforce single-call
semantics.