workspace-rules · git:20260813.234d462 · 2026-08-13 · sha256 aea215920ba3f9b7

workspace-rules git:20260813.234d462A

Immutable. This exact content never changes and is served at /api/v1/blob/aea215920ba3f9b7.

---
name: workspace-rules
description: Give a repo its own rules at both layers, and put each rule at the cheapest layer that holds it. The told layer is what a project's workspace tells a model before it writes, so it establishes where a session starts, which repo each kind of file belongs in, how the gate is run, the facts nobody can infer, what this repo does not have, the enforced rules as an index rather than a copy, and the handful no script can count. The caught layer is what turns the build red afterwards, as a linter setting, an architecture test or a hook, derived from this repo's own evidence, proved red by name and green on an untouched tree, with the cap, the displacement clause and the dated judged-out list inside the check file. Runs after a cleanup, spring-clean or otherwise. Use when the user asks to set house rules or project conventions, write or fix a CLAUDE.md, set up a project's .claude layer, tell the next session how this project works, onboard an agent to a codebase, stop a bug class from coming back, make the linter enforce the style guide, turn a written rule into a test, add architecture tests or guardrails, prune a rule set that has sprawled, wants a codebase standard that holds, or says "house rules", "workspace rules", "قانون بذار", "قوانین پروژه", "استاندارد کد", "این قانون رو تست کن", or complains that a rule everyone agreed on keeps getting broken.
---

A repo's rules sit at two layers: what its workspace tells a model before a line exists, and what its build catches after one is written. Telling costs a line in a file the model already reads; catching costs a red build, a turn, and a check somebody maintains forever. A rule belongs at the cheapest layer that holds it, and getting that call right is most of this pass. One test governs both layers: **if you could have written the rule without opening this repo, the model already knows it and the line is a tax.**

## Which layer, and this is the judgment the rest hangs on

**Sort by what the rule hands the model.** A rule that hands it information it could not infer costs nothing to obey and holds with no gate, no judge and no repetition: what this repo does not have, which of two sources wins when they disagree, where the local default is wrong and how widely. A rule that asks it to pay a cost against the task it was given is not held by prose at any volume. Loudness buys nothing and neither does frequency: the loudest rule in this evidence, bold and mandatory and restated in a second file, sits beside a settings file granting access to the very directory it forbids touching, and the rule restated in eleven files describes the exact failure it never prevented.

**If a script could count compliance, something must count it.** That is the best-evidenced claim here and it runs one way only: every countable rule nobody counted was found violated, most often by the file that stated it. A file carrying a two hundred line target ran five hundred and fifty three. One size cap existed as three different numbers in three files, and no reader was wrong locally. A field no downstream reader consumed was blank in thirty-seven of thirty-nine notes.

**Take the capability away instead, wherever the rule can be one.** A reviewer shipped without an edit tool cannot fix the code it reviews, which no instruction achieves and no compacted context forgets. Then read the default posture, because omission from an allow list is not removal.

**Where a cost remains and the capability cannot go, put the result in front of somebody who did not produce it, reading the primary evidence and not the producer's account of it.** The one controlled comparison in this evidence is exactly that: reviews handed a summary found none of the blockers, and reviews handed the diff found twelve. A self-reported pass is worse than no check, because it launders trust downstream. Where even a second reader is too heavy, make the disclosure the artifact, so a missing declaration is itself the violation.

**What is left is a cost no script can count, and that is the handful worth writing down.** No script reads degree or intent, so none can tell a surgical cut from a rewrite. None reaches a truth living outside the repo, like what someone else's binary does with your flags after their next release. None sees how you checked, only what you wrote, so *render it and look at it* is beyond reach. And none gets any signal when the violation still works, which covers every judgment about where a thing belongs. Write those down knowing they are the weakest thing you have, and write almost nothing else twice.

## What the told layer establishes

Where a session starts, said from both ends, because a model opens wherever the shell happened to be and one repo claiming the front door is not enough. Which repo each kind of file belongs in, as a test rather than an inventory: if the code changes and this file must change in the same branch it belongs with the code, everything else belongs in the workspace, and that same test places the rules themselves. How the gate is run, as the literal commands from the named root, including the flag whose absence is a silent defect.

Then the gated rules as an index, one clause and a location each, saying outright that this document cannot fail and the check is the authority. The facts nobody could infer, each carrying the version and date it was measured against, because this class fails by going stale rather than by being ignored. **What this repo does not have, and what nobody is to build here**, which is the cheapest thing on either layer: every entry is a confident invention somebody actually committed, and the second half stops the helpful addition nothing told the model not to make. The handful no script can count. And the principles, tests among them: this project writes tests that would fail if the thing broke, a standard a model can hold rather than a coverage number to check.

## Prose is the default, and format is never the mechanism

