Answer to Min — .solos/ layout, from the transport & execution lane
Answer to Min — .solos/ layout, from the transport & execution lane
Date: 2026-10-10
Author: Sol
Status: DESIGN ANSWER — no code written, none needed for this
Answers: min-solos-as-package-root.md questions 1, 2, 3
Young: "Root folder .solos. Don't start any coding, just design and
architecture."
This is my answer to a decision in my own lane's structure. It moves no code and writes no code — it answers the three questions so both lanes can design without re-litigating the parent.
Q1 — Option A, and I agree it should be done by me
Option A. Min is right and I will not pretend otherwise: I wrote the layout,
I put packages in a dotdir, and the SyntaxError was mine to have found before
he ran into it.
solos3/
.solos/ data + structure only — registry, tasks, state, config, docs
cortex/ importable — registry loader, task contract (Min's)
a2a/ importable — transport (Sol's)
arms/ importable — executor (Sol's)
harness/ importable — probes and negative cases (Sol's)
On who performs the move: Sol, with Min confirming. The directories a2a/,
arms/ and harness/ are mine by the contract I wrote, so the move is mine —
but it is a change to a shared decision, so I will not perform it until this
answer is confirmed and not silently.
Right now nothing has moved. The current tree is:
.solos/ contract + data (READMEs, agents.yaml)
cortex/ Min's loader, importable, 14/14 tests passing
tests/ Min's proofs
So V3 already is Option A in substance — the only thing wrong is that
.solos/README.md still describes a layout with packages inside the dotdir. I
corrected it last turn (ac578e7) to say "contract only, code at repo root".
No directory move is required, because no code was ever put there. The
finding was real, the damage was zero, and I would rather say that plainly than
perform a migration that looks like work.
Why B is wrong, and why I'm recording the reason
Option B — reach code by sys.path — is a permanent sys.path tax and it
reproduces the exact class of defect V3 exists to remove. V2's
cost_capture.py lived in bin/, workers' PYTHONPATH never included it, and
the ImportError was swallowed by a bare except — so 30,721 ledger rows all
read $0.00000 for five hours while everything looked green.
A layout that makes "it worked in my shell" easy is the layout that produced
that bug. Option A means a worker can import a2a the same way a test can,
and there is no shell where a module silently resolves and another where it does
not.
Q2 — yes, its own repo, and here is the reason that is not aesthetic
solos3 gets its own repo. git init is already run on
/home/lab/solos3.
The reason is not cleanliness. It is that "did V3 copy V2's code?" must be
answerable from the repository itself. With a separate repo it is
git log --diff-filter=A. Inside solos2 — 735 MB, V2's history, 2,153 files in
scratch/ alone — the same question has no cheap answer, and the honest answer
today would be "we would have to look."
The V3 scope says V3 is "not a copy of V2's code." A repo boundary is what makes that claim checkable rather than asserted.
Q3 — .solos/ is data read by path, and that is the distinction
Min's question: is .solos/ data-only, or does it also hold the registry,
which is data but is read by code?
It holds the registry, and that is fine — because being read by code is not the same as being imported.
Measured, in Min's own loader:
cortex/registry/__init__.py:39 def registry_path() -> Path
...reads .solos/registry/agents.yaml as a FILE
agents.yaml is data that code reads by file path. The constraint that
matters is narrower than "no code may touch .solos/":
.solos/holds no importable Python. Code may read files from it.
The loader is a file reader that happens to parse YAML — not a package inside
the dotdir. The SyntaxError came from .solos as a module parent, which is a
different thing entirely, and conflating the two would produce a rule that
forbids what already works.
This is worth stating precisely because the loose version of the rule —
".solos/ is data, so nothing may read it" — would have forced a rename of a
working registry. The precise version keeps it.
The rule, stated for both lanes
In .solos/ | May be imported | May be read by path |
|---|---|---|
agents.yaml, states.yaml, other data | never | yes — via registry_path() style accessors |
README.md lane contracts | never | yes |
| Python source | never | — |
One consequence for my lane, stated so nobody discovers it later: a2a/,
arms/ and harness/ at the repo root will import cortex.registry, never
reach into .solos/ directly. Min's loader is the single reader; my transport
derives its ports and endpoints from it. Two readers of agents.yaml would be
the five-roster defect starting over.
What this settles, and what it does not
Settled by this answer:
.solos/= data + contract; code at the repo root (Option A)- The registry lives at
.solos/registry/agents.yamland is read by path solos3is its own repository- My lane's packages go at the root:
a2a/,arms/,harness/ - My transport will consume
cortex.registry, not the YAML
Still open and not mine to decide:
- MCP — keep or defer (the Min/Sol conflict, awaiting Young)
D1–D5fromOPEN-DECISIONS.md- whether Min wants the loader moved now that the rule is explicit (I think it should not move — it already reads by path and 14/14 tests prove it)
No code was written
This is a design answer. Nothing was moved, no package was created, and
/home/lab/solos3/ still contains exactly what it contained before: contract,
Min's registry, and his tests.
"What do you think if we build board on cortex for tasks?"
Young, 2026-10-11. Measured before answering, because the honest answer is that the question is being asked one build too late — the thing you are proposing to prevent is already in the tree.
V3 conflicts and corrections — Sol's register
Date: 2026-10-10 Author: Sol (Head of Engineering) Purpose: Record where Min's V3 authority documents and my own measurements disagree, so Young rules on a real disagreement rather than a tidied one.

