verify-project-tighten-only
Verify: a project policy cannot weaken the user policy under tighten-only
The promise
Property. With CC_SAFETY_NET_PROJECT_TIGHTEN_ONLY=1, every protection the user policy gives on its own is still given after mergeProjectPolicy merges in the project policy.
Harm if broken. A user opts into tighten-only so that a cloned repo cannot relax their guard. If the merge misses one weakening, a repo's project policy file silently turns off a destructive-command rule, a capability such as fail_closed, or secret protection for a path, and the agent runs what the user meant to block.
Run it
bun test tests/core/policy/merge-tighten-only.test.ts
It takes about 2 seconds and needs no tool beyond Bun. It also runs in bun run check (the pre-push hook and CI), so a break fails the push even if nobody runs it by hand.
What it checks
The check calls the real code, not a copy: mergeProjectPolicy(user, project, true, sessionSafetyLevel(user.safety.level, env)) exactly as loadPolicyConfig in src/core/policy/store.ts calls it. It then turns both the user policy alone and the merged policy into a set of protections with the same functions the hook uses: getCCSafetyNetEnvModes (capabilities, worktree mode), resolveEffectiveDestructiveCommandRules (which destructive rules are on), and resolveSecretDisabledRules. It fails if any protection of the user policy is missing from the merged one, and prints at most three counterexamples.