Skip to content

The .zones directory

A repository that has just been set up has this, and nothing else:

.zones/
zones.yml the zone map — what is protected, why, and who owns it
board.json which board this repository answers to
AGENTS.md the block your agent reads (see below)

That is complete. Everything else in this page appears on its own, the first time you do the thing that produces it. If you have compared your .zones/ against a repository that has been running for months and concluded that yours is missing something, it is not — you have just not closed a task yet.

The directories are consequences, not prerequisites. Creating them empty at setup would be the documentation project this product exists to argue against, and an empty audit/ says nothing that its absence does not say better.

Path Created by The first time you…
zones.yml cycle init, or cc_setup over the connector set the repository up
board.json the same set the repository up
AGENTS.md the same set the repository up
tasks/ cycle start, or cc_intake / cc_scope over the connector file or start a task
state/grants/ cycle sync, or cc_start over the connector hold a grant
audit/ cycle verify --close, or cc_close over the connector close a task
playbooks/ cycle seed / cycle feed, or cc_close’s learned answer keep what a close taught
decisions/ cycle challenge accept or reject a proposal
state/events/ the hook, and only the hook have a write observed

† needs the CLI installed — the challenge flow has no connector form yet. ‡ needs the hook, and no server can substitute for it. Everything else in this table is a decision — the board makes it, and either side can write it down. An event is an observation, and an observation without a witness is an invention. Decisions travel as files; observations need a witness.

Written at birth, so a task never exists on the board without a record beside the code. It holds what the task declared: its goal, its non-goals, the zones it asked for, and the state changes it went through.

cycle start writes it when it files the task. Over the connector, cc_intake hands the same file back the moment the task is filed — still in Triage — and cc_scope, cc_start, cc_submit and cc_close each return it regenerated, so the record on disk follows the board. The connector’s version says there is no branch and no grant until the gate issues them, because on that path there cannot be.

Committed, deliberately. The record travels with the branch it describes.

Grants and event logs. cycle init adds .zones/state/ to your .gitignore, and it stays out for two reasons: a grant is scoped to one machine and one branch, and the event log is a record of what happened here rather than of what the code is.

The two halves are different animals. A grant is a decision — the gate issues it, and it reaches this directory through cycle sync, or as a file cc_start hands back over the connector. An event is an observation: the hook writes events/, only the hook ever can, and its shape is not a contract.

The record the closing gate produces — through cycle verify --close, or handed back as a file by cc_close over the connector: what the task declared against what the diff touched, plus whatever evidence the quality gate asked for. Committed, because it is the answer to “who changed this, under what permission, and who agreed” long after everyone has forgotten.

A connector close is on the honour system, and the record shows it rather than saying it: base and head read reported instead of commit SHAs, and mutations_observed is zero, because no hook was running and nothing independent saw the writes. The sentence spelling that out is in cc_close’s reply; the record carries the evidence of it.

If this directory is empty on a repository with closed tasks, something is wrong — see the closing gate.

One file per declared topic — a taxonomy that grows by the birth rule, plus always-on playbooks pointed at from AGENTS.md that load whatever a task declares — growing by append and never by rewrite. cycle seed drafts them from your codebase with citations; cycle feed adds a bullet after a close — and over the connector, cc_close asks what the work taught and hands back the same append for your agent to write. A topic with nothing to cite is not a topic and gets no file, and a lesson with a citation is cited content, which is how a missing playbook may be born from one.

You will end up with everything except two things: zones.yml, board.json, AGENTS.md, a growing tasks/, grants under state/grants/ while work runs, an audit/ file per close, and playbooks/ whenever a close taught something. That is not a partial installation — it is the whole record, kept on the honour system.

The two absences are the honest ones. decisions/ waits for the challenge flow to reach the connector. And state/events/ never appears, because it is the hook watching writes happen — the one file no board can hand you. A close on this path reports its file list rather than proving it, and installing the hook is what turns reported into observed.

It is the one file CommitCycle does not own.

.zones/ is ours — our tasks, our grants, our record. Nothing else reads it and nothing else has to. AGENTS.md is the opposite: it belongs to your agent, and Claude Code, Codex and Cursor all look for it at the repository root. Inside .zones/ nobody would ever open it, and Layer 1 would quietly stop existing.

That is also why it is the only file with <!-- cc:begin --> and <!-- cc:end --> markers around our part. Inside .zones/ we can rewrite whatever we like. In AGENTS.md we are a guest: everything between the markers is regenerated on every sync, and every byte outside them is yours and is never touched. Write your own house rules above or below the block and they will survive.

What you will see in CommitCycle’s own repository, and should not copy

Section titled “What you will see in CommitCycle’s own repository, and should not copy”

CC is built under CC, so its .zones/ is the oldest one that exists — and it carries three directories that are not part of the product:

  • evidence/ — files attached by hand at closes whose quality gate asked for proof. Nothing creates it; the gate accepts evidence as a URL or a path, and these happen to be paths.
  • exceptions/ — written arguments for cases where a rule did not fit, kept so the reasoning survives the decision. A convention of this repository, not a feature.
  • salvage/ — residue of one recovery operation, kept for history.

They are all defensible where they are and none of them is something your repository is missing. Anyone imitating this layout would be copying our history and calling it architecture.

  • Zones — what belongs in a zone map
  • AGENTS.md — what the block says, and what it deliberately does not claim
  • The audit record — what a close writes