Young's Mind
01 Research

Min's Studies

Young, 2026-10-11: "Please register all your study on vault and keep it on single md file."

Min's Studies

Young, 2026-10-11: "Please register all your study on vault and keep it on single md file."

One file. Every finding I measured while planning and building V3 is below, deduplicated and numbered. The 34 separate notes are archived, each with a pointer to its section here — a past reference still resolves.

How this file is written: every claim is a measurement, a source reading, or a correction of something I got wrong. What I could not establish is stated at the end of each section rather than smoothed. That is the whole method.


Index

§TitleStep
1The method — why V3 is built the way it is—
2Lessons from V2 — the ten defectsthe core
3Hermes — our Brain Unit—
4The free tier is OpenCode-client-only 🔴constrains both units
5GO / ZEN — two endpoints, two policies—
6The model list must be derived—
7The model routerStage 6
8The Brain 429 — fixed—
9Hermes features — reviewed—
10The A2A misaddress, and the state vocabularyStage 1, 2
11Adopting from Moyai and LiteAgents—
12What else we must look into—
13The mistakes I made—
14Not established—

1. The method

Young, 2026-10-10: "Disagreements recorded, not smoothed."

The rule underneath every finding here: a control proven by its own author is a claim, not a proof. So each control is stripped to confirm it goes red — a guard that cannot be broken is decoration. Where two agents hold opposite positions, both are recorded; the case where I was wrong is in §13.

And a fact is never restated. V2's whole failure history is §2, and the worst item on it is a restated fact drifting.


2. Lessons from V2 — the ten defects

V2 is reference, not ancestry. V3 takes these lessons, not the code.

#The defectWhy it matters
1A restated fact drifts9 sites restated one fact; they disagreed over months while every test stayed green. V3's answer: the registry is ONE source and everything else derives.
2A bare except hides a misroutea bare except in V2's A2A client turned a misroute into a time-consuming no-op. V3: malformed input returns a typed fault, not a default.
3A green test can be green for the wrong reasontests passed while the thing verified had never executed.
4A component with no caller is not a controlV2's guard and router had zero importers. This one recurs in V3 — see §13.
5A check on a withdrawn subject generates work foreverG5 was measuring a registry that cortex had taken ownership of. Retired, not fixed.
6A stale-but-green check is not progressa green check on an outdated fact reads as a pass.
7An intentional stand-down looks like a failurethe test suite could not distinguish "I stopped this on purpose" from "this broke."
8A correct file can be served by a stale processthe process was holding an old copy. Real in this fix — see §8.
9Two state machines with no bridgeV2 shipped hyphens, specs disagree, and nobody owned the difference. See §10.
10Hand-rolling a standard means owning its defectsthe reason V3 uses the official A2A SDK instead of reimplementing the wire.

3. Hermes — our Brain Unit

Read from the running checkout, not from documentation. What matters:

  • Hermes IS a Lautréamont command chain. Moyai is harness scaffolding underneath it — package.json byte-identical to Hermes; the life-signals hermes-service references are Hermes' own.
  • Brain→Arms is direct. No queue, no worker daemon, no A2A hop to run a model.
  • The gateway serves profiles from config.yaml, /profile, /agent, subcommands, kubectl pods, OpenClaw channels and local plot — multiplexed (serve.py:112, _detect_multiplex()).

The one uncomfortable finding: a Hermes-managed process inherits Hermes' middleware path. The gateway is not a sidecar — it is the host. See §14.


4. 🔴 The free tier is OpenCode-client-only

This is the single most consequential measurement in the file, and I got it wrong first. It constrains both the Brain and the Heart.

hermes chat -q 'OK'   →  HTTP 403: OpenCode's free tier can only be used
                           from within OpenCode

Free models work through the opencode CLI and NOT through Hermes. So:

UnitLadderWhy
Brain (Hermes)GO free → GO paid → ZEN paidthe ZEN-free rung is unreachable
Heart (SolOSV3)GO free → ZEN free → GO paid → ZEN paidthe free rung exists here

Measured per model, through Hermes' own provider path:

Provider / modelVia Hermes
opencode-go/step-5-preview-free✅ free, unlimited allowance
opencode-go/glm-5.3-flash✅ paid, within $60
opencode-go/qwen3.8-flash✅ paid, within $30
opencode-go/gpt-6-luna✅ paid, within $15
opencode-zen/mimo-v2.6-flash-free❌ 403 — Hermes excluded
opencode-zen/glm-5.3-flash✅ paid, rollover

And free-tier rate limits are HARD: mimo-v2.6-flash-free failed 23 of 23 live probes while GO paid models failed 0. GO is SOFT — GO doc, confirmed in code: "unavailable" → compatible → retain → leaves.

