fix(primitive-author): annotate tier moves and route package config

- annotate the research Must demoted to hook Should 12; narrow Must 5 note
- extend Must 6 to scripts run via an interpreter -c string
- add a fallback dispatch row and comma-joined --target guidance
- fall back when agentsmd-author is not installed
- add the apm-workflow boundary; pin upstream apm source URL

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KkT7RSDwDbmrM9T34b6sTi
This commit is contained in:
2026-09-29 08:00:26 +00:00
parent 36723ae3fc
commit fd86ee42f4
5 changed files with 28 additions and 18 deletions

View File

@@ -1,9 +1,10 @@
---
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 read-only
review -> factory-audit. Not skills -> skill-author. Not agents -> agent-author.
Use when the user wants an apm hook, instruction or prompt created, or
findings applied to one. Not read-only review -> factory-audit. Not skills
-> skill-author. Not agents -> agent-author. Not apm.yml, targets or package
config -> apm-workflow.
allowed-tools: Bash Read Write Edit
metadata:
version: "0.1.0"
@@ -25,9 +26,10 @@ metadata:
|---|---|---|
| A hook — `.apm/hooks/<name>.json`, or "run X whenever Y happens" | hook | `references/hook.md` |
| An instruction — `.apm/instructions/<name>.instructions.md`, or a rule for files matching a pattern | instruction | `references/instruction.md` |
| A prompt — `.apm/prompts/<name>.prompt.md`, or a reusable message the user types to kick off work | prompt | `references/prompt.md` |
| A prompt — `.apm/prompts/<name>.prompt.md`, or a slash command steering existing skills | prompt | `references/prompt.md` |
| Anything else (agent file, context/memory file) | none | stop; agents -> `agent-author`, otherwise name the unsupported type |
Read only the reference matching the resolved type — 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.
Read only the matching reference. 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
@@ -45,7 +47,7 @@ Signals: grill output, `/factory-audit` findings, inline feedback, session conte
## Step 4 — Validate and close
1. Run `/factory-audit` on the file, inline in this context; resolve every FAIL before reporting done, including the `### Prose` FAILs Vale raises on an instruction or prompt body or description.
2. Render it: in a fresh `mktemp -d` directory, run `rtk apm install <absolute path to the owning package> --target <its targets:, or all when it declares none>`, then read what each target received — `.claude/settings.json` and `.github/hooks/`, `.claude/rules/` and `.github/instructions/`, or `.claude/commands/` and `.github/prompts/`. A local path deploys the working tree; `--dry-run` renders nothing and a repo-root install resolves the remote's `main`.
3. Bump the owning package's `apm.yml` `version:` — minor for a new hook, instruction or prompt, patch for a fix — unless this branch already bumped it for unreleased work. None of these is released on its own version — bump the package even if an instruction carries an optional `version:` key.
1. Run `/factory-audit` on the file, inline in this context; resolve every FAIL before reporting done, including Vale's `### Prose` FAILs on an instruction or prompt.
2. Render it: in a fresh `mktemp -d` directory, run `rtk apm install <absolute path to the owning package> --target <its targets: joined with commas, or all when it declares none>` (a repeated `--target` keeps only the last; Codex receives no prompts), then read what each target received — `.claude/settings.json` and `.github/hooks/`, `.claude/rules/` and `.github/instructions/`, or `.claude/commands/` and `.github/prompts/`. A local path deploys the working tree; `--dry-run` renders nothing and a repo-root install resolves the remote's `main`.
3. Bump the owning package's `apm.yml` `version:` (minor for a new hook, instruction or prompt, patch for a fix; even if an instruction carries its own `version:` key) unless this branch already bumped it for unreleased work.
4. **Commit verification.** Inside a git worktree, once the audit is clean, run `rtk git add` and `rtk git commit`, then confirm `rtk git log --oneline -1` changed from Step 1's hash: staged-but-uncommitted work is lost if the tree is cleaned up. Outside a worktree, report done on a clean audit and name that as the reason.

View File

