Problem
Inverse of #1150. When Tower boot reconciliation finds a live type='architect' terminal_sessions row whose matching architects registry row is missing, it reconnects the terminal (correctly — the process is alive) but does NOT re-create the registry row. The architect appears to work for the current Tower lifetime, then silently fails in two ways:
- Doesn't survive
afx workspace stop/start: launchInstance's reconciliation loop iterates getArchitects(workspacePath) to respawn siblings. No row → no respawn → architect disappears on next start with no warning.
- Loses conversation on in-process crash:
session-manager.ts's auto-restart bakes --resume <session_id> from the architect row. No row → no stored session id → fresh spawn without resume → new conversation, prior context lost.
Both failures are silent to the user — the architect worked, then didn't, with no diagnostic pointing at the missing registry row.
How the state gets orphaned:
Origin
Follow-up filed by the pir-1150 builder during its dev-approval discussion. #1150 fixes the "row survives, terminal doesn't → zombie respawn from stale row" direction. This issue fixes the mirror direction: "terminal survives, row doesn't → silent loss on next lifecycle event."
Root cause hypothesis
reconcileTerminalSessions in packages/codev/src/agent-farm/servers/tower-terminals.ts reconnects each live type='architect' terminal but assumes the accompanying architect registry row exists. There is no cross-check that verifies the row is present or a self-repair path that re-creates it.
Fix sketch
In reconcileTerminalSessions Phase 1 (tower-terminals.ts), when reconnecting a type='architect' terminal_sessions row:
- Check
getArchitectByName(workspacePath, session.role_id) — if a row exists, no action needed
- If missing, re-create it via
setArchitectByName(workspacePath, session.role_id, null) (or the appropriate helper)
workspace_path: from the terminal_sessions row
name: from role_id (which is how architects register their name)
session_id: null (backfills at next restart-bake once the process crashes-then-recovers and a fresh session id is minted)
- Log INFO: "self-repaired architect registry row for
<workspace>/<name> (was orphaned from terminal_sessions)"
This is the inverse operation of #1150's fix: #1150 prunes registry rows without live terminals; this issue re-creates registry rows for terminals that survived.
Scope
packages/codev/src/agent-farm/servers/tower-terminals.ts — reconcileTerminalSessions Phase 1 self-repair branch
- Tests: simulate orphaned architect terminal → verify registry row created on reconcile
- No CLI changes, no HTTP endpoint changes, no schema changes
Related
Suggested label: area/tower.
Problem
Inverse of #1150. When Tower boot reconciliation finds a live
type='architect'terminal_sessionsrow whose matchingarchitectsregistry row is missing, it reconnects the terminal (correctly — the process is alive) but does NOT re-create the registry row. The architect appears to work for the current Tower lifetime, then silently fails in two ways:afx workspace stop/start:launchInstance's reconciliation loop iteratesgetArchitects(workspacePath)to respawn siblings. No row → no respawn → architect disappears on next start with no warning.session-manager.ts's auto-restart bakes--resume <session_id>from the architect row. No row → no stored session id → fresh spawn without resume → new conversation, prior context lost.Both failures are silent to the user — the architect worked, then didn't, with no diagnostic pointing at the missing registry row.
How the state gets orphaned:
removeArchitectsucceeds at killing the shellper but fails at deletingterminal_sessions— inverse of afx: removed sibling architect resurrects after Tower recovery — reconciliation trusts persisted row without liveness check #1150, which was DB delete succeeding but shellper survival)synchronous = NORMAL)Origin
Follow-up filed by the pir-1150 builder during its dev-approval discussion. #1150 fixes the "row survives, terminal doesn't → zombie respawn from stale row" direction. This issue fixes the mirror direction: "terminal survives, row doesn't → silent loss on next lifecycle event."
Root cause hypothesis
reconcileTerminalSessionsinpackages/codev/src/agent-farm/servers/tower-terminals.tsreconnects each livetype='architect'terminal but assumes the accompanying architect registry row exists. There is no cross-check that verifies the row is present or a self-repair path that re-creates it.Fix sketch
In
reconcileTerminalSessionsPhase 1 (tower-terminals.ts), when reconnecting atype='architect'terminal_sessions row:getArchitectByName(workspacePath, session.role_id)— if a row exists, no action neededsetArchitectByName(workspacePath, session.role_id, null)(or the appropriate helper)workspace_path: from the terminal_sessions rowname: fromrole_id(which is how architects register their name)session_id: null (backfills at next restart-bake once the process crashes-then-recovers and a fresh session id is minted)<workspace>/<name>(was orphaned from terminal_sessions)"This is the inverse operation of #1150's fix: #1150 prunes registry rows without live terminals; this issue re-creates registry rows for terminals that survived.
Scope
packages/codev/src/agent-farm/servers/tower-terminals.ts—reconcileTerminalSessionsPhase 1 self-repair branchRelated
Suggested label:
area/tower.