revert: roll back v12.3.3 (Issue Blowout 2026)

SessionStart context injection regressed in v12.3.3 — no memory
context is being delivered to new sessions. Rolling back to the
v12.3.2 tree state while the regression is investigated.

Reverts #2080.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alex Newman
2026-04-20 11:59:15 -07:00
parent 708a258d39
commit bfc7de377a
45 changed files with 367 additions and 1249 deletions
+12 -18
View File
@@ -28,7 +28,6 @@ import { sanitizeEnv } from '../supervisor/env-sanitizer.js';
// ensure the worker daemon is up without importing this entire module — which
// transitively pulls in the SQLite database layer via ChromaSync/DatabaseManager.
import { ensureWorkerStarted as ensureWorkerStartedShared } from './worker-spawner.js';
import { RestartGuard } from './worker/RestartGuard.js';
// Re-export for backward compatibility — canonical implementation in shared/plugin-state.ts
export { isPluginDisabledInClaudeSettings } from '../shared/plugin-state.js';
@@ -483,7 +482,7 @@ export class WorkerService {
// Best-effort loopback MCP self-check
getSupervisor().assertCanSpawn('mcp server');
const transport = new StdioClientTransport({
command: process.execPath, // Use resolved path, not bare 'node' which fails on non-interactive PATH (#1876)
command: 'node',
args: [mcpServerPath],
env: sanitizeEnv(process.env)
});
@@ -559,14 +558,12 @@ export class WorkerService {
}
}
// Purge stale failed pending messages to prevent unbounded queue growth (#1957)
// Only remove failures older than 1 hour to preserve recent failures for inspection/retry
// Purge failed pending messages to prevent unbounded queue growth (#1957)
try {
const pendingStore = this.sessionManager.getPendingMessageStore();
const FAILED_MESSAGE_RETENTION_MS = 60 * 60 * 1000; // 1 hour
const purged = pendingStore.clearFailedOlderThan(FAILED_MESSAGE_RETENTION_MS);
const purged = pendingStore.clearFailed();
if (purged > 0) {
logger.info('SYSTEM', `Purged ${purged} stale failed pending messages (older than 1h)`);
logger.info('SYSTEM', `Purged ${purged} failed pending messages`);
}
} catch (e) {
if (e instanceof Error) {
@@ -819,19 +816,17 @@ export class WorkerService {
}
// Fall through to pending-work restart below
}
if (pendingCount > 0) {
// Windowed restart guard: only blocks tight-loop restarts, not spread-out ones (#2053)
if (!session.restartGuard) session.restartGuard = new RestartGuard();
const restartAllowed = session.restartGuard.recordRestart();
session.consecutiveRestarts = (session.consecutiveRestarts || 0) + 1; // Keep for logging
const MAX_PENDING_RESTARTS = 3;
if (!restartAllowed) {
logger.error('SYSTEM', 'Restart guard tripped: too many restarts in window, stopping to prevent runaway costs', {
if (pendingCount > 0) {
// Track consecutive pending-work restarts to prevent infinite loops (e.g. FK errors)
session.consecutiveRestarts = (session.consecutiveRestarts || 0) + 1;
if (session.consecutiveRestarts > MAX_PENDING_RESTARTS) {
logger.error('SYSTEM', 'Exceeded max pending-work restarts, stopping to prevent infinite loop', {
sessionId: session.sessionDbId,
pendingCount,
restartsInWindow: session.restartGuard.restartsInWindow,
windowMs: session.restartGuard.windowMs,
maxRestarts: session.restartGuard.maxRestarts
consecutiveRestarts: session.consecutiveRestarts
});
session.consecutiveRestarts = 0;
this.terminateSession(session.sessionDbId, 'max_restarts_exceeded');
@@ -851,7 +846,6 @@ export class WorkerService {
} else {
// Successful completion with no pending work — clean up session
// removeSessionImmediate fires onSessionDeletedCallback → broadcastProcessingStatus()
session.restartGuard?.recordSuccess();
session.consecutiveRestarts = 0;
this.sessionManager.removeSessionImmediate(session.sessionDbId);
}