Skip to content

inspectWorkbenchSurface fails on projects with a rendered SKILL.tsx under the react-server condition (AB3005 recentlyCreatedOwnerStacks) #441

Description

@ScriptedAlchemy

Summary

inspectWorkbenchSurface() (the workbench-surface proof level) fails on any project that has a rendered Skill (SKILL.tsx) when the test runs under the react-server condition — which is exactly the pool agentBundleRstest() configures for tests/route-unit/**. The Workbench compiler pass runs in development mode, so the rendered-skill JSX goes through react/jsx-dev-runtime, and under react-server that runtime reaches a ReactSharedInternals shape that lacks recentlyCreatedOwnerStacks:

AB3005: Rendered skill component _default threw: Cannot read properties of undefined (reading 'recentlyCreatedOwnerStacks')

The same project passes agent-bundle validate / build (production mode) and passes inspectWorkbenchSurface() under plain node. So a project with a rendered skill cannot put its workbench-surface test beside its other route-unit tests, and the docs table for the harness levels does not mention the restriction.

Found while porting the cargo-hauler plugin (ScriptedAlchemy/cargo-hauler) on preview 4edbd493b.

Repro

mkdir -p repro/src/skills/demo repro/src/mcp/demo/tools && cd repro
cat > package.json <<'EOF'
{ "name": "repro", "version": "0.0.1", "private": true, "type": "module" }
EOF
cat > agent-bundle.config.ts <<'EOF'
import { defineConfig } from 'agent-bundle/config';
export default defineConfig({ plugin: { description: 'repro', name: 'repro' }, targets: ['claude'] });
EOF
cat > src/skills/demo/SKILL.tsx <<'EOF'
import React from 'react';
export const frontmatter = { description: 'Demo rendered skill.', name: 'demo' };
export default () => (<><h1>Demo</h1><p>Hello <strong>world</strong>.</p></>);
EOF
cat > src/mcp/demo/tools/ping.tsx <<'EOF'
import React from 'react';
import type { ToolConfig, ToolRouteProps } from 'agent-bundle';
import { Agent } from '@agent-bundle/runtime';
import { z } from 'zod';
export const config = { annotations: { readOnlyHint: true }, description: 'Ping.' } satisfies ToolConfig;
export const inputSchema = z.object({}).strict();
export const resultSchema = z.object({ ok: z.literal(true) }).strict();
export default async function Ping(_: ToolRouteProps<typeof inputSchema>) {
  return <Agent.Result value={{ ok: true }}><Agent.Text>pong</Agent.Text></Agent.Result>;
}
EOF
cat > probe.mjs <<'EOF'
import { inspectWorkbenchSurface } from 'agent-bundle/test';
try {
  const surface = await inspectWorkbenchSurface({ root: process.cwd() });
  console.log('OK skills:', surface.counts.skills);
} catch (error) {
  console.log('FAIL', error.message);
}
EOF
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/agent-bundle@4edbd493b https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@4edbd493b react@19.2.8 zod@4.5.4 @rstest/core@0.11.11
node probe.mjs                              # OK skills: 1
node --conditions=react-server probe.mjs    # FAIL … AB3005 … recentlyCreatedOwnerStacks

Observed

FAIL The compiler pass produced no valid project (source state invalid), so the dev server would report the route manifest unavailable.
  compiler:     3 error(s), first AB3005: Rendered skill component _default threw: Cannot read properties of undefined (reading 'recentlyCreatedOwnerStacks')

Expected

The rendered-skill evaluation should not depend on the ambient react-server condition (render the skill with the production JSX runtime, or resolve react for the skill renderer without the condition), so inspectWorkbenchSurface works from the route-unit pool like the other harness levels. Failing that, the harness docs should say the workbench-surface level must run in the plain pool when a project has rendered skills.

Workaround

Keep the inspectWorkbenchSurface test in the plain rstest pool (no react-server condition). cargo-hauler does this in tests/workbench-surface.test.ts.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions