Skip to content

v0.38.6

Choose a tag to compare

@github-actions github-actions released this 08 Nov 20:51
4e7a414

Bug fixes. The first start after upgrading reinstalls 18 harnesses once: see "Upgrading" below.

Upgrading

  • The harnesses installed from npm or PyPI (Claude Code, Qwen Code, Gemini CLI, Cline, Codex, Pi, MiMo Code, MiniMax Code, Aider, the Qoder SDK, CheetahClaws, OpenHands, nanobot, DeepSeek Harness, Hermes, OpenSquilla, System One and Agent Zero) are reinstalled once, at the first start after the upgrade, from their new locks. That took 8 minutes on the amd64 host we measured. Later starts install nothing.
  • If the network fails during that start, a harness it couldn't reinstall is reported as not installed and is tried again at the next start.
  • The npm harnesses now live in /data/agent-tools/npm/<name> instead of /data/agent-tools/lib/node_modules; the old trees are removed as each one is reinstalled.
  • HR_QODER_SHA256, HR_CHEETAHCLAWS_SHA256, HR_OPENSQUILLA_SHA256 and HR_MINIMAX_SHA256 are no longer read. A version override (HR_*_VERSION) installs without a lock, as before, and its stamp and a start-time warning say it is unverified.

What was wrong

  • A harness's own dependencies were not pinned (#652, #653, #623, thanks @eric-epsilla). 0.38.5 pinned each harness's own version, but the packages under it were resolved within upstream's ranges at install time, and npm ran every package's install script as root.
    • Every npm and PyPI harness now installs from a lock committed in the image: each package of its tree by version and by the digest of its file, checked at install. A file that differs, or a package the lock doesn't name, fails the install.
    • npm installs run with --ignore-scripts. The one install script that still runs is Claude Code's own, which links its native binary from a package the lock already holds. MiniMax Code's SQLite binding, which its install script used to download unchecked, is fetched and checked against a digest committed in the image.
    • PyPI installs take wheels only. The few packages that publish no wheel are named per harness and built against a locked build backend.
    • The locks hold the versions the previous release installed, so no harness's behaviour should change.
    • scripts/lock-pypi.sh and scripts/lock-npm.sh regenerate a lock. Some locked versions carry published advisories; a round of version updates, each with real tasks, comes next.
  • A refused key named the wrong vendor (#650). On a custom connection, a refused key read "Your tokenrouter key was refused". It now names the vendor you connected.

Checked

On 0.38.6-rc.1, on an existing volume upgraded from 0.38.5:

  • The upgrade reinstalled the 18 harnesses from their locks in 8 minutes with no warning. Each stamp names its lock, and the old npm trees were removed.
  • Nothing under the harness tools folder is writable by anyone but root. An unprivileged user can't write into a harness or replace a command, and every moved command answers its version as that user.
  • Real tasks on every changed harness, through the console: a first turn, a follow-up, a switch to another model and back, a file the task must produce, and a sandbox recycled and recalled. All five passed on the 16 that take a text task (all but System One and Qoder).
    • Pi's recall answer and Aider's file task each missed once on gpt-5.4-mini. Pi's session still held its history and passed all five on a re-run; Aider passed all five on Gemini Flash Lite.
    • System One completed its built-in order desk in 6 actions.
    • The Qoder SDK created and deleted an environment and a vault on Qoder's API. A Qoder model turn needs a Qoder plan with enabled models, which the test account no longer has.
  • A plugin's skill and its stdio MCP tool were each used on all 16 changed harnesses the plugin check covers. Aider used them on Claude Haiku 5.5 and missed both on gpt-5.4-mini.
  • On a fresh volume, the release gate installed all 30 harnesses on amd64 and arm64, a second start installed and warned about nothing, and the credential canary passed.
  • Every hash in every lock matched the file PyPI or npm published for that exact version, and the two direct downloads matched their bytes.
  • The gateway and runner suites pass on the release tree with no failure that main doesn't also have.
  • The release's tree is identical to the candidate's.

Full Changelog: v0.38.5...v0.38.6