35 Commits

Author SHA1 Message Date
stefano 0bea1c590d fix: review feedback — signal handling, cancel race, stderr consistency
Address issues found by code review:

1. Bug: timeout/signal-killed child reported as 'completed' with exit
   code 0 because close handler ignored the signal parameter. Now
   treats any signal termination as timed_out.

2. Bug: cancelled job gets overwritten by watcher on child exit. The
   watcher now re-reads the job file before writing and skips if the
   status has been changed to 'cancelled'.

3. Inconsistency: watcher path skipped stderr noise filtering. Added
   filterStderrNoise to the watcher (duplicated from execute.ts to
   keep the watcher self-contained).

4. getJobResult now guards against missing result field instead of
   using non-null assertion.
2026-05-20 14:17:28 -05:00
stefano 33c898ff9a fix: use companion watcher process for async job completion
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.
2026-05-20 14:08:44 -05:00
stefano 017eb1b410 fix: pipe and close stdin for codex to prevent hang on stdin read
When codex exec receives a prompt as a positional argument, it still
tries to read additional input from stdin (prints 'Reading additional
input from stdin...'). With stdio stdin set to 'ignore' or default,
codex blocks indefinitely waiting for stdin that never comes.

Fix: use stdio ['pipe', 'pipe', 'pipe'] and immediately close stdin
via child.stdin.end() in both execute.ts (sync) and jobs.ts (async).
This signals EOF to codex so it proceeds with the positional prompt.
2026-05-20 13:47:32 -05:00
stefano afac143cb3 fix: filter codex ReasoningSummary stderr noise on exit code 0
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
2026-05-20 13:37:21 -05:00
stefano 7b886a7b33 feat(M4): Documentation & Final Integration 2026-05-19 22:49:05 -05:00
stefano 6655e2e1e8 feat(S-401): Update SKILL.md for async-first usage 2026-05-19 22:42:16 -05:00
stefano 591829369c feat(M3): Async CLI Integration 2026-05-19 22:22:54 -05:00
stefano 51f978db4c feat(S-303): Update --help output and add CLI integration smoke tests 2026-05-19 22:04:19 -05:00
stefano 4fe99b8c57 feat(S-302): Test-drive and implement job lifecycle subcommands 2026-05-19 22:00:11 -05:00
stefano 62840b908e feat(S-301): Test-drive and implement async default for run and dispatch 2026-05-19 21:42:58 -05:00
stefano e7b01612c8 feat(M2): Background Job Manager 2026-05-19 20:29:35 -05:00
stefano 3b9ed0cc38 feat(S-202): Test-drive and implement src/jobs.ts (write) 2026-05-19 20:17:15 -05:00
stefano abf7726071 feat(S-201): Define job types and storage interfaces 2026-05-19 19:58:48 -05:00
stefano bcddb42608 feat(M1): Codex Reliability Fix 2026-05-19 19:54:27 -05:00
stefano 1983dd82e7 feat(S-104): Add stderr-length and exit-code correlation diagnostics 2026-05-19 19:51:10 -05:00
stefano 94389df6f1 feat(S-103): Test-drive and implement --debug diagnostic mode 2026-05-19 19:48:40 -05:00
stefano dc3fe8d6eb feat(S-102): Test-drive and implement --timeout flag, config layering, and default in 2026-05-19 19:39:46 -05:00
stefano 476dd317b3 feat(S-101): Extend types.ts with ExecResult metadata, timeout config shape, and debu 2026-05-19 19:20:53 -05:00
stefano e523b34d1b fix: codex uses --yolo not --full-auto 2026-05-18 19:15:59 -05:00
stefano fd1d2c3e92 fix: invoke all CLI clients in full-access/yolo mode
- codex: --full-auto
- claude: --dangerously-skip-permissions
- opencode: --dangerously-skip-permissions
2026-05-18 19:15:04 -05:00
stefano d3aa92be0d fix: use 'opencode run' instead of bare prompt for OpenCode client 2026-05-18 19:06:34 -05:00
stefano 4f59258b20 feat(M5): CLI Integration 2026-05-18 18:39:33 -05:00
stefano 7fa959d115 feat(S-401): Test-drive and implement src/dispatch.ts 2026-05-18 18:14:13 -05:00
stefano a2cfa7027e feat(M3): Direct Execution 2026-05-18 18:11:45 -05:00
stefano a99041f910 feat(S-301): Test-drive and implement src/execute.ts 2026-05-18 18:01:51 -05:00
stefano 82fcd3363c feat(M2): Client Detection & Configuration 2026-05-18 17:53:47 -05:00
stefano 185083ace8 merge S-203 into M2 2026-05-18 17:51:44 -05:00
stefano f3458734d4 feat(S-203): Test-drive and implement src/config.ts 2026-05-18 17:51:44 -05:00
stefano 2642c280a2 feat(S-202): Test-drive and implement src/detect.ts 2026-05-18 17:51:07 -05:00
stefano 4629fe17de feat(M1): Project Scaffold 2026-05-18 17:45:27 -05:00
stefano 162517c0e0 feat(S-103): Create scripts/ai-cli-dispatch launcher 2026-05-18 17:40:10 -05:00
stefano 47f555a367 feat(S-201): Create src/types.ts with shared type definitions 2026-05-18 17:38:35 -05:00
stefano 445d9bfdee merge S-102 into M1 2026-05-18 17:36:31 -05:00
stefano 50928313a1 feat(S-102): Create package.json, tsconfig.json, .gitignore 2026-05-18 17:36:31 -05:00
stefano fb01334273 feat(S-101): Create SKILL.md with YAML frontmatter 2026-05-18 17:36:21 -05:00