Skip to content

The closing gate

Done is not a column you drag a card into. In Review → Done is the quality gate, and it checks two things:

The whole diff, compared against the task’s Affected zones — every touched path either falls in a zone declared for write, in unprotected space, or in a generated: exemption. A renamed file counts at its old path as well as its new one, because moving a file out of a zone changes that zone as much as moving one in (CC-1382). Anything else fails the close, with the surplus named, and a change inside a zone the task declared only for read fails it the same way (CC-1300). The board’s close also refuses a declared high risk write zone that never had its owner’s approval for this task. In memory mode no zone is judged, so the comparison reports what the work touched and refuses nothing for it. Layer 3 runs the same comparison on the pull request where it runs at all: where the board answers and merges wait for green, a laptop that lied about its hook stops mattering by merge time. Today it runs only in CommitCycle’s own CI, and its limits are on that page.

The inventory comes from observation, not memory: the hook logs every mutation as it happens, and the close cross-checks that log against the git diff. Disagreement between the two is itself a finding.

Each task carries a quality gate chosen at scoping — none, visual review, API contract check, regression suite, or QA sign-off. The gate demands its evidence — a URL, an attached capture, a green run — and CC never executes anything to get it. Demanding evidence and checking it keeps the product out of your execution path; anything that runs on your behalf would be blast radius added, not removed.

Every close writes a markdown record: what was declared, what was touched, what evidence closed it, who approved what, and — the section that makes the records worth reading — the exceptions: every block, closing warning and override, placed above the narrative. It also says when something was not observed: a file list the closer reported, rather than one taken from git, is labelled as reported. The record is legible without the tool, which is the point: it’s the artifact you hand a skeptical CTO, not a database row you export for them.

Terminal window
cycle verify # the checks, without closing
cycle verify --close # close it, and write the audit record

Two flags matter at the edges. --evidence <url|path> attaches what the quality gate asked for. --override "reason" closes when the checks cannot pass for a reason a person will put their name on — it records the bypass rather than hiding it, which is the only version of an override worth having. An override does not answer the evidence check, because a signature cannot stand in for the evidence itself. Run cycle verify --close again with --evidence and a URL, or a path committed in this repository.

There is also --from-history, for work that merged before it closed. Such work cannot be verified from its branch — the merge base is the tip, so the diff is empty — so the manifest is rebuilt from the task’s own commits in the trunk, and labelled as such so no record mistakes it for a branch diff. It takes several task ids, and checks and closes each on its own (CC-1383).

The other doors run the same gate. Over the connector, cc_close takes the file list the agent reports, and the record says it was reported. In the console, Review and close is a signed-in reviewer’s act: it refuses while a pull request is still open, and it needs a merge GitHub confirmed — from the signed webhook, or by the board asking GitHub at close — rather than one a client reported (CC-1330, CC-1346). Without one it sends the reviewer to cycle verify --close, which checks the branch is in the trunk. For a task handed in before the board recorded files, it reads the diff from the task’s verified pull requests (CC-1352).