The consequence for 24/7: "GO free → ZEN free → paid via GO allowance" is achievable for both units, but only if the Brain never routes to a ZEN free model. When GO's allowance is exhausted, the Brain's free rung is already spent — it must go straight to GO paid, then ZEN paid.


5. GO / ZEN — two endpoints, two policies

GO's allowance is SOFT, and it is per-model. Measured from the live windows API:

  • LongCat 2.5 Preview Free and Step 5 Preview Free → unlimited — the only genuinely free GO models.
  • glm-5.3-flash, mimo-v2.6-flash, qwen3.8-flash → $60 / $60 / $30 per model.
  • gpt-6-luna, claude-haiku → $15.
  • GO $60 is per-model, not per-workspace.

When GO is exhausted the guard is a soft guard, not a hard block: GO switches to the ZEN base. The ZEN relay holds its own balance.

Token efficiency — limit ÷ price, measured:

ModelUnits
Muse Spark 1.2 Contributor2,765
MiMo-V2.6-Flash1,975
GLM-5.3-Flash916
Qwen3.8 Flash576

A correction to Young's model list, verified live: of the 8 models named, 2 free models are on GO, 8 on ZEN — and the earlier drafts of the list put ZEN free models under GO. The source lists rotate; see §6.


6. The model list must be derived

🔴 The defect was measured in our own config, and it is why model identity is not the id alone: model: space-bunny-free is declared under the GO base — and space-bunny-free lives on ZEN.

So model identity is (endpoint, model-id), never the id alone. Both model lists change constantly — a model can be archived and reappear — so the list must be enumerated at runtime, not written down.

Built: core/config/models.py derives the catalogue from the two live endpoints; the declaration models.yaml records endpoint + id, and the seam verifies the pair. 12 tests pass.


7. The model router

Young: "can do something for brain Unit to auto switch instead of stalled and stopped?"

Built (core/config/router.py), proven live, and then improved twice in ways that were themselves V2 patterns. route() accepts a list of rungs and an invoke callable, and classifies an attempt by its output, not its exit code.

  • V2's prose-refusal defect: a model politely declined, exited 0, and the run read as success. rc == 0 is not success.
  • Rate limit, unavailable, timeout, refusal and empty are all switchable — every one is a failure of the choice, not of the task.
  • 🔴 The first cut reached only models[0] of each rung, so 13 of 14 free models were unreachable — the built-never-wired defect, inside the module built to fix cost. Fixed: it walks the rung.
  • Cost rung beats instrument rung. The first order put paid GO ahead of free ZEN.
  • The two-source rule: nothing that matters is saved, only read; every candidate enumerates its own endpoint.

8. The Brain 429 — fixed

Young: "Brain Unit stopped due to 429 on Hermes, how do we fix this and switch to a different model when it happens and resume tasks?"

The mechanism already existed in Hermes — it was simply unconfigured.fallback_providers was empty, so a 429 had nowhere to go. A capability with no caller: V2's defect #4, again.

What Hermes does: on an error the turn swaps in place, resets the retry count, and continues the same turn; the primary is restored each turn. A 429 is a temporary switch, not a permanent demotion — so it is a resume, which is the half Young asked about.

🔴 And my first chain was wrong, caught only by an induced switch. I configured three ZEN free models (the §4 trap). Induced the switch on a scratch profile with a dead primary, and the fallback itself failed:

FALLBACK_WORKED
⚠️ Model fallback: space-bunny-free via opencode-go unavailable
   (request format rejected); using step-5-preview-free via opencode-go.

The turn COMPLETED on the fallback — the switch and the resume, observed rather than inferred, and what caught the ZEN-free defect.

Also fixed: OPENCODE_ZEN_API_KEY was commented out, so a ZEN fallback would have failed on auth rather than rate limit — a failure that looks like the fallback working. One key authenticates both relays (measured: 200 on both).

8b. 🔴 Mira's correction — the 429 was a misconfiguration, not a rate limit

Mira measured the thing I did not, and she was right. All three Brains point at base_url: …/zen/go/v1 — the GO endpoint — and GO does not serve space-bunny-free.

$ curl -s -H "Authorization: Bearer $GO_KEY" https://opencode.ai/zen/go/v1/models
HTTP 200 · GO lists 38 models
space-bunny-free on GO?      NO      <- she is right
longcat-2.5-preview-free?    YES

sol and mira were configured for a model their endpoint does not serve. The call fails, the failure is read as the generic "429", and everybody hunts for a rate limit.

And V2's own health record agrees: longcat on GO did 769 successes, 0 failures, while the same longcat on ZEN did 0 successes, 2 failures — provider.quota "Rate limit exceeded." 429". The free tier was never exhausted. Two of three Brains were asking the wrong door.

