Reference
Asking a model, when shape cannot decide
How a gate asks a model for a judgement its input's structure cannot give, and what it does when no model answers.
Some rules are not about shape: whether a claim is grounded, whether a
closing report hands work back to the operator. The decider there is a model,
and Brama answers it by default.
ports::model_judgement is the one route:
model_judgement::object(prompt, name, schema, check) and
model_judgement::choose(prompt, name, options) send the prompt
through the product's own one-shot call, oko gateway object --prompt …
--name … --schema … — run by the
same Oko every hook asks, TAMA_OKO_CLI when set, else
oko on PATH — which
carries Oko's signed bearer to the gateway and prints the one object the model
answered under the gate's strict JSON Schema, or —
on a machine without Brama — goes to the OpenAI-compatible service declared
with oko model-service set, with its declared model. No gate reads
a line of prose. A question goes unanswered as
Judgement::Unavailable(reason). An unavailable judgment is not
evidence that the source violates a rule. Each gate must distinguish that
failure from an actual model finding. Numeric review refuses an unreviewed
write with the failed operation, not with an allegation about its source.
A judge Oko has recorded as not answering is not asked. Oko writes that
record — judge-health.json beside its transcript index — from
every verification pass and from oko tasks judge
--probe, and the same probe lifts it. A question reads it first
and returns Unavailable with Oko last saw the judge
refuse at …: …; not asked again from a hook, because asking anyway
costs Brama's whole retry wait inside the event, and a single refused
proxy-call can take tens of seconds inside a stop gate. A record
that exists and cannot be read or is not Oko's shape is not read as "never
observed": the question writes model judgement: <path> cannot be
read: …; the judge is asked on stderr and asks, and
block-broken-judge, which reads the same record through the same
reader, refuses oko tasks verify naming the record that could not
be read and the probe that writes it again. The
engine kills no hook for being slow, and the OMP adapter sets no wait of its
own; OMP itself refuses a tool call whose handler has not answered within the
time its own extension-handler setting allows, naming the extension. A hook the
harness stopped waiting for is ended by the next event that proves it has no
caller, as the runtime
page describes, not by a clock.
A question the judge already answered is not asked again. The prompt is the
whole question, the command or text it judges included, so the judge's answer
to that exact prompt and schema is kept under Tama's state, in
model-judgements/<SHA-256 of the prompt and schema>
(TAMA_JUDGEMENT_MEMORY_DIR moves it for a test), and
read back before the question is asked: a command many sessions run
costs one model call, not one each, and while the judge is slow it stands
inside one tool call instead of every one. Only answers are kept; an
unanswered question is asked again. A kept answer that cannot be read is the
question's Unavailable reason, naming the file; an answer that
cannot be kept is still returned, and model judgement: the answer is not
kept for the next ask: … on stderr says why.
A choice between named options
A gate that decides between named options does not read a line of prose.
model_judgement::choose(prompt, name, options) asks through
oko gateway object --prompt … --name … --schema … for one
object whose choice is one of the options the gate names and whose
reason is the judge's sentence, bound to a strict JSON Schema. The
gate compares choice with its own option and uses
reason in its refusal, so the words a model puts around its answer
never decide whether a call passes. An answer
that is not one of the options is an Unavailable judgement naming
the answer, and the gate refuses it as below. The kept answer is keyed by the
prompt and the schema together. These gates ask this way:
block-inline-execution, block-one-off-repairs,
block-keychain-prompt-commands,
block-local-model-training,
block-oko-trajectory-edits, block-subagent-spawn,
block-external-source-edits,
block-hook-scan-narrowing,
block-device-level-tests-without-consent and
check-humanized-actions choose PASS or
BLOCK; block-background-execution chooses
PASS, DETACH or WAIT;
check-legacy-activation-bypass chooses READS or
RUNS; check-merge-deletion-loss chooses
UNDID or KEPT; and pre-bash chooses
PASS or the one forbidden shape the command has
(REVIEW, SCRATCH, SOURCE,
SEARCH, BROWSER, WELES,
CLOUD, QUARANTINE, HELPER,
HOOKS or TRUNCATE) and refuses with the operator's
sentence for that shape.
A gate whose answer is more than one choice writes its own schema and asks
model_judgement::object(prompt, name, schema, check), which reads
the answer as the type the gate names and hands it to the gate's
check; an answer that does not fit, or that the check refuses, is
neither kept nor returned but is the Unavailable judgement naming
it. block-unregistered-build-or-restart asks for the list of
steps the command performs, each a kind (build or
restart) and the directory or service it named;
block-one-off-commands asks for one verdict per declared command,
each naming the command, choosing PASS or BLOCK and
giving its reason, and an answer that leaves a command without a verdict is no
answer.
When a shell or write gate's question goes unanswered
A rule a model enforces is not off while the model is. Every gate that judges a shell command or a
write by model — pre-bash, block-inline-execution,
block-one-off-repairs, block-unregistered-build-or-restart,
block-keychain-prompt-commands, block-background-execution,
block-local-model-training, block-subagent-spawn,
block-external-source-edits, block-device-level-tests-without-consent,
block-oko-trajectory-edits, block-hook-scan-narrowing,
check-humanized-actions, check-legacy-activation-bypass and
check-merge-deletion-loss — hands an Unavailable judgement to
model_judgement::unanswered::refusal, which refuses the call:
TAMA_HOOK_INFRASTRUCTURE: <hook>: review unavailable: <why nobody answered>
The cause is the judge's recorded state (Oko last saw the judge refuse at …: …), the
held question, the missing Oko program or the gateway's own failure; a write or merge gate adds
(judging <file>). oko tasks judge --probe asks the judge one question
and lifts the record when it answers. Two calls pass instead, each saying so on stderr:
- any call on a machine whose operator declared no model with
tama model-provider set --none:<hook>: no model is asked on this machine, the call passes: …; - a shell line whose every command runs a program the judge stands on — this Tama, the Oko it asks
(
TAMA_OKO_CLI, elseoko) and every productstado product catalogdeclares that Oko depending on, at any depth — so the judge can be repaired:<hook>: no judgement (…); the command only runs what the judge stands on, and passes. When that catalog cannot be read the call is refused with both causes:…: review unavailable: …; and which programs the judge stands on cannot be read: ….
The stop gates that judge a closing answer keep their own rule. The journey
cargo test --manifest-path rust/Cargo.toml -p tama-cli --test model_judgement_judge_repairs
runs the built hook with the judge recorded as not answering and the real catalog: a line of
oko and stado passes saying why, and the same line with
python3 -c is refused naming the judge's state. Each gate's own journey requires
the refusal with the judge down.
pre-write-edit never asks the numeric reviewer from the edit
callback. When numeric candidates need review, it retains the exact prompt
and refuses immediately with
tama hook check-unsubstantiated-constants --review <request>.
Run that operation outside the edit callback; it asks
model_judgement::object through oko gateway object
for {"findings": [N, …]}, the numbers of the candidates that are
unexplained tuning choices, each bound by the schema to one of the listed
candidates, and an empty list when none is. Shared child-output collection prints
czekam for Oko's gateway operation and retains that object or the failure,
including the executable, exit status and actual cause. Repeat the unchanged edit after a valid answer. The answer is
bound to the complete file, path, candidates, review instructions and recorded
justification; changed input cannot inherit the previous verdict, and a
retained answer that does not fit the findings schema refuses the edit naming it.
Requests and results live under session-control/numeric-reviews
in Tama state; TAMA_SESSION_CONTROL_ROOT scopes isolated journeys.
Concurrent review operations refuse an already owned request rather than
starting another model call. A missing answer, unreadable record, malformed
reply or actual model failure remains a refusal. No background process is
detached from the edit and no timer retries the reviewer. The CLI and the
attached editor's decision surface show the same request and cause; Desktop
Session and Posture show that recorded hook decision, not a claimed model
success. Review-operation success means an answer was retained, not that the
source passed: the repeated write applies the numeric findings.
tests/numeric-review/retained.rs, registered as
numeric_review_retained, drives the built hook with a real
persisted request and a genuinely missing Oko executable. It retains the
declared candidate, binary digest, command, input, exit status, output and
elapsed time under Cargo's ignored build directory, through its pending, failed,
changed-input and malformed-justification cases.
check-substantiation-with-model uses the model gateway.
That is also the route for a judgment about prose that cannot be decided
from the input's structure; an embedded word list is not a substitute.