Reference
Completion policy and work registers
Role preflight, actionable work and the distinction between a source repair and a qualified result.
#Completion enforcement
block-supervisor-stop refuses completion for a session whose local
Oko role is supervisor. It reads ~/.oko/session-roles.json
inside the native runtime before starting any judge hook: no subprocess, database,
network or model request. The refusal directs the supervisor to
oko sessions agents, confirmation dialogs, stopped executors and
their next open assignments. Only the operator clearing that role with
oko sessions role clear SESSION releases this role guard.
Other enabled completion guards still apply after it passes.
Malformed or unreadable roles and absent session identity refuse with the
exact operation and cause; they are not interpreted as an unassigned session.
An absent register means no role has ever been recorded, as in Oko's contract.
Unknown record fields are ignored. Enable it with
tama enforcement only EXISTING_HOOK_IDS block-supervisor-stop,
preserving every id currently shown by tama enforcement status --json.
The Desktop Hooks inspector and session refusal records expose the same hook
and reason; Oko Desktop's Agent sessions Role menu manages the local role.
When the effective selection enables block-supervisor-stop,
OMP reuses a stop assessment only while the local role document has the same
content digest. An external role clear or assignment invalidates both an old
refusal and an old pass, even if the assistant candidate and transcript identity
are unchanged. An unreadable register cancels the retained assessment and
refuses with its path and actual read cause. For an executor, the identity also
includes the local defect register, blocker register and prepared task snapshot:
file identity, size, modification/change timestamps and mode. An assigned
defect or changed task reading therefore invalidates the retained decision
without another tool call or a guessed expiry. These are local metadata reads,
not scans of ledger contents. The native runtime remains the authority that
interprets the role and work; metadata alone never grants completion.
The real tests/hooks-running/stop-review/journey.mjs journey includes
roles.mjs: genuine Oko role set, clear and reassignment against an
isolated home, persisted role checks, and actual native Tama dispatch behind the
same assessment cache. Declare TAMA_TEST_OKO_BIN alongside the
candidate Tama executable and source revision; the run retains both binary
digests and the real command results. A directory substituted for the isolated
role file checks causal read refusal and cancellation. An executor case creates
a genuine isolated Oko defect after assessment and requires a fresh native
decision naming that assignment despite an unchanged assistant candidate.
For an executor, the same local preflight selects an open assigned
defect first, then open defects of products named by its recorded assignments.
It reads Oko's atomic defect and blocker registers without running a process:
OKO_DEFECT_REGISTER and OKO_BLOCKER_REGISTER, or
~/Library/Application Support/Oko/defects.json and
blockers.json. The refusal names oko defects show ID
and the recorded owner for coordination. A valid open blocker naming that exact
defect, by full or short id at the beginning of its blocks field,
bare or in Oko's reference form defect-<id> (as
oko blockers record --blocks defect-<id> keeps it),
holds only that item; a repository-wide publication wait does not hide the queue.
A repair claim also holds the item it names: a repair claim in Oko's
claims register (OKO_CLAIM_REGISTER, or claims.json
beside the defect register) whose subject is that defect's full or short id and
whose newest verdict of each kind at the claim's own revision is not
broken. What such an item waits on is a verdict its author cannot
give, a test on a build or an adversarial reviewer on another model, so the
refusal names it among the waits (waits on the verification of repair
claim ID at REVISION) and moves to the next item; a broken verdict
returns the item to the queue. The retained stop assessment is renewed by a
change of the defect or blocker register or of the task reading; recording a
claim alone does not renew it until one of those changes.
Malformed or unreadable registers refuse with their actual path and cause.
Executor task settlement runs in the background
before_provider_request dispatch, before the text gate, only when
the local defect selection cannot already name actionable work. A known actionable
defect keeps Stop refused without reading the remote task ledger or manufacturing
an empty ready snapshot. Once no such defect remains, preparation reads
Oko's authoritative session ledger, including relations, rather than Oko's
private pre-settlement cache. The result is atomically retained under
TAMA_SESSION_CONTROL_ROOT/executor-work (the normal session-control
state directory when no override is set). Stop reads that local observation;
it starts neither Oko nor a reviewer. After assigned and product defects, the
refusal names the next own task through oko tasks show ID.
An exact-item blocker holds that task only. Submitted tasks already awaiting
review retain the existing completion reader's classification.
The OMP adapter supplies tama_work_generation, renewed on
activation, input and tool completion. Missing, unfinished, failed or
different-generation observations refuse; a late reader cannot overwrite a
newer generation. A failed generation is not automatically retried. A new work
boundary initiates a new reading. This is an observation of the ledger at that
boundary, not a live subscription to other sessions' remote task mutations.
Native callers must prepare the same generation with
tama run-hook before_provider_request omp before
tama run-hook stop omp. Both receive the session and generation in
their JSON input. The Desktop session refusal record uses the same reason.
The real executor defect journey uses isolated Oko role, defect and blocker mutations and requires actual external-failure evidence plus the real blocker reviewer. With actionable defects it also removes access to the Oko executable, requires preparation to avoid task settlement, confirms no task snapshot was created and requires Stop to name the same persisted defect.
The blocker-form journey (a_blocker_holds_its_item_whichever_way_it_names_the_defect
in tests/supervisor-stop/executor/blocked.rs, run with the same --ignored
command) writes the blocker register in the shape Oko keeps it with one open wait for the owned
defect, named by its whole id, as defect-<id> and by its short id in turn, and
requires each Stop to name the other open defect and not the blocked one.
The claim journey (a_claimed_repair_holds_the_owned_item_until_a_verdict_breaks_it
in tests/supervisor-stop/executor.rs, run with cargo test -p tama-cli
--test supervisor_stop_roles -- --ignored and the same declarations) records a real
repair claim on the executor's owned defect through Oko in isolated registers, requires
Stop to name the other product defect and the claim among the waits, then records a
broken test verdict and requires Stop to name the owned defect again.
The registered tests/supervisor-stop/tasks.rs journey reads a
real executor's Oko ledger without mutating its tasks or role. Declare
TAMA_TEST_SOURCE_REVISION, TAMA_TEST_OKO_BIN,
TAMA_TEST_EXECUTOR_SESSION and TAMA_TEST_EXECUTOR_TASK,
then run cargo test -p tama-cli --test supervisor_stop_roles
settled_tasks_refuse_locally_and_failed_or_superseded_readings_never_pass -- --ignored.
It isolates the prepared state, records both binary digests and every command,
prepares through actual Oko, and proves local refusal with the Oko executable
absent. It also covers different-generation refusal, genuine executable failure
and a fresh-generation recovery.
Every supported harness completion binding reaches the canonical
stop event. OMP's blocking boundary is session_stop;
agent_end and turn_end are notification-only, not
additional cancellation APIs. This does not claim control over operator
interruption, process exit, or OMP subagents, which do not emit
session_stop. The real supervisor_stop_roles journey
uses Oko role set/clear and the built runtime, checks persisted role changes,
supervisor refusal, clearing, unknown metadata and unreadable state.
Prompt text does not execute a Stop rule. Enabled hook commands do.
block-stop-with-open-work reconstructs the successful tracker state
and blocks pending or in-progress items. Once that plan is clear, including
when every local item is marked blocked, executor roles use the same prepared
generation and item selection described above. Other sessions read the
authoritative Oko ledger for the native OMP session id. An absent local plan
does not skip the applicable reading; an unavailable ledger refuses Stop with
its actual error. For sessions without a recorded executor role,
when the machine has no Oko CLI (neither TAMA_OKO_CLI nor oko on
PATH is an executable), the session's own registers are the only task
registers: Stop is refused on the tracker's pending or in-progress items and, once
they are clear, on the task-scope declaration while it still names a task or a
defect, with BLOCKED: this machine has no Oko CLI, and the session's own
declaration still names open work: <entry> — "<the operator's words>"
and the way out, tama task scope clear --session <ID>; a cleared
declaration lets the next Stop through, and a declaration that cannot be read
refuses as an unreadable ledger (cannot confirm completion …), never
as an empty one. An installed Oko that cannot be read still refuses. The other
gates that read Oko take the same alternative on such a machine:
block-text-outside-tool-calls lets the final message through,
block-one-off-repairs admits a build, compile or test because no
register holds an item without a repair, and tama task scope set
accepts the --task or --defect identifier the session
names as the entry, with the repositories it names as the scope and nothing
written back. require-task-scope then refuses with that one command
instead of the Oko commands it names when Oko is installed.
check-open-items-with-model uses the same ledger qualification
when enabled. Neither guard asks a second model to reinterpret open tasks as
permission to stop.
block-text-outside-tool-calls runs before model requests and on Stop.
The OMP adapter uses a completed gate answer from the current session and work
generation and refreshes it in the background; a late answer from an older
generation cannot authorize prose. The ledger read does not consume the
harness's provider-handler budget.
For supported OpenAI function-tool payloads, an open-work refusal sets
tool_choice: "required"; this shape is also forced before the first answer.
Anthropic requests and unsupported or absent tool shapes are not forced: they are
sent unchanged with the limitation on stderr. Their Stop gate still checks completion,
but it runs after text may already have streamed and cannot retract that text.
Provider acceptance, prevention of streamed prose and refusal of completion are separate outcomes;
none is established merely by a published source revision. See the adapter contract and its limitations.
For sessions outside the executor role policy above, any executable task
still marked not done in any session blocks completion,
and every defect that records no fixing revision blocks it too: of every product, unless the
operator limited the session to some products by confirming a task contract scoped to them
(contract.terms.scope with contract.terms.confirmedAt, written with
oko tasks state --scope … --confirm by the operator); then only of those products,
and the refusal counts the other products' open work as outside the session's scope. A scope a
session wrote into its own contract limits nothing: the session answers for every product's open
work. An entry in
oko blockers, a blocked verdict, a judge outage after evidence, or a
wait on other open work does not stand an item aside: only Oko recording a task done or
withdrawn, or a defect fixed, removes it. A task Oko relates as duplicate-of
another is counted once, as the original.
The refusal counts the open work instead of copying it, so its size does not grow with the
registers: it says how many open tasks and defects Oko holds and how many carry no pushed repair,
lists this session's own items (its open tasks, and the open defects Oko records it as owning), names
the one item to take now (the session's own item with no repair first, else the first item with no
repair, else the batch build once every item carries one), and names the commands that print the
rest: oko tasks owed, oko defects list --unrepaired,
oko defects list --open --owner SESSION_ID, and oko tasks show ID or
oko defects show ID for one item. The same summary is what
check-open-items-with-model refuses with. A session's own plan with open items is
refused with their count and the first of them; the todo tool prints the rest. Copying every open
defect and task into each refusal put tens of thousands of tokens into every refused turn, which the
session then read again on every later call. The operator's answers to the excuses agents give are
not repeated in the refusal: they reach the session at its start and after every compaction.
The real test is tests/completion/summary.rs (cargo test -p tama-cli --test
completion_summary with TAMA_COMPLETION_SESSION naming a live session that has no
executor role): it checks the count against oko defects list --open, that every owned
defect and own task is named and no other defect except the item to take now, and writes the
refusal's size beside the source revision.
When Oko's ruling register (oko rulings) holds a ruling on an item the refusal names,
the refusal quotes it word for word with its session and message number and says to follow it and
never ask the operator again or list it as a blocker or next step. The register is read as a file on
this machine (OKO_RULING_REGISTER moves it); one that cannot be read is named in the
refusal rather than left out.
block-one-off-repairs reads the same register for every build, compile and test
run, and refuses while any open item carries no repair: a task with no commit or report
recorded by oko tasks evidence, or a defect with no revision recorded by
oko defects repaired. A code repair is only proven by a build, so building waits for
every repair to exist, not for every item to close; the one build then proves them, and each
item is closed or reopened on what it shows. The refusal lists the items that still carry no
repair. A recorded revision counts as a repair only when it comes after the defect: when the
defect's found_in names a commit of the same repository, the repair must descend from
that commit and differ from it, so a fix committed before the defect was recorded still counts;
otherwise the repair must be committed after the defect's found_at time. A revision
this machine cannot resolve is counted as recorded. A build the operator consents to passes before
that. His standing Oko ruling is read first, before any open work and without asking his window, from
Oko's one admission decision: the gate runs oko admit build --product <product>
--json for each product built (without --product when the products cannot be
named), and Oko decides from the newest ruling on build, build:<product>,
no-build or no-build:<product>. Tama keeps no copy of that rule. A consent
admits the build and prints build admitted by build of <product> is allowed by the operator's
ruling <id> on <subject> (session <session> message #<n>): "<his words>"
on stderr, and the refusal tells the agent his window is never asked for a product a ruling covers. A
standing withdrawal refuses the build outright, before a session capability is read, with
block-one-off-repairs: build of <product> may not run until a later ruling of the operator
allows it: the operator's ruling <id> on no-build… "<his words>"; a later consent lifts
it. An oko that cannot answer is said on stderr and admits nothing. tama attestation
list --kind build lists the consents that stand from oko rulings constraints --json
(store oko rulings, lifetime until withdrawn); consent he gives per
conversation (SSH, a local browser, hook edits) is never read from rulings. The real journey is
tests/build-gate/standing.rs. No build is ever asked of the operator: there is no build-consent
ask, and the refusal tells the agent never to ask him through his window or an Oko ask
(tests/build-gate/consent_ask.rs). When he gives his consent in the conversation himself, the
agent records it as the Tama session capability {"tool": "build", "actions": ["<product>"]}
(or {"tool": "build"} for any product) with the lifetime he named —
single-use, expires-at or current-session — and the gate lets
a build through whose arguments name a granted product. For cargo the product is the
checkout the command builds in — the one holding its --manifest-path, else the directory
it runs in — named as that checkout's .wisent-release.json names it, else by its directory,
so a consent to build Tama admits cargo check in any crate of the Tama checkout; its
-p selections are package names and decide nothing, and a command outside any checkout or
naming two manifests establishes no product. For swift build|test|run and
stado product swift the product is named the same way from the checkout holding its
--package-path, else the directory it runs in, so a standing consent to build a product
covers its Swift package too. For stado product cargo the products are its
-p/--package selections. For stado release submit --source PATH and
stado build submit --source PATH the product is the product the checkout's
.wisent-release.json declares (the name Stado builds it under, which a checkout whose
directory name is not a product name declares), else the name of the
checkout directory PATH resolves to; a relative path such as --source . is resolved against the directory the
command runs in, and a path that names no existing directory establishes no product, so only a grant
with no product list admits it. stado release submit --build ID names no
product in its arguments, so the gate reads the product from the fleet's build record
(stado build status ID --json); a build the fleet does not hold is admitted only by a grant
with no product list. When the operator withdraws his consent, the agent runs
tama sessions capability revoke --session SESSION_ID --agent omp, and the gate refuses the next build
at once.
After producing and checking the real result,
run oko tasks verify --before-stop --session SESSION_ID.
Oko's independent Brama judge reads recorded calls and tool results as well as
the answer, then saves each verdict. A claim or tracker update cannot replace
that qualification. A later operator correction takes precedence. Answering
the same refusal in prose does not release it: every later Stop repeats the
open task identity until real work records evidence or Oko records a
qualified blocker. A recorded judge outage only replaces the verify command
with the instruction to record evidence; it does not make the task done.
Done and withdrawn tasks do not block. An unfinished task may pause only with Oko's qualified receipt: the matching task ordinal and request hash, transcript hash, actual failed call/result, independently checked permitted alternatives, cause, observed state and condition for resumption. Tama rejects a prose-only reason, unmatched receipt, missing operation or unchecked alternative. The refusal names the original task and the observations still required; a worker's claim or local “blocked” flag never grants permission to stop.
#A refusal is shown once
The core records each session's last turn ending in turn-end.<session>.json beside
its control files: when the stop was received, when it was answered and the whole decision sent. A
stop refused with exactly the refusal the previous stop of the session got is still refused, but the
harness is sent one line, BLOCKED: the same refusal as this session's previous ending, given N
times in a row, is not printed again; its full text is `decision.reason` in <path>; the
record keeps the full refusal and every time it was given (givenAtMs). A different refusal,
or the first one after a stop that passed, is given in full. block-stop-with-open-work lists
the open defects and tasks once per session (open-work-listed.<session>.json); later
refusals give their counts, the next item, and the commands that list them. A marker that cannot be
written is said on standard error and the list is given in full. Real journey
tests/stop-gate/identical_endings.rs.
#A claimed repair is still work
A repair recorded with oko defects repaired is its author's claim until something verifies
it. Once every open item carries a pushed repair, block-stop-with-open-work does not offer the
batch build: it asks Oko's work queue for the next repair claimed and not verified that this session may
take (oko work next --executor SESSION [--product P] --json, once per product of a scoped
session) and names it as the next step, verify the repair of <id> claimed at <revision>:
<reason>, the reason naming the verification it needs: the repair plan read against the
committed source, CLI, GUI, docs and test, remaining instances searched, and the item reopened with what is
missing. A queue Oko cannot answer is said in the refusal's notes with its cause. Real journey
tests/claimed-work/stop.rs.
The gates that keep a session's own conduct tied to its work — gate cycles, claimed calls, purgatory, reports, repeated looks, operator messages and the operator's stop order — are on Conduct gates.