Labsco
mastra-ai logo

builder-smoke-test

โ˜… 25,837

by mastra-ai ยท part of mastra-ai/mastra

Smoke test the Agent Builder feature branch end-to-end against a hermetic project scaffolded by the skill (linked to the current worktree). Covers workspace reconciliation, stored agents/skills CRUD, ownership, visibility, stars, registry/library Copy flow, picker allowlists, model policy, RBAC role gating, role impersonation UI, builder defaults, infrastructure diagnostics, channels, and Studio + Agent Builder UI. Trigger when validating the agent-builder feature branch, PRs that touch packages

๐Ÿงฐ Not standalone. This skill ships with mastra-ai/mastra and only works together with that tool โ€” install the tool first, then add this skill.

This is the playbook your agent receives when the skill activates โ€” you don't need to read it to use the skill, but it's here to audit before installing.

Builder Smoke Test

End-to-end smoke testing of the Agent Builder feature set against a hermetic project the skill scaffolds at ~/mastra-builder-smoke-tests/builder-smoke (configurable). The project links to the current worktree via pnpm link: overrides, so changes to packages under packages/, stores/, auth/, channels/, observability/, browser/, and client-sdks/ take effect on the next mastra dev restart.

This skill is for branch QA โ€” it complements the release-time mastra-smoke-test. It exercises the Builder EE surface (stored entities, RBAC, registry, infra, channels) using a minimal, predictable project rather than the kitchen-sink examples/agent.

โš ๏ธ Mandatory Test Checklist

Use task_write to track progress. Run ALL sections unless --test or --scope narrows the run.

Do not skip sections unless you hit an actual blocker. "Seemed complex" or "I'll come back to it" are not valid reasons. Attempt every step โ€” only stop when you literally cannot proceed. Report what you tried and what blocked you.

#SectionReferenceWhen required
1Setupreferences/setup.mdAlways
2Workspacereferences/workspace.md--test workspace or full
3Reconciliationreferences/reconciliation.mdSteps 1 + 5 only; steps 2/3/4/6 are out of smoke-test scope (see below)
4Defaultsreferences/defaults.md--test defaults or full
5Model Policyreferences/model-policy.md--test model-policy or full
6Skillsreferences/skills.md--test skills or full
7Registryreferences/registry.md--test registry or full
8Agentsreferences/agents.md--test agents or full
9Picker Allowlistsreferences/picker-allowlist.md--test pickers or full
10Favoritesreferences/favorites.md--test favorites or full (formerly stars)
11Permissions / RBACreferences/permissions.md--test permissions or full
12Infrastructurereferences/infrastructure.md--test infrastructure or full
13Channelsreferences/channels.md--test channels or full
14UIreferences/ui.md--test ui or full
15Authreferences/auth.md--test auth or --auth on

Execution flow

  1. Confirm the project directory. Before scaffolding, ask the user where they want $PROJECT_DIR to live. Offer the default (~/mastra-builder-smoke-tests/builder-smoke) as a suggestion. Skip the question if they already passed --dir or have $BUILDER_SMOKE_TEST_DIR exported. See references/setup.md step 0.
  2. Read the reference file for each section you're about to run.
  3. Under --auth on, extract the session cookie before running any other section. The WorkOS cookie is httpOnly, so curl cannot mint it and document.cookie cannot read it. The scaffold ships a debug route at GET /smoke-test/cookie gated by SMOKE_TEST_COOKIE_LEAK=1. Follow the "Extracting the session cookie for curl (auth on)" section below before touching any auth-on endpoint. Do not pivot to UI-only testing because curl is "blocked" โ€” the cookie route is the unblock path.
  4. Seed non-owner data after the server has booted at least once. A fresh scaffold has no skills authored by anyone other than the test user, which makes non-owner / Library Copy / non-owner visibility / non-admin stars flows untestable. Run bash .claude/skills/builder-smoke-test/scripts/seed-multi-user.sh (or with --dir $PROJECT_DIR) before sections 6 (Skills), 7 (Registry), and 10 (Stars). The script is idempotent and bypasses RBAC by writing directly to libsql, so it works regardless of --auth mode or current role. Do not mark non-owner steps as "blocked" without running this first.
  5. Execute the steps โ€” use curl for API checks (with -H "Cookie: $COOKIE" under --auth on), whichever browser tool the harness has wired up (Stagehand, Chrome MCP, etc.) for UI checks.
  6. Record results in the summary table.
  7. Mark the section complete with task_write before moving to the next.

