ci(agent-image): gate the built image's env against wrong-image builds (RIG-1444) - #420
Merged
mattwilkinsonn merged 3 commits intoAug 19, 2026
Merged
Conversation
|
Compass engineering docs preview: https://compass-agent-rig-1444-agent.compass-eng-docs.pages.dev Deployed from |
…s (RIG-1444) A green `container build` proves the compass-agent image realises; it does not prove the image is correct. Three wrong-image defects have shipped through a successful build, each caught only by hand-inspecting the image: a build-host home path baked into DEVENV_ROOT (non-reproducible across build hosts), a DEVENV_ROOT=/env the image does not carry (mkdir/ln errors on every container start), and a stale DEVENV_CONTAINER corrupting an unrelated image. All three leave one fingerprint: a DEVENV_-prefixed key surviving the fork's imageEnv filter (forks/devenv/src/modules/containers.nix) into the image's OCI config.Env — a sealed-added filter the fork's own suite cannot cover. Add tools/agent-image-env-gate, a moon project that builds the exact spec the publish lane ships, inspects its OCI config through the fork's nix:-transport skopeo, and fails on a leaked DEVENV_ key, a build-host home path in the env, or a platform-contract (linux/amd64) drift. Its inputs mirror agent-image's build closure, so the assertion runs on exactly the PRs that can change the image. The pure core (env-check.ts) is unit-tested against each historical defect shape; the check task depends on compass-agent-image:build so the realise is ordered first and the build here is a store cache hit. Co-authored-by: Matt Wilkinson <matt@rigel.build>
…ths (RIG-1444) Review fixes for the agent-image env-gate. Extract the runner's non-shell logic into pure, exported seams — `extractSpec` (last-line store-path pick) and `evaluateImage` (Os/Arch drift + absent-Env + forbidden-env, over the pure `findForbiddenEnv`) — and move the imperative body under `import.meta.main`, matching the sibling cx-token-gate's tested-runner shape. Add `index.test.ts` (12 tests) over those seams. Harden the runner's failure paths: both `nix`/`skopeo` shell calls now route a non-zero exit through `fail()` (prefixed message + exit 1) instead of a raw ShellError; an unset `HOME` emits a WARN that the build-host-home leak check is inactive; an absent or empty `config.Env` is now itself a wrong-image signal. Reciprocal mirror-drift reminder added to agent-image/moon.yml. Spec-impact: none. Refs RIG-1444 Co-authored-by: Matt Wilkinson <matt@rigel.build>
…s (RIG-1444)
Address the round-2 review nit: the Os/Architecture drift tests probed with a broad `.includes('Os')`/`.includes('Architecture')` substring, which would not catch a message-wording regression. Tighten both to exact-message `toContain` checks, matching the unset-Os test's contract-defending style.
Spec-impact: none. Refs RIG-1444
Co-authored-by: Matt Wilkinson <matt@rigel.build>
rigel-mintaka
force-pushed
the
compass-agent/rig-1444-agent-image-env-gate
branch
from
August 19, 2026 20:25
5e72053 to
5bb4312
Compare
mattwilkinsonn
approved these changes
Aug 19, 2026
rigel-mintaka
added a commit
that referenced
this pull request
Aug 19, 2026
…nt main Folds the PR #434 review findings into the RIG-2336 forks-reversal record: - HIGH: add tools/agent-image-env-gate/ to the L1/L2 consumer inventory. It is a registered moon project that both globs /forks/{devenv,nix2container}/** for affected-detection and invokes the fork CLIs raw (index.ts:100,118), so a repoint that omits it leaves dead input globs (silently disabling the fail-closed gate) and dangling path:../forks/* CLI refs (reddening main). index.ts:118 is also an OQ2 divergence site. - Re-ground planning-evidence base 7d77f50 -> 13a43ce (current main; #420/#429 landed). Correct drifted .moon/workspace.yml (78/79/80-83) and agent-image/moon.yml (69/70) citations. - L3: the generated header at credential_keys_gen.go:3 comes from a hardcoded literal at gen_credential_keys.go:74, not from schemaRelPath:42 — add :74 to the edit list (regeneration alone re-emits the deleted path). Pin the npm schema path to the resolved packages/compass-agent/node_modules/ location (not top-level hoisted). Reword the byte-identity expectation: v17.1.8 vendored vs 16.5.2 npm is a major gap, so expect a denylist diff and re-review the TestCredentialKeysMatchSchema want set in the same PR. Refs RIG-2336 Co-authored-by: Matt Wilkinson <matt@rigel.build>
rigel-mintaka
added a commit
that referenced
this pull request
Aug 19, 2026
…nt main Folds the PR #434 review findings into the RIG-2336 forks-reversal record. Round 1 (1 HIGH + 3 MEDIUM + 2 LOW): - HIGH: add tools/agent-image-env-gate/ to the L1/L2 consumer inventory. It is a registered moon project that both globs /forks/{devenv,nix2container}/** for affected-detection and invokes the fork CLIs raw (index.ts:100,118), so a repoint that omits it leaves dead input globs (silently disabling the fail-closed gate) and dangling path:../forks/* CLI refs (reddening main). index.ts:118 is also an OQ2 divergence site. - Re-ground planning-evidence base 7d77f50 -> 13a43ce (current main; #420/#429 landed). Correct drifted .moon/workspace.yml (78/79/80-83) and agent-image/moon.yml (69/70) citations. - L3: the generated header at credential_keys_gen.go:3 comes from a hardcoded literal at gen_credential_keys.go:74, not from schemaRelPath:42 — add :74 to the edit list (regeneration alone re-emits the deleted path). Pin the npm schema path to the resolved packages/compass-agent/node_modules/ location (not top-level hoisted). Reword the byte-identity expectation: v17.1.8 vendored vs 16.5.2 npm is a major gap, so expect a denylist diff and re-review the TestCredentialKeysMatchSchema want set in the same PR. Round 2 (2 LOW prose-accuracy folds): - Narrow the "no Renovate" claim: the only renovate.json is upstream's inside forks/devenv/.github/ (no compass workflow runs it; L2 deletes it with the subtree) — not "none anywhere in this checkout". - L4: delete the dangling shared fork-projects comment block .moon/workspace.yml:64-77 once all three -fork entries are gone; cover the markdownlint-cli2 rationale comment (:5-6) alongside the ignore entry (:23). Add agent-image/moon.yml:5,38 (path:../forks/devenv example + cwd-rationale comment) to the L2 comment sweep. Refs RIG-2336 Co-authored-by: Matt Wilkinson <matt@rigel.build>
rigel-mintaka
added a commit
that referenced
this pull request
Aug 20, 2026
…nt main Folds the PR #434 review findings into the RIG-2336 forks-reversal record. Round 1 (1 HIGH + 3 MEDIUM + 2 LOW): - HIGH: add tools/agent-image-env-gate/ to the L1/L2 consumer inventory. It is a registered moon project that both globs /forks/{devenv,nix2container}/** for affected-detection and invokes the fork CLIs raw (index.ts:100,118), so a repoint that omits it leaves dead input globs (silently disabling the fail-closed gate) and dangling path:../forks/* CLI refs (reddening main). index.ts:118 is also an OQ2 divergence site. - Re-ground planning-evidence base 7d77f50 -> 13a43ce (current main; #420/#429 landed). Correct drifted .moon/workspace.yml (78/79/80-83) and agent-image/moon.yml (69/70) citations. - L3: the generated header at credential_keys_gen.go:3 comes from a hardcoded literal at gen_credential_keys.go:74, not from schemaRelPath:42 — add :74 to the edit list (regeneration alone re-emits the deleted path). Pin the npm schema path to the resolved packages/compass-agent/node_modules/ location (not top-level hoisted). Reword the byte-identity expectation: v17.1.8 vendored vs 16.5.2 npm is a major gap, so expect a denylist diff and re-review the TestCredentialKeysMatchSchema want set in the same PR. Round 2 (2 LOW prose-accuracy folds): - Narrow the "no Renovate" claim: the only renovate.json is upstream's inside forks/devenv/.github/ (no compass workflow runs it; L2 deletes it with the subtree) — not "none anywhere in this checkout". - L4: delete the dangling shared fork-projects comment block .moon/workspace.yml:64-77 once all three -fork entries are gone; cover the markdownlint-cli2 rationale comment (:5-6) alongside the ignore entry (:23). Add agent-image/moon.yml:5,38 (path:../forks/devenv example + cwd-rationale comment) to the L2 comment sweep. Cross-lane (forge, verified against orion at source): - OQ2 (rev-pin shape): narrow it. orion has frozen the nix-flake-input class as github:RigelBuild/<fork> pinned via lockfile (oss-fork-github-native-reversal.md:142-155 — the deliberate default + RIG-1860 whole-repo-narHash fix), so compass's one flake-input consumer (agent-image/devenv.lock) converges with no reason to diverge. The genuinely open half is compass-specific: the six raw-CLI sites that bypass devenv.lock (orion has no raw-CLI equivalent). Recommendation stays a compass-side re-export flake; the coherent alternative is orion's literal style + a CI rev-equality assert. Matt rules only the raw-CLI shape. - L0a devenv base rev afed7bf3 confirmed matching orion (devenv.lock:33). Refs RIG-2336 Co-authored-by: Matt Wilkinson <matt@rigel.build>
rigel-mintaka
added a commit
that referenced
this pull request
Aug 20, 2026
…nt main Folds the PR #434 review findings into the RIG-2336 forks-reversal record. Round 1 (1 HIGH + 3 MEDIUM + 2 LOW): - HIGH: add tools/agent-image-env-gate/ to the L1/L2 consumer inventory. It is a registered moon project that both globs /forks/{devenv,nix2container}/** for affected-detection and invokes the fork CLIs raw (index.ts:100,118), so a repoint that omits it leaves dead input globs (silently disabling the fail-closed gate) and dangling path:../forks/* CLI refs (reddening main). index.ts:118 is also an OQ2 divergence site. - Re-ground planning-evidence base 7d77f50 -> 13a43ce (current main; #420/#429 landed). Correct drifted .moon/workspace.yml (78/79/80-83) and agent-image/moon.yml (69/70) citations. - L3: the generated header at credential_keys_gen.go:3 comes from a hardcoded literal at gen_credential_keys.go:74, not from schemaRelPath:42 — add :74 to the edit list (regeneration alone re-emits the deleted path). Pin the npm schema path to the resolved packages/compass-agent/node_modules/ location (not top-level hoisted). Reword the byte-identity expectation: v17.1.8 vendored vs 16.5.2 npm is a major gap, so expect a denylist diff and re-review the TestCredentialKeysMatchSchema want set in the same PR. Round 2 (2 LOW prose-accuracy folds): - Narrow the "no Renovate" claim: the only renovate.json is upstream's inside forks/devenv/.github/ (no compass workflow runs it; L2 deletes it with the subtree) — not "none anywhere in this checkout". - L4: delete the dangling shared fork-projects comment block .moon/workspace.yml:64-77 once all three -fork entries are gone; cover the markdownlint-cli2 rationale comment (:5-6) alongside the ignore entry (:23). Add agent-image/moon.yml:5,38 (path:../forks/devenv example + cwd-rationale comment) to the L2 comment sweep. Cross-lane (forge, verified against orion at source): - OQ2 (rev-pin shape): narrow it. orion's frozen class table (oss-fork-github-native-reversal.md:142-147) has four import classes (flake-input, standalone-executable, GHCR-image, no-consumer) but NO raw-CLI-bypass class, so its flake-input default (github:RigelBuild/<fork> pinned via lockfile, :142-155, +RIG-1860 narHash fix) settles compass's one flake input (agent-image/devenv.lock) but not the six raw-CLI sites that bypass devenv.lock. The still-open half is compass-specific. Recommendation stays a compass-side re-export flake (no orion analog); the coherent alternative — literals + a CI rev-equality assert — mirrors orion's terraform-provider release-pin pattern (:145,166-178: pinned non-flake consumption, committed sha256 verified at build time). Matt rules only the raw-CLI shape. - L0a devenv base rev afed7bf3 confirmed matching orion (devenv.lock:33). Refs RIG-2336 Co-authored-by: Matt Wilkinson <matt@rigel.build>
rigel-mintaka
added a commit
that referenced
this pull request
Aug 20, 2026
…nt main Folds the PR #434 review findings into the RIG-2336 forks-reversal record. Round 1 (1 HIGH + 3 MEDIUM + 2 LOW): - HIGH: add tools/agent-image-env-gate/ to the L1/L2 consumer inventory. It is a registered moon project that both globs /forks/{devenv,nix2container}/** for affected-detection and invokes the fork CLIs raw (index.ts:100,118), so a repoint that omits it leaves dead input globs (silently disabling the fail-closed gate) and dangling path:../forks/* CLI refs (reddening main). index.ts:118 is also an OQ2 divergence site. - Re-ground planning-evidence base 7d77f50 -> 13a43ce (current main; #420/#429 landed). Correct drifted .moon/workspace.yml (78/79/80-83) and agent-image/moon.yml (69/70) citations. - L3: the generated header at credential_keys_gen.go:3 comes from a hardcoded literal at gen_credential_keys.go:74, not from schemaRelPath:42 — add :74 to the edit list (regeneration alone re-emits the deleted path). Pin the npm schema path to the resolved packages/compass-agent/node_modules/ location (not top-level hoisted). Reword the byte-identity expectation: v17.1.8 vendored vs 16.5.2 npm is a major gap, so expect a denylist diff and re-review the TestCredentialKeysMatchSchema want set in the same PR. Round 2 (2 LOW prose-accuracy folds): - Narrow the "no Renovate" claim: the only renovate.json is upstream's inside forks/devenv/.github/ (no compass workflow runs it; L2 deletes it with the subtree) — not "none anywhere in this checkout". - L4: delete the dangling shared fork-projects comment block .moon/workspace.yml:64-77 once all three -fork entries are gone; cover the markdownlint-cli2 rationale comment (:5-6) alongside the ignore entry (:23). Add agent-image/moon.yml:5,38 (path:../forks/devenv example + cwd-rationale comment) to the L2 comment sweep. Cross-lane (forge, verified against orion at source): - OQ2 (rev-pin shape): narrow it. orion's frozen class table (oss-fork-github-native-reversal.md:142-147) has four import classes (flake-input, standalone-executable, GHCR-image, no-consumer) but NO raw-CLI-bypass class, so its flake-input default (github:RigelBuild/<fork> pinned via lockfile, :142-155, +RIG-1860 narHash fix) settles compass's one flake input (agent-image/devenv.lock) but not the six raw-CLI sites that bypass devenv.lock. The still-open half is compass-specific. Recommendation stays a compass-side re-export flake (no orion analog); the coherent alternative — literals + a CI rev-equality assert — mirrors orion's terraform-provider release-pin pattern (:145,166-178: pinned non-flake consumption, committed sha256 verified at build time). Matt rules only the raw-CLI shape. - L0a devenv base rev afed7bf3 confirmed matching orion (devenv.lock:33). - nix2container prerequisite CLEARED (forge #1483-merge ping, re-verified at source): orion PR #1483 (RIG-2215) merged 2026-08-19 (mergeCommit f561bd97, via gh api); the canonical fork RigelBuild/nix2container main is at rev 8f4a6fd7b10abaeeddff6c4d8bb4908c5123c90c (git ls-remote, public) — upstream master plus the one relocated-copyToRoot-paths patch, the same nix-DB-drop fix compass carries at forks/nix2container/default.nix:386-395. Folded: L0b marked done with the concrete rev; L1 consume target pinned to 8f4a6fd7 (Matt's one-fork-per-upstream — consume the shared repo, no duplicate); the RIG-2332 arm64-builder block recorded as resolved; dependency/execution-order note updated (L1 no longer gated on an open-ended external block). Refs RIG-2336 Co-authored-by: Matt Wilkinson <matt@rigel.build>
mattwilkinsonn
added a commit
that referenced
this pull request
Aug 21, 2026
…igelBuild repos (RIG-2336) (#434) * docs(design): compass forks-reversal — externalize forks/ to shared RigelBuild repos (RIG-2336) Design record for reversing compass's forks/ vendoring: each of the three vendored subtrees (devenv, nix2container, oh-my-pi) returns to its public RigelBuild/* repo, and compass consumes it as a pinned github: nix flake input, removing the subtrees (~7424 tracked files) and their carrying machinery. Frozen decision (Matt, 2026-08-19): shared RigelBuild/{devenv,nix2container, oh-my-pi} repos + combined patch work with orion's reversal (RIG-2213), not compass-own forks. Coordinated the disjoint-patch-ownership contract with forge (owns nix2container fix + scaffolding; compass owns devenv containers.nix patch). Ships as its own PR per skill://design; freezes on merge; impl lanes (L0-L4) are filed from the frozen record. Two load-bearing Open Questions for Matt: oh-my-pi drop-vs-consume, and the raw-CLI pin shape (rev-literal vs one lockfile). Refs RIG-2336 Co-authored-by: Matt Wilkinson <matt@rigel.build> * docs(design): address review — env-gate consumer + re-ground at current main Folds the PR #434 review findings into the RIG-2336 forks-reversal record. Round 1 (1 HIGH + 3 MEDIUM + 2 LOW): - HIGH: add tools/agent-image-env-gate/ to the L1/L2 consumer inventory. It is a registered moon project that both globs /forks/{devenv,nix2container}/** for affected-detection and invokes the fork CLIs raw (index.ts:100,118), so a repoint that omits it leaves dead input globs (silently disabling the fail-closed gate) and dangling path:../forks/* CLI refs (reddening main). index.ts:118 is also an OQ2 divergence site. - Re-ground planning-evidence base 7d77f50 -> 13a43ce (current main; #420/#429 landed). Correct drifted .moon/workspace.yml (78/79/80-83) and agent-image/moon.yml (69/70) citations. - L3: the generated header at credential_keys_gen.go:3 comes from a hardcoded literal at gen_credential_keys.go:74, not from schemaRelPath:42 — add :74 to the edit list (regeneration alone re-emits the deleted path). Pin the npm schema path to the resolved packages/compass-agent/node_modules/ location (not top-level hoisted). Reword the byte-identity expectation: v17.1.8 vendored vs 16.5.2 npm is a major gap, so expect a denylist diff and re-review the TestCredentialKeysMatchSchema want set in the same PR. Round 2 (2 LOW prose-accuracy folds): - Narrow the "no Renovate" claim: the only renovate.json is upstream's inside forks/devenv/.github/ (no compass workflow runs it; L2 deletes it with the subtree) — not "none anywhere in this checkout". - L4: delete the dangling shared fork-projects comment block .moon/workspace.yml:64-77 once all three -fork entries are gone; cover the markdownlint-cli2 rationale comment (:5-6) alongside the ignore entry (:23). Add agent-image/moon.yml:5,38 (path:../forks/devenv example + cwd-rationale comment) to the L2 comment sweep. Cross-lane (forge, verified against orion at source): - OQ2 (rev-pin shape): narrow it. orion's frozen class table (oss-fork-github-native-reversal.md:142-147) has four import classes (flake-input, standalone-executable, GHCR-image, no-consumer) but NO raw-CLI-bypass class, so its flake-input default (github:RigelBuild/<fork> pinned via lockfile, :142-155, +RIG-1860 narHash fix) settles compass's one flake input (agent-image/devenv.lock) but not the six raw-CLI sites that bypass devenv.lock. The still-open half is compass-specific. Recommendation stays a compass-side re-export flake (no orion analog); the coherent alternative — literals + a CI rev-equality assert — mirrors orion's terraform-provider release-pin pattern (:145,166-178: pinned non-flake consumption, committed sha256 verified at build time). Matt rules only the raw-CLI shape. - L0a devenv base rev afed7bf3 confirmed matching orion (devenv.lock:33). - nix2container prerequisite CLEARED (forge #1483-merge ping, re-verified at source): orion PR #1483 (RIG-2215) merged 2026-08-19 (mergeCommit f561bd97, via gh api); the canonical fork RigelBuild/nix2container main is at rev 8f4a6fd7b10abaeeddff6c4d8bb4908c5123c90c (git ls-remote, public) — upstream master plus the one relocated-copyToRoot-paths patch, the same nix-DB-drop fix compass carries at forks/nix2container/default.nix:386-395. Folded: L0b marked done with the concrete rev; L1 consume target pinned to 8f4a6fd7 (Matt's one-fork-per-upstream — consume the shared repo, no duplicate); the RIG-2332 arm64-builder block recorded as resolved; dependency/execution-order note updated (L1 no longer gated on an open-ended external block). Refs RIG-2336 Co-authored-by: Matt Wilkinson <matt@rigel.build> --------- Co-authored-by: Matt Wilkinson <matt@rigel.build>
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.
A green
container buildproves the compass-agent image realises; it does notprove the image is correct. Three wrong-image defects have shipped through a
successful build, each caught only by hand-inspecting the image: a build-host
home path baked into DEVENV_ROOT (non-reproducible across build hosts), a
DEVENV_ROOT=/env the image does not carry (mkdir/ln errors on every container
start), and a stale DEVENV_CONTAINER corrupting an unrelated image. All three
leave one fingerprint: a DEVENV_-prefixed key surviving the fork's imageEnv
filter (forks/devenv/src/modules/containers.nix) into the image's OCI
config.Env — a sealed-added filter the fork's own suite cannot cover.
Add tools/agent-image-env-gate, a moon project that builds the exact spec the
publish lane ships, inspects its OCI config through the fork's nix:-transport
skopeo, and fails on a leaked DEVENV_ key, a build-host home path in the env, or
a platform-contract (linux/amd64) drift. Its inputs mirror agent-image's build
closure, so the assertion runs on exactly the PRs that can change the image.
The pure core (env-check.ts) is unit-tested against each historical defect
shape; the check task depends on compass-agent-image:build so the realise is
ordered first and the build here is a store cache hit.
Co-authored-by: Matt Wilkinson matt@rigel.build