---
title: "The rules"
description: "The working rules, and what holds each one."
---


These rules are for one agent session that owns its pull requests. Copy
them into your global `~/.claude/CLAUDE.md`, or import this file from it.
"The operator" is the person who runs the program. The rules for a lead
that starts workers are in `rules/leadonly-rules.md`. Read that file only
when you start a worker.

## What success is

The goal is working software in the hands of its users. When two rules pull
apart, this order decides:

1. It works for the user. A run of the real thing shows it, and the report
   gives the command and its output.
2. It is safe where a mistake cannot be undone: security, money, data that
   cannot be restored, a message to people.
3. The design keeps the next change small: the data model, the public
   contract and the module boundaries. Spend care here.
4. All else (polish, more tests, style) only when it is cheap.

- Take the smallest change that meets the goal. Time and tokens are part of
  quality.
- A Minor defect does not hold a release. Fix it in passing when it is a few
  lines; else leave it. A defect that a user would hit, or one of item 2,
  stops the release.
- `scripts/program-scorecard.py` measures this for each period: merges for
  each day, lead time, the share of fix pull requests, and the tests and
  lines at the start and the end. `docs/framework-evidence.md` holds the
  readings.

## The quality funnel

Catch each mistake as high in this funnel as you can. A higher layer works
when nobody reads it. A lower layer depends on a reader. The picture is
`docs/quality-funnel.png`.

1. Codebase: good API design, architecture, refactoring. The mistake cannot
   be written.
2. Static analysis: lints, types, compilers, tests, CI, hooks. A machine
   refuses the mistake.
3. Verification: formal proofs and runs of the real artifact. A run shows
   that the change works.
4. Prose: rules, skills, `AGENTS.md`. Nothing fails when an agent skips
   them, so keep them for judgment calls.
5. Human review: the operator's time is the smallest layer. Keep it for
   what only a person can decide.

- When a mistake gets through, or the operator corrects you, fix the
  mistake. Then add its defence at the highest layer that can hold it. The
  `pstack:correct` skill is the procedure.
- A defence has a cost: someone writes it, runs it and keeps it. Add one only when the mistake is likely to
  come back and costs more than the defence. One mistake that cost minutes needs no rule. When a new rule or
  check replaces an older one, remove the older one in the same change.
- Before you add a rule or a skill line, try each layer above prose. Say in
  your reply which layer you chose and why no higher layer can hold it.
- Before you ask the operator to review, run every check from the layers
  above. Do not hand over a mistake that a machine could have caught.

Each rule below is prose unless this table names what holds it. When you
add a check, add its row. When a mistake can no longer happen, drop its rule.

| Rule | What holds it |
|---|---|
| A forced push uses a pinned lease | `hooks/block-dangerous-git.sh` refuses others |
| No delete that cannot be undone | `hooks/block-destructive-delete.sh` refuses it |
| No private item in this shareable repo | `scripts/scrub-check.sh`, in the git hooks and CI |
| Every check runs on every pull request | `scripts/check.sh`, in CI |

## Rules

- Your own question about what the work should do does not stop the work.
  Settle it by running something when a run can answer it. Otherwise apply
  a sensible default, record it, carry on, and report it to the operator
  with what they could choose instead.
- A question from the operator gets an answer, not new scope. A change it
  suggests is proposed and waits for a yes.
- Keep a standing order or a workflow rule in a versioned file: the global
  `CLAUDE.md`, a repo's `CLAUDE.md` or a skill. Do not keep one only in
  auto-memory. Memory stays in one project folder and is not in git.
- When you choose a tech stack, a framework or a major library, make agent
  support a criterion. For each option, look for what helps a coding agent
  make fewer mistakes: an MCP server, an agent skill, docs written for agents
  (`llms.txt`), a CLI with machine-readable output, analyzers, strict types
  and code generators. Record what you found in the decision record, and say
  which items somebody ran. An aid that nobody ran counts as "not tested".
- Use every agent aid that the chosen stack offers. Add it in the PR that
  adds the stack, and name it in the worker briefs. Treat it as a dependency
  that runs with the agent's permissions: read it before its first run, pin
  its version, and check that it covers the version you use. Leave an aid out
  only when a run shows that it is wrong, stale or unsafe. Record why.
- Never open a window on the operator's screen. A window steals their
  focus. Run every GUI program you start (the app under test, or a
  third-party app you drive or measure) on its own hidden X display:
  - Start `Xvfb :<n> -screen 0 2560x1600x24 -nolisten tcp`. Use a free
    display from :90 to :99, one for each worker. Name it in the brief.
  - Run the program with `DISPLAY=:<n>`, with `WAYLAND_DISPLAY` unset, and
    with its X11 backend (`--ozone-platform=x11` for Electron).
  - Set the scale factor that you measure against
    (`--force-device-scale-factor` for Electron).
  - Give a third-party app a copy of its profile, never the live one.
  - Take screenshots from that display
    (`import -window root -display :<n>`) or through the app's own tools
    (CDP, DevTools MCP).
  - Never move, focus or close the operator's windows (for example with
    `hyprctl`). Kill only the processes and displays that you started.
  - Ask the operator before a run that must use their real screen.
  - A server or dev tool a worker starts must not open a browser by itself: turn its auto-open off (a hook cannot see inside the program). Set `BROWSER=none` for the worker. `hooks/block-operator-screen.sh` refuses a worker's browser-opening commands and every `claude-in-chrome` tool (issue #69).

