Skip to content

Canonical User Todo completion updates

A promoted local Goal routes todo update --status done for User Todos through the TypeScript terminal transaction. File and SQLite use the same semantic owner; PostgreSQL exercises it through the service-owned provider. This does not select a default provider or promote an existing Goal.

loopx todo update --goal-id example --todo-id todo_observation \
  --agent-id agent-a --status done --note 'Observed outcome verified' \
  --no-follow-up --update-operation-id observation-completion

Use the same operation id and intent after a lost response. A new annotation uses a new id (omitting the id generates one). --dry-run validates and previews without running declared validation, writing a receipt, or delivering a display. Agent completion continues to require loopx todo complete.

One edit, one terminal transaction

The update decoder, authoring planner and record materializer are shared with ordinary edits. The terminal owner checks the original Todo's completion authority and the edited record's update authority; clearing a claim or binding cannot turn an update-only grant into a completion grant. Existing lease ownership/requirement restrictions remain: an annotation cannot rewrite an execution grant. Supplied lease proof must identify a current execution; expired explicit proof does not enable automatic reacquisition.

The transaction checks linked successors before issuing validation effects. Self-links and missing successors fail without running a caller command. This ordering also applies to the existing complete/supersede transaction. Completion does not invent a decision outcome: use the explicit decision workflow when an approval, rejection or cancellation must be recorded.

A declared validation command runs in the host after TS admission. The resumed update binds the issued provider revision, retains the registry source witness, and refreshes the clock. Any intervening provider commit rejects that resume, even an unrelated Todo edit. Retry re-reads and revalidates; validation itself may have external effects. Registry witnessing is optimistic, not an atomic cross-resource authorization transaction or an executor-held effect fence.

Todo fields, completion state, lease release, projection intent and the business receipt commit together. Release preserves the existing lease version and epoch. Markdown is a display projection and is not required to admit a completion. Private validation declarations remain in their private store; they are neither imported from an untrusted display nor embedded in public completion receipts.

Recovery and callers

  • Historical replay precedes current source admission and returns the original business receipt. Changed edit intent with the same operation id is rejected.
  • An already completed User Todo can receive a new completion-update annotation without rerunning validation or changing its completion timestamp. This does not reopen the Todo or grant further execution authority.
  • The existing Chat User-completion action uses its reviewed canonical revision and proposal operation id. Failed validation produces a failed proposal with no success receipt. Pending display delivery is retryable; a retry recovers the canonical operation before checking present-day freshness, then projects the current head. Agent completion keeps its existing dedicated route.
  • CLI and Python use the same public facade. No frontend layout, action name, status selector or provider setting is added. The shared typed review plan now exposes the original-operation retry for canonical User completion too. The existing completion button and failed-proposal retry interaction remain the user entry points.

The same synthetic pending-completion proposal on the packaged desktop surface: before: omitted from recoverable proposals, after: the original-operation retry. These images use the repository's synthetic workspace fixture, not a live Goal. No responsive layout changes are involved.

The local update transport uses request v3 for the completion envelope. v0–v2 reject that envelope instead of silently accepting only part of the intent. Their ordinary update behavior and receipt encoding remain unchanged. The provider-neutral terminal receipt includes the User edit identity only for this new operation family; existing complete/supersede receipt identities remain valid.

Migration boundary

Unpromoted Goals retain their existing Python Markdown/event adapters. The shared host validation executor and failure projection replace duplicated transport plumbing; the TS edit decoder/materializer is no longer owned only by the ordinary update transaction. Permanent rendering and private command execution still have real Python callers and are not retirement candidates.

This closes the User completion-update caller within TS T1/T2 and local-default L2. It does not close every Monitor/event caller, executor-held effect fencing, D1 consumer recovery, SQLite D2 capacity/elapsed soak, or D3 whole-Goal cutover. See the local-default program.

Rollback the code before using the new caller, or finish/retry its outstanding projection delivery before downgrading. Older binaries reject request v3 and cannot recover this operation through the old update route. Existing durable Todo/lease records, historical receipts and permanent import/export obligations are not removed by this change; never revive stale Markdown as authority.