@@ -68,7 +68,7 @@ Must:
else fails the Copilot install outright. The file contributes at least one entry, and every
entry carries at least one handler: an empty list or a handler-less entry deploys nothing, with
only a warning.
4. Every event is one each target the package deploys to fires, after apm's rename for that target
4. Every event is one that each target the package deploys to fires, after apm's rename for that target
(`_HOOK_EVENT_MAP`; no `targets:` means every target). Write Claude's PascalCase names
(`PreToolUse`, `PostToolUse`, `UserPromptSubmit`, `SessionStart`, `Stop`, …), which apm renames
for each target its map covers. A name the map does not cover deploys verbatim with no warning,
@@ -84,10 +84,11 @@ Must:
the path itself, and no space. When quoting, quote the whole token —
`"${PLUGIN_ROOT}/scripts/my-hook.sh"`, never `"${PLUGIN_ROOT}"/scripts/x.sh`: apm rewrites
`${PLUGIN_ROOT}` only when a path separator follows it directly, and only up to the next space
or quote, so a split quote is left unrewritten and a spaced path is cut short. This is stricter
than the research's Should, as with Must 6: either defect fails every time the hook fires. A
missing script is only a warning at install time.
6. A script run directly as the command's first token is executable. This is stricter than the
or quote, so a split quote is left unrewritten and a spaced path is cut short. The quoting and
space rules are stricter than the research's Should, as with Must 6: either defect fails every
time the hook fires. A missing script is only a warning at install time.
6. A script run directly as the command's first token, or as the first token of an interpreter's
`-c` command string (`bash -c "${PLUGIN_ROOT}/x.sh"`), is executable. This is stricter than the
research's Should: without it the hook fails every time it fires. A script passed to an
interpreter (`bash ${PLUGIN_ROOT}/x.sh`) needs no executable bit.
@@ -105,5 +106,5 @@ Should:
12. No filename that routes by target. Case-insensitively, apm routes a stem of exactly
`hooks-<target>` and any stem ending `<target>-hooks` — bare (`claude-hooks`), prefixed
(`x-claude-hooks`) or combined (`claude-codex-hooks`, the union). That routing is deprecated and
reach belongs to `targets:` (see Gate); the research allows it only when deprecated routing is
intended.
reach belongs to `targets:` (see Gate). The research files this as a Must; it is a Should here
because only the author can say deprecated routing is intended.

View File

@@ -15,13 +15,16 @@ An instruction is a scoped rule: it applies when the agent touches files matchin
glob. On Claude it deploys to `.claude/rules/<stem>.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`.
always-on source. Stop and hand to `agentsmd-author`; if it is not installed, edit the repo's
AGENTS.md directly.
- **No file pattern fits** → an instruction without `applyTo` is always-on in every session of
every repo that installs this package, and `apm compile` can fold it into the global sections of
`AGENTS.md` and `CLAUDE.md` (CLAUDE.md is skipped when `.claude/rules/` is populated, AGENTS.md
when `.github/instructions/` is, unless `--force-instructions`). 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`.
- **Which harnesses receive it, or other package config** → set by the package `apm.yml`
`targets:`, never by the instruction file. Stop and hand to `apm-workflow`.
- **A rule scoped to a file pattern** → continue.
## Checklist

View File

@@ -26,6 +26,8 @@ worse skill on every harness.
`disable-model-invocation: true`: the prompt's body reaches the model, and the model cannot
invoke a skill that sets it, so the steering would dead-end (the same check `factory-audit`'s
prompt flow applies).
- **Which harnesses receive it, or other package config** → set by the package `apm.yml`
`targets:`, never by the prompt file. Stop and hand to `apm-workflow`.
## Description contract
@@ -36,7 +38,8 @@ trigger clause invites the router to pick the wrapper over the skills it wraps.
## Checklist
Copy `assets/templates/name.prompt.md.template` and drop `.template` only on the final path.
Copy `assets/templates/name.prompt.md.template` and drop `.template` only on the final path. No
parameters: delete `input:` and the `${input:…}` line.
Must:

View File

@@ -2,7 +2,8 @@
## apm-cli-installed-source
- **URL:** file:///root/.local/pipx/venvs/apm-cli/lib/python3.11/site-packages/apm_cli/
- **URL:** https://github.com/microsoft/apm/tree/v0.28.0/src/apm_cli/
- **Note:** read locally from the pipx install at `~/.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; each Must/Should traces to the research docs' Authoring checklists or audit-only lists, or to ADR-0029, with tier moves annotated inline, and the `**/*.instructions.md` local-discovery glob behind the template-suffix Gotcha is `primitives/discovery.py` `LOCAL_PRIMITIVE_PATTERNS`; the per-target event rename maps are `integration/hook_integrator.py` `_HOOK_EVENT_MAP`; and Step 4.2's render relies on `apm install <local path>` deploying the working tree to every `--target`, verified against 0.28.0
- **Contributing files:** SKILL.md, references/hook.md, references/instruction.md, references/prompt.md