ccppccpp home
Browse the documentation

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.ts name (JavaScript and TypeScript extensions);
  • an import of bun:test, vitest or @jest/globals, an in-source import.meta.vitest block, or a top-level describe(, it( or test( 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

PolicyRule
tests-by-ccpp-testerAny 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-deleteA 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-onlyThe cpo:ccpp-tester skill (mutation testing) is refused to every agent but the tester.
ccpp-tester-track-codeRecords every source file another agent writes this session, in state.session.ccppTesterCode. It does not block.

The tester

PolicyRule
ccpp-tester-no-code-readRefuses 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-testsThe 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-writesIts shell commands change nothing in ~ or /tmp outside the scratch directories, create no link and no jq filter.
ccpp-tester-mutation-reportMutation 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.

Edit this page on GitHub