From 6528330be8f0f009ca585cf13f7161223292b358 Mon Sep 17 00:00:00 2001 From: Erik <262919414+try-works@users.noreply.github.com> Date: Mon, 31 Aug 2026 19:33:35 +0800 Subject: [PATCH 01/11] fix(runtime): bound private storage reads --- .../src/track-b-operations.ts | 34 ++++++++++++++----- .../test/track-b-operations-api.test.ts | 29 ++++++++++++++++ 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/role-model-router/apps/runtime-host-bridge/src/track-b-operations.ts b/role-model-router/apps/runtime-host-bridge/src/track-b-operations.ts index 3f975dff..884821db 100644 --- a/role-model-router/apps/runtime-host-bridge/src/track-b-operations.ts +++ b/role-model-router/apps/runtime-host-bridge/src/track-b-operations.ts @@ -661,6 +661,7 @@ const privateRetentionRequest = async ( token: string | undefined, route: string, init: { readonly method?: string; readonly body?: Record } = {}, + timeoutMs = 5_000, ): Promise => { if (!endpoint) return null; if (!token || token.trim().length < 24) { @@ -668,14 +669,26 @@ const privateRetentionRequest = async ( "Track B private operations boundary requires a launcher-issued authentication token", ); } - const response = await fetch(new URL(route, endpoint.endsWith("/") ? endpoint : `${endpoint}/`), { - method: init.method ?? "GET", - headers: { - ...(init.body ? { "content-type": "application/json" } : {}), - authorization: `Bearer ${token}`, - }, - ...(init.body ? { body: JSON.stringify(init.body) } : {}), - }); + let response: Response; + try { + response = await fetch(new URL(route, endpoint.endsWith("/") ? endpoint : `${endpoint}/`), { + method: init.method ?? "GET", + headers: { + ...(init.body ? { "content-type": "application/json" } : {}), + authorization: `Bearer ${token}`, + }, + ...(init.body ? { body: JSON.stringify(init.body) } : {}), + signal: AbortSignal.timeout(timeoutMs), + }); + } catch (error) { + if (error instanceof Error && error.name === "TimeoutError") { + throw new TrackBPrivateOperationError( + 504, + `private Track B operation timed out after ${timeoutMs}ms`, + ); + } + throw error; + } const result = (await response.json().catch(() => ({}))) as { readonly error?: unknown }; if (!response.ok) throw new TrackBPrivateOperationError( @@ -1060,6 +1073,7 @@ export function createTrackBOperations({ runtimeChannel = "development", operationsEndpoint = process.env.ROLE_MODEL_TRACK_B_OPERATIONS_URL?.trim(), operationsToken = process.env.ROLE_MODEL_TRACK_B_OPERATIONS_TOKEN, + operationsTimeoutMs = 5_000, extensionRuntime, }: { readonly statePath: string; @@ -1067,6 +1081,8 @@ export function createTrackBOperations({ readonly runtimeChannel?: "development" | "stage" | "production"; readonly operationsEndpoint?: string; readonly operationsToken?: string; + /** Bounds a private sidecar operation so a dashboard request cannot wait forever. */ + readonly operationsTimeoutMs?: number; readonly extensionRuntime?: { listExtensions(): readonly unknown[] | Promise; mutateExtension(input: Record): unknown | Promise; @@ -1075,7 +1091,7 @@ export function createTrackBOperations({ const requestPrivate = ( route: string, init?: { readonly method?: string; readonly body?: Record }, - ) => privateRetentionRequest(operationsEndpoint, operationsToken, route, init); + ) => privateRetentionRequest(operationsEndpoint, operationsToken, route, init, operationsTimeoutMs); return { async readGraphMigration(): Promise { const remote = await requestPrivate("graph-migration"); diff --git a/role-model-router/apps/runtime-host-bridge/test/track-b-operations-api.test.ts b/role-model-router/apps/runtime-host-bridge/test/track-b-operations-api.test.ts index db5f19f0..3e1135f0 100644 --- a/role-model-router/apps/runtime-host-bridge/test/track-b-operations-api.test.ts +++ b/role-model-router/apps/runtime-host-bridge/test/track-b-operations-api.test.ts @@ -2061,6 +2061,35 @@ describe("Track B operations APIs", () => { } }); + test("run95 bounds a stalled private storage summary instead of leaving the operator read pending", async () => { + const operations = createServer((_request, _response) => { + // Deliberately never respond: this models a stalled private sidecar. + }); + await new Promise((resolve, reject) => { + operations.once("error", reject); + operations.listen(0, "127.0.0.1", resolve); + }); + try { + const address = operations.address(); + if (!address || typeof address === "string") + throw new Error("operations server did not bind"); + const api = createTrackBOperations({ + statePath: path.join(os.tmpdir(), `run95-stalled-storage-${Date.now()}.json`), + catalog: [], + operationsEndpoint: `http://127.0.0.1:${address.port}`, + operationsToken: "run95-stalled-storage-token-0001", + operationsTimeoutMs: 25, + }); + const startedAt = Date.now(); + await expect(api.readStorageRetention()).rejects.toThrow(/timed out/i); + expect(Date.now() - startedAt).toBeLessThan(1_000); + } finally { + await new Promise((resolve, reject) => + operations.close((error) => (error ? reject(error) : resolve())), + ); + } + }); + test("run79 mutateExtension enables disables and sets mode with audit receipts", async () => { const runtimeStateRoot = path.join(os.tmpdir(), `track-b-run79-mutate-${Date.now()}`); roots.push(runtimeStateRoot); From 9cfd764a274f62e7ff730de0b09b53f12f8e627a Mon Sep 17 00:00:00 2001 From: Erik <262919414+try-works@users.noreply.github.com> Date: Mon, 31 Aug 2026 19:50:08 +0800 Subject: [PATCH 02/11] fix(runtime): resolve packaged taxonomy data --- .../packages/core/src/taxonomy/index.test.ts | 22 +++++++++++++++++++ .../packages/core/src/taxonomy/index.ts | 12 +++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 role-model-router/packages/core/src/taxonomy/index.test.ts diff --git a/role-model-router/packages/core/src/taxonomy/index.test.ts b/role-model-router/packages/core/src/taxonomy/index.test.ts new file mode 100644 index 00000000..f11c777d --- /dev/null +++ b/role-model-router/packages/core/src/taxonomy/index.test.ts @@ -0,0 +1,22 @@ +import path from "node:path"; +import { describe, expect, test } from "vitest"; + +import { taxonomyDataRootCandidates } from "./index.js"; + +describe("taxonomyDataRootCandidates", () => { + test("R95 resolves the taxonomy staged next to a packaged executable", () => { + const executablePath = path.join("D:", "release", "role-model-dev.exe"); + + expect(taxonomyDataRootCandidates(executablePath)).toContain( + path.join( + "D:", + "release", + "role-model-router", + "packages", + "core", + "data", + "taxonomy", + ), + ); + }); +}); diff --git a/role-model-router/packages/core/src/taxonomy/index.ts b/role-model-router/packages/core/src/taxonomy/index.ts index 2d969e62..6ae72f43 100644 --- a/role-model-router/packages/core/src/taxonomy/index.ts +++ b/role-model-router/packages/core/src/taxonomy/index.ts @@ -152,11 +152,21 @@ function readArgValue(name: string): string | undefined { return index >= 0 ? process.argv[index + 1] : undefined; } -const taxonomyDataRootCandidates = (): string[] => { +export const taxonomyDataRootCandidates = (executablePath = process.execPath): string[] => { const explicitRoot = process.env.ROLE_MODEL_TAXONOMY_DATA_ROOT; const repoRoot = readArgValue("--repo-root") ?? process.env.ROLE_MODEL_REPO_ROOT; return [ ...(explicitRoot ? [explicitRoot] : []), + // A SEA executable has no source checkout to resolve from. Packaging stages this + // directory beside the executable, so prefer that self-contained release path. + path.join( + path.dirname(executablePath), + "role-model-router", + "packages", + "core", + "data", + "taxonomy", + ), ...(repoRoot ? [path.join(repoRoot, "role-model-router", "packages", "core", "data", "taxonomy")] : []), From c25904e3907ac13fbdc36bf4eb1a8d42a0914418 Mon Sep 17 00:00:00 2001 From: Erik <262919414+try-works@users.noreply.github.com> Date: Mon, 31 Aug 2026 20:09:08 +0800 Subject: [PATCH 03/11] fix(runtime): retain Track B capture failure class --- .../apps/runtime-host-bridge/src/index.ts | 27 ++++++-- .../test/track-b-operations-api.test.ts | 68 +++++++++++++++++++ 2 files changed, 91 insertions(+), 4 deletions(-) diff --git a/role-model-router/apps/runtime-host-bridge/src/index.ts b/role-model-router/apps/runtime-host-bridge/src/index.ts index 83e5d7fd..51c1c572 100644 --- a/role-model-router/apps/runtime-host-bridge/src/index.ts +++ b/role-model-router/apps/runtime-host-bridge/src/index.ts @@ -24070,6 +24070,7 @@ export async function createRuntimeBridgeBackend( | { readonly scopeId: string; readonly artifactId: string; readonly contentHash: string } | undefined; let routeCapture: Record | undefined; + let routeCaptureDegradationReason: string | undefined; try { if (localGraphStore) { const content = JSON.stringify(bundle); @@ -24116,10 +24117,25 @@ export async function createRuntimeBridgeBackend( }; } } - } catch { + } catch (error) { // Capture remains non-routing-critical before graph-primary cutover. // Run 94 (SP2): without a graph artifact reference the SQLite row must still be // bounded — persist the compact degradation stub instead of the full bundle. + // Keep the operator receipt actionable without copying a private-boundary + // message, which may include untrusted capture content. + const status = + error && + typeof error === "object" && + "status" in error && + typeof error.status === "number" && + Number.isInteger(error.status) + ? error.status + : undefined; + routeCaptureDegradationReason = + status && status >= 100 && status <= 599 + ? `track-b-capture-boundary-http-${status}` + : "track-b-capture-boundary-unavailable"; + console.error("Track B route capture failed", routeCaptureDegradationReason); } const graphEvidence = routeCapture ? { @@ -24160,9 +24176,12 @@ export async function createRuntimeBridgeBackend( schemaVersion: "role-model.degradation-receipt.v1", degraded: true, capability: "runtime-observation-persist", - reason: String( - error instanceof Error ? error.message : "runtime observation persist failed", - ).slice(0, 256), + reason: + routeCaptureDegradationReason ?? + String(error instanceof Error ? error.message : "runtime observation persist failed").slice( + 0, + 256, + ), routingContinues: true, atMs: Date.now(), }; diff --git a/role-model-router/apps/runtime-host-bridge/test/track-b-operations-api.test.ts b/role-model-router/apps/runtime-host-bridge/test/track-b-operations-api.test.ts index 3e1135f0..bd8e89ef 100644 --- a/role-model-router/apps/runtime-host-bridge/test/track-b-operations-api.test.ts +++ b/role-model-router/apps/runtime-host-bridge/test/track-b-operations-api.test.ts @@ -1205,6 +1205,74 @@ describe("Track B operations APIs", () => { } }); + test("reports a bounded private capture failure instead of masking it as a graph writer error", async () => { + const runtimeStateRoot = path.join(os.tmpdir(), `track-b-capture-failure-${Date.now()}`); + roots.push(runtimeStateRoot); + const scopeId = "track-b-capture-failure"; + const operations = createServer(async (request, response) => { + for await (const _chunk of request) { + // Drain the request without retaining potentially rich capture content. + } + if (request.url === "/capture/route") { + response.writeHead(503, { "content-type": "application/json" }); + response.end(JSON.stringify({ error: "capture service unavailable" })); + return; + } + response.writeHead(200, { "content-type": "application/json" }); + response.end(JSON.stringify({ status: "accepted" })); + }); + await new Promise((resolve, reject) => { + operations.once("error", reject); + operations.listen(0, "127.0.0.1", resolve); + }); + const address = operations.address(); + if (!address || typeof address === "string") throw new Error("operations server did not bind"); + const backend = await createRuntimeBridgeBackend({ + repoRoot, + fixtureRoot, + runtimeStateRoot, + scopeId, + trackBOperationsEndpoint: `http://127.0.0.1:${address.port}`, + trackBOperationsToken: "c".repeat(64), + }); + try { + const databasePath = resolveSqliteMemoryLocation({ runtimeStateRoot, scopeId }); + const migration = new LegacySqliteMigration({ + databasePath, + backupPath: path.join(runtimeStateRoot, "legacy-backup.sqlite"), + artifactWriter: ({ contentHash }) => ({ + artifactId: contentHash, + artifactPath: `artifact://${contentHash}`, + contentHash, + }), + routerRoot: path.join(repoRoot, "role-model-router"), + }); + migration.backfill({ scopeId: `tenant:${scopeId}`, batchSize: 10 }); + migration.enterShadowMirror({ deadlineMs: Date.now() + 10_000 }); + migration.verifyParity({ backupVerified: true, restoreVerified: true, consumersVerified: true }); + migration.cutover(); + + const result = await backend.executeChatCompletions( + { + model: "deepseek/chat-capture-v1", + messages: [{ role: "user", content: "verify bounded capture failure" }], + }, + "req-track-b-capture-failure-001", + ); + + expect(result.persistenceDegradation).toMatchObject({ + capability: "runtime-observation-persist", + reason: "track-b-capture-boundary-http-503", + }); + expect(readRuntimeTelemetryRecord({ databasePath, requestId: "req-track-b-capture-failure-001" })).toBeNull(); + } finally { + await backend.shutdown(); + await new Promise((resolve, reject) => + operations.close((error) => (error ? reject(error) : resolve())), + ); + } + }); + test("legacy failure recovery retries extension closure after graph commit and propagates sidecar auth failures", async () => { const runtimeStateRoot = path.join(os.tmpdir(), `track-b-recovery-retry-${Date.now()}`); roots.push(runtimeStateRoot); From c4f433cd096f3dff9b0951846adbc5f2947bcba7 Mon Sep 17 00:00:00 2001 From: Erik <262919414+try-works@users.noreply.github.com> Date: Mon, 31 Aug 2026 20:17:37 +0800 Subject: [PATCH 04/11] fix(runtime): discover state-root configuration --- .../apps/runtime-host-bridge/src/index.ts | 17 +++++++++++------ .../runtime-host-bridge/test/index.test.ts | 19 +++++++++++++++++++ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/role-model-router/apps/runtime-host-bridge/src/index.ts b/role-model-router/apps/runtime-host-bridge/src/index.ts index 51c1c572..3ddba1b6 100644 --- a/role-model-router/apps/runtime-host-bridge/src/index.ts +++ b/role-model-router/apps/runtime-host-bridge/src/index.ts @@ -29210,10 +29210,6 @@ export function resolveBridgeServerOptions(input: { const packagedProfile = readPackagedRuntimeProfile(input.executablePath); const profile = packagedProfile ?? resolveRuntimeChannelProfile("production"); const statePath = resolveBridgePathApi([input.localAppData], process.env.LOCALAPPDATA); - const runtimeStatePath = resolveBridgePathApi( - [input.runtimeStateRoot, input.localAppData], - process.env.LOCALAPPDATA, - ); const inferredRepoRoot = input.executablePath ? (() => { const executableDir = repoPath.dirname(repoPath.resolve(input.executablePath)); @@ -29245,6 +29241,13 @@ export function resolveBridgeServerOptions(input: { statePath.join(os.homedir(), ".local", "state"); const runtimeStateRoot = input.runtimeStateRoot?.trim() || statePath.join(platformStateBase, profile.state_root_name); + const explicitUnifiedRuntimeConfigPath = input.unifiedRuntimeConfigPath?.trim(); + const stateRootUnifiedRuntimeConfigPath = statePath.join(runtimeStateRoot, "runtime-config.yaml"); + const legacyUnifiedRuntimeConfigPath = statePath.join( + runtimeStateRoot, + "state", + "runtime-config.yaml", + ); return { host: input.host?.trim() || profile.host, @@ -29259,7 +29262,9 @@ export function resolveBridgeServerOptions(input: { preferRepoRootBuild: Boolean(input.repoRoot?.trim()) || Boolean(packagedProfile), }), unifiedRuntimeConfigPath: - input.unifiedRuntimeConfigPath?.trim() || - runtimeStatePath.join(runtimeStateRoot, "state", "runtime-config.yaml"), + explicitUnifiedRuntimeConfigPath || + (existsSync(stateRootUnifiedRuntimeConfigPath) + ? stateRootUnifiedRuntimeConfigPath + : legacyUnifiedRuntimeConfigPath), }; } diff --git a/role-model-router/apps/runtime-host-bridge/test/index.test.ts b/role-model-router/apps/runtime-host-bridge/test/index.test.ts index 7b10bda0..ec18894a 100644 --- a/role-model-router/apps/runtime-host-bridge/test/index.test.ts +++ b/role-model-router/apps/runtime-host-bridge/test/index.test.ts @@ -23620,6 +23620,25 @@ describe("runtime-host-bridge", () => { }); }); + test("prefers an existing state-root runtime config when a packaged launch omits the flag", async () => { + const runtimeStateRoot = await mkdtemp(path.join(os.tmpdir(), "role-model-runtime-config-default-")); + try { + await writeFile(path.join(runtimeStateRoot, "runtime-config.yaml"), 'version: "1.0"\n', "utf8"); + const result = ( + bridge as { + resolveBridgeServerOptions: (value: { + repoRoot?: string; + runtimeStateRoot?: string; + }) => { unifiedRuntimeConfigPath: string }; + } + ).resolveBridgeServerOptions({ repoRoot, runtimeStateRoot }); + + expect(result.unifiedRuntimeConfigPath).toBe(path.join(runtimeStateRoot, "runtime-config.yaml")); + } finally { + await rm(runtimeStateRoot, { recursive: true, force: true }); + } + }); + test("keeps repoRoot-derived static paths stable when runtimeStateRoot uses a different path dialect", () => { const result = ( bridge as { From 7f7f92f582949cf440a6b0db8f937908bafc79af Mon Sep 17 00:00:00 2001 From: Erik <262919414+try-works@users.noreply.github.com> Date: Mon, 31 Aug 2026 20:41:06 +0800 Subject: [PATCH 05/11] fix(runtime): allow bounded durable route capture --- .../src/track-b-operations.ts | 7 +++- .../test/track-b-operations-api.test.ts | 41 +++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/role-model-router/apps/runtime-host-bridge/src/track-b-operations.ts b/role-model-router/apps/runtime-host-bridge/src/track-b-operations.ts index 884821db..5f47d1a8 100644 --- a/role-model-router/apps/runtime-host-bridge/src/track-b-operations.ts +++ b/role-model-router/apps/runtime-host-bridge/src/track-b-operations.ts @@ -661,7 +661,10 @@ const privateRetentionRequest = async ( token: string | undefined, route: string, init: { readonly method?: string; readonly body?: Record } = {}, - timeoutMs = 5_000, + // Route captures may perform bounded durable CAS and SQLite commits after the + // provider response. Five seconds aborts healthy local captures on mature + // runtimes; retain a finite budget while allowing that proven completion path. + timeoutMs = 8_000, ): Promise => { if (!endpoint) return null; if (!token || token.trim().length < 24) { @@ -1073,7 +1076,7 @@ export function createTrackBOperations({ runtimeChannel = "development", operationsEndpoint = process.env.ROLE_MODEL_TRACK_B_OPERATIONS_URL?.trim(), operationsToken = process.env.ROLE_MODEL_TRACK_B_OPERATIONS_TOKEN, - operationsTimeoutMs = 5_000, + operationsTimeoutMs = 8_000, extensionRuntime, }: { readonly statePath: string; diff --git a/role-model-router/apps/runtime-host-bridge/test/track-b-operations-api.test.ts b/role-model-router/apps/runtime-host-bridge/test/track-b-operations-api.test.ts index bd8e89ef..af9a769e 100644 --- a/role-model-router/apps/runtime-host-bridge/test/track-b-operations-api.test.ts +++ b/role-model-router/apps/runtime-host-bridge/test/track-b-operations-api.test.ts @@ -2158,6 +2158,47 @@ describe("Track B operations APIs", () => { } }); + test("run95 allows a bounded local route capture to complete beyond the legacy five-second budget", async () => { + const operations = createServer((request, response) => { + if (request.method !== "POST" || request.url !== "/capture/route") { + response.writeHead(404).end(); + return; + } + setTimeout(() => { + response.writeHead(200, { "content-type": "application/json" }).end( + JSON.stringify({ + status: "captured", + scope: "runtime:test", + rootArtifactId: "artifact:test", + rootArtifactDigest: "sha256:test", + }), + ); + }, 5_500); + }); + await new Promise((resolve, reject) => { + operations.once("error", reject); + operations.listen(0, "127.0.0.1", resolve); + }); + try { + const address = operations.address(); + if (!address || typeof address === "string") + throw new Error("operations server did not bind"); + const api = createTrackBOperations({ + statePath: path.join(os.tmpdir(), `run95-capture-budget-${Date.now()}.json`), + catalog: [], + operationsEndpoint: `http://127.0.0.1:${address.port}`, + operationsToken: "run95-capture-budget-token-0001", + }); + await expect( + api.recordLocalRouteCapture({ requestId: "request-1" }), + ).resolves.toMatchObject({ status: "captured", rootArtifactId: "artifact:test" }); + } finally { + await new Promise((resolve, reject) => + operations.close((error) => (error ? reject(error) : resolve())), + ); + } + }); + test("run79 mutateExtension enables disables and sets mode with audit receipts", async () => { const runtimeStateRoot = path.join(os.tmpdir(), `track-b-run79-mutate-${Date.now()}`); roots.push(runtimeStateRoot); From 57acc71bb8d9e7e1d3ee8e97cc8d9adfa22493b5 Mon Sep 17 00:00:00 2001 From: Erik <262919414+try-works@users.noreply.github.com> Date: Mon, 31 Aug 2026 21:04:17 +0800 Subject: [PATCH 06/11] style(runtime): format packaged capture fixes --- .../apps/runtime-host-bridge/src/index.ts | 7 +++---- .../src/track-b-operations.ts | 3 ++- .../apps/runtime-host-bridge/test/index.test.ts | 14 +++++++++++--- .../test/track-b-operations-api.test.ts | 17 ++++++++++++----- .../packages/core/src/taxonomy/index.test.ts | 10 +--------- 5 files changed, 29 insertions(+), 22 deletions(-) diff --git a/role-model-router/apps/runtime-host-bridge/src/index.ts b/role-model-router/apps/runtime-host-bridge/src/index.ts index 3ddba1b6..11d05d6a 100644 --- a/role-model-router/apps/runtime-host-bridge/src/index.ts +++ b/role-model-router/apps/runtime-host-bridge/src/index.ts @@ -24178,10 +24178,9 @@ export async function createRuntimeBridgeBackend( capability: "runtime-observation-persist", reason: routeCaptureDegradationReason ?? - String(error instanceof Error ? error.message : "runtime observation persist failed").slice( - 0, - 256, - ), + String( + error instanceof Error ? error.message : "runtime observation persist failed", + ).slice(0, 256), routingContinues: true, atMs: Date.now(), }; diff --git a/role-model-router/apps/runtime-host-bridge/src/track-b-operations.ts b/role-model-router/apps/runtime-host-bridge/src/track-b-operations.ts index 5f47d1a8..b5c158c4 100644 --- a/role-model-router/apps/runtime-host-bridge/src/track-b-operations.ts +++ b/role-model-router/apps/runtime-host-bridge/src/track-b-operations.ts @@ -1094,7 +1094,8 @@ export function createTrackBOperations({ const requestPrivate = ( route: string, init?: { readonly method?: string; readonly body?: Record }, - ) => privateRetentionRequest(operationsEndpoint, operationsToken, route, init, operationsTimeoutMs); + ) => + privateRetentionRequest(operationsEndpoint, operationsToken, route, init, operationsTimeoutMs); return { async readGraphMigration(): Promise { const remote = await requestPrivate("graph-migration"); diff --git a/role-model-router/apps/runtime-host-bridge/test/index.test.ts b/role-model-router/apps/runtime-host-bridge/test/index.test.ts index ec18894a..76055a3c 100644 --- a/role-model-router/apps/runtime-host-bridge/test/index.test.ts +++ b/role-model-router/apps/runtime-host-bridge/test/index.test.ts @@ -23621,9 +23621,15 @@ describe("runtime-host-bridge", () => { }); test("prefers an existing state-root runtime config when a packaged launch omits the flag", async () => { - const runtimeStateRoot = await mkdtemp(path.join(os.tmpdir(), "role-model-runtime-config-default-")); + const runtimeStateRoot = await mkdtemp( + path.join(os.tmpdir(), "role-model-runtime-config-default-"), + ); try { - await writeFile(path.join(runtimeStateRoot, "runtime-config.yaml"), 'version: "1.0"\n', "utf8"); + await writeFile( + path.join(runtimeStateRoot, "runtime-config.yaml"), + 'version: "1.0"\n', + "utf8", + ); const result = ( bridge as { resolveBridgeServerOptions: (value: { @@ -23633,7 +23639,9 @@ describe("runtime-host-bridge", () => { } ).resolveBridgeServerOptions({ repoRoot, runtimeStateRoot }); - expect(result.unifiedRuntimeConfigPath).toBe(path.join(runtimeStateRoot, "runtime-config.yaml")); + expect(result.unifiedRuntimeConfigPath).toBe( + path.join(runtimeStateRoot, "runtime-config.yaml"), + ); } finally { await rm(runtimeStateRoot, { recursive: true, force: true }); } diff --git a/role-model-router/apps/runtime-host-bridge/test/track-b-operations-api.test.ts b/role-model-router/apps/runtime-host-bridge/test/track-b-operations-api.test.ts index af9a769e..9681288e 100644 --- a/role-model-router/apps/runtime-host-bridge/test/track-b-operations-api.test.ts +++ b/role-model-router/apps/runtime-host-bridge/test/track-b-operations-api.test.ts @@ -1249,7 +1249,11 @@ describe("Track B operations APIs", () => { }); migration.backfill({ scopeId: `tenant:${scopeId}`, batchSize: 10 }); migration.enterShadowMirror({ deadlineMs: Date.now() + 10_000 }); - migration.verifyParity({ backupVerified: true, restoreVerified: true, consumersVerified: true }); + migration.verifyParity({ + backupVerified: true, + restoreVerified: true, + consumersVerified: true, + }); migration.cutover(); const result = await backend.executeChatCompletions( @@ -1264,7 +1268,9 @@ describe("Track B operations APIs", () => { capability: "runtime-observation-persist", reason: "track-b-capture-boundary-http-503", }); - expect(readRuntimeTelemetryRecord({ databasePath, requestId: "req-track-b-capture-failure-001" })).toBeNull(); + expect( + readRuntimeTelemetryRecord({ databasePath, requestId: "req-track-b-capture-failure-001" }), + ).toBeNull(); } finally { await backend.shutdown(); await new Promise((resolve, reject) => @@ -2189,9 +2195,10 @@ describe("Track B operations APIs", () => { operationsEndpoint: `http://127.0.0.1:${address.port}`, operationsToken: "run95-capture-budget-token-0001", }); - await expect( - api.recordLocalRouteCapture({ requestId: "request-1" }), - ).resolves.toMatchObject({ status: "captured", rootArtifactId: "artifact:test" }); + await expect(api.recordLocalRouteCapture({ requestId: "request-1" })).resolves.toMatchObject({ + status: "captured", + rootArtifactId: "artifact:test", + }); } finally { await new Promise((resolve, reject) => operations.close((error) => (error ? reject(error) : resolve())), diff --git a/role-model-router/packages/core/src/taxonomy/index.test.ts b/role-model-router/packages/core/src/taxonomy/index.test.ts index f11c777d..cf3851dc 100644 --- a/role-model-router/packages/core/src/taxonomy/index.test.ts +++ b/role-model-router/packages/core/src/taxonomy/index.test.ts @@ -8,15 +8,7 @@ describe("taxonomyDataRootCandidates", () => { const executablePath = path.join("D:", "release", "role-model-dev.exe"); expect(taxonomyDataRootCandidates(executablePath)).toContain( - path.join( - "D:", - "release", - "role-model-router", - "packages", - "core", - "data", - "taxonomy", - ), + path.join("D:", "release", "role-model-router", "packages", "core", "data", "taxonomy"), ); }); }); From 0748070ada4ab9557996cef9adaef275ead4611f Mon Sep 17 00:00:00 2001 From: Erik <262919414+try-works@users.noreply.github.com> Date: Mon, 31 Aug 2026 21:16:08 +0800 Subject: [PATCH 07/11] test(runtime): make config path assertion portable --- role-model-router/apps/runtime-host-bridge/test/index.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/role-model-router/apps/runtime-host-bridge/test/index.test.ts b/role-model-router/apps/runtime-host-bridge/test/index.test.ts index 76055a3c..824f40e9 100644 --- a/role-model-router/apps/runtime-host-bridge/test/index.test.ts +++ b/role-model-router/apps/runtime-host-bridge/test/index.test.ts @@ -23616,7 +23616,7 @@ describe("runtime-host-bridge", () => { runtimeStateRoot: "C:\\runtime-state", scopeId: "standalone-runtime", staticRoot: path.join(repoRoot, "role-model-router", "apps", "runtime-ui", "build", "client"), - unifiedRuntimeConfigPath: "C:\\runtime-state\\state\\runtime-config.yaml", + unifiedRuntimeConfigPath: path.join("C:\\runtime-state", "state", "runtime-config.yaml"), }); }); From 55dcf10c7df837b1d27b87b5c83fb2f91fef2513 Mon Sep 17 00:00:00 2001 From: Erik <262919414+try-works@users.noreply.github.com> Date: Mon, 31 Aug 2026 21:16:59 +0800 Subject: [PATCH 08/11] test(runtime): keep mixed path assertions portable --- role-model-router/apps/runtime-host-bridge/test/index.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/role-model-router/apps/runtime-host-bridge/test/index.test.ts b/role-model-router/apps/runtime-host-bridge/test/index.test.ts index 824f40e9..a8273036 100644 --- a/role-model-router/apps/runtime-host-bridge/test/index.test.ts +++ b/role-model-router/apps/runtime-host-bridge/test/index.test.ts @@ -23681,7 +23681,7 @@ describe("runtime-host-bridge", () => { scopeId: "standalone-runtime", staticRoot: "/home/runner/work/role-model/role-model/role-model-router/apps/runtime-ui/build/client", - unifiedRuntimeConfigPath: "C:\\runtime-state\\state\\runtime-config.yaml", + unifiedRuntimeConfigPath: path.join("C:\\runtime-state", "state", "runtime-config.yaml"), }); }); From f2174616da674850629136d459f0ceb4119cb2bb Mon Sep 17 00:00:00 2001 From: Erik <262919414+try-works@users.noreply.github.com> Date: Mon, 31 Aug 2026 22:13:40 +0800 Subject: [PATCH 09/11] fix(release): require exact private stage head --- .github/workflows/build-binaries.yml | 5 +++-- scripts/build-binaries-workflow.test.mjs | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-binaries.yml b/.github/workflows/build-binaries.yml index 0856d752..18e3ad6c 100644 --- a/.github/workflows/build-binaries.yml +++ b/.github/workflows/build-binaries.yml @@ -327,8 +327,9 @@ jobs: exit 1 fi git fetch --no-tags origin "+refs/heads/${REQUIRED_PRIVATE_BRANCH}:refs/remotes/origin/${REQUIRED_PRIVATE_BRANCH}" - if ! git merge-base --is-ancestor "$RELEASE_PRIVATE_SHA" "origin/$REQUIRED_PRIVATE_BRANCH"; then - echo "Private revision must be promoted through role-model-internal/$REQUIRED_PRIVATE_BRANCH before $ROLE_MODEL_BUILD_CHANNEL packaging." + required_private_head="$(git rev-parse "origin/$REQUIRED_PRIVATE_BRANCH")" + if [[ "$RELEASE_PRIVATE_SHA" != "$required_private_head" ]]; then + echo "Paired private revision must equal the current role-model-internal/$REQUIRED_PRIVATE_BRANCH head before $ROLE_MODEL_BUILD_CHANNEL packaging." exit 1 fi diff --git a/scripts/build-binaries-workflow.test.mjs b/scripts/build-binaries-workflow.test.mjs index f35cabed..526e0597 100644 --- a/scripts/build-binaries-workflow.test.mjs +++ b/scripts/build-binaries-workflow.test.mjs @@ -54,7 +54,8 @@ test("the public release orchestrator enforces paired private promotion", () => assert.match(workflow, /fetch-depth: 0/); assert.match(workflow, /Verify private revision passed paired promotion branch/); assert.match(workflow, /REQUIRED_PRIVATE_BRANCH:[\s\S]*?'main'[\s\S]*?'stage'/); - assert.match(workflow, /git merge-base --is-ancestor/); + assert.match(workflow, /required_private_head="\$\(git rev-parse "origin\/\$REQUIRED_PRIVATE_BRANCH"\)"/); + assert.match(workflow, /\[\[ "\$RELEASE_PRIVATE_SHA" != "\$required_private_head" \]\]/); }); test("paired private checkout never dirties the public package provenance worktree", () => { From 6632790b9a2692bfa83d21175975080f78900b3c Mon Sep 17 00:00:00 2001 From: Erik <262919414+try-works@users.noreply.github.com> Date: Mon, 31 Aug 2026 22:14:54 +0800 Subject: [PATCH 10/11] style(release): format provenance contract test --- scripts/build-binaries-workflow.test.mjs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/build-binaries-workflow.test.mjs b/scripts/build-binaries-workflow.test.mjs index 526e0597..630380c1 100644 --- a/scripts/build-binaries-workflow.test.mjs +++ b/scripts/build-binaries-workflow.test.mjs @@ -54,7 +54,10 @@ test("the public release orchestrator enforces paired private promotion", () => assert.match(workflow, /fetch-depth: 0/); assert.match(workflow, /Verify private revision passed paired promotion branch/); assert.match(workflow, /REQUIRED_PRIVATE_BRANCH:[\s\S]*?'main'[\s\S]*?'stage'/); - assert.match(workflow, /required_private_head="\$\(git rev-parse "origin\/\$REQUIRED_PRIVATE_BRANCH"\)"/); + assert.match( + workflow, + /required_private_head="\$\(git rev-parse "origin\/\$REQUIRED_PRIVATE_BRANCH"\)"/, + ); assert.match(workflow, /\[\[ "\$RELEASE_PRIVATE_SHA" != "\$required_private_head" \]\]/); }); From ad14fa40df655c76ac237e4118fbbe1ada66c25d Mon Sep 17 00:00:00 2001 From: Erik <262919414+try-works@users.noreply.github.com> Date: Mon, 31 Aug 2026 23:17:39 +0800 Subject: [PATCH 11/11] fix(track-b): retry pending receipts on readback --- .../apps/runtime-host-bridge/src/cli.ts | 21 +++++++----- .../src/track-b-runtime.ts | 9 +++++ .../test/run94-sp5-sp10.test.ts | 33 +++++++++++++++++++ 3 files changed, 55 insertions(+), 8 deletions(-) diff --git a/role-model-router/apps/runtime-host-bridge/src/cli.ts b/role-model-router/apps/runtime-host-bridge/src/cli.ts index 05bf1709..9ef0138c 100644 --- a/role-model-router/apps/runtime-host-bridge/src/cli.ts +++ b/role-model-router/apps/runtime-host-bridge/src/cli.ts @@ -1012,10 +1012,9 @@ export async function main(): Promise { // available at runtime. const currentPostObservationOperations = (): ReturnType | null => postObservationOperations; - const drainPostObservationOutbox = async ( - runtime: Awaited>, - ) => - postObservationOutbox.drain((observation) => { + const postObservationHandler = + (runtime: Awaited>) => + (observation: Parameters[1]) => { const processingInput = { scope: options.scopeId, channel: packagedProfile?.channel ?? "development", @@ -1036,7 +1035,10 @@ export async function main(): Promise { (aggregate) => operations.recordContributionAggregate(aggregate), ) : runTrackBPostObservation(runtime, observation, processingInput); - }); + }; + const drainPostObservationOutbox = async ( + runtime: Awaited>, + ) => postObservationOutbox.drain(postObservationHandler(runtime)); const createBackend = async ( trackBOperationsEndpoint?: string, trackBOperationsToken?: string, @@ -1097,14 +1099,17 @@ export async function main(): Promise { readTrackBExtensionReadback: async (body) => { const requestId = String(body.requestId ?? "").trim(); if (!requestId) throw new Error("Track B extension readback requestId is required"); - const receipt = await postObservationOutbox.readReceipt(requestId); + const runtime = extensionRuntimeRef.current; + if (!runtime) throw new Error("Track B extension runtime is unavailable"); + const receipt = await postObservationOutbox.drainUntilReceipt( + requestId, + postObservationHandler(runtime), + ); if (!receipt) throw new Error(`Track B observation receipt not found: ${requestId}`); const result = receipt.result as Record; const closure = result.extensionClosure as TrackBExtensionClosure | undefined; if (!closure) throw new Error(`Track B observation has no extension closure: ${requestId}`); - const runtime = extensionRuntimeRef.current; - if (!runtime) throw new Error("Track B extension runtime is unavailable"); return verifyTrackBExtensionClosureAfterRestart(runtime, closure, { channel: packagedProfile?.channel ?? "development", scope: options.scopeId, diff --git a/role-model-router/apps/runtime-host-bridge/src/track-b-runtime.ts b/role-model-router/apps/runtime-host-bridge/src/track-b-runtime.ts index 6b60497d..4feb2e13 100644 --- a/role-model-router/apps/runtime-host-bridge/src/track-b-runtime.ts +++ b/role-model-router/apps/runtime-host-bridge/src/track-b-runtime.ts @@ -1792,6 +1792,15 @@ export function createTrackBPostObservationOutbox({ } }); }, + async drainUntilReceipt( + requestId: string, + handler: (observation: TrackBPostObservationWorkItem) => Promise, + ): Promise { + const existing = await this.readReceipt(requestId); + if (existing) return existing; + await this.drain(handler); + return this.readReceipt(requestId); + }, async read(): Promise<{ readonly pendingCount: number; readonly receiptCount: number; diff --git a/role-model-router/apps/runtime-host-bridge/test/run94-sp5-sp10.test.ts b/role-model-router/apps/runtime-host-bridge/test/run94-sp5-sp10.test.ts index eab26344..a863f156 100644 --- a/role-model-router/apps/runtime-host-bridge/test/run94-sp5-sp10.test.ts +++ b/role-model-router/apps/runtime-host-bridge/test/run94-sp5-sp10.test.ts @@ -76,6 +76,39 @@ test("GREEN: post-observation outbox is a normalized SQLite authority with bound afterDrain.close(); }); +test("GREEN: a readback-driven retry drains a transiently failed pending observation without another routed request", async () => { + const root = await import("node:fs/promises").then(({ mkdtemp }) => + mkdtemp(path.join(os.tmpdir(), "run95-readback-retry-")), + ); + roots.push(root); + const outbox = createTrackBPostObservationOutbox({ + filePath: path.join(root, "post-observation-outbox.sqlite"), + maxItems: 8, + }); + await outbox.enqueue(identity("retry-without-next-route")); + await expect( + outbox.drain(async () => { + throw new Error("temporary private operation timeout"); + }), + ).rejects.toThrow(/temporary private operation timeout/); + expect(await outbox.read()).toMatchObject({ pendingCount: 1, receiptCount: 0 }); + + const recovered = await ( + outbox as unknown as { + drainUntilReceipt( + requestId: string, + handler: (item: Record) => Promise, + ): Promise<{ requestId: string } | null>; + } + ).drainUntilReceipt("retry-without-next-route", async (item) => ({ + status: "recovered", + extensionClosure: { requestId: item.requestId }, + })); + + expect(recovered).toMatchObject({ requestId: "retry-without-next-route" }); + expect(await outbox.read()).toMatchObject({ pendingCount: 0, receiptCount: 1 }); +}); + test("GREEN: imports N-1 JSON once, classifies every legacy row, and quarantines malformed rows", async () => { const root = await import("node:fs/promises").then(({ mkdtemp }) => mkdtemp(path.join(os.tmpdir(), "run94-sp5-legacy-")),