fix: prevent stale subagent data from showing in windows

- Reduce getRecentSubagents window from 60 to 15 minutes
- Skip old/completed agents when restoring window states (10 min cutoff)
- Clear old activity data when new agent with same ID is discovered
- Force close existing window for agentId before opening fresh one

Fixes issue where old prompts/input from previous Ralph Loop runs
were displayed when clicking on subagent windows.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
arkon
2026-01-29 12:04:14 +01:00
co-authored by Claude Opus 4.5
parent 5c2d985dce
commit a73f7c3a4f
4 changed files with 22 additions and 7 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ When user says "COM":
1. Increment version in BOTH `package.json` AND `CLAUDE.md`
2. Run: `git add -A && git commit -m "chore: bump version to X.XXXX" && git push && npm run build && systemctl --user restart claudeman-web`
**Version**: 0.1425 (must match `package.json`)
**Version**: 0.1426 (must match `package.json`)
## Project Overview
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "claudeman",
"version": "0.1425",
"version": "0.1426",
"description": "The missing control plane for Claude Code - run 20 autonomous agents with real-time monitoring and session persistence",
"type": "module",
"main": "dist/index.js",
+18 -3
View File
@@ -1792,8 +1792,14 @@ class ClaudemanApp {
addListener('subagent:discovered', async (e) => {
const data = JSON.parse(e.data);
// Clear all old data for this agentId (in case of ID reuse)
this.subagents.set(data.agentId, data);
this.subagentActivity.set(data.agentId, []);
this.subagentToolResults.delete(data.agentId);
// Close any existing window for this agentId (will be reopened fresh)
if (this.subagentWindows.has(data.agentId)) {
this.forceCloseSubagentWindow(data.agentId);
}
this.renderSubagentPanel();
// Find which Claudeman session owns this subagent (by working directory)
@@ -7447,12 +7453,18 @@ class ClaudemanApp {
}
// Restore minimized state, but verify session mapping is correct
// Skip old agents from previous runs to avoid confusion
const cutoffTime = Date.now() - 10 * 60 * 1000; // 10 minutes
for (const [savedSessionId, agentIds] of Object.entries(states.minimized || {})) {
if (Array.isArray(agentIds) && agentIds.length > 0) {
for (const agentId of agentIds) {
const agent = this.subagents.get(agentId);
if (!agent) continue; // Agent no longer exists
// Skip completed or old agents
const agentStartTime = agent.startedAt ? new Date(agent.startedAt).getTime() : 0;
if (agent.status === 'completed' || agentStartTime < cutoffTime) continue;
// Use discovered parentSessionId, or validate saved sessionId exists
const correctSessionId = agent.parentSessionId ||
(this.sessions.has(savedSessionId) ? savedSessionId : null);
@@ -7467,11 +7479,14 @@ class ClaudemanApp {
}
}
// Restore open windows (for non-completed agents only)
// Restore open windows (for recent, non-completed agents only)
const now = Date.now();
const maxAgeMs = 10 * 60 * 1000; // 10 minutes - don't restore windows for old agents
for (const { agentId, position } of (states.open || [])) {
const agent = this.subagents.get(agentId);
// Only restore window if agent exists and is still active/idle (not completed)
if (agent && agent.status !== 'completed') {
// Only restore window if agent exists, is recent, and is still active/idle
const agentAge = agent?.startedAt ? now - new Date(agent.startedAt).getTime() : Infinity;
if (agent && agent.status !== 'completed' && agentAge < maxAgeMs) {
this.openSubagentWindow(agentId);
// Restore position if saved (with viewport bounds check)
if (position) {
+2 -2
View File
@@ -4600,7 +4600,7 @@ NOW: Generate the implementation plan for the task above. Think step by step.`;
scheduledRuns: Array.from(this.scheduledRuns.values()),
respawnStatus,
globalStats: this.store.getAggregateStats(activeSessionTokens),
subagents: subagentWatcher.getRecentSubagents(60), // Last hour of subagent activity
subagents: subagentWatcher.getRecentSubagents(15), // Last 15 min - filter out stale agents from previous runs
timestamp: Date.now(),
};
}
@@ -4630,7 +4630,7 @@ NOW: Generate the implementation plan for the task above. Think step by step.`;
scheduledRuns: Array.from(this.scheduledRuns.values()),
respawnStatus,
globalStats: this.store.getAggregateStats(activeSessionTokens),
subagents: subagentWatcher.getRecentSubagents(60),
subagents: subagentWatcher.getRecentSubagents(15), // 15 min to avoid stale agents
timestamp: Date.now(),
};
}