diff --git a/plugins/kyberforge/.apm/skills/factory-audit/SKILL.md b/plugins/kyberforge/.apm/skills/factory-audit/SKILL.md index f5a0fb1..fe1be28 100644 --- a/plugins/kyberforge/.apm/skills/factory-audit/SKILL.md +++ b/plugins/kyberforge/.apm/skills/factory-audit/SKILL.md @@ -2,12 +2,12 @@ name: factory-audit description: > Use when a skill, agent, or apm hook, instruction or prompt needs auditing, - including "is this ready to ship", or after hand-editing one outside its - author skill. Not applying skill fixes -> skill-author. - Not applying agent fixes -> agent-author. + or "is this ready to ship". Not fixing a skill -> skill-author. + Not fixing an agent -> agent-author. + Not fixing a hook, instruction or prompt -> primitive-author. allowed-tools: Bash Read metadata: - version: "1.1.0" + version: "1.1.1" category: factory source_keys: - agentskills-home diff --git a/plugins/kyberforge/.apm/skills/forge/SKILL.md b/plugins/kyberforge/.apm/skills/forge/SKILL.md index 8bc3053..df01df5 100644 --- a/plugins/kyberforge/.apm/skills/forge/SKILL.md +++ b/plugins/kyberforge/.apm/skills/forge/SKILL.md @@ -2,13 +2,12 @@ name: forge description: > Use when the user wants to build or improve something but has not yet named - the artifact type — skill, agent, plugin, or marketplace entry; "not sure if - this should be a skill or a plugin", "I have an idea but don't know where it - belongs". Routes to the matching author skill. Do not use when the type is - already named — invoke `skill-author`, `agent-author` or `apm-workflow` - directly. + the artifact type; "not sure if this should be a skill or a plugin", "I have + an idea but don't know where it belongs". Routes to the matching author + skill. Do not use when the type is already named — invoke `skill-author`, + `agent-author`, `primitive-author` or `apm-workflow` directly. metadata: - version: "1.0.1" + version: "1.0.2" category: factory source_keys: - claude-code-subagents-docs @@ -18,7 +17,7 @@ metadata: ## Gotchas -- forge is an optional guided entry point, not a gate — `skill-author`, `agent-author`, `factory-audit` and `apm-workflow` all stay directly invokable, and forge never intercepts a direct call to one. +- forge is an optional guided entry point, not a gate — `skill-author`, `agent-author`, `primitive-author`, `factory-audit` and `apm-workflow` all stay directly invokable, and forge never intercepts a direct call to one. - Claude Code's skill-level `context: fork` frontmatter field and the `/fork` subagent command are opposites despite the shared word: `context: fork` isolates (fresh context, no parent access), while `/fork` inherits the full conversation. The route reference each classification loads spends that distinction: `references/author-routes.md` chooses between the two, `references/apm-routes.md` rules the fork out. ## Step 1 — Grill the intent @@ -37,12 +36,13 @@ Match the grilled intent against exactly one row — or more than one, if the in |---|---|---|---| | A reusable capability the agent loads inline in the main conversation, triggered by description-matching, free to bundle its own `references/`, `scripts/` or `assets/` | Skill | `skill-author` | `references/author-routes.md` | | A recurring task needs its own reusable definition — dedicated system prompt, tools and description, invokable by name across sessions | Agent / subagent | `agent-author` | `references/author-routes.md` | +| A runtime callback at a harness event, a rule scoped to a file pattern, or a reusable user-typed message steering existing skills | Hook / instruction / prompt (apm primitive) | `primitive-author` | `references/author-routes.md` | | A new distributable unit — no existing plugin is the right home for the skill, agent, hook or MCP server being built, or the bundle needs its own manifest, versioning and install lifecycle | Plugin | `apm-workflow` (`apm plugin init`) | `references/apm-routes.md` | | The plugin already exists and only its marketplace-facing metadata changes — a first listing, or a version/description update, never the plugin's contents | Marketplace entry | `apm-workflow` (`apm marketplace package add`) | `references/apm-routes.md` | The table classifies what to build, not how to run it: a one-off task that merely needs an isolated or context-inheriting run is not an artifact and has no row here. If the intent stays genuinely ambiguous between rows after grilling, ask the user rather than guessing. -A real artifact that matches no row — a hook, an MCP server, an AGENTS.md, a research doc — has no route here. Say so, hand the user the skill that does own it, and never bend it into a row to make the table fit. +A real artifact that matches no row — an MCP server, an AGENTS.md, a research doc — has no route here. Say so, hand the user the skill that does own it, and never bend it into a row to make the table fit. When the intent spans several rows, chain the routes in dependency order — an artifact that must exist on disk before another skill can target it goes first, so `apm-workflow` scaffolds the plugin directory before `skill-author` scaffolds a skill inside it. @@ -51,4 +51,4 @@ When the intent spans several rows, chain the routes in dependency order — an ## Step 3 — Closing gates, common to every route - **Resolve before closing.** A route is finished only when its verification reports nothing unresolved. An actionable finding reopens the route; it is never reported onward as a caveat. -- **Bump the package version.** A skill route always lands here: `skill-author` moves only a skill's own `metadata.version`, which is not the package `apm.yml`'s number — so read `references/version-bump.md` after one. `agent-author` and the apm routes bump the package themselves at plugin scope; after those, read it only when their output does not say they did. +- **Bump the package version.** A skill route always lands here: `skill-author` moves only a skill's own `metadata.version`, which is not the package `apm.yml`'s number — so read `references/version-bump.md` after one. `agent-author`, `primitive-author` and the apm routes bump the package themselves at plugin scope; after those, read it only when their output does not say they did. diff --git a/plugins/kyberforge/.apm/skills/forge/references/author-routes.md b/plugins/kyberforge/.apm/skills/forge/references/author-routes.md index 5314934..d1be25a 100644 --- a/plugins/kyberforge/.apm/skills/forge/references/author-routes.md +++ b/plugins/kyberforge/.apm/skills/forge/references/author-routes.md @@ -3,12 +3,13 @@ source_keys: - claude-code-subagents-docs --- -# Routing a skill or agent to its author skill +# Routing a skill, agent or apm primitive to its author skill -Reached from `SKILL.md` Step 2 when the classified artifact is a skill or an agent/subagent -definition. Route a skill to `skill-author` and an agent to `agent-author`. The two branches -differ on the author skill only — both verify the result with `factory-audit`, which detects the -artifact type itself — and everything below applies to both. +Reached from `SKILL.md` Step 2 when the classified artifact is a skill, an agent/subagent +definition, or a hook, instruction or prompt. Route a skill to `skill-author`, an agent to +`agent-author`, and a hook, instruction or prompt to `primitive-author`. The branches differ on +the author skill only — all verify the result with `factory-audit`, which detects the artifact type +itself — and everything below applies to all of them. ## Choose fork or inline @@ -25,8 +26,8 @@ Fall back to an **inline invocation** — same conversation, no subagent — whe ## Two-tier verification -Both author skills already close out with their own inline audit, in the same context as the -authoring work: `skill-author` and `agent-author` each invoke `factory-audit` on what they wrote. +Every author skill already closes out with its own inline audit, in the same context as the +authoring work: `skill-author`, `agent-author` and `primitive-author` each invoke `factory-audit` on what they wrote. That is tier one, and forge does not change it. Tier two belongs to forge. Once the author skill's run has finished, spin up a separate diff --git a/plugins/kyberforge/.apm/skills/primitive-author/SKILL.md b/plugins/kyberforge/.apm/skills/primitive-author/SKILL.md new file mode 100644 index 0000000..ccc768c --- /dev/null +++ b/plugins/kyberforge/.apm/skills/primitive-author/SKILL.md @@ -0,0 +1,52 @@ +--- +name: primitive-author +description: > + Use when the user wants an apm hook, instruction or prompt file created, or + audit findings or feedback applied to an existing one. + Not skills -> skill-author. Not agents -> agent-author. +allowed-tools: Bash Read Write Edit +metadata: + version: "0.1.0" + category: factory + source_keys: + - apm-cli-installed-source + - apm-docs-llms-full +--- + +## Gotchas + +- `apm compile --validate` is not a gate. apm turns every instruction and prompt problem into a warning and exits 0, and `apm install` never validates at all — `/factory-audit` is the only check that fails. +- Never draft with the real suffix outside `.apm//`. apm's local discovery globs `**/*.instructions.md` across the whole tree, so a draft or template named that way anywhere in the repo compiles into `AGENTS.md`. The templates carry a trailing `.template` for this reason; drop it only on the final path. +- Never hand-write `.claude/settings.json`, even to test a hook. apm owns that file (ADR-0019), overwrites it outright when it is malformed, and `apm audit --ci` fails on anything it would not have written. + +## Step 1 — Dispatch + +| Target or intent | Primitive | Reference | +|---|---|---| +| A hook — `.apm/hooks/.json`, or "run X whenever Y happens" | hook | `references/hook.md` | +| An instruction — `.apm/instructions/.instructions.md`, or a rule for files matching a pattern | instruction | `references/instruction.md` | +| A prompt — `.apm/prompts/.prompt.md`, or a reusable message the user types to kick off work | prompt | `references/prompt.md` | +| A skill or an agent | — | stop: route to `skill-author` or `agent-author` | + +Read only the reference matching the resolved primitive — each is self-contained. If the target sits inside a git worktree, capture `rtk git log --oneline -1` before touching the filesystem; Step 4 needs it. + +## Step 2 — Boundary gate + +Run the reference's **Gate** section before writing anything. A failed gate stops this skill: name the owner it points to — `skill-author` for procedure, `agentsmd-author` for a repo-only rule, `apm-workflow` for reach or `targets:` — and hand over. Never bend the artifact to pass the gate. + +## Step 3 — Create or improve + +| Condition | Action | +|---|---| +| No file at the target path | Create: copy the reference's template from `assets/templates/`, drop `.template`, fill every `FILL IN`, and apply the reference's checklist | +| File exists, at least one signal | Improve: read the whole file, then apply each signal against the reference's checklist | +| File exists, no signal | Stop and ask whether the user meant a new file or has feedback to apply | + +Signals: grill output, `/factory-audit` findings, inline feedback, session context describing what went wrong. Group findings by root cause and fix the cause once. + +## Step 4 — Validate and close + +1. Run `/factory-audit` on the file, inline in this context; resolve every FAIL before reporting done. +2. Run `rtk apm install --dry-run` from the repo root and read what each target will receive. On a feature branch, discard `apm.lock.yaml` churn afterwards (`rtk git checkout -- apm.lock.yaml`). +3. Bump the owning package's `apm.yml` `version:` — minor for a new primitive, patch for a fix — unless this branch already bumped it for unreleased work. A primitive has no version of its own. +4. **Commit verification.** Inside a git worktree, once the audit is clean, run `rtk git add` and `rtk git commit`, then re-run `rtk git log --oneline -1` and confirm the hash changed from Step 1's. Staged-but-uncommitted work is silently lost if the tree is cleaned up. Outside a worktree, report done on a clean audit and name that as the reason. diff --git a/plugins/kyberforge/.apm/skills/primitive-author/assets/templates/hook.json.template b/plugins/kyberforge/.apm/skills/primitive-author/assets/templates/hook.json.template new file mode 100644 index 0000000..28a590e --- /dev/null +++ b/plugins/kyberforge/.apm/skills/primitive-author/assets/templates/hook.json.template @@ -0,0 +1,16 @@ +{ + "hooks": { + "FILL_IN_PascalCaseEvent": [ + { + "matcher": "FILL_IN_matcher", + "hooks": [ + { + "type": "command", + "command": "${PLUGIN_ROOT}/.apm/hooks/FILL_IN_script.sh", + "timeout": 10 + } + ] + } + ] + } +} diff --git a/plugins/kyberforge/.apm/skills/primitive-author/assets/templates/name.instructions.md.template b/plugins/kyberforge/.apm/skills/primitive-author/assets/templates/name.instructions.md.template new file mode 100644 index 0000000..c5e7dd6 --- /dev/null +++ b/plugins/kyberforge/.apm/skills/primitive-author/assets/templates/name.instructions.md.template @@ -0,0 +1,7 @@ +--- +description: "FILL IN: one sentence on what this rule governs" +applyTo: "FILL IN: glob, e.g. **/*.{ts,tsx}" +--- + +FILL IN: the rule, as direct second-person guidance. Put any rationale Claude needs here — the +description above never reaches Claude. diff --git a/plugins/kyberforge/.apm/skills/primitive-author/assets/templates/name.prompt.md.template b/plugins/kyberforge/.apm/skills/primitive-author/assets/templates/name.prompt.md.template new file mode 100644 index 0000000..ff54818 --- /dev/null +++ b/plugins/kyberforge/.apm/skills/primitive-author/assets/templates/name.prompt.md.template @@ -0,0 +1,8 @@ +--- +description: "FILL IN: one user-facing action naming the skills it steers" +input: + - FILL_IN_name: "FILL IN: what the user supplies" +--- + +FILL IN: the message the user would otherwise type, steering existing skills or agents by name. +Use ${input:FILL_IN_name} where the value belongs. diff --git a/plugins/kyberforge/.apm/skills/primitive-author/references/hook.md b/plugins/kyberforge/.apm/skills/primitive-author/references/hook.md new file mode 100644 index 0000000..5888e27 --- /dev/null +++ b/plugins/kyberforge/.apm/skills/primitive-author/references/hook.md @@ -0,0 +1,82 @@ +--- +source_keys: + - apm-cli-installed-source + - apm-docs-llms-full +--- + +# Authoring an apm hook + +Reached from `SKILL.md` Step 1 for a hook. Run the Gate, then write against the shape and the +checklist, then return to `SKILL.md` Step 3. + +## Gate + +A hook is a runtime callback the harness fires inside its own tool loop — "this must always +happen at this event", enforced deterministically rather than left to the model. apm's own +guidance is to reach for a skill, instruction or prompt first, and to treat hooks as opt-in +surface: they ship to a strict subset of harnesses and are silently skipped everywhere else. + +- **Procedure, know-how, or anything the model should decide to do** → a skill. Stop and hand to + `skill-author`. +- **The hook must reach only some harnesses** → reach is set by the package `apm.yml` `targets:`, + never by the hook file. Stop and hand to `apm-workflow`. `targets:` is package-wide, so a + harness-specific hook in a multi-target package means either a separate package or accepting that + the other targets receive it too. +- **A runtime callback** → continue. + +## Shape + +One JSON file per concern at `.apm/hooks/.json`, with a plain name. Copy +`assets/templates/hook.json.template`. Write the canonical shape apm documents and renders per +target: + +```json +{ + "hooks": { + "PreToolUse": [ + { + "matcher": "Bash", + "hooks": [ + {"type": "command", "command": "${PLUGIN_ROOT}/.apm/hooks/check.sh", "timeout": 10} + ] + } + ] + } +} +``` + +- **`${PLUGIN_ROOT}`** is the target-neutral token; apm rewrites it per target + (`"${CLAUDE_PROJECT_DIR}/.claude/hooks//…"` on Claude, repo-relative elsewhere). + `${CLAUDE_PLUGIN_ROOT}` also works but ties the source to one harness's name. +- **Claude is the verified target.** apm 0.28.0 passes this nested shape to Copilot without + reshaping it, and whether Copilot CLI runs nested entries or honours `matcher` is unverified. That + gap is apm's to close — do not work around it with a second, Copilot-flat file. + +## Checklist + +Must: + +1. The file sits directly in `.apm/hooks/`, is not a symlink or hardlink, and parses as a JSON + object. apm skips invalid JSON silently. +2. Every event value is a list of objects, and every nested `hooks` is a list of objects. Anything + else fails the Copilot install outright. +3. Event names are PascalCase (`PreToolUse`, `PostToolUse`, `UserPromptSubmit`, `SessionStart`, + `Stop`, …). An all-lowercase name (`stop`) never warns and never fires; a camelCase name outside + apm's rename map (`userPromptSubmit`) deploys verbatim to Claude and never fires. +4. The script is referenced as `${PLUGIN_ROOT}/…` (package root) or `./…` (hook directory), + exists inside the package, and is executable. No absolute path, and no `$` or backtick in the + path itself. A missing script is only a warning at install time. +5. No `hooks-` or `*--hooks` filename. That routing is deprecated; reach belongs to + `targets:` (see Gate). + +Should: + +6. Every handler sets `"type": "command"` and an explicit `timeout` in seconds — apm passes `type` + through but never supplies it. +7. Set `matcher` explicitly on tool events and on `SessionStart` (`startup`, `resume`, …). Omitted, + Claude receives `"*"`. +8. Do not author Copilot's flat `bash` / `powershell` / `timeoutSec` keys in a Claude-shaped file; + they render onto Claude as stray keys. +9. Quote a script path that may contain spaces: `"${PLUGIN_ROOT}/scripts/my hook.sh"`. +10. Keep helper files in the hook directory non-JSON. Copilot's loader rejects any bundled `.json` + without a `hooks` key. diff --git a/plugins/kyberforge/.apm/skills/primitive-author/references/instruction.md b/plugins/kyberforge/.apm/skills/primitive-author/references/instruction.md new file mode 100644 index 0000000..38e7068 --- /dev/null +++ b/plugins/kyberforge/.apm/skills/primitive-author/references/instruction.md @@ -0,0 +1,51 @@ +--- +source_keys: + - apm-cli-installed-source + - apm-docs-llms-full +--- + +# Authoring an apm instruction + +Reached from `SKILL.md` Step 1 for an instruction. Run the Gate, then write against the checklist, +then return to `SKILL.md` Step 3. + +## Gate + +An instruction is a scoped rule: it applies when the agent touches files matching its `applyTo` +glob. On Claude it deploys to `.claude/rules/.md` with `applyTo` renamed to `paths:`. + +- **A rule for this repo alone** → it belongs in the repo's AGENTS.md, which is the single + always-on source. Stop and hand to `agentsmd-author`. +- **No file pattern fits** → an instruction without `applyTo` is always-on in every session of + every repo that installs this package, and `apm compile` folds it into the global sections of + `AGENTS.md` and `CLAUDE.md`. Say exactly that to the user and continue only on an explicit yes. + Legitimate when a package deliberately ships guidance to its consumers; never a default. +- **Procedure the agent follows step by step** → a skill. Stop and hand to `skill-author`. +- **A rule scoped to a file pattern** → continue. + +## Checklist + +Copy `assets/templates/name.instructions.md.template` and drop `.template` only on the final path. + +Must: + +1. The path is `.apm/instructions/.instructions.md`, directly in that directory, not a + symlink or hardlink. +2. `description` is a non-empty string. apm only warns when it is missing. +3. The body is non-empty. apm deploys an empty rule silently. +4. `applyTo` is a non-empty glob or comma-separated list — top-level commas only as separators, + alternation inside `{}` (`"**/*.{ts,tsx}"`) — or absent after the Gate's explicit yes. +5. The stem is unique across the package and its dependencies: a `.claude/rules/.md` + collision is silently overwritten. + +Should: + +6. Write `applyTo` as a scalar string, not a YAML list. Copilot receives the source verbatim, and + its handling of a list is unverified. +7. Keep frontmatter to `description` and `applyTo`, plus optional `author` and `version`. No target + consumes other keys, and Claude drops them. +8. Put any rationale Claude needs in the body. `description` never reaches Claude — it survives only + for Copilot and as Cursor's index text. +9. Keep relative markdown links resolvable from the source file. +10. Check the glob against the tree: one that matches nothing never fires, and one broader than the + rule's real scope spends context on every file it touches. diff --git a/plugins/kyberforge/.apm/skills/primitive-author/references/prompt.md b/plugins/kyberforge/.apm/skills/primitive-author/references/prompt.md new file mode 100644 index 0000000..17f6ea1 --- /dev/null +++ b/plugins/kyberforge/.apm/skills/primitive-author/references/prompt.md @@ -0,0 +1,59 @@ +--- +source_keys: + - apm-cli-installed-source + - apm-docs-llms-full + - adr-0029-prompt-house-rule +--- + +# Authoring an apm prompt + +Reached from `SKILL.md` Step 1 for a prompt. Run the Gate, then write against the description +contract and the checklist, then return to `SKILL.md` Step 3. + +## Gate + +This repo holds a prompt to ADR-0029, which is stricter than apm: apm calls a prompt "a callable +program", but on Claude it deploys as a command that is a skill in every respect except that it +keeps fewer frontmatter keys, apm drops `disable-model-invocation` so it can never be made +user-only, and Codex receives no prompts at all. A prompt that carries procedure is therefore a +worse skill on every harness. + +- **Reusable know-how, steps, gotchas, bundled files, or anything the model should find on its + own** → a skill. Stop and hand to `skill-author`; if a short steering message is still wanted + afterwards, come back and write it against the new skill. +- **A single-intent message the user would otherwise type repeatedly, steering existing skills or + agents by name** → continue. Confirm each skill or agent it names exists and is not + `disable-model-invocation: true`, which the model cannot invoke. + +## Description contract + +One plain, user-facing sentence stating the action and naming the skills it steers — "Review the +current PR with `gitea-prs` and `factory-audit`, then summarise the findings." No "Use when" +trigger clause and no `Not X -> Y` boundary: on Claude the description is model-visible, and a +trigger clause invites the router to pick the wrapper over the skills it wraps. 250 characters at +most. + +## Checklist + +Copy `assets/templates/name.prompt.md.template` and drop `.template` only on the final path. + +Must: + +1. The path is `.apm/prompts/.prompt.md`, directly in that directory, not a symlink. `` + is a safe path segment and unique across `.apm/prompts/` and the package root; it becomes the + Copilot filename and the Claude `/command` name. +2. `description` is present and non-empty, per the contract above. +3. Every `input:` name matches `^[A-Za-z][\w-]{0,63}$`, written in the object form + `- pr_number: "The PR to review"`. Never copy apm's published `- name: pr_number` / + `description: …` example: apm reads the map's keys, so it produces the arguments `name` and + `description`. +4. Every `${input:x}` in the body is declared in `input:`, and every declared name is used. Without + `input:`, no `${input:…}` may appear — it would reach Claude unrewritten. +5. Frontmatter keys stay within `description`, `allowed-tools`, `model`, `argument-hint` and + `input`. Claude drops everything else with only a warning. + +Should: + +6. Spell keys in kebab-case — `allowed-tools`, `argument-hint` — not the camelCase aliases. +7. Omit `argument-hint` when `input:` is set; apm synthesises ` ` from the input names. +8. Keep one intent per prompt, and write the body as second-person instructions. diff --git a/plugins/kyberforge/.apm/skills/primitive-author/references/sources.md b/plugins/kyberforge/.apm/skills/primitive-author/references/sources.md new file mode 100644 index 0000000..17e0faa --- /dev/null +++ b/plugins/kyberforge/.apm/skills/primitive-author/references/sources.md @@ -0,0 +1,26 @@ +# Sources + +## apm-cli-installed-source + +- **URL:** file:///root/.local/pipx/venvs/apm-cli/lib/python3.11/site-packages/apm_cli/ +- **Research doc:** plugins/kyberforge/docs/research/docs/microsoft-apm/sources.md +- **Description:** Installed apm-cli 0.28.0 source — ground truth for what apm deploys from a hook, instruction or prompt file and what it silently skips or only warns on; every Must/Should checklist item traces to the research docs' Authoring checklists, and the `**/*.instructions.md` local-discovery glob behind the template-suffix Gotcha is `primitives/discovery.py` `LOCAL_PRIMITIVE_PATTERNS` +- **Contributing files:** SKILL.md, references/hook.md, references/instruction.md, references/prompt.md +- **Status:** `extracted` + +## apm-docs-llms-full + +- **URL:** https://microsoft.github.io/apm/llms-full.txt +- **Research doc:** plugins/kyberforge/docs/research/docs/microsoft-apm/sources.md +- **Description:** Published apm docs bundle — the "Hooks and commands" guide's canonical hook shape, `${PLUGIN_ROOT}`, reach via `targets:` rather than deprecated filename routing, and "reach for a skill, instruction, or prompt first"; the "Author a prompt" guide's one-intent rule +- **Contributing files:** SKILL.md, references/hook.md, references/instruction.md, references/prompt.md +- **Status:** `extracted` + +## adr-0029-prompt-house-rule + +- **URL:** docs/adr/0029-prompts-are-thin-user-triggered-steering-messages.md +- **Research doc:** none +- **Basis:** docs/adr/0029-prompts-are-thin-user-triggered-steering-messages.md +- **Description:** The repo's prompt house rule — a prompt is a single-intent, user-triggered steering message with no procedure — and its description contract: one user-facing sentence naming the steered skills, no trigger or boundary clause +- **Contributing files:** references/prompt.md +- **Status:** `extracted` diff --git a/plugins/kyberforge/README.md b/plugins/kyberforge/README.md index 1e838f2..fda9f08 100644 --- a/plugins/kyberforge/README.md +++ b/plugins/kyberforge/README.md @@ -39,10 +39,11 @@ Authoring source lives in `.apm/`; it is the only content source and the only th | 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 | +| `forge` | Grill an unclassified "I want to add something" request, decide whether it's a skill, agent, hook, instruction, prompt, 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 | | `agent-author` | Author an agent definition file | -| `factory-audit` | Audit a skill directory or an agent definition — structure, provider safety, description and body quality, and provenance; produces a findings report. Auto-detects which of the two it was handed (ADR-0025) | +| `primitive-author` | Create or improve an apm hook, instruction or prompt, gated on whether it should be one at all (ADR-0029 for prompts) | +| `factory-audit` | Audit a skill directory, an agent definition, or an apm hook, instruction or prompt — structure, provider safety, description and body quality, and provenance; produces a findings report. Auto-detects which it was handed (ADR-0025) | | `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 |