diff --git a/.changeset/closed-audit-g3-template-version.md b/.changeset/closed-audit-g3-template-version.md new file mode 100644 index 000000000..72c6036a6 --- /dev/null +++ b/.changeset/closed-audit-g3-template-version.md @@ -0,0 +1,5 @@ +--- +"create-agent-bundle": patch +--- + +Scaffolded `agent-bundle.config.ts` no longer repeats the deprecated `plugin.version`; every template derives its release version from `package.json`, matching the #94 identity contract. diff --git a/.gitignore b/.gitignore index ab57b83ed..28957c855 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ coverage/ artifacts/ *.log examples/audiobook-curator/artifact/ +examples/worktree-proximity/artifact/ # Aborted runtime-playground fixture workspaces .runtime-playground-*/ diff --git a/README.md b/README.md index fa2703dd5..f9fcb4ff5 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Or describe the plugin by hand in `agent-bundle.config.ts` at the project root: import { defineConfig } from 'agent-bundle/config'; export default defineConfig({ - plugin: { name: 'my-plugin', version: '0.1.0', description: 'What it does.' }, + plugin: { name: 'my-plugin', description: 'What it does.' }, // version comes from package.json targets: ['plugin'], skills: ['src/skills/*'], hooks: { sessionStart: { handler: './src/session-start.ts' } }, diff --git a/docs/diagnostics.md b/docs/diagnostics.md index 6e958a1d9..de389f3bc 100644 --- a/docs/diagnostics.md +++ b/docs/diagnostics.md @@ -29,8 +29,11 @@ gate a build, a validation, or a dev rebuild. | `AB7010`–`AB7013` | npm prepack inventory, artifact freshness, package bin targets, and release-version agreement. | | `AB7xxx` | Project preparation and development rebuilds. | | `AB7300`–`AB7320` | Read-only install Doctor: host probes, installed inventory, bundle comparison and registration proof, runtime endpoint health and identity, durable-state inventory, and static bytes-at-rest validation. | +| `AB8200`–`AB8209` | Workbench development runtime routes (`/api/runtime/**`): `AB8200` development runtime provider configuration, load, or lifecycle failure, `AB8201` runtime/session/run not available, `AB8202` invalid route path, `AB8203` invalid request shape, `AB8204` stale runtime generation or MCP session revision (409), `AB8205` runtime request could not be completed, `AB8206` Workbench runtime client failure, `AB8207` Agent Document decoding needs the optional `@agent-bundle/runtime` peer (503), `AB8208` stored Flight could not be decoded as an Agent Document (409), `AB8209` decoded Agent Document over the 16 MiB budget (413) or an invalid document response. | +| `AB8210`–`AB8214` | Workbench semantic lifecycle replay routes (`/api/lifecycles`, `/api/lifecycles/replays`): `AB8210` invalid path, `AB8211` malformed replay request or native envelope (400, carries the shared validator message), `AB8212` replay unavailable or could not be completed, `AB8213` stale manifest binding (409; the page repairs it with refresh → explicit re-run), `AB8214` replay over the 16 MiB budget (413). | | `AB8215`–`AB8218` | Workbench read-only host discovery route. | | `AB8219`–`AB8223` | Workbench live MCP probe route (user-initiated, read-only initialize + tools/list): `AB8219` invalid path, `AB8220` invalid request/method, `AB8221` probe target not found, `AB8222` response over the 16 MiB budget, `AB8223` probe unavailable. | +| `AB8233`–`AB8235` | Workbench browser-side strict decoders rejecting a dev-server response: `AB8233` lifecycle replay, `AB8234` host discovery, `AB8235` MCP probe report. | | `AB8xxx` | Development server configuration. | | `AB9xxx` | Eval selection, harnesses, and persisted runs. | diff --git a/docs/entry-conventions.md b/docs/entry-conventions.md index d53a037b2..c3c5c6377 100644 --- a/docs/entry-conventions.md +++ b/docs/entry-conventions.md @@ -80,6 +80,7 @@ entries carry `provenance.kind: 'conventional'` in the normalized model. | `src/scripts/.ts` | Plain script compiled to `scripts/.mjs` in every selected target artifact — the same pipeline explicit `scripts` entries use, with ordinary Node stdout/stderr semantics. A `scripts` entry that references the file claims it. Nested modules are hard errors (`AB4808`). | Prefix a path segment with `_`, or claim the file with an explicit `scripts` entry | | `src/scripts/.tsx` | Rendered script: the async default component receives `{ argv, signal }` and renders through the Agent renderer with the CLI output contract (`--json`, `--ndjson`, TTY progress, piped Markdown). Compiles to `scripts/.mjs` plus a `scripts/-flight.mjs` react-server worker. The extension is the explicit, visible contract — plain `.ts` scripts are never wrapped in React behavior, and explicit `scripts` config entries stay plain regardless of extension. | Rename to `.ts`, prefix a path segment with `_`, or claim the file with an explicit `scripts` entry | | `src/cli/**/*.{ts,tsx}` | Routed CLI commands compiled into one collision-checked command graph and one generated package executable named after `plugin.name` (superseding the `src/cli.ts` bin convention for the project). Nesting is identity: `src/cli/library/audit.ts` runs as ` library audit`. Plain `.ts` commands execute directly and print one canonical JSON line; `.tsx` commands render through the dispatcher with the four output modes. | `bin: false`, `routes.cli: 'conventional'`, or prefix a path segment with `_` | +| `src/events//.{ts,tsx}`, `src/events/stop.{ts,tsx}` | Semantic event route: the path is the canonical event family (`src/events/tool/after.tsx` is `tool/after`; `stop` is the one top-level family) and must be one of the admitted `canonicalAgentEvents`. The optional static `config` (`AgentEventRouteConfig`: `targets`, `tools`, `runtime: 'shared' \| 'standalone'`, `fallback`, `delivery`, `timeoutMs`) restricts hosts and selects the execution mode; the async default Server Component receives `AgentEventRouteProps` (`{ canonical, native, signal }`) and returns `Agent.*` output that the selected host adapter encodes into its native hook envelope. Application code never branches on host JSON or emits native hook documents; per-host support is a capability state (`supported`/`degraded`/`unavailable`/`prohibited`) surfaced by `inspect` and enforced at build time (`AB4817`, `AB4823`–`AB4825`). | Restrict `config.targets`, or prefix a path segment with `_` | | `src/state.ts` | Project state definition: default-exports `defineState({ ... })`; generated MCP, routed-CLI, and rendered-script request scopes mount `(await agent()).state` and `.notices`. | `state: false`, or rename the file to `_state.ts` | | `src/providers/.{ts,tsx}` | Request context provider: default-exports a factory receiving `{ invocation, signal }`; its value is mounted at `(await agent()).providers.` for generated MCP and event routes, projected MCP commands, rendered routed CLI commands, and rendered scripts. | Prefix the file with `_` | diff --git a/docs/framework-mode.md b/docs/framework-mode.md index 2910fcf94..3c1875149 100644 --- a/docs/framework-mode.md +++ b/docs/framework-mode.md @@ -9,7 +9,9 @@ Agent Bundle has one newcomer model: `src/commands/*.md`, and `src/rules/*.mdc`. Top-level `assets/` holds static resources, and `agent-bundle.config.ts` stays at the project root. 2. **One small flat config.** `agent-bundle.config.ts` holds project identity, - targets, and policy that no route file can own. + targets, and policy that no route file can own. The release version is + not repeated there: `package.json` is the single version source + (`plugin.version` is deprecated; see [Diagnostics](diagnostics.md#release-identity-ab4001-ab4008ab4011-ab4013)). 3. **JSX = rendering.** An executable route is one async default Server Component. It does the work and returns `Agent.*`; there is no public `execute`/`render` split. @@ -22,7 +24,7 @@ The complete conventional config is usually: import { defineConfig } from 'agent-bundle/config'; export default defineConfig({ - plugin: { description: 'Evidence-backed project tools.', name: 'my-plugin', version: '0.1.0' }, + plugin: { description: 'Evidence-backed project tools.', name: 'my-plugin' }, targets: ['portable', 'codex', 'claude'], }); ``` diff --git a/packages/create-agent-bundle/templates/cli-tool/agent-bundle.config.ts b/packages/create-agent-bundle/templates/cli-tool/agent-bundle.config.ts index 8b53932d8..d59b34bcb 100644 --- a/packages/create-agent-bundle/templates/cli-tool/agent-bundle.config.ts +++ b/packages/create-agent-bundle/templates/cli-tool/agent-bundle.config.ts @@ -1,10 +1,10 @@ import { defineConfig } from 'agent-bundle'; export default defineConfig({ + // No `version` field: package.json is the single release-version source. plugin: { description: 'A command-line tool scaffolded from the cli-tool template.', name: 'my-agent-plugin', - version: '0.1.0', }, // Optional: move the build artifact root (default `dist`); the CLI // `--output` flag still wins. diff --git a/packages/create-agent-bundle/templates/mcp-server/agent-bundle.config.ts b/packages/create-agent-bundle/templates/mcp-server/agent-bundle.config.ts index 82340a92b..074b3f72c 100644 --- a/packages/create-agent-bundle/templates/mcp-server/agent-bundle.config.ts +++ b/packages/create-agent-bundle/templates/mcp-server/agent-bundle.config.ts @@ -2,10 +2,10 @@ import { defineConfig } from 'agent-bundle'; export default defineConfig({ lib: './src/status.ts', + // No `version` field: package.json is the single release-version source. plugin: { description: 'A stdio MCP server plugin scaffolded from the mcp-server template.', name: 'my-agent-plugin', - version: '0.1.0', }, scripts: { 'check-status': './src/scripts/check-status.ts', diff --git a/packages/create-agent-bundle/templates/minimal/agent-bundle.config.ts b/packages/create-agent-bundle/templates/minimal/agent-bundle.config.ts index 846b3db20..0ee02a4ae 100644 --- a/packages/create-agent-bundle/templates/minimal/agent-bundle.config.ts +++ b/packages/create-agent-bundle/templates/minimal/agent-bundle.config.ts @@ -3,10 +3,10 @@ import { defineConfig } from 'agent-bundle'; export default defineConfig({ // No `skills` field needed: every `src/skills//SKILL.md` directory is // discovered by convention. Declare `skills:` only to override the layout. + // No `version` field: package.json is the single release-version source. plugin: { description: 'A skills-only agent plugin scaffolded from the minimal template.', name: 'my-agent-plugin', - version: '0.1.0', }, // Optional: move the build artifact root (default `dist`); the CLI // `--output` flag still wins. diff --git a/packages/create-agent-bundle/tests/scaffold.test.ts b/packages/create-agent-bundle/tests/scaffold.test.ts index 9bbf4772d..a241cc1eb 100644 --- a/packages/create-agent-bundle/tests/scaffold.test.ts +++ b/packages/create-agent-bundle/tests/scaffold.test.ts @@ -230,6 +230,22 @@ describe('scaffold', () => { } }); + for (const template of ['minimal', 'mcp-server', 'cli-tool'] as const) { + it(`declares the ${template} release version only in package.json`, async () => { + const { root } = await scaffoldTemplate(template); + try { + const manifest = JSON.parse(await readFile(join(root, 'package.json'), 'utf8')) as { + readonly version?: string; + }; + expect(manifest.version).toBe('0.1.0'); + const config = await readFile(join(root, 'agent-bundle.config.ts'), 'utf8'); + expect(config).not.toMatch(/\bversion:/u); + } finally { + await rm(root, { force: true, recursive: true }); + } + }); + } + it('writes the selected targets into the config', async () => { const { root } = await scaffoldTemplate('minimal', { targets: ['portable', 'cursor'] }); try {