Skip to content

afx spawn silently attributes the builder to 'main' when CODEV_ARCHITECT_NAME is absent, even inside another architect's session #1406

Open

Description

@amrmelsayed

Observed (2026-08-11, live)

The streamdeck architect ran afx spawn 1403 --protocol air from its own architect session. Tower registered builder-air-1403 with owner main; the builder's reports landed on main's terminal, and main had to ask who owned it.

Mechanism

packages/codev/src/agent-farm/commands/spawn.ts:26-39: the spawning architect's name is read once at module load from CODEV_ARCHITECT_NAME (Spec 755) and silently falls back to 'main' when the var is empty. In the reporting session the var WAS empty, while afx whoami run from the very same shell resolved the identity correctly (type: architect, name: streamdeck), so Tower-side resolution works where the env-var path failed. Shells spawned by tools/subprocesses inside an architect terminal do not reliably carry the injected var.

Consequences of misattribution

  • Builder reports route to the wrong architect's terminal.
  • The builder's afx send architect affinity points at the wrong architect, and Tower's spoofing check then actively blocks the builder from addressing its real spawner via architect:<name>.
  • Review/gate flow lands on an architect who doesn't own the work.

Suggested fix

Resolve the spawning architect the way afx whoami does (Tower PID/terminal lookup), with the env var as a fast path, and keep the 'main' fallback only for genuinely-outside-any-architect-terminal invocations. At minimum: when falling back to 'main', print a visible warning naming the fallback, so misattribution is caught at spawn time instead of at first report.

Workaround until fixed

Prefix spawns with the explicit var: CODEV_ARCHITECT_NAME=<name> afx spawn ….

Related: #1391/#1392 (workspace registration edges), #1393 (gate-relay semantics); same family of multi-architect attribution seams.

Activity

  1. amrmelsayed commented on Aug 12, 2026

    @amrmelsayed
    CollaboratorAuthor

    Second recurrence (2026-08-12): builder pir-1425 was spawned by the streamdeck architect, but its afx send architect reports route to main — including a message that says "per your two hardware-section fixes" referring to fixes the streamdeck architect made, leaving no doubt about the intended recipient. Same silent owner-fallback as the air-1403 case (2026-08-11). Coordination cost is real: main must recognize the misattribution from message content and manually forward each gate-shaped report. Possibly relevant: the workspace's architects were respawned via afx workspace add-architect after the 08-12 Tower restart wiped registrations (#1176 datapoint, comment 5264008797) — if owner attribution keys off a registration row that changed identity across the respawn, that would explain both occurrences following restarts.

  2. amrmelsayed commented on Aug 15, 2026

    @amrmelsayed
    CollaboratorAuthor

    Prioritisation case: this stops being cosmetic the moment the Stream Deck gains an architect-summon key (#1463, now in flight).

    Today this bug costs a status line and some forwarding. Every builder spawned by a sibling architect routes its afx send architect reports to main instead of its owner, so main reads each one, recognises it from content, and forwards it. Annoying, self-correcting, invisible to anyone outside the two architects involved.

    #1463 changes the consequence rather than the frequency. It puts a physical key on the deck whose press summons an architect. Under mis-attribution the press summons the wrong human's agent, silently, because the deck faithfully renders whatever attribution it was handed. A wrong status line is a cosmetic defect; a wrong escalation target is a correctness defect with a hardware surface.

    Two independent routes now produce the same wrong outcome, which is what makes this worth pulling forward rather than leaving in the registry-integrity cluster:

    1. Spawn attribution (this issue). The owner recorded at spawn silently falls back to main, so the builder's reports — and anything keyed off its owner — point at the wrong architect from birth.
    2. Registry visibility (afx: reconcileTerminalSessions doesn't self-repair orphaned architect registry rows (inverse of #1150) #1176 and its siblings). OverviewData.architects is built by liveArchitects() (tower-routes.ts:1077-1090), which walks the registry and skips any architect whose terminal session Tower cannot currently see (if (!session) continue). It is a visibility view, not an existence view. Three times this week that view has been wrong: the 2026-08-12 Tower restart dropped every architect and builder registration; a builder row vanished during normal operation with no restart; and a live registration behind a dead PTY is a shape neither afx status nor this list can distinguish. A summon key resolving its fallback from that list inherits every one of those.

    Either route alone is arguable. Both routes converging on "the deck summons the wrong architect" — one from how ownership is recorded, one from how presence is observed — is the argument for treating this as a prerequisite of #1463 rather than a follow-up to it.

    Mitigations already going into #1463, so this issue is not the only line of defence: an explicit unavailable face when the live list is empty (a silent dead press is the worst outcome, since the deck's promise is that a press does something), exact-name resolution preferred over positional fallback with positional as last resort only, and a hardware test case confirming the rendered face visibly names the architect it will summon — the rendered name being the only safeguard a human has against positional fallback picking a sibling.

    Raised jointly by the streamdeck architect (who owns #1463) and main (who owns this issue and the registry surface). Prioritisation is the owner's call; this comment exists so the decision is made against the hardware consequence rather than against the status line.

  3. amrmelsayed commented on Aug 26, 2026

    @amrmelsayed
    CollaboratorAuthor

    Fresh instance, 2026-08-26T01:59Z (frequency data — this class is now biting roughly weekly per the vscode architect):

    • Mailbox row 536759ba-0303-4b5d-91ed-29af c89f2077 (codev workspace; space inserted to avoid autolink, remove to query): a message unmistakably authored by builder-pir-1552 (body opens "Project 1552 — flagging a gap Amr hit while testing… which you fenced off from me", i.e. addressed to its spawning architect) was delivered to_agent=main, terminal 1d52cb40 (main's), NOT to vscode.
    • afx status at the same time lists builder-pir-1552 Owner: vscode.
    • The vscode architect attests the message never reached it ("those two builder questions never reached me").
    • Additional anomaly beyond this issue's scope: the row records from_agent=architect, not builder-pir-1552 — the sender identity was also lost/rewritten, which is the same transport-metadata-weaker-than-the-weight-on-it class as the Mailbox: delivered-message wrappers carry no recipient field — deliveries are not self-attesting (rescoped from refuted misrouting report) #1543 wrapper mislabel. Compare a healthy row from another workspace the same day where a builder→architect message correctly recorded from_agent=builder-pir-4421.

    Consequence: two decision-shaped questions (a scope/fence confirmation and a follow-up-tracking question) landed on the wrong architect. Handled by answer-and-forward this time at no cost, but the failure mode is a builder's gate-adjacent question silently reaching an architect without the lane context to answer it.

    Cross-filed as captured repro data on #1544 (registry divergence, repro-first): the status registry (owner=vscode) and the affinity routing (delivered to main) disagreed about the same builder at the same moment, with the mailbox row as the instrument.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/towerArea: Tower server / agent farm CLI

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions