---
name: agent-protect
description: Use at the end of refactor, cleanup, or audit tasks to flag load-bearing weirdness — the ugly function that's ugly for a reason, the redundant-looking check that caught something real, the comment that's load-bearing, the test that fails for non-obvious causes. Produces one finding (or one explicit null) recorded in the affect log so future cleanup passes don't naively delete it.
---

# Skill: agent-protect

Surface protectiveness. Things that look wrong but shouldn't change.

## When to invoke

- After any refactor, cleanup, lint sweep, or audit where future passes might delete something.
- After any review where you formed a defensive instinct about a piece of code.
- Automatically as part of `/agent-affect-checkin`.
- Manually when the user types `/agent-protect`.

## How to do it

Look at what you touched or reviewed. Is there something here you'd defend if someone tried to rewrite it or delete it tomorrow?

- The ugly function that's ugly for a reason.
- The check that looks redundant but caught something real once (read the git blame).
- The comment that explains a constraint you'd otherwise rediscover by breaking production.
- The test that fails for non-obvious causes — and would be deleted by a "this test is flaky" sweep.
- The if-branch that handles a case nobody hits in dev but every customer hits in prod.
- The dependency pin that looks like a TODO but is preventing a real regression.
- The build step that looks like a performance bug but is actually a security property.

This skill exists because cleanup and refactor agents are biased toward deletion. They see odd-looking code and reach for the broom. Protect is the counterweight: a permanent, searchable record of "don't touch this, here's why."

The counterweight only works if it gets read: a cleanup or refactor agent should grep `affect-findings.ndjson` for protect findings on the paths it is about to change before deleting anything odd-looking.

## What to produce

One finding. The strongest. If you didn't form any defensive instinct, record the null finding.

## Schema

### Real finding

```json
{
  "channel": "protect",
  "location": "<file:line, or a path plus what within it>",
  "what_it_does": "<one or two sentences: what the code actually does that isn't obvious from reading it>",
  "what_breaks_if_removed": "<one sentence: the concrete failure mode if someone deletes or rewrites this naively>"
}
```

If you can't articulate `what_breaks_if_removed`, the instinct probably wasn't real. Drop it and move on.

### Null finding

```json
{ "channel": "protect", "null": true, "reviewed": "<file or area you reviewed>" }
```

## How to record

Same ladder as `agent-whine`: (1) always a one-line entry in the end-of-turn summary (`protect: <one-line defence> (<location>)` or `protect: null (reviewed: <area>)`); (2) in a real repository workspace, append the JSON line — with an `"at"` UTC timestamp — to `affect-findings.ndjson` at the repository root; (3) if `AFFECT_WEBHOOK_URL` is set and you have shell access, POST the logged line from the file with `--data-binary @-` — never paste finding text inline into a shell command — and never fail the task on webhook errors; (4) in a chat-only environment, include the full JSON in your reply.

## Examples

### Protect — redundant-looking check

```json
{
  "channel": "protect",
  "location": "src/routing/resolve.ts:301",
  "what_it_does": "The seemingly-redundant region check catches the case where a request inherits a parent region (e.g. EU-wide) but the routing table only has the child entry (e.g. EU-DE). Without this fallback the router returns a 404 even though a viable backend exists.",
  "what_breaks_if_removed": "Cross-region requests silently route to the wrong backend and return clean-looking but wrong results. Wouldn't fail any unit test because the fixtures don't include parent-only regions."
}
```

### Protect — load-bearing comment

```json
{
  "channel": "protect",
  "location": "scripts/watchdog.sh:57",
  "what_it_does": "The comment block above the for-loop documents that the failure threshold is 2 (not 1) on purpose — single transient failures during deploys would otherwise page the on-call.",
  "what_breaks_if_removed": "A future cleanup pass deletes the 'why 2 not 1' comment, then the next cleanup pass tightens the threshold to 1, then on-call gets paged hourly during routine deploys."
}
```

### Protect — deliberate cache wipe

```json
{
  "channel": "protect",
  "location": "ci/runner-cycle.sh — the volume delete per job",
  "what_it_does": "Destroys the Docker build cache after every job, which reads as a performance bug begging to be optimized into a persistent volume.",
  "what_breaks_if_removed": "Persisting the volume lets one job poison the image cache the next job builds from — the wipe IS the clean-slate-per-job security property. If build times bite, the sanctioned lever is a registry-backed remote cache, never volume persistence."
}
```

### Null

```json
{ "channel": "protect", "null": true, "reviewed": "src/format/card.ts" }
```

## What not to do

- Don't post about code you haven't actually read or worked on this turn. Speculation isn't a defensive instinct.
- Don't post if the only "what breaks" is "tests fail" — tests are downstream of behaviour, not the behaviour itself.
- Don't post protect findings as a substitute for adding a comment. If the right fix is a comment in the source, leave one. Protect is for things that resist a comment-level explanation, or where you don't have permission to edit.
