Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
86c979e
fix(runtime): recover adaptively from upstream failures (#133)
try-works Aug 14, 2026
95f38d3
Merge pull request #159 from try-works/stage
try-works Aug 23, 2026
88e50c2
Merge pull request #160 from try-works/main
try-works Aug 23, 2026
e9fb66c
Complete Run 94 graph storage runtime wiring
try-works Aug 24, 2026
7709f83
Fix shadow rollout scoring provenance
try-works Aug 24, 2026
08df5b5
Preserve runtime channel in extension status
try-works Aug 24, 2026
15d234e
Probe provider-native model identifiers
try-works Aug 24, 2026
f14a8a6
Expose durable extension readback evidence
try-works Aug 24, 2026
5e06d4a
Expose durable tool graph evidence
try-works Aug 24, 2026
d4299b6
Prove live tool graph and capture budgets
try-works Aug 24, 2026
03d4a1d
Expose measured Run 94 capture baseline
try-works Aug 24, 2026
3a1ccc7
Preserve API-authored runtime aliases
try-works Aug 24, 2026
6fc45ce
Route env-backed providers through runtime
try-works Aug 24, 2026
51357dd
Persist supervised extension outputs
try-works Aug 24, 2026
12e85e5
Preserve bounded post-observation receipts
try-works Aug 24, 2026
bd3de1a
Raise structured outbox receipt bound
try-works Aug 24, 2026
9b3cae3
Make extension readback repeatable
try-works Aug 24, 2026
a9f582c
Correlate runtime aggregates end to end
try-works Aug 24, 2026
fc17a45
Expose measured provider latency in request detail
try-works Aug 24, 2026
24b5da7
Preserve backend context for Verifiers export
try-works Aug 24, 2026
26c73c9
Conform live exports to Verifiers TraceTask
try-works Aug 24, 2026
72f875c
Project tool calls into Verifiers dialect
try-works Aug 24, 2026
469820b
Capture provider failures in Track B graph
try-works Aug 24, 2026
66e160b
Recover consumed provider failure evidence
try-works Aug 24, 2026
47a4264
Harden Track B recovery and migration identity
try-works Aug 25, 2026
7d89285
Normalize packaged extension health probes
try-works Aug 25, 2026
3a72480
Format provider failure regression
try-works Aug 25, 2026
9f7db7a
fix(runtime): separate recommendation lookup scope
try-works Aug 25, 2026
f9a0e0b
fix(runtime): reject stale disclosure authorization
try-works Aug 25, 2026
a3a7395
feat(runtime): support ordered alias endpoint preferences
try-works Aug 25, 2026
a7ec81e
fix(runtime): rehydrate known degraded aliases safely
try-works Aug 25, 2026
de6d80c
fix(runtime): terminate sole-endpoint retryable failures after one at…
try-works Aug 25, 2026
19418cb
style(runtime): biome-format track-b-operations-api test
try-works Aug 25, 2026
3d5a1a0
fix(runtime): emit schema-valid finish_reason stop for provider-failu…
try-works Aug 25, 2026
4cb4a74
test(runtime): make release-root packaging test platform-agnostic for…
try-works Aug 26, 2026
d0ea49f
chore(ci): re-run paired lanes with updated private pairing
try-works Aug 26, 2026
4e874a4
style(runtime): biome-format platform-agnostic release-root test
try-works Aug 26, 2026
fb1bfc9
chore(ci): re-run with diagnostic private pairing
try-works Aug 26, 2026
36696c0
chore(ci): ignore the nested private paired checkout in the public tree
try-works Aug 26, 2026
53c45b9
ci: use the explicit ci-contract packaged launch mode for the Track B…
try-works Aug 26, 2026
0bd7675
ci: point the Track B browser gate at the run-94 sp8 specs
try-works Aug 26, 2026
00136b8
ci(run94): update workflow contract tests to the run-94 browser gate
try-works Aug 26, 2026
8064a68
test(run94): assert the exact Logical classes summary label in the st…
try-works Aug 26, 2026
3d83271
Merge pull request #161 from try-works/recursive/94-direct-track-b-st…
try-works Aug 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ jobs:
done
test -s "$recommendation_material"
node _private/scripts/track-b/launch-packaged-runtime.mjs \
--ci-contract \
--public-root "$GITHUB_WORKSPACE" \
--manifest "$GITHUB_WORKSPACE/_private/dist/run00-dev/track-b-runtime-manifest.json" \
--qa-extension-manifest "$GITHUB_WORKSPACE/role-model-router/apps/runtime-host-bridge/test/fixtures/recursive-87-synthetic-extension.manifest.json" \
Expand All @@ -228,4 +229,4 @@ jobs:
--url http://127.0.0.1:3462/healthz \
--timeout-ms 120000 \
--poll-interval-ms 1000
pnpm --filter @role-model-router/runtime-ui exec playwright test --grep @recursive:87-direct-track-b-semantic-completion
pnpm --filter @role-model-router/runtime-ui exec playwright test --grep @recursive:94-direct-track-b-storage-graph-cloud-roundtrip
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ tmp-role-model-launch.log
role-model-router/apps/runtime-ui/build/
role-model-router/apps/runtime-ui/test-results/
/.recursive/config/recursive-router-discovered.json
# CI paired-checkout directory (checkout of try-works/role-model-internal nested by the track-b lane)
_private/
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"test:track-b-router-continuity": "node scripts/track-b/run-command-test.mjs TB03-CMD-02",
"test:track-b-capacity": "node scripts/track-b/run-command-test.mjs TB03-CMD-03",
"storage:audit": "node scripts/track-b/run-command-test.mjs TB04-CMD-01",
"storage:audit:read-only": "node scripts/track-b/storage-audit.mjs",
"storage:migrate:dry-run": "node scripts/track-b/run-command-test.mjs TB04-CMD-02",
"test:track-b-performance-history": "node scripts/track-b/run-command-test.mjs TB04-CMD-03",
"storage:migrate:verify-parity": "node scripts/track-b/run-command-test.mjs TB04-CMD-04",
Expand Down
8 changes: 7 additions & 1 deletion packages/extension-host/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,13 @@ export class ExtensionHost {
return Promise.reject(
new Error("oversized payload requires a channel-local transfer artifact"),
);
if (envelope.capability && !registered.descriptor.capabilities.includes(envelope.capability))
const hostReadCapability =
registered.kind === "process" && envelope.capability === "extension-output:read";
if (
envelope.capability &&
!hostReadCapability &&
!registered.descriptor.capabilities.includes(envelope.capability)
)
return Promise.reject(new Error("capability denied"));
if (envelope.signal?.aborted) {
this.#record(id, "cancelled", envelope);
Expand Down
126 changes: 125 additions & 1 deletion packages/extension-host/worker-runtime.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { createHash } from "node:crypto";
import { once } from "node:events";
import { mkdirSync } from "node:fs";
import { join } from "node:path";
import { DatabaseSync } from "node:sqlite";
import { pathToFileURL } from "node:url";
import { encodeFrame, extractFrames } from "../extension-sdk/index.mjs";

Expand All @@ -7,6 +11,116 @@ if (!moduleRef) throw new Error("worker module URL required");
const extension = await import(moduleRef.includes(":") ? moduleRef : pathToFileURL(moduleRef).href);
if (typeof extension.run !== "function") throw new Error("worker module must export run(envelope)");

const extensionId = process.env.ROLE_MODEL_EXTENSION_ID ?? "unknown-extension";
const stateRoot = process.env.ROLE_MODEL_EXTENSION_STATE_ROOT;
if (stateRoot) mkdirSync(stateRoot, { recursive: true });
const outputDatabase = new DatabaseSync(
stateRoot ? join(stateRoot, "durable-output.sqlite") : ":memory:",
);
outputDatabase.exec(`
PRAGMA journal_mode=WAL;
PRAGMA synchronous=FULL;
CREATE TABLE IF NOT EXISTS durable_extension_outputs (
output_key TEXT PRIMARY KEY,
request_id TEXT NOT NULL,
capability TEXT NOT NULL,
channel TEXT NOT NULL,
scope_id TEXT NOT NULL,
result_hash TEXT NOT NULL,
byte_length INTEGER NOT NULL,
result_json TEXT,
created_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS durable_extension_outputs_created
ON durable_extension_outputs(created_at, output_key);
`);
const MAX_INLINE_OUTPUT_BYTES = 16 * 1024;
const MAX_DURABLE_OUTPUT_ROWS = 512;

function persistBusinessOutput(envelope, result) {
const capability = envelope.capability ?? "health:probe";
const resultJson = JSON.stringify(result ?? null);
const byteLength = Buffer.byteLength(resultJson, "utf8");
const resultHash = `sha256:${createHash("sha256").update(resultJson).digest("hex")}`;
const outputKey = `sha256:${createHash("sha256")
.update(`${extensionId}\0${envelope.requestId}\0${capability}\0${resultHash}`)
.digest("hex")}`;
outputDatabase
.prepare("INSERT OR IGNORE INTO durable_extension_outputs VALUES (?,?,?,?,?,?,?,?,?)")
.run(
outputKey,
envelope.requestId,
capability,
envelope.channel,
envelope.scope,
resultHash,
byteLength,
byteLength <= MAX_INLINE_OUTPUT_BYTES ? resultJson : null,
new Date().toISOString(),
);
outputDatabase
.prepare(`DELETE FROM durable_extension_outputs WHERE output_key IN (
SELECT output_key FROM durable_extension_outputs
ORDER BY created_at DESC, output_key DESC LIMIT -1 OFFSET ?
)`)
.run(MAX_DURABLE_OUTPUT_ROWS);
const durableLocator = Object.freeze({
extensionId,
requestId: envelope.requestId,
capability,
channel: envelope.channel,
scope: envelope.scope,
outputKey,
resultHash,
byteLength,
});
const businessOutput =
result && typeof result === "object" && !Array.isArray(result) ? result : { value: result };
return {
...businessOutput,
businessOutput,
durableLocator,
evidenceRef: `extension-output:${outputKey}`,
readCapability: "extension-output:read",
};
}

function readBusinessOutput(envelope) {
const locator = envelope.payload?.durableLocator;
const durableOutputId = envelope.payload?.durableOutputId;
if (
!locator ||
locator.extensionId !== extensionId ||
locator.channel !== envelope.channel ||
locator.scope !== envelope.scope ||
!locator.outputKey ||
!durableOutputId
) {
throw new Error("durable extension output read identity is incomplete");
}
const row = outputDatabase
.prepare("SELECT * FROM durable_extension_outputs WHERE output_key=?")
.get(locator.outputKey);
if (
!row ||
row.request_id !== locator.requestId ||
row.capability !== locator.capability ||
row.channel !== locator.channel ||
row.scope_id !== locator.scope ||
row.result_hash !== locator.resultHash ||
row.byte_length !== locator.byteLength
) {
throw new Error("durable extension output locator does not match stored evidence");
}
return {
durableLocator: locator,
evidenceRef: `extension-output:${locator.outputKey}`,
readbackOutputId: durableOutputId,
resultHash: row.result_hash,
byteLength: row.byte_length,
};
}

const retained = new Map();
let input = Buffer.alloc(0);
const send = async (value) => {
Expand All @@ -24,12 +138,22 @@ process.stdin.on("data", async (chunk) => {
continue;
}
if (message.type === "shutdown") {
outputDatabase.close();
await send({ type: "shutdown-ack" });
process.exit(0);
}
if (message.type !== "invoke") continue;
try {
const result = await extension.run(message.envelope);
let result;
if (message.envelope.capability === "extension-output:read") {
result = readBusinessOutput(message.envelope);
} else {
const value = await extension.run(message.envelope);
result =
message.envelope.capability === "health:probe"
? value
: persistBusinessOutput(message.envelope, value);
}
const response = { type: "result", requestId: message.requestId, result };
retained.set(message.requestId, response);
await send(response);
Expand Down
Loading
Loading