Partial testing (--test)

If --test is provided:

  1. Always run Setup.
  2. Run only the specified section(s).
  3. Skip everything else.

Example: --test skills,registry,agents โ†’ Setup + Skills + Registry + Agents.

Scope shortcuts (--scope)

--scope runs a curated group of related sections. Setup is always implied.

ScopeIncludes
rbacpermissions, auth
skillsskills, registry, defaults
agentsagents, pickers, defaults, model-policy
infrainfrastructure, channels, reconciliation
uiui
quickworkspace, skills, agents, favorites, ui (skips long-running)

--scope and --test can be combined; the union is run.

Parameters

ParameterDescriptionDefault
--testComma-separated section names (see table above).(all sections)
--scopeNamed group of sections (rbac, skills, agents, infra, ui, quick). Combinable with --test.(none)
--authon, off, or auto. auto enables the Auth section iff WORKOS_CLIENT_ID + WORKOS_API_KEY are set.auto
--roleExpected role of the logged-in user under --auth on: owner, admin, member, or viewer. Setup asserts the live /api/auth/me roles match; on mismatch the run stops and the user is told to either change their WorkOS role or re-run with the correct --role. Ignored under --auth off.admin
--cleanDelete test entities (smoke-test workspaces / agents / skills) at the end of each section.false
--skip-browserRun only API/curl checks. UI section is skipped.false
--dirProject directory the skill scaffolds into. Forwarded to scripts/scaffold.sh. Also reads $BUILDER_SMOKE_TEST_DIR from the environment when the flag is omitted.~/mastra-builder-smoke-tests/builder-smoke
--reuseIf the project already exists at $PROJECT_DIR and has node_modules/@mastra/core, skip pnpm install. Forwarded to scripts/scaffold.sh.false
--openai-keyOPENAI_API_KEY value to write into the scaffolded .env. If omitted, the scaffold script falls back to $OPENAI_API_KEY in the shell, then to an interactive prompt.(shell or prompt)
--workos-api-key
--workos-client-id
--workos-organization-id
All three are required together to scaffold an auth-on project. Writes AUTH_PROVIDER=workos plus the three keys plus WORKOS_REDIRECT_URI=http://localhost:4111/api/auth/callback into .env.(auth off)

If --auth auto and no WorkOS env vars are present, the Auth section is auto-skipped and reported as โญ๏ธ Skipped (no WORKOS_* env vars).

Canonical order

When running multiple sections, execute them in the order shown in the section table (1 โ†’ 15). The order is intentional:

  • Setup must run first โ€” preflight + readiness probe gate every later section.
  • Workspace / Reconciliation / Defaults / Model Policy establish that the server's view of the project matches what the rest of the run assumes. Run them before any CRUD pass.
  • Skills โ†’ Registry โ†’ Agents โ†’ Pickers โ†’ Stars is a build-up: agents reference skills, pickers depend on the entities created above.
  • Permissions / Infrastructure / Channels / UI are read-mostly inspections that benefit from existing entities.
  • Auth runs last because it requires restarting mastra dev with a different .env.

If --test or --scope narrows the run, keep the relative order โ€” just skip the sections that fall outside the selection.

Required vs optional reference tiers

References fall into three tiers; an agent should treat them accordingly:

  • Required (every run): setup.md. Any failure here blocks the rest of the run.
  • Standard (default tiers for full, quick, scope shortcuts): workspace.md, skills.md, agents.md, favorites.md, ui.md (core), auth.md when --auth on.
  • Extended (only when explicitly selected via --test/--scope or the matching code surface changed): reconciliation.md, defaults.md, model-policy.md, registry.md, picker-allowlist.md, permissions.md, infrastructure.md, channels.md, ui.md extended tier.

When skipping an extended section, mark it โญ๏ธ Skipped (not in scope) in the result table โ€” don't silently omit it.

Cleanup

The scaffold is a self-contained throwaway directory at $PROJECT_DIR. All fixture state (workspaces, agents, skills, libsql DB, .mastra/workspace files) lives inside it. The smoke test never writes to anything outside $PROJECT_DIR (other than the dev server it runs).

