You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 4a37174
Browse filesBrowse the repository at this point in the historyBrowse files
api.mdx: main's per-module table with the web-host row in place of the removed
serve-app-command; api/_meta.json follows; package.json keeps the web-host
tsconfig in typecheck.
Allow an event route under `src/events/**` to declare a `preflight` gate — `export { default as preflight } from './<name>.js'`, a sync or async function that receives the frozen `{ canonical, host, signal, terminal }` context and returns `'execute'`, `{ outcome: 'continue' }`, or `{ outcome: 'deny', reason }` — which the generated hook entry runs on the canonical event before the rendered route runtime, React, or any application provider loads. `inspect`, `validate`, `build`, and `dev` report `AB4840` when `preflight` is declared inline, exported more than once, re-exported from a bare package or under a binding other than `default`, unresolvable, cyclic, or not a function, naming the route module and, once a re-export was found, its specifier. Allow an executed event route to declare the provider keys it requires (`config.providers: ['<key>', …]`) so only that subset resolves, in the existing deterministic key/source order with `processLifetime` seeded first; a route without a declaration still resolves every conventional provider, `[]` mounts `processLifetime` alone, and `AB4841` reports a malformed declaration, a duplicate key, the reserved `processLifetime`, or a key that matches no discovered `src/providers/*` module — unknown keys list the project's provider keys. Export `EventPreflight`, `EventPreflightContext`, `EventPreflightResult`, `validateEventPreflightResult`, and `eventFamilyAllowsPreflightDeny` from `agent-bundle`, `agent-bundle/api`, and `agent-bundle/routes`. Export the payload-free `EventTraceEvent` union, `createEventTracer`, and `installEventTraceObserver` for developer tooling. (#618)
Move invalid `--port`, `--trials`, `dev --install-host`, and install or uninstall `<host>`, `--mode`, and `--scope` values in the `agent-bundle` CLI away from `AB5000` diagnostics and exit code 1 to Commander usage errors and exit code 2. (#615)
Copy file name to clipboardExpand all lines: docs/diagnostics.md
+53-1Lines changed: 53 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -30,7 +30,7 @@ even when no error diagnostic was reported.
30
30
|`AB4765`–`AB4766`| Artifact-hosted routed CLI: a target without the `cli` capability omits `bin/<name>.mjs`; a host-emitted file collides with it (see below). |
31
31
|`AB477x`| MCP App view compilation (`AB4770`: compile error with file, line, column and the bundler message; `AB4771`: compile warning; `AB4772`: emitted-size advisory; see below). |
32
32
|`AB490x`/`AB492x`| Conventional host components (#100 stage 2): rules `src/rules/*.mdc` (`AB4900`–`AB4908`) and commands `src/commands/*.md` (`AB4920`–`AB4928`), including per-host feature-set enforcement (`AB4907`/`AB4908`, `AB4927`/`AB4928`); see below. |
33
-
|`AB48xx`/`AB494x`| Route graph, state, layout (`AB4830`–`AB4832`), generated route declarations outside the TypeScript program (`AB4834`), route render budgets (`AB4835`), tool task support (`AB4836`), a route module that value-imports a compiler-carrying framework entry (`AB4837`), a CLI route `inputSchema` reference the static resolver cannot follow (`AB4838`) or that cycles (`AB4839`), and provider conventions (see below). |
33
+
|`AB48xx`/`AB494x`| Route graph, state, layout (`AB4830`–`AB4832`), generated route declarations outside the TypeScript program (`AB4834`), route render budgets (`AB4835`), tool task support (`AB4836`), a route module that value-imports a compiler-carrying framework entry (`AB4837`), a CLI route `inputSchema` reference the static resolver cannot follow (`AB4838`) or that cycles (`AB4839`), an event route's `preflight` gate export (`AB4840`), an event route's declared provider keys (`AB4841`), and provider conventions (see below). |
34
34
|`AB5000`| General CLI and adapter failures (see below). |
35
35
|`AB60xx`| Built-artifact validation, including schema documents and referenced files (`AB6005`: an emitted JavaScript module — a host-pack module or a package build `dist` bundle (`dist/bin/*.js`, the Flight workers, the `lib` entry), prebuilt payloads excepted — has an import that is neither a Node built-in nor a relative or `file:` specifier resolving to a listed regular file inside its tree, or a non-literal dynamic import; a `dist` finding names `dist/<path>`; `AB6011`/`AB6012`: a target's required pinned-schema document is missing or invalid; `AB6025`: a manifest-declared `logo` path is missing from the artifact or escapes the deploy tree; `AB6034`: emitted Skill Markdown has no instruction body; `AB6035`–`AB6038`: Agent Plugins portable validation, see below). |
36
36
|`AB6200`–`AB6202`| Workbench artifact inspection over published epochs: `AB6200` the epoch does not validate or its provenance is inconsistent, `AB6201` an epoch reference could not be released, `AB6202` unsafe runtime metadata (see below). |
@@ -1204,6 +1204,56 @@ graphs whose schemas are all inline keep their recorded digests.
1204
1204
Workbench route detail shows a route's contract origin and the other routes
1205
1205
sharing it.
1206
1206
1207
+
An event route (`src/events/<family>/*`) may add a **preflight gate** (#595):
1208
+
a named `preflight` export the generated hook entry runs after envelope
1209
+
decoding, host validation, and canonical event construction, and before any
1210
+
of the rendered route runtime — React, the RSC renderer, layouts, providers,
1211
+
state, notices — is loaded. The gate is sync or async, receives a frozen
1212
+
context of the `canonical` identity and payload the route would receive, the
1213
+
compiled host identity and native event name, the request `signal` owned by
1214
+
the hook deadline, and translated `terminal` capability metadata (never
1215
+
`native`, state, notices, lineage, providers, or
1216
+
the request context), and returns exactly one of `'execute'` (load the route
1217
+
runtime, resolve its declared providers, render), `{ outcome: 'continue' }`
1218
+
(pass through with no host decision), or `{ outcome: 'deny', reason }` (a
1219
+
denial projected through the family's canonical outcome rules;
1220
+
observation-only families cannot deny). `undefined`, an unknown outcome, an
1221
+
extra field, or an empty reason fails closed at hook time. A gate is only
1222
+
cheap when the compiler can bundle it on its own, so exactly one authoring
1223
+
form is accepted: a single `export { default as preflight } from './<name>.js'`
1224
+
in the route module, whose relative target (a `.js` specifier resolves to the
1225
+
`.ts`/`.tsx` source, as route imports do) is a readable module whose default
1226
+
export is a function — followed, like a route's default re-export, through an
1227
+
acyclic chain of relative default re-exports. The compiler records that module
1228
+
on the route's own graph node (`preflight` on the compiled route, part of the
1229
+
graph digest) and keeps it out of route discovery, so
1230
+
`src/events/tool/before.preflight.ts` beside `before.tsx` is application code
1231
+
the route names, never a second event route. A `preflight` declared inline in
1232
+
the route module (`export const preflight = …`, `export function preflight`)
1233
+
is rejected too: evaluating the route module evaluates its rendering and
1234
+
provider imports, the very cost the gate exists to avoid. Every rejected form
1235
+
is `AB4840`, once per route on the route module; the route compiles without a
1236
+
gate beside the error, and because the diagnostic is an error the build fails
1237
+
instead of silently taking the expensive path.
1238
+
1239
+
Provider laziness is declaration-driven (#595). Preflight materializes no
1240
+
application providers. An executed event route with no provider declaration
1241
+
resolves every conventional provider, as before; a route that declares the
1242
+
provider keys it requires — `config.providers: ['<key>', …]`, string literals
1243
+
inside the static config grammar — loads and resolves only that subset, still
1244
+
once per request, sequentially in the deterministic key-then-source order
1245
+
(never declaration order), fail-closed, with the framework-owned
1246
+
`processLifetime` seeded first. `[]` is a valid declaration that mounts
1247
+
`processLifetime` alone. Keys are the camel-cased `src/providers/<name>.*`
1248
+
stems the graph derives (`retry-policy.ts` is `retryPolicy`), the same keys
1249
+
the generated `AgentBundleProviders` declares; `processLifetime` is not one of
1250
+
them and must not be declared. The declaration is judged when the route graph
1251
+
compiles: a declaration that is not an array of string literals, a key listed
1252
+
twice, the reserved `processLifetime`, or a key naming no discovered provider
1253
+
module is `AB4841`, once per route with every defect in one message; a
1254
+
declaration with any defect selects nothing, so the build fails rather than
1255
+
resolving a provider set the author did not write.
1256
+
1207
1257
| Code | Severity | Trigger |
1208
1258
| --- | --- | --- |
1209
1259
|`AB4800`| error | An MCP server has both discovered route modules under `src/mcp/<id>/` and an existing entry claim (the conventional `src/mcp/<id>.ts` module, or a declared `entry`/`command`/`url`) without an explicit `routes.servers.<id>` mode. |
@@ -1246,6 +1296,8 @@ sharing it.
1246
1296
| `AB4837` | error | A route module of any kind except an App — a `src/cli/**` command, a `src/scripts/**` script, a tool, resource, or prompt route of a generated server, an event route — a layout, or a provider, or a module one of them reaches through relative value imports, imports `agent-bundle`, `agent-bundle/api`, `agent-bundle/config`, `agent-bundle/eval`, `agent-bundle/rstest`, `agent-bundle/test`, or `agent-bundle/test/browser` as a value (a static import whose binding is read at run time, `import 'agent-bundle/api'`, `import('agent-bundle/api')` with a literal specifier, or a non-type re-export). Those entries carry the compiler, and the generated executable is self-contained (#387): the bundler would inline the compiler and fail on the framework's runtime-relative module references (`Module not found: Can't resolve '../events'`), or the artifact validator would reject the inlined compiler's non-literal dynamic imports with `AB6005` — either way naming a generated file instead of the route (#558). Judged statically when the route graph compiles, so `inspect`, `validate`, `build`, and `dev` all report it, once per module, naming the route and the helper the import lives in. `import type`, `type`-qualified specifiers, and imports used only in type positions are elided by the bundler and never reported; routes of a server that is not generated (`custom`/`command`/`remote`, or an `AB4800` conflict) or of a CLI that is not generated (`conventional`, or an `AB4801` conflict) are never bundled, so they are not judged; likewise a layout that no bundled rendered route composes through (a worker imports only the layouts its routes reach: the tool, resource, and prompt routes of a generated server, the rendered `.tsx` commands of a generated CLI, and rendered `.tsx` scripts), and a provider in a project whose only executables are plain `.ts` scripts, which are bundled from their own source and mount none. Keep framework calls in a host process: expose an MCP App with `web.apps` and open it from the installed artifact with `<plugin> web`; keep other framework calls in host processes (`package.json` scripts, a hand-written `.mjs` run from the checkout). The bundle-safe entries stay allowed: `agent-bundle/app` (the browser MCP App client, a leaf with no Zod, Node, or compiler import), `agent-bundle/routes`, `agent-bundle/launch-env`, `agent-bundle/meta`, `agent-bundle/mcp-apps`, `agent-bundle/mcp-entry`, `agent-bundle/cli-entry`, `agent-bundle/terminal-capability`, and `agent-bundle/web-host`. |
1247
1297
| `AB4838` | error | A CLI route's `inputSchema` references a binding the static resolver cannot follow. The message is `CLI route <path> inputSchema: <chain> <reason>.` — the chain is the reference path from `inputSchema`, each step `<binding>`, or `<binding> (<module>)` when it crosses into another module (`inputSchema -> statusInputSchema (src/lib/protocol-schemas.ts) -> requestStatusSchema -> requestStatuses`), and the reason names the boundary: a specifier that `is not a relative module path`, one that `resolves outside the project` or `does not resolve to a module inside the project` (missing or unreadable), a target module that does not declare a top-level `export const <name>`, a binding that is not a top-level `const` (`let`/`var`, destructuring, a function, a class, a default or namespace import — the message says what it is), an identifier that `is neither a top-level const in this module nor a named import from a relative module`, or a dynamic initializer — one that is neither a method chain, an object or array literal, nor a static literal (`whose initializer is a call expression`, `a function expression`, `a template literal with substitutions`). Reported on the route module; the recovery names the supported forms — relative imports inside the project, `export const`, alias chains — then says to inspect again. Only CLI routes raise it, because only there the static contract is load-bearing: an MCP, script, or event route whose schema the resolver cannot follow compiles without a static contract, as an out-of-grammar inline schema does, and the runtime derives its MCP JSON Schema from the real zod object. A reference that resolves but whose schema leaves the grammar is `AB4814`. |
1248
1298
|`AB4839`| error | A CLI route's `inputSchema` reference chain is cyclic — `a` → `b` → `a`, within one module or across several: every visited `<module>#<binding>` is recorded and revisiting one stops the walk. The message is `CLI route <path> inputSchema: <chain> is a reference cycle.` and prints the cycle; it is reported on the route module, with the same recovery and the same CLI-only rule as `AB4838`. |
1299
+
| `AB4840` | error | An event route's `preflight` gate (#595) is not the one physically cheap form the compiler can bundle on its own. Rejected: `preflight` declared inline in the route module (`export const preflight = …`, `export function preflight`) or exported more than once; re-exported under a binding other than `default` (`export { gate as preflight } from './gate.js'`, `export { preflight } from './gate.js'`); re-exported from a non-relative specifier (a bare package such as `'@scope/gate'`); a relative target that is missing, unreadable, or part of a re-export cycle; a target default export that cannot be followed through an acyclic chain of relative default re-exports; or a target default export that is not a function the scan can see. The message names the route module and, once a re-export was found, its specifier. Judged statically when the route graph compiles, so `inspect`, `validate`, `build`, and `dev` all report it, once per route with the route module as `sourcePath`; the route compiles without a gate beside the error, and the build fails rather than silently taking the expensive rendered path. Write exactly `export { default as preflight } from './<name>.js'` in the route module, and make that module default-export one sync or async function receiving `{ canonical, host, signal, terminal }` and returning `'execute'`, `{ outcome: 'continue' }`, or `{ outcome: 'deny', reason }`. |
1300
+
|`AB4841`| error | An event route's static required-provider declaration (#595) does not select a known set of conventional providers: `config.providers` is not an array of provider-key strings; a key is declared more than once; a key is the reserved `processLifetime`; or a key matches no conventional provider the route graph discovered under `src/providers/`. The message names the route and every offending key. Declare each key exactly once, spelled as the camel-cased stem of its `src/providers/<name>.*` module, drop `processLifetime`, declare `[]` to mount `processLifetime` alone, or omit `config.providers` to preserve the all-provider compatibility default. |
1249
1301
|`AB4940`| error | A conventional provider module has no default export or its default export is not a function. Default-export a factory receiving `{ invocation, plugin, signal }`. |
1250
1302
|`AB4941`| error | Two provider filenames derive the same camel-cased provider key. Rename one file so every provider key is unique. |
1251
1303
|`AB4942`| error | A provider filename derives the reserved `processLifetime` key. Rename the file so its camel-cased key does not collide with the framework-owned provider. |
0 commit comments