archiveOrphanedAgents Migration: Why It Must Run Before Agent Respawning in Munder Difflin
The archiveOrphanedAgents migration is a startup routine that scans the agents table for entries with no live PTY, marks them as archived, and logs the cleanup to prevent duplicate agents and system instability before the respawn mechanism activates.
The archiveOrphanedAgents migration ensures database consistency in the munder-difflin terminal management system by reconciling stale agent records with actual process states before new PTY creation begins. Implemented in src/main/index.ts (lines 865-886), this critical procedure resolves lifecycle bugs documented in CHANGELOG.md (#56-58) where orphaned agents previously caused cost-ledger corruption and circuit-breaker failures.
What the archiveOrphanedAgents Migration Does
The migration performs a targeted cleanup of the agents table during application startup. It executes a database transaction that identifies records where the archived flag is false but the associated PTY (pseudo-terminal) process no longer exists (indicated by pty_id IS NULL).
For each orphaned record found, the migration sets archived to true and outputs a diagnostic log:
// src/main/index.ts – startup migration (lines 865-886)
if (!config.archivedAgentsMigrationRun) {
await db.transaction(async tx => {
const rows = await tx.all<Agent>('SELECT id FROM agents WHERE archived = 0 AND pty_id IS NULL');
for (const {id} of rows) {
await tx.run('UPDATE agents SET archived = 1 WHERE id = ?', id);
console.log('[migration] archived orphaned agent (no live PTY):', id);
}
});
}
This transaction ensures atomicity—either all orphaned agents are archived together, or the database remains unchanged if the migration fails.
Why the Migration Must Run Before Agent Respawning
The agent respawning logic assumes that all existing non-archived agents possess live PTY processes. If orphaned agents remain un-archived, the respawn mechanism treats these stale records as active entities, leading to three critical system failures identified in the source code analysis.
Preventing Cost-Ledger Spam
Dead agents that remain archived: false continue rewriting frozen ledger rows approximately every 30 seconds. The archiveOrphanedAgents migration stops this feedback loop by explicitly flagging dead processes before the respawn logic evaluates agent health.
Stopping Circuit-Breaker Floods
When orphaned agents persist in the database, the circuit-breaker component receives inbox messages from non-existent agents, preventing the breaker from clearing its error state. Archiving these agents severs the communication path to defunct processes.
Eliminating Un-Archived Stale Entries
The respawning code in src/main/agentRespawn.ts checks for missing PTY associations to determine whether to create new terminal processes. Without the migration, the code encounters agents that appear valid but lack live PTYs, causing it to skip necessary respawns or create duplicate entries:
// src/main/agentRespawn.ts (simplified)
if (!agent.ptyId) {
// Safe to create a new PTY because all orphaned agents are already archived
const newPty = await createPtyForAgent(agent.id);
await db.run('UPDATE agents SET pty_id = ?, archived = 0 WHERE id = ?', newPty.id, agent.id);
}
Source Code References
The archiveOrphanedAgents migration implementation spans several key files in the munder-difflin repository:
src/main/index.ts(lines 865-886): Contains the primary migration logic that executes during startup.CHANGELOG.md(line 984): Documents the original bug report (#56-58) motivating the migration.src/main/agentRespawn.ts: Implements the respawning logic that depends on the migration's cleanup having already occurred.src/main/db.ts: Defines the underlying database migration framework usinguser_version-based schema management.
Summary
- The archiveOrphanedAgents migration identifies agent records with dead PTY processes and sets their
archivedflag totrueduring startup. - It must execute before agent respawning to ensure the respawn logic assumes a consistent database state where only live or properly archived agents exist.
- The migration prevents three specific failures: cost-ledger spam, circuit-breaker message floods, and duplicate agent creation.
- Implementation resides in
src/main/index.ts(lines 865-886) and runs automatically unless disabled in configuration.
Frequently Asked Questions
What triggers the archiveOrphanedAgents migration?
The migration runs automatically during application startup when config.archivedAgentsMigrationRun evaluates to false. The system checks this configuration flag in src/main/index.ts before executing the database transaction to archive orphaned agents.
How does the migration prevent duplicate agents?
By setting archived = 1 on records where pty_id IS NULL, the migration ensures that the respawning logic in src/main/agentRespawn.ts does not mistake dead agents for active ones. This prevents the creation of redundant PTY processes for the same logical agent ID.
Where is the archiveOrphanedAgents migration implemented?
The implementation resides in src/main/index.ts at lines 865-886, within the application's startup sequence. The code executes a SQLite transaction that queries for unarchived agents with null PTY references and updates their status accordingly.
What happens if the archiveOrphanedAgents migration is skipped?
If skipped, orphaned agents remain archived: false despite having no live PTY, causing the respawn mechanism to treat them as active. This leads to continued cost-ledger updates from dead processes, persistent circuit-breaker errors from inbox message confusion, and potential duplicate agent entries that corrupt the process registry.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →