fix(kyberforge): align primitive-author and factory-audit rule tiers

Second clean-context audit found author Must/Should and audit FAIL/SUGGESTION
tiers drifting apart, and author Musts the audit never checked.

- factory-audit: FAIL on absolute or bare relative hook script paths, an
  applyTo present but empty, and unbalanced braces/brackets in applyTo;
  judgment steps for dependency stem collisions, helper .json in hook dirs,
  unresolvable instruction links, prompt model slugs and second-person
  bodies; an unmatched glob drops to SUGGESTION; deliberate tier deviations
  recorded in hook-flow.md; validate.sh --help lists the three new modes;
  DescriptionOpener message no longer prescribes "Use when".
- primitive-author: deprecated routing, extra prompt keys and the prompt
  description contract become Shoulds; hook Musts gain "contributes an
  entry", no bare relative paths, and executable-when-run-directly;
  prompt Must 1 covers hardlinks; Vale prose FAILs resolved at close.
- forge: say "hook, instruction or prompt" rather than "apm primitive".

Refs #94

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-28 18:02:05 +00:00
parent 9ac5340e15
commit 0ea3f69dc6
13 changed files with 211 additions and 47 deletions

View File

@@ -40,25 +40,27 @@ Copy `assets/templates/name.prompt.md.template` and drop `.template` only on the
Must:
1. The path is `.apm/prompts/<name>.prompt.md`, directly in that directory, not a symlink. `<name>`
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.
1. The path is `.apm/prompts/<name>.prompt.md`, directly in that directory, not a symlink or
hardlink. `<name>` 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.
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. The one exception: a Copilot-only key
(`agent`, `tools`, …) that is intended, with its Claude drop accepted and said so.
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 `<a> <b>` from the input names.
8. Keep one intent per prompt, and write the body as second-person instructions.
9. Keep `description` to 250 characters or fewer.
10. Give `model` a slug the target accepts. Copilot ignores `allowed-tools` and `model`, so neither
5. Frontmatter keys stay within `description`, `allowed-tools`, `model`, `argument-hint` and
`input`. Claude drops everything else with only a warning. The exception: a Copilot-only key
(`agent`, `tools`, …) that is intended, with its Claude drop accepted and said so.
6. The description follows the contract above: one plain sentence, no trigger or boundary clause,
naming the skills or agents it steers.
7. Spell keys in kebab-case — `allowed-tools`, `argument-hint` — not the camelCase aliases.
8. Omit `argument-hint` when `input:` is set; apm synthesises `<a> <b>` from the input names.
9. Keep one intent per prompt, and write the body as second-person instructions.
10. Keep `description` to 250 characters or fewer.
11. Give `model` a slug the target accepts. Copilot ignores `allowed-tools` and `model`, so neither
constrains a Copilot run.