Summary
agent-bundle doctor reports a freshly installed Cursor plugin as invalid, three times, even though the install came straight from a bundle that agent-bundle validate accepted and install.mjs wrote byte-for-byte.
AB7320: Static validation of cursor bytes at "/home/zack/.cursor/plugins/local/cargo-hauler" reported AB6027: hooks/hooks.json/hooks: must NOT have additional properties.
Recovery: Reinstall the Cursor plugin from a freshly validated bundle, then rerun Doctor.
(repeated 3× — presumably once per hook event.)
Cause
The plugin target emits one bundle for Claude, Codex, and Cursor. The bundle's hooks/ directory contains both hook manifests:
hooks/hooks.json — Claude format (PreToolUse/PostToolUse/Stop, ${CLAUDE_PLUGIN_ROOT}), referenced by .claude-plugin/plugin.json
hooks/hooks-cursor.json — Cursor format (preToolUse/postToolUse/stop, version: 1, ${CURSOR_PLUGIN_ROOT}), referenced by .cursor-plugin/plugin.json → "hooks": "./hooks/hooks-cursor.json"
Doctor's Cursor static validation validates hooks/hooks.json against the Cursor hooks schema regardless of what .cursor-plugin/plugin.json#hooks points to. The PascalCase Claude event names are the "additional properties". The file the Cursor loader actually reads (hooks-cursor.json) is valid.
Expected
Doctor should validate the hooks file named by each host manifest's hooks field, and only that file. (The emitter could alternatively avoid placing the other host's manifest at the assumed path, but the manifest-driven lookup is the right fix: the install tree is exactly what the framework emitted.)
Repro
cargo-hauler 0.3.5 (framework mode, targets: ['plugin', 'portable'], three event routes with targets: ['plugin']), agent-bundle 0.0.0-preview-105c65d:
pnpm build && node artifact/plugin/install.mjs # installs to ~/.cursor/plugins/local/cargo-hauler
pnpm exec agent-bundle doctor # → 3× AB7320/AB6027 as above
jq .hooks ~/.cursor/plugins/local/cargo-hauler/.cursor-plugin/plugin.json # "./hooks/hooks-cursor.json"
The suggested recovery (reinstall from a validated bundle) cannot resolve it, since that is exactly what was done.
Also observed in the same run (minor)
AB7303 for Claude and Codex ("no pinned read-only inventory verb") is counted as an error-level finding; it is a known framework limitation rather than a problem with the install, so info/warning level would keep the Doctor summary error count meaningful.
Summary
agent-bundle doctorreports a freshly installed Cursor plugin as invalid, three times, even though the install came straight from a bundle thatagent-bundle validateaccepted andinstall.mjswrote byte-for-byte.(repeated 3× — presumably once per hook event.)
Cause
The
plugintarget emits one bundle for Claude, Codex, and Cursor. The bundle'shooks/directory contains both hook manifests:hooks/hooks.json— Claude format (PreToolUse/PostToolUse/Stop,${CLAUDE_PLUGIN_ROOT}), referenced by.claude-plugin/plugin.jsonhooks/hooks-cursor.json— Cursor format (preToolUse/postToolUse/stop,version: 1,${CURSOR_PLUGIN_ROOT}), referenced by.cursor-plugin/plugin.json→"hooks": "./hooks/hooks-cursor.json"Doctor's Cursor static validation validates
hooks/hooks.jsonagainst the Cursor hooks schema regardless of what.cursor-plugin/plugin.json#hookspoints to. The PascalCase Claude event names are the "additional properties". The file the Cursor loader actually reads (hooks-cursor.json) is valid.Expected
Doctor should validate the hooks file named by each host manifest's
hooksfield, and only that file. (The emitter could alternatively avoid placing the other host's manifest at the assumed path, but the manifest-driven lookup is the right fix: the install tree is exactly what the framework emitted.)Repro
cargo-hauler 0.3.5 (framework mode,
targets: ['plugin', 'portable'], three event routes withtargets: ['plugin']), agent-bundle0.0.0-preview-105c65d:The suggested recovery (reinstall from a validated bundle) cannot resolve it, since that is exactly what was done.
Also observed in the same run (minor)
AB7303 for Claude and Codex ("no pinned read-only inventory verb") is counted as an error-level finding; it is a known framework limitation rather than a problem with the install, so info/warning level would keep the
Doctor summaryerror count meaningful.