Skip to content

refactor: migrate claude to the target registry (no behavior change) - #19

Merged
steve-calvert-glean merged 4 commits into
mainfrom
refactor/claude-target-registry
Jul 26, 2026
Merged

refactor: migrate claude to the target registry (no behavior change)#19
steve-calvert-glean merged 4 commits into
mainfrom
refactor/claude-target-registry

Conversation

@steve-calvert-glean

Copy link
Copy Markdown
Contributor

Recreated after #15 was auto-closed when its stacked base branch was deleted by the #14 squash-merge (GitHub can't reopen a PR whose base branch no longer exists — the branch and commits were never lost). Same content as #15.

Summary

  • Ports emitClaude/validateClaude into src/targets/claude.ts as a PluginTargetDefinition, verified directly against claude plugin validate --strict: a minimal manifest with only name fails that check, confirming the existing version/description/author.name requirements already match the real CLI. No validation behavior change — this is a structural port.
  • Applies the per-plugin version override in buildPluginManifest (pluginConfig.version ?? version) from the start, avoiding the bug just fixed on cursor's copy of this pattern in refactor: migrate cursor to the target registry #14 (a new regression test covers this: "applies per-target and per-plugin version overrides").
  • Adds @deprecated markers to the now-superseded emitClaude/validateClaude, matching copilot/antigravity's already-migrated pattern.

Test plan

  • npm run typecheck
  • npm run lint
  • npm test (59/59 passing, including claude's pre-existing version-override regression test)
  • npm run build
  • node dist/cli.js docs --check

steve-calvert-glean and others added 3 commits July 26, 2026 13:42
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>
Ports emitClaude/validateClaude into src/targets/claude.ts as a
PluginTargetDefinition, verified directly against `claude plugin
validate --strict`: a minimal manifest with only `name` fails that
check, confirming the existing version/description/author.name
requirements already match the real CLI rather than over-constraining
it.

Applies the per-plugin version override in buildPluginManifest
(pluginConfig.version ?? version) up front, matching the identical fix
just made to cursor's copy of this pattern.
@steve-calvert-glean steve-calvert-glean added the internal Internal refactoring, cleanup, or maintenance work label Jul 26, 2026
…t-registry

# ------------------------ >8 ------------------------
# Do not modify or remove the line above.
# Everything below it will be ignored.
#
# Conflicts:
#	src/targets/registry.ts
@steve-calvert-glean
steve-calvert-glean merged commit 645dbc0 into main Jul 26, 2026
1 check passed
@steve-calvert-glean
steve-calvert-glean deleted the refactor/claude-target-registry branch July 26, 2026 23:11
Comment thread src/targets/claude.ts

defaultComponents: ["skills", "agents", "hooks", "scripts", "assets"],

resolvePluginPath: (pluginName, pluginConfig, targetConfig) =>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: In src/targets/claude.ts, resolvePluginPath does not normalize the computed pluginPath with toPosix(), unlike the legacy emitClaude and the migrated Copilot target, so on Windows the marketplace entry source field will contain backslashes (e.g. "./plugins\my-plugin") instead of the expected POSIX-style path, changing behavior and potentially breaking consumers that expect forward slashes.

Suggested fix: Update resolvePluginPath in src/targets/claude.ts to mirror the legacy Claude and Copilot implementations by wrapping the joined path in toPosix(), and import toPosix from ../fs.js. For example:

import path from "node:path";
import { toPosix } from "../fs.js";
...
resolvePluginPath: (pluginName, pluginConfig, targetConfig) =>
  pluginConfig.path ??
  toPosix(path.join(targetConfig.pluginRoot ?? "plugins", pluginName)),

🔧 Tag @ glean-for-engineering to fix or click here to fix in Glean

💬 Help us improve! Was this comment helpful? React with 👍 or 👎

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

internal Internal refactoring, cleanup, or maintenance work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant