What Else To Look Into
Consolidated. This note's findings now live in
../MIN-STUDIES.md§12. The original is kept for its measurements; do not re-derive from it.
What else we need to look into
Young, 2026-10-10: "We are designing at this stage, what else do we need to look into?"
This is a gap analysis, not a task list. Each item is something the current design does not answer, verified against V2's code where V2 has an answer at all. Ordered by what would hurt most if it stayed unanswered.
Tier 1 — the design is not safe to build without these
1. The verification gate is NOT on the completion path
Verified in V2's code, 2026-10-10. This is the sharpest finding in the review, because the mechanism is subtle enough that the gate looks wired.
The gate is called from exactly two places:
harness/conformance.py:86 vg = VerificationGate() ← a probe
cortex/verification/gate.py:89 vg = VerificationGate() ← its own __main__
Nothing on the completion path calls it. And the reason is structural:
| Component | What it does | The problem |
|---|---|---|
gate.verify() (gate.py:58) | requires state == VERIFIED, then checks evidence | It can only inspect a task already marked verified. It cannot prevent verification — it checks after the fact |
Coordinator.verify_task() (coordinator.py:141) | writes VERIFIED with role="verifier", then immediately COMPLETED | The "verifier" is whoever called it. With verified=True it never reads evidence at all |
So the gate is downstream of the decision it is supposed to make. It asks "was this task verified?" rather than "should it be?" — and by the time it can ask, the task is already complete.
And the bypass is reachable from the live surface. arms/mcp_server.py:300
exposes verify_task as an MCP tool; it calls coord.verify_task(...) directly:
elif name == "verify_task":
coord = Coordinator()
result = coord.verify_task(arguments["task_id"], arguments["verified"], ...)
A caller with access to that tool can complete any working task with
verified=True, and no evidence is inspected anywhere on the path.
Measured: 25 tasks currently sit in verified — a state the gate requires but
that only verify_task writes, and it completes them immediately after.
This is V2's "built, never wired" pattern at the most load-bearing point in the system. The design rule "a claim is not a completion until something the claimant cannot write to has verified it" is unenforced — and worse, the component that would enforce it is positioned where it cannot.
What V3 must answer, precisely:
- Does the gate run BEFORE
VERIFIEDis written? It must, or it is a report. - Who is the verifier, and can they write the state they are verifying? If
verify_taskboth writesVERIFIEDand claimsrole="verifier", the separation of duties is self-declared. - Can the bypass path exist at all? If a
verify_task(verified=True)tool is reachable, the gate is decorative no matter where it sits.
2. The kill switch does not reach execution
Verified: board/kill/ACTIVE.json does not exist, and grep enforcement:
| File | refs |
|---|---|
runtime/opencode_exec.py | 8 |
core/queue.py | 0 |
So a queue operation does not consult enforcement — a hold cannot stop a
state transition. V2's measured form of this: with the kill switch engaged,
message/send still returned state: submitted.
What V3 must answer: at which layer is enforcement authoritative, and is it consulted on every path that can start work?
3. A completed task can be false
The defect V2 never closed. An agent that refuses in prose sets no failure
signal, so the outcome classifier returns success. V2's ledger held 30,721
attempt rows and every cost read $0.00000 — because cost_capture.py lived
in bin/, a worker's PYTHONPATH never included it, and the ImportError was
swallowed by a bare except.
Related, and the same class: ok=True follows bool(texts) — so an
unparseable stdout line becomes a false success. A banner line alone yields
ok=True with zero work done.
What V3 must answer: what distinguishes "ran and produced nothing" from "ran and succeeded"? Right now, nothing.
Tier 2 — the design names these but has not decided them
4. HITL escalation has no consumer
Coordinator.escalate_to_hitl() exists and does do something real — it calls
queue.hold(...), which is a legal transition. But:
- Its only callers are tests. No live path escalates.
- It prints
🚨 HITL escalation: task ...to stdout. Under systemdType=simplewith noStandardOutput=, that is discarded — V2's own recorded defect (H5).
So "escalate to a human" currently means "write a hold row and print to a void". The task does stop — but nobody is told.
What V3 must answer: how does a human actually learn a task needs them? This is the same gap as the task follow-up Young named, from the other side.
5. Retry policy — is it enforced or declared?
V2's rule: 2 per approach, 4 total, then hold. record_attempt() computes an
escalate flag. The design must state where that is checked and what happens
when the budget is exhausted mid-execution — V2 had escalate computed and
discarded in one path.
6. The 5-hour window is the binding constraint, not the month
Mira's finding, and it belongs in the design: GO is a subscription with a $60 allowance cap; ZEN is $40/mth PAYG. Neither is a monthly dollar cap. Window exhaustion blocks the MODEL, not the bill — and a dollar cap reads green right up to the moment the model stops serving.
What V3 must answer: how is window exhaustion detected and recorded, as distinct from spend?
7. Retention is a routing input, not a policy footnote
Mira's rule, currently stated but not designed: anything touching vault content, credentials, task text or the registry routes only to a zero-retention model, or to no model.
What V3 must answer: how is a model's retention class declared and enforced? If it is a comment in a config, it is not a control.
Tier 3 — real, but they do not block the first build
| # | Gap | Why it matters |
|---|---|---|
| 8 | skills: [] must be a hard failure | V2 served 8 empty cards and read them as healthy. Mira's probe list names it; it needs to be in the design |
| 9 | The guard must check the RESOLVED method name | Sol's finding: with any compat layer, checking the string a client sent lets a differently-named call reach an ungated path |
| 10 | Heartbeat has no lock | V2: 8 concurrent writers on one JSON file, 849 corruption observations, all 8 agents collapsing to 2 entries |
| 11 | references/spec/ must be tracked | V2: 18 MB, untracked, one git clean from gone — why the protocol got hand-rolled |
| 12 | Two solos_paths-class roots | V2 had 5 databases; the guard must fail closed on any undeclared root |
What I would NOT add
Stated so the list does not grow by default:
- No orchestrator. Retired in V2, zero importers, duplicates routing already done at submit.
- No second protocol. One transport, A2A. V2 ran MCP, ACP and A2A for the same traffic.
- No self-evolution. V2's G4 probe was a fake green; the feature has zero code.
- No new state.
blocked_by_holdalready maps to the wire'sinput-required. A stuck task needs the existing state to be reachable and observable, not a new one.
The one question under all of them
Every Tier 1 item is the same shape: a control that exists and is not consulted on the path that matters.
- the gate exists, and
verify_taskbypasses it - enforcement exists, and
queue.pynever reads it - a refusal is detectable, and the outcome classifier calls it success
- HITL exists, and nothing calls it
So the single design question for V3 is not "what components do we need?" — it is "what proves a control is in force?"
Mira's probe table and Sol's harness are the answer taking shape. V3's first deliverable should be that instrument, before any component is built — because V2's six built-with-zero-callers defects were each found by a human noticing, not by anything the system did.

