From 12c44295f22816f7172cc13ce05c8fba4325e2f1 Mon Sep 17 00:00:00 2001 From: danielmeppiel Date: Thu, 23 Apr 2026 09:08:10 +0200 Subject: [PATCH 1/5] docs(gh-aw): replace deprecated dependencies: with shared/apm.md import gh-aw deprecated the top-level 'dependencies:' frontmatter field in favor of the 'imports: - uses: shared/apm.md with: packages:' pattern. Our integration page still presented 'dependencies:' as 'Recommended' and included an 'Isolated Mode' section tied to the deprecated object form. Changes: - Renamed primary section to 'Shared apm.md Import (Recommended)' with the canonical pattern from gh-aw reference docs (matches how this repo's own .github/workflows/pr-review-panel.md consumes APM). - Added a package reference format table that explicitly documents the three forms: full package, individual primitive (any layout), pinned ref. The per-primitive form is what lets workflows consume skills from repos like github/awesome-copilot that don't use the .apm/ layout, without restructuring them. - Added a deprecation callout pointing migrators away from the old 'dependencies:' field. - Removed the 'Isolated Mode' section -- it documented an option only reachable through the deprecated object form. - Updated the Bundles example to drop the inline imports list (which did not match the shared/apm.md pattern) and added a pointer to enterprise/registry-proxy as the live-routing complement to bundles. - Updated the Content Scanning paragraph to reference shared/apm.md resolution instead of the old dependencies-via-apm-action wording. Build: 42 pages, all internal links valid. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/src/content/docs/integrations/gh-aw.md | 89 +++++++-------------- 1 file changed, 28 insertions(+), 61 deletions(-) diff --git a/docs/src/content/docs/integrations/gh-aw.md b/docs/src/content/docs/integrations/gh-aw.md index 8c950de92..e6f283d79 100644 --- a/docs/src/content/docs/integrations/gh-aw.md +++ b/docs/src/content/docs/integrations/gh-aw.md @@ -18,11 +18,9 @@ APM defines **what** agents know. gh-aw defines **when** and **how** they act. ## Integration Approaches -### Frontmatter Dependencies (Recommended) +### Shared apm.md Import (Recommended) -gh-aw natively supports APM through a [`dependencies:` frontmatter field](https://github.github.com/gh-aw/reference/frontmatter/#apm-dependencies-dependencies). Declare APM packages directly in your workflow's frontmatter and gh-aw handles the rest. - -**Simple array format:** +gh-aw ships a [shared `apm.md` workflow component](https://github.github.com/gh-aw/reference/dependencies/) that turns APM packages into gh-aw dependencies. Import it in your workflow's frontmatter and pass the packages you want. ```yaml --- @@ -31,9 +29,13 @@ on: types: [opened] engine: copilot -dependencies: - - microsoft/apm-sample-package - - github/awesome-copilot/skills/review-and-refactor +imports: + - uses: shared/apm.md + with: + packages: + - microsoft/apm-sample-package + - github/awesome-copilot/skills/review-and-refactor + - your-org/security-compliance#v1.4.0 --- # Code Review @@ -41,37 +43,30 @@ dependencies: Review the pull request using the installed coding standards and skills. ``` -**Object format with options:** - -```yaml ---- -on: - issues: - types: [opened] -engine: copilot - -dependencies: - packages: - - microsoft/apm-sample-package - - your-org/security-compliance - isolated: true ---- - -# Issue Triage +**Package reference formats:** -Analyze the opened issue for security implications. -``` +| Format | Description | +|---|---| +| `owner/repo` | Full APM package (skills/agents/instructions under `.apm/`) | +| `owner/repo/path/to/primitive` | Individual primitive (skill, instruction, plugin, etc.) from any repository, regardless of layout | +| `owner/repo#ref` | Pinned to a tag, branch, or commit SHA | -Each entry is a standard APM package reference -- either `owner/repo` for a full package or `owner/repo/path/to/skill` for an individual primitive. +The per-primitive path form is what makes `github/awesome-copilot/skills/review-and-refactor` work -- the awesome-copilot repo lays skills out at `/skills//`, not under `.apm/`. Use this form to consume skills from existing repositories without restructuring them. **How it works:** -1. The gh-aw compiler detects the `dependencies:` field in your workflow frontmatter. -2. In the **activation job**, APM resolves the full dependency tree and packs the result. -3. In the **agent job**, the bundle is unpacked into the workspace and the agent discovers the primitives. +1. The gh-aw compiler detects the `shared/apm.md` import and adds a dedicated `apm` job to the compiled workflow. +2. The `apm` job runs `microsoft/apm-action` to install packages and uploads a bundle archive as a GitHub Actions artifact. +3. The agent job downloads and unpacks the bundle as pre-steps, making all primitives available at runtime. The APM compilation target is automatically inferred from the configured `engine:` field (`copilot`, `claude`, or `all` for other engines). No manual target configuration is needed. +Packages are fetched using gh-aw's cascading token fallback: `GH_AW_PLUGINS_TOKEN` -> `GH_AW_GITHUB_TOKEN` -> `GITHUB_TOKEN`. + +:::caution[Deprecated: `dependencies:` frontmatter] +Earlier gh-aw versions accepted a top-level `dependencies:` field on the workflow. That form is deprecated and no longer supported -- migrate to the `imports: - uses: shared/apm.md` pattern shown above. +::: + ### apm-action Pre-Step For more control over the installation process, use [`microsoft/apm-action@v1`](https://github.com/microsoft/apm-action) as an explicit workflow step. This approach runs `apm install` directly, giving you access to the full APM CLI. To also compile, add `compile: true` to the action configuration. @@ -112,48 +107,20 @@ For sandboxed environments where network access is restricted during workflow ex 1. Run `apm pack` in your CI pipeline to produce a self-contained bundle. 2. Distribute the bundle as a workflow artifact or commit it to the repository. -3. Reference the bundled primitives in your workflow. - -```yaml ---- -on: pull_request -engine: copilot -imports: - - .github/agents/code-reviewer.md - - .github/agents/security-auditor.md ---- - -# Code Review -Review the PR using team standards. -``` +3. Reference the bundled primitives directly from `.github/agents/` in your workflow. Bundles resolve full dependency trees ahead of time, so workflows need zero network access at runtime. -See the [CI/CD Integration guide](../ci-cd/) for details on building and distributing bundles. +See the [CI/CD Integration guide](../ci-cd/) and [Pack & Distribute](../../guides/pack-distribute/) for details on building and distributing bundles. For routing live install traffic through an enterprise proxy instead, see [Registry Proxy & Air-gapped](../../enterprise/registry-proxy/). ## Content Scanning -APM automatically scans dependencies for hidden Unicode characters during installation. Critical findings block deployment. This applies to both direct `apm install` and when GitHub Agentic Workflows resolves frontmatter dependencies via apm-action. +APM automatically scans dependencies for hidden Unicode characters during installation. Critical findings block deployment. This applies to both direct `apm install` and when gh-aw resolves packages via `shared/apm.md`. For CI visibility into scan results (SARIF reports, step summaries), see the [CI/CD Integration guide](../../integrations/ci-cd/#content-scanning-in-ci). For details on what APM detects, see [Content scanning](../../enterprise/security/#content-scanning). -## Isolated Mode - -When a gh-aw workflow runs in a repository that already has developer-focused instructions (like "use 4-space tabs" or "prefer functional style"), those instructions become noise for an automated agent that should only follow its declared dependencies. - -The `isolated` flag addresses this. When set to `true` in the object format: - -```yaml -dependencies: - packages: - - your-org/triage-rules - isolated: true -``` - -gh-aw clears existing `.github/` primitive directories (instructions, skills, agents) before unpacking the APM bundle. The agent sees only the context declared by the workflow, preventing instruction pollution from the host repository. - ## Learn More - [gh-aw Documentation](https://github.github.com/gh-aw/) From 9fc3181ed34c6b0d7234e53b9594db902a52be68 Mon Sep 17 00:00:00 2001 From: danielmeppiel Date: Thu, 23 Apr 2026 09:24:35 +0200 Subject: [PATCH 2/5] docs: add Anatomy of an APM Package guide Adds a new conceptual page in Introduction that answers the recurring question: 'what is .apm/ and why does it exist?' Covers: - The src/dist mental model (.apm/ = src, .github/.claude/.cursor/ = dist, apm_modules/ = node_modules, apm.yml = package.json) - Why .apm/ exists: separates source primitives from per-runtime compiled output; avoids self-referential context pollution where the dev-time agent reads in-progress sources from .github/ - Why not .github/ directly (3 reasons), why not the repo root (3 reasons) - Two ways to be importable: package form (apm.yml + .apm/) vs primitive form (owner/repo/path/to/primitive virtual package) - Decision guide for consumers vs publishers - Dogfooding example: this very repo has .apm/skills/ as source and byte-identical .github/skills/ as compiled output the in-repo Copilot agent reads - Discovery rules and quick FAQ (ls -a tip, overwrite-on-install warning) Wires: - Sidebar entry under 'Understanding APM' after Key Concepts - Link from integrations/gh-aw.md primitive-form table to this page Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/astro.config.mjs | 1 + docs/src/content/docs/integrations/gh-aw.md | 2 +- .../introduction/anatomy-of-an-apm-package.md | 261 ++++++++++++++++++ 3 files changed, 263 insertions(+), 1 deletion(-) create mode 100644 docs/src/content/docs/introduction/anatomy-of-an-apm-package.md diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index f0790d964..364c7f188 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -50,6 +50,7 @@ export default defineConfig({ { label: 'Why APM?', slug: 'introduction/why-apm' }, { label: 'How It Works', slug: 'introduction/how-it-works' }, { label: 'Key Concepts', slug: 'introduction/key-concepts' }, + { label: 'Anatomy of an APM Package', slug: 'introduction/anatomy-of-an-apm-package' }, ], }, { diff --git a/docs/src/content/docs/integrations/gh-aw.md b/docs/src/content/docs/integrations/gh-aw.md index e6f283d79..15bb2061e 100644 --- a/docs/src/content/docs/integrations/gh-aw.md +++ b/docs/src/content/docs/integrations/gh-aw.md @@ -51,7 +51,7 @@ Review the pull request using the installed coding standards and skills. | `owner/repo/path/to/primitive` | Individual primitive (skill, instruction, plugin, etc.) from any repository, regardless of layout | | `owner/repo#ref` | Pinned to a tag, branch, or commit SHA | -The per-primitive path form is what makes `github/awesome-copilot/skills/review-and-refactor` work -- the awesome-copilot repo lays skills out at `/skills//`, not under `.apm/`. Use this form to consume skills from existing repositories without restructuring them. +The per-primitive path form is what makes `github/awesome-copilot/skills/review-and-refactor` work -- the awesome-copilot repo lays skills out at `/skills//`, not under `.apm/`. Use this form to consume skills from existing repositories without restructuring them. See [Anatomy of an APM Package](../../introduction/anatomy-of-an-apm-package/) for the full source-vs-output model. **How it works:** diff --git a/docs/src/content/docs/introduction/anatomy-of-an-apm-package.md b/docs/src/content/docs/introduction/anatomy-of-an-apm-package.md new file mode 100644 index 000000000..c5e64960a --- /dev/null +++ b/docs/src/content/docs/introduction/anatomy-of-an-apm-package.md @@ -0,0 +1,261 @@ +--- +title: "Anatomy of an APM Package" +description: "What .apm/ is, why it exists, and how APM decides what is importable." +sidebar: + order: 5 +--- + +If you have read [What is APM?](./what-is-apm/) and [How It Works](./how-it-works/), +you know APM is a package manager for agent primitives. This page answers the +next question every user asks: what does an APM package actually look like on +disk, and why does it look that way? + +## The one-line mental model + +`apm.yml` is your `package.json`. `.apm/` is your `src/`. `apm_modules/` is your +`node_modules/`. The compiled output under `.github/`, `.claude/`, `.cursor/`, +and friends is your `dist/` -- generated, tool-specific, not the source of +truth. + +If you remember nothing else: **`.apm/` holds the primitives you author. +Everything outside `.apm/` that looks similar is either a build artifact or +someone else's package.** + +## Why `.apm/` exists + +AI coding tools each invented their own folder for context: `.github/` for +Copilot, `.claude/` for Claude Code, `.cursor/rules/` for Cursor, and so on. +Each one is read at runtime by exactly one tool. None of them are designed to +be authored portably, versioned as a dependency, or shared across tools. + +APM separates two concerns that those folders conflate: + +1. **Source primitives** -- the skills, agents, instructions, and prompts you + write and version. These live in `.apm/`. +2. **Compiled output** -- the tool-specific files APM generates from your + sources for each runtime you target. These live in `.github/`, `.claude/`, + `.cursor/`, etc. + +`apm install` and `apm compile` read from `.apm/` and write outward. + +### A concrete example: this repo + +The `microsoft/apm` repository (the one shipping the CLI you are reading docs +for) dogfoods this layout. It contains both source and compiled output side by +side: + +``` +microsoft/apm/ ++-- apm.yml ++-- .apm/ +| +-- skills/ +| | +-- writing-skills/ +| | +-- SKILL.md +| +-- instructions/ +| +-- agents/ ++-- .github/ +| +-- skills/ +| | +-- writing-skills/ +| | +-- SKILL.md (compiled from .apm/, byte-identical) +| +-- instructions/ +| +-- agents/ ++-- src/ ++-- tests/ +``` + +The file under `.apm/skills/writing-skills/SKILL.md` is the source. The file +under `.github/skills/writing-skills/SKILL.md` is the compiled artifact that +the in-repo Copilot agent actually loads while we work on the CLI. Same +content today, but only one of them is authoritative -- and only one of them +gets shipped when this repo is consumed as an APM package. + +## Why not just put primitives in `.github/` directly? + +It is tempting. `.github/` already exists, Copilot already reads it, why add +another folder? + +Three reasons, in order of severity. + +**1. Self-referential context pollution.** +The Copilot, Claude, or Cursor agent helping you author a skill reads +whatever sits in its runtime folder. If you author skills directly into +`.github/skills/`, your in-progress, half-written, possibly broken skill +becomes part of the system prompt of the agent you are using to write it. +Writing a code-review skill? Copilot starts applying it -- including to the +skill file itself -- before you have finished. Keeping sources in `.apm/` +means the dev-time agent only sees what you have explicitly compiled. + +**2. Portability across runtimes.** +A skill in `.github/skills/` is a Copilot-shaped file. A skill in +`.claude/skills/` is a Claude-shaped file. They are not interchangeable. The +whole point of APM is one source, many runtimes. That requires a +runtime-neutral source folder, and `.github/` is not it. + +**3. Packaging boundary.** +`apm pack` needs to know what is part of the package and what is incidental. +A dedicated `.apm/` directory makes that boundary trivial. Mixing sources +into `.github/` makes it a guessing game. + +## Why not the repo root? + +Also tempting, also wrong, for symmetric reasons: + +- **Naming collisions.** Most repos already have `skills/`, `agents/`, or + `prompts/` directories that mean something else (test fixtures, app code, + marketing copy). APM cannot safely claim those names at the root. +- **No discoverability signal.** A consumer cloning your repo cannot tell at + a glance whether it is an APM package. `.apm/` plus `apm.yml` is that + signal. +- **No clean pack boundary.** Same problem as `.github/`: `apm pack` would + need heuristics to know what to bundle. + +`.apm/` is short, namespaced, conventional, and unambiguous. That is the +whole argument. + +## Two ways to be importable + +A repo can expose primitives to APM consumers in two forms. They are not +mutually exclusive. + +### Package form + +The repo declares itself an APM package: `apm.yml` at the root, primitives +under `.apm/`. Consumers reference it by repo name: + +```yaml +# consumer's apm.yml +dependencies: + apm: + - your-org/your-repo +``` + +`apm install` resolves the repo, reads its `apm.yml`, and pulls every +primitive declared in `.apm/` into `apm_modules/`. + +This is the right form when: + +- You are publishing a curated set of primitives meant to be consumed + together. +- You want a one-line install for the whole bundle. +- You want versioning, lockfile entries, and a clean update path. + +Canonical examples: [`microsoft/apm-sample-package`](https://github.com/microsoft/apm-sample-package), +[`apm-handbook`](https://github.com/danielmeppiel/apm-handbook) (a multi-package +monorepo with `apm.yml` plus `.apm/skills/` and `.apm/agents/`), and this +repository itself. + +### Primitive form + +Any subdirectory of any GitHub repo that looks like a primitive can be +imported directly by path. The upstream repo does not need an `apm.yml` and +does not need to use `.apm/`: + +```yaml +# consumer's apm.yml +dependencies: + apm: + - github/awesome-copilot/skills/review-and-refactor +``` + +APM treats the subdirectory as a virtual single-primitive package. + +This is the right form when: + +- You want one or two skills out of a large repo, not the whole thing. +- The upstream repo is not APM-aware (and you do not want to ask the + maintainer to refactor). +- You are pinning a specific primitive at a specific commit without taking + on the rest of the repo's surface area. + +Both forms produce the same artifact in `apm_modules/` and the same compiled +output. The reference syntax is the only difference. + +## Decision guide + +| Situation | Use | Does upstream need `.apm/`? | +|----------------------------------------------------------|----------------|-----------------------------| +| Importing one or two skills from a third-party repo | Primitive form | No | +| Publishing your team's full skill set as a bundle | Package form | Yes | +| Mixed: a curated bundle plus a few file-level imports | Package form | Yes (works for both) | +| Quick test before adopting someone's skill | Primitive form | No | + +The short version: **if you are consuming, primitive form covers most cases +without forcing anyone to refactor. If you are publishing, package form is +the right investment.** + +If you started authoring directly in `.github/` and later want to make a +proper package, the migration is mechanical: move the files into `.apm/`, +add an `apm.yml`, and run `apm install` to re-generate `.github/` from the +new source. No data loss, no breaking change for downstream consumers. + +## Why does microsoft/apm itself have a `.apm/` folder? + +Because we use APM to manage the agent context that develops APM. + +The skills in `.apm/skills/` are the source primitives our team authors and +versions. The files in `.github/skills/` are the compiled output that the +Copilot agent attached to this repository reads while contributors work on +the CLI. Same content right now, but distinct roles: one is what we ship, +the other is what we run locally. + +If you are looking for a working reference layout, this repo is it. + +## What APM looks for + +Discovery rules, in order: + +1. **`apm.yml`** at the repo root marks the directory as an APM package and + declares its dependencies, scripts, and metadata. +2. **`.apm/`** at the repo root is the source root for primitives. APM does + not look elsewhere for sources. +3. Inside `.apm/`, primitives are grouped by type subdirectory: + + ``` + .apm/ + +-- skills/ (SKILL.md plus supporting files) + +-- agents/ (agent definitions) + +-- instructions/ (instruction files) + +-- prompts/ (prompt templates) + +-- chatmodes/ (chat mode configurations) + +-- context/ (shared context fragments) + ``` + +4. **Per-primitive references** (`owner/repo/path/to/primitive`) bypass + `.apm/` entirely. APM treats the named subdirectory as a single-primitive + virtual package regardless of where it sits in the upstream repo. +5. **Compiled output** (`.github/`, `.claude/`, `.cursor/rules/`, and other + runtime targets) is generated by `apm compile` based on the runtimes + declared in `apm.yml`. Never edit these directly in an APM-managed repo. + +For the full schema, see [Manifest Schema](../../reference/manifest-schema/) +and [Primitive Types](../../reference/primitive-types/). + +## Quick FAQ + +**I edited `.github/skills/my-skill/SKILL.md` directly. What happens on the +next `apm install`?** Your edit gets overwritten. Edit the source under +`.apm/skills/my-skill/SKILL.md` instead and re-run `apm install`. + +**I ran `ls` and don't see `.apm/`.** It's a dotfile directory, hidden by +default. Use `ls -a`. + +**Do I need `.apm/` to install packages?** No. `.apm/` is for authoring. If +you only consume packages, `apm install` creates the runtime targets +(`.github/`, `.claude/`, etc.) directly under `apm_modules/` and you never +touch `.apm/`. + +**What's the minimum for a valid APM package?** `apm.yml` at the root plus +at least one primitive under `.apm/`. + +## See also + +- [Your First Package](../../getting-started/first-package/) -- create a + package from scratch using this layout. +- [Primitive Types](../../reference/primitive-types/) -- the canonical + reference for skills, agents, instructions, prompts, and friends. +- [Manifest Schema](../../reference/manifest-schema/) -- the full `apm.yml` + spec. +- [gh-aw Integration](../../integrations/gh-aw/) -- how compiled output + feeds GitHub Agentic Workflows. +- [Compilation](../../guides/compilation/) -- how `.apm/` becomes + `.github/`, `.claude/`, and the rest. From 0731a508a477cc71087a819def021d4ce2584233 Mon Sep 17 00:00:00 2001 From: danielmeppiel Date: Thu, 23 Apr 2026 09:34:02 +0200 Subject: [PATCH 3/5] docs(anatomy): shield against plugins-skeptic + DRY corpus integration Per doc-writer corpus-fit audit: Anatomy page additions: - New 'Why not just ship a plugin.json?' section after 'Why not the repo root?' that frames plugins as runtime distribution format vs .apm/ as source layout (complementary, not competing). Calls out the three concrete touchpoints: APM consumes plugins natively, exports to plugin format via 'apm pack --format plugin', and supports hybrid mode (apm.yml + plugin.json together). - FAQ entry mirroring the same point for skim readers. - Compressed dogfooding section to a back-link (was duplicating the earlier 'concrete example' block). Corpus DRY trims (anatomy is now the single source of truth for layout): - key-concepts.md: removed 'Supported Locations' tree (~30 lines that framed .apm/ and .github/ as equivalent source locations, contradicting anatomy). Replaced 'Organized Structure' tree and 'Integration with VSCode' section with one-line links to anatomy. - first-package.md: added one-line link to anatomy in the post-init note so step-2's '.apm/instructions/' is no longer introduced silently. - how-it-works.md: linked '.apm/ directory' bullet in the architecture caption to anatomy. - guides/plugins.md: added a leading link from 'Plugin authoring' to the new plugin-skeptic section in anatomy (round-trip). Net word count across corpus: down (~60 lines trimmed vs ~40 added). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../docs/getting-started/first-package.md | 2 +- docs/src/content/docs/guides/plugins.md | 2 + .../introduction/anatomy-of-an-apm-package.md | 59 +++++++++++++++--- .../content/docs/introduction/how-it-works.md | 2 +- .../content/docs/introduction/key-concepts.md | 60 +++---------------- 5 files changed, 61 insertions(+), 64 deletions(-) diff --git a/docs/src/content/docs/getting-started/first-package.md b/docs/src/content/docs/getting-started/first-package.md index dae286961..2c81521c9 100644 --- a/docs/src/content/docs/getting-started/first-package.md +++ b/docs/src/content/docs/getting-started/first-package.md @@ -26,7 +26,7 @@ my-coding-standards/ └── apm.yml # Package manifest ``` -> **Note:** By default, `apm init` creates only `apm.yml`. The directory structure below is what you build manually in the following steps. +> **Note:** By default, `apm init` creates only `apm.yml`. The directory structure below is what you build manually in the following steps. See [Anatomy of an APM Package](../../introduction/anatomy-of-an-apm-package/) for what `.apm/` is and why files live there. ## 2. Add an Instruction diff --git a/docs/src/content/docs/guides/plugins.md b/docs/src/content/docs/guides/plugins.md index b3dbf3c59..e5e1aaf54 100644 --- a/docs/src/content/docs/guides/plugins.md +++ b/docs/src/content/docs/guides/plugins.md @@ -8,6 +8,8 @@ APM supports plugins through the `plugin.json` format. Plugins are automatically ## Plugin authoring +For where plugins fit relative to APM's source layout, see [Anatomy -- Why not just ship a `plugin.json`?](../../introduction/anatomy-of-an-apm-package/#why-not-just-ship-a-pluginjson). + Plugin ecosystems handle distribution but lack dependency management, security scanning, version locking, and dev/prod separation. As plugins depend on shared primitives, these gaps compound. APM is the supply-chain layer. Author packages with full tooling — transitive dependencies, lockfile pinning, [security scanning](../../enterprise/security/), [`devDependencies`](../../reference/manifest-schema/#5-devdependencies) — then export as standard plugins. Consumers never need APM installed. diff --git a/docs/src/content/docs/introduction/anatomy-of-an-apm-package.md b/docs/src/content/docs/introduction/anatomy-of-an-apm-package.md index c5e64960a..cfa5bd8c7 100644 --- a/docs/src/content/docs/introduction/anatomy-of-an-apm-package.md +++ b/docs/src/content/docs/introduction/anatomy-of-an-apm-package.md @@ -112,6 +112,44 @@ Also tempting, also wrong, for symmetric reasons: `.apm/` is short, namespaced, conventional, and unambiguous. That is the whole argument. +## Why not just ship a `plugin.json`? + +This is the sharpest version of the question, because plugin formats are +real and the ecosystem is converging on them. APM does not compete with +plugins -- it sits underneath them. + +- `plugin.json` is a **runtime distribution format**. It tells a single + host (Copilot CLI, Claude Code, Cursor) how to load a bundle of + primitives at runtime. +- `.apm/` is a **source layout**. It tells APM what you authored, so it + can resolve dependencies, lock versions, scan for security issues, and + compile to *every* runtime -- including plugin format. + +The two are complementary, and APM treats them that way: + +1. **APM consumes plugins as first-class dependencies.** Any repo with a + `plugin.json` (root, `.github/plugin/`, `.claude-plugin/`, or + `.cursor-plugin/`) is auto-recognized by `apm install`. APM + synthesizes an `apm.yml` from the plugin metadata so it gets version + pinning, lockfile entries, and transitive resolution. Marketplaces + (`marketplace.json`) resolve through the same path. See + [Plugins](../../guides/plugins/) and [Marketplaces](../../guides/marketplaces/). +2. **APM compiles `.apm/` to plugin format.** Run `apm pack --format + plugin` and you get a standalone plugin directory -- no `apm.yml`, no + `apm_modules/`, no `.apm/` -- consumable by any plugin host. See + [Pack & Distribute -- Plugin format](../../guides/pack-distribute/#plugin-format). +3. **Hybrid mode is supported.** A repo can ship `apm.yml` + `plugin.json` + together: author with APM (dependency management, lockfile, security + scanning, dev/prod separation), distribute as a standard plugin. + +What `plugin.json` alone does not give you: transitive dependency +resolution, a consumer-side lockfile, security scanning that blocks +critical findings on install, `devDependencies` that stay out of the +shipped artifact, or a single source that targets multiple runtimes. +That is the gap `.apm/` fills. If you only ever target one host and +never depend on shared primitives, plugin-only is fine -- and APM still +consumes you. + ## Two ways to be importable A repo can expose primitives to APM consumers in two forms. They are not @@ -190,15 +228,9 @@ new source. No data loss, no breaking change for downstream consumers. ## Why does microsoft/apm itself have a `.apm/` folder? -Because we use APM to manage the agent context that develops APM. - -The skills in `.apm/skills/` are the source primitives our team authors and -versions. The files in `.github/skills/` are the compiled output that the -Copilot agent attached to this repository reads while contributors work on -the CLI. Same content right now, but distinct roles: one is what we ship, -the other is what we run locally. - -If you are looking for a working reference layout, this repo is it. +Because we use APM to manage the agent context that develops APM. The +[concrete example above](#a-concrete-example-this-repo) is this repo. If +you are looking for a working reference layout, it is right there. ## What APM looks for @@ -247,6 +279,15 @@ touch `.apm/`. **What's the minimum for a valid APM package?** `apm.yml` at the root plus at least one primitive under `.apm/`. +**Isn't the industry converging on the plugin format? Why do I need +`.apm/` at all?** APM consumes plugins natively (`plugin.json` packages +install as first-class dependencies) and exports to plugin format +(`apm pack --format plugin`). `.apm/` is the source layout that gives +you dependency management, lockfiles, and security scanning during +authoring; `plugin.json` is the runtime distribution format. Use both -- +see [Why not just ship a `plugin.json`?](#why-not-just-ship-a-pluginjson) +above and the [hybrid authoring workflow](../../guides/plugins/#hybrid-authoring-workflow). + ## See also - [Your First Package](../../getting-started/first-package/) -- create a diff --git a/docs/src/content/docs/introduction/how-it-works.md b/docs/src/content/docs/introduction/how-it-works.md index e0bc3c613..a6f94e47a 100644 --- a/docs/src/content/docs/introduction/how-it-works.md +++ b/docs/src/content/docs/introduction/how-it-works.md @@ -114,7 +114,7 @@ graph TD **Key Architecture Components**: -1. **Context** (.apm/ directory) - Your source code for AI workflows +1. **Context** (.apm/ directory) - Your source code for AI workflows. See [Anatomy of an APM Package](../anatomy-of-an-apm-package/) for the directory layout. 2. **APM CLI** - Three core engines working together: - **Package Manager** - Dependency resolution and distribution - **Primitives Compiler** - Transforms primitives → agents.md format diff --git a/docs/src/content/docs/introduction/key-concepts.md b/docs/src/content/docs/introduction/key-concepts.md index a66e363f7..2f6664f42 100644 --- a/docs/src/content/docs/introduction/key-concepts.md +++ b/docs/src/content/docs/introduction/key-concepts.md @@ -71,40 +71,12 @@ The APM CLI supports the following types of primitives: > **Note**: Both `.agent.md` (new format) and `.chatmode.md` (legacy format) are fully supported. VSCode provides Quick Fix actions to help migrate from `.chatmode.md` to `.agent.md`. -## File Structure +## Where primitives live -### Supported Locations - -APM discovers primitives in these locations: - -``` -# APM-native structure -.apm/ -├── agents/ # AI assistant definitions (new format) -│ └── *.agent.md -├── chatmodes/ # AI assistant definitions (legacy format) -│ └── *.chatmode.md -├── instructions/ # Coding standards and guidelines -│ └── *.instructions.md -└── hooks/ # Lifecycle event handlers - ├── *.json # Hook definitions (JSON) - └── scripts/ # Referenced scripts - └── *.sh, *.py - -# VSCode-compatible structure -.github/ -├── agents/ # VSCode Copilot agents (new format) -│ └── *.agent.md -├── chatmodes/ # VSCode Copilot chatmodes (legacy format) -│ └── *.chatmode.md -└── instructions/ # VSCode Copilot instructions - └── *.instructions.md - -# Generic files (anywhere in project) -*.agent.md -*.chatmode.md -*.instructions.md -``` +Primitives are authored in `.apm/` and deployed to runtime folders +(`.github/`, `.claude/`, `.cursor/`, `.opencode/`) by `apm install` and +`apm compile`. For the full layout, source-vs-output distinction, and +discovery rules, see [Anatomy of an APM Package](../anatomy-of-an-apm-package/). ## Component Types Overview @@ -385,16 +357,7 @@ Use specific `applyTo` patterns for instructions: Keep primitives in version control alongside your code. Use semantic versioning for breaking changes. ### 4. Organized Structure -Use the structured `.apm/` directories for better organization: -``` -.apm/ -├── agents/ -│ ├── code-reviewer.agent.md -│ └── documentation-writer.agent.md -└── instructions/ - ├── python-style.instructions.md - └── typescript-conventions.instructions.md -``` +Use `.apm/` subdirectories by primitive type. See [Anatomy](../anatomy-of-an-apm-package/#what-apm-looks-for). ### 5. Team Collaboration - Include author information in frontmatter @@ -403,16 +366,7 @@ Use the structured `.apm/` directories for better organization: ## Integration with VSCode -For VSCode Copilot compatibility, place files in `.github/` directories: -``` -.github/ -├── agents/ -│ └── assistant.agent.md -└── instructions/ - └── coding-standards.instructions.md -``` - -These files follow the same format and will be discovered alongside APM-specific primitives. +VS Code Copilot reads compiled output in `.github/`. Author in `.apm/` and let `apm install` produce it -- see [Anatomy](../anatomy-of-an-apm-package/) for the source-vs-output model. ## Error Handling From 8734cfbd046444cede565ab1b482f9041a2af72f Mon Sep 17 00:00:00 2001 From: Daniel Meppiel <51440732+danielmeppiel@users.noreply.github.com> Date: Thu, 23 Apr 2026 09:44:04 +0200 Subject: [PATCH 4/5] Update docs/src/content/docs/integrations/gh-aw.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- docs/src/content/docs/integrations/gh-aw.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/content/docs/integrations/gh-aw.md b/docs/src/content/docs/integrations/gh-aw.md index 15bb2061e..b9630e546 100644 --- a/docs/src/content/docs/integrations/gh-aw.md +++ b/docs/src/content/docs/integrations/gh-aw.md @@ -49,7 +49,7 @@ Review the pull request using the installed coding standards and skills. |---|---| | `owner/repo` | Full APM package (skills/agents/instructions under `.apm/`) | | `owner/repo/path/to/primitive` | Individual primitive (skill, instruction, plugin, etc.) from any repository, regardless of layout | -| `owner/repo#ref` | Pinned to a tag, branch, or commit SHA | +| `owner/repo#ref` or `owner/repo/path/to/primitive#ref` | Pinned to a tag, branch, or commit SHA, for either a full package or a specific primitive | The per-primitive path form is what makes `github/awesome-copilot/skills/review-and-refactor` work -- the awesome-copilot repo lays skills out at `/skills//`, not under `.apm/`. Use this form to consume skills from existing repositories without restructuring them. See [Anatomy of an APM Package](../../introduction/anatomy-of-an-apm-package/) for the full source-vs-output model. From 18a46693068a3b315818ad67d73c722703dfaee6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Apr 2026 07:47:35 +0000 Subject: [PATCH 5/5] docs(gh-aw): document default isolated mode in shared/apm.md import Agent-Logs-Url: https://github.com/microsoft/apm/sessions/31d38cde-05ac-45e5-8d5b-fdd4186014f8 Co-authored-by: danielmeppiel <51440732+danielmeppiel@users.noreply.github.com> --- docs/src/content/docs/integrations/gh-aw.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/src/content/docs/integrations/gh-aw.md b/docs/src/content/docs/integrations/gh-aw.md index b9630e546..f271fc0c3 100644 --- a/docs/src/content/docs/integrations/gh-aw.md +++ b/docs/src/content/docs/integrations/gh-aw.md @@ -63,6 +63,10 @@ The APM compilation target is automatically inferred from the configured `engine Packages are fetched using gh-aw's cascading token fallback: `GH_AW_PLUGINS_TOKEN` -> `GH_AW_GITHUB_TOKEN` -> `GITHUB_TOKEN`. +:::note[Isolated install by default] +`shared/apm.md` invokes `microsoft/apm-action` with `isolated: true`. Only the packages listed under `packages:` are installed -- any host-repo primitives under `.apm/` or `.github/` (instructions, prompts, skills, agents) are ignored and pre-existing primitive directories are cleared. To merge host-repo primitives with imported ones, use the [apm-action Pre-Step](#apm-action-pre-step) approach below, which leaves `isolated` at its default of `false`. +::: + :::caution[Deprecated: `dependencies:` frontmatter] Earlier gh-aw versions accepted a top-level `dependencies:` field on the workflow. That form is deprecated and no longer supported -- migrate to the `imports: - uses: shared/apm.md` pattern shown above. :::