**A pointer is not telling.** An agent handed the path to its rules and told they were authoritative produced twenty-two high findings in one review, every one a violation of a rule it had been pointed at; it skimmed once and wrote from memory. That repo's fix was to concatenate every rule file into every task file, thousands of lines of it, kept in sync by a script and a hook. The finding is right and the fix is the wrong end of it: inline what must be obeyed where the writer is already looking, cite what only has to be findable, and read a rule set that needs thousands of embedded lines as the defect rather than the argument for embedding.

Moving a rule into a rules file, a skill, an agent or a hook changes its container, not its force, and in this evidence the container almost never earned itself: what earned was removing a capability or putting a second reader on primary evidence, and those work in any container. So spend the choice on reach instead. A rules file scoped to the paths it governs, for what matters only when those files are touched. A skill for a workflow somebody invokes by name. An agent for a job worth delegating, which almost always means that second reader. A hook only for what must physically happen every session and that prose has demonstrably failed to make happen. An instruction nobody can satisfy where it is read is worse than none, because it teaches the model to discount its neighbours.

## Derive from this repo, never from a list

- **The headers of the gates that already run**, the richest source in any repo with machinery: the script carries the rule and its comment carries the why, including the scope somebody already deleted and the reason.
- **The `fix:` and revert log**, deduped because a rebase leaves the same subject twice, clustered by defect class and dated, and **the decision log**, where a decision that changed a count becomes an equality assertion on that count.
- **Prose in the tree**, every comment carrying never or always, the **suppressions**, each a rule somebody started writing and abandoned, and **your own session transcripts**, where a whole class of defect costs real time and never appears in a diff.
- **What already runs**, so you subtract rather than re-encode, and **what nothing reaches**: the directory that is production for one rule and invisible to another is where violations live, and the rules file nothing loads is where told rules die.

Each rule carries the incident that bought it: what happened, the date, and what the miss cost in this repo's own units. **No incident, no slot.** Having no mechanism disqualifies nothing, since the largest dated expensive cluster with nothing a check could catch is exactly what the told layer is for. Neither does being generic: run the generic sweep if you like, and let the tree win every tie.

## Encode it, prove it, cap it

A linter setting, a linter rule pinned to what exists, an architecture test, a hook that refuses the edit, a CI job. A detector written into a document is on neither layer: it is a comment until something runs it, and it looks exactly like enforcement. Run each over the whole tree with the code you will ship and read the count, because a handful is a ledger and hundreds means you aimed at the wrong files. **Prove the search path exists before believing an empty result**, since a scan of a directory that is not there exits clean, reads exactly like no hits, and the second reviewer inherits the same bad path.

**A rule the tree already satisfies just ships. One it breaks takes one of three shapes**: pin every current violator at its measured value with the ledger's own length capped, or set the limit at the target and warn until the slack closes, or scope the detector to added lines only, which needs no ledger. What it never does is ship as a block that has to be bypassed on day one. Block only where the detector is near enough to zero false positives on this tree, otherwise warn, and name in its header which layer does block.

**Seen red by name, and green on an untouched tree.** Break it on purpose and watch it fail by name in the real gate, once per file class it claims to cover and once per trigger that runs it, then assert the other half on unmodified HEAD. Keep the probe and date it. Every detector needs outcomes past pass and fail: could-not-run, and out-of-scope, neither of which is green. Rules land in the command that already runs, and a container build or a release script is a gate too, often the only one whose failure stops a deploy. Then assert the reverse: every gate is reachable from a committed trigger, and every rules file from something that loads it, because at both layers the dominant failure is a correct rule nothing invokes.

**Say it once, and re-derive it.** Twenty duplications were counted across this evidence and not one stayed in sync; the copy reads as authoritative and is the one that drifts. So the told layer gets exactly one gate, the cheapest there is: every path and command named in a document, a comment or an error message resolves, and correspondence beats presence or a rename passes green. Anything the filesystem or the config already knows is derived or deleted, never hand-maintained beside a staleness warning. Where a copy is unavoidable, generate it and byte-compare it.

Count the gated rules, the unit being the name printed when one fails, one `describe` title or one linter key at `error`, or the same set measures eight times larger depending on how somebody split their functions. Assert that number and add the displacement clause: a rule that wants in pushes one out. Cap the told layer the same way, on the bytes that reach the context rather than the lines, because one file here grew its line count by two thirds and its weight fourfold, and a cap counting lines never saw it. Retire a rule when its surface is gone, when another covers it, when its scope matches zero files, or when it never caught anything, and say which rules you deliberately do not check beside the ones you do. A rule found wrong is retracted where it sits, with the date.

## Red flags

- A pointer standing in for a rule: *see `rules/`* in an agent's brief, or a rules file nothing path-scopes and nothing links.
- The same rule in two files. Not redundancy, but the drift you will read and believe. A document announcing its own staleness is the same defect wearing a warning label.
- A rule whose own examples break it. Demonstrated beats stated every time, so the example teaches the violation.
- An exception whose receipt is a commit message. Make it a token on the line, in the file the check already scans.
- A detector whose coverage is set by an optional field, measuring its own opt-in rate and printing green, or a gate whose exit code dies in a pipe and reports a pass it never got.