fix(kyberforge): resolve PR #144 review and audit round 1

- factory-audit: no-op hooks, ./ after interpreters, split-quote and
  spaced ${PLUGIN_ROOT} paths, camelCase events in Claude-targeted flat
  files, case-insensitive routing stems, and non-string YAML keys are
  now caught; input: forms and prompt boundary clauses align with
  primitive-author; bats 347 -> 367
- primitive-author: routing forms, quoting guidance, install exit on
  hidden Unicode, argument-hint exception
- forge: drop duplicated gotcha, fit description and body budgets (#143)
- skill-author: primitive-author boundary, Claude-only env vars
- hook: exit unless CLAUDE_PROJECT_DIR is set, so Copilot/Codex never
  run apm update; ADR-0019 correction, ADR-0025 amendment, docs fixes

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 20:13:43 +00:00
parent b2d77b2945
commit df28351d3e
23 changed files with 591 additions and 147 deletions

View File

@@ -15,7 +15,7 @@ metadata:
## Gotchas
- `apm compile --validate` is not a gate: it reports instruction problems only as warnings, exits 0, and never reads prompts. `apm install` fails only on a hook payload Copilot would reject, and merely warns on bad prompt input names and dropped keys — `/factory-audit` is the only check that fails on the rest.
- `apm compile --validate` is not a gate: it only warns on instructions, exits 0, and never reads prompts. `apm install` exits 1 only on a hook payload Copilot would reject or on critical hidden Unicode, which also blocks the package's deployment; bad prompt input names and dropped keys merely warn — `/factory-audit` is the only check that fails on the rest.
- Never draft with the real suffix outside `.apm/<type>/`. apm's local discovery globs `**/*.instructions.md` across the whole tree, so a draft or template named that way anywhere in the repo is picked up as a real instruction. 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.

View File

@@ -86,9 +86,15 @@ Should:
Claude receives `"*"`.
9. Do not author Copilot's flat `bash` / `powershell` / `timeoutSec` keys in a Claude-shaped file;
they render onto Claude as stray keys.
10. Quote a script path that may contain spaces: `"${PLUGIN_ROOT}/scripts/my hook.sh"`.
10. Keep script paths free of spaces, and when quoting, quote the whole token:
`"${PLUGIN_ROOT}/scripts/my-hook.sh"`. apm rewrites `${PLUGIN_ROOT}` only when a path separator
follows it directly, and only up to the next space or quote — so `"${PLUGIN_ROOT}"/scripts/x.sh`
is left unrewritten and a spaced path is cut short.
11. Keep helper files in the hook directory non-JSON. Copilot's loader rejects any bundled `.json`
without a `hooks` key.
12. Prefer `${PLUGIN_ROOT}` over `${CLAUDE_PLUGIN_ROOT}`.
13. No `hooks-<target>` or `*-<target>-hooks` filename. That routing is deprecated and reach belongs
to `targets:` (see Gate); the research allows it only when deprecated routing is intended.
13. 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.

View File

@@ -32,7 +32,8 @@ Must:
1. The path is `.apm/instructions/<stem>.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.
2. `description` is a non-empty string. Only `apm compile` warns when it is missing; `apm install`
deploys it silently.
3. The body is non-empty after trimming whitespace. 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}"`), braces and brackets balanced — or absent after the

View File

@@ -59,7 +59,8 @@ Should:
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.
8. Omit `argument-hint` when `input:` is set, unless the `<a> <b>` form apm synthesises from the
input names is inadequate; an explicit `argument-hint` wins.
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