agent-orchestrator/packages
Harsh Batheja 62d0630d7c fix(pipeline): non-blocking command executor — release engine lock during child runtime
Addresses Greptile P1: command stages held the engine's serialization lock
for their entire execution (up to DEFAULT_COMMAND_TIMEOUT_MS = 10 min).
Every other operation — cancelRun, tick, sibling stages, concurrent
dispatch — queued behind lockTail for that whole window. The agent
executor avoids this with a startStage/pollStage/cancelStage handoff; the
command executor now matches.

**Executor refactor** (`packages/core/src/pipeline/executors/command.ts`):
- New `startStage(input)` spawns the child and returns a
  `RunningCommandStage` handle immediately. Synthetic failures (fork
  refusal / spawn error) produce a handle whose `outcome` is already
  populated and `done` already resolved.
- New `pollStage(handle)` is synchronous: returns the cached outcome or
  `{ status: "running" }`.
- New `cancelStage(handle)` is idempotent: clears timers, SIGTERMs the
  process tree, schedules SIGKILL after `COMMAND_KILL_GRACE_MS`, and
  settles the outcome synchronously so callers awaiting `done` unblock
  without waiting on `close`.
- `CommandExecutorSpawnError` added (mirrors `AgentExecutorSpawnError`)
  for kind-mismatch — the engine catches and dispatches STAGE_FAILED.
- `run()` is now a thin sugar: `startStage(input)` then `await done`.
  Test ergonomics unchanged.

**Engine wiring** (`packages/core/src/pipeline/engine.ts`):
- Added `commandInflight: Map<StageRunId, RunningCommandStage>` (parallel
  to the agent `inflight` map).
- `runCommandStage` now awaits the fast `startStage`, then either
  dispatches an already-settled outcome (refusal / spawn fail) inline OR
  stores the handle in `commandInflight` and returns. **The lock
  releases immediately after spawn.**
- `tick()` polls `commandInflight` after agent stages and dispatches
  STAGE_COMPLETED / STAGE_FAILED on terminal outcomes.
- `CANCEL_STAGE` handler extended to check `commandInflight` and call
  `cancelStage`.

**Tests**:
- pipeline-command-executor: +6 tests for `startStage`/`pollStage`/
  `cancelStage` directly, including idempotency, spawn-fast, sleep-30
  cancellation, kind-mismatch throw, fork-refusal handle.
- pipeline-engine-executors: regression test proving `cancelRun`
  completes in <500ms against two parallel `sleep 5` stages — would have
  timed out in the pre-refactor code.

**Bonus** (round-3 P2 deferred from previous review):
- Added regression test for the stdout-overflow path including stderr in
  the error message (`packages/core/src/pipeline/executors/command.ts`
  line 268). The earlier round-3 fix was correct but had no test
  coverage; now it does.

All 1372 core tests pass. Typecheck clean. Zero lint errors.
2026-05-17 00:51:45 +05:30
..
ao fix(agent-plugins,lifecycle): distinguish indeterminate probe from "not found" + bump ps timeout (closes #1838) (#1839) 2026-05-14 21:50:39 +05:30
cli chore(pipelines): merge main into pipelines (40 commits) — resolve conflicts 2026-05-16 22:13:41 +05:30
core fix(pipeline): non-blocking command executor — release engine lock during child runtime 2026-05-17 00:51:45 +05:30
integration-tests fix(cli): reap daemon children on stop+SIGINT, sweep orphans on start (closes #1848) (#1849) 2026-05-15 03:38:09 +05:30
plugins fix(pipeline): self-review round 2 — config validation, top-level exports, fork tests, stderr cap 2026-05-17 00:05:44 +05:30
web feat(pipeline): v1.2 — command executor + builtin router + builtin compose 2026-05-16 23:00:56 +05:30