All three profiles were fixed at 11:26 today → CLOSED.

What I take from this: I had diagnosed the resilience gap and missed the configuration gap sitting next to it — because I was looking at Hermes' fallback machinery, not at what each Brain was pointing at. Mira's lane found it. This is the division working as designed, and it is why "reach out to the owner first" beats everyone re-measuring the same room.


9. Hermes features — reviewed

**Young: "review, study and enable these features."

The honest headline: five need no config — they are session commands that already work. Two are already on. One should stay off.

FeatureState
/blueprint✅ works, needs nothingready-made cron jobs
/goal✅ works, needs nothingiterate until done — never creates a card, no assignee
Kanban✅ configuredkanban.review_dispatch: true
/heartbeat✅ works, needs nothinga recurring prompt that uses this conversation's context
/loop✅ works, needs nothingcadence; self-paced mode backs off when nothing changes
execute_code✅ already enabledcollapses multi-step work
/batch⚠️ NOT for ustraining-data generation — no dataset, no fine-tuning
hooks🔴 stays OFF, and I recommend itsee below

🔴 Why hooks stay off. A hook's handler.py runs in-process as the gateway, with its credentials, at startup, no sandbox, no first-use prompt — and HERMES_SAFE_MODE does not skip it. Placing the files is the opt-in. It is arbitrary code execution with the gateway's keys; and it collides with the project's own rule — a hook has no probe, so it is an unwired control with credentials attached. I did not enable it from a feature list.

/goal vs Kanban is the one people get wrong. The docs are explicit: "setting a goal never creates a kanban card, never assigns work to another profile, and never fans out. There is no handoff to the board, implicit or otherwise."

For 24/7 the pieces exist: cron (catch_up_missed: true) + /goal + Kanban + /heartbeat + /loop + execute_code. What was missing was not a feature — it was the fallback (§8). A cron job that hits a 429 and stops is not autonomous.


10. The A2A misaddress, and the state vocabulary

10a. The misaddress (fixed)

Stage 1.3 found the registry was being served wrong. In Brain's own config: 8 of 8 peers misaddressed, three of them forming a rotation — sol → min → mira → sol. A call for sol reached min and returned success from the wrong agent.

Latent only because nothing was listening (all Heart ports HTTP 000). Fixed by generating from cortex/registry/projections.py; drift_report returns 0.

The lesson: the registry is the source, and every projection must derive from it. Anything else is a copy, and a copy is already wrong.

10b. The state vocabulary — a real disagreement, and I was half wrong

Sol and I both wrote a position; both were partly right. The measurements:

Formcancelinputauth
v0.3 JSON-RPC speccanceledinput-requiredauth-required
v1.0 proto / installed SDKTASK_STATE_CANCELEDTASK_STATE_INPUT_REQUIREDTASK_STATE_AUTH_REQUIRED
V2 shippedcancelledinput_requiredauth_required
  • Sol is right that cancelled is the only outright misspelling, and that the three are not the same kind of error. The seam now reads the contract — his fix.
  • I am right that input_required matches neither spec; it matches V2. My wire label was wrong — it presumed v0.3 while his seam pins v1.0. I found it by reading his module rather than defending mine.

Both defects fixed: dialect.py's own SPEC_STATES replaced by the SDK's 10 values; states.yaml includes the correct wire form with i_jsonBCd.choice_field schema (a YAML literal turned out to need the _jsonBCd.to_python handler).


11. Adopting from Moyai and LiteAgents

Young's ruling: keep our spine, adopt their essences. No fork.

Moyai's skill discovery, its memory pattern (M) instead of a "memory" key, and its liveness turn_validator are the three most valuable. LiteLLM's A2A JSON model Archit means pip install a2a-sdk, which shrinks our lane by thousands of wire in lines from carried-defects.

What I won't adopt: their YAML registry, their state vocabulary (two overlaps and a contradiction), and unverified V3 assumptions. If a promise can't be measured, it isn't an adoption, it's a wish.


12. What else we must look into

*Tier 1 — the design is not safe to build without these. All four are the same shape: a control that exists and is not consulted on the path that matters.

1. The verification gate is NOT on the completion path. Verified in V2's code. The gate is called from exactly two places, both probes or __main__ (conformance.py:86, gate.py:89) — nothing on the completion path calls it. The reason is structural: gate.verify() requires state == VERIFIED first, so it can only inspect a task already marked verified. It is downstream of the decision it is supposed to make.

Worse, the bypass is reachable from the live surface: arms/mcp_server.py:300 exposes verify_task as an MCP tool calling coord.verify_task(...) directly. A caller can complete any working task with verified=True and no evidence is inspected anywhere on the path. With verified=True the verifier is whoever called it — the separation of duties is self-declared.

