Problem
A controller-declared Todo completion validator is immutable after Todo creation. When the referenced test file is later moved, Todo completion runs the stale argv, returns pytest exit code 4, and quota settlement remains blocked. The CLI accepts validation-command fields on todo add only, so the agent has no typed CAS-safe repair path and must not edit Goal state by hand.
Reproduction
- Add an advancement Todo with a completion validation argv pointing to a repository test file.
- Move that test file while keeping the Todo open.
- Run todo complete from a correct independent worktree.
- Observe a committed validation settlement receipt with passed=false / exit_code=4 and validation_blocked_completion=true.
- Run quota spend-slot for the bound Turn and observe that spend is rejected until the Todo completes.
The actual replacement test passes; only the persisted validator path is stale.
Expected contract
Provide a typed update/migration path for an open Todo completion validator, with operation id, expected provider revision, declaration digest replacement, audit history, and readback. The TypeScript authority/state-machine boundary should own validation of the transition; Python CLI remains an adapter. Existing completion receipts must remain immutable, and changing the validator after a validation attempt must require an explicit new declaration revision rather than silently reinterpreting the old receipt.
Acceptance
- An authorized open Todo can replace a stale validator using CAS/idempotency semantics.
- Old and new declaration digests and the actor are auditable.
- A stale historical validation receipt cannot satisfy the replacement declaration.
- todo complete executes only the current declared validator and quota settlement accepts the matching durable receipt.
- File-authority and promoted-provider conformance tests cover the transition.
- CLI/managed Turn and dashboard projection expose the same typed state; no second source of truth is introduced.
Problem
A controller-declared Todo completion validator is immutable after Todo creation. When the referenced test file is later moved, Todo completion runs the stale argv, returns pytest exit code 4, and quota settlement remains blocked. The CLI accepts validation-command fields on todo add only, so the agent has no typed CAS-safe repair path and must not edit Goal state by hand.
Reproduction
The actual replacement test passes; only the persisted validator path is stale.
Expected contract
Provide a typed update/migration path for an open Todo completion validator, with operation id, expected provider revision, declaration digest replacement, audit history, and readback. The TypeScript authority/state-machine boundary should own validation of the transition; Python CLI remains an adapter. Existing completion receipts must remain immutable, and changing the validator after a validation attempt must require an explicit new declaration revision rather than silently reinterpreting the old receipt.
Acceptance