You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When a builder addresses an architect it isn't allowed to (afx send architect:<name> where <name> isn't the builder's spawning architect), the CLI prints only the opaque code:
The agent/human can't tell why it failed — "no such architect" vs. "not authorized to address that architect" look identical. During Spec 1313 manual testing a builder literally had to guess: "no architect named codex-architect is registered/active (or, since I'm a builder, architect: only works for my own spawning architect)."
Tower does generate a descriptive message for exactly this case — it just never reaches the CLI.
Root cause (verified in code)
Two layers collaborate to drop the detail:
resolveArchitectByName (packages/codev/src/agent-farm/servers/tower-messages.ts) returns a helpful message on the spoofing rejection:
return{code: 'NOT_FOUND',message: addressSpoofingErrorMessage(sender)};// "builder <id> may only address its own spawning architect"
(and a distinct "Architect '<name>' not found in workspace '<ws>'." for a genuinely-missing architect.)
handleSend (packages/codev/src/agent-farm/servers/tower-routes.ts) serializes both fields:
send.ts then throws new Error(result.error) → fatal("NOT_FOUND").
So the descriptive message is produced server-side and thrown away client-side.
Impact
Diagnosability only — no misrouting, no corruption. But it makes a common, legitimate rejection (the builder spoofing guard) hard to understand, especially in multi-architect workspaces.
Suggested fix (one to decide during planning)
Preferred: when the response carries both, surface the human-readable message (optionally as "<message> (<code>)") instead of the bare code — either in tower-client.request()'s extraction (json.message || json.error, or combine) or in send.ts's error rendering. Keep the machine code available for programmatic callers.
Confirm the two error strings remain distinguishable: spoofing rejection vs. genuinely-absent architect.
Scope is the afx send / Tower error-surfacing path; addressing/spoofing semantics are correct and should not change (a builder may only address its own spawning architect).
Small, isolated (~error-rendering seam); good BUGFIX candidate.
Problem
When a builder addresses an architect it isn't allowed to (
afx send architect:<name>where<name>isn't the builder's spawning architect), the CLI prints only the opaque code:The agent/human can't tell why it failed — "no such architect" vs. "not authorized to address that architect" look identical. During Spec 1313 manual testing a builder literally had to guess: "no architect named codex-architect is registered/active (or, since I'm a builder, architect: only works for my own spawning architect)."
Tower does generate a descriptive message for exactly this case — it just never reaches the CLI.
Root cause (verified in code)
Two layers collaborate to drop the detail:
resolveArchitectByName(packages/codev/src/agent-farm/servers/tower-messages.ts) returns a helpful message on the spoofing rejection:(and a distinct
"Architect '<name>' not found in workspace '<ws>'."for a genuinely-missing architect.)handleSend(packages/codev/src/agent-farm/servers/tower-routes.ts) serializes both fields:But the client's generic error extraction (
packages/core/src/tower-client.ts,request()) prefers the code over the detail:send.tsthen throwsnew Error(result.error)→fatal("NOT_FOUND").So the descriptive
messageis produced server-side and thrown away client-side.Impact
Diagnosability only — no misrouting, no corruption. But it makes a common, legitimate rejection (the builder spoofing guard) hard to understand, especially in multi-architect workspaces.
Suggested fix (one to decide during planning)
message(optionally as"<message> (<code>)") instead of the bare code — either intower-client.request()'s extraction (json.message || json.error, or combine) or insend.ts's error rendering. Keep the machine code available for programmatic callers.Notes
json.error || json.messageextraction predates it. Surfaced while testing afx send: mailbox-first delivery — persist, gate on rendered-empty, never force-inject #1313 (seeSPIR-1313-testing.md, steps 7/9/14/15).afx send/ Tower error-surfacing path; addressing/spoofing semantics are correct and should not change (a builder may only address its own spawning architect).