At the end of every run:

  1. Stop the dev server (kill $(lsof -i :4111 -sTCP:LISTEN -t) or foreground Ctrl-C).
  2. Choose how to dispose of fixture state:
    • Reuse: leave $PROJECT_DIR in place. The next run can pass --reuse (or --skip-scaffold to preflight) and pick up where this one left off. Fastest for iterating.
    • Reset: rm -rf "$PROJECT_DIR" (or re-run scripts/scaffold.sh without --reuse). Cheapest way to get back to a known-clean state. Don't bother per-entity DELETE โ€” the directory IS the state.
  3. If a section bailed mid-flight (assertion failure, network error), record the partial state in the report's Issues section so the next run knows what to expect.

Per-entity DELETE calls are only needed when a specific section explicitly tests DELETE behavior (those sections include the DELETE step inline). Otherwise the throwaway-directory model handles cleanup.

Never leave the dev server running on :4111 after the report is filed โ€” it blocks future runs.

Starting the dev server

If the server is not running on :4111, the Setup section starts it. The convenience helpers live under scripts/:

# Scaffold + preflight (writes .env, installs deps, detects auth mode)
bash .claude/skills/builder-smoke-test/scripts/preflight.sh --expect off

# Start the server from the scaffolded project
cd ~/mastra-builder-smoke-tests/builder-smoke
pnpm mastra:dev

# Poll /api/agents until 200 (60s budget). Detects mastra dev's port-bump.
bash .claude/skills/builder-smoke-test/scripts/wait-for-server.sh

wait-for-server.sh probes /api/agents โ€” not / โ€” because the SPA shell can return 200 before the API mounts. If it reports the server is up on :4112+ instead of :4111, mastra dev fell through to the next port; stop, free :4111, and restart. Continuing on a non-default port silently breaks every curl in every reference.

API base URL

Every reference assumes $BASE is exported. Set it once at the start of the run:

export BASE=http://localhost:4111/api

All curl examples in the references use $BASE and won't work in a shell that hasn't exported it.

Quick reference: key endpoints

This table lists the surfaces an agent will hit and where to look for the authoritative request/response shape. Don't copy curl blocks from here โ€” run the per-section commands in references/<section>.md.

SurfaceEndpoint
Builder settingsGET /editor/builder/settings
Builder infraGET /editor/builder/infrastructure
Registries (list)GET /editor/builder/registries
Registry searchGET /editor/builder/registries/:registryId/search?q=โ€ฆ
Registry popularGET /editor/builder/registries/:registryId/popular
Registry previewGET /editor/builder/registries/:registryId/preview?owner=โ€ฆ&repo=โ€ฆ&path=โ€ฆ
Registry installPOST /editor/builder/registries/:registryId/install
Workspace CRUDGET/POST/PATCH/DELETE /stored/workspaces[/:id]
Agent CRUDGET/POST/PATCH/DELETE /stored/agents[/:id]
Agent favoritePUT / DELETE /stored/agents/:id/favorite
Agent avatarPATCH /stored/agents/:id with metadata.avatarUrl (owner-only)
Skill CRUDGET/POST/PATCH/DELETE /stored/skills[/:id]
Skill publishPOST /stored/skills/:id/publish
Skill favoritePUT / DELETE /stored/skills/:id/favorite
Auth meGET /api/auth/me (returns logged-in user + roles + permissions)
Auth refreshPOST /auth/refresh

Builder Studio routes

FeatureRoute
Agent Builder shell/agent-builder
Agents (default view)/agent-builder
Agent detail (view)/agent-builder/agents/:id/view (bare :id redirects to /view)
Agent detail (edit)/agent-builder/agents/:id/edit
Skills/agent-builder/skills
Library (public skills)/agent-builder/library
Skill detail/agent-builder/skills/:id/edit (owner) or /agent-builder/skills/:id/view (non-owner)
Workspaces/agent-builder/workspaces
Infrastructure/agent-builder/infrastructure (readable by every default role โ€” see infrastructure.md)

Mobile renders a bottom-bar with the same primary entries.

Browser smoke

Use whichever browser tool the harness has wired up (Stagehand, Chrome MCP, etc.). Don't assume a specific provider โ€” discover what's available, then drive the same checklist in references/ui.md.

The scaffolded project registers StagehandBrowser (matching examples/agent-builder). If BROWSERBASE_* keys aren't set in the shell, Stagehand falls back to local Playwright; that's fine for smoke. If neither Stagehand nor a local browser is reachable, mark UI as โญ๏ธ Skipped (no browser provider).

