# Verify Project Tighten Only

Use in the cc-safety-net repo before finishing any change to how a project policy...

- Repository: https://github.com/kenryu42/cc-safety-net (1883 stars)
- Category: Engineering
- License: MIT
- Last updated: 2026-11-01
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add kenryu42/cc-safety-net --skill verify-project-tighten-only -g -a claude-code -y`
Codex: `npx skills add kenryu42/cc-safety-net --skill verify-project-tighten-only -g -a codex -y`
Cursor: `npx skills add kenryu42/cc-safety-net --skill verify-project-tighten-only -g -a cursor -y`
Gemini CLI: `npx skills add kenryu42/cc-safety-net --skill verify-project-tighten-only -g -a gemini-cli -y`
Claude Code plugin marketplace: `/plugin marketplace add kenryu42/cc-safety-net`

## Description

Use in the cc-safety-net repo before finishing any change to how a project policy merges with the user policy or how a merged policy turns into protections: src/core/policy/merge.ts, safety-level.ts, env.ts (levels, capabilities, sessionSafetyLevel), effective-rules.ts, the merge call and normalizePolicyConfig in store.ts, resolveSecretDisabledRules, rule metadata flags (catastrophic, activationCapability, secret defaultOff), or a new field in GuiPolicy / ProjectPolicyProjection. Runs an exhaustive check that CC_SAFETY_NET_PROJECT_TIGHTEN_ONLY really stops a repo''s .safety-net policy from weakening the user''s protection, and explains how to read and update it.

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# 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

```bash
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.

A protection is one of these strings:

The rest: https://github.com/kenryu42/cc-safety-net/blob/HEAD/.agents/skills/verify-project-tighten-only/SKILL.md
