APM Concepts
This page is the shared vocabulary for everything else in this onboarding set. Read it once; the rest will make sense.
At a glance
| Term | One-line definition | Lives in |
|---|---|---|
| Primitive | A single, independently versioned building block (agent, instructions, prompt, skill, hook, or init script). | primitives/<type>/<name>/ in calab-ai/apm-registry |
| Package | A named, versioned bundle that composes one or more primitives. | packages/<name>/ in calab-ai/apm-registry |
| Registry | The Git-backed source of truth for primitives and packages. | calab-ai/apm-registry |
| Catalog | A versioned snapshot (portal-data.json) of everything published. | catalog/ in the registry, attached to each release |
Manifest (apm.yml) | The desired-state dependency list authored in a consumer repo. | Consumer repository root |
Lockfile (apm.lock.yaml) | The fully resolved tag → commit SHA + file-hash record. | Consumer repository root |
Provenance (.generated-from-apm.json) | Per-file record of where every installed file came from. | Consumer repository root |
Primitives
A primitive is the smallest unit APM ships. It lives at primitives/<type>/<name>/ and always carries an apm-primitive.json manifest validated against schemas/apm-primitive.schema.json.
The six primitive type values, with the directory each maps to:
type | Directory | Typical entrypoint | What it is |
|---|---|---|---|
agents | primitives/agents/<name>/ | agent.md | A Copilot/Claude/Codex agent definition (frontmatter + system prompt). |
instructions | primitives/instructions/<name>/ | instructions.md | Always-on guidance scoped by glob (e.g. coding standards, security rules). |
prompts | primitives/prompts/<name>/ | prompt.md | Reusable, parameterized prompt template. |
skills | primitives/skills/<name>/ | SKILL.md | A Copilot skill (capability + invocation contract + supporting files). |
hooks | primitives/hooks/<name>/ | hook.ps1 / hook.sh | Pre- or post-task local automation invoked by the agent runtime. |
init | primitives/init/<name>/ | init.ps1 / init.sh | First-run workspace setup (e.g. cloud-agent-setup). |
The id pattern is ^[a-z][a-z0-9]*\.(agent|instructions|prompt|skill|hook|init)\.[a-z][a-z0-9-]+$ — note the singular type segment in the id (calab.agent.build) versus the plural directory (primitives/agents/build/).
Primitives are independently versioned; each release gets a tag of shape refs/tags/primitives/<type>/<name>/v<version>.
Packages
A package at packages/<name>/ composes primitives into a named, installable bundle. Its apm-package.json is validated against schemas/apm-package.schema.json and lists primitives by registry-relative path:
{
"id": "calab.package.workspace-base",
"name": "calab-workspace-base",
"version": "1.0.0",
"primitives": [
{ "ref": "primitives/agents/build" },
{ "ref": "primitives/agents/plan" },
{ "ref": "primitives/instructions/coding-standards" },
{ "ref": "primitives/skills/gh-cli" }
]
}Packages have their own version (and tag, refs/tags/packages/<name>/v<version>) independent of the primitives they reference. A package version bump is required whenever the primitive set changes or a referenced primitive bumps a major version.
The two GA packages today are:
calab-workspace-base— base workspace for any consumer repo.calab-org-agents— org-level agent bundle distributed tocalab-ai/.github-private.
Registry
The registry is just the repo: calab-ai/apm-registry. It owns:
primitives/andpackages/— source of truth for content.schemas/— JSON Schema files for every manifest type.catalog/— generator script and the latestportal-data.jsonsnapshot.distribution/— release artefacts (e.g. payload for.github-privatein [Decision 14](../../../00 Governance/Decisions/14 APM GitHub Private Distribution.md)).
There is no runtime registry service today. Per [Decision 15](../../../00 Governance/Decisions/15 APM Future Registry Service.md), Git tags + gh api + portal-data.json are the protocol.
Catalog and portal-data.json
Each apm-registry release attaches a portal-data.json artifact (≈6 KB at v1.6.1) that lists every published primitive and package with its current GA version, ref, and metadata. The schema is schemas/portal-data.schema.json.
gh calab apm catalog reads portal-data.json (falling back to Git tag enumeration if absent) and powers both:
- the marketplace portal, and
- the in-handbook APM Marketplace snapshot.
Manifest (apm.yml)
apm.yml is the single human-authored file in a consumer repo. It declares dependencies as (repo, ref, path) tuples:
version: "1"
name: my-consumer-repo
dependencies:
- id: calab.package.workspace-base
source:
repo: calab-ai/apm-registry
ref: refs/tags/packages/calab-workspace-base/v1.0.0
path: packages/calab-workspace-base
targets:
- path: .github/copilotSchema: schemas/apm-manifest.schema.json.
Production manifests must use tag refs. Branch refs are rejected by default (override only in dev with policy.allow_branch_refs: true).
Lockfile (apm.lock.yaml)
apm.lock.yaml is the machine-generated derived file produced by gh calab apm resolve. For every dependency it records:
- the resolved commit SHA the tag pointed at,
- a SHA-256 hash of every file in the dependency,
- the policy snapshot at resolve time.
Schema: schemas/apm-lock.schema.json.
Two consumers running apm sync against the same lockfile produce byte-identical trees. That is the whole reason it exists.
Provenance (.generated-from-apm.json)
Every file apm sync writes is recorded in .generated-from-apm.json with its source ref, commit, path, and hash. This is what makes safe deletion possible: apm sync only removes files it previously wrote.
Schema: schemas/generated-from-apm.schema.json.
Tag-ref convention
APM uses three tag prefixes — never overlap them:
refs/tags/catalog/v<version> # whole-catalog snapshot
refs/tags/packages/<name>/v<version> # one package
refs/tags/primitives/<type>/<name>/v<version> # one primitiveSee docs/apm-tag-ref-conventions.md in the registry for the canonical rules.