Mechanical rename produced by scripts/msd-rename.cjs: gsd/Gsd/GSD -> msd/Msd/MSD across contents and paths, upstream package/repo coordinates -> @golem15/msd-core and golem15com/msd-core. Deep links into upstream history, sibling upstream packages, the GSD-2 import feature, CHANGELOG.md and .changeset/ are kept as-is. Hand edits on top: MSD block-letter banner and logos, LICENSE copyright line, package/plugin identity, regenerated lockfile, install-tree fixtures, derived registries and benchmark baseline; migration checksum baseline re-locked (MSD keeps its own install state, so no install had applied the old sums); sort-order and regex-escaped expectations in tests adjusted.
146 lines
8.0 KiB
Markdown
146 lines
8.0 KiB
Markdown
# How to version and upgrade a capability
|
|
|
|
This guide covers two separate journeys: how a **capability author** keeps their manifest correctly versioned as MSD evolves, and how a **capability consumer** safely applies updates. Read only the section that matches your role; each stands alone.
|
|
|
|
---
|
|
|
|
## If you author a capability
|
|
|
|
### Choose a version number
|
|
|
|
Every `capability.json` must carry a `version` field expressed as a [semver](https://semver.org) string. MSD rejects a capability manifest that omits it.
|
|
|
|
Use the standard semver conventions:
|
|
|
|
| Kind of change | Version bump | Examples |
|
|
|---|---|---|
|
|
| Backwards-compatible bug fixes or minor prompt improvements | **patch** (0.0.x) | Fix a typo in an agent instruction; tighten a hook condition. |
|
|
| New loop-extension hook, new skill, or new config key — existing consumers unaffected | **minor** (0.x.0) | Add a `verify:post` gate; add a new optional config key. |
|
|
| Breaking change to the hook contract, removal of a skill or config key, change of `id` | **major** (x.0.0) | Rename a hook extension point; remove a skill consumers depend on. |
|
|
|
|
Set the version in your manifest before every release:
|
|
|
|
```jsonc
|
|
{
|
|
"id": "my-deploy-gate",
|
|
"version": "1.2.0",
|
|
"engines": { "msd": ">=1.6.0 <3.0.0" }
|
|
}
|
|
```
|
|
|
|
> **First-party capabilities are versioned automatically.** The native capabilities shipped inside MSD (`capabilities/<id>/capability.json`) are stamped in lockstep with the MSD package version at release time by `scripts/sync-manifest-versions.cjs` — their `version` always equals the MSD version, so per-capability semver and `compatVersions` only carry independent signal for **third-party** capabilities. As an author of a third-party capability, you own your own version line; the lockstep rule does not apply to you.
|
|
|
|
### Decide when to raise `engines.msd`
|
|
|
|
The `engines.msd` range expresses which MSD host versions your capability is compatible with. MSD enforces this as a hard gate at install time and again at load time.
|
|
|
|
Raise the lower bound when you start using a MSD feature introduced in a specific release — for example, a loop extension point added in 1.7.0, a new manifest field, or a config federation key that does not exist in older MSD builds. Do not raise it pre-emptively; only raise it when the capability genuinely requires the newer behaviour.
|
|
|
|
When you do raise the lower bound:
|
|
|
|
1. Bump `version` (at minimum a minor bump, or a major bump if the change is otherwise breaking).
|
|
2. Update `engines.msd` to reflect the new minimum.
|
|
3. Add a `compatVersions` entry (see below).
|
|
|
|
### Maintain `compatVersions`
|
|
|
|
`compatVersions` is a capability-version → MSD-version-**range** table that lets MSD offer older consumers a downgrade instead of a hard block. Each value is a semver range (the same grammar as `engines.msd`), evaluated against the running MSD version:
|
|
|
|
```jsonc
|
|
{
|
|
"version": "2.0.0",
|
|
"engines": { "msd": ">=1.7.0 <3.0.0" },
|
|
"compatVersions": {
|
|
"1.2.0": ">=1.6.0 <1.7.0"
|
|
}
|
|
}
|
|
```
|
|
|
|
This entry tells MSD: "version 1.2.0 of this capability is compatible with MSD versions `>=1.6.0 <1.7.0`." When a consumer's MSD is older than the current `engines.msd` floor (1.7.0), MSD consults `compatVersions`, picks the **newest** capability version whose range the host satisfies, and offers that instead of failing outright.
|
|
|
|
Add a new entry **only when you change `engines.msd`** — that is the only moment an older MSD version and a specific capability version become correlated. A `compatVersions` entry is not meaningful for a capability distributed as a bare tarball URL (a tarball exposes a single version and cannot be auto-selected from a table); it is only actionable for sources that enumerate versions: git tags, a registry, or npm.
|
|
|
|
### Publish a new version
|
|
|
|
How consumers receive the update depends on your distribution channel.
|
|
|
|
**Git tag.** Commit the updated `capability.json` (with the new `version` field), then push a tag whose name matches the version:
|
|
|
|
```bash
|
|
git tag v1.2.0
|
|
git push origin v1.2.0
|
|
```
|
|
|
|
MSD's git adapter fetches tags to determine what is available. Without a matching tag, the new version is invisible to `msd capability outdated`.
|
|
|
|
**npm.** Publish normally. MSD uses `dist-tags` to check for updates, so the standard `npm publish` flow is sufficient:
|
|
|
|
```bash
|
|
npm version 1.2.0
|
|
npm publish
|
|
```
|
|
|
|
**New tarball.** Upload the new archive at a URL and communicate the URL to consumers. MSD cannot auto-detect updates for tarball sources, and `msd capability update` only ever re-resolves the URL **already recorded** in the ledger — it takes no new-URL argument. To move a tarball install to a new URL, the consumer **re-installs from the new URL** (`msd capability install <new-url> …`), which overwrites the recorded source. If you anticipate frequent updates, consider switching to a git or npm source so `msd capability update <id>` can pick up new versions automatically.
|
|
|
|
---
|
|
|
|
## If you consume a capability
|
|
|
|
### Check for available updates
|
|
|
|
Run:
|
|
|
|
```bash
|
|
msd capability outdated
|
|
```
|
|
|
|
MSD contacts the source of each installed capability and reports which ones have a newer version available. Whether an update is detectable depends on the source:
|
|
|
|
| Source | Auto-detectable? |
|
|
|---|---|
|
|
| Git (tags / manifest) | Yes — MSD fetches available tags. |
|
|
| npm | Yes — MSD checks `dist-tags`. |
|
|
| Tarball URL | **No** — a tarball exposes one version; updates must be applied manually by re-installing from a new URL. |
|
|
| Registry (`<name>@<registry>`) | **Not yet** — the registry source kind is reserved but unimplemented today; `outdated` reports `status: unknown` for it and `update` cannot re-resolve it. |
|
|
|
|
If a capability is installed from a tarball and the author publishes a new version at a different URL, `msd capability update <id>` will not help — it only re-resolves the URL already recorded at install time, and takes no new-URL argument. Once the author communicates the new address, **re-install from it** with `msd capability install <new-url> …`; that overwrites the recorded source with the new version.
|
|
|
|
### Apply an update
|
|
|
|
To update a specific capability:
|
|
|
|
```bash
|
|
msd capability update <id>
|
|
```
|
|
|
|
To update all installed capabilities at once:
|
|
|
|
```bash
|
|
msd capability update --all
|
|
```
|
|
|
|
Updates are **atomic**: MSD fully fetches and validates the new version before swapping it in. The ledger write is the commit point. If MSD stops mid-update (for example, due to a network failure), the next command run will detect the orphaned state via a reconciliation sweep and restore a consistent install — you will never be left with a half-updated capability.
|
|
|
|
### Consent when the executable surface changes
|
|
|
|
The CLI is **non-interactive** — it never stops to ask a question. If the new version adds or removes hooks, MCP server entries, or command modules compared to the version you have installed, `msd capability update <id>` **aborts** rather than swapping: it prints the disclosed surface change and instructs you to re-run with `--yes`, leaving the current version fully in place. Re-running with `--yes` grants consent for the new surface and completes the swap:
|
|
|
|
```bash
|
|
msd capability update <id> --yes
|
|
```
|
|
|
|
This re-consent is required every time the surface changes, scoped to the declared executable surface of a specific version, so a changed surface is always a fresh `--yes`. (A version whose executable surface is unchanged updates without `--yes`.)
|
|
|
|
### When `engines.msd` no longer matches
|
|
|
|
If the new version of a capability requires a MSD version newer than what you have installed, MSD will tell you clearly and — where the source enumerates versions — offer the newest `compatVersions`-compatible version instead. If no compatible version is available, or the source is a bare tarball, you will need to either upgrade MSD or stay on your current capability version.
|
|
|
|
---
|
|
|
|
## Related guides
|
|
|
|
- [How to remove or disable a capability](remove-a-capability.md)
|
|
- [Develop a Capability for MSD 1.5+](develop-a-capability.md)
|
|
- [Capability manifest reference](../reference/capability-manifest.md)
|
|
- [Turn a capability off (and keep it off)](turn-a-capability-off.md)
|