Skip to content

feat(devenv-image): move to nixos-26.05 (devenv 2.1.2), VERSION 2.0.0 - #480

Merged
wz-gsa merged 6 commits into
mainfrom
feat/devenv-image-2x
Oct 9, 2026
Merged

wz-gsa merged 6 commits into
mainfrom
feat/devenv-image-2x

Conversation

@basiliskus

@basiliskus basiliskus commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Move the devenv image's NIXPKGS_REV to nixos-26.05 (0d9e9b832d03ac387417e16ce1febf73b2e631e1), which ships devenv 2.1.2, and bump VERSION to 2.0.0 because the devenv major is part of the image contract. The README records that contract and what a 2.x CLI changes for repos still locked to 1.x modules. Existing consumers keep the immutable 1.0.0 tag.

Eligibility & Accountability

  • I am a federal employee or contractor (PRs merge with @GSA-TTS/agentic-coding-team code-owner approval; eligibility is attested here, not authenticated). Anyone may open issues without this.
  • I understand this change and can explain it in my own words — I am the author of record and accountable for it.
  • By opening this PR, I attest I have the right to release this work under the repository's CC0-1.0 dedication.

AI Assistance Disclosure

  • AI tools were used in this contribution
  • I verified all AI-generated content: no fabricated/hallucinated APIs, dependencies, citations, or placeholder content; any AI-suggested dependency was confirmed to exist.
  • Any inherited/reused third-party material retains its original license and is identified (not represented as public domain).

Type of Change

  • New tool/editor integration (integrations/)
  • Documentation update
  • Infrastructure/tooling change

Motivation

