Awesome Reviewers

In error/timeout/recovery flows, ensure every failure (including exceptions thrown inside callbacks, stream write failures, and detached promises) is routed through the code path that owns reporting/retries/state invariants—never as an unhandled rejection/exception and never as a silent fallback.

Actionable standards: 1) Catch exceptions in async callback chains

2) Wrap “stop/kill” paths so shutdown failures can’t escape

3) Handle stream-side async errors (EPIPE/Eof) explicitly

4) Clear or cancel timers on spawn/initialization failure

5) Never leave detached promises unhandled

6) Keep telemetry side-effects non-interrupting

7) Classify retries/recovery intentionally

Example pattern (spawn + attach failure routing):

export function spawnSandbox(config: Config): ChildProcess {
  const handle = new SandboxedProcess();
  void loadSandbox()
    .then((sandboxed) => {
      try {
        handle.attach(sandboxed); // may throw
      } catch (e) {
        handle.fail(e instanceof Error ? e : new Error(String(e)));
      }
    })
    .catch((error) => {
      const reason = error instanceof Error ? error.message : String(error);
      handle.fail(new Error(`Couldn't keep this command inside project: ${reason}`));
    });
  return handle as unknown as ChildProcess;
}

Example pattern (stdin write error absorption):

child.stdin?.on('error', (err) => {
  // Record/annotate, but do not let it crash the host process.
  Logger.debug(`stdin write failed: ${(err as Error).message}`);
});

These rules directly prevent the recurring failure modes seen in the discussions: unhandled rejections/uncaught exceptions, incorrect or silent fallbacks after initialization/settings reads, and retry/recovery decisions that don’t match the error semantics.