Merge final immutable-image qualification guard

Co-Authored-By: Paperclip <noreply@paperclip.ing>

* codex/runner-native-platform-prerequisites:
  fix(environments): bind platform facts to the effective immutable image
This commit is contained in:
DottaandPaperclip committed 2026-10-12 16:17:20 -05:00
commit f340d92b39
4 files changed
+26 -8

No files matched your search

+1 -1
View File
@@ -661,7 +661,7 @@ export async function resolveEnvironmentDriverConfigForRuntime(
// configuration and tooling so the test reflects what real agent runs use.
applyCustomImageTemplate?: boolean;
readOnlyCustomImageTemplate?: boolean;
onResolvedCustomImageTemplate?: (identity: { id: string; capturedAt: string | null }) => void;
onResolvedCustomImageTemplate?: (identity: { id: string; capturedAt: string | null; templateKind: string; bindingField: string }) => void;
},
): Promise<ParsedEnvironmentConfig> {
const parsed = parseEnvironmentDriverConfig(environment);
@@ -560,7 +560,7 @@ export async function resolveActiveEnvironmentCustomImageTemplateForRuntime(
secretRefExcludePaths?: Iterable<string>;
now?: Date;
readOnly?: boolean;
onResolvedTemplate?: (identity: { id: string; capturedAt: string | null }) => void;
onResolvedTemplate?: (identity: { id: string; capturedAt: string | null; templateKind: string; bindingField: string }) => void;
},
): Promise<SandboxEnvironmentConfig> {
const row = await db
@@ -591,7 +591,8 @@ export async function resolveActiveEnvironmentCustomImageTemplateForRuntime(
// match. Runtime-only knobs such as lease reuse, timeouts, and resource hints
// are excluded from the fingerprint so those edits do not discard the capture.
const now = input.now ?? new Date();
input.onResolvedTemplate?.({ id: row.id, capturedAt: row.capturedAt?.toISOString() ?? null });
input.onResolvedTemplate?.({ id: row.id, capturedAt: row.capturedAt?.toISOString() ?? null,
templateKind: row.templateKind ?? "unknown", bindingField: resolveEnvironmentCustomImageRuntimeConfigBinding(row).field });
if (!input.readOnly) await db
.update(environmentCustomImageTemplates)
.set({ lastUsedAt: now, updatedAt: now })
+5 -3
View File
@@ -34,15 +34,17 @@ export function parseSandboxPlatformFacts(output: string): PlatformFacts {
...(libc === "glibc" ? { glibcVersion: version?.trim() ?? "unknown" } : {}) };
}
async function sandboxBinding(db: Db, environment: Environment, companyId: string) {
let template: { id: string; capturedAt: string | null } | null = null;
const selectedTemplate: { value: { id: string; capturedAt: string | null; templateKind: string; bindingField: string } | null } = { value: null };
const parsed = await resolveEnvironmentDriverConfigForRuntime(db, companyId, environment, {
applyCustomImageTemplate: true, readOnlyCustomImageTemplate: true,
onResolvedCustomImageTemplate: identity => { template = identity; },
onResolvedCustomImageTemplate: identity => { selectedTemplate.value = identity; },
});
if (parsed.driver !== "sandbox") return null;
const image = parsed.config.image;
// Names, mutable tags, provider defaults and snapshot names are not immutable identities.
if (!isImmutableImage(image) || record(parsed.config).snapshot) return null;
const template = selectedTemplate.value;
if (!isImmutableImage(image) || ["snapshot", "template", "templateRef"].some(key => record(parsed.config)[key])
|| (template && (template.templateKind !== "image" || template.bindingField !== "image"))) return null;
return { baseConfigFingerprint: fingerprint(environment.config), runtimeConfigFingerprint: fingerprint(parsed.config as unknown as Record<string, unknown>), image, template };
}