ADR-123
check answers four questions: VALID · ACCESS READY · CAPACITY FIT · RUN READY, and run refuses what check refuses
accepted · 2026-09-03 · L0 L3 L4 · cites 3
0ADR-123: check answers four questions, and run refuses what check refuses #
Context #
A green nika check was read as « this will run ». It could not be: the
ladder judged the DEFINITION (grammar · DAG · permits · types · the
resolver's knowledge of the model) and said nothing about THIS machine
(is a path ready?) nor about the seat against the declaration (can it
emit that many tokens?). Two measurements forced the decision:
- The W1 persona gauntlet (2026-09-03) read
✔ MODELS … key presence on this machine not judgedas readiness, metNIKA-INFER-001on a dead key ninety seconds later, and counted three JSON shapes for the same access decision (check --jsonaccess_plan[].chosen·run --dry-run --jsonaccess.plans[].class· the boot manifest's JSON-encoded map). - The same rig showed
checkrefusing a reasoning seat undermax_tokens: 32(exit 2) whilerunadmitted and executed the same file: the run's clean gate folded the ladder's findings and skipped the MODELS rung's judgments.
The one-door pack's product law: check answers four different
questions and never collapses them into one checkmark, and nika check
must not spend tokens to prove readiness.
Decision #
- Four layered verdicts, computed once beside the exit code.
VerdictLayers { valid, access_ready, capacity_fit, blockers }withrun_ready()derived. VALID = the ladder + resolution + skills. ACCESS READY = every static lane admitted by the frozenExecutionAccessPlan(ADR-122) this machine resolves — presence only, never a dial;Nonewhen no static model exists. CAPACITY FIT = the thinking laws + the new CAPACITY laws. RUN READY = the three plus any known blocker. The text render prints an ACCESS rung under MODELS and alayers ·line after the audited line;--jsonadds averdictsobject.cleankeeps meaning VALID + CAPACITY FIT (what it always folded):REPORT_VERSIONstays 1, the exit codes stay closed, and RUN READY false is a--profile operationaloutcome (exit 2), never the default. - CAPACITY laws from the catalog's positive knowledge only
(
catalog_knows· the mock never judged):infer.max_tokensabove the seat's max output;schema:on a seat the catalog marks without a JSON mode;agent.max_tokens_totalabove the context window;vision:on a seat whose input modalities exclude images. They ride the MODELS rung's findings rail on the CLI, the MCP oracle and the run gate. - `run` refuses what `check` refuses. The run's clean gate folds
the MODELS rung's judgments (resolution · thinking · capacity), judged
on the effective model (
--modelapplied) exactly likecheck. - One lane-row shape.
nika_service_execution::access::lane_rowsrendersmodel · provider · resolved · access · chosen · billing · pinned · rejected[]and every machine surface carries those rows:check --jsonaccess_plan,run --dry-run --jsonaccess.plans, the boot manifest'saccess_plan(an array now; the resume reader still folds the 0.117 map). The text dry-run always prints the plan plus one access line per lane. - `check --access <pin>` judges the plan under the pin
run --accesstakes. Presence is worded as presence:doctorsayskey present · not validated, the ACCESS rung saysnot validated (check never dials).
Consequences #
- A file that is legal but cannot run here is no longer green on the operational profile, and the human surface says which question failed.
- The thinking-budget hint no longer blames a task pinned to the mock (the capability defaults read the mock as reasoning-capable; the hint now asks the catalog first).
- Proof:
crates/nika-cli/tests/check_run_layers_e2e.rson the real binary (the reasoning floor red on both doors · capacity red on both doors · one lane shape on three surfaces ·check --accesspins likerun· the layers line), the analyzer's capacity laws, the display's render tests, the service driver's row test.
Follow-ups #
- Delivered in wave 2b: a failed task terminal carries its lane and a
note naming the model;
run_settledcarrieserroron every failed frame (launch refusals included) and theaccess_planrows of the lanes that served;run --helpends on its exit ladder; the resume access refusal isNIKA-1807; « wrote .nika/traces » prints only when a trace exists; the MODELS rung's judges (verdict_layers· capacity · resolution · the boot access stamps) are hosted innika_cli_host::models_rung, the door the MCP oracle reaches (wave 3). - Delivered in wave 3.b (the W3 gauntlet): the RUN READY preflight at
the admission belt for the two cases it missed — a pinned seat whose
product binary this machine lacks (the seat is two binaries, and the
probe row carries both) and an
infer:that names no model with no seat pinned (NIKA-1800 before task 1);check, the dry-run and the run read the same judges. The lane row names the ready paths it outranked; the COST rung says when a model is seat-served. - The run-time ACCESS READY probe (a non-billable credential check) stays open.
read at v0.118.7 · the decision record ships with the engine