Project note
The second operator is the test
sprintctl and actionq enforce useful execution discipline, but five current invariants rely on one operator remaining the only source of identity, authority, and audit judgment.
agent workflow / Published Jul 19, 2026 / Revised Jul 22, 2026
- Project: vuoro
On this page
No second human operator, no coordination system. Only disciplined self-management.
Within the
Vuoro project, sprintctl owns work
items, claims, dependencies, and handoffs; actionq owns queued machine actions
and their execution lifecycle. Both can arbitrate concurrent worker sessions.
That is not the same as arbitrating between people. Their current contracts
assume one human authority behind every actor string, claim token, queue worker,
and completion decision. Here N=2 means two independent human authorities,
not two agents operating for the same person. The single-operator assumption is
load-bearing in five places.
The claimant can certify completion
An active exclusive execute claim is sufficient completion authority.
item done-from-claim
checks the claim type, exclusivity, expiry, ID, and token, then moves the work
item to done and normally releases the claim. The
work_item schema
has one status and no submission, review, or acceptance relation. With one
operator, execution proof and the decision that the work is sufficient can be
the same act. At N=2, the implementer can certify their own result and the
system cannot express a reviewer disagreeing without rewriting the item state
by convention.
Names stand in for principals
Actor labels are descriptive text, not authenticated identity. The sprintctl
schema stores work-item assignee, event actor, and claim agent as
text,
while its own operating guide says actor, instance, host, and process metadata
are
advisory only.
Actionq likewise stores created_by, claimed_by, and event actor as
TEXT,
and its CLI accepts the worker and actor labels from the caller. With one
operator, a name is a useful note because the reader already knows who caused
the event. At N=2, either operator can write the other’s name, assignment
cannot grant permission, and the audit log records a claim about identity
rather than identity established by the system.
Expired ownership is disposable
Update, 2026-07-19 — partially fixed. PostgreSQL expiry now marks active claims
expiredand retains their rows. Reacquisition preserves the old row before creating its replacement. The current verification note also states the remaining boundary: SQLite expiry still deletes, and proof-bearing release still deliberately deletes an active claim. The original paragraph below records the behavior at the audited commit; it is no longer the complete PostgreSQL behavior.
Expired sprintctl claims are deleted, not retained as claim history. The
SQLite maintenance path executes
DELETE FROM claim,
and the PostgreSQL path does the
same
for rows past backend time. The documented remote-mode checklist still tells an
operator to schedule that purge. No retained claim-history model exists in
these paths: claim creation and expiry purge do not append matching lifecycle
events. With one operator, deletion is tolerable because the person
reconstructing the incident is the person who held the claim. At N=2, expiry
erases who occupied the work, when their authority lapsed, and which later
attempt replaced it; the remaining item state cannot reconstruct the deleted
lease.
Expiry disciplines the holder but does not fence them
Update, 2026-07-19 — schema landed, fencing did not. Sprintctl now stores a
lease_epoch: remote token rotation increments it, and remote reacquisition advances it across retained claim rows. The completion note says there is noexpected_epochcommand input and no downstream enforcement. The old “no epoch” statement is now historical. The invariant in this section remains: expiry still cannot fence a stale holder’s external work, and actionq still does not bind terminal transitions to its current worker.
A claim deadline is a coordination cue, not a fencing epoch. Sprintctl’s
claim ownership protocol
states that expiry cannot reject stale downstream work, and its retained direct
backend admits a stale heartbeat after another owner has claimed the item; the
opt-in remote arbiter repairs that renewal history but still makes no downstream
fencing claim. The claim schema has tokens and expiry but no epoch. Actionq is
looser: its
complete, fail, and reject transitions
check only that the action is currently claimed, not that the caller is the
current claimed_by worker, and its protocol names this limitation explicitly.
With one operator, TTL and sweep are self-discipline. At N=2, a timed-out worker
can continue external writes or win a terminal transition after reassignment,
so the newer claim does not make the older execution harmless.
Repository identity carries project authority
The repository is both storage scope and authority scope. PgStore carries a
repo_id that is
prepended to every query as a tenant discriminator,
and backend resolution derives that ID from the repository directory or marker.
Actionq’s dispatch server requires one concrete repo_id and writes it directly
into the action’s
project
field. There is no separate project, membership, or principal boundary in these
schemas. With one operator, project equals repository because both names point
to the same personal scope. At N=2, a project spanning repositories has split
authority, two projects sharing a repository cannot have separate policy, and
database access to a repository tenant is indistinguishable from permission to
operate all of it.
Five things, not one
The conceptual repair is small even if an implementation would not be: assignment names the accountable party; a claim grants temporary execution rights; an attempt records one session and its artifacts; a submission presents an attempt for judgment; acceptance is the authorized decision that the work item is complete. None implies the next. This is what a multi-operator fix would have to express, not a statement of build intent.
Verification boundary
This inventory was checked against sprintctl commit
11519c4
and actionq commit
85b72bd
on 2026-07-19. Code, current schema, tests, and protocol documents outrank the
project narrative. The claims above are limited to those two revisions. The
N=2 consequences and five-part resolution are analysis, not implemented state.
The dated updates were checked against sprintctl commit
80aaa97;
actionq remained at the audited revision.
Coordination infrastructure without a second operator is design theater. The correct output is the analysis.