Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
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
38d39ba
Merge pull request #162 from try-works/dev
try-works Aug 26, 2026
4235005
feat(stage): package the stage channel with self-contained managed se…
try-works Aug 26, 2026
34990bd
style: biome-format stage secrets packaging changes
try-works Aug 26, 2026
09d1608
Merge pull request #163 from try-works/recursive/94-stage-rc-packaged…
try-works Aug 26, 2026
36bbd82
Merge pull request #164 from try-works/dev
try-works Aug 27, 2026
0ad1c63
fix(ci): write stage secrets with pwsh on the windows build runner
try-works Aug 27, 2026
cdcada4
Merge pull request #165 from try-works/recursive/94-stage-rc-packaged…
try-works Aug 27, 2026
f48ca01
Merge pull request #166 from try-works/dev
try-works Aug 27, 2026
7d7769d
fix(run94 SP36): bound compact-stub node-id locators with truncation …
try-works Aug 27, 2026
4145ae9
fix(run94 SP48): default 90-day observation expiry, NULL-retain eligi…
try-works Aug 27, 2026
607c9d9
fix(run94 SP49): bound telemetry JSON columns and assert the compact-…
try-works Aug 28, 2026
d0bffd5
Merge pull request #167 from try-works/recursive/94-stage-rc-packaged…
try-works Aug 28, 2026
3a1a070
Merge pull request #168 from try-works/dev
try-works Aug 28, 2026
a2c4749
fix(storage): preserve inventory projections
try-works Aug 28, 2026
d003dc6
fix(storage): preserve inventory projections
try-works Aug 28, 2026
50a82db
Merge remote-tracking branch 'origin/dev' into fix/run94-storage-adde…
try-works Aug 28, 2026
0827b50
style(storage): format retention contracts
try-works Aug 28, 2026
3a39448
feat(storage): render logical physical mappings
try-works Aug 28, 2026
4815cd2
style(storage): sort retention test imports
try-works Aug 28, 2026
4ab76e5
fix(storage): show observation freshness
try-works Aug 28, 2026
32afe2d
test(storage): assert precise audit terminology
try-works Aug 28, 2026
83155d8
fix(storage): separate unobserved availability
try-works Aug 28, 2026
d5419c1
fix(storage): explain inventory availability counts
try-works Aug 28, 2026
82d62ba
fix(storage): type accounting state
try-works Aug 28, 2026
695bab4
Merge pull request #170 from try-works/fix/run94-storage-addendum12-p…
try-works Aug 28, 2026
e99e042
Merge branch 'stage' into dev
try-works Aug 28, 2026
2731155
Merge pull request #171 from try-works/dev
try-works Aug 28, 2026
afe3451
fix(runtime): allow bounded Track B state recovery
try-works Aug 28, 2026
4fb7291
Merge pull request #172 from try-works/fix/run94-storage-addendum12-p…
try-works Aug 28, 2026
5403ba6
Merge branch 'stage' into dev
try-works Aug 28, 2026
9010fab
Merge pull request #173 from try-works/dev
try-works Aug 28, 2026
6980f84
fix(runtime): retire legacy Track B SQLite observations
try-works Aug 28, 2026
d41133c
Merge pull request #174 from try-works/fix/run94-storage-legacy-sqlit…
try-works Aug 28, 2026
dd49fbe
test(runtime): keep legacy alias migration hermetic
try-works Aug 28, 2026
ac1bc2c
Merge pull request #176 from try-works/fix/run94-ci-hermetic-vendor
try-works Aug 28, 2026
5c3bb2f
Merge pull request #175 from try-works/dev
try-works Aug 28, 2026
c2f1f63
fix(router): advertise routable alias efforts
try-works Aug 28, 2026
5bc4188
Merge pull request #177 from try-works/fix/run94-alias-effort-projection
try-works Aug 28, 2026
ef35378
test(ci): synchronize supervisor restart fixture
try-works Aug 28, 2026
5cff4de
Merge pull request #179 from try-works/fix/run94-process-supervisor-ci
try-works Aug 28, 2026
a9a90fc
Merge pull request #178 from try-works/dev
try-works Aug 28, 2026
e1e58fa
fix(runtime): preserve default effort through outbox
try-works Aug 28, 2026
ea195ab
Merge pull request #180 from try-works/fix/run94-default-effort-outbox
try-works Aug 28, 2026
1f08303
Merge pull request #181 from try-works/dev
try-works Aug 28, 2026
e0d31ac
test(storage): accept observed cloud inventory bytes
try-works Aug 28, 2026
48b75e9
Merge pull request #182 from try-works/fix/run94-storage-boundary-tim…
try-works Aug 28, 2026
5e0bcbe
test(storage): derive byte assertions from observation state
try-works Aug 28, 2026
c434a5f
Merge remote-tracking branch 'origin/dev' into fix/run94-storage-boun…
try-works Aug 28, 2026
486a623
Merge pull request #183 from try-works/fix/run94-storage-boundary-tim…
try-works Aug 29, 2026
d97d7cc
Merge pull request #184 from try-works/dev
try-works Aug 29, 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
16 changes: 16 additions & 0 deletions .github/workflows/build-binaries.yml
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,22 @@ jobs:
}
}

- name: Include managed stage secrets in the stage package
if: env.ROLE_MODEL_BUILD_CHANNEL == 'stage'
shell: pwsh
env:
STAGE_ARTIFACT_DIGEST_KEY: ${{ secrets.STAGE_ARTIFACT_DIGEST_KEY }}
STAGE_ARTIFACT_ENCRYPTION_KEY: ${{ secrets.STAGE_ARTIFACT_ENCRYPTION_KEY }}
STAGE_DESTINATION_MATERIAL: ${{ secrets.STAGE_DESTINATION_MATERIAL }}
STAGE_RECOMMENDATION_MATERIAL: ${{ secrets.STAGE_RECOMMENDATION_MATERIAL }}
run: |
$secretsDir = "role-model-router/dist/release/${{ matrix.target }}/secrets"
New-Item -ItemType Directory -Force -Path $secretsDir | Out-Null
[IO.File]::WriteAllText("$secretsDir/artifact-digest.key", $env:STAGE_ARTIFACT_DIGEST_KEY)
[IO.File]::WriteAllText("$secretsDir/artifact-encryption.key", $env:STAGE_ARTIFACT_ENCRYPTION_KEY)
[IO.File]::WriteAllText("$secretsDir/destination-material.json", $env:STAGE_DESTINATION_MATERIAL)
[IO.File]::WriteAllText("$secretsDir/recommendation-material.json", $env:STAGE_RECOMMENDATION_MATERIAL)

- name: Archive standalone package (Unix)
if: matrix.target != 'win32-x64'
run: |
Expand Down
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