From fc27975113b5b93b925f05ede28930d03da06c7f Mon Sep 17 00:00:00 2001 From: sanjey99 Date: Tue, 1 Sep 2026 11:21:36 +0800 Subject: [PATCH] fix: wire live verifier through state volume ## Summary Make the containerized live Runtime gate address independent verification snapshots through its wrapper-provided Docker state volume. ## Root cause The live gate omitted containerStateRoot and containerStateVolume when constructing ContainerVerifier. That forced a host bind mount for a controller-private path, so Docker could not create the verifier container. ## Fix - Pass the resolved state root and volume to the live verifier. - Add a causal composition regression for both coordinates. ## Testing - Observed the new regression fail before the fix and pass after it. - Targeted composition tests: 5 passed. - Server test typecheck passed. - Live test list and credential-free container preflight passed. Refs #111 --- .../shepherd/live-runtime.composition.test.ts | 28 +++++++++++++++++++ .../shepherd/live-runtime.integration.test.ts | 2 ++ 2 files changed, 30 insertions(+) create mode 100644 apps/server/src/shepherd/live-runtime.composition.test.ts diff --git a/apps/server/src/shepherd/live-runtime.composition.test.ts b/apps/server/src/shepherd/live-runtime.composition.test.ts new file mode 100644 index 0000000..cc638fa --- /dev/null +++ b/apps/server/src/shepherd/live-runtime.composition.test.ts @@ -0,0 +1,28 @@ +import { readFile } from "node:fs/promises"; +import path from "node:path"; +import { describe, expect, it } from "vitest"; + +function liveVerifierArguments(source: string): string { + const expression = "new ContainerVerifier(registry(), {"; + const start = source.indexOf(expression); + if (start < 0) throw new Error("live verifier composition site was not found"); + const close = /^\s*\}\);/mu.exec(source.slice(start)); + if (!close) throw new Error("live verifier composition site was not terminated"); + return source + .slice(start, start + close.index) + .replace(/\/\/[^\n]*/gu, "") + .replace(/\/\*[\s\S]*?\*\//gu, ""); +} + +describe("live Runtime verifier composition", () => { + it("addresses independent verification snapshots through the controller state volume", async () => { + const source = await readFile( + path.resolve(process.cwd(), "src/shepherd/live-runtime.integration.test.ts"), + "utf8", + ); + const options = liveVerifierArguments(source); + + expect(options).toContain("stateRoot: config.containerStateRoot"); + expect(options).toContain("stateVolume: config.containerStateVolume"); + }); +}); diff --git a/apps/server/src/shepherd/live-runtime.integration.test.ts b/apps/server/src/shepherd/live-runtime.integration.test.ts index c122094..d865b72 100644 --- a/apps/server/src/shepherd/live-runtime.integration.test.ts +++ b/apps/server/src/shepherd/live-runtime.integration.test.ts @@ -439,6 +439,8 @@ describe.skipIf(!liveEnabled)("Shepherd live Codex Runtime gate", () => { maxTimeoutMs: config.shepherdVerificationTimeoutMs, maxOutputBytes: config.codexMaxOutputBytes, sensitiveValues: [config.arkApiKey, config.authToken], + stateRoot: config.containerStateRoot, + stateVolume: config.containerStateVolume, }); verifiers.push(verifier); const store = new JsonStore(statePath, {