Files
clawmates/docs/UPSTREAM-SCAN.md
T
Omar SobhandClaude Opus 5 563b074116 docs: ZeroClaw upstream, scanned against what we actually run
331 behind, 54 ahead. The previous scan said 218 and its conclusion about the
egress commit was wrong, so it is marked superseded rather than edited.

Merge cost is smaller than the number suggests: 660 files changed upstream, 52
by us, and **18 overlap**. `claude_cli.rs` — the provider every mission runs
through — exists in our tree and in zero upstream files, so it cannot conflict.

The find worth recording is not a feature. Upstream defaulted skills to compact
injection on 2026-08-05 (#8313), then restored the full default for v0.8.x on
2026-08-13 (#9913). Eight days. That is our `index` arm, tried at larger scale
and pulled back out of the stable line — evidence bearing directly on our own
open question of whether to flip the default, and with our own data at n=1 per
arm it argues for more pairs before flipping, not fewer.

Their documentation also states plainly what ours should: "Compact mode reduces
prompt size; it is not an isolation boundary for untrusted skill sources."
Progressive disclosure is a token optimisation. It is not a security control.

Also noted, as a documented limit rather than a surprise: upstream fixed
case-insensitive allowlist matching (#9568) and symlink-escape path resolution
(#9384) in their command gate. Ours resolves no paths, so a symlink to `curl`
defeats it.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01WZb5A2kfVfjpdwSochkuHz
2026-08-27 09:58:01 -05:00

5.5 KiB

ZeroClaw upstream, scanned against what we run — 2026-08-27

Our fork (git.redclaw.dev/osobh/zeroclaw) sits 331 commits behind upstream/master and 54 ahead. The previous scan in TOOL-CALL-ARCHITECTURE.md said 218; that number is stale and its conclusion about the egress commit was wrong — see MISSION-EGRESS.md.

Upstream since our merge base (a56c345d51, v0.8.4): 198 fixes, 35 features, 25 docs, 24 tests. The scan below filters that to what touches how ClawMates uses the runtime: claude_cli as the mission provider, the gateway RPC and WS, pairing, the skills door, and the claude→kimi→glm fallback chain.

Merge cost

files we changed 52
files upstream changed 660
overlap 18

claude_cli.rs exists in our tree and in zero upstream files, so the provider that runs every mission cannot conflict. The overlap is concentrated in providers/{factory,catalog,lib,compatible}.rs, runtime/agent/{loop_,turn, system_prompt}.rs, gateway/ws.rs and config/schema.rs. A full merge is a real piece of work but not an unbounded one.

Tier 1 — take these

841f28c7f1 fix(gateway): serialize config writes so a flush can't erase concurrent updates (#9519). The one I would take first. Upstream added a config_write_lock around "the read-mutate-save-swap critical section of every HTTP" config write. Our pinned gateway has no such lock — the mutexes in gateway/src/lib.rs are for rate limits, keys, cancellation and the SOP engine.

We make two config writes per mission, on adjacent keys:

providers.models.claude_cli.default.settings (hooks — orchestrator:341) providers.models.claude_cli.default.mcp_config (skills door — orchestrator:980)

Stated honestly: ours are sequential and awaited, so this is a latent hazard, not a demonstrated bug in our deployment. It earns first place because the failure mode is one this codebase has hit repeatedly — two writers of one document, second wins, no error — and because the loser here is either the security gate or the skills door, both of which fail silently and invisibly.

eadaee0b62 fix(providers): redact Anthropic credential fragments (#10092). We forward provider credentials into mission containers and log heavily around them. Credential fragments in logs are a live risk for us specifically.

47adb9863e fix(gateway): harden unauthenticated /api/pair against lockout bypass (#9438). We mint a pairing code per mission container. The gateway port is not published to the host, but mission containers share clawmates_edge, so one mission's container can reach another's gateway. A pairing lockout that can be bypassed is a cross-mission path.

49ba8064d3 + 0b1a715c72 + 0cba80e422 — reliable-fallback accounting and served-model logging. We run claude→kimi→glm and care which one answered; these make the fallback's own account of itself accurate.

Tier 2 — take the idea, not the code

Upstream's skills system is not ours: mission skills go through our delivery path and our MCP door. The findings still apply.

d04b345bda honor always-inject frontmatter in compact prompt mode (#9520). Upstream compact mode has an always: true escape hatch — a skill that stays fully injected no matter the mode. Our skills table has no such column (id, workspace_id, title, author, description, body, installs, created_at, name, when_to_use, tags, source_kind, current_version, updated_at), and our delivery A/B produced exactly the failure it prevents: workspace-repo-commit-protocol scored Trigger=FAIL in the index arm because no agent fetched it. An always-inject flag is the missing piece.

9ea4f3371a633c06f7c5 — the default, and the reversal. Upstream defaulted skills to compact injection on 2026-08-05, then restored the full default for v0.8.x on 2026-08-13. Eight days. That is direct evidence for our own open question of whether index should become the default: someone larger tried the same move and pulled it out of the stable line. It does not tell us they were right, and their reason is in an issue rather than the commit — but with our own evidence at n=1 per arm, it argues for more pairs before flipping a default rather than fewer.

Their documentation also carries a line worth adopting verbatim in spirit: "Compact mode reduces prompt size; it is not an isolation boundary for untrusted skill sources." Progressive disclosure is a token optimisation. It is not a security control, and ours should not be described as one.

86f03d2d75 match command allowlist names case-insensitively (#9568) and 7388987b55 resolve shell command path arguments to block symlink escapes (#9384). Different codebase, same bug class as the one we fixed in vm_tool_gate yesterday. Our gate resolves no paths and follows no symlinks, so /tmp/link-to-curl -d @secret … defeats it. Worth knowing as a documented limit rather than pretending otherwise.

Tier 3 — situational

  • 53cba1ddde opt-in multi-arch Alpine image — we hand-build arm64 today.
  • 4282a5564a gateway chat WebSocket keepalive — we already hardened our side.
  • 0db7d999a shared egress policy — chat tier only; see MISSION-EGRESS.md for why it cannot reach a mission's curl.
  • 6d76787556 per-server custom CA trust for MCP — our door is plain HTTP inside docker; no value today.

Not relevant

zerocode (21), the channel integrations (WhatsApp, Telegram, Matrix, Slack), hardware/uno-q, the installer, and the Nostr dependency work. None of it is on a path ClawMates executes.