Skip to content

v0.6.0

Latest

Choose a tag to compare

@peckda peckda released this 15 Oct 14:46

Coco verifies its own work.

Twenty-two findings from two monitored /coco:loop runs turned out to be one defect wearing different clothes: the workflow made a claim and never checked it. It ran close and never read it back. It read max_review_iterations and never counted. Its import checklist asserted every task had an issue_key when none did. Its reviewer reported measurements it hadn't taken. Its own fixes shipped correct, merged, and inert.

Every one was found by a human watching — which is precisely the condition coco exists to remove. A workflow that cannot check its own work isn't autonomous; it's unsupervised, and the difference only shows up when nobody is looking.

So: every claim — about state, evidence, budget or delivery — is verified at the point of claiming, and the loop stops when it cannot verify.

Fixes

State. close, update and epic-close re-read after writing and exit non-zero if the record isn't what was written. _coco_write_record refuses to write to an unparseable file and checks its rewrite before the mv — one malformed line previously made the update-vs-append probe read as "record absent", appended a duplicate, printed success and exited 0. epic-close refuses over unfinished tasks (--force overrides): an epic closed over an in_progress task makes it unreachable, since ready selects only pending.

Recovery. New coco-tracker reconcile [--fix] finds tasks left in_progress by an interrupted run, epics closed over unfinished work, and orphaned tasks. The Pre-Loop Gate runs it, so a loop killed by a usage limit, crash or Ctrl-C is recoverable instead of permanently stuck reporting "all remaining tasks are blocked" with nothing blocked.

Bounds. New coco-tracker round <key> --bump counts review rounds in .coco/state/. max_review_iterations was read from config and never compared to anything, because the count lived in the model's head. A new Review Exhausted exit condition stops when a PR can't converge, rather than logging a warning and carrying on.

One stopping rule replaces two opposite bugs: stop when continuing cannot change the outcome without a human, and never otherwise. That covers both stopping to narrate ("Holding for the review verdict" — every clause true, still wrong, because the reviewer returns to the loop) and failing to stop when a PR had burned its budget.

Evidence. Every code-reviewer finding states how it's known — observed with the command run, or inferred. A reviewer may not report output from a command it didn't run. Verification harnesses must prove themselves with a control (a null change must report SURVIVED) and a clean baseline. Two new TestValue triggers, including a test that derives its expected value by reimplementing the behaviour under test rather than calling it.

Budgets. ## Test Strategy carries an Expected count per FR, a Ceiling, and a Feature-review allowance. Constitution principles carry a Bounds line beside MUST and Rationale — without it a principle can require and never limit, so principles accumulate as ratchets.

Speed. The loop starts the next non-overlapping task while a review runs, instead of blocking 7–19 minutes per review. Four preconditions, including a clean reconcile — pipelining over unverified state corrupts twice as fast. Re-reviews are scoped to the incremental diff.

Corrections to 0.5.0

  • pause_on_error: false was documented as skipping a failed task. It also stranded it, because nothing reset in_progress. Fixed by reconcile.
  • "The orchestrator cannot bound its wait on a dispatched agent; markdown cannot express a timeout" was wrong. TaskOutput takes block and timeout, and a timeout returns status: running plus partial output. Corrected everywhere, with an explicit instruction not to add an abandon-deadline.

What is measured, and what is not

The test-budget ceiling has a control: unbudgeted produced 1,726 test lines against 388 of source with a core mechanic untested; a stated ceiling produced 44 against 40 with the overage self-reported. Treat that as known.

The speed claim does not. It has arithmetic but no run against its 123-minute baseline, and CLAUDE.md labels it a hypothesis until one exists.

New config

issue_tracker.per_task_issues, pr.review.tiers, and a path-glob map form for testing.test_command. All default to previous behaviour.

Tests

84 tracker (was 46), 9 hooks, 26 setup-config (was 0). Every mechanical change is unit-tested and mutation-tested.

Upgrade

/plugin

Then update coco, and confirm the path contains /0.6.0/:

which coco-tracker

Then in each existing project:

/coco:setup migrate

.coco/config.yaml is copied once at setup and never re-read, so the new keys and defaults reach an existing project only through migrate — which now commits the change, or says plainly that it hasn't.

Full Changelog: v0.5.0...v0.6.0