Troubleshooting
“Denied by CC” — what now?
Section titled ““Denied by CC” — what now?”Read the block, not just the verdict. A denial for a zone reads like this (packages/contracts/src/messages.ts):
Write on apps/api/migrations/0021_orders.sql was denied — zone "schema" (Database schema) is closed for writing. Owner: paulo@commitcycle.com.
Do not look for another way to make this change. Not Bash, not a script, not hardcoding the result you would have gotten.Working around this is a worse outcome than not making the change at all, because it hides the boundary you hit.
You have two good options: 1. Ask for access: cycle request-access CC-42 --zone schema --mode write --reason "..." --alternative "..." Say what you need it for and what you will do if the answer is no. 2. Carry on with the rest of the task and report this block in your summary.
Either way this block is on the record.- The zone, and whether reading or writing was refused — what boundary you hit.
- The owner — a person, not a policy. They can open it.
- The way forward, ready to run — the
cycle request-accessline for this task and this zone. One approval, thencycle syncon the task’s branch to bring the widened grant down, and the write lands.--alternativeis mandatory — the CLI refuses the ask without it — because the approver deserves to know what happens on “no”. In a repository with no board, the message names the owner to ask instead, because there is no command that could reach one.
What your task declared is the other half of the answer: cycle status lists what the grant opens, and the mismatch is usually that the task was scoped without this zone.
What not to do is copy the file somewhere unprotected, edit it there and move it back. The closing gate compares the whole diff against declared zones, so the workaround surfaces at close — later, with less context, and looking worse than the request would have.
“Denied” on a file nothing protects
Section titled ““Denied” on a file nothing protects”The refusal names no zone, and the path is one the zone map never mentions:
Write on notes/plan.md was denied — no task is active on this branch — start one so the change is on the record.
Nothing about this path is protected. The problem is that there is no task on this branch,so the change would have nowhere to be recorded. Ask for a task to be started, or say what youwere about to change and why, and stop here.With no task bound to the branch, nothing is writable — not only the protected paths. A zone map decides which task may write where; the task itself is what makes a write recordable at all, and a change with nowhere to be recorded is the one thing the product does not allow. This is the same rule on a branch with no task, on main, and on a branch whose grant has expired.
The way out is the ordinary one: cycle start "<what you are about to do>" … to file and scope it, or cycle start CC-42 to adopt a task the board already holds. If the work genuinely is not a task — a scratch file, a note to yourself, an export you are about to throw away — an agent cannot simply write it outside the repository: the hook refuses its file tools there too. On the trunk the editor’s own folders are the exception — in Claude Code, the session scratchpad and the project’s memory folder (CC-1348) — and the refusal names them. A person editing by hand is not judged by the hook at all.
It catches people twice in particular: just after a hand-in, because cycle submit revokes the grant and clears the block, so the branch you are standing on has no task any more; and eight hours in, when the grant’s TTL runs out mid-session. Both read as the tool breaking and are the tool working.
The two have different ways out, and the second one used not to have any.
“The grant expired” — eight hours in, mid-task
Section titled ““The grant expired” — eight hours in, mid-task”cycle status and cycle doctor both name it:
The grant expired at 2026-09-06T17:12:04.881Z — that is why writes stopped.Run `cycle renew`: it asks the board for the same grant again — the same zones, a newexpiry — and can never widen it.Run cycle renew. It re-issues the grant this task already holds: the same zones, the same modes, the same branch, a new expiry. It cannot widen anything — the board re-issues what the grant carried, not what the task now declares — and a high-risk zone whose approval was withdrawn or timed out is refused, exactly as it would be at the gate. Every renewal is recorded with your name on it and appears in the task’s audit record.
It works on a board with one member, where there is nobody to ask (D-33). With more people on the board it says so and names the path that is theirs: cycle pause <task> --reason "…" hands the grant back, and cycle start <task> re-earns it at the gate.
Do not reach for cycle start here. It refuses to run with uncommitted changes — which is to say it refuses in exactly the state eight hours of work produces — and the refusal it prints is about the working tree or the state machine, not about the expiry you were actually trying to fix.