Files
holocron/plugins/kyberforge/.apm/skills/apm-workflow/references/configure.md
Defame1297 164948a0bc fix(apm-workflow): type: selects processing, it does not validate content
configure.md said apm.yml's `type:` field "constrains what .apm/ may
contain" and that changing it later "does not retroactively validate what
is already on disk" — both implying a validation step that does not exist.
Read against the installed apm-cli 0.28.0: PackageContentType controls how
a package is processed during install/compile, apm_package.py only
enum-checks the declared string, and validate_apm_package() branches on the
structural type derived from files on disk, never on the declared field.
There is no content-vs-type mismatch check anywhere.

The hazard is therefore the opposite of what the wording primed for:
silent omission. A package declaring type: instructions while shipping
.apm/skills/ installs no skill and compiles AGENTS.md only, exits 0, and
reports success having shipped none of its primitives. The rule is now to
verify deployed output rather than the exit code. apm-orchestrate carried
the same wording as a Hard Rule and is corrected in step; its separate
defects stay with #120.

Also refreshes the exemplar figures this branch had re-staled. 264a5db set
them to 3,222 words of references; 6cb47f8 then added 63 words and
invalidated them, and the correction above adds more. Re-measured after
all edits: body 237 and whole-file 304 both still hold, references total
3,416. body-discipline.md's "roughly 3,200" moves with it.

ADR-0020 is deliberately untouched — it self-pins its citations to
f9b919d — as is the git-commits negative example pinned to 5e23250.

Refs #99
2026-08-30 20:51:45 +00:00

6.3 KiB

topic, source_keys
topic source_keys
configure
context7-microsoft-apm

Scaffolding a new package

apm plugin init --yes --target claude,copilot

Run from inside the target package directory, with no positional name argument (see Gotchas). Creates apm.yml + plugin.json in the current directory — it does NOT scaffold a .apm/ skeleton. Primitive subdirectories (.apm/skills/, .apm/agents/, .apm/hooks/) must be created manually as content is migrated into them. Run this once per package (e.g. once per plugins/<name>/ directory in a monorepo-hybrid layout), not once for the whole repo.

apm.yml — required fields

Only name and version (SemVer) are required:

name: my-pkg
version: 1.0.0

apm.yml — top-level keys

  • name, version — required (see above)
  • description, author, license, homepage, repository, keywords — standard package metadata
  • type — instructions | skill | hybrid | prompts; selects how the package is processed at install/compile time. It is a routing selector, not a constraint on what .apm/ may contain (see Gotchas)
  • targets — which harnesses this package compiles to (plural list form preferred; legacy singular target: copilot,claude CSV form still accepted)
  • includes — auto publishes the authoritative local layout as-is; it is not scoped down to what's relevant, so anything narrower needs an explicit repo-path list. Note: auto also does not sweep generic root-level passthrough files (README.md, docs/, sources.md, config files) into the apm pack distribution bundle — see references/compile.md
  • dependencies/devDependencies — apm/mcp/lsp entries; devDependencies share the same shape but are excluded from the shipped artifact
  • scripts — named commands runnable via apm run <name>
  • compilation — target/strategy/exclude/placement controls for apm compile/apm pack
  • policy — e.g. fetch_failure_default
  • registries — named registry endpoints for shorthand dependency resolution
  • marketplace — owner + packages list; see references/marketplace.md for the full marketplace workflow

See docs/research/docs/microsoft-apm/configuration.md for the complete annotated schema.

Bumping a package's own version (repo policy)

apm ships no version-bump command, so version: in a package's own apm.yml is a hand edit. Policy: bump a package's own apm.yml version: whenever anything that reaches its compiled output changes. Two triggers, not one:

  • Its .apm/ content — a new or removed skill/agent/hook, or a substantive edit to an existing one.
  • Its own apm.yml manifest metadata — description, keywords, author, license, homepage, repository. These are compiled verbatim into .claude-plugin/plugin.json and .github/plugin/plugin.json, so editing them republishes the package's public description under an unchanged version number, which is the same defect as shipping changed content silently. Purely local edits that reach no compiled output — a README.md, a docs/ page — do not require a bump on their own.

The version belongs to the package, not to the repo: editing plugins/foo/.apm/ never bumps plugins/bar/apm.yml.

Under a per_package strategy the same number is also carried in the catalog's marketplace.packages[] entry, so both copies move together in the same commit. The catalog's own version follows a separate rule — see references/marketplace.md. apm pack --check-versions fails the push when a package's version disagrees with the configured strategy, so a bump applied in only one of the two places is caught, but a bump skipped in both is not: nothing infers intent from a content diff.

Dependency reference forms

dependencies.apm entries accept: a pinned tag (owner/repo#tag), a plain repo (uses default branch), a single primitive path within a repo, a raw git URL, a git:/path:/ref: object for finer control, or a local relative path (./packages/my-shared-skills).

MCP server secrets

${VAR} indirection is required for MCP server secrets (headers, env vars) in apm.yml, never literal values — see SKILL.md Gotchas.

Registries (config-level, not apm.yml)

Any git repo is a valid package source by default — no registry required. To declare named registries for shorthand dependency resolution:

apm experimental enable registries   # required first — see Gotchas
apm config set registry.corp-main.url https://artifactory.corp.example.com/apm
apm config set registry.corp-main.token eyJ...
apm config set registry.corp-main.default true

apm config get/apm config unset manage individual keys the same way.

Gotchas

  • apm.yml's type: field validates nothing about .apm/. It selects processing: instructions compiles to AGENTS.md only, skill installs a native skill only, prompts emits commands only, hybrid does both (see apm_cli/models/validation.py, PackageContentType). apm checks only that the value parses to one of those four strings; no check anywhere compares it against the primitives actually on disk, and no mismatch diagnostic exists. A package declaring type: instructions while shipping .apm/skills/ therefore raises no error — the mismatch resolves silently, either by omitting that primitive from the install/compile output or, in apm 0.28.0 where get_effective_type() routes off the on-disk layout and never reads the declared field, by ignoring the declared value outright. Both directions are silent: apm install and apm compile can exit 0 having shipped none of the primitives you expected. Set type: to cover every primitive the package ships, and confirm the deployed output rather than the exit code.
  • apm experimental enable registries must run before any registry.* config takes effect. Declaring a registries: block or running apm config set registry.* without it silently does nothing — no error, no warning.
  • apm plugin init <name> run with a positional name argument, from inside a directory already named <name>, creates a wrongly-nested <name>/<name>/ subdirectory — it treats the positional arg as "create a new project directory named X," not "confirm the current directory is X." Fix: omit the positional argument entirely when already cd'd into the target package directory — run apm plugin init --yes --target claude,copilot instead.