Skip to content

v0.4.9: a bash call that ends, and an abort that aborts

Choose a tag to compare

@matAtWork matAtWork released this 24 Aug 19:07
· 126 commits to main since this release

What's Changed

  • #49 — bash: kill the process group, complete on exit; bound an aborted turn in core by @matAtWork
  • A patch release: two filed defects with one shared cause, a third found in the same function, two new bounds, and a core backstop. Harness packages now move in lockstep — see Versioning.

Full Changelog: v0.4.8...v0.4.9


The defect

bash -c forks each pipeline stage as its own process, and plugins/bash got both halves of that wrong.

  • #47 — abort and timeout signalled the direct child only, with no detached and therefore no process group to signal. find / … | head -5 lost its shell to the SIGTERM and left find traversing the filesystem, reparented to init.
  • #48 — completion hung off 'close', which needs the process to have exited and every stdio stream to have reached EOF. The orphan inherited stdout, so the event stream never terminated.

Individually each is a leak. Together the turn is unrecoverable: the session sits at "working" for ever while every abort reports success, because the abort worked and the tool call is simply unreachable. Measured before fixing — 'exit' at 14ms, 'close' at 5021ms behind a five-second orphan.

A third bug in the same function, unfiled: a signal-killed script gives code === null, which the success arm read as exit code 0, so a timeout kill and an abort both reported a clean run. docker-bash carried it too and is fixed with it.

What changed

  • Own process group (POSIX; Windows keeps the direct-child kill), every stop signalling the negative pid, SIGTERM → SIGKILL after a grace.
  • 'exit' is authoritative for completion. 'close' still wins when it arrives, since it means the output is complete; otherwise an idle drain window ends the call and says so in stderr rather than reading a pipe nothing waits for.
  • A kill is reported as a kill, naming the reason.
  • Two bounds for an unattended host, which has no operator to restart it — both defaults rather than limits. timeout defaults to ten minutes, and combined stdout+stderr to 1000000 bytes via a new maxOutputBytes param; either can be raised per call. A bound the caller cannot lift is a ceiling on what the tool can be used for rather than a safety net: the only party who knows whether 400KB is a verbose build or a yes loop is the one that wrote the command. The numbers are generous because the failure directions are not symmetric — overflowing output is output whose process was killed, so too low kills legitimate work, while runaway protection barely notices, since anything genuinely runaway trips either number in well under a second. docker-bash accepts the same param, overriding its bash_config setting for that one command.
  • core — an aborted turn no longer depends on the tool's cooperation. The runner iterated executors with a bare for await, so any tool that never returns held the turn open for ever. Once aborted, the read is bounded (30s): stop reading, warn, record the call as interrupted, keeping every tool_use paired with a tool_result. Armed only on abort, so a long tool on a healthy turn is never cut short. bash got there through inherited file descriptors; a generator awaiting something that never settles does too.

function-tools also ships an unrelated pending change: the lambda guidance now states that wrapping a single tool call you are not reducing is the pathological case, not merely the expensive one.

Versioning

core, plugin-api, cli and web-bundle are now a changesets fixed group and move together; plugins version independently. Both halves of the harness assumed lockstep already — the boot banner reads any difference between the CLI and the resolved core/plugin-api versions as two physical copies of a host singleton, and about_matbot reports the app's own version — so a core-only release would have printed a false "run a clean reinstall" warning on every boot while the version it reported stayed put.

Published: core, plugin-api, cli, web-bundle at 0.4.9; function-tools at 0.4.9; tool-bash and tool-docker-bash at 0.4.9 (0.4.8 was cut first, then superseded within this release by the maxOutputBytes change above).