camunda / camunda/spm-cli

Explore support for transitive skill dependencies via nested ai.json

Open
#68 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
Rust
Stars
8
Forks
0
Avg merge
6h 12m
Merged PRs (30d)
19

Description

Summary

Explore/design support for transitive skill dependencies: allow a skill referenced in ai.json to itself declare an ai.json (at its repo root or skill path), and have spm recursively resolve and vendor those nested dependencies alongside the top-level ones.

This mirrors how Cargo/npm handle transitive deps, but spm's trust model (skills can carry executable agent instructions) means the blast radius of auto-fetching arbitrary git repos is larger, so this needs careful design before implementation.

Proposed mechanism

After resolver::resolve pins a skill to a commit, look inside the store checkout at <path>/ai.json (or the repo-root ai.json). If present, recursively resolve its skills map too, merging everything into one flat ai.lock, deduplicated by (git, commit, path) to avoid re-cloning/re-vendoring the same skill twice.

Open design questions to resolve before coding

  1. Supply-chain trust — auto-fetching arbitrary git repos transitively is a bigger risk than typical package managers since skills can influence agent behavior. Should this be opt-in (e.g. spm add --with-deps, or an explicit manifest flag) rather than default-on, at least initially?
  2. Version conflicts — if two skills (directly or transitively) require different tags/commits of the same dependency, what's the resolution policy? Error-on-conflict is safest; "first wins" is more npm-like but can be surprising.
  3. Cycles — need a visited-set keyed by resolved (git, commit, path), not just skill name, to detect and safely handle dependency cycles.
  4. Targets — does a transitively-resolved skill inherit the top-level targets (Claude/Copilot), or can it declare its own subset? Likely should inherit, but needs confirming against src/vendor/mod.rs's for_target dispatch.
  5. Lockfile shape — how does ai.lock (src/lockfile.rs) represent the dependency graph vs. a flat list? Do we need to preserve "who depends on whom" for diagnostics/spm list?

Relevant code

  • src/resolver.rs — resolves a skill spec (tag/branch/commit) to an immutable commit SHA + store key.
  • src/manifest.rs — the user-authored ai.json model.
  • src/lockfile.rs — the generated ai.lock pin file.
  • src/store.rs — global store management (one clone per commit).

Context

Originated from a design discussion in a prior session (2026-08-27, "Handle Skills Transitive Dependencies") exploring whether each skill could carry its own ai.json to declare further dependencies. No implementation has started; this issue tracks the design/decision work per the repo's "no task without a tracked issue" policy.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading src/resolver.rs and the manifest, lockfile, and store models in src/manifest.rs, src/lockfile.rs, and src/store.rs; inspect src/vendor/mod.rs for target dispatch. Compare the existing resolution and lockfile behavior with each open design question. Done means the trust, conflict, cycle, target, and lockfile policies are documented well enough to guide a later implementation.

Written by the indexing model from the issue text.

Assessment

Tech stack
git, rust
Domain
cli, devtools, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.