Skip to content

v2.16.10

Choose a tag to compare

@nokhodian nokhodian released this 26 Sep 15:11

[2.16.10] — 2026-09-26

Fixed

  • The sandbox-stub crash ledger's reclaim() could wrongly treat a live entry as dead, because alive() was not pid-namespace aware. The Claude SDK sandbox runs every org role under bwrap --unshare-pid, so a role sees its own private pid namespace, not the host's: process.kill(pid, 0) on a pid recorded by another role (or the host daemon) always throws ESRCH, whether that process is alive or not, because the pid simply is not visible from inside the caller's namespace. reclaim() read that ESRCH as "dead" and freed the entry's stubs — so a sandboxed role's own crash/recovery drill calling reclaim() could empty ~/.monomind/orgrt-sandbox-stubs/ledger.json mid-run while the run's real daemon and its stubs were still alive. Each ledger entry now also records the writer's pid namespace (/proc/self/ns/pid) and the machine's boot id (/proc/sys/kernel/random/boot_id, stable for one boot, never reused after a reboot). reclaim() now only treats an entry as reclaimable when it is either from a different boot (the machine rebooted, so no pid from that boot can still be alive) or from the same boot AND the same pid namespace with a pid that fails the liveness check; an entry from the same boot but a different (or unreadable) pid namespace is left alone, since its liveness cannot be determined from here. Entries written before this change (no pidNamespace/bootId fields) keep the old bare-pid behavior.

  • Sandboxed org roles no longer fail Bash calls with bwrap: Can't find source path …. Every recent release run had 0–5 of these (~/.claude/local, <org root>/.claude/settings.local.json), each audited as a sandbox-fault. For a missing "dangerous file" (.bashrc, .mcp.json, .claude/settings.local.json, ~/.claude/local, …), the SDK sandbox has bubblewrap create an empty mount-point file, and deletes it when that command ends. It coordinates this only within one process, and every role is its own process. So a role that wrapped a command while another role's stub existed bound the stub as a real file, and the other role's cleanup deleted it before bubblewrap started. Before a sandboxed role starts, the runtime now creates each of those paths that is missing, as the same empty read-only file, and keeps it until the run stops. The SDK never deletes a path that already existed. At the end the runtime removes only the files and .claude/ directories it created, and only while they are unchanged. Pre-existing files are never touched. A per-machine ledger (~/.monomind/orgrt-sandbox-stubs/ledger.json) lets the next runtime reclaim, under the same rule, the stubs of a daemon that was killed or a machine that rebooted mid-run. Verified against the real bundled CLI with two concurrent role processes. See Git policy enforcement.

  • Every push to main now gets a Deploy Pages run (#348). pages.yml filtered pushes by paths: ['doc/**', ...], so a push that changed no doc file got no run at all. The 2.16.8 release push (d09b3ecdd..803111a67, only CHANGELOG.md and the package.json versions) was one of these: d09b3ecdd and its doc changes had already been pushed and deployed. The release rules then found no pages run for the release commit, and the publisher had to dispatch one by hand. The trigger no longer has a path filter. A changes job diffs github.event.before..github.sha and runs the deploy job only when doc/** or pages.yml changed. A new branch, a force push or a before that cannot be fetched always deploys, and so does workflow_dispatch. A push with no doc change now ends as a successful run with the deploy job skipped.

  • cleanup --data prunes project data whose whole parent tree was deleted, and prunes the project registry. A ~/.monomind/projects/<name>-<hash> folder counted as orphaned only when its project's parent directory still existed, so a project inside a deleted test root (/var/tmp/fx-init/agent-ops-test-* after /var/tmp/fx-init was removed) was kept forever, and --aggressive did not help. The check now walks up to the nearest directory that still exists. The folder is pruned unless that directory is a mount point or a removable-media directory (/Volumes, /media, /mnt, /run/media), where the project may be on a volume that is not mounted. The home directory, /tmp, /var/tmp and the OS temp directory count as local. cleanup --data also lists ~/.monomind-projects.json entries whose project was deleted by the same rule, and removes them with --force. The CLI test suite now points HOME and the global brain at a temp directory, so test runs no longer leave folders in ~/.monomind/projects (#347).

npm: monomind@2.16.10, @monoes/monomindcli@2.16.10 published to https://www.npmjs.com/package/monomind