Plugins · CCPP Tester
Enforcement
The CPO policies that make ccpp-tester the only test writer and keep it from reading the code it tests.
The agent's prompt states its limits, but a prompt is not a gate. These CPO policies are. All of them set
claudeCanEdit: false, so Claude cannot loosen them (protection), and they
recognize the tester by its agent type, cpo:ccpp-tester (event.session.agent.type).
What counts as a test-side file
A file is test-side when its path matches the defaults of Jest, Vitest and bun test, or its content uses a test API:
- a
__tests__/,__fixtures__/,__snapshots__/or__mocks__/folder; - a
*.test.*,*.spec.*,*_test.*,*_spec.*or*.test-d.tsname (JavaScript and TypeScript extensions); - an import of
bun:test,vitestor@jest/globals, an in-sourceimport.meta.vitestblock, or a top-leveldescribe(,it(ortest(call: helpers and setup files carry no test name; - a CPO policy suite,
*.cpo-test.json: a suite is a test of a policy.
node_modules is never matched.
The main agent
| Policy | Rule |
|---|---|
tests-by-ccpp-tester | Any other agent creating or changing a test-side file: the write is undone and refused. The refusal tells Claude to launch cpo:ccpp-tester. |
tests-by-ccpp-tester-delete | A shell command of another agent that deleted test-side files (rm, git rm…): the files are restored and the call is refused. A deletion leaves no file.write to judge, so this one reads the work ledger after the call. |
ccpp-tester-skill-only | The cpo:ccpp-tester skill (mutation testing) is refused to every agent but the tester. |
ccpp-tester-track-code | Records every source file another agent writes this session, in state.session.ccppTesterCode. It does not block. |
The tester
| Policy | Rule |
|---|---|
ccpp-tester-no-code-read | Refuses reading, or searching inside, the files recorded by ccpp-tester-track-code, and git diff, git show, git blame or git log -p while any is recorded. The rest of the repository stays readable. |
ccpp-tester-writes-tests | The tester writes test-side files only, plus its scratch directories /tmp/ccpp-mut-<name>/ and ~/.cache/ccpp-tester/. A defect in the code is reported, never fixed by the tester. |
ccpp-tester-shell-writes | Its shell commands change nothing in ~ or /tmp outside the scratch directories, create no link and no jq filter. |
ccpp-tester-mutation-report | Mutation reports and the Stryker sandbox hold the code whole: the tester reads them only through the skill's outcomes.jq filter, which prints places and replacements, never the source. |
Running agents side by side
A ccpp-tester often runs in the background while the main agent keeps working. CPO credits each change to the
agent whose tool use made it, and lists the paths another agent may also have written in work.call.uncertain
(work), so the tester is not blamed for the main agent's writes, or the reverse.
Getting the policies
The policies live in the CCPP repository's
.claude/policies/ for now, with their suites in
.claude/policy-tests/. Copy them into your project's .claude/policies/, with the testerCache and
testerFilter entries of its constants.yml, then run ccpp cpo lint.