debug: add PTY spawn diagnostics for Session: None investigation
When an agent CLI exits without creating a session, we now log: - Number of prior sessions and total session log bytes - Child process exit status (exit code or signal) - Explicit SESSION NONE warning with context This will help diagnose whether the fatal runtime error (output.write assertion) correlates with accumulated sessions, budget exhaustion, or something else. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -209,7 +209,22 @@ fn run_agent_pty_blocking(
|
|||||||
cmd.env_remove("CLAUDECODE");
|
cmd.env_remove("CLAUDECODE");
|
||||||
cmd.env_remove("CLAUDE_CODE_ENTRYPOINT");
|
cmd.env_remove("CLAUDE_CODE_ENTRYPOINT");
|
||||||
|
|
||||||
slog!("[agent:{story_id}:{agent_name}] Spawning {command} in {cwd} with args: {args:?}");
|
// Count existing session files for this worktree to detect budget exhaustion.
|
||||||
|
let session_dir = format!(
|
||||||
|
"/home/huskies/.claude/projects/-workspace--huskies-worktrees-{}/",
|
||||||
|
story_id.replace('_', "-").replace('.', "-")
|
||||||
|
);
|
||||||
|
let session_count = std::fs::read_dir(&session_dir)
|
||||||
|
.map(|d| d.filter(|e| e.as_ref().map(|e| e.path().extension().is_some_and(|ext| ext == "jsonl")).unwrap_or(false)).count())
|
||||||
|
.unwrap_or(0);
|
||||||
|
let session_bytes: u64 = std::fs::read_dir(&session_dir)
|
||||||
|
.map(|d| d.filter_map(|e| e.ok()).filter(|e| e.path().extension().is_some_and(|ext| ext == "jsonl")).filter_map(|e| e.metadata().ok()).map(|m| m.len()).sum())
|
||||||
|
.unwrap_or(0);
|
||||||
|
|
||||||
|
slog!(
|
||||||
|
"[agent:{story_id}:{agent_name}] Spawning {command} in {cwd} with args: {args:?} \
|
||||||
|
(prior_sessions={session_count}, session_log_bytes={session_bytes})"
|
||||||
|
);
|
||||||
|
|
||||||
let mut child = pair
|
let mut child = pair
|
||||||
.slave
|
.slave
|
||||||
@@ -429,7 +444,19 @@ fn run_agent_pty_blocking(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let _ = child.kill();
|
let _ = child.kill();
|
||||||
let _ = child.wait();
|
let wait_result = child.wait();
|
||||||
|
match &wait_result {
|
||||||
|
Ok(status) => {
|
||||||
|
slog!(
|
||||||
|
"[agent:{story_id}:{agent_name}] Child exited: {status:?}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
slog!(
|
||||||
|
"[agent:{story_id}:{agent_name}] Child wait error: {e}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Wait for the reader thread to finish so it releases the cloned PTY
|
// Wait for the reader thread to finish so it releases the cloned PTY
|
||||||
// master fd before we return. Without this, the next PTY spawn for the
|
// master fd before we return. Without this, the next PTY spawn for the
|
||||||
@@ -438,6 +465,17 @@ fn run_agent_pty_blocking(
|
|||||||
slog!("[agent:{story_id}:{agent_name}] Reader thread panicked: {e:?}");
|
slog!("[agent:{story_id}:{agent_name}] Reader thread panicked: {e:?}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Log whether session was created — Session: None indicates CLI died
|
||||||
|
// before emitting any events (possible causes: rate limit, budget
|
||||||
|
// exhaustion, PTY write failure, CLI crash).
|
||||||
|
if session_id.is_none() {
|
||||||
|
slog_warn!(
|
||||||
|
"[agent:{story_id}:{agent_name}] SESSION NONE: CLI exited without creating a session. \
|
||||||
|
Check for 'fatal runtime error' in agent logs. \
|
||||||
|
prior_sessions={session_count}, session_log_bytes={session_bytes}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
slog!(
|
slog!(
|
||||||
"[agent:{story_id}:{agent_name}] Done. Session: {:?}",
|
"[agent:{story_id}:{agent_name}] Done. Session: {:?}",
|
||||||
session_id
|
session_id
|
||||||
|
|||||||
Reference in New Issue
Block a user