feat(kyberforge): primitive-author and factory-audit support for apm hooks, instructions and prompts #144
Reference in New Issue
Block a user
Delete Branch "feat/primitive-author"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Closes the gap #94 describes: kyberforge had no author or audit support for three apm primitives (hooks, instructions and prompts), and
forgehad no route for them.primitive-author(new skill). It authors and improves hooks, instructions and prompts.SKILL.md.references/{hook,instruction,prompt}.mdhold each primitive's boundary gate and Must/Should checklist, andassets/templates/holds.templatefiles.factory-auditinline, thenapm install --dry-run, the package version bump, and commit verification.factory-audit: three new Step 0 flows (hook, instruction, prompt). These follow ADR-0020's merge-siblings rule rather than adding a separate audit skill.scripts/lib-checks-primitive.sh. Judgment checks are in the flow references.forgegains a route for hooks, instructions and prompts toprimitive-author, using the same two-tier clean audit.CONTEXT.mdgains the terms apm primitive, Prompt, Instruction and Hook.plugins/kyberforge/docs/research/docs/microsoft-apm/) are completed and corrected against apm 0.28.0:.claude/settings.jsonis overwritten on install.${PLUGIN_ROOT}..claude/settings.jsonentry is unchanged. This was checked by installing two scratch packages that differ only in the token and comparing the output byte for byte.docs/hooks.mdare corrected.lib-boundary-resolver.shandvalidate-adapter.batsare now Python unicode escape sequences, which silences apm's hidden-character warning. skill-author's${CLAUDE_PLUGIN_ROOT}guidance now points toprimitive-author.Versions
executables.allowkey moves with it.marketplace.jsonregenerated.factory-audit1.1.1,forge1.0.2,skill-author1.0.6.primitive-authoris new at 0.1.0.Verification
factory-auditpasses with a consistency check against ADR-0029,CONTEXT.mdand the research checklists. All findings are resolved (commits9ac5340,0ea3f69).primitive-authorandfactory-auditpass with no findings.forgepasses with 2 suggestions for description and body length that predate this PR, tracked in #143.factory-auditbats 347/347, andtests/run-tests.sh21/21 suites.apm audit --ci,apm pack --check-clean, the provenance corpus check and the executables allow-key sync.Not in this PR
forgelength budgets, tracked in #143.*.instructions.mdand*.prompt.md. The repo has none of these files yet, socheck-hooks-applyandtest-vale-wrap.shcase 32 reject a hook that matches nothing. Vale's glob coverage for them is already tested in case 28.matcher, and how strongly Claude avoids routing to a prompt description with no trigger clause.Fixes #94
🤖 Generated with Claude Code
https://claude.ai/code/session_01KkT7RSDwDbmrM9T34b6sTi
factory-audit gains three Step 0 rows and flows for the apm primitives that have no container of their own: a .json file under hooks/, a *.instructions.md and a *.prompt.md. apm validates almost none of them (invalid hook JSON is skipped silently, instruction validate() only warns, input: names are never checked against ${input:x}), so the deterministic checks live in a new scripts/lib-checks-primitive.sh, wired into validate.sh's path-shape detection. Each check and tier traces to the Authoring checklists in the microsoft-apm research docs. - Hook: JSON/shape/event-list checks mirroring the Copilot payload validator, never-firing event casing, missing/escaping/non-executable scripts (FAIL); deprecated filename routing and ${CLAUDE_PLUGIN_ROOT} (SUGGESTION). - Instruction: location, frontmatter, description, body, stem clash (FAIL); missing or list applyTo and unread keys (SUGGESTION). - Prompt: location/name, frontmatter, description, input names, the upstream `- name: x` docs bug, declared-vs-used ${input:x} (FAIL); ADR-0029 description length and trigger clause, dropped keys, camelCase aliases, argument-hint with input (SUGGESTION). Whether a prompt carries procedure is judgment in prompt-flow.md, not a script heuristic. Vale now lints *.instructions.md and *.prompt.md with the Kyberforge style; test-vale-wrap.sh gains their probe rows. New tests/validate-primitive.bats (31 cases). kyberforge 2.0.1 -> 2.1.0 with the executables.allow key, catalog 0.5.1 -> 0.5.2, marketplace.json regenerated. Refs #94 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KkT7RSDwDbmrM9T34b6sTiSwitch the SessionStart hook to apm's target-neutral ${PLUGIN_ROOT} token. Two scratch packages differing only in the token deploy byte-identical SessionStart entries with apm 0.28.0, matching the committed .claude/settings.json, so the deployed output does not change. The test pin in tests/test-apm-current-hook.sh moves with it. Correct the claim that Copilot loads no hooks from kyberforge. targets: is package-wide, so apm also writes .github/hooks/kyberforge-hooks.json (nested shape passed through, runtime unverified) and merges into .codex/hooks.json when .codex/ exists. Recorded as accepted in an ADR-0019 amendment dated 2026-09-28; README and docs/hooks.md updated. Refs #94 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KkT7RSDwDbmrM9T34b6sTideployment-modes.md told authors to use ${CLAUDE_PLUGIN_ROOT} in hook commands. Hook authoring now belongs to primitive-author, which specifies the target-neutral ${PLUGIN_ROOT}; point there instead. Refs #94 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KkT7RSDwDbmrM9T34b6sTi- 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_01KkT7RSDwDbmrM9T34b6sTiReview and audit loop: 3 rounds
I ran three rounds of review and fixes on this PR. Each round had:
factory-auditof every changed primitive:primitive-author,factory-audit,forge,skill-author,apm-workflow, and kyberforge'shooks.json,skill-author/primitive-author, followed by the full test suite.The audits used the branch copy of
factory-audit. The deployed copy is older than this PR and cannot audit hooks, instructions or prompts.df28351965208b5d0f988After round 3, every agent that applied fixes re-audited its own changes and got PASS; two of those results still carry an INFO note. No fourth independent round was run, because the cap was three rounds.
Behaviour changes
CLAUDE_PROJECT_DIRis set.apm update --yesin Copilot and Codex sessions.docs/hooks.mdare corrected, and there are new tests for the variable being unset or empty.bash -e,sh -c "…");${PLUGIN_ROOT}path with the quotes split or a space in it, which apm does not rewrite;_HOOK_EVENT_MAP).npx prettier ./srcandprintf '.\n'no longer FAIL, and Claude-plugin layouts (plugin.jsonwith noapm.yml) are accepted.apm install --dry-runreplaced. The dry run showed neither what each target receives nor the branch's own files. The step now renders into a throwaway consumer with a local-path install, which was verified with apm 0.28.0.0.1.0(ADR-0022).new-skill.shworks with both GNU and BSDsed. A failed run no longer leaves a half-built scaffold, and re-running it on a finished skill changes nothing.primitive-author, so the two skills no longer overlap.Verification
tests/run-tests.shpasses 21/21 suites.apm audit --ci,apm pack --check-clean, the provenance corpus check and the version-bump check..claude/settings.jsonnorapm.lock.yamlwas touched.Decisions worth a look
sources.md. These lists will need updating when those docs change.userPromptSubmitted, but apm renames it touserPromptSubmit. The audit accepts apm's name because authors cannot change the rename. This may be an apm bug worth reporting upstream.If named, use instead: skill -> …, at exactly 250 characters. That fits the budget and keeps the "already named" qualifier.Still open
.claude/skills/factory-auditstays stale until this merges tomainand is reinstalled.🤖 Generated with Claude Code
https://claude.ai/code/session_01KkT7RSDwDbmrM9T34b6sTi
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.