Skip to content

feat(plugin): per-provider bundles under plugins/databricks/<provider>/#165

Merged
simonfaltum merged 3 commits into
mainfrom
simonfaltum/plugins-databricks-bundle
Jun 19, 2026
Merged

feat(plugin): per-provider bundles under plugins/databricks/<provider>/#165
simonfaltum merged 3 commits into
mainfrom
simonfaltum/plugins-databricks-bundle

Conversation

@simonfaltum

Copy link
Copy Markdown
Member

Why

The plugin shipped from a single whole-repo source (marketplace.json source: "./"), which caused real problems. Copilot crashed copying the repo's .git/fsmonitor--daemon.ipc socket (upstream #3842), Codex mis-resolved hook paths from the repo root, and every install cloned the entire repo even though each agent only uses its own dialect's files. There was also no easy way to see, per provider, exactly what ships.

Changes

Before: one source: "./" per catalog; all four agents cloned the whole repo; commands/ and commands-cursor/ were maintained as two near-duplicate trees.

Now: each agent fetches a generated, self-contained plugins/databricks/<provider>/ folder (claude, codex, copilot, cursor) holding only what it uses: its plugin.json, a copy of skills/, its hook wiring as hooks/hooks.json plus the scripts it references, and where applicable commands/, rules/, assets/. The four root marketplace.json catalogs (Cursor's is new) each point a scoped source at their own subfolder, so an install fetches only that provider's payload.

Implementation:

  • skillsgen/bundle.py: assembles each provider folder and byte-exact drift-checks it (a missing, stale, hand-edited, or extra file all fail CI).
  • Uniform hooks/hooks.json per provider, auto-discovered from the plugin root, so no plugin.json declares a "hooks" path. The per-dialect names (codex-hooks.json, ...) remain only at the repo root so the single generation step does not collide; the bundle renames each into its folder.
  • skillsgen/commands.py + templated commands/*.md: one source per command with a {{claude-or-codex | cursor}} alternation, rendered per provider. commands-cursor/ removed.
  • plugins.py: catalogs scoped per provider via metaplugin/plugin.meta.json marketplace.source; ref: main for now (a mechanical follow-up flips it to v{version} tag-pinning).
  • CLI files-channel unchanged: the stable repo_dir stays skills (root skills/), so manifest.json and the released CLI are untouched.
  • .gitattributes marks plugins/** linguist-generated; release.yml stages plugins/databricks; validate-manifest.yml triggers on plugins/**.
  • Docs (CLAUDE / AGENTS / CONTRIBUTING / READMEs / metaplugin) and tests updated.

Everything under plugins/ is generated, committed, and drift-checked (not gitignored), so a reviewer sees the exact bytes each agent fetches.

Test plan

  • python3 scripts/skills.py validate clean
  • 110 unit tests pass (python3 -m unittest discover -s tests -p '*_test.py')
  • Verified empirically against a throwaway GitHub repo: scoped install on all four agents; tag-freeze on Claude/Codex/Copilot (a tagged add/remove sequence serves only the tagged contents); plugin load on Cursor (cursor-agent --plugin-dir); the Copilot fsmonitor fix (the whole-repo control crashes, the scoped install does not); the CLI files-channel path; and the ./ -> scoped migration on a version bump.
  • Codex still needs its policy block plus a live router-fire check (an open question tracked in the proposal).

Follow-up (separate, mechanical PR): flip ref_template from main to v{version} so the ref-capable tools (Claude, Codex, Copilot) serve frozen release tags instead of main HEAD. Cursor cannot pin a ref and always tracks the default branch.

This pull request and its description were written by Isaac.

Replace the whole-repo "./" plugin source with generated, committed,
drift-checked per-provider bundles: plugins/databricks/{claude,codex,copilot,
cursor}/. Each folder is self-contained and holds only what that provider uses:
its plugin.json, a copy of skills/, its hook wiring as hooks/hooks.json plus the
scripts it references (and _routing_data.json only where the router is wired),
and, where applicable, commands/ (Claude, Cursor), rules/ (Cursor), assets/
(Codex). The four root marketplace.json catalogs (Cursor's is new) each point a
scoped source at their own provider subfolder, so an install fetches only that
provider's payload.

Why: a self-contained folder per provider is easy to see and debug, fixes the
Copilot fsmonitor crash and the Codex root-source bug, and makes each install a
cheap scoped fetch.

Changes:
- skillsgen/bundle.py: assemble + byte-exact drift-check each provider folder
  (a missing, stale, hand-edited, or extra file all fail CI)
- uniform hooks/hooks.json per provider: each folder ships its dialect's wiring
  as hooks/hooks.json (auto-discovered from the plugin root), so no plugin.json
  declares a "hooks" path. The per-dialect names (codex-hooks.json, ...) stay
  only at the repo root so generation doesn't collide; the bundle renames each.
- skillsgen/commands.py + templated commands/*.md: one source per command with a
  {{claude-or-codex|cursor}} alternation, rendered per provider; commands-cursor/
  removed
- plugins.py: catalogs scoped per provider via meta.marketplace.source; ref
  "main" for now (a mechanical follow-up flips to v{version} tag-pinning)
- CLI files-channel unchanged: the stable repo_dir stays "skills" (root skills/),
  so manifest.json and the released CLI are untouched
- .gitattributes marks plugins/** linguist-generated; release.yml stages
  plugins/databricks; validate-manifest.yml triggers on plugins/**
- docs (CLAUDE/AGENTS/CONTRIBUTING/READMEs/metaplugin) + tests updated

Validation is clean and all 110 unit tests pass. Verified empirically against a
throwaway repo: scoped install + tag-freeze on Claude/Codex/Copilot, plugin load
on Cursor, the Copilot fsmonitor fix (the whole-repo control crashes, the scoped
install does not), the CLI files-channel path, and the "./" -> scoped migration
on a version bump. Codex still needs its policy block + a live router-fire check
(an open question in the proposal).

Co-authored-by: Isaac
Signed-off-by: simon <simon.faltum@databricks.com>
@simonfaltum simonfaltum requested review from a team and lennartkats-db as code owners June 19, 2026 13:27
…atabricks-bundle

Signed-off-by: simon <simon.faltum@databricks.com>
PR #164 edited four databricks-apps / databricks-dabs source files after
this branch was cut, so the committed per-provider bundle copies drifted
(CI validate caught it on the merge checkout). Merge main and regenerate
so all four providers' skill copies match the updated source.

Also remove the now-dead `.codex-plugin/**` trigger from
validate-manifest.yml: this PR moved Codex's plugin.json into
plugins/databricks/codex/.codex-plugin/ (already covered by `plugins/**`),
so root `.codex-plugin/` no longer exists.

Co-authored-by: Isaac
Signed-off-by: simon <simon.faltum@databricks.com>
@simonfaltum simonfaltum added this pull request to the merge queue Jun 19, 2026
Merged via the queue into main with commit 2b109a8 Jun 19, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants