Problem
All sessions remain permanently at in_progress status in the database. The handleSessionEnd() function in hookDBBridge.js (which updates status = 'completed') is dead code — the Agent SDK does not emit SessionEnd or Stop hooks in programmatic query() mode.
Evidence
- 54K-line production SSE stream log (
WTF-IS-THIS-THINKING.md): 259 hook events, zero SessionEnd or Stop events
- SDK docs explicitly mark
SessionEnd as "TypeScript only as SDK callback" (CLI mode only)
- All 16 production session manifests contain
agent_stop events but never session_end
Root Cause
handleSessionEnd() in hookDBBridge.js (lines 615-651) is properly wired:
- Registered in
sdkHooksConfig (sdkHooks.js line 2363)
- Listed in
HOOKS_TO_BRIDGE (hookDBBridge.js line 1155)
- Routed in
persistHookEvent switch (hookDBBridge.js line 710)
But the SDK never triggers it in query() mode. The only two code paths that update sessions.status to completed are:
handleSessionEnd() — never called (dead code in query mode)
archiveOldSessions() — only transitions completed → archived
Fix
Commit: 34adc52 on deploy-week-4-infrastructure
Added status = 'completed' to the existing persistFinalEventMetadata() UPDATE query, which already fires server-side (fire-and-forget) after stream completion:
-- Before:
UPDATE sessions SET metadata = ..., updated_at = NOW()
WHERE session_key = $1
-- After:
UPDATE sessions SET metadata = ..., status = 'completed', updated_at = NOW()
WHERE session_key = $1 AND status = 'in_progress'
Safety
- Fires only AFTER
agentQuery stream is fully consumed and shouldContinue = false
- Fire-and-forget with
.catch() — cannot propagate errors or affect the stream
send(finalPayload) already sent to client before this runs
- Nothing in the codebase polls
sessions.status to terminate processes
- Idempotent:
AND status = 'in_progress' guard prevents double-updates
Manual corrections applied
2026-03-13-1773426614 → completed
2026-03-07-1772900028 → completed
Future consideration
- Add
status = 'failed' update in the server error/catch path (~line 1706) so errored sessions don't stay at in_progress either
handleSessionEnd() and related code (persistSessionMetrics, persistWaveData, persistPhaseSummary, refreshSessionSummaryView) remain dead code in query mode — could be called from persistFinalEventMetadata to rescue that bookkeeping
🤖 Generated with Claude Code
Problem
All sessions remain permanently at
in_progressstatus in the database. ThehandleSessionEnd()function inhookDBBridge.js(which updatesstatus = 'completed') is dead code — the Agent SDK does not emitSessionEndorStophooks in programmaticquery()mode.Evidence
WTF-IS-THIS-THINKING.md): 259 hook events, zeroSessionEndorStopeventsSessionEndas "TypeScript only as SDK callback" (CLI mode only)agent_stopevents but neversession_endRoot Cause
handleSessionEnd()inhookDBBridge.js(lines 615-651) is properly wired:sdkHooksConfig(sdkHooks.js line 2363)HOOKS_TO_BRIDGE(hookDBBridge.js line 1155)persistHookEventswitch (hookDBBridge.js line 710)But the SDK never triggers it in
query()mode. The only two code paths that updatesessions.statustocompletedare:handleSessionEnd()— never called (dead code in query mode)archiveOldSessions()— only transitionscompleted→archivedFix
Commit:
34adc52ondeploy-week-4-infrastructureAdded
status = 'completed'to the existingpersistFinalEventMetadata()UPDATE query, which already fires server-side (fire-and-forget) after stream completion:Safety
agentQuerystream is fully consumed andshouldContinue = false.catch()— cannot propagate errors or affect the streamsend(finalPayload)already sent to client before this runssessions.statusto terminate processesAND status = 'in_progress'guard prevents double-updatesManual corrections applied
2026-03-13-1773426614→completed2026-03-07-1772900028→completedFuture consideration
status = 'failed'update in the server error/catch path (~line 1706) so errored sessions don't stay atin_progresseitherhandleSessionEnd()and related code (persistSessionMetrics,persistWaveData,persistPhaseSummary,refreshSessionSummaryView) remain dead code in query mode — could be called frompersistFinalEventMetadatato rescue that bookkeeping🤖 Generated with Claude Code