The async startJob previously relied on Node.js event listeners in the
CLI process to capture child output and finalize the job file. But the
CLI process exits immediately after returning the job ID, killing the
event loop before the close handler fires — leaving jobs stuck at
'running' forever.
Fix: startJob now spawns a companion watcher process (job-watcher.ts)
that is itself detached and outlives the CLI. The watcher:
- Spawns the actual client (codex/claude/opencode)
- Captures stdout/stderr
- Writes the final job record to disk on child exit
- Has its own 10-minute timeout safety net
The CLI returns the job ID immediately. The watcher independently
finalizes the job. The CLI no longer needs to stay alive.
Also updates tests to mock the watcher spawn via injectable
spawnWatcher option.
Codex writes informational ERROR messages about ReasoningSummaryDelta
to stderr even on successful execution (exit code 0). The OpenClaw
agent misinterprets this non-empty stderr as a failure.
- Add filterStderrNoise() to strip known codex noise patterns from
stderr when exit code is 0
- Preserve raw stderr in DebugInfo.rawStderr when --debug is active
- Add 5 new tests covering noise filtering, preservation on failure,
debug raw output, and non-codex client passthrough