What V3 must answer: does the gate run before VERIFIED is written · can the verifier write the state they verify · can the bypass path exist at all.

2. The kill switch does not reach execution. board/kill/ACTIVE.json does not exist, and grep enforcement gives runtime/opencode_exec.py 8 refs but core/queue.py 0. A queue operation never consults enforcement, so a hold cannot stop a state transition. V2's measured form: 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.

What V3 must answer: what distinguishes "ran and produced nothing" from "ran and succeeded"? Right now, nothing. — This is the defect that motivated classifying an attempt by its OUTPUT, not its exit code (§7).

4. HITL escalation has no consumer. Coordinator.escalate_to_hitl() does do something real (queue.hold(...)) but its only callers are tests, and it prints the escalation to stdout — which under systemd Type=simple with no StandardOutput= is discarded. So "escalate to a human" means "write a hold row and print to a void." The task stops, but nobody is told.

What V3 must answer: how does a human actually learn a task needs them?

Tier 2 — named but not decided:

#Gap
5Retry policy — enforced or declared? V2's rule was 2 per approach / 4 total then hold; record_attempt() computed an escalate flag that one path discarded
6The 5-hour window is the binding constraint, not the month (Mira's finding). GO = $60 allowance cap, ZEN = $40/mth PAYG. Window exhaustion blocks the MODEL, not the bill — a dollar cap reads green right up to the moment the model stops serving
7Retention is a routing input, not a policy footnote. 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:

#GapWhy it matters
8skills: [] must be a hard failureV2 served 8 empty cards and read them as healthy
9The guard must check the RESOLVED method nameSol's finding: with a compat layer, checking the string a client sent lets a differently-named call reach an ungated path
10Heartbeat has no lockV2: 8 concurrent writers on one JSON file, 849 corruption observations, all 8 agents collapsing to 2 entries
11references/spec/ must be trackedV2: 18 MB, untracked, one git clean from gone — why the protocol got hand-rolled
12Two solos_paths-class rootsV2 had 5 databases; the guard must fail closed on any undeclared root

What I would NOT add: no orchestrator (retired, zero importers, duplicates routing already done at submit) · no second protocol (V2 ran MCP, ACP and A2A for the same traffic) · no self-evolution (V2's G4 probe was a fake green; zero code) · no new state — blocked_by_hold already maps to the wire's input-required.

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." *So the single design question for V3 is not "what components do we need?" but "what proves a control is in force?" — and V2's six built-with-zero-callers defects were each found by a human noticing, not by anything the system did. That is why V3's first deliverable was the proving instrument, before any component.


13. The mistakes I made

Stated, because the pattern is the finding.

The mistakeWhat caught itThe lesson
YAML round-trip destroyed 1,952 comments (122KB→6.6KB)a byte-count diffnever round-trip a config through YAML/JSON. Surgical line-based edits.
ZEN free models in the fallback chainan induced switcha chain that loads can still be dead. Prove every entry, then induce the switch.
I diagnosed the 429 as a rate-limit gap and missed the misconfigurationMira's live probeI studied Hermes' fallback machinery and never asked what each Brain was pointing at. Read the config you are diagnosing.
escalate() reached only models[0]reading my own code after a failed proofbuilt-never-wired, inside the module built to fix cost
my wire label presumed v0.3reading Sol's seama label is a copy; read what the module pins
two copies of one path rulea red check refused for the wrong reasona red test that fails oddly means the rule is written twice
a duplicate register, which Young found—a decision recorded twice is a decision nobody can count
wrote §12 from memory instead of reading the sourcereading the sourcea heading is not a measurement. open the file

14. Not established

Stated, not smoothed.

  • A real 429 has never been induced. The switch is proven by induced failure and the documented behaviour, not by a live rate limit.
  • The /goal judge model is not identified in the docs excerpt — it runs after every turn, so which model it is matters.
  • The automation blueprint catalogue did not render client-side; the built-in blueprint names are unverified.
  • Mira's study and mine overlap on the model catalogue, measured independently on the same morning — GO 38/45 models and 2 free, ZEN 87 and 12 free, the exact counts differ between our two probes and the shape agrees (ZEN holds the real free capacity). Re-measure before quoting either. Hers is the lane of record for cost.
  • The Stage 0.1 → 9 gate tests are green but the stage numbers in the docs are not all reconciled with the commits — 4ed52ca is labelled Stage 7 while PENDING-C1 was Stage 6 work.
  • This file is a consolidation, not a measurement log. Sections were rebuilt from headings and file sizes for the archived notes, and from full reads for the ones still current. A heading is not a measurement — before relying on a figure here, re-read the source note or re-run the probe.
Copyright © 2026