chore(agent-tools): bump the Claude Code pin 2.1.221 → 2.1.222 — worktree-isolation + PreToolUse hook-bypass fixes; compat re-verification [schedule: Daily agent update check] #290
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Cloonar/coding-lab#290
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Goal
Move the agent-tools Claude Code pin from
2.1.221to2.1.222(one release, published 2026-08-04T20:37:17Z), re-verifying the compat record first, exactly ascontainers/agent-tools/versions.envanddocs/ops.md § "Agent-tools images"mandate:This is a one-release bump, and
internal/compat/compat.mdwas fully re-verified against 2.1.221 only yesterday (2026-08-04, via #235/#273 — the first bump whose live gate was actually run). So the baseline is fresh and the diff is small. The re-verification is still the work; the two-lineversions.envedit is the trivial part.Two of 2.1.222's fixes are permission/isolation fixes that land squarely on lab's spawn posture (
--permission-mode auto, unattended, per-run injected hooks, sessions running in linked git worktrees). Those are the reason to take this bump, and they are also the two items most likely to change behaviour under us.Evidence — current state
containers/agent-tools/versions.env:21-22:internal/compat/compat.md:3:Upstream, checked 2026-08-05:
Note the
stabledist-tag still lags at2.1.220.latestis the tag this repo tracks — #273 took2.1.221on exactly that basis whilestablewas already2.1.220— so2.1.222is the target. If the implementing agent decides the repo should switch to followingstableinstead, that is a separate decision: say so on this issue rather than silently pinning a different version.New pin values
Source — Anthropic's per-version manifest, which is exactly what the
versions.envcomment names as the authority and whatcontainers/agent-tools/build.sh:62-65verifies the download against:This method was validated before quoting it: the same manifest field for
2.1.221returns15b068e0…f301a32f, byte-identical to whatversions.envpins today. Re-derive the digest yourself from the downloaded artifact anyway (build.shdoes this automatically) — do not trust this issue as the sole source.The fetch URL
build.sh:62-65uses is unchanged:https://downloads.claude.ai/claude-code-releases/${CLAUDE_CODE_VERSION}/linux-x64-musl/claude.Security / safety fixes in this release — these DO reach us
The
claudebinary ships into every container instance (agent-tools:claude-<ver>, ADR-0051) and lab spawns it unattended with--permission-mode auto(compat §1). The permission classifier is therefore the only guard and nobody is watching it — that is the standing reason this repo treats permission fixes as reaching it, recorded in §1 for the 2.1.221 bump.1. Worktree isolation no longer leaks to the main checkout.
Every lab instance runs with cwd set to a linked git worktree whose
.gitis a file pointing at the reference repo's bare clone (internal/gitx). Lab does not itself invoke Claude Code's own worktree-isolation feature — but AFK runs spawned with theultracodeoption (compat §1,spec.Options) do run multi-agent subagents, and Claude Code's Agent tool takesisolation: "worktree". On 2.1.221 such a subagent could run destructive git against the main checkout; on 2.1.222 it cannot. This is the single best reason to take the bump.It is also the highest-risk item in the other direction — see the §1/§12 verification note below.
2. PreToolUse auto-allow hooks no longer bypass tool restrictions.
lab injects a
PreToolUsehook into every run via a per-run--settingsfile (compat §9,internal/provider/claudecode/dialogspool.go). Reachability assessment, written down so the next sweep does not re-derive it: lab's own hook cannot be the bypass vector — §9 pins it as purely observational, it exits 0 with no stdout and never emitspermissionDecision:"allow"or exit code 2. The fixed bug is about hooks that do auto-allow. So this fix does not close a hole lab opened; it hardens a path lab's hook shares. The reason it still matters here is the inverse: the PreToolUse evaluation path was touched in background agent tasks (summaries, compaction, renames), and §9's dialog capture depends on that hook firing reliably. Re-verify §9 rather than assume.3. Auto-mode
SendMessagenow goes through the permission classifier.lab spawns
--permission-mode autofor unattended runs. Defence in depth on the cross-session dispatch path. No lab-side change expected.No CVE is claimed for any of these; they are safety/permission fixes, not advisories. Recorded at that weight deliberately.
What changed that touches how this repo uses Claude Code
Each item maps to a numbered section of
internal/compat/compat.md. These are hypotheses to verify, not confirmed breaks — none was observed against a live 2.1.222 binary during this investigation.§1 Spawn argv + §12 no-
--remote-controlarm — the highest-risk item.git commit/git pushto the bare origin would newly fail or prompt. Verify this first: spawn a real session in a lab-shaped linked worktree and confirm a normal commit + push still runs with no prompt. If it reproduces, this bump is blocked — report the drift here rather than working around it..claude/settings.jsonor.claude/settings.local.json) can no longer turn it on (they can still turn it off); enable it at user scope via/config." Expected to be a no-op for lab:--remote-controlis passed as an explicit CLI flag (§1, a lab-gated knob, default OFF since #163), never via settings, and the per-run--settingsfile lab writes carries onlyhooks+env(§9/§11). Confirm the explicit flag still attaches the bridge (§2 deep-link capture is what would go quiet if not). This repo's committed.claude/settings.local.jsonis{"enableAllProjectMcpServers": true}— nothing remote-control-related, so nothing to migrate.§9 Dialog-capture hook contract — see security item 2. Re-confirm: the settings
hooksshape still merges additively via--settings, the three payload field names are unchanged, and the observational exit-0 contract still lets the tool proceed.TestCompat_HookPayload_mapsguards the payload mapping; the merge semantics and live firing are the by-hand part.§10 Builtin slash-command catalog — "Removed ultraplan feature".
ultraplanis not one of the 33 pinned rows (grep -rn ultraplanover this repo returns zero hits), so the removal needs nocommands.goedit. It does mean the 2.1.221 registry's 105-row count should drop — useful as a sanity check that your extractor is reading the new bundle and not a cached one./status. Check both by the reverse-grep method §10 mandates (take each pinned string, grep the raw binary for it), not a forwarddescription:"…"regex:/usage("Fixed/usageoverattributing usage to MCP servers") and/diff-adjacent rendering ("Improved the/diffview, the Remote Control workspace diff, and file-edit diffs … to use raw git blob content, ignoring workspace-configured diff drivers and textconv").doctor,feedback,usage-credits) — they were freshly re-pinned yesterday, so any movement here is real drift and not the known pre-existing miss. RememberdoctorpinsmenuDescription, notdescription.§5 Transcript location + JSONL schema — "Fixed 'Connection closed mid-response' errors being reported on responses that had actually completed" and "Fixed tool errors not being displayed for tools no longer available locally". Both change what error/result entries land in the rollout JSONL that lab parses as the chat transcript.
ParseRollout/ReadChatmust keep degrading gracefully on unknown entry shapes. Fixture updates only if the grammar genuinely moved.§6/§7/§8 Reply, dialog, and interrupt recipes — nothing in the 2.1.222 changelog names the TUI composer, the
AskUserQuestion/ExitPlanModepickers, or key handling. Expected clean. Re-drive the automated suite anyway (it is one command, below) — that is what makes "green" mean "no drift".Model/effort seam (D14, ADR-0043) — "Fixed org-restricted
model: opus-style subagent and teammate family aliases dropping to the parent model instead of stepping down to the newest org-allowed model in the family" and "Fixed the spinner's effort label in a subagent's transcript view showing the session's effort level instead of the subagent's owneffort:setting". lab passes--model M/--effort Eexplicitly (§1) and owns its catalogs provider-side, so no lab change is expected. Note in the compat record if theclaude debug-side catalog output moved.Skills — "Improved the refusal when Claude tries to invoke a skill with
disable-model-invocation: Claude is now told to ask you to run the skill instead of replicating its workflow." Three repo-shipped skills set that flag (.claude/skills/zoom-out,setup-matt-pocock-skills,grill-with-docs). Behaviour-only, no lab surface. Noted, not a gate.Build/CI — no change needed.
build.sh'sdownloads.claude.aiURL and manifest-digest flow are unchanged, and the egress list indocs/ops.md § Agent-tools imagesstill holds.Scope — files an implementing agent will touch
containers/agent-tools/versions.envCLAUDE_CODE_VERSION+CLAUDE_CODE_SHA256_X64_MUSL, moved atomically with the compat-record updateinternal/compat/compat.md2.1.222note under §10 like the existing 2.1.220/2.1.221 onesinternal/provider/claudecode/commands.goultraplanneeds no edit — it was never pinned.internal/provider/claudecode/*.go+testdata/nix/module.nixneeds no edit —container.toolsImagesderives its default tag fromversions.envat eval time (nix/module.nix:197-213,docs/ops.mdoption table).Done means
-voutput shows they RAN (every one carries its own skip-gate; a skipped run is not a pass):LAB_COMPAT_LIVE=1 go test ./internal/compat/ -run Live -vgit commitandgit pushto the bare origin under--permission-mode autowith no new prompt or refusal.--settingshooks block still merges additively,PreToolUsestill fires forAskUserQuestion|ExitPlanMode, the spool still lands, and the observational exit-0 contract still lets the tool proceed.doctor'smenuDescriptionre-checked.go test ./...green (hermetic).golangci-lint runclean.containers/**) builds the claude image and passes the injection smoke test on the PR — locally reproducible withcontainers/agent-tools/build.sh claude && containers/agent-tools/smoke-test.sh claude.Closes #<this issue>.Out of scope
CODEX_VERSION=0.133.0→0.146.0is tracked on #249 and is a much larger re-verification. Do not fold it in here.versions.env:28-30) — still deferred to #126.Filed by the Daily agent update check schedule, 2026-08-05. Release notes quoted verbatim from
anthropics/claude-codeCHANGELOG.md§ 2.1.222; versions from the npm registry@anthropic-ai/claude-code; digest fromdownloads.claude.ai/claude-code-releases/2.1.222/manifest.json, with the method validated against the 2.1.221 pin this repo already carries.