Commit Graph
2 Commits
Author SHA1 Message Date
Omar SobhandClaude Opus 5 1c9be52291 build(runtime): pin Claude Code 2.1.276 and Kimi 0.41.0; missions run the image we ship
deploy / test (push) Successful in 5m16s
deploy / build (push) Successful in 1m4s
Two things found while asking "what version of Claude Code do missions run?"

Mission containers are created from CLAWMATES_RUNTIME_IMAGE, which on both
stacks still pointed at clawmates-runtime:hooks — zeroclaw 0.8.4, Claude Code
2.1.237 (2.1.228 locally), built 2026-08-21. The v0.8.5 upgrade on 09-06
rebuilt only the persistent clawmates-runtime container, which container-tier
missions do not drive their turns through. Every measured mission this month
ran on 0.8.4/2.1.237; the measurements stand (one image throughout) but the
version attached to them in the handoff and in memory was wrong, and has been
corrected there.

The drift itself came from `npm install -g @anthropic-ai/claude-code` with no
version: each rebuild takes whatever npm has that day, so two builds three
weeks apart shipped two CLIs and nothing recorded either. The changelog shows
why that is not merely untidy — 2.1.265 and 2.1.275 each broke every turn on
ANTHROPIC_BASE_URL endpoints, the path the GLM and Kimi backends use — and
today's floating local build silently took Kimi 2.0.1, a major version. Both
are ARGs now, defaulting to what was verified.

Verified before promoting: two local missions on 0.8.5 + 2.1.276 — tool
arguments recorded on 40/40 and 123/123 calls, gate.installed, skill reads,
judge met and independent with the correction loop closing, spend rows with
provider and model, and with delegation forced, 4 Agent spawns → 45 subagent
calls across 4 ids all typed general-purpose (44/4 on the old CLI). The hook
payload did not move. Prod's .env now names clawmates-runtime:v085-cc276,
built on tank from the fork at 57635deb with this Dockerfile.

The local override's CLAWMATES_RUNTIME_IMAGE points at :toolchain, which is
the same lineage plus cmake/python3-dev for `cargo test` on cmake-driven deps.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01WZb5A2kfVfjpdwSochkuHz
2026-09-18 12:26:49 -05:00
Omar SobhandClaude Opus 5 869c3adcb7 fix(missions): egress from a subnet of their own, so the host can police it
deploy / test (push) Successful in 5m39s
deploy / build (push) Successful in 7m28s
docs/MISSION-EGRESS.md measured that a mission container reaches the entire
tailnet and SSH on its own host, and left the remediation unapplied. Applying
it on 2026-09-18 found why five iptables lines were never going to be enough:
missions egressed from clawmates_edge, the SERVER's network, and the server
needs the tailnet — Beszel on architect, Ollama for the local backend, the
node daemons for exec-test and node-placed terminals. A tailnet drop scoped to
172.23/16 cut the server off from architect:8090 inside a minute.

Missions now egress from clawmates_missions, 172.25.0.0/16, pinned so the
firewall can name it and declared in both compose files with the same shape
edge has. Compose v1 does not create a network no service uses, so on gw-04
it was created by hand with compose's own labels; the server's attach failure
message now says to check for it. core is unchanged: the door and API are
still reached over 172.20.

The policy itself (/usr/local/sbin/clawmates-egress.sh on gw-04, systemd unit
+ drop-ins on docker and tailscaled) lives in mangle/PREROUTING with
--ctstate NEW. Two earlier placements failed measurably: filter/FORWARD loses
to tailscaled re-inserting ts-forward above it on every restart, and
raw/PREROUTING runs before conntrack, so it dropped the server's replies to
tailnet clients and took the API off 100.102.112.85:8088. Verified from the
mission subnet (tailnet, host ssh, link-local blocked; public and core open),
from edge (tailnet open, ssh blocked), and inbound from tank; and proved to
survive restarting both daemons.

Also: deploy/compose/docker-compose.override.yml is tracked now. It holds the
fixes for the five local bring-up gaps and every credential in it is a
${VAR:?} reference, and it had lived on one laptop that lost a volume this
week.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01WZb5A2kfVfjpdwSochkuHz
2026-09-18 11:06:03 -05:00