Result reporting

After testing, provide:


## Builder Smoke Test Results

**Date**: <date>
**Branch**: <branch>
**Commit**: <short sha>
**Server**: scaffolded project @ localhost:4111 (`$PROJECT_DIR`)
**Auth**: on / off / auto-skipped

| #   | Section            | Status   | Notes                           |
| --- | ------------------ | -------- | ------------------------------- |
| 1   | Setup              | โœ…/โŒ    |                                 |
| 2   | Workspace          | โœ…/โŒ    |                                 |
| 3   | Reconciliation     | โœ…/โŒ/โญ๏ธ |                                 |
| 4   | Defaults           | โœ…/โŒ    |                                 |
| 5   | Model Policy       | โœ…/โŒ    |                                 |
| 6   | Skills             | โœ…/โŒ    |                                 |
| 7   | Registry           | โœ…/โŒ    |                                 |
| 8   | Agents             | โœ…/โŒ    |                                 |
| 9   | Pickers            | โœ…/โŒ    |                                 |
| 10  | Stars              | โœ…/โŒ    |                                 |
| 11  | Permissions / RBAC | โœ…/โŒ    |                                 |
| 12  | Infrastructure     | โœ…/โŒ    |                                 |
| 13  | Channels           | โœ…/โŒ    |                                 |
| 14  | UI                 | โœ…/โŒ/โญ๏ธ |                                 |
| 15  | Auth               | โœ…/โŒ/โญ๏ธ | (skipped if no WORKOS\_\* vars) |

**Product issues**: (list any โ€” server/UI behaved unexpectedly. For each: HTTP method + path or UI route, expected vs actual, one-sentence guess at the cause. Do not pre-decide "known bug" โ€” log what the server actually did. Say "none" if empty.)
**Skill issues**: (list any โ€” the skill itself was wrong, unclear, stale, or unreachable. For each: which file + step (e.g. `references/skills.md` step F2), and what was wrong. Doc drift, not product bugs. Say "none" if empty.)

**Verify before filing.** Before adding anything to either list, re-confirm against the live response in this run, not memory of an earlier call:

- For any **shape mismatch / missing field / wrong key name** claim, paste the actual JSON fragment (or the relevant keys) directly under the bullet so the claim is reproducible. If the skill says `features.agent.skills` and the response has `features.agent.skills`, that is not a skill issue โ€” names that look similar in passing (`featSkills`, `agent.features.skill`, etc.) are easy to misread.
- For any **endpoint inconsistency** claim (e.g. "endpoint A returns X but B returns Y"), re-curl both endpoints fresh in the same run rather than reusing a stale response from earlier in the section.
- For any **RBAC / authz** claim (403 where you expected 200, or vice versa), check `references/permissions.md` for the matrix _and_ check the "Design decisions" list in this file. Several roles intentionally share `*:read`, which means infra/list/get endpoints look "ungated" but are working as intended. Also confirm the cookie you sent belongs to the role you think it does (`curl -H "Cookie: $(cat /tmp/cookie.txt)" $BASE/auth/me | jq '.role // .roles'`).
- For any **missing endpoint** claim (e.g. "agent avatar 404"), confirm the contract first โ€” several flows are client-composed on top of generic CRUD (avatar = `PATCH metadata.avatarUrl`; Library Copy = `POST /stored/skills` with `metadata.origin`). The "Design decisions (don't file as bugs)" section enumerates the common ones.
- If a claim can't be reproduced on a fresh request, drop it.
  **Regressions**: (list any behavioral changes from a previous run)
  **Warnings**: (e.g., dev-server crash on `/auth/refresh` polling, OPENAI_API_KEY required at startup)
  **Skipped sections**: (list with reason)

Known rough edges

The branch has accumulated minor papercuts. Note these in your report only if you hit them; don't fail the run on them:

  • Don't rm $PROJECT_DIR/mastra.db by hand while the server is up โ€” stop the server first, then delete.
  • Dev server can crash on hot-reload from /auth/refresh polling. Restart and continue.
  • OPENAI_API_KEY is required at startup โ€” server won't boot without it, even if you only test non-LLM surfaces.
  • mastra dev overwrites process.env from .env at boot, so inline env overrides on the command line don't reach the server. Re-run scaffold to change .env.
  • The scaffold links against the current worktree's packages via link: overrides. If you switch worktrees, re-run scaffold so the symlinks point at the right tree.

