Docs/Reference

Reference

Completion policy and work registers

Role preflight, actionable work and the distinction between a source repair and a qualified result.

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.