Skip to content
3 min read · 594 words

Interface: RunShellCommandCompletion ​

Defined in: src/batteries/sandbox/tool.ts:57

What one run_shell_command invocation actually did.

Remarks ​

The structured completion for createRunShellCommandTool's onCompletion callback. Deliberately issued once per invocation, on EVERY terminal outcome — a clean exit, a non-zero exit, a timeout, a kill, a gate/approval denial, and an enforcer throw all settle this — because the audit seam exists precisely so a denied or killed command is not indistinguishable from a successful one.

Field rules:

  • exitCode is the child's real exit status, or null when the command never ran (a gate denial, a path refusal, a spawn failure) or its exit status is unknowable.
  • failed is true for every outcome that is not a successful zero exit, INCLUDING denials, timeouts, killed children, enforcer errors, and a per-call policy function that failed. exitCode !== 0 implies failed, and so do outcomes with exitCode: null.
  • timedOut marks the timeout_seconds deadline firing (exitCode is then null or the killed child's status, depending on whether completed settled).
  • killedBy names the signal that ACTUALLY terminated the child instead of letting it exit, read from the real child settlement (Node's signalCode), e.g. 'SIGKILL' when the enforcer kills the process group on a timeout. Absent when the child exited on its own (a clean exit, a non-zero exit, or a timeout it won by exiting before the kill landed).
  • denied marks a refusal BEFORE the command ran (a gate denial, a path/gate/allow-list refusal) — no child was spawned.
  • diagnostics carries everything the enforcer reported (diagnosticsFor, the [sandbox] denied: … lines) plus, for a handler failure, the thrown value's message — including a per-call policy function that threw or rejected, which fires this completion before the error surfaces. Empty usually.
  • artifactRef names the returned SpooledArtifact's correlation id — the same id the spool store keyed the stream under — so an audit sink can join the completion to the artifact. It is present whenever the run reached the enforcer, including an enforcer throw (its id still keys any diagnostics recorded for that run). It is absent for the very first refusals (those throw before any stream exists) and a throwing per-call policy (it fails before a stream is opened).

The tool's own return type is UNCHANGED: it still resolves to the artifact. This type travels only through the callback, so existing consumers keep compiling.

Properties ​

PropertyModifierTypeDescriptionDefined in
artifactRef?readonlystringThe spool store correlation id backing the invocation's returned artifact, when one exists.src/batteries/sandbox/tool.ts:71
denied?readonlybooleanWhether the command was refused before spawning (gate denial, path refusal, allow-list).src/batteries/sandbox/tool.ts:67
diagnosticsreadonlyreadonly string[]Enforcer diagnostics ([sandbox] denied: … lines) and, on a handler failure, its message.src/batteries/sandbox/tool.ts:69
exitCodereadonlynumber | nullThe child's real exit status; null when the command never ran or never reported one.src/batteries/sandbox/tool.ts:59
failedreadonlybooleantrue for every non-success outcome, including denials, timeouts, kills, and enforcer throws.src/batteries/sandbox/tool.ts:61
killedBy?readonlystringThe signal that actually killed the child instead of letting it exit, when one did, e.g. 'SIGKILL'.src/batteries/sandbox/tool.ts:65
timedOutreadonlybooleanWhether the timeout_seconds deadline fired and terminated the command.src/batteries/sandbox/tool.ts:63