Toolchain currency for the generic devenv image (item 1 of #418): devenv 2.x is absent from nixos-25.05 and nixos-25.11 and first appears in nixos-26.05. This PR is only the pin bump plus consumer documentation; size/startup measurement, the devenv container generation model, and persistence docs from that issue are left for follow-ups.

This satisfies the substrate requirement in GSA-TTS/agentic-coding-quickstart#474 (ADR-0030: a channel carrying the intended devenv major, with the major recorded in the image contract), so it should land before GSA-TTS/agentic-coding-quickstart#474 claims that requirement is met. The dependency is conceptual: that PR pins no devenv image tag, so nothing enforces the order. nixos-26.05 is the only channel that is both devenv 2.x and release-pinned: 2.2 and later exist only in nixpkgs-unstable (currently 2.4.0), and devenv 2.2 stopped building for x86_64-darwin (devenv v2.2 release notes).

Testing

Build: workflow_dispatch of devenv-image.yml on this branch succeeded on all four legs (shell/opencode × amd64/arm64); the manifest job skipped as designed off main. Run: https://github.com/GSA-TTS/agentic-coding-patterns/actions/runs/37489740805

Image smoke test (arm64 devenv-opencode digest from that run, in an msb sandbox created through acq with a real kit stack): devenv version → devenv 2.1.2 (aarch64-linux); installer Nix 2.24.9 and direnv 2.37.1 present; non-interactive bash -c 'devenv version' works; agent:agent owns /nix, /nix/store (1775) and /nix/var/nix/db. A minimal devenv 2.x project built in the sandbox: its outputs are registered in the shared store DB (schema 10) as seen by the installer's nix path-info, nix store verify passes, and no group/world-writable outputs are produced (the single-user-store regression fixed upstream in cachix/devenv#2757 is absent). Locked GitHub inputs, cache.nixos.org and cachix fetches all succeeded through the kit-provided CA via devenv's bundled Nix.

Consumer compatibility (devenv 2.1.2 from the same nixpkgs rev, run against scratch copies of two team repos that stay locked to 1.x modules): a Python/venv/tasks repo passes unchanged; a Ruby/Postgres/git-hooks repo fails until the git-hooks input is declared in devenv.yaml, then passes including devenv up -d Postgres. devenv shell under 2.x rewrites devenv.lock (drops implicit git-hooks/pre-commit-hooks/flake-compat nodes) and a 1.x CLI adds them back at current HEAD; .devenv/ is reusable across majors. These behaviors are what the README section documents.

Safety Checklist

  • No secrets, API keys, tokens, or passwords included
  • No PII (names, emails, SSNs, addresses)
  • No CUI (Controlled Unclassified Information)
  • No internal URLs, hostnames, or system paths
  • No customer data or proprietary information

Quality Checklist

  • Plain language used (Grade 10 or below preferred)

Validation Results

make validate

✓ All validators passed

Related Issues

Relates to #418

Additional Context

The feature-branch build wrote to the shared devenv-*:cache-{amd64,arm64} registry cache tags, so the next main build after merge rebuilds more layers than usual.

Known follow-ups not in this PR: a post-build smoke-test job in devenv-image.yml (fixture with git-hooks, direnv exec . true, store-permission check); devenv processes down can time out and SIGKILL the process group without stopping a service's children (observed with Postgres under the 2.1.2 CLI); the devenv update path (2.x modules, prek default, native process manager) could not be exercised behind a GitHub-API-rate-limited proxy because the bundled Nix's libgit2 fallback fails with authentication required but no callback set.

Reviewer Notes

Reviewers should verify:

  • NIXPKGS_REV resolves to a nixos-26.05 commit and the Dockerfile comment matches
  • VERSION is 2.0.0 and not previously published
  • README 2.x consumer notes match the migration guide's documented breaking changes
  • No sensitive information included
  • make validate passes in CI

Pin NIXPKGS_REV to nixos-26.05 so the image ships devenv 2.x, which first
appears there. The devenv major is part of the image contract, so this is a
major VERSION bump; 1.x consumers keep the immutable 1.0.0 tag.
… notes

Document that the devenv major is part of the image contract and what a
2.x CLI changes for repos still locked to 1.x modules: the explicit
git-hooks input, lock rewrites between majors, .devenv reuse, and the
devenv processes down behavior observed in sandboxes.
@basiliskus basiliskus added enhancement New feature or request supply-chain Dependency, script, provenance, external inspiration labels Oct 6, 2026
@basiliskus
basiliskus marked this pull request as ready for review October 6, 2026 17:29
@basiliskus
basiliskus requested a review from a team as a code owner October 6, 2026 17:29
@wz-gsa

wz-gsa commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

AI-assisted review (OpenCode), advisory. Reviewed head 9ecb253. The change itself is small and I verified its three load-bearing claims independently; the useful part of this review is a cross-repo sequencing fact neither PR states.


Verified

The pin is a genuine nixos-26.05 ancestor, not a fork or unstable HEAD:

$ gh api repos/NixOS/nixpkgs/commits/0d9e9b832d03ac387417e16ce1febf73b2e631e1
  date=2026-10-04T19:50:49Z   msg=[26.05] brave: 1.96.59 -> 1.96.61 (#569667)

$ gh api repos/NixOS/nixpkgs/compare/nixos-26.05...0d9e9b83
  status=behind  ahead_by=0  behind_by=59

ahead_by=0 is the one that matters — the rev is on the release branch, 59 commits back from its tip.

It really ships devenv 2.1.2:

pkgs/by-name/de/devenv/package.nix @ 0d9e9b83
  version = "2.1.2";

The major VERSION bump is justified, and 2.1.2 is the right target rather than 2.2/2.3 — those exist only in nixpkgs-unstable, which the Dockerfile comment correctly warns against ("unpinned nixpkgs#… tracks unstable HEAD and drifts per build"). nixos-26.05 is the only channel that is both 2.x and release-pinned.


This unblocks quickstart#474, and neither PR says so

GSA-TTS/agentic-coding-quickstart#474's ADR-0030 ("agent kits on a devenv base") specifies exactly this move:

"channel … resolves to devenv 1.11.2. devenv 2.x is present in neither nixos-25.05 nor nixos-25.11; it first appears in nixos-26.05 (2.1.2) and in nixpkgs-unstable (2.2/2.3). The devenv major is therefore part of the substrate contract." — ADR-0030:42-44

"The base image must move to a channel that carries the intended devenv major, and the devenv major must be recorded as part of the substrate contract." — ADR-0030:79

Same channel, same version, same "record the major in the contract" requirement. I reached the channel and version independently before reading that ADR, so this is agreement rather than one document being derived from the other.

Worth stating explicitly in one of the two places, because right now:

So the dependency is real but invisible from either side. #480 should land before #474 can claim its substrate contract is met.

One supporting check: ADR-0030:84 says "No existing kit uses devenv, so there is no 1.x-to-2.x migration cost for kit authors." I confirmed the other half — quickstart main pins no devenv image tag anywhere, only capability checks (/nix is missing, install devenv in the base image or a create-time kit). So nothing consumes 1.0.0 today and the major bump breaks no current consumer.


One gap in the 2.x notes, from the same ADR

The README's "devenv 2.x notes for consuming repos" covers four CLI-major changes (implicit git-hooks input, lock-node churn, .devenv cross-major reuse, devenv processes down timing out). ADR-0030 lists six behaviour areas changed since 2.0, and one of them is a requirement on the consumer rather than a note:

".devenv (evaluation cache and detached process-manager state) must be persisted for supervision and caching to work across runs." — ADR-0030:425

The README currently says .devenv/ is reusable across majors (true, and useful), but not that it must be persistent for the 2.0 native process manager to supervise anything across runs. On 2.1.2 the Rust process manager is the default, and the README's own last bullet — "devenv up -d works; devenv processes down may time out" — is a symptom readers will hit in exactly the setup where .devenv is ephemeral.

Suggest one line under the existing .devenv bullet, something like: ".devenv must be on a persistent path for detached process supervision and the eval cache to survive a sandbox restart — pair the image with a kit-declared volumes: entry." That also ties into the README's existing "Sized /nix store" bullet, which already points at volumes:.

The other ADR-0030 items I checked and would not add — they are additive on 2.1.2 and not consumer-visible breaks: --from out-of-tree environments, JSON introspection surfaces, and the 2.2-only changes (shared process manager, devenv.nix-keyed auto-activation, reverse proxy) which do not exist in 2.1.2.

Two I am less sure about and raise as questions rather than findings:

  • Automatic port allocation and strict-port mode arrived in 2.0. Does that interact with a kit declaring publishedPorts, or is it inert unless a devenv.nix asks for ports?
  • SecretSpec is bundled in 2.x and "prompts before releasing values". In a non-interactive sandbox a prompt is a hang rather than a failure. Is it reachable without a repo opting in via devenv.yaml? If it is opt-in, no action; if it can trigger on an existing devenv.nix, that is worth a note next to the git-hooks one.

Net

The pin, the version, and the major bump all check out, and keeping existing consumers on the immutable 1.0.0 tag is the right call. The .devenv persistence line is a small README addition; the cross-repo note is the thing I would most want recorded, since the two PRs currently satisfy and require the same contract without referencing each other.

Not blocking on my read.

@wz-gsa

wz-gsa commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Reviewed the 32-line diff, then went looking for cross-repo consumers because a major version bump on a published image is mostly a question about who pins it. No findings. One sequencing fact worth recording, because neither PR states it.


The pin and the version claim both check out

Verified rather than taken from the description:

nixpkgs 0d9e9b832d03  ->  "[26.05] brave: 1.96.59 -> 1.96.61"   dated 2026-10-04
compare nixos-26.05...0d9e9b83  ->  status=behind  ahead_by=0  behind_by=59

ahead_by=0 is the part that matters — the rev is a genuine ancestor of the release branch, not a fork or an unstable snapshot.

And that rev really does ship the version the major bump is justified by:

pkgs/by-name/de/devenv/package.nix @ 0d9e9b83  ->  version = "2.1.2";

The "existing consumers keep the immutable 1.0.0 tag" claim is also machine-enforced, not just intended — devenv-image.yml:131-141 refuses to publish over a published version tag:

if docker buildx imagetools inspect "${IMAGE}:${VERSION}" >/dev/null 2>&1; then
  echo "::error::${IMAGE}:${VERSION} is already published — bump VERSION"
  exit 1
fi

so 2.0.0 becomes a new tag and 1.0.0 is untouched. (latest does move, which the workflow comment says explicitly — fine, and worth consumers knowing.)


This unblocks quickstart#474, and neither PR says so

GSA-TTS/agentic-coding-quickstart#474 carries ADR-0030 ("agent kits on a devenv base"), which states the constraint this PR satisfies:

"channel … resolves to devenv 1.11.2. devenv 2.x is present in neither nixos-25.05 nor nixos-25.11; it first appears in nixos-26.05 (2.1.2) and in nixpkgs-unstable (2.2/2.3). The devenv major is therefore part of the substrate contract." — ADR-0030:42-44

"The base image must move to a channel that carries the intended devenv major, and the devenv major must be recorded as part of the substrate contract." — ADR-0030:79-80

That is exactly what this PR does: nixos-26.05, devenv 2.1.2, major recorded in VERSION. I had confirmed the channel and version independently before reading the ADR, so the agreement is a real match rather than my reading one into the other.

Two things follow that I think are worth stating on the PRs:

  • Sequencing. Security Policy violation Repository Administrators #474 cannot claim its substrate contract is met until this lands. This PR's body doesn't mention Security Policy violation Repository Administrators #474, and ADR-0030 refers to integrations/isolation/images/devenv/ generically without citing the version bump that satisfies it. A reader of either PR alone would not know.
  • 2.1.2 is the right target, and 2.2/2.3 would not be. ADR-0030:74 notes "2.2 drops x86_64-darwin" — contributor hosts, not the image matrix, but it would strand macOS contributors. And 2.2/2.3 live only in nixpkgs-unstable, which the Dockerfile comment here explicitly rules out ("unpinned nixpkgs#… tracks unstable HEAD and drifts per build"). So nixos-26.05 is the only channel that is simultaneously 2.x and release-pinned. That reasoning isn't in this PR, and it's the strongest defence of the choice.

On the 2.x notes list

I compared this README's consumer notes against ADR-0030's survey of 2.x, expecting gaps. There aren't any that matter, and the reason is worth noting rather than filed as a finding:

ADR-0030 surveys 2.0 -> 2.3 to justify CHOOSING a major:
  shared process manager (2.2), auto-activation keyed on devenv.nix (2.2),
  --from out-of-tree envs (2.0/2.2), SecretSpec, footprint, 2.2 drops darwin

This README documents what breaks for a CONSUMER at 2.1.2:
  git-hooks input no longer implicit, devenv.lock node churn across majors,
  .devenv/ reuse, devenv up -d / processes down SIGKILL behaviour

Most of the ADR's items are 2.2+ features that are not in 2.1.2, so a narrower list is the correct one for the version actually shipped. The git-hooks item is the one a consuming repo will actually hit first, and it's documented with the exact error string — which is the useful form.

One I could not verify offline: whether SecretSpec is present in 2.1.2 or arrives in 2.2+. If it is in 2.1.2 it is a behaviour a consuming repo could encounter, and a line in the notes would help. Flagging as a question, not a finding — I have no evidence either way.


What I checked and found clean

  • No consumer pins the devenv image tag today. git grep across all three repos: quickstart main references devenv only as capability checks (/nix is missing, install devenv in the base image or a create-time kit), never a tag. ADR-0030:84 says the same from the other side — "No existing kit uses devenv, so there is no 1.x-to-2.x migration cost for kit authors." So the major bump breaks nothing in-tree.
  • VERSION 1.0.0 → 2.0.0 is consistent with the README's stated rule, which this PR also updates to make the major-bump trigger explicit ("with a major bump when the devenv major changes").
  • The Dockerfile comment now records why the rev and VERSION move together, which is the thing that rots first.

No changes requested. The only thing I'd add is a cross-reference to quickstart#474 in the body, so whoever merges knows the ordering.


AI-assisted review (OpenCode), prepared on operator instruction. Advisory.

…d SecretSpec

Record three devenv 2.1.2 behaviors a consuming repo can hit in a sandbox:
.devenv/ lives in the workspace (lost on recreate under --clone), built-in
services auto-allocate the next free port once a repo uses 2.x modules
(strict_ports: true keeps a published port fixed), and SecretSpec is opt-in
and prompts only on a terminal.
@basiliskus

Copy link
Copy Markdown
Contributor Author

Thanks. Taken in ebe73f2 and the PR body:

  • quickstart#474 sequencing: added to the body, with the reason nixos-26.05 is the only 2.x release-pinned channel (2.2/2.3 are unstable-only; 2.2 drops x86_64-darwin).
  • .devenv persistence: devenv keeps it in the project root (DEVENV_DOTFILE, DEVENV_STATE=.devenv/state), so in a sandbox it lives in the workspace and persists with a host-mounted checkout; no volumes: entry is needed there. The real loss is under --clone, where a recreate discards .devenv/state and any service data in it. The README now says that.
  • Port allocation (your question): not inert. At 2.1.2, 34 built-in service modules (Postgres, Redis, …) use ports.<name>.allocate, so a repo on 2.x modules whose base port is taken silently moves to the next free one; a kit publishing a fixed guest port would then forward to the wrong place. Repos still locked to 1.x modules are unaffected until devenv update. The README recommends strict_ports: true in that case.
  • SecretSpec (your question): present (since 1.8) but opt-in (secretspec.enable, the CLI flags, or SECRETSPEC_PROVIDER/SECRETSPEC_PROFILE). On missing secrets, devenv prompts only when stdin is a terminal and otherwise fails (devenv/src/main.rs at v2.1.2), so it does not hang a non-interactive run; an agent PTY can still count as a terminal. Noted in the README.

@basiliskus basiliskus self-assigned this Oct 7, 2026
@wz-gsa

wz-gsa commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

AI-assisted review (OpenCode), advisory — needs a human to confirm before it drives a change. Reviewed head ebe73f2b.

Checked every version claim against upstream rather than reading the diff. One finding; the change itself is correct.

Verified

  • NIXPKGS_REV=0d9e9b832d03ac387417e16ce1febf73b2e631e1 is a real commit (2026-10-04) and is genuinely on the release branch, not a cherry-pick or an unstable rev: compare 0d9e9b8...nixos-26.05@HEAD returns status: ahead, ahead_by: 311, behind_by: 0, so the pin is an ancestor of the branch head.
  • devenv at that exact rev is 2.1.2 (pkgs/by-name/de/devenv/package.nix), not just at branch HEAD. direnv at the same rev is 2.37.1, matching your smoke-test output.
  • The channel-availability claim holds: nixos-25.05 → devenv 1.11.2, nixos-25.11 → devenv 1.11.1, nixos-26.05 → devenv 2.1.2. 2.x genuinely first appears in 26.05.
  • No stale 1.0.0 image references anywhere in either repo, so the VERSION bump doesn't orphan a consumer reference.

Should-fix: the "why not newer" justification is stale and partly unverifiable

The PR body says 26.05 is the only viable channel because "2.2 and 2.3 exist only in nixpkgs-unstable, and 2.2 drops x86_64-darwin." Two problems:

  1. nixpkgs-unstable is at devenv 2.4.0 as of today, not 2.2/2.3.
  2. I can't substantiate the x86_64-darwin drop. Pulling package.nix from nixpkgs-unstable, its meta block contains only changelog, description, homepage, license, mainProgram, maintainers — no platforms and no badPlatforms. If 2.2+ dropped x86_64-darwin, it isn't visible there.

This doesn't change the decision: pinning a release branch over unstable is right regardless, and 26.05 remains the only release channel carrying 2.x. But the stated reason is load-bearing for the "only channel that is both devenv 2.x and release-pinned" conclusion, and as written it doesn't check out. Either cite where the darwin drop is observable (upstream release notes or a nixpkgs commit), or drop that half and rest on "unstable isn't release-pinned," which is sufficient on its own.

Not blocking — it's the rationale in the PR body, not the change.

Note on the quickstart#474 sequencing claim

You state this "satisfies the substrate requirement in GSA-TTS/agentic-coding-quickstart#474 (ADR-0030) … so it should land before #474 claims that requirement is met."

I looked for a mechanical dependency and didn't find one: on #474's branch, acq and acq.backends/ reference devenv only as a detected workspace type (devenv.nix/devenv.yaml/devenv.lock detection in common.sh:1130, activation guidance, and /nix doctor warnings) — no devenv image tag is pinned anywhere in that branch. So the dependency is conceptual rather than a code reference, and nothing enforces the ordering.

Worth stating explicitly in the PR body if the ordering matters, since a reader checking #474 for a devenv-*:1.0.0 pin to update won't find one.

README accuracy

The devenv 2.x consumer notes match what your testing section reports, and the behaviours documented (implicit git-hooks input removed, devenv.lock churn between majors, .devenv/ cross-major reuse, strict_ports, SecretSpec opt-in and its TTY prompt behaviour) are the right things to warn a consuming repo about. I did not independently verify the per-behaviour claims — they need a 1.x-locked repo and a live sandbox, which I don't have. Taking those on your reported runs.


Method: upstream API/raw-file checks against NixOS/nixpkgs for the pinned rev, its branch ancestry, and devenv/direnv versions at that rev and at three channel heads; grep across both repos for stale image-tag references and for a mechanical #474 devenv pin. No image built, no sandbox created.

UNVERIFIED: the image build, the smoke test (devenv 2.1.2 in-sandbox, store ownership/permissions, nix store verify, cachix fetches), and the two-repo consumer-compatibility runs. Those are taken on your evidence.

@basiliskus

Copy link
Copy Markdown
Contributor Author

Thanks. Fixed in the body: nixpkgs-unstable is at 2.4.0, so it now says "2.2 and later". The x86_64-darwin drop is real but lives in devenv's own release notes rather than nixpkgs meta: v2.2's notes say "Dropped x86_64-darwin (Intel macOS): devenv is no longer built, tested, or released for x86_64-darwin". The body now cites that. Agreed the GSA-TTS/agentic-coding-quickstart#474 ordering is conceptual (no image tag is pinned there); the body says so.

@basiliskus

Copy link
Copy Markdown
Contributor Author

@wz-gsa can I get another review and verdict for this PR?

@wz-gsa

wz-gsa commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

Both findings closed. Verified rather than taken on assertion, since the darwin claim was the one I couldn't substantiate last time.

The x86_64-darwin citation checks out. I was looking in the wrong place — it isn't in nixpkgs' package.nix metadata (no platforms/badPlatforms there), it's in upstream devenv's own release notes, exactly where you now point. Pulled v2.2's notes via the GitHub releases API:

Dropped x86_64-darwin (Intel macOS): devenv is no longer built, tested, or released for x86_64-darwin. Intel Mac users should pin an older devenv CLI release.

That settles the "only channel that is both devenv 2.x and release-pinned" conclusion, which was the part the rationale was load-bearing for.

The version correction matches what I measured. "2.2 and later exist only in nixpkgs-unstable (currently 2.4.0)" is right — I read 2.4.0 at unstable HEAD.

The #474 dependency framing is now accurate. "The dependency is conceptual: that PR pins no devenv image tag, so nothing enforces the order" is what I found when I searched that branch — devenv appears there only as a detected workspace type.

Head moved ebe73f2b → 7838d574, which is a main merge picking up #436; no change to the three files under review. The pin verifications from my earlier pass therefore still hold and I did not re-run them: rev on the release branch (ahead_by: 311, behind_by: 0), devenv 2.1.2 and direnv 2.37.1 at that exact rev, channel progression 25.05→1.11.2 / 25.11→1.11.1 / 26.05→2.1.2, no orphaned 1.0.0 references.

Verdict: no remaining findings from me. Still carrying the same unverified set as before — the image build, the in-sandbox smoke test, and the two-repo consumer-compatibility runs are taken on your reported evidence, since I have no sandbox-capable host.

@wz-gsa wz-gsa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. One non-blocking nit — a quoted error string that devenv does not emit. Everything else verified, and this time I had a working sandbox, so the claims I previously took on your reported evidence are now measured.

First, a correction to my earlier reviews: I said I had "no sandbox-capable host." That was wrong — Docker 29.8.0 was running the whole time and I should have checked instead of asserting. I rebuilt this image locally and exercised the README's claims directly.

Built both pins, so the cross-major claims could actually be tested

pr480-devenv-1x:local      devenv 1.11.2  direnv 2.36.0   (old pin, nixos-25.05)
pr480-devenv-review:local  devenv 2.1.2   direnv 2.37.1   (this PR, nixos-26.05)
pr480-devenv-oc:local      devenv 2.1.2   opencode 1.18.32 (opencode variant)

All arm64. The 1.x build also independently confirms the README's channel progression table.

Verified in-image

devenv version                  2.1.2 (aarch64-linux)      matches the pin
direnv version                  2.37.1                     matches
/nix owner                      agent:agent                single-user, no daemon socket
nix on PATH                     2.24.9                     installer's
devenv's bundled nix            devenv-nix-2.34-source
store db                        one /nix/var/nix/db/db.sqlite, agent-owned
non-interactive `sh -c`         devenv, direnv, nix all resolve
flakes                          experimental-features = nix-command flakes

That fourth group is the README's most substantive claim — "devenv 2.x bundles its own Nix … and shares the single-user store … both read and write the same store database" — and it is exactly right: two Nix versions, one store. The non-interactive check confirms the ENV PATH comment's reasoning too (bash -c never reads .bashrc).

The lock-churn claim: reproduced, full round trip

1.x:        devenv, flake-compat, git-hooks, nixpkgs, root   (5)
2.x:        devenv, nixpkgs, root                            (3)  <- strips
1.x again:  devenv, flake-compat, git-hooks, nixpkgs, root   (5)  <- re-adds

Worth recording a nuance I had to find the hard way: the churn only manifests when 2.x succeeds. On a repo that uses git-hooks.hooks, 2.x fails the assertion and leaves the lock untouched at 5 nodes. My first attempt tested the wrong shape and gave a misleading result.

.devenv/ cross-major reuse: verified in the risky direction

1.x -> 2.x -> 1.x on one shared .devenv/, all three exit 0. I specifically tested 1.x reading a .devenv/ that 2.x had rewritten, since that is the direction a mixed-CI team would hit.

Resolved two things I previously flagged as unverifiable

  • SecretSpec is in 2.1.2. src/modules/integrations/secretspec.nix exists at tag v2.1.2 (it arrived in 1.8). So the opt-in note is correct and load-bearing for the shipped version — this was my open question last round.
  • strict_ports is in 2.1.2, at devenv-core/src/config.rs:383 with an alias = "strictPorts". Not a 2.2-only key.

Also built the opencode variant

A merge publishes four images (shell and opencode × amd64/arm64), and I had only built shell. The opencode variant verifies identically, with its base toolchain intact (opencode 1.18.32), so the matrix is not broken by the pin bump.

Nit — the quoted error string does not exist

README:49-51:

A repo using git-hooks.hooks fails with git-hooks or pre-commit-hooks input required

The behaviour is right; the quote is not. Actual output from the built image:

error: Failed assertions:
- To use 'git-hooks', run the following command:

    $ devenv inputs add git-hooks github:cachix/git-hooks.nix --follows nixpkgs

The template is "To use '${attribute}', ${command}" (v2.1.2 src/modules/lib.nix:46). I checked whether the README was merely stale — the phrase appears in no tag I tested (v1.11.2, v2.0.0, v2.1.0, v2.1.2) and returns 0 code-search hits, so it is invented rather than outdated.

Not blocking, but worth fixing: it is what someone greps for when debugging, and the real message is more useful since it hands you the exact remediation command. The actual string also lets a reader distinguish this failure from an unrelated input error.

Two small things, take or leave

A local rebuild behind a TLS-inspecting proxy needs EXTRA_CA_CERT, and only the Dockerfile says so. The bare build fails at exit 60, and the cause is not obvious: github.com 302s to release-assets.githubusercontent.com, whose signed URL carries the path claim releaseassetproduction.blob.core.windows.net — an intercepted host on some corporate networks, while github.com itself is often on a bypass list. So the failure looks like a broken pin rather than a proxy. One line in the README's local-rebuild notes would save the next person the trace. The hatch itself works exactly as designed.

CI never builds this image on a PR — on: push: branches: [main] plus workflow_dispatch. A Dockerfile change merges unbuilt, and the first real build is the publish. That is a deliberate tradeoff (a PR build that pushed tags would be worse), but it does mean a local build is currently the only pre-merge signal. If a build-only, no-push PR job is cheap, it would close the gap.

Not verified

  • devenv processes down SIGKILL timing and the next-free-port behaviour — both need a long-running service in the container. Doable, not done.
  • amd64 for either variant. I built arm64 only; amd64 is emulated on this host.
  • Live acq/kit integration — image-level only.

AI-assisted review (OpenCode), approved on the maintainer's authority with their explicit go-ahead for this PR. Advisory — a human owns the merge.

@wz-gsa wz-gsa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. Converting my 2026-10-08 verdict into a formal review — it was posted as a comment, which left this sitting at REVIEW_REQUIRED and reading as unreviewed on the dashboard. My fault, not yours.

Confirmed the verdict still applies at the current head: 7838d574 → cf4db27d is main arriving (#453's paseo identity gate, #423's ADR). This PR's own three files are untouched:

git diff 7838d574 cf4db27d -- integrations/isolation/images/devenv
(empty)

Both findings from my first review are closed:

The x86_64-darwin claim is substantiated. I had flagged it as unverifiable because it is not in nixpkgs' package.nix metadata — no platforms or badPlatforms there. I was looking in the wrong place. Pulled cachix/devenv's v2.2 release notes:

Dropped x86_64-darwin (Intel macOS): devenv is no longer built, tested, or released for x86_64-darwin. Intel Mac users should pin an older devenv CLI release.

Your citation is accurate, and it settles the "only channel that is both devenv 2.x and release-pinned" conclusion the rationale was load-bearing for.

The version range is corrected. "2.2 and later exist only in nixpkgs-unstable (currently 2.4.0)" matches what I measured at unstable HEAD.

The #474 dependency is now stated accurately — "conceptual: that PR pins no devenv image tag, so nothing enforces the order" is exactly what I found when I searched that branch.

Carrying forward the pin verifications from the first pass, which still hold since the files did not change:

  • The pinned rev is genuinely on the release branch, not a cherry-pick: compare 0d9e9b8...nixos-26.05@HEAD returns ahead_by: 311, behind_by: 0.
  • devenv 2.1.2 and direnv 2.37.1 at that exact rev, not just at branch HEAD.
  • Channel progression confirms 2.x first appears in 26.05: 25.05 → 1.11.2, 25.11 → 1.11.1, 26.05 → 2.1.2.
  • No orphaned 1.0.0 image references anywhere in either repo, so the VERSION bump does not strand a consumer.

Unverified, unchanged: the image build, the in-sandbox smoke test (devenv 2.1.2, store ownership/permissions, nix store verify, cachix fetches), and the two-repo consumer-compatibility runs. No sandbox-capable host here; those stay on your reported evidence.

@wz-gsa
wz-gsa merged commit e042f14 into main Oct 9, 2026
7 checks passed
@wz-gsa
wz-gsa deleted the feat/devenv-image-2x branch October 9, 2026 20:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request supply-chain Dependency, script, provenance, external inspiration

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants