Skip to content

Commit a8266cd

Browse files
fix(doctor): renumber the Cursor Agent Plugins launch proof to AB7326 (AB7325 is the Claude load-refusal code since #479)
1 parent 86ce9c7 commit a8266cd

17 files changed

Lines changed: 28 additions & 28 deletions

File tree

‎.changeset/426-cursor-agent-plugins-expansion.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
"agent-bundle": patch
33
---
44

5-
Expand Agent Plugins placeholders for Cursor at install time. The `install.mjs` emitted with a `portable` bundle now rewrites `mcp.json` in the `~/.cursor/plugins/local/<name>` copy — `${PLUGIN_ROOT}` to the absolute plugin root, `${PLUGIN_DATA}` to `~/.cursor/agent-bundle/plugin-data/<name>` (created), an omitted `cwd` to the plugin root, plugin-relative `./` commands to absolute paths, and `PLUGIN_ROOT`/`PLUGIN_DATA` into every stdio server's `env` — because Cursor 3.18.25 performs none of that resolution and every spec-shaped stdio server failed to spawn there. The bundle itself is untouched, the pre-expansion document is recorded in the install receipt (`cursorExpansion`), reruns stay idempotent and older unexpanded copies are replaced on the next run. `agent-bundle doctor --host cursor` validates the Agent Plugins contract (`AB7320`) against the recorded document and adds `AB7325` (`expanded` / `unexpanded` / `drifted`) for the launch proof; `cursor`-target bundles are never rewritten. (#482)
5+
Expand Agent Plugins placeholders for Cursor at install time. The `install.mjs` emitted with a `portable` bundle now rewrites `mcp.json` in the `~/.cursor/plugins/local/<name>` copy — `${PLUGIN_ROOT}` to the absolute plugin root, `${PLUGIN_DATA}` to `~/.cursor/agent-bundle/plugin-data/<name>` (created), an omitted `cwd` to the plugin root, plugin-relative `./` commands to absolute paths, and `PLUGIN_ROOT`/`PLUGIN_DATA` into every stdio server's `env` — because Cursor 3.18.25 performs none of that resolution and every spec-shaped stdio server failed to spawn there. The bundle itself is untouched, the pre-expansion document is recorded in the install receipt (`cursorExpansion`), reruns stay idempotent and older unexpanded copies are replaced on the next run. `agent-bundle doctor --host cursor` validates the Agent Plugins contract (`AB7320`) against the recorded document and adds `AB7326` (`expanded` / `unexpanded` / `drifted`) for the launch proof; `cursor`-target bundles are never rewritten. (#482)

‎docs/audits/2026-09-03-agent-plugins-cursor-ide-proof.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ the §7.2.1/§9 resolution itself, for the Cursor copy only:
178178
`{ pluginRoot, pluginData, documents: { "mcp.json": <shipped text> } }`.
179179
- `agent-bundle doctor --host cursor` validates the Agent Plugins contract
180180
(`AB7320`) against the shipped document from the receipt and proves the
181-
expansion (`AB7325`: `expanded`, `unexpanded` for a copy still in spec
181+
expansion (`AB7326`: `expanded`, `unexpanded` for a copy still in spec
182182
shape, `drifted` for a moved/duplicated/edited copy).
183183
- Provenance is `derived` everywhere it is reported
184184
(`portable-1.0.0.json` `plugin.cursorLocalInstall.placeholderExpansion`);

‎docs/diagnostics.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ even when no error diagnostic was reported.
3636
| `AB7010`–`AB7013` | npm prepack inventory, artifact freshness, package bin targets, and release-version agreement. |
3737
| `AB7200`–`AB7202`, `AB7210`–`AB7211` | Development rebuilds and live host surfaces: rebuild admission and phase failures, development host install sync, and the dev-epoch contract gate (see below). |
3838
| `AB7xxx` | Project preparation and development rebuilds. |
39-
| `AB7300`–`AB7326` | Read-only install Doctor: host probes, installed inventory, bundle comparison and registration proof, runtime endpoint health and identity, durable-state inventory, static bytes-at-rest validation, foreign-install detection (`AB7321`; see below), Cursor plugin hook registration / marketplace staging (`AB7322`–`AB7324`; see below), host load refusal (`AB7325`; see below), and the Cursor Agent Plugins launch proof (`AB7326`; see below). |
39+
| `AB7300`–`AB7326` | Read-only install Doctor: host probes, installed inventory, bundle comparison and registration proof, runtime endpoint health and identity, durable-state inventory, static bytes-at-rest validation, foreign-install detection (`AB7321`; see below), Cursor plugin hook registration / marketplace staging (`AB7322`–`AB7324`; see below), host load refusal (`AB7326`; see below), and the Cursor Agent Plugins launch proof (`AB7326`; see below). |
4040
| `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. |
4141
| `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). |
4242
| `AB8215`–`AB8218` | Workbench read-only host discovery route. |
@@ -879,7 +879,7 @@ The JSON report exposes the same facts: `hosts[].inventory.findings[].errors`,
879879
report prints the comparison as `installed copy: load failed (installed
880880
<version>, refused by the host: <errors>)`.
881881

882-
## Read-only Doctor Cursor Agent Plugins launch proof (`AB7325`)
882+
## Read-only Doctor Cursor Agent Plugins launch proof (`AB7326`)
883883

884884
Cursor 3.18.25 loads Agent Plugins 1.0.0 packages from
885885
`~/.cursor/plugins/local/<name>` but spawns their stdio servers without
@@ -900,4 +900,4 @@ placeholders itself.
900900

901901
| Code | Severity | Meaning | Recovery |
902902
| --- | --- | --- | --- |
903-
| `AB7325` | info / warning / error | Info (`launch.state = expanded`): the receipt's expansion still describes the installed copy — same plugin root, existing data directory, no placeholder left, absolute `cwd` and plugin-root `command`/`args` paths that exist, `PLUGIN_ROOT` / `PLUGIN_DATA` equal to the recorded values. Warning (`unexpanded`): an Agent Plugins install without a recorded expansion whose stdio servers still rely on the spec forms Cursor does not resolve (the message lists the forms per server); Cursor reports `spawn … ENOENT` / `MODULE_NOT_FOUND` for them. Error (`drifted`, entry `corrupt`): the installed `mcp.json` is not byte-identical to the expansion Doctor recomputes from the recorded document (edited, replaced, or removed after install), the recorded expansion names another plugin root (the copy was moved or duplicated), the data directory or an expanded path no longer exists, or the environment no longer carries the recorded values. Only a byte-identical copy has its recorded document validated by `AB7320`; a drifted copy is validated as the bytes on disk. Packages without stdio servers, and copies already carrying absolute paths with the §9.1 variables, produce no finding. | Reinstall with the bundle's emitted `install.mjs` at the copy's current location; the Cursor-target (`.cursor-plugin/plugin.json`) bundle is never rewritten and is not subject to this check. |
903+
| `AB7326` | info / warning / error | Info (`launch.state = expanded`): the receipt's expansion still describes the installed copy — same plugin root, existing data directory, no placeholder left, absolute `cwd` and plugin-root `command`/`args` paths that exist, `PLUGIN_ROOT` / `PLUGIN_DATA` equal to the recorded values. Warning (`unexpanded`): an Agent Plugins install without a recorded expansion whose stdio servers still rely on the spec forms Cursor does not resolve (the message lists the forms per server); Cursor reports `spawn … ENOENT` / `MODULE_NOT_FOUND` for them. Error (`drifted`, entry `corrupt`): the installed `mcp.json` is not byte-identical to the expansion Doctor recomputes from the recorded document (edited, replaced, or removed after install), the recorded expansion names another plugin root (the copy was moved or duplicated), the data directory or an expanded path no longer exists, or the environment no longer carries the recorded values. Only a byte-identical copy has its recorded document validated by `AB7320`; a drifted copy is validated as the bytes on disk. Packages without stdio servers, and copies already carrying absolute paths with the §9.1 variables, produce no finding. | Reinstall with the bundle's emitted `install.mjs` at the copy's current location; the Cursor-target (`.cursor-plugin/plugin.json`) bundle is never rewritten and is not subject to this check. |

‎docs/framework-mode.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ that expansion itself in the `~/.cursor/plugins/local/<name>` copy of
504504
as `PLUGIN_DATA`, plugin-root `cwd`, resolved `./` command, `PLUGIN_ROOT` /
505505
`PLUGIN_DATA` in each stdio server's `env`), keeps the shipped document in the
506506
install receipt (`cursorExpansion`), and `doctor` proves the expansion with
507-
`AB7325` while validating the Agent Plugins contract against the shipped
507+
`AB7326` while validating the Agent Plugins contract against the shipped
508508
document. The bundle stays spec-conformant; the provenance is `derived`.
509509

510510
The framework CLI performs those same operations:
@@ -562,6 +562,6 @@ plugin's manifest hook registration as `registered`, `stale` (a
562562
unparsable; `AB7324` reports a staged marketplace as imported or still
563563
awaiting the Customize step, and `doctor --from` resolves a marketplace-mode
564564
bundle to that staged copy instead of reporting it missing. For Agent Plugins
565-
installs, `AB7325` reports the installer's placeholder expansion as
565+
installs, `AB7326` reports the installer's placeholder expansion as
566566
`expanded`, `unexpanded` (spec forms Cursor cannot launch), or `drifted`
567567
(moved, duplicated, or edited after the expansion was recorded).

‎packages/agent-bundle/README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ variables; omitted `cwd` → home directory; `./` commands → workspace folder)
203203
rewrites `mcp.json` in that copy only with absolute paths
204204
(`PLUGIN_DATA` = `~/.cursor/agent-bundle/plugin-data/<name>`, created), keeps
205205
the shipped document in the install receipt (`cursorExpansion`), and
206-
`agent-bundle doctor --host cursor` proves the expansion (`AB7325`). The bundle
206+
`agent-bundle doctor --host cursor` proves the expansion (`AB7326`). The bundle
207207
itself stays spec-conformant for other Agent Plugins clients.
208208

209209
Cursor installation is user-scoped. Claude also accepts `--scope project` and

‎packages/agent-bundle/src/adapters/capabilities/portable-1.0.0.json‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@
7777
"2026-09-02: Cursor 3.18.25 does not expand ${PLUGIN_ROOT} in cwd or args and does not default an omitted cwd to the plugin root (spec 7.2.1/9.2 MUSTs), so spec-conformant stdio servers fail to launch there; its proprietary ${CURSOR_PLUGIN_ROOT} expands and connects.",
7878
"2026-09-02: With a launchable configuration the Cursor IDE completed the stdio handshake (connect_success with stable heartbeat), so the launch pipeline itself consumes this format.",
7979
"2026-09-03: Re-verified on the same Cursor 3.18.25 build (realCommit 280eca2911f1…af3; no newer stable release): the cwd, args, and default-cwd gaps reproduce, and single-variable probes additionally show ${PLUGIN_ROOT}/${PLUGIN_DATA} unexpanded in env values (spec 9.2), the reserved PLUGIN_ROOT/PLUGIN_DATA subprocess variables absent (spec 9.1), and plugin-relative ./ commands resolved against the workspace folder (spec 7.2.1); recorded with log excerpts and captures in docs/audits/2026-09-03-agent-plugins-cursor-ide-proof.md; not submitted to Cursor by maintainer decision.",
80-
"2026-09-03: framework-side support for the Cursor gap (#426): the emitted install.mjs detects an Agent Plugins pack (root plugin.json with an agent-plugins.org $schema, no .cursor-plugin/plugin.json) and rewrites mcp.json in the ~/.cursor/plugins/local/<name> copy only — ${PLUGIN_ROOT} → the absolute plugin root, ${PLUGIN_DATA} → ~/.cursor/agent-bundle/plugin-data/<name> (created by the installer), an omitted cwd → the plugin root, ./ commands → absolute paths under it, and PLUGIN_ROOT/PLUGIN_DATA added to every stdio server's env — because Cursor's spawn honours absolute command, args, cwd and env verbatim (the control run that connected). The bundle stays spec-conformant; the pre-expansion mcp.json is kept in the install receipt (cursorExpansion) and Doctor validates it against the Agent Plugins contract while AB7325 proves the expanded paths (expanded / unexpanded / drifted). Provenance: derived — Cursor still expands nothing itself, so the pathTokens rows above describe the bundle, not what Cursor resolves."
80+
"2026-09-03: framework-side support for the Cursor gap (#426): the emitted install.mjs detects an Agent Plugins pack (root plugin.json with an agent-plugins.org $schema, no .cursor-plugin/plugin.json) and rewrites mcp.json in the ~/.cursor/plugins/local/<name> copy only — ${PLUGIN_ROOT} → the absolute plugin root, ${PLUGIN_DATA} → ~/.cursor/agent-bundle/plugin-data/<name> (created by the installer), an omitted cwd → the plugin root, ./ commands → absolute paths under it, and PLUGIN_ROOT/PLUGIN_DATA added to every stdio server's env — because Cursor's spawn honours absolute command, args, cwd and env verbatim (the control run that connected). The bundle stays spec-conformant; the pre-expansion mcp.json is kept in the install receipt (cursorExpansion) and Doctor validates it against the Agent Plugins contract while AB7326 proves the expanded paths (expanded / unexpanded / drifted). Provenance: derived — Cursor still expands nothing itself, so the pathTokens rows above describe the bundle, not what Cursor resolves."
8181
],
8282
"legacySse": {
8383
"reason": "2026-09-02: Agent Plugins 1.0.0 §7.2.1 defines the deprecated HTTP+SSE variant as OPTIONAL for clients; the compiler emits only the required modern transports and rejects a legacy transport with AB4339 (https://agent-plugins.org/specification).",
@@ -156,11 +156,11 @@
156156
"placeholderExpansion": {
157157
"evidence": [
158158
"2026-09-02/03: Cursor 3.18.25 (docs/audits/2026-09-03-agent-plugins-cursor-ide-proof.md) fails every spec-shaped stdio launch (cwd \"${PLUGIN_ROOT}\" → spawn node ENOENT; args \"${PLUGIN_ROOT}/…\" → MODULE_NOT_FOUND under $HOME; omitted cwd → $HOME; env values and the §9.1 variables unexpanded/absent; \"./…\" commands resolved against the workspace) while the same server with absolute paths connects (connect_success, stable heartbeat).",
159-
"2026-09-03: the emitted install.mjs performs that expansion for the Cursor copy at install time and records it in the receipt; tests/install-surface.test.ts (bundle untouched, copy expanded, idempotent rerun, same-version re-expansion, older unexpanded copies repaired, skills-only and Cursor Plugin bundles untouched), tests/doctor.test.ts (AB7325 unexpanded → expanded → drifted → moved) and the portable host-install proof (isolated Cursor home, Doctor AB7325 info) pin it."
159+
"2026-09-03: the emitted install.mjs performs that expansion for the Cursor copy at install time and records it in the receipt; tests/install-surface.test.ts (bundle untouched, copy expanded, idempotent rerun, same-version re-expansion, older unexpanded copies repaired, skills-only and Cursor Plugin bundles untouched), tests/doctor.test.ts (AB7326 unexpanded → expanded → drifted → moved) and the portable host-install proof (isolated Cursor home, Doctor AB7326 info) pin it."
160160
],
161161
"installer": "install.mjs (emitted with the portable bundle)",
162162
"provenance": "derived",
163-
"reason": "Cursor 3.18.25 expands no Agent Plugins placeholder, provides no PLUGIN_ROOT/PLUGIN_DATA, defaults an omitted cwd to the home directory and resolves ./ commands against the workspace (spec §7.2.1/§9); the emitted installer rewrites mcp.json in the ~/.cursor/plugins/local/<name> copy with absolute paths (PLUGIN_DATA = ~/.cursor/agent-bundle/plugin-data/<name>, created), keeps the shipped document in the receipt, and Doctor proves the expanded paths (AB7325). Never claimed as Cursor behaviour: the bundle itself still relies on the consuming client.",
163+
"reason": "Cursor 3.18.25 expands no Agent Plugins placeholder, provides no PLUGIN_ROOT/PLUGIN_DATA, defaults an omitted cwd to the home directory and resolves ./ commands against the workspace (spec §7.2.1/§9); the emitted installer rewrites mcp.json in the ~/.cursor/plugins/local/<name> copy with absolute paths (PLUGIN_DATA = ~/.cursor/agent-bundle/plugin-data/<name>, created), keeps the shipped document in the receipt, and Doctor proves the expanded paths (AB7326). Never claimed as Cursor behaviour: the bundle itself still relies on the consuming client.",
164164
"state": "supported"
165165
}
166166
},

