Skip to content

Application IR: resolve local schema imports so one route contract can drive MCP, CLI argv, Apps, and generated types #593

Description

@ScriptedAlchemy

Problem

A real framework consumer, ScriptedAlchemy/cargo-hauler, has to duplicate a route schema because Agent Bundle's static CLI argv extraction cannot consume the same imported schema that MCP/runtime validation uses.

Concrete example: cargo-hauler/src/cli/status.tsx contains an inline z.object(...) solely because the compiler reports AB4814 when the route imports the canonical statusInputSchema from src/lib/protocol-schemas.ts. A test then exists to pin the duplicate CLI schema to the protocol schema.

Meanwhile src/mcp/hauler/tools/hauler_status.tsx can simply do:

export const inputSchema = statusInputSchema;
export const resultSchema = statusResultSchema;

The framework therefore turns one logical operation contract into two authored schemas plus a compatibility test.

This conflicts with #592's intended architecture: route discovery should produce one Application IR contract that downstream MCP, CLI, browser, test, and host projections consume.

Direction

Extend static route-contract extraction so local, statically analyzable schema imports are resolved rather than requiring the schema AST to be written inline in the route module.

This should be intentionally bounded. Do not execute arbitrary user modules during discovery.

A useful supported subset:

  • relative imports only;
  • exported z.object, z.enum, arrays/unions/optional/default/describe and other already-supported schema AST forms;
  • const references whose initializer is itself statically analyzable;
  • one or more local hops with cycle detection;
  • deterministic diagnostics naming the unresolved symbol/path when analysis crosses the supported boundary.

The compiler should canonicalize the result into Application IR once. CLI argv projection, MCP JSON Schema, generated route types, Workbench, and tests should consume that same normalized schema representation.

Longer-term API

The important contract is not "make AB4814 more permissive". It is:

source schema
    ↓
canonical RouteContract IR
    ├─ MCP input/output schema
    ├─ CLI argv grammar
    ├─ generated route/client types
    ├─ Workbench editor
    └─ projection tests

The same mechanism should cover imported resultSchema, and should become the basis for the typed MCP App client requested separately rather than making Apps hand-copy protocol shapes.

Acceptance

  • A CLI route may import { statusInputSchema } from '../../lib/protocol-schemas.js' and export it as inputSchema when the imported schema is statically analyzable.
  • The generated argv grammar is identical to the inline form.
  • MCP and CLI routes importing the same schema produce one canonical normalized contract in the application graph.
  • Local enum/const references used by the schema are resolved without duplicating literals in the route file.
  • Unsupported dynamic construction fails with a specific diagnostic containing the import/symbol chain, not a generic static-analysis failure.
  • Cycles are deterministic and fail cleanly.
  • No user module execution is required for discovery.
  • cargo-hauler can delete its duplicated status CLI schema and the schema-compat pinning test.

Consumer evidence

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

    enhancementNew feature or requestmeta-frameworkAgent Bundle compiler-coupled meta-framework

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions