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

@@ -261,6 +261,20 @@ no hook at all, for the reasons already documented in `plugins/kyberforge/docs/h
> need a separate package declaring `target: claude` — the seventh-plugin alternative below, still
> rejected as disproportionate — because per-file routing (`claude-hooks.json`) is deprecated and
> narrowing kyberforge's own `targets:` would drop its skills from Copilot and Codex.
>
> *The "inert" rationale for the reach is superseded by the correction below.*
> **Correction (2026-09-28) — the lockfile guard never made the hook inert under Copilot or Codex;
> a `CLAUDE_PROJECT_DIR` guard now does.** The hook only reaches a project through `apm install`,
> which writes `apm.lock.yaml`, so in every project that receives it the lockfile guard passes. The
> script then fell back to `$PWD` for its project directory and ran `apm outdated`, and
> `apm update --yes` when anything was stale — a lock rewrite and full redeploy on a Copilot or Codex
> session start, with no `reloadSkills` or advice that harness understands. The hook is now Claude
> Code only: `check-apm-current.sh` opens with `[[ -n "${CLAUDE_PROJECT_DIR:-}" ]] || exit 0`, the
> cwd fallback is gone, and `tests/test-apm-current-hook.sh` pins that an unset or empty
> `CLAUDE_PROJECT_DIR` exits 0 silently without invoking `apm`. apm still deploys the hook to
> Copilot and Codex; it exits immediately there. The acceptance stands on that guard, not on the
> lockfile. The seventh-plugin alternative below remains rejected, now for the same reason.
**`scripts/git-hooks/` is now empty.** `post-push` and `test-post-push.sh` are deleted.
`install.sh`'s copy block is generic and is kept; `test-git-hooks-install.sh` now synthesizes its

View File

@@ -172,6 +172,31 @@ fallback row. It could not route a `SKILL.md` file path, a trigger its own descr
Its agent row ("a path under `.apm/agents/`… or an agent markdown file") was both wider than the
script and circular.
> **Amendment (2026-09-28) — three more modes: hook, instruction and prompt.** The "two accepted
> shapes" above are now five. The `primitive-author` change (issue #94, PR #144) added three rows to
> the Step 0 table, each with its own self-contained flow file and a shared
> `scripts/lib-checks-primitive.sh` that `validate.sh` sources for all three:
>
> - A file named `*.instructions.md` takes the instruction flow (`references/instruction-flow.md`).
> - A file named `*.prompt.md` takes the prompt flow (`references/prompt-flow.md`); the prompt rules
> themselves are ADR-0029's.
> - A `.json` file whose *immediate* parent directory is `hooks/` (`.apm/hooks/`, or a package's
> root `hooks/`) takes the hook flow (`references/hook-flow.md`).
>
> The suffix rows are checked before the `agents/`-parent rule, so a `*.prompt.md` or
> `*.instructions.md` under `agents/` is not audited as an agent. The fallback row is unchanged in
> kind: anything else stops, runs no validator, exits 2, and names every accepted shape rather than
> two. The exit-code table below applies to the new modes as written; its "matches neither shape"
> row now means "matches none of the five".
>
> This is ADR-0020's merge-siblings rule applied forward rather than a new decision. Auditing a hook,
> an instruction or a prompt is the same job as auditing a skill or agent — deterministic checks,
> a read, a qualitative pass, one shared report — over a different input type, which is exactly the
> case the rule says belongs in one skill behind a dispatch table, not in a new sibling audit skill.
> The authoring side follows the rule's other half: the author skills stay split because they emit
> genuinely different artifacts, so the three primitives got their own `primitive-author` rather
> than rows in `skill-author` or `agent-author`.
**3. One entry point per script, auto-detecting, with the mode-specific half sourced.**
- `scripts/validate.sh` detects the target type itself, then sources `scripts/lib-boundary-resolver.sh`