refactor: migrate cursor to the target registry - #14
Merged
Conversation
Re-checking the originally planned Cursor "fixes" against the vendored plugin.schema.json / marketplace.schema.json (this repo's own conformance oracle, already passing against the current shape) showed they were wrong: - displayName/category/tags ARE valid plugin.json fields per the schema (additionalProperties: false, and they're explicitly listed) — not marketplace-entry-only fields as previously assumed. - Marketplace `owner` is genuinely optional (required: ["name", "plugins"] does not include it) — not required as previously assumed. Moving category/tags to the marketplace entry would have been actively wrong: entries only allow name/source/description (additionalProperties: false). None of that is changed here. What this commit actually does: - Migrates cursor onto PluginTargetDefinition, preserving every existing field and behavior (verified by the vendored-schema conformance test staying green). - Fixes one genuine, low-risk issue: the manifest builder's own hardcoded default-components list could diverge from this target's actual defaultComponents (components.ts). Replaced both with one list of schema-valid pointer fields, checked directly against the plugin's real resolved componentDirs — eliminates the divergence risk with no observable behavior change (confirmed via a new test exercising the one case that could have differed: an explicit `components: [...]` override). - Ports update-check's hook-injection into the new shared engine (src/targets/engine.ts), which previously only existed in the legacy emitCursor/emitClaude path — migrating cursor without this would have silently dropped update-check support. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
buildPluginManifest used the target-level `version` param directly instead of `pluginConfig.version ?? version`, silently dropping a per-plugin version override — a real regression from the pre-migration behavior, caught by porting the equivalent test from the claude migration (no test previously covered this for cursor specifically). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Jul 26, 2026
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Migrates the
cursortarget ontoPluginTargetDefinition(see #13). No behavior change — the originally planned "fixes" for Cursor turned out to be wrong once checked against this repo's own vendored conformance oracle (tests/fixtures/cursor/*.schema.json), which was already passing against the current shape:displayName/category/tagsare validplugin.jsonfields (the schema explicitly lists them, withadditionalProperties: false) — not marketplace-entry-only fields as I'd assumed from docs research.owneris genuinely optional (required: ["name", "plugins"]doesn't include it).category/tagsonto the marketplace entry — the original plan — would have been actively wrong: entries only allowname/source/description(alsoadditionalProperties: false).The tell I should have caught before writing the plan: a docs-derived "fix" that would break an already-oracle-verified passing test is a signal the fix is wrong, not the test. None of that field-placement stuff is touched here.
What this PR actually does:
defaultComponents. Unified to one list of schema-valid pointer fields, checked against the plugin's real resolved component set. No observable behavior change (confirmed via a new test on the one case that could have differed — an explicitcomponents: [...]override).src/targets/engine.ts) — this only existed in the legacyemitCursor/emitClaudepath before. Migrating cursor without doing this would have silently dropped update-check support for it.Test plan
displayName/category/tagspreserved inplugin.json; an explicitcomponents: ["skills", "commands"]override correctly gets acommandspointernpm run checkgreen — 58/58 tests, including the vendored-schema conformance test and the update-check conformance test (both exercise the new registry path now)claude plugin validate --strictdirectly (the real oracle) — a plugin.json with onlynamefails--stricton missing version/description/author warnings-as-errors, meaning pluginpack's existing stricter validation was already correct. That fix is dropped too; the claude migration (next PR) will be a pure structural port with no behavior change.🤖 Generated with Claude Code