feat: named per-repo toolchain image variants - #10
Merged
Conversation
Allow consumers to build a per-repo content-hashed layer on the agent
image and select it via agent({ variant }) without threading tags
through every test (#5).
devzeebo
commented
Aug 30, 2026
devzeebo
left a comment
Collaborator
Author
There was a problem hiding this comment.
Review (issue #5)
Named variant + buildToolchainImage is the right consumer API, and the vitest worker registry problem is real. I would not merge yet: skip-if-present plus a Dockerfile-only hash can serve a stale image, and the on-disk registry is a racy read-modify-write.
(Posted as a comment review — GitHub blocks REQUEST_CHANGES on your own PR.)
Blockers
- Incomplete invalidate key — tag ignores parent image ID and build-context files (
COPY/ADD). See inline onbuild-toolchain-image.ts. variants.jsonlost updates — shared read→mutate→write under parallel registration / this repo’s parallel specs. See inline.
Should fix
FROMis docs-only; not tied tooptions.agent(easy footgun:agent: "claude"+ CursorFROM).ensureDockerImageandagentRunError(unchanged in this PR) still only hintbuildAgentImagewhen a pruned toolchain tag is usually abuildToolchainImagemiss — please update those messages in this PR or a follow-up.- Image digest uses
packageRoot; registry path usesprocess.cwd()— document or align.
Nit
c59f101(.codegraph/gitignore) is unrelated to #5 — prefer a separate commit/PR.- Tmp root is
.agent-gwtwhile workspaces use.agents-gwt. - Prefer one file per variant key (or lock + atomic write) over a single JSON blob.
What’s solid
variantvsimagemutual exclusion and clear unknown-variant errors- Disk bridge for vitest
globalSetup→ workers - Reuse of
buildDockerImagememoization for the Docker side - GWT coverage for tag identity / Dockerfile change / skip-if-present
- README example folds
buildAgentImageintobuildToolchainImage
This reverts commit c59f101.
Include parent image ID in the digest, force docker rebuilds, pass AGENT_IMAGE as a build-arg with FROM validation, and use per-key registry files under the packageRoot digest. Update missing-image hints and README caveats; drop the unrelated .codegraph gitignore.
Collaborator
Author
|
Addressed the review on this PR:
|
devzeebo
commented
Aug 30, 2026
devzeebo
left a comment
Collaborator
Author
There was a problem hiding this comment.
Follow-up review (1a98dbb)
Prior blockers look addressed. Nice work — this is in much better shape.
Resolved
- Parent image ID in the digest +
force: true(Dockerfile/COPY/ADD+ parent rebuilds) - Per-key registry files under
packageRootdigest, atomicwrite+rename, shared.agents-gwttmp root AGENT_IMAGEbuild-arg +FROMvalidation; README example/caveatsensureDockerImage/agentRunErrortoolchain hints- Unrelated
.codegraphgitignore dropped;agent.specmocks resolve (no shared-registry flake) - Tests for parent-id change, force rebuild, FROM mismatch
CI is green. Remaining items are smaller — see inline. I would not block merge on them, but the variant filename collision is worth fixing before this gets wide use.
Use a digest of agent::variant for on-disk filenames so variants cannot collide, clear temp packageRoot registries in aspect hooks, note first-FROM-only validation, and cover force/buildArgs on buildDockerImage.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
buildToolchainImage(variant, { agent, dockerfileRelative, ... })to bake a content/repo-hashed layer on top of the agent image and register it by nameagent({ name, variant })(no tag plumbing);imageremains a mutually exclusive escape hatch/tmp/.agent-gwt/…so vitestglobalSetupis visible to test workers; documents the pattern in the READMECloses #5
Test plan
pnpm lint && pnpm testFROM agent-gwt/cursor-cli:local, callbuildToolchainImage("node18", …)from vitestglobalSetup, and runagent({ name: "cursor", variant: "node18" })variantstill uses the stock agent image; unknown variant / bothimage+varianterror clearly