Compare commits
10 Commits
4aab9d327c
...
6cb47f81f6
| Author | SHA1 | Date | |
|---|---|---|---|
| 6cb47f81f6 | |||
| 0c0df46ac9 | |||
| 59aaec4ed6 | |||
| 92ba9abe7c | |||
| 38efd2be67 | |||
| bdff6fdb3c | |||
| b25412bf39 | |||
| 79c60715dc | |||
| 264a5dbd67 | |||
| aa982b9d26 |
@@ -36,7 +36,7 @@ Fall back to raw shell only when no skill covers it.
|
||||
- **Do not add repo-owned keys to `.claude/settings.json`.** apm treats it as its own deployed artifact and `apm audit --ci` replays the install and diffs, so anything apm would not have written is permanent drift that fails the `apm-audit-ci` pre-push hook. A hook you want here is authored in `plugins/<name>/.apm/hooks/` and deployed by apm, never hand-written into that file. The `SessionStart` entry already in it is exactly that: kyberforge authors it in `plugins/kyberforge/.apm/hooks/hooks.json` and apm merges it in, so it is apm's own output, it is what the replay expects, and it belongs in the commit — do not strip it (ADR-0019). Machine-specific settings go in the gitignored `.claude/settings.local.json`; shared enforcement goes in `.pre-commit-config.yaml`.
|
||||
- **`apm.lock.yaml` turning up modified is expected, not a bug.** kyberforge's `SessionStart` hook runs `apm outdated` at startup and `apm update --yes` when something is behind, which rewrites the lock. Commit or discard it deliberately.
|
||||
- **A `.apm/` edit is not live in this session until it is pushed.** The six dependencies resolve from the holocron remote, unpinned against the default branch. `apm install` deploys from the lock; `apm update` is what re-resolves refs.
|
||||
- **The ADR-0020 skill gates ship hot, with no baseline.** Three skills still exceed a FAIL tier, all in `kyberforge`: `apm-workflow` (817-char description), `forge` (648 chars, 1,093-word body) and `apm-install` (514 chars). Editing any of those three *for any reason* means retrofitting it to the contract first — a one-line fix cannot be committed until the skill complies. Deliberate; tracked as Gitea issue #99, which is retrofitting the corpus plugin by plugin and has `kyberforge` left. **No routing target dangles any more**, and `tests/test-adr0020-targets.sh` now pins that set as empty, so a new boundary clause naming a non-existent skill fails the suite rather than joining a backlog. The `Kyberforge.CompositionNote` Vale rule fires nowhere, but `skill-size-check` does not cover the Vale half and any new description can reintroduce it, so check both: `pre-commit run --all-files`.
|
||||
- **The ADR-0020 skill gates ship hot, with no baseline — and the corpus is now clean.** All 39 skills clear both FAIL tiers: no description over 400 characters, no body over 900 words (counted body-only). Issue #99 retrofitted them plugin by plugin and `kyberforge` was the last wave. Because nothing is grandfathered, the gates now bite on first commit — a new skill, or an edit that pushes a description past 400, is blocked until it complies. **No routing target dangles**, and `tests/test-adr0020-targets.sh` pins that set as empty, so a new boundary clause naming a non-existent skill fails the suite rather than joining a backlog. Two blind spots survive: `skill-size-check` does not cover the Vale half, so `Kyberforge.CompositionNote` fires nowhere today but any new description can reintroduce it; and the `Kyberforge` style is scoped `[**/SKILL.md]`, so every `references/` file is unlinted — which matters because the contract's own remedy is to move prose *into* `references/`, out of the prose gate's reach. Check both: `pre-commit run --all-files`.
|
||||
- **Run `bash tests/run-tests.sh --strict` before considering any change done.** Keep the flag: without it a suite whose dependency is missing exits 77 and is counted SKIPPED rather than failed, so the run goes green having verified less than it claims.
|
||||
- **Before pushing, rehearse the gate locally:** `pre-commit run --hook-stage pre-push --all-files`. It runs the 14 pre-push hooks this repo authors itself plus pre-commit's 2 `meta` hooks, so it prints 16; `check-release-needed` passes without checking anything, because it needs a real push to `main`. `docs/spec/gates.md` reconciles both.
|
||||
- **Pushing without a network** needs `SKIP=apm-marketplace-check,apm-pack-check-clean git push` — those two resolve a remote marketplace entry via `git ls-remote`. Skip only those two; the rest are real local checks, and adding one to `SKIP` disarms it silently.
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
---
|
||||
name: caveman
|
||||
disable-model-invocation: true
|
||||
description: >
|
||||
Ultra-compressed communication mode. Cuts token usage ~75% by dropping
|
||||
filler, articles, and pleasantries while keeping full technical accuracy.
|
||||
Use when user says "caveman mode", "talk like caveman", "use caveman",
|
||||
"less tokens", "be brief", or invokes /caveman.
|
||||
Ultra-compressed output mode: drops articles, filler and pleasantries while
|
||||
keeping technical substance exact. Cuts token usage by roughly 75%. Hand-invoked
|
||||
only — type /caveman to turn it on, "stop caveman" or "normal mode" to turn it
|
||||
off. Stays active across turns until you do.
|
||||
---
|
||||
|
||||
Respond terse like smart caveman. All technical substance stay. Only fluff die.
|
||||
|
||||
@@ -13,7 +13,7 @@ A feedback loop is a fast, deterministic, agent-runnable pass/fail signal for th
|
||||
7. **Property / fuzz loop.** If the bug is "sometimes wrong output", run 1000 random inputs and look for the failure mode.
|
||||
8. **Bisection harness.** If the bug appeared between two known states (commit, dataset, version), automate "boot at state X, check, repeat" so you can `git bisect run` it.
|
||||
9. **Differential loop.** Run the same input through old-version vs new-version (or two configs) and diff outputs.
|
||||
10. **HITL bash script.** Last resort. If a human must click, drive _them_ with `../scripts/hitl-loop.template.sh` so the loop is still structured. Captured output feeds back to you.
|
||||
10. **HITL bash script.** Last resort. If a human must click, drive _them_ with `scripts/hitl-loop.template.sh` so the loop is still structured. Captured output feeds back to you.
|
||||
|
||||
## Iterate on the loop itself
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
---
|
||||
name: caveman
|
||||
disable-model-invocation: true
|
||||
description: >
|
||||
Ultra-compressed communication mode. Cuts token usage ~75% by dropping
|
||||
filler, articles, and pleasantries while keeping full technical accuracy.
|
||||
Use when user says "caveman mode", "talk like caveman", "use caveman",
|
||||
"less tokens", "be brief", or invokes /caveman.
|
||||
Ultra-compressed output mode: drops articles, filler and pleasantries while
|
||||
keeping technical substance exact. Cuts token usage by roughly 75%. Hand-invoked
|
||||
only — type /caveman to turn it on, "stop caveman" or "normal mode" to turn it
|
||||
off. Stays active across turns until you do.
|
||||
---
|
||||
|
||||
Respond terse like smart caveman. All technical substance stay. Only fluff die.
|
||||
|
||||
@@ -13,7 +13,7 @@ A feedback loop is a fast, deterministic, agent-runnable pass/fail signal for th
|
||||
7. **Property / fuzz loop.** If the bug is "sometimes wrong output", run 1000 random inputs and look for the failure mode.
|
||||
8. **Bisection harness.** If the bug appeared between two known states (commit, dataset, version), automate "boot at state X, check, repeat" so you can `git bisect run` it.
|
||||
9. **Differential loop.** Run the same input through old-version vs new-version (or two configs) and diff outputs.
|
||||
10. **HITL bash script.** Last resort. If a human must click, drive _them_ with `../scripts/hitl-loop.template.sh` so the loop is still structured. Captured output feeds back to you.
|
||||
10. **HITL bash script.** Last resort. If a human must click, drive _them_ with `scripts/hitl-loop.template.sh` so the loop is still structured. Captured output feeds back to you.
|
||||
|
||||
## Iterate on the loop itself
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
name: git-submodules
|
||||
|
||||
description: >
|
||||
Use when managing Git submodules — adding, updating, pinning, inspecting,
|
||||
repointing, or removing a nested repository inside a superproject.
|
||||
Use when managing Git submodules — the full lifecycle of a nested
|
||||
repository inside a superproject.
|
||||
Not multiple checkouts of one repo -> `git-worktrees`.
|
||||
Not the superproject's own remotes -> `git-remotes`.
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
name: git-worktrees
|
||||
|
||||
description: >
|
||||
Use when working on several branches at once without stashing.
|
||||
Create, list, lock, move, remove, prune, or repair git worktrees.
|
||||
Use when working on several branches at once without stashing —
|
||||
manages the full lifecycle of a git worktree.
|
||||
Not ordinary branch switching or checkout -> `git-branches`.
|
||||
Not interactive multi-step git guidance -> `git-workflow`.
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
name: git-submodules
|
||||
|
||||
description: >
|
||||
Use when managing Git submodules — adding, updating, pinning, inspecting,
|
||||
repointing, or removing a nested repository inside a superproject.
|
||||
Use when managing Git submodules — the full lifecycle of a nested
|
||||
repository inside a superproject.
|
||||
Not multiple checkouts of one repo -> `git-worktrees`.
|
||||
Not the superproject's own remotes -> `git-remotes`.
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
name: git-worktrees
|
||||
|
||||
description: >
|
||||
Use when working on several branches at once without stashing.
|
||||
Create, list, lock, move, remove, prune, or repair git worktrees.
|
||||
Use when working on several branches at once without stashing —
|
||||
manages the full lifecycle of a git worktree.
|
||||
Not ordinary branch switching or checkout -> `git-branches`.
|
||||
Not interactive multi-step git guidance -> `git-workflow`.
|
||||
|
||||
|
||||
@@ -64,10 +64,10 @@ edge cases, `get_commit` will not.
|
||||
## Token scope
|
||||
|
||||
Both tools are believed to require `write:repository`, even though they're read-only — inferred by
|
||||
analogy with the scope-gating principle in `overview.md` (Gitea gates reads behind write scope for
|
||||
repo-scoped operations), not a claim `overview.md` makes for commits by name: its explicit
|
||||
`write:repository` enumeration lists PR, branch, file, release, and tag operations, but doesn't
|
||||
mention commits. An earlier version of this doc claimed `write:issue` alone worked, based on
|
||||
analogy with the scope-gating principle confirmed for branch operations in `branches.md`'s Token
|
||||
scope section (Gitea gates reads behind write scope for repo-scoped operations), not a claim any
|
||||
doc in this skill makes for commits by name: nothing here enumerates commits under
|
||||
`write:repository` explicitly. An earlier version of this doc claimed `write:issue` alone worked, based on
|
||||
empirical testing under a token that held both `write:issue` and `write:repository`
|
||||
simultaneously — that test didn't isolate the variable either. Treat this as unverified until
|
||||
tested under a token scoped to `write:issue` only (no `write:repository`).
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
name: gitea-files
|
||||
|
||||
description: >
|
||||
Use when reading or writing files in a Gitea repository rather than on the local filesystem —
|
||||
read, list, walk the tree, create, update, or delete — even when the user does not say "Gitea".
|
||||
Not commit history -> `gitea-branches`. Not pull requests -> `gitea-prs`.
|
||||
Use when reading or writing files or directories in a Gitea repository via the MCP server,
|
||||
rather than the local filesystem — even when the user does not say "Gitea". Not commit
|
||||
history -> `gitea-branches`. Not pull requests -> `gitea-prs`.
|
||||
|
||||
compatibility: Requires the Gitea MCP server configured with a token scoped to at least
|
||||
write:repository. Tested with a token holding write:issue + write:repository; write:issue
|
||||
|
||||
@@ -17,7 +17,7 @@ metadata:
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **Deleting a release never deletes its tag, and deleting a tag never deletes the release wrapping it.** A release is a metadata wrapper around a tag, so removing both takes two independent destructive calls.
|
||||
- **Deleting a release never deletes its tag.** A release is a metadata wrapper around a tag, so removing both takes two independent destructive calls. The reverse — whether deleting a tag deletes its release — is *unconfirmed*; verify with `list_releases`/`get_release` after `delete_tag` rather than assume it survives.
|
||||
- **`is_draft`/`is_pre_release` are booleans the caller sets — Gitea never infers a prerelease from a `-beta`/`-rc` tag name.** The response object names them `draft`/`prerelease`; passing `draft` as an input key is silently ignored, not rejected.
|
||||
- **`list_releases`/`list_tags` default `per_page` to 20**, where most other gitea-mcp list tools default to 30 — a caller assuming 30 under-counts the pages a full sweep needs.
|
||||
|
||||
|
||||
@@ -64,10 +64,10 @@ edge cases, `get_commit` will not.
|
||||
## Token scope
|
||||
|
||||
Both tools are believed to require `write:repository`, even though they're read-only — inferred by
|
||||
analogy with the scope-gating principle in `overview.md` (Gitea gates reads behind write scope for
|
||||
repo-scoped operations), not a claim `overview.md` makes for commits by name: its explicit
|
||||
`write:repository` enumeration lists PR, branch, file, release, and tag operations, but doesn't
|
||||
mention commits. An earlier version of this doc claimed `write:issue` alone worked, based on
|
||||
analogy with the scope-gating principle confirmed for branch operations in `branches.md`'s Token
|
||||
scope section (Gitea gates reads behind write scope for repo-scoped operations), not a claim any
|
||||
doc in this skill makes for commits by name: nothing here enumerates commits under
|
||||
`write:repository` explicitly. An earlier version of this doc claimed `write:issue` alone worked, based on
|
||||
empirical testing under a token that held both `write:issue` and `write:repository`
|
||||
simultaneously — that test didn't isolate the variable either. Treat this as unverified until
|
||||
tested under a token scoped to `write:issue` only (no `write:repository`).
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
name: gitea-files
|
||||
|
||||
description: >
|
||||
Use when reading or writing files in a Gitea repository rather than on the local filesystem —
|
||||
read, list, walk the tree, create, update, or delete — even when the user does not say "Gitea".
|
||||
Not commit history -> `gitea-branches`. Not pull requests -> `gitea-prs`.
|
||||
Use when reading or writing files or directories in a Gitea repository via the MCP server,
|
||||
rather than the local filesystem — even when the user does not say "Gitea". Not commit
|
||||
history -> `gitea-branches`. Not pull requests -> `gitea-prs`.
|
||||
|
||||
compatibility: Requires the Gitea MCP server configured with a token scoped to at least
|
||||
write:repository. Tested with a token holding write:issue + write:repository; write:issue
|
||||
|
||||
@@ -17,7 +17,7 @@ metadata:
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **Deleting a release never deletes its tag, and deleting a tag never deletes the release wrapping it.** A release is a metadata wrapper around a tag, so removing both takes two independent destructive calls.
|
||||
- **Deleting a release never deletes its tag.** A release is a metadata wrapper around a tag, so removing both takes two independent destructive calls. The reverse — whether deleting a tag deletes its release — is *unconfirmed*; verify with `list_releases`/`get_release` after `delete_tag` rather than assume it survives.
|
||||
- **`is_draft`/`is_pre_release` are booleans the caller sets — Gitea never infers a prerelease from a `-beta`/`-rc` tag name.** The response object names them `draft`/`prerelease`; passing `draft` as an input key is silently ignored, not rejected.
|
||||
- **`list_releases`/`list_tags` default `per_page` to 20**, where most other gitea-mcp list tools default to 30 — a caller assuming 30 under-counts the pages a full sweep needs.
|
||||
|
||||
|
||||
@@ -446,8 +446,17 @@ def known_targets(start_dir):
|
||||
# condition, pc-run's "run pre-commit hooks" reads as a route to a
|
||||
# non-existent `pre-commit` skill.
|
||||
# * A BARE arrow target counts only in ADR-0020's compressed boundary form,
|
||||
# `Not <thing> -> <skill-name>`. Without that, diagnose's process chain
|
||||
# "fix -> regression-test" reads as a route to `regression-test`.
|
||||
# `Not <thing> -> <skill-name>`. The example that motivated it is gone:
|
||||
# diagnose's process chain "fix -> regression-test", which without the
|
||||
# gate read as a route to a non-existent `regression-test` skill, was cut
|
||||
# when issue #99 retrofitted that description. So the gate is currently
|
||||
# UNEXERCISED — gating and not gating produce the same verdict corpus-wide.
|
||||
# Keep it anyway. It is a false-positive guard against prose no one has
|
||||
# written yet, and any new process chain re-arms it. Unexercised is not the
|
||||
# same as unnecessary, and the branch it guards is still load-bearing: the
|
||||
# bare-arrow rule is the sole extractor for three real targets in
|
||||
# kyberforge's audit skills (agent-audit -> agent-author, agent-audit ->
|
||||
# skill-audit, skill-audit -> skill-author), all written unbackticked.
|
||||
# * A backticked hyphenated token counts only inside a boundary sentence.
|
||||
# Unconditionally, `pre-push` or `commit-msg` in a TRIGGER clause is a hard
|
||||
# FAIL with no escape hatch. Gating it costs nothing (measured over this
|
||||
|
||||
@@ -4,7 +4,7 @@ Installs and configures the `apm` (Agent Package Manager) CLI and the agent runt
|
||||
|
||||
## What it does
|
||||
|
||||
Covers the two provisioning steps for working with apm: installing the `apm` binary itself (quick-install script, pinned version, air-gapped mirror, or pip), and installing/managing an agent runtime apm drives (`apm runtime setup copilot|codex|gemini|llm`, listing installed runtimes, checking which one `apm run` defaults to).
|
||||
Covers the two provisioning steps for working with apm: installing the `apm` binary itself (quick-install script, pinned version, air-gapped mirror, or pip/pipx), and installing/managing an agent runtime apm drives (`apm runtime setup copilot|codex|gemini|llm`, listing installed runtimes, checking which one `apm run` defaults to).
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
---
|
||||
name: apm-install
|
||||
description: >
|
||||
Use when the user wants to install the apm (Agent Package Manager) CLI
|
||||
itself, pin or upgrade its version, set up an air-gapped/enterprise mirror
|
||||
install, or install and manage an agent runtime that apm drives (Copilot
|
||||
CLI, Codex, Gemini, generic llm) — "install apm", "set up apm", "pin apm to
|
||||
a version", "apm runtime setup", "which runtime will apm run pick". Do not
|
||||
use for authoring apm.yml, scaffolding a package/marketplace, compiling,
|
||||
packing, publishing, or running apm audit — use apm-workflow for those.
|
||||
Use when installing, pinning, or upgrading the apm (Agent Package Manager)
|
||||
CLI itself, or installing and managing an agent runtime apm drives. Not
|
||||
authoring, publishing, or auditing apm packages -> `apm-workflow`.
|
||||
metadata:
|
||||
category: apm
|
||||
source_keys:
|
||||
@@ -16,13 +12,12 @@ metadata:
|
||||
|
||||
## Gotchas
|
||||
|
||||
- apm does not execute agents itself — it only installs and manages the runtimes that do. "Install apm" and "install a runtime apm manages" are two separate steps; don't conflate them or skip the second when the user actually wants a working agent CLI, not just the package manager.
|
||||
- The air-gapped/enterprise mirror path needs `GITHUB_URL` and `VERSION` set together against a downloaded `install.sh` — it does not work through the piped one-liner form.
|
||||
- `pip install apm-cli` requires Python 3.10+; the quick-install script has no such prerequisite. Prefer the quick-install script unless the environment is pip-first.
|
||||
- On a Debian/externally-managed Python environment (PEP 668), `pip install apm-cli` fails immediately with `error: externally-managed-environment`. Fall back to `pipx install apm-cli` — same PyPI package, but pipx creates an isolated venv and correctly exposes the `apm` binary on `PATH`.
|
||||
- Installing the Copilot CLI runtime through `apm runtime setup copilot` requires Node.js v22+ and npm v10+ already present — apm does not install Node/npm for you.
|
||||
- apm never executes an agent itself — it only installs and manages the runtimes that do. Installing apm alone leaves the user with a package manager and no working agent CLI, so Step 2 is required whenever the user actually wants one; skip it only when they explicitly want the package manager alone.
|
||||
- `apm runtime setup copilot` needs Node.js v22+ and npm v10+ already on `PATH`; apm will not install them for you.
|
||||
|
||||
## Install apm
|
||||
## Step 1 — Install the apm CLI
|
||||
|
||||
If `apm --version` already answers and the user is not pinning or upgrading, skip to Step 2.
|
||||
|
||||
Default:
|
||||
|
||||
@@ -31,16 +26,17 @@ curl -sSL https://aka.ms/apm-unix | sh
|
||||
```
|
||||
|
||||
Escape hatches — combine as needed:
|
||||
- Pin a version: append `@vX.Y.Z` to the piped script's arguments, e.g. `curl -sSL https://aka.ms/apm-unix | sh -s -- @v1.2.3`.
|
||||
- Custom install directory: set `APM_INSTALL_DIR` on the piped script's command, e.g. `curl -sSL https://aka.ms/apm-unix | APM_INSTALL_DIR=$HOME/.local/bin sh`.
|
||||
- Air-gapped / GitHub Enterprise mirror: download `install.sh` first, then run it with `GITHUB_URL` and `VERSION` set, e.g. `GITHUB_URL=https://github.corp.com VERSION=v1.2.3 sh install.sh`.
|
||||
- pip (Python 3.10+ environments): `pip install apm-cli`.
|
||||
- pipx (externally-managed/PEP 668 environments where plain `pip install` fails, e.g. Debian): `pipx install apm-cli`.
|
||||
- Manual: download the platform archive from the GitHub releases page, extract, place the binary on `PATH`.
|
||||
|
||||
- **Pin a version** — append `@vX.Y.Z` to the piped script's arguments: `curl -sSL https://aka.ms/apm-unix | sh -s -- @v1.2.3`.
|
||||
- **Custom install directory** — set `APM_INSTALL_DIR` on the piped script's command: `curl -sSL https://aka.ms/apm-unix | APM_INSTALL_DIR=$HOME/.local/bin sh`.
|
||||
- **Air-gapped mirror / GitHub Enterprise** — an air-gapped host cannot reach `aka.ms` at all, so get `install.sh` onto the box and run it from disk instead of piping. Point it at the mirror with `APM_RELEASE_BASE_URL` and pin `VERSION`: `APM_RELEASE_BASE_URL=https://mirror.corp/apm VERSION=v1.2.3 sh install.sh`; add `APM_RELEASE_METADATA_URL` instead if you leave `VERSION` unset. `GITHUB_URL` is the GitHub Enterprise host, not a release mirror. All four are ordinary environment variables that also work through the pipe — running from disk is a network constraint, not a script one.
|
||||
- **pip** — `pip install apm-cli` requires Python 3.10+. Not on an externally-managed (PEP 668) Python such as Debian or Ubuntu, where it hard-fails with `error: externally-managed-environment`; use pipx below. The quick-install script has no Python prerequisite, so prefer it unless the environment is pip-first.
|
||||
- **pipx** — `pipx install apm-cli` on those PEP 668 environments. Same PyPI package, but pipx builds an isolated venv and exposes `apm` on `PATH`.
|
||||
- **Manual** — download the platform archive from the GitHub releases page, extract, and place the binary on `PATH`.
|
||||
|
||||
Verify with `apm --version`.
|
||||
|
||||
## Install or manage an agent runtime
|
||||
## Step 2 — Install or manage an agent runtime
|
||||
|
||||
Default:
|
||||
|
||||
|
||||
@@ -51,6 +51,8 @@ apm publish --package acme/my-skill
|
||||
|
||||
Publishes a producer package (root containing `apm.yml`, `.apm/`, and optionally a `registries:` block) to a registry. Always dry-run with `-v` first — publishing is not trivially reversible once a version tag is claimed on a registry.
|
||||
|
||||
Publishing to a named registry requires `apm experimental enable registries` to have already run — see `references/configure.md`'s Gotchas for the full precondition and its silent-no-op failure mode.
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
|
||||
@@ -18,3 +18,5 @@ With no arguments, resolves and installs everything declared under `dependencies
|
||||
`--update` is the escape hatch for a lockfile hash mismatch against upstream — normal `apm install` treats that as drift and won't silently accept it; see `references/audit.md` for the CI-side check (`apm install --frozen`) that fails instead of re-resolving.
|
||||
|
||||
`--target agent-skills` generates the vendor-neutral output directory instead of a Claude/Copilot-specific one — for IDE-agnostic tool support.
|
||||
|
||||
If a `PACKAGE_REF` resolves through a named registry rather than a plain git source, `apm experimental enable registries` must already have been run — see `references/configure.md`'s Gotchas for the full precondition and its silent-no-op failure mode.
|
||||
|
||||
@@ -80,13 +80,13 @@ table** plus the gates common to every branch, and each flow lives in its own se
|
||||
`references/` file. Inlining all of them is a FAIL regardless of word count, because every
|
||||
invocation then pays for every branch it did not take.
|
||||
|
||||
The reference shape in this repo is `apm-workflow`: a **421-word body** dispatching to roughly
|
||||
3,000 words of references across five mutually exclusive invocations. Its whole-file count is 554
|
||||
words — cite 421 when calibrating a body, or the conflation this section warns against reappears
|
||||
The reference shape in this repo is `apm-workflow`: a **237-word body** dispatching to roughly
|
||||
3,200 words of references across five mutually exclusive invocations. Its whole-file count is 304
|
||||
words — cite 237 when calibrating a body, or the conflation this section warns against reappears
|
||||
in the finding itself.
|
||||
|
||||
Note its wiring: a three-column table (invocation, action, reference file) closed by one line,
|
||||
*"Read only the reference file matching the requested action."* That is the endorsed shape, and it
|
||||
*"Read only the reference file matching the requested action …"* That is the endorsed shape, and it
|
||||
is why the literal-conditional requirement above exempts a body that dispatches. Do not flag it.
|
||||
|
||||
## Gotchas sections
|
||||
|
||||
@@ -372,8 +372,17 @@ def known_targets(start_dir):
|
||||
# condition, pc-run's "run pre-commit hooks" reads as a route to a
|
||||
# non-existent `pre-commit` skill.
|
||||
# * A BARE arrow target counts only in ADR-0020's compressed boundary form,
|
||||
# `Not <thing> -> <skill-name>`. Without that, diagnose's process chain
|
||||
# "fix -> regression-test" reads as a route to `regression-test`.
|
||||
# `Not <thing> -> <skill-name>`. The example that motivated it is gone:
|
||||
# diagnose's process chain "fix -> regression-test", which without the
|
||||
# gate read as a route to a non-existent `regression-test` skill, was cut
|
||||
# when issue #99 retrofitted that description. So the gate is currently
|
||||
# UNEXERCISED — gating and not gating produce the same verdict corpus-wide.
|
||||
# Keep it anyway. It is a false-positive guard against prose no one has
|
||||
# written yet, and any new process chain re-arms it. Unexercised is not the
|
||||
# same as unnecessary, and the branch it guards is still load-bearing: the
|
||||
# bare-arrow rule is the sole extractor for three real targets in
|
||||
# kyberforge's audit skills (agent-audit -> agent-author, agent-audit ->
|
||||
# skill-audit, skill-audit -> skill-author), all written unbackticked.
|
||||
# * A backticked hyphenated token counts only inside a boundary sentence.
|
||||
# Unconditionally, `pre-push` or `commit-msg` in a TRIGGER clause is a hard
|
||||
# FAIL with no escape hatch. Gating it costs nothing (measured over this
|
||||
|
||||
@@ -120,8 +120,8 @@ A generic pointer ("see references/ for details") is a Vale error — the agent
|
||||
|
||||
**Dispatch is mandatory at two or more mutually exclusive flows.** The body carries the dispatch
|
||||
table and the gates common to every branch; each flow gets its own self-contained `references/`
|
||||
file. Exemplar: the `apm-workflow` skill — a **421-word body** dispatching to 3,006 words of
|
||||
references. Calibrate against 421: that file's whole-file count is 554 words, and aiming at that
|
||||
file. Exemplar: the `apm-workflow` skill — a **237-word body** dispatching to 3,222 words of
|
||||
references. Calibrate against 237: that file's whole-file count is 304 words, and aiming at that
|
||||
number instead overshoots the body budget by ~30%.
|
||||
|
||||
**Length.** 600 words SUGGESTION, 900 words FAIL, counting the **body only** — everything after
|
||||
|
||||
@@ -446,8 +446,17 @@ def known_targets(start_dir):
|
||||
# condition, pc-run's "run pre-commit hooks" reads as a route to a
|
||||
# non-existent `pre-commit` skill.
|
||||
# * A BARE arrow target counts only in ADR-0020's compressed boundary form,
|
||||
# `Not <thing> -> <skill-name>`. Without that, diagnose's process chain
|
||||
# "fix -> regression-test" reads as a route to `regression-test`.
|
||||
# `Not <thing> -> <skill-name>`. The example that motivated it is gone:
|
||||
# diagnose's process chain "fix -> regression-test", which without the
|
||||
# gate read as a route to a non-existent `regression-test` skill, was cut
|
||||
# when issue #99 retrofitted that description. So the gate is currently
|
||||
# UNEXERCISED — gating and not gating produce the same verdict corpus-wide.
|
||||
# Keep it anyway. It is a false-positive guard against prose no one has
|
||||
# written yet, and any new process chain re-arms it. Unexercised is not the
|
||||
# same as unnecessary, and the branch it guards is still load-bearing: the
|
||||
# bare-arrow rule is the sole extractor for three real targets in
|
||||
# kyberforge's audit skills (agent-audit -> agent-author, agent-audit ->
|
||||
# skill-audit, skill-audit -> skill-author), all written unbackticked.
|
||||
# * A backticked hyphenated token counts only inside a boundary sentence.
|
||||
# Unconditionally, `pre-push` or `commit-msg` in a TRIGGER clause is a hard
|
||||
# FAIL with no escape hatch. Gating it costs nothing (measured over this
|
||||
|
||||
@@ -4,7 +4,7 @@ Installs and configures the `apm` (Agent Package Manager) CLI and the agent runt
|
||||
|
||||
## What it does
|
||||
|
||||
Covers the two provisioning steps for working with apm: installing the `apm` binary itself (quick-install script, pinned version, air-gapped mirror, or pip), and installing/managing an agent runtime apm drives (`apm runtime setup copilot|codex|gemini|llm`, listing installed runtimes, checking which one `apm run` defaults to).
|
||||
Covers the two provisioning steps for working with apm: installing the `apm` binary itself (quick-install script, pinned version, air-gapped mirror, or pip/pipx), and installing/managing an agent runtime apm drives (`apm runtime setup copilot|codex|gemini|llm`, listing installed runtimes, checking which one `apm run` defaults to).
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
---
|
||||
name: apm-install
|
||||
description: >
|
||||
Use when the user wants to install the apm (Agent Package Manager) CLI
|
||||
itself, pin or upgrade its version, set up an air-gapped/enterprise mirror
|
||||
install, or install and manage an agent runtime that apm drives (Copilot
|
||||
CLI, Codex, Gemini, generic llm) — "install apm", "set up apm", "pin apm to
|
||||
a version", "apm runtime setup", "which runtime will apm run pick". Do not
|
||||
use for authoring apm.yml, scaffolding a package/marketplace, compiling,
|
||||
packing, publishing, or running apm audit — use apm-workflow for those.
|
||||
Use when installing, pinning, or upgrading the apm (Agent Package Manager)
|
||||
CLI itself, or installing and managing an agent runtime apm drives. Not
|
||||
authoring, publishing, or auditing apm packages -> `apm-workflow`.
|
||||
metadata:
|
||||
category: apm
|
||||
source_keys:
|
||||
@@ -16,13 +12,12 @@ metadata:
|
||||
|
||||
## Gotchas
|
||||
|
||||
- apm does not execute agents itself — it only installs and manages the runtimes that do. "Install apm" and "install a runtime apm manages" are two separate steps; don't conflate them or skip the second when the user actually wants a working agent CLI, not just the package manager.
|
||||
- The air-gapped/enterprise mirror path needs `GITHUB_URL` and `VERSION` set together against a downloaded `install.sh` — it does not work through the piped one-liner form.
|
||||
- `pip install apm-cli` requires Python 3.10+; the quick-install script has no such prerequisite. Prefer the quick-install script unless the environment is pip-first.
|
||||
- On a Debian/externally-managed Python environment (PEP 668), `pip install apm-cli` fails immediately with `error: externally-managed-environment`. Fall back to `pipx install apm-cli` — same PyPI package, but pipx creates an isolated venv and correctly exposes the `apm` binary on `PATH`.
|
||||
- Installing the Copilot CLI runtime through `apm runtime setup copilot` requires Node.js v22+ and npm v10+ already present — apm does not install Node/npm for you.
|
||||
- apm never executes an agent itself — it only installs and manages the runtimes that do. Installing apm alone leaves the user with a package manager and no working agent CLI, so Step 2 is required whenever the user actually wants one; skip it only when they explicitly want the package manager alone.
|
||||
- `apm runtime setup copilot` needs Node.js v22+ and npm v10+ already on `PATH`; apm will not install them for you.
|
||||
|
||||
## Install apm
|
||||
## Step 1 — Install the apm CLI
|
||||
|
||||
If `apm --version` already answers and the user is not pinning or upgrading, skip to Step 2.
|
||||
|
||||
Default:
|
||||
|
||||
@@ -31,16 +26,17 @@ curl -sSL https://aka.ms/apm-unix | sh
|
||||
```
|
||||
|
||||
Escape hatches — combine as needed:
|
||||
- Pin a version: append `@vX.Y.Z` to the piped script's arguments, e.g. `curl -sSL https://aka.ms/apm-unix | sh -s -- @v1.2.3`.
|
||||
- Custom install directory: set `APM_INSTALL_DIR` on the piped script's command, e.g. `curl -sSL https://aka.ms/apm-unix | APM_INSTALL_DIR=$HOME/.local/bin sh`.
|
||||
- Air-gapped / GitHub Enterprise mirror: download `install.sh` first, then run it with `GITHUB_URL` and `VERSION` set, e.g. `GITHUB_URL=https://github.corp.com VERSION=v1.2.3 sh install.sh`.
|
||||
- pip (Python 3.10+ environments): `pip install apm-cli`.
|
||||
- pipx (externally-managed/PEP 668 environments where plain `pip install` fails, e.g. Debian): `pipx install apm-cli`.
|
||||
- Manual: download the platform archive from the GitHub releases page, extract, place the binary on `PATH`.
|
||||
|
||||
- **Pin a version** — append `@vX.Y.Z` to the piped script's arguments: `curl -sSL https://aka.ms/apm-unix | sh -s -- @v1.2.3`.
|
||||
- **Custom install directory** — set `APM_INSTALL_DIR` on the piped script's command: `curl -sSL https://aka.ms/apm-unix | APM_INSTALL_DIR=$HOME/.local/bin sh`.
|
||||
- **Air-gapped mirror / GitHub Enterprise** — an air-gapped host cannot reach `aka.ms` at all, so get `install.sh` onto the box and run it from disk instead of piping. Point it at the mirror with `APM_RELEASE_BASE_URL` and pin `VERSION`: `APM_RELEASE_BASE_URL=https://mirror.corp/apm VERSION=v1.2.3 sh install.sh`; add `APM_RELEASE_METADATA_URL` instead if you leave `VERSION` unset. `GITHUB_URL` is the GitHub Enterprise host, not a release mirror. All four are ordinary environment variables that also work through the pipe — running from disk is a network constraint, not a script one.
|
||||
- **pip** — `pip install apm-cli` requires Python 3.10+. Not on an externally-managed (PEP 668) Python such as Debian or Ubuntu, where it hard-fails with `error: externally-managed-environment`; use pipx below. The quick-install script has no Python prerequisite, so prefer it unless the environment is pip-first.
|
||||
- **pipx** — `pipx install apm-cli` on those PEP 668 environments. Same PyPI package, but pipx builds an isolated venv and exposes `apm` on `PATH`.
|
||||
- **Manual** — download the platform archive from the GitHub releases page, extract, and place the binary on `PATH`.
|
||||
|
||||
Verify with `apm --version`.
|
||||
|
||||
## Install or manage an agent runtime
|
||||
## Step 2 — Install or manage an agent runtime
|
||||
|
||||
Default:
|
||||
|
||||
|
||||
@@ -51,6 +51,8 @@ apm publish --package acme/my-skill
|
||||
|
||||
Publishes a producer package (root containing `apm.yml`, `.apm/`, and optionally a `registries:` block) to a registry. Always dry-run with `-v` first — publishing is not trivially reversible once a version tag is claimed on a registry.
|
||||
|
||||
Publishing to a named registry requires `apm experimental enable registries` to have already run — see `references/configure.md`'s Gotchas for the full precondition and its silent-no-op failure mode.
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
|
||||
@@ -18,3 +18,5 @@ With no arguments, resolves and installs everything declared under `dependencies
|
||||
`--update` is the escape hatch for a lockfile hash mismatch against upstream — normal `apm install` treats that as drift and won't silently accept it; see `references/audit.md` for the CI-side check (`apm install --frozen`) that fails instead of re-resolving.
|
||||
|
||||
`--target agent-skills` generates the vendor-neutral output directory instead of a Claude/Copilot-specific one — for IDE-agnostic tool support.
|
||||
|
||||
If a `PACKAGE_REF` resolves through a named registry rather than a plain git source, `apm experimental enable registries` must already have been run — see `references/configure.md`'s Gotchas for the full precondition and its silent-no-op failure mode.
|
||||
|
||||
@@ -80,13 +80,13 @@ table** plus the gates common to every branch, and each flow lives in its own se
|
||||
`references/` file. Inlining all of them is a FAIL regardless of word count, because every
|
||||
invocation then pays for every branch it did not take.
|
||||
|
||||
The reference shape in this repo is `apm-workflow`: a **421-word body** dispatching to roughly
|
||||
3,000 words of references across five mutually exclusive invocations. Its whole-file count is 554
|
||||
words — cite 421 when calibrating a body, or the conflation this section warns against reappears
|
||||
The reference shape in this repo is `apm-workflow`: a **237-word body** dispatching to roughly
|
||||
3,200 words of references across five mutually exclusive invocations. Its whole-file count is 304
|
||||
words — cite 237 when calibrating a body, or the conflation this section warns against reappears
|
||||
in the finding itself.
|
||||
|
||||
Note its wiring: a three-column table (invocation, action, reference file) closed by one line,
|
||||
*"Read only the reference file matching the requested action."* That is the endorsed shape, and it
|
||||
*"Read only the reference file matching the requested action …"* That is the endorsed shape, and it
|
||||
is why the literal-conditional requirement above exempts a body that dispatches. Do not flag it.
|
||||
|
||||
## Gotchas sections
|
||||
|
||||
@@ -372,8 +372,17 @@ def known_targets(start_dir):
|
||||
# condition, pc-run's "run pre-commit hooks" reads as a route to a
|
||||
# non-existent `pre-commit` skill.
|
||||
# * A BARE arrow target counts only in ADR-0020's compressed boundary form,
|
||||
# `Not <thing> -> <skill-name>`. Without that, diagnose's process chain
|
||||
# "fix -> regression-test" reads as a route to `regression-test`.
|
||||
# `Not <thing> -> <skill-name>`. The example that motivated it is gone:
|
||||
# diagnose's process chain "fix -> regression-test", which without the
|
||||
# gate read as a route to a non-existent `regression-test` skill, was cut
|
||||
# when issue #99 retrofitted that description. So the gate is currently
|
||||
# UNEXERCISED — gating and not gating produce the same verdict corpus-wide.
|
||||
# Keep it anyway. It is a false-positive guard against prose no one has
|
||||
# written yet, and any new process chain re-arms it. Unexercised is not the
|
||||
# same as unnecessary, and the branch it guards is still load-bearing: the
|
||||
# bare-arrow rule is the sole extractor for three real targets in
|
||||
# kyberforge's audit skills (agent-audit -> agent-author, agent-audit ->
|
||||
# skill-audit, skill-audit -> skill-author), all written unbackticked.
|
||||
# * A backticked hyphenated token counts only inside a boundary sentence.
|
||||
# Unconditionally, `pre-push` or `commit-msg` in a TRIGGER clause is a hard
|
||||
# FAIL with no escape hatch. Gating it costs nothing (measured over this
|
||||
|
||||
@@ -120,8 +120,8 @@ A generic pointer ("see references/ for details") is a Vale error — the agent
|
||||
|
||||
**Dispatch is mandatory at two or more mutually exclusive flows.** The body carries the dispatch
|
||||
table and the gates common to every branch; each flow gets its own self-contained `references/`
|
||||
file. Exemplar: the `apm-workflow` skill — a **421-word body** dispatching to 3,006 words of
|
||||
references. Calibrate against 421: that file's whole-file count is 554 words, and aiming at that
|
||||
file. Exemplar: the `apm-workflow` skill — a **237-word body** dispatching to 3,222 words of
|
||||
references. Calibrate against 237: that file's whole-file count is 304 words, and aiming at that
|
||||
number instead overshoots the body budget by ~30%.
|
||||
|
||||
**Length.** 600 words SUGGESTION, 900 words FAIL, counting the **body only** — everything after
|
||||
|
||||
Reference in New Issue
Block a user