feat(infra): pin claude-code to 2.1.110, add version visibility #84
No reviewers
Labels
No labels
area:agents
area:dashboard
area:database
area:design
area:design-review
area:flows
area:infra
area:meta
area:security
area:sessions
area:webhook
area:workdir
security
type:bug
type:chore
type:meta
type:user-story
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/claude-hooks!84
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "dev/83"
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?
Summary
Dockerfile: addsARG CLAUDE_CODE_VERSION=2.1.110with a comment pointing at issue #83 and the v2.1.111 context-bloat regression (anthropics/claude-code#49593) that motivated the pinscripts/smoke-creds.sh: new "Claude Code version probe" section reads the pin from the Dockerfile and asserts each running container'sclaude --versionmatches — fails loud on driftsrc/main.ts: probesclaude --versiononce at startup and caches the result;/healthnow includesclaude_code_versionso operators can verify the CLI build without exec-ing into the containerCLAUDE.md: documents the intentional-PR cadence for bumping the pin (rebuild → smoke → re-dispatch #62/#77/#79 → merge)Closes #83
Review summary
CI is green. The Dockerfile pin, comment, smoke-creds.sh probe, and CLAUDE.md policy are all correct and satisfy the acceptance criteria. One issue in
src/main.ts: the version probe runs against the hostclaudebinary, not the pinned binary inside the agent containers, so/healthwill report the wrong version.❌
src/main.ts— version probe targets host binary, not container binaryWhat the code does:
main.tsruns on the host desktop (not inside a Docker container).Bun.spawn(["claude", "--version"])therefore probes the host'sclaudeinstallation — the issue itself states the host is on v2.1.113, while the containers are being pinned to v2.1.110. An operator checking/healthafter this PR would see"claude_code_version": "2.1.113"and incorrectly conclude there's a drift, or worse, trust it and not notice a real drift.What the acceptance criterion wants:
The intent is visibility into what the agents are actually running.
Simplest fix — read the pin from the Dockerfile (same approach smoke-creds.sh uses, zero Docker exec overhead):
Alternative fix — docker exec per worker at startup:
This is more accurate (verifies the built image) but heavier; reading the Dockerfile is simpler and sufficient since the Dockerfile is the source of truth for what was baked in.
@ -572,0 +580,4 @@const m = out.match(/(\d+\.\d+\.\d+)/);if (m) claudeCodeVersion = m[1];} catch {// claude binary not in PATH (e.g. running outside container) — skipBun.spawn(["claude", "--version"])resolves to the host claude binary (v2.1.113 per the issue), not the pinned v2.1.110 inside the agent containers.main.tsruns on the host desktop, so/healthwill report the host version rather than what agents actually execute.Fix: read
ARG CLAUDE_CODE_VERSIONfrom the Dockerfile (same approach asscripts/smoke-creds.sh), ordocker execinto a worker container. Dockerfile read is simpler:Fixed in
bcdef6e. ReplacedBun.spawn(["claude", "--version"])with a Dockerfile parse — same approach assmoke-creds.sh./healthnow reports the pinnedARG CLAUDE_CODE_VERSIONvalue, which is the source of truth for what's baked into agent containers.Review: APPROVED ✅
CI green (
bcdef6e, 2m35s). All acceptance criteria from #83 met.Checklist
ARG CLAUDE_CODE_VERSION=2.1.110in Dockerfile, referenced in npm installsmoke-creds.shprobes each running container, fails loud on driftGET /healthreturnsclaude_code_versionCLAUDE.mdOne note on the implementation choice
The AC said "run
claude --versionon startup and cache" butmain.tsreads from the Dockerfile instead. This is the right call: runningclaude --versionfrom the host service process would return the host operator's CLI version, not the containers' baked version. Reading from the Dockerfile is semantically correct and consistent with what the smoke script validates per-container. No issue here.Minor observations (non-blocking)
new URL("../../Dockerfile", import.meta.url)resolves correctly fromsrc/main.ts→ project root. The silenttry/catch→"unknown"is a reasonable degradation for out-of-repo runs.dirname "$0"in the smoke script is consistent with its existing style and works for the normal invocation pattern.