You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Git-source dependencies in apm.yml accept only branch names, tag names,
and SHAs as ref: values. Marketplace dependencies (PR #1422) and
registry dependencies (PR #1471) both accept semver ranges (^1.2.0, ~2.1, >=1.0 <2.0). The git source is the odd one out, which forces
authors who depend on a tagged git repo to either pin to an exact tag
(losing patch-level updates) or track a moving branch (losing
determinism).
This issue proposes resolving semver ranges on git-source deps against
the repo's git tags, using the existing RefResolver + tag-pattern
machinery already shipped for the marketplace source.
Motivation
After PR #1471 and PR #1422 land, three of APM's resolution sources speak
semver and one does not:
A consumer who depends on acme-org/some-skills@^1.2.0 directly from a
git repository (no marketplace, no registry) cannot express that intent
today. They must write ref: v1.5.3 and bump it manually.
Proposal
Accept a semver range or version expression as ref: on git-source
deps (string shorthand owner/repo#^1.2.0 and object form { git: ..., ref: ^1.2.0 }). When the value matches the registry semver grammar
(apm_cli.deps.registry.semver.is_semver_range), resolve it as
follows:
List the repo's tags via the existing RefResolver.list_remote_refs.
Drop pre-release tags by default (matching the existing marketplace
behavior). An opt-in (e.g. an include_prerelease: true field on the
object form) follows in a later issue if requested.
Pick the highest tag satisfying the range using marketplace.semver.satisfies_range + SemVer ordering.
Record both the constraint and the resolved tag in the lockfile so apm install is reproducible and apm update knows what to widen.
Existing ref: semantics are preserved unchanged: any value that
parses as a branch, a tag literal, or a SHA continues to take that
path. Semver routing is opt-in by syntax, not by flag.
Examples
String shorthand:
dependencies:
apm:
- acme-org/some-skills#^1.2.0 # resolved to highest v1.x.y tag
- acme-org/other-skills#main # unchanged: branch ref
- acme-org/pinned#v1.5.3 # unchanged: literal tag
- acme-org/sha-pin#abc1234 # unchanged: SHA
No new tag-pattern field on git deps in v1. Authors who use a
non-default tag pattern can declare the dep through a marketplace
entry (where tagPattern is already supported) or pin to a literal
tag. We can revisit per-dep tag_pattern: if demand surfaces.
Pre-release exclusion default matches marketplace behavior and
the registry resolver. Authors who genuinely want a pre-release can
pin it as a literal tag (ref: v2.0.0-beta.1).
Lockfile additivity. New fields are constraint, resolved_tag, resolved_at on LockedDependency. They are written only for
git-source semver-resolved deps. The lockfile version stays at v2.
Out of scope
Per-dep tag_pattern: override.
Pre-release opt-in flag.
apm update behavior changes (covered by existing update flow once
the lockfile carries the constraint).
Summary
Git-source dependencies in
apm.ymlaccept only branch names, tag names,and SHAs as
ref:values. Marketplace dependencies (PR #1422) andregistry dependencies (PR #1471) both accept semver ranges (
^1.2.0,~2.1,>=1.0 <2.0). The git source is the odd one out, which forcesauthors who depend on a tagged git repo to either pin to an exact tag
(losing patch-level updates) or track a moving branch (losing
determinism).
This issue proposes resolving semver ranges on git-source deps against
the repo's git tags, using the existing
RefResolver+ tag-patternmachinery already shipped for the marketplace source.
Motivation
After PR #1471 and PR #1422 land, three of APM's resolution sources speak
semver and one does not:
/versions{name}--v{version}tagsA consumer who depends on
acme-org/some-skills@^1.2.0directly from agit repository (no marketplace, no registry) cannot express that intent
today. They must write
ref: v1.5.3and bump it manually.Proposal
Accept a semver range or version expression as
ref:on git-sourcedeps (string shorthand
owner/repo#^1.2.0and object form{ git: ..., ref: ^1.2.0 }). When the value matches the registry semver grammar(
apm_cli.deps.registry.semver.is_semver_range), resolve it asfollows:
RefResolver.list_remote_refs.v{version}(e.g.v1.5.3) — primary, lockstep convention{name}--v{version}(e.g.some-skills--v1.5.3) — secondary,Claude Code / PR feat(deps): support marketplace dependencies in plugin.json #1422 convention for per-package tags in
multi-marketplace repos
behavior). An opt-in (e.g. an
include_prerelease: truefield on theobject form) follows in a later issue if requested.
marketplace.semver.satisfies_range+SemVerordering.apm installis reproducible andapm updateknows what to widen.Existing
ref:semantics are preserved unchanged: any value thatparses as a branch, a tag literal, or a SHA continues to take that
path. Semver routing is opt-in by syntax, not by flag.
Examples
String shorthand:
Object form:
Considerations
non-default tag pattern can declare the dep through a marketplace
entry (where
tagPatternis already supported) or pin to a literaltag. We can revisit per-dep
tag_pattern:if demand surfaces.default patterns map to real ecosystems:
v{version}is thelockstep convention;
{name}--v{version}is the Claude/feat(deps): support marketplace dependencies in plugin.json #1422per-package convention. The patterns are disjoint regexes, so both
can be tried in order without ambiguity.
the registry resolver. Authors who genuinely want a pre-release can
pin it as a literal tag (
ref: v2.0.0-beta.1).constraint,resolved_tag,resolved_atonLockedDependency. They are written only forgit-source semver-resolved deps. The lockfile version stays at v2.
Out of scope
tag_pattern:override.apm updatebehavior changes (covered by existing update flow oncethe lockfile carries the constraint).
References
deps/registry/semver.py.version:field andmarketplace/version_resolver.py.marketplace/ref_resolver.py,marketplace/semver.py,marketplace/tag_pattern.py.Consumed by
apm deps whysurfaces the newconstraintfield per edge.policy.dependencies.require_pinned_constraintclassifies git-source semver constraints uniformly with marketplace/registry sources.Related (orthogonal)
apm lock) #975 —apm lock(lockfile-only resolution). Different problem(when to write the lockfile vs. what constraints are accepted), but
both touch the resolution surface.
resolution). Different concern (cross-host identity vs. semver
routing), no coupling.