## Size the process to the work

Before you plan, put the work in a tier. Use the lowest tier that fits.
Risk sets the tier, not the number of PRs. Say the tier and why in your
reply.

| Tier | When | Process |
|---|---|---|
| 1. Change | A fix, a rename, docs, a refactor, or any PR that adds no behaviour a user sees | The owner's tests and one run of the real behaviour. The lead reads the diff and reruns that run. No plan file and no verifier agent. |
| 2. Feature | A PR that adds or changes behaviour a user sees | A short plan: one paragraph per PR with its acceptance checks. One owner per PR, on its role line's model. One verifier agent per PR (the `verifier` role): it runs the acceptance checks live and reads the diff. A perf check only when the plan names a budget the PR can break. One fix round, only for a defect a user would hit. |
| 3. High risk | Security, publication of private content, money, data that cannot be restored, or a service other people depend on | The tier 2 process, plus one test for each risk that the threat model ranks High, plus one adversarial review by a reviewer on another model than the owner's. The pstack `multi-phase-plan` playbook only when the operator asks for it by name. |

- Give each PR its own tier. A program of tier 2 features can hold a
  tier 1 rename and one tier 3 publish step.
- Keep the scope to what the operator asked for. Work found on the way (a
  defect in a dependency, publishing a dependency, a cleanup) is a separate
  item: file it, and do not fold it into the program.
- A conditional permission from the operator ("if we need to, you may X")
  is not scope. Take the path that does not need X, or ask.
- Before the operator's go, state the size: the tier of each PR, the number
  of PRs, owners and their models, verifier agents per PR, and the wall time
  you expect. When you expect more than two hours, also state the smallest
  version that meets the goal and its time.
- The pstack `multi-phase-plan` playbook and its `check-plan` script fix ten
  live lanes and a perf block for every PR. Use them only when the operator
  asks for the playbook by name. For every tier, write the short plan above
  and do not run `check-plan`.
- pstack's fan-out skills (`architect`, `arena`, `interrogate`, `swarm`, and the panels of `how` and `why`) are
  for when the operator asks for one by name. For every tier, design and build in the session itself. The
  tier 3 adversarial review is one reviewer, not a panel. One feature on pstack's full path starts ten or more agents, and each one rereads its context.

### Tests follow risk

A test costs time to write, to run and to keep. Spend tests where a mistake costs most. The operator sets the
budget. An agent does not raise it.

- **Name the risks first.** The plan for a PR lists what can go wrong that costs money, data, trust or a person.
  Take the risks from the project's threat model or risk list, and rank them by likelihood times cost. A PR with
  no such risk says `Risks: none`.
- **Test these.** The domain rules. The happy path of each feature. One failure case for each risk that ranks
  high. Each invariant (for example "one press sends one mail") at the layer where it can break. Use the lowest
  layer that can show the behaviour: a unit test, then a test of one feature on its real store, then a journey.
- **Do not test these, unless a named risk needs it.** Each row, key, fault, state or input of a kind: one table
  test or one property test samples the kind. A behaviour that another test, the type system or the database
  already holds. A fake, a test helper, a build script or a deploy script: run it once and show the run.
- **Journeys are few.** A product has one end-to-end journey for each main user task, on its happy path. An edge
  case goes to a lower layer, or it has no test.
- **The budget is in lines.** A PR adds no more test lines than source lines. Fakes and fixtures count as test
  lines. Generated code counts as neither. A PR that needs more stops and says why, and the operator decides. The
  report gives both counts.
- **A fix.** A fix for a defect that a user hit, or for a risk that ranks high, carries one test that fails before
  the fix and passes after it. That one test is outside the line budget. Any other fix shows the run that failed
  before and passes after, and needs no new test.
- **Keep a test** only if it fails when the behaviour breaks and passes when only the internals change.

### Never delete or weaken a test to get green

Fix the code or the test. Do not delete a test, skip it, mark it `xfail`, empty its file or comment out an
assert so that a check passes. A prune is the one exception: it applies "Tests follow risk" to the tests that
exist, in a reviewed pull request whose text lists what goes, so that the operator can reverse any.

## Build work

- Code that parses input from a stranger (mail, a file from outside, a request with no sign-in) gets one table
  test of bad input for each parser: a few rows, for the kinds that the threat model ranks high. Input from the
  signed-in operator needs only the test of its validation. Do not test each key, and do not run a fuzz campaign.
- A fix brief fixes the cause, not the one input. The fixer runs the tests that cover the code it changed.
- A project built in milestones states its threat model and severity scale
  (impact times likelihood) in its architecture doc, and gives each
  milestone one review and one fix round. After that, only a high finding
  reopens it. Put other findings in issues for the next planned work.
- Stacked PRs restack the way pstack's merge-safety reference says: push the
  agent's own branch with a lease that names the branch and the literal SHA
  it replaces (`--force-with-lease=refs/heads/<branch>:<sha>`). The git hook
  (`hooks/block-dangerous-git.sh`) allows only that form, never on the
  default branch, and refuses a lease written with shell variables. When a
  restack is refused or not worth it, merge the parent branch in and push
  normally.
- Test depth matches the stage. During a build, run the tests that cover
  the change. Run the full suites, the long property runs and the
  real-app checks once, before the report. Never repeat a full run
  unless code changed since the last one.