Design decisions (don't file as bugs)

These have come up across multiple runs and are intentional. If you observe one, note it in your report as "expected behavior" โ€” do not open a product issue.

  • GET /auth/me without a cookie returns 200 with a null-ish body. The route is mounted as a public route (createPublicRoute); the contract is "return the current user or null", not "401 if missing". A 401 here would break the public app shell.
  • /editor/builder/infrastructure is readable by every default role (admin / member / viewer). The handler gates on infrastructure:read and every default role has *:read, which matches by resource-wildcard. The page only exposes deployment-shape data (provider names, registered flags, configured/unconfigured booleans) โ€” no secrets.
  • Flipping a skill's visibility from private to public does not auto-publish unless the skill has a registered skillPath. Visibility and publication are independent fields by design. A plain-create skill flipped public stays at activeVersionId: null until a real POST /publish runs against a source path.
  • Zod schema validation runs before the permission middleware on /stored/* writes. A malformed body from a viewer returns a 400, not a 403. This is standard request lifecycle; the response surface doesn't leak resource state.
  • The role-impersonation picker only lists roles different from the current one. Logged in as admin, you'll see Member and Viewer and nothing else โ€” there is no Admin self-item. This is intentional (admin is the baseline; you're already there).
  • Impersonation is UI-only. The API still answers per the real logged-in role. A curl while impersonating viewer will still return the admin's response.
  • Favorites sidebar entry links to /agent-builder/favorite (singular). The plural /favorites is not a registered route and renders the React Router 404. Use the sidebar link or the singular URL when scripting.
  • Avatar upload uses agent PATCH with metadata.avatarUrl, not a dedicated /avatar endpoint. See references/agents.md.
  • Copy is client-side. There is no POST /stored/skills/:id/copy. The UI fetches the source skill and POSTs a new row to /stored/skills with metadata.origin = "library-copy". See references/registry.md.

Out of smoke-test scope

Some flows are documented in references/ but are not driven by the smoke-test agent because they require server-lifecycle gymnastics that don't fit a single run:

  • Reconciliation steps 2/3/4/6 (references/reconciliation.md) require editing $PROJECT_DIR/src/mastra/index.ts (changing basePath / workspaceId / config), restarting mastra dev multiple times, and observing drift detection or orphan archival across restarts. The smoke-test agent runs only Step 1 (fresh-startup persistence) and Step 5 (non-builder workspaces untouched). Run the rest by hand when changing reconciliation code.
  • Real role-swap testing (logging in as multiple WorkOS users with different roles in the same run) is out of scope. The agent verifies whichever role the live --role user actually has, and additionally exercises the UI-only role impersonation flow under --role admin (see references/ui.md).

References

  • references/setup.md โ€” server health, builder settings sanity, baseline counts, builder workspace existence
  • references/workspace.md โ€” workspace CRUD via API
  • references/reconciliation.md โ€” config-driven workspace lifecycle (fresh, idempotent, drift, archival, backfill)
  • references/defaults.md โ€” builder defaults applied at agent create (memory, workspace, browser, model)
  • references/model-policy.md โ€” allowed list, default model, dropdown filtering, rejection
  • references/skills.md โ€” skill CRUD, visibility, publish, filesystem writes, files array
  • references/registry.md โ€” skills.sh browse/install, library Copy flow, origin badges, gating
  • references/agents.md โ€” stored agent CRUD, skill attachment, model swap, delete-from-edit, avatar upload
  • references/picker-allowlist.md โ€” tools/agents/workflows pickers respect allowlists
  • references/favorites.md โ€” favorite/unfavorite agents and skills, idempotency (formerly stars.md)
  • references/permissions.md โ€” viewer/member/admin/owner gating, role expectation matrix, UI impersonation, auth-off bypass
  • references/infrastructure.md โ€” /editor/builder/infrastructure payload + UI
  • references/channels.md โ€” Slack provider visibility, connectChannel tool
  • references/ui.md โ€” browser checklist across Builder routes
  • references/auth.md โ€” WorkOS on/off, 401 behavior, authorId, mode-toggle via .env
  • scripts/scaffold.sh โ€” scaffold or refresh the hermetic project at $PROJECT_DIR
  • scripts/preflight.sh โ€” wraps scaffold.sh + mode expectation (--expect off|on)
  • scripts/wait-for-server.sh โ€” poll :4111 until healthy