‎packages/agent-bundle/src/install/cursor-agent-plugins-launch.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export interface InspectCursorAgentPluginsLaunchOptions {
5050
readonly caseInsensitivePaths?: boolean;
5151
}
5252

53-
const DIAGNOSTIC_CODE = 'AB7325';
53+
const DIAGNOSTIC_CODE = 'AB7326';
5454
const REINSTALL_RECOVERY =
5555
"Reinstall the package with its bundle's emitted `install.mjs`, which expands the Agent Plugins placeholders for the Cursor copy " +
5656
'(absolute plugin root and data directory, plugin-root `cwd`, resolved `./` command, `PLUGIN_ROOT`/`PLUGIN_DATA` environment) and records them in the receipt.';

‎packages/agent-bundle/src/install/doctor.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ const installedCursorStaticIssues = async (
605605
target: 'cursor',
606606
});
607607
if (!isAgentPluginsManifest(installed)) return symlinks;
608-
// The Cursor copy of an expanded package is conformant only as the bundle shipped it (AB7325 proves the expansion).
608+
// The Cursor copy of an expanded package is conformant only as the bundle shipped it (AB7326 proves the expansion).
609609
const documents = launch?.documents;
610610
const [portable, containment] = await Promise.all([
611611
validatePortablePluginFiles({

‎packages/agent-bundle/src/install/surface.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ const portableInstructions = (): string[] => [
154154
'(created by the installer), an omitted `cwd` becomes the plugin root, `./` commands resolve against',
155155
'it, and every stdio server gains `PLUGIN_ROOT` / `PLUGIN_DATA` in its environment. The bundle itself',
156156
`stays spec-conformant; the pre-expansion document is kept in \`${installReceiptFile}\` (\`cursorExpansion\`),`,
157-
'and `agent-bundle doctor --host cursor` verifies the expanded paths (`AB7325`). Nothing is changed for',
157+
'and `agent-bundle doctor --host cursor` verifies the expanded paths (`AB7326`). Nothing is changed for',
158158
'other Agent Plugins clients, which expand the placeholders themselves.',
159159
'',
160160
'### Reinstall after a same-version rebuild',

‎packages/agent-bundle/tests/doctor.test.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -312,12 +312,12 @@ it('validates root plugin.json installs that declare an Agent Plugins schema aga
312312
}
313313
});
314314

315-
it('proves Agent Plugins stdio launch on Cursor: unexpanded spec forms warn, the emitted installer\'s expansion is verified, drift is corrupt (AB7325)', async () => {
315+
it('proves Agent Plugins stdio launch on Cursor: unexpanded spec forms warn, the emitted installer\'s expansion is verified, drift is corrupt (AB7326)', async () => {
316316
const fixture = await temporaryDoctor();
317317
const installRoot = join(fixture.home, '.cursor', 'plugins', 'local');
318318
const pluginSchema = 'https://agent-plugins.org/schemas/1.0.0/plugin.schema.json';
319319
const mcpSchema = 'https://agent-plugins.org/schemas/1.0.0/mcp.schema.json';
320-
const ab7325 = (report: DoctorReport) => report.diagnostics.filter((entry) => entry.code === 'AB7325');
320+
const ab7325 = (report: DoctorReport) => report.diagnostics.filter((entry) => entry.code === 'AB7326');
321321
const ab7320Errors = (report: DoctorReport) => report.diagnostics.filter((entry) => entry.code === 'AB7320' && entry.severity === 'error');
322322
const doctor = () => runDoctor({ endpointDirectory: fixture.endpointDirectory, home: fixture.home, hosts: ['cursor'] });
323323
try {

0 commit comments

Comments
 (0)