# tests/ Test files for scripts bundled with this skill. ## When to add tests Add tests here when the skill has scripts in `scripts/` that are complex enough to break silently — validators, parsers, generators, anything with branching logic or edge cases. Test infrastructure (`.bats`, `*_test.*`, `test_*.sh`) belongs here, not in `scripts/`. ## Dependencies Tests require [bats-support](https://github.com/bats-core/bats-support) and [bats-assert](https://github.com/bats-core/bats-assert). The test files load helpers from the repo root's `tests/test_helper/`. From the repo root: ```bash git clone https://github.com/bats-core/bats-support tests/test_helper/bats-support git clone https://github.com/bats-core/bats-assert tests/test_helper/bats-assert ``` Run all tests for this skill (from the repo root): ```bash bats plugins/kyberforge/.apm/skills/factory-audit/tests/ ``` ## Files | File | Purpose | |------|---------| | `validate-skill.bats` | `scripts/validate.sh` against skill directories | | `validate-agent.bats` | `scripts/validate.sh` against agent files | | `validate-provenance-skill.bats` | `scripts/validate-provenance.sh` against skill directories | | `validate-provenance-agent.bats` | `scripts/validate-provenance.sh` against agent files | | `validate-primitive.bats` | `scripts/validate.sh` against apm hook, instruction and prompt files | ## Two scripts, five suites `factory-audit` merges what were two skills — `skill-audit` and `agent-audit` — each of which shipped its own `validate.sh` and `validate-provenance.sh`. The merged skill has **one** of each. Every suite here invokes one of those two scripts; the four skill and agent files are two scripts × two artifact types, not four scripts. `validate-primitive.bats` is a fifth suite over the same `scripts/validate.sh`, for hooks, instructions and prompts, which have no provenance mode and so no provenance suite. `validate-skill.bats` and `validate-agent.bats` run the same `scripts/validate.sh` and differ only in the fixtures they point it at. The two provenance suites stand in the same relation to `scripts/validate-provenance.sh`. Do not add a third script path here on the assumption that a differently named suite must mean a differently named script. ### Auto-detection is pinned across the suites Each entry point decides for itself what it was handed. ADR-0025 states the skill and agent rule: a directory containing `SKILL.md` takes the skill flow; an `.agent.md` file, or a file under a directory named `agents/`, takes the agent flow. `scripts/validate.sh` adds three primitive shapes: a `*.instructions.md` or `*.prompt.md` file takes the instruction or prompt flow wherever it sits, and a `.json` file directly under a `hooks/` directory takes the hook flow. Any shape outside the five is rejected rather than guessed at. Classification could not be wrong before the merge — each script was hard-wired to one artifact type — so it is asserted from every side rather than in one place: - the skill-side suites pin the skill-directory classification and the neither-shape rejection, - the agent-side suites pin the two agent rules *separately* — `.agent.md` in a directory that is not `agents/`, and a plain `.md` under `.apm/agents/` — so that a detector implementing only one of them cannot pass both. Plus a control asserting an agent file never picks up a skill-only gate. - `validate-primitive.bats` pins the hook, instruction and prompt shapes, including the precedence that makes a `*.instructions.md` or `*.prompt.md` under `agents/` take the primitive flow rather than the agent flow, a hook file under a package-root `hooks/`, and a `.json` outside `hooks/` matching no shape. It also pins the primitive exit tiers: every negative case asserts exit 1 (`assert_failure 1`), and a missing python3 or PyYAML asserts exit 2. Both skill-side suites additionally pin the `SKILL.md` **file** path, not just the directory: a pre-commit `files:` hook matches files, so every hook-driven invocation hands over a `SKILL.md` path. Each entry point resolves it to the directory, and the suites assert the two spellings produce the identical verdict rather than merely that the file spelling survives. A misclassification is silent and total — the wrong rubric runs end to end and reports the artifact clean against gates that never applied to it — and no other fixture in these suites would notice, because every other fixture is already the shape its own suite expects. ### The two provenance exit contracts are different on purpose `scripts/validate-provenance.sh` does **not** behave identically in its two modes, and the difference is deliberate: | Mode | Successful run | |------|----------------| | skill | may exit 0 **with** output — INFO findings print, status stays 0 | | agent | exits 0 and prints **nothing** | Each half is asserted from its own side, by the `exit contract:` test in each provenance suite. Both are asserted on purpose: a merge that collapsed one contract into the other would still satisfy whichever side was left unasserted, so a single-sided pin would go green on exactly the defect it exists to catch.