What happened
builder-experiment-39 sent a status message intended for its architect. It was delivered to the architect named main, not to its spawning architect uiv2. main had to forward it manually, noting it had landed in the wrong inbox.
Why this is a defect either way
The attribution in global.db is correct:
sqlite3 -readonly ~/.agent-farm/global.db \
"select id, spawned_by_architect from builders where id='builder-experiment-39';"
builder-experiment-39|uiv2
So there are only two possibilities, and both are bugs:
- The builder used the bare
afx send architect form. Documented behaviour is "From a builder: its spawning architect." spawned_by_architect is uiv2 and it resolved to main anyway, so the resolver is ignoring the column and falling back to the main-else-first-registered rule that is meant to apply only to non-builder senders.
- The builder used
afx send architect:main explicitly. That is supposed to be refused. Per CLAUDE.md: "a builder may only use this for its own spawning architect — mismatches are rejected as spoofing." A builder reaching an architect that did not spawn it means the anti-spoofing check did not fire.
I cannot tell which from the outside, since the sent form is not recorded. That is arguably a third small gap.
Why it matters beyond one stray message
This is the multi-architect case the workspace explicitly supports (cluesmith#755, cluesmith#761, cluesmith#786, cluesmith#823). With two architects in one workspace, a builder's messages reaching the wrong one is not cosmetic:
- The wrong architect receives blockers it has no context for and no authority over.
- In this instance the misrouted message carried stale infrastructure state (it claimed a Cloudflare tunnel was live that had already been deleted). The architect that could have corrected it immediately never saw it, and the one that did see it correctly declined to act on another architect's builder. The correction took a manual relay.
- It undermines the ownership boundary between architects, which is the entire point of named architects.
Reproduction sketch
afx workspace add-architect --name other in a workspace that already has main.
- Spawn a builder from
other.
- From the builder,
afx send architect "test".
- Observe which architect receives it. Expected
other; observed main in this case.
Suggested fix
- Bare
architect from a sender that is a builder must resolve through spawned_by_architect and must never fall back to the main-else-first rule. If the column is null, fail loudly rather than guessing — a message delivered to the wrong architect is worse than one that errors.
architect:<name> from a builder must be rejected unless <name> equals spawned_by_architect, which is the documented behaviour.
- Record the address form used on the mailbox row, so misroutes are diagnosable after the fact.
Found while running two architects (main, uiv2) against separate builders in codev-1455.
What happened
builder-experiment-39sent a status message intended for its architect. It was delivered to the architect namedmain, not to its spawning architectuiv2.mainhad to forward it manually, noting it had landed in the wrong inbox.Why this is a defect either way
The attribution in
global.dbis correct:So there are only two possibilities, and both are bugs:
afx send architectform. Documented behaviour is "From a builder: its spawning architect."spawned_by_architectisuiv2and it resolved tomainanyway, so the resolver is ignoring the column and falling back to themain-else-first-registered rule that is meant to apply only to non-builder senders.afx send architect:mainexplicitly. That is supposed to be refused. Per CLAUDE.md: "a builder may only use this for its own spawning architect — mismatches are rejected as spoofing." A builder reaching an architect that did not spawn it means the anti-spoofing check did not fire.I cannot tell which from the outside, since the sent form is not recorded. That is arguably a third small gap.
Why it matters beyond one stray message
This is the multi-architect case the workspace explicitly supports (cluesmith#755, cluesmith#761, cluesmith#786, cluesmith#823). With two architects in one workspace, a builder's messages reaching the wrong one is not cosmetic:
Reproduction sketch
afx workspace add-architect --name otherin a workspace that already hasmain.other.afx send architect "test".other; observedmainin this case.Suggested fix
architectfrom a sender that is a builder must resolve throughspawned_by_architectand must never fall back to themain-else-first rule. If the column is null, fail loudly rather than guessing — a message delivered to the wrong architect is worse than one that errors.architect:<name>from a builder must be rejected unless<name>equalsspawned_by_architect, which is the documented behaviour.Found while running two architects (
main,uiv2) against separate builders incodev-1455.