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
4.3 KiB
source_keys
| source_keys | ||
|---|---|---|
|
Hook Flow
Steps 1 to 3 for an apm hook — the target Step 0 matched as a .json file directly under a
hooks/ directory. Work them in order, then return to SKILL.md Step 4 to report.
Gotchas
- apm checks almost nothing here. Invalid JSON is skipped without a word, an all-lowercase event deploys and never fires, and a missing script only warns — so
apm installexiting 0 says nothing about whether the hook works. Never cite a clean install as evidence against a finding. - Copilot receiving a Claude-shaped file is not a finding. apm renders one source for every target and documents that it owns the per-target shape; whether Copilot CLI honours a nested entry or
matcheris unverified upstream, not a defect in the file.
Step 1 — Deterministic checks
Resolve the path against this skill's own directory. Run exactly:
bash scripts/validate.sh <hook-file>
Its findings become the ### Structure dimension, FAILs and SUGGESTIONs both, at the tier the script assigned: JSON validity, the wrapped-or-naked shape, event lists and nested handler lists (the checks whose failure makes the Copilot install fail), a file contributing no entries, event names that never fire, referenced scripts that are missing, outside the package, not executable when run directly, or referenced by an absolute or bare relative path apm will not bundle, deprecated filename routing, and ${CLAUDE_PLUGIN_ROOT} where ${PLUGIN_ROOT} would do. It exits 0 with no FAIL, 1 on real findings, 2 when it never ran — report that as ### Structure unverified, quoting the stderr reason.
There is no provenance and no Vale step: a hook carries no source_keys and no prose.
Three tiers deliberately differ from primitive-author's checklist or the research's. Do not re-tier them by judgment:
- A hook file directly under a package-root
hooks/passes. apm discovers both.apm/hooks/andhooks/, and this audit may target a third-party package;primitive-authorauthors only in.apm/hooks/. - Deprecated filename routing is a SUGGESTION, matching the author's Should: the research allows it when deprecated routing is intended.
- A non-executable script run as the command's first token is a FAIL, stricter than the research's Should, because it fails every time it fires.
Step 2 — Read the hook and its scripts
Read the hook file, every script it references, and the package's apm.yml targets: — reach is narrowed there, never in the hook file.
Step 3 — Qualitative audit
Cite file and line for every finding.
purpose — apm's own rule is to reach for a skill, instruction or prompt first; a hook is for "this must always happen at this event".
- FAIL: the script carries procedure the agent should follow — instructions printed to the model, a multi-step workflow — rather than a runtime callback. That is a skill.
- SUGGESTION: the behaviour is harness-specific (a Claude-only event, a Claude-only matcher value) in a package whose
targets:includes other harnesses, and nothing records that the other targets receiving it was accepted. The apm-native fix is a separate package with its owntargets:, not a routing filename.
handlers — the research checklist's Should and audit-only items, which apm never checks:
- SUGGESTION: a handler without
"type": "command"or an explicit numerictimeoutin seconds. - SUGGESTION: a tool event (
PreToolUse,PostToolUse) orSessionStartwith nomatcher— Claude receives"*". Amatcheron an event Claude ignores it for (Stop,UserPromptSubmit) is inert, not wrong. - SUGGESTION: a PascalCase event name that is not a real Claude Code event (a misspelling deploys verbatim and never fires; the script cannot tell a typo from an event it does not know).
- SUGGESTION:
bash/powershell/timeoutSeckeys in a Claude-shaped file — they render, but leave stray keys insettings.json. - SUGGESTION: an unquoted script path that could contain spaces.
- SUGGESTION: a helper
.jsonfile in the hook directory without ahookskey — Copilot's loader scans the bundled scripts directory and rejects it. Keep helper configuration non-JSON.
Then return to SKILL.md Step 4, opening the report with this coverage line:
Checked: structure · purpose · handlers