feat(kyberforge): execute the plugin→APM conversion #95
21
AGENTS.md
21
AGENTS.md
@@ -4,9 +4,19 @@ This repo is the global AI development configuration repository — the authorit
|
||||
|
||||
## Structure
|
||||
|
||||
- `plugins/` — installable plugin units; each is self-contained (skills, agents, hooks, MCP servers, bundled assets); install separately via `claude plugin install <name>@holocron`
|
||||
- `plugins/` — installable plugin units; each is an apm package (`apm.yml` + `.apm/`) carrying skills, agents, hooks, MCP servers, and bundled assets; install separately via `claude plugin install <name>@holocron`
|
||||
- `providers/claude-code/` — Claude Code adapter (deployed to `~/.claude/` via `install.sh`)
|
||||
|
||||
## Edit `.apm/`, never the flat mirror
|
||||
|
||||
Inside a plugin, `plugins/<name>/.apm/` is the **only** hand-edited content source. Everything else in a plugin root is generated:
|
||||
|
||||
- `scripts/sync-plugin-content.sh` generates the flat `plugins/<name>/{skills,agents,commands,instructions,extensions}/` directories and the merged `plugins/<name>/hooks/hooks.json` (ADR-0017)
|
||||
- `apm pack` generates both per-plugin manifests — `plugins/<name>/.claude-plugin/plugin.json` and `plugins/<name>/.github/plugin/plugin.json` — and **two of the three** root marketplace manifests: `.claude-plugin/marketplace.json` (apm's `claude` output profile) and `.agents/plugins/marketplace.json` (its `codex` profile, a differently-shaped file) (ADR-0015)
|
||||
- `scripts/sync-marketplace-mirror.sh` generates the third, `.github/plugin/marketplace.json` — Copilot CLI's legacy manifest path. **No apm output profile targets it**: apm ships exactly two marketplace output profiles, `claude` and `codex` (documented in `plugins/kyberforge/.apm/skills/apm-workflow/references/marketplace.md`). The mirror is a byte-identical copy of `.claude-plugin/marketplace.json`, gated by the `check-marketplace-mirror-sync` pre-push hook. Do not expect `apm pack` to refresh it — that assumption is exactly the drift this pair exists to prevent
|
||||
|
||||
Nothing labels a generated file as generated — `plugins/kyberforge/skills/forge/SKILL.md` is byte-identical to its `.apm/` original, with no marker in either. Check the path before you edit. An edit to the mirror is discarded by the next sync and is reported as drift by the `check-plugin-content-sync` pre-push hook, which is the earliest anyone finds out. Details in `docs/spec/architecture.md`.
|
||||
|
||||
## Prefer plugin skills over raw shell
|
||||
|
||||
This repo dogfoods its own plugins. Before shelling out to git, gitea, or lint tooling directly, check whether an installed skill already owns the operation — it usually does:
|
||||
@@ -21,10 +31,13 @@ Fall back to raw shell only when no skill covers it.
|
||||
|
||||
## Setup and testing
|
||||
|
||||
- Install git hooks via `git:pc-run`, wiring all three stages — this repo's `.pre-commit-config.yaml` has no `default_install_hook_types`, so a plain install silently skips `commit-msg` (Conventional Commits) and `pre-push` (tests, manifest check).
|
||||
- Install the `vale` binary — required by the `vale-audit-prefilter-skill`/`-agent` pre-commit hooks, which run on every commit touching a `SKILL.md` or agent `.md` file. Without it the hooks fail with a bare "command not found" and no install pointer. `brew install vale` (macOS), `snap install vale` (Linux), `choco install vale` (Windows), or see https://vale.sh/docs/vale-cli/installation/. No `vale sync` needed — the `Kyberforge` styles are committed under `plugins/kyberforge/.apm/skills/{skill-audit,agent-audit}/assets/vale/styles/`, not downloaded packages (see ADR-0014).
|
||||
- Install git hooks via `git:pc-run`, wiring all three stages — this repo's `.pre-commit-config.yaml` has no `default_install_hook_types`, so a plain install silently skips `commit-msg` (Conventional Commits) and `pre-push` (the 12-hook gate described below).
|
||||
- Install the `apm` CLI — four pre-push hooks shell out to it: `apm-marketplace-check`, `apm-audit-ci`, `apm-pack-check-clean`, and `check-plugin-content-sync` (via `scripts/sync-plugin-content.sh`, which wraps `apm pack`). The first three are bare `apm …` hook entries, so without it the push dies with an unhelpful "command not found". Use `kyberforge:apm-install`, or `curl -sSL https://aka.ms/apm-unix | sh`; verify with `apm --version`.
|
||||
- Install `jq` — required by `scripts/check-manifests.sh` and `scripts/sync-plugin-content.sh`, both pre-push. These at least fail loudly (`Error: jq is required but not installed`).
|
||||
- Install the `vale` binary — required by the `vale-audit-prefilter-skill`/`-agent` pre-commit hooks. Their `files:` patterns are `.apm/`-scoped: `^plugins/[^/]+/\.apm/skills/[^/]+/SKILL\.md$` and `^plugins/[^/]+/\.apm/agents/[^/]+\.agent\.md$`. Only the authoring source triggers them — a `SKILL.md` in the generated mirror matches neither pattern, so prose findings surface only when you edit the file you are supposed to be editing. Without the binary the hooks fail with a bare "command not found" and no install pointer. `brew install vale` (macOS), `snap install vale` (Linux), `choco install vale` (Windows), or see https://vale.sh/docs/vale-cli/installation/. No `vale sync` needed — the `Kyberforge` styles are committed under `plugins/kyberforge/.apm/skills/{skill-audit,agent-audit}/assets/vale/styles/`, not downloaded packages (see ADR-0014).
|
||||
- Run `bash tests/run-tests.sh` before considering any change done — it runs every `test-*.sh` script in the repo plus the bats suite (`--bats-only` for just bats). First run auto-initializes the bats submodules; no manual `git submodule update` needed.
|
||||
- Pushing re-runs the full suite plus `scripts/check-manifests.sh` via the pre-push hook — same commands, so run them locally first.
|
||||
- Pushing runs 12 pre-push hooks, not just the test suite — `run-tests` and `check-manifests`, plus generated-content drift gates (`check-plugin-content-sync`, `check-marketplace-mirror-sync`, `check-vale-style-sync`, `check-scope-walkup-sync`), apm's own gates (`apm-marketplace-check`, `apm-audit-ci`, `apm-pack-check-clean`), host validators (`validate-plugins`, `validate-marketplace`, both needing the `claude` CLI), and `check-release-needed`. Run `pre-commit run --hook-stage pre-push --all-files` locally — one command, the whole gate.
|
||||
- `apm-marketplace-check` needs the network. It resolves every `marketplace.packages[]` entry including the remote `mattpocock-skills` ref, and it is `always_run`, so an unreachable network hard-fails the push. `--offline` is not an escape hatch — it still exits 1 on that entry (`No cached refs (offline)`). To push without a network, skip that one hook using pre-commit's own mechanism: `SKIP=apm-marketplace-check git push`. Skip that hook alone — it is the only one whose failure mode is "no network". Every other pre-push hook is a real local check, and adding it to `SKIP` disarms it silently.
|
||||
- Author commits with `git:git-commits` — it validates Conventional Commits (enforced at `commit-msg`) for you.
|
||||
|
||||
## Key documents
|
||||
|
||||
@@ -27,10 +27,10 @@ A separate product (separate repo) for browsing, editing, and configuring AI dev
|
||||
Reusable slash commands for AI coding tools, defined as `SKILL.md` files following the [Agent Skills open standard](https://agentskills.io). Deployed via plugin — `plugins/<plugin-name>/.apm/skills/<skill-name>/SKILL.md`, available after the plugin is installed (`claude plugin install <name>@<marketplace>`). Skills are self-contained — they cannot reference files outside the plugin directory after install-time caching.
|
||||
|
||||
### Plugin
|
||||
The deployable unit in the plugin marketplace. A plugin bundles one or more skills, agents, hooks, prompts, MCP servers, and optionally a `bin/` directory into a single installable directory. In this repo, plugins live under `plugins/<name>/`, each with its own `apm.yml` + `.apm/{skills,agents,hooks,...}` — this is the authoring source of truth for the plugin's content (ADR-0015). Two categories of tracked output are compiled from that source, never hand-edited: `.claude-plugin/plugin.json` (Claude Code) and `.github/plugin/plugin.json` (Copilot CLI) via `apm pack`/`apm compile`; and, alongside them, a flat `agents/`, `skills/`, `commands/`, `instructions/`, `extensions/` directory mirror plus a merged `hooks.json` at the plugin root, generated by `scripts/sync-plugin-content.sh` — Claude Code's and Copilot's installers convention-scan only these flat root-level paths and have no awareness of `.apm/` nesting at all, so this mirror is what actually makes `.apm/` content discoverable at install time (ADR-0017). Plugins are copied to a cache on install — they cannot reference files outside their own directory. Install a plugin with `claude plugin install <name>@<marketplace>`.
|
||||
The deployable unit in the plugin marketplace. A plugin bundles one or more skills, agents, hooks, prompts, MCP servers, and optionally a `bin/` directory into a single installable directory. In this repo, plugins live under `plugins/<name>/`, each with its own `apm.yml` + `.apm/{skills,agents,hooks,...}` — this is the authoring source of truth for the plugin's content (ADR-0015). Two categories of tracked output are compiled from that source, never hand-edited: `.claude-plugin/plugin.json` (Claude Code) and `.github/plugin/plugin.json` (Copilot CLI) via `apm pack`/`apm compile`; and, alongside them, a flat `agents/`, `skills/`, `commands/`, `instructions/`, `extensions/` directory mirror at the plugin root plus a merged hooks file at `hooks/hooks.json`, generated by `scripts/sync-plugin-content.sh` — Claude Code's and Copilot's installers convention-scan only these flat paths (`hooks/hooks.json` is the convention path for hooks specifically; a root-level `hooks.json` is scanned by nothing and is deleted as stale by a sync — see ADR-0017's 2026-08-14 amendment) and have no awareness of `.apm/` nesting at all, so this mirror is what actually makes `.apm/` content discoverable at install time (ADR-0017). Plugins are copied to a cache on install — they cannot reference files outside their own directory. Install a plugin with `claude plugin install <name>@<marketplace>`.
|
||||
|
||||
### Plugin marketplace
|
||||
A Git repository with a `marketplace.json` manifest listing installable plugins. No backend, registry, or SaaS required — the Git repo is the marketplace. This repo is the `holocron` marketplace. The manifest at `.claude-plugin/marketplace.json` (read by both Claude Code and Copilot CLI) is **compiled output** of `apm pack`, generated from the root `apm.yml`'s `marketplace:` block (owner, build/output config, versioning strategy, and the `packages:` list of installable plugins) — it is not hand-edited. See ADR-0015. `.github/plugin/marketplace.json` is Copilot CLI's legacy manifest path; apm has no output profile for it (only `claude` and `codex`, and `codex`'s is a differently-shaped file at `.agents/plugins/marketplace.json`), so `scripts/sync-marketplace-mirror.sh` keeps it byte-identical to `.claude-plugin/marketplace.json`, checked at pre-push. Each listed package's `source:` still points at that plugin's own `plugins/<name>/` root, not at an `apm pack` build artifact — which is why that root also carries the flat `agents/`/`skills/`/`commands/`/`hooks.json` content mirror described under "Plugin" (ADR-0017): without it, an install from this marketplace finds a valid manifest but no discoverable content.
|
||||
A Git repository with a `marketplace.json` manifest listing installable plugins. No backend, registry, or SaaS required — the Git repo is the marketplace. This repo is the `holocron` marketplace. The manifest at `.claude-plugin/marketplace.json` (read by both Claude Code and Copilot CLI) is **compiled output** of `apm pack`, generated from the root `apm.yml`'s `marketplace:` block (owner, build/output config, versioning strategy, and the `packages:` list of installable plugins) — it is not hand-edited. See ADR-0015. `.github/plugin/marketplace.json` is Copilot CLI's legacy manifest path; apm has no output profile for it (only `claude` and `codex`, and `codex`'s is a differently-shaped file at `.agents/plugins/marketplace.json`), so `scripts/sync-marketplace-mirror.sh` keeps it byte-identical to `.claude-plugin/marketplace.json`, checked at pre-push. Each listed package's `source:` still points at that plugin's own `plugins/<name>/` root, not at an `apm pack` build artifact — which is why that root also carries the flat `agents/`/`skills/`/`commands/`/`hooks/hooks.json` content mirror described under "Plugin" (ADR-0017): without it, an install from this marketplace finds a valid manifest but no discoverable content.
|
||||
|
||||
### HITL (human-in-the-loop)
|
||||
Agent pauses before a consequential action; human approves before execution. Required for irreversible or high-stakes actions (architecture changes, production deployments, security configuration). The agent drafts the change plan and waits — it does not proceed autonomously. Contrast with HOTL.
|
||||
@@ -67,7 +67,7 @@ A skill pair in the `core` plugin for writing, updating, and reviewing a repo's
|
||||
A companion skill (`core` plugin) that detects a target repo's provider-specific instruction file (`CLAUDE.md`, `.cursor/rules/*.mdc`, `copilot-instructions.md`, etc.) and, where it duplicates content AGENTS.md should own, converts it into a thin adapter that imports AGENTS.md — mirroring this repo's own ADR-0002/ADR-0003 two-tier adapter pattern. Self-validates via its own bundled deterministic script (`scripts/validate-adapter.sh`: checks for an import reference, no duplicated headings, size threshold) rather than a separate paired audit skill — the check is mechanical, so a script suffices per governance.md's "prefer deterministic code for repeatable tasks." `agentsmd-author` calls this skill via skill composition when it detects an existing provider file with overlapping content.
|
||||
|
||||
### lint plugin
|
||||
A standalone, repo-agnostic plugin (`plugins/lint/`) for configuring and running linters — not scoped to kyberforge's own meta-tooling. First linter is Vale (prose style linting), split into two skills per the git/gitea per-concern pattern: `vale-config` (setup — `.vale.ini`, `StylesPath`, styles) and `vale-run` (invoke Vale, interpret/report findings). A `lint-runner` agent composes these for isolated-context lint sweeps; it is report-only (no `Edit` tool) — it flags findings, it does not rewrite prose. Vale's research docs (`docs/research/docs/vale/`) moved from `plugins/kyberforge/` to `plugins/lint/` to keep the provenance chain same-plugin.
|
||||
A standalone, repo-agnostic plugin (`plugins/lint/`) for configuring and running linters — not scoped to kyberforge's own meta-tooling. First linter is Vale (prose style linting), split into two skills per the git/gitea per-concern pattern: `vale-config` (setup — `.vale.ini`, `StylesPath`, styles) and `vale-run` (invoke Vale, interpret/report findings). A `lint-runner` agent composes these for isolated-context lint sweeps; it is report-only **by instruction, not by capability** — its body states "You never edit files" and "Do not edit, fix, or rewrite any flagged content", but nothing enforces that. It previously carried `tools: Bash, Read, Grep, Glob`, which withheld `Edit` outright; plugin-scope APM agents cannot express a `tools:` field at all (ADR-0016 — `apm compile` copies frontmatter verbatim to both Claude Code and Copilot, whose `tools:` vocabularies are incompatible, so a value correct for one harness is wrong for the other), so `plugins/lint/.apm/agents/lint-runner.agent.md` now declares only `name`/`description`/`source_keys` and inherits every tool, `Edit` included. ADR-0016 accepted this loss of enforcement knowingly; the restriction survives as prose the agent is expected to follow. Vale's research docs (`docs/research/docs/vale/`) moved from `plugins/kyberforge/` to `plugins/lint/` to keep the provenance chain same-plugin.
|
||||
|
||||
### Vale audit prefilter (skill-audit / agent-audit)
|
||||
Wiring Vale as a deterministic prefilter for `skill-audit`/`agent-audit`'s Description dimension (ADR motivation: issue #84) is repo-specific, not part of the generic `lint` plugin, so it doesn't live in `plugins/lint/` — but per ADR-0014 it also doesn't live at the repo root anymore. Two copies live inside `plugins/kyberforge/`, one per skill, since a plugin's cache-install only copies each skill's own files (no cross-skill sharing): `plugins/kyberforge/.apm/skills/agent-audit/assets/vale/` is canonical (`.vale.ini` plus a custom `Kyberforge` style covering description-opener banning ("This skill/agent..."), vague-capability wording ("helps with", "utilize", ...), and generic "see references/ for details" padding — and a `KyberforgeCopilot` style scoped only to `.agent.md` files for the Copilot-only "Use proactively has no effect" check), and `plugins/kyberforge/.apm/skills/skill-audit/assets/vale/` is a smaller duplicate (`Kyberforge` only, scoped to `SKILL.md`) kept in sync by `scripts/check-vale-style-sync.sh` (pre-push). A root-level `.pre-commit-hooks.yaml` exposes both copies (plus `skill-size-check`) so any external repo can enforce the same rules via `repo: <this-repo-url>, rev: <tag>` in its own `.pre-commit-config.yaml` — pre-commit clones the pinned rev into its own cache, independent of whether Claude Code or the `kyberforge` plugin is installed at all, and the same mechanism covers CI (`pre-commit run --all-files`). This repo's own `vale-audit-prefilter-skill`/`-agent` pre-commit hooks consume the identical plugin-bundled copies via `repo: local` (not a third root copy, and not a pinned self-reference — a pinned self-reference would lint working-tree edits against the last tagged release rather than the change being made). Every rule is `level: error` and every alert is a FAIL — no ignorable tier, same as shellcheck, the test suite, and conventional-pre-commit. Graded severities do not work here: Vale's exit code keys on `error` alerts alone, so `warning`/`suggestion` rules exit 0 and pre-commit swallows the output of a passing hook, leaving them invisible and blocking nothing. `MinAlertLevel` and `--minAlertLevel` are correspondingly absent from `.vale.ini` and the hook, being no-ops under this model. Vale covers the pattern-matchable sub-checks named in issue #84 (imperative opener, vague filler, `Use proactively`, generic reference-pointer padding) plus, per ADR-0013, one body-wide prose-pattern check ("There is/are" sentence openers) — everything else about body discipline (defaults-vs-menus, why-rationale, non-pattern-matchable judgment calls), near-miss exclusion strength, and control calibration stays LLM judgment.
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
**Supersedes:** ADR-0011 (provider-agnostic issue tracker with file-based default — archived during refactoring)
|
||||
|
||||
> **Note on the ADR-0011 number.** Every "ADR-0011" on this page means the *archived* provider-agnostic issue tracker ADR, which no longer exists in `docs/adr/` — it was removed when it was superseded, and the number 0011 was later reused for an unrelated decision, `docs/adr/0011-gitea-skill-deep-modules.md` (the gitea skill's split into deep modules). That file is not the ADR referenced below. The number is not renumbered here: these ADRs are a published record and renumbering would break every citation that already points at either one. The archived text is recoverable from git history.
|
||||
|
||||
ADR-0011 established a provider-agnostic model with `docs/issues/NNNN-<slug>.md` as the file-based default, switching to Gitea MCP at runtime when available. The interim model was justified because Gitea would not be configured until after Chunk 3, and the repo needed to work before then.
|
||||
|
||||
Gitea is now configured and in active use. The condition in ADR-0011 has been met. This ADR supersedes it.
|
||||
|
||||
@@ -65,8 +65,13 @@ cannot be expressed as a `--config` argument at all — the config path has to b
|
||||
the process, from the script's own location. `vale-wrap.sh` accordingly defaults to its sibling
|
||||
`assets/vale/.vale.ini`, resolved from `${BASH_SOURCE[0]}`, whenever no `--config` is supplied;
|
||||
an explicit `--config` from any other caller still wins and still resolves against the caller's
|
||||
cwd, so both audit skills' Step 1 (`--config assets/vale/.vale.ini`) is unaffected. Both
|
||||
manifests now carry the identical argument-free `entry:`. Keeping them identical is part of the
|
||||
cwd. Both audit skills' Step 1 passes no `--config` either, for the same reason and one more: a
|
||||
relative `--config assets/vale/.vale.ini` resolves against the cwd, not against the skill
|
||||
directory the wrapper path was resolved from, so it yields `E100 Runtime error … does not exist`
|
||||
and exit 2 — which both skills' fallback misreads as "vale unavailable" and silently downgrades
|
||||
to full LLM judgment, the exact failure the self-location exists to prevent. Both `SKILL.md` Step
|
||||
1 sections say so explicitly ("Pass no `--config`"), and both manifests now carry the identical
|
||||
argument-free `entry:`. Keeping them identical is part of the
|
||||
decision: the local `repo: local` hook resolved its `--config` correctly only because the
|
||||
consuming repo *was* this repo, and that one difference is why three review rounds exercised a
|
||||
code path no external consumer ever takes.
|
||||
|
||||
@@ -52,7 +52,8 @@ new hand-maintained manifest format.
|
||||
`apm-orchestrate` (issue #88, already landed on this branch) fully replace what these two skills
|
||||
did. `plugin-author`/`marketplace-author` were deleted in issue #90's execution.
|
||||
- Translating the existing plugins into `apm.yml` + `.apm/` and running the real conversion was
|
||||
executed in issue #90 (https://git.dev.rkdr.net/Defame1297/holocron/issues/90, closed).
|
||||
executed under issue #90 (https://git.dev.rkdr.net/Defame1297/holocron/issues/90), which tracks
|
||||
that work through to merge.
|
||||
- `CONTEXT.md`'s "Plugin"/"Plugin marketplace" glossary entries were rewritten in issue #90 to
|
||||
describe the compiled-output model directly, rather than carrying a forward-pointer to this ADR.
|
||||
|
||||
@@ -119,9 +120,34 @@ correction) sorted what they document into three buckets:
|
||||
issue #90 had to re-author plugin-scope agents: `.apm/agents/*.agent.md` compiles verbatim to
|
||||
both Claude and Copilot, so those files carry only `name`/`description`/`model`/`source_keys` —
|
||||
existing dual-file `<name>.md`+`<name>.agent.md` pairs could not be raw-moved, only re-authored.
|
||||
- Two follow-up issues tracked the remaining work, both done: #89 (`skill-author`/`agent-author`
|
||||
routing adaptation, merged in #93) and #90 (the actual repo conversion, which also deleted
|
||||
`plugin-author`/`marketplace-author`).
|
||||
- Two follow-up issues tracked the remaining work: #89 (`skill-author`/`agent-author` routing
|
||||
adaptation — closed, merged in #93) and #90 (the actual repo conversion, which also deleted
|
||||
`plugin-author`/`marketplace-author` — tracked through to merge; treat #90's own state as the
|
||||
authority on whether it has landed, not this line).
|
||||
- **`displayName` is gone from all six compiled `plugin.json` files, and `owner.email` from the
|
||||
marketplace manifest — accepted, not overlooked.** `apm.yml` has no key that compiles to either,
|
||||
so the conversion dropped both: every `plugins/<name>/.claude-plugin/plugin.json` now carries
|
||||
`author`/`description`/`homepage`/`keywords`/`license`/`name`/`repository`/`version` (plus
|
||||
`mcpServers` for `bin`) and no `displayName`, and `.claude-plugin/marketplace.json`'s `owner`
|
||||
block is `{name, url}` only. Both fields are optional —
|
||||
`plugins/kyberforge/docs/research/docs/claude-code-plugins/api-reference.md:14` lists
|
||||
`displayName` as `Required: No`, "Human-readable name shown in plugin manager" — which is why
|
||||
`claude plugin validate --strict` still passes on all six. The visible cost is that the plugin
|
||||
manager falls back to the bare `name` as each plugin's label. Accepted as the price of `apm.yml`
|
||||
being the single authoring source: re-injecting `displayName` post-compile would mean a second
|
||||
`reinject_*` workaround of the kind ADR-0017's amendment reserves for fields apm strips on a
|
||||
factually wrong premise, and apm's premise here is simply that the key does not exist in its
|
||||
schema.
|
||||
- **`mattpocock-skills` is now version-pinned, and the pin is maintained by hand.** Pre-conversion
|
||||
the entry was `{"repo": "mattpocock/skills", "source": "github"}` — an unpinned reference that
|
||||
tracked the upstream default branch, so consumers got whatever was on it at install time. Root
|
||||
`apm.yml` now declares `version: "^1.2.0"` for it, which `apm pack` resolves and freezes into
|
||||
`.claude-plugin/marketplace.json` as `ref: v1.2.3` + an explicit `sha`. Consumers get a
|
||||
reproducible version instead of a moving target, which is the improvement; the cost is that
|
||||
nothing advances it. apm has no version-bump automation (established under "Versioning" in issue
|
||||
#90's plan), so picking up a new upstream release means a human editing the `version:` range in
|
||||
root `apm.yml` and re-running `apm pack`. Left un-bumped, the marketplace pins an ageing release
|
||||
indefinitely and silently.
|
||||
- **Caveat on "Status: executed" above:** issue #90's own execution comment flagged, before merge,
|
||||
that Claude Code's ability to actually load content out of `.apm/` was unverified — that caveat
|
||||
turned out to be a real defect, not a formality: the native installer has zero awareness of
|
||||
|
||||
@@ -25,7 +25,14 @@ Skills are **not** deployed by `install.sh`. They are distributed as plugins and
|
||||
|
||||
## Plugin model
|
||||
|
||||
Skills, agents, MCP servers, and hooks are distributed as self-contained plugin units under `plugins/`. Each plugin has a `plugin.json` manifest and is installed independently via `claude plugin install`.
|
||||
Skills, agents, MCP servers, and hooks are distributed as self-contained plugin units under `plugins/`, installed independently via `claude plugin install <name>@holocron`. Each plugin is an **apm package**: `plugins/<name>/apm.yml` plus a hand-authored `plugins/<name>/.apm/{skills,agents,hooks,commands,instructions,extensions}/` tree (ADR-0015). There is no hand-maintained `plugin.json` — every manifest and every host-visible content directory is compiled from that source.
|
||||
|
||||
Two compilers produce the plugin roots you see in the tree:
|
||||
|
||||
- **`apm pack` compiles the manifests** (ADR-0015). Per plugin: `.claude-plugin/plugin.json` and `.github/plugin/plugin.json`, both generated from `plugins/<name>/apm.yml`. Repo-wide, from the root `apm.yml`'s `marketplace:` block: `.claude-plugin/marketplace.json` (apm's `claude` output profile) and `.agents/plugins/marketplace.json` (its `codex` profile, a differently-shaped file). Those two are the only marketplace outputs apm has profiles for — the third root manifest, `.github/plugin/marketplace.json` (Copilot CLI's legacy path), is a byte-identical mirror of the Claude one maintained by `scripts/sync-marketplace-mirror.sh` and gated by the `check-marketplace-mirror-sync` pre-push hook.
|
||||
- **`scripts/sync-plugin-content.sh` compiles the content mirror** (ADR-0017). It wraps `apm pack --format plugin` and copies the resulting bundle's flat `agents/`, `skills/`, `commands/`, `instructions/`, `extensions/`, and merged `hooks/hooks.json` back to the plugin root. Claude Code's installer convention-scans those flat paths and has no `.apm/` awareness whatsoever, so the mirror exists solely to satisfy the host's discovery contract.
|
||||
|
||||
`.apm/` is the sole hand-edited authoring source for plugin content. An edit made in the flat mirror is discarded by the next sync and is reported as drift by the `check-plugin-content-sync` pre-push hook. Hand-authored material that is not an `.apm/` primitive — `README.md`, `docs/`, `bin/`, `sources.md`, and `.mcp.json` — lives at the plugin root and is untouched by either compiler.
|
||||
|
||||
## Governance layer
|
||||
|
||||
@@ -37,7 +44,7 @@ The governance layer has two phases:
|
||||
|
||||
## AGENTS.md pattern
|
||||
|
||||
This repo uses two `AGENTS.md` files as the provider-agnostic source of always-on rules (ADR-0012):
|
||||
This repo uses two `AGENTS.md` files as the provider-agnostic source of always-on rules (ADR-0003):
|
||||
|
||||
- **Repo-level `AGENTS.md`** — instructions for agents working inside this repo (structure, key rules). Imported by repo `CLAUDE.md` via `@AGENTS.md`.
|
||||
- **Global `core/AGENTS.md`** — Communication and Behavior rules that apply across all projects. Deployed to `~/.agents/AGENTS.md`; imported by `~/.claude/CLAUDE.md` via `@~/.agents/AGENTS.md`.
|
||||
|
||||
@@ -30,10 +30,12 @@ copilot plugin install ./plugins/bin
|
||||
|
||||
## Contents
|
||||
|
||||
| Component | Path | Description |
|
||||
| -------------| ------------------------------------------------------| ---------------------------------------------------------------|
|
||||
| Skills | `skills/` | Slash commands available after install |
|
||||
| Agents | `agents/` | Role-based agents (`.md` for Claude, `.agent.md` for Copilot) |
|
||||
| Component | Path | Description |
|
||||
|---|---|---|
|
||||
| Skills | `.apm/skills/` → `skills/` | Slash commands available after install |
|
||||
| MCP servers | `.mcp.json` | The `obsidian` server (`npx @bitbonsai/mcpvault@latest docs/`), hand-authored at the plugin root and reinjected into both compiled `plugin.json` manifests |
|
||||
|
||||
`.apm/` is the authoring source; `skills/` is the generated mirror plugin hosts scan (ADR-0017). This plugin ships no agents. It is the only plugin here with a non-empty `.mcp.json`, which is why its compiled manifests are the only ones carrying an `mcpServers` block.
|
||||
|
||||
## Author
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# core
|
||||
|
||||
Cross-cutting utility skills for everyday AI-assisted coding — triage, diagnosis, architecture review, and session navigation.
|
||||
Skills for authoring and auditing a repo's AGENTS.md and the provider adapter files that defer to it.
|
||||
|
||||
## Install
|
||||
|
||||
@@ -32,7 +32,9 @@ copilot plugin install ./plugins/core
|
||||
|
||||
| Component | Path | Description |
|
||||
|---|---|---|
|
||||
| Skills | `skills/` | Slash commands available after install |
|
||||
| Skills | `.apm/skills/` → `skills/` | Slash commands available after install |
|
||||
|
||||
`.apm/` is the authoring source; `skills/` is the generated mirror plugin hosts scan (ADR-0017).
|
||||
|
||||
## Skills
|
||||
|
||||
|
||||
@@ -7,3 +7,11 @@
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/microsoft-apm/sources.md
|
||||
- **Contributing files:** SKILL.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## apm-github-repo
|
||||
|
||||
- **URL:** https://github.com/microsoft/apm
|
||||
- **Description:** APM's own Python source (`src/apm_cli/`), read directly for schema and compile-mapping ground truth where Context7's doc snippets were thin. Informed the research doc's primitive-schema and releasing pages; nothing in this skill's install/runtime guidance derives from it.
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/microsoft-apm/sources.md
|
||||
- **Contributing files:** (none)
|
||||
- **Status:** `referenced`
|
||||
|
||||
@@ -37,6 +37,31 @@ version: 1.0.0
|
||||
|
||||
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`).
|
||||
|
||||
@@ -4,6 +4,7 @@ source_keys:
|
||||
- context7-microsoft-apm
|
||||
- context7-websites-code-claude
|
||||
- claude-code-plugins-docs
|
||||
- apm-github-repo
|
||||
---
|
||||
|
||||
## Building a marketplace from a producer repo
|
||||
@@ -68,6 +69,33 @@ marketplace:
|
||||
|
||||
Without this block, the default versioning strategy ties every listed package to the marketplace/root version.
|
||||
|
||||
## Bumping the catalog's own version (repo policy)
|
||||
|
||||
The section above is apm's *mechanic* — how per-package versions are declared and how
|
||||
`marketplace.versioning.strategy` resolves them. This section is *policy*: apm has no version-bump
|
||||
automation, so the one number apm will never pick for you is the catalog's own
|
||||
`marketplace.version` in the root `apm.yml`. Bump it by hand, in the same commit as the change that
|
||||
earned it:
|
||||
|
||||
- **Minor** when a `marketplace.packages[]` entry is added or removed. The catalog's contents
|
||||
changed — a consumer resolving it now gets a different set of installable packages.
|
||||
- **Patch** when only `marketplace:`-block fields change and the set of packages is unchanged: the
|
||||
catalog description, owner, `build:`/`outputs:` config, or an existing entry's `version:`,
|
||||
description, or category. The catalog describes the same packages; only its metadata moved. An
|
||||
entry's `version:` is the most frequent of these by far — under `per_package` it moves here every
|
||||
time any package bumps (see `references/configure.md`), and that alone earns the catalog patch.
|
||||
|
||||
Keep the root `apm.yml`'s top-level `version:` in step with `marketplace.version`. They are separate
|
||||
keys — the top-level one is not inherited into the compiled `marketplace.json`, but `apm audit`
|
||||
reads it — so letting them diverge produces two different answers to "what version is this catalog".
|
||||
|
||||
Editing a package's *own* `.apm/` content is a different bump against a different number — see
|
||||
`references/configure.md`. Note what the tooling does and does not catch: `apm pack --check-clean`
|
||||
regenerates every marketplace output and diffs it against what is on disk, so a bump made in
|
||||
`apm.yml` but never re-packed fails the gate. A bump you never made at all fails nothing — no apm
|
||||
flag infers a required version change from a content diff, which is why this is policy and not a
|
||||
hook.
|
||||
|
||||
## Which mechanism to use
|
||||
|
||||
- **Local packages, no distribution needed yet** — local-path dependencies in `apm.yml` (`./packages/my-shared-skills`); no marketplace or registry involved.
|
||||
|
||||
@@ -8,6 +8,14 @@
|
||||
- **Contributing files:** SKILL.md, references/configure.md, references/install.md, references/marketplace.md, references/compile.md, references/audit.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## apm-github-repo
|
||||
|
||||
- **URL:** https://github.com/microsoft/apm
|
||||
- **Description:** APM's own Python source (`src/apm_cli/`), read directly for schema and compile-mapping ground truth where Context7's doc snippets were thin. Backs the marketplace output-profile claim (`apm_cli/marketplace/output_profiles.py` — only `claude` and `codex` profiles exist, so there is no native Copilot marketplace output) and the `apm pack --check-clean`/`--check-versions` semantics.
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/microsoft-apm/sources.md
|
||||
- **Contributing files:** references/marketplace.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## context7-websites-code-claude
|
||||
|
||||
- **URL:** context7:/websites/code_claude
|
||||
|
||||
@@ -30,25 +30,31 @@ copilot plugin install ./plugins/kyberforge
|
||||
|
||||
## Contents
|
||||
|
||||
Authoring source lives in `.apm/`. The `skills/`, `agents/`, and `hooks/hooks.json` paths below are the generated mirror that plugin hosts actually scan — produced by `scripts/sync-plugin-content.sh`, never hand-edited (ADR-0017).
|
||||
|
||||
| Component | Path | Description |
|
||||
|---|---|---|
|
||||
| Skills | `skills/` | Slash commands available after install |
|
||||
| Agents | `agents/` | Role-based agents (`.md` for Claude, `.agent.md` for Copilot) |
|
||||
| Hooks | `hooks/hooks.json` (Claude) / `hooks.json` (Copilot) | Event-triggered automation |
|
||||
| MCP servers | `.mcp.json` | Model Context Protocol server definitions |
|
||||
| Skills | `.apm/skills/` → `skills/` | Slash commands available after install |
|
||||
| Agents | `.apm/agents/*.agent.md` → `agents/` | Role-based agents; one vendor-neutral `.agent.md` per agent, copied verbatim to both targets (ADR-0016) |
|
||||
| Hooks | `.apm/hooks/` → `hooks/hooks.json` | Event-triggered automation — read by Claude Code only, see below |
|
||||
| MCP servers | `.mcp.json` | Model Context Protocol server definitions (hand-authored at the plugin root) |
|
||||
|
||||
**Hooks are Claude Code-only in practice.** Claude Code convention-scans `hooks/hooks.json` at the plugin root, so that file is live. Copilot CLI has no default hooks path — `agents` and `skills` default to `agents/` and `skills/`, but `hooks` defaults to nothing (`docs/research/docs/github-copilot-plugins/configuration.md:47`), so Copilot reads hooks only via an explicit `"hooks": "hooks.json"` pointer in `plugin.json` (`docs/research/docs/github-copilot-plugins/examples.md:49`). apm's manifest compiler strips pointer fields from every manifest it generates, so neither `.claude-plugin/plugin.json` nor `.github/plugin/plugin.json` carries one, and re-injecting it is the option ADR-0017 explicitly rejected. Copilot therefore loads no hooks from this plugin — and did not load them from the old root-level `hooks.json` either. The Copilot half of this row is aspirational, not current behaviour.
|
||||
|
||||
## Skills
|
||||
|
||||
| Skill | Description |
|
||||
|---|---|
|
||||
| `forge` | Grill an unclassified "I want to add something" request, decide whether it's a skill, agent, plugin, or marketplace entry, then route to the matching author skill |
|
||||
| `skill-author` | Create or improve a skill from scratch, audit findings, or inline feedback |
|
||||
| `skill-audit` | Audit a skill directory against the agentskills.io spec and produce a findings report |
|
||||
| `agent-author` | Author an agent definition file |
|
||||
| `pc-author` | Create, add, remove, and configure `.pre-commit-config.yaml` |
|
||||
| `pc-run` | Install, run, autoupdate, and maintain the pre-commit setup |
|
||||
| `agent-audit` | Audit an agent definition across structure, provider safety, description and body quality, and provenance; produces a findings report |
|
||||
| `apm-install` | Install or upgrade the apm CLI and set up the agent runtimes it drives (Copilot CLI, Codex, Gemini, generic llm) |
|
||||
| `apm-workflow` | Author apm.yml, scaffold an apm package/marketplace, install dependencies, and compile/pack/publish/audit apm content |
|
||||
|
||||
Pre-commit tooling (`pc-author`, `pc-run`) lives in the `git` plugin, not here.
|
||||
|
||||
## Author
|
||||
|
||||
Defame1297
|
||||
|
||||
@@ -2,12 +2,7 @@
|
||||
|
||||
Plugin documentation. Not read automatically by Claude Code or GitHub Copilot CLI — reference specific files from skill bodies or agent prompts as needed.
|
||||
|
||||
## Files
|
||||
|
||||
| Path | Purpose |
|
||||
|------|---------|
|
||||
| `plugin-marketplace-architecture.md` | Claude Code vs Copilot CLI divergence, two-manifest pattern, plugin constraints, cross-tool compatibility |
|
||||
| `adding-agents.md` | How to add agent definitions to the kyberforge plugin |
|
||||
This directory currently holds no standalone documents of its own — everything under it is research material.
|
||||
|
||||
## research/
|
||||
|
||||
@@ -16,5 +11,9 @@ Upstream reference material gathered during skill authoring. Not shipped with th
|
||||
| Path | Purpose |
|
||||
|------|---------|
|
||||
| `research/docs/agentskillsio/` | agentskills.io spec, skill authoring, description optimization, eval design, scripts |
|
||||
| `research/docs/agentsmd/` | agents.md format spec and cross-tool configuration reference |
|
||||
| `research/examples/skill-write/` | Upstream skill examples reviewed when authoring skill-write and skill-audit |
|
||||
| `research/docs/claude-code-plugins/` | Claude Code plugin and marketplace manifests, plugin directory layout, agent definition format, `claude plugin validate` behaviour |
|
||||
| `research/docs/github-copilot-plugins/` | Copilot CLI plugin manifest and marketplace format, agent definition format, Copilot extensions and SDK |
|
||||
| `research/docs/microsoft-apm/` | apm CLI reference, `apm.yml` schema, primitive schemas (agent, prompt, instructions, hooks), monorepo repo shapes, marketplace/registries, packing and releasing |
|
||||
| `research/examples/skill-write/` | Upstream skill examples reviewed when authoring skill-author and skill-audit |
|
||||
|
||||
AGENTS.md research moved to `plugins/core/docs/research/docs/agentsmd/` when the AGENTS.md skills landed in the `core` plugin (ADR-0012) — it is no longer part of kyberforge's provenance chain.
|
||||
|
||||
@@ -7,3 +7,11 @@
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/microsoft-apm/sources.md
|
||||
- **Contributing files:** SKILL.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## apm-github-repo
|
||||
|
||||
- **URL:** https://github.com/microsoft/apm
|
||||
- **Description:** APM's own Python source (`src/apm_cli/`), read directly for schema and compile-mapping ground truth where Context7's doc snippets were thin. Informed the research doc's primitive-schema and releasing pages; nothing in this skill's install/runtime guidance derives from it.
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/microsoft-apm/sources.md
|
||||
- **Contributing files:** (none)
|
||||
- **Status:** `referenced`
|
||||
|
||||
@@ -37,6 +37,31 @@ version: 1.0.0
|
||||
|
||||
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`).
|
||||
|
||||
@@ -4,6 +4,7 @@ source_keys:
|
||||
- context7-microsoft-apm
|
||||
- context7-websites-code-claude
|
||||
- claude-code-plugins-docs
|
||||
- apm-github-repo
|
||||
---
|
||||
|
||||
## Building a marketplace from a producer repo
|
||||
@@ -68,6 +69,33 @@ marketplace:
|
||||
|
||||
Without this block, the default versioning strategy ties every listed package to the marketplace/root version.
|
||||
|
||||
## Bumping the catalog's own version (repo policy)
|
||||
|
||||
The section above is apm's *mechanic* — how per-package versions are declared and how
|
||||
`marketplace.versioning.strategy` resolves them. This section is *policy*: apm has no version-bump
|
||||
automation, so the one number apm will never pick for you is the catalog's own
|
||||
`marketplace.version` in the root `apm.yml`. Bump it by hand, in the same commit as the change that
|
||||
earned it:
|
||||
|
||||
- **Minor** when a `marketplace.packages[]` entry is added or removed. The catalog's contents
|
||||
changed — a consumer resolving it now gets a different set of installable packages.
|
||||
- **Patch** when only `marketplace:`-block fields change and the set of packages is unchanged: the
|
||||
catalog description, owner, `build:`/`outputs:` config, or an existing entry's `version:`,
|
||||
description, or category. The catalog describes the same packages; only its metadata moved. An
|
||||
entry's `version:` is the most frequent of these by far — under `per_package` it moves here every
|
||||
time any package bumps (see `references/configure.md`), and that alone earns the catalog patch.
|
||||
|
||||
Keep the root `apm.yml`'s top-level `version:` in step with `marketplace.version`. They are separate
|
||||
keys — the top-level one is not inherited into the compiled `marketplace.json`, but `apm audit`
|
||||
reads it — so letting them diverge produces two different answers to "what version is this catalog".
|
||||
|
||||
Editing a package's *own* `.apm/` content is a different bump against a different number — see
|
||||
`references/configure.md`. Note what the tooling does and does not catch: `apm pack --check-clean`
|
||||
regenerates every marketplace output and diffs it against what is on disk, so a bump made in
|
||||
`apm.yml` but never re-packed fails the gate. A bump you never made at all fails nothing — no apm
|
||||
flag infers a required version change from a content diff, which is why this is policy and not a
|
||||
hook.
|
||||
|
||||
## Which mechanism to use
|
||||
|
||||
- **Local packages, no distribution needed yet** — local-path dependencies in `apm.yml` (`./packages/my-shared-skills`); no marketplace or registry involved.
|
||||
|
||||
@@ -8,6 +8,14 @@
|
||||
- **Contributing files:** SKILL.md, references/configure.md, references/install.md, references/marketplace.md, references/compile.md, references/audit.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## apm-github-repo
|
||||
|
||||
- **URL:** https://github.com/microsoft/apm
|
||||
- **Description:** APM's own Python source (`src/apm_cli/`), read directly for schema and compile-mapping ground truth where Context7's doc snippets were thin. Backs the marketplace output-profile claim (`apm_cli/marketplace/output_profiles.py` — only `claude` and `codex` profiles exist, so there is no native Copilot marketplace output) and the `apm pack --check-clean`/`--check-versions` semantics.
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/microsoft-apm/sources.md
|
||||
- **Contributing files:** references/marketplace.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## context7-websites-code-claude
|
||||
|
||||
- **URL:** context7:/websites/code_claude
|
||||
|
||||
Reference in New Issue
Block a user