From 36d0dae5bd27cef3a21a1643a5c67e88ba426ab6 Mon Sep 17 00:00:00 2001 From: Theodore Song Date: Sat, 22 Aug 2026 04:48:58 -0400 Subject: [PATCH] Compact fallback runtime transport --- scripts/run-autonomous-cycle.mjs | 74 ++++++++++++++++++++++++++++- scripts/test-autonomous-runtime.mjs | 34 ++++++++++++- 2 files changed, 106 insertions(+), 2 deletions(-) diff --git a/scripts/run-autonomous-cycle.mjs b/scripts/run-autonomous-cycle.mjs index 0a26268..e5d7562 100644 --- a/scripts/run-autonomous-cycle.mjs +++ b/scripts/run-autonomous-cycle.mjs @@ -13,6 +13,77 @@ const FORBIDDEN_RUNTIME_KEYS = Object.freeze([ "pma_paid_agent_chat_v1", ]); const MAX_STATE_BYTES = 900_000; +const TRANSPORT_HISTORY_LIMIT = 24; +const TRANSPORT_SNAPSHOT_LIMIT = 96; +const TRANSPORT_MAKER_OUTCOME_LIMIT = 30; + +function sampleSnapshots(rows, limit = TRANSPORT_SNAPSHOT_LIMIT) { + const list = Array.isArray(rows) ? rows : []; + if (list.length <= limit) return list; + const recentCount = Math.min(24, limit); + const older = list.slice(0, -recentCount); + const olderSlots = limit - recentCount; + const sampled = []; + for (let i = 0; i < olderSlots; i += 1) { + const index = olderSlots === 1 ? older.length - 1 : Math.round(i * (older.length - 1) / (olderSlots - 1)); + if (older[index] && sampled.at(-1) !== older[index]) sampled.push(older[index]); + } + return sampled.concat(list.slice(-recentCount)).slice(-limit); +} + +function compactHistoryRow(row) { + if (!row || typeof row !== "object") return row; + return { + date: row.date, + action: row.action, + question: typeof row.question === "string" ? row.question.slice(0, 140) : row.question, + side: row.side, + detail: typeof row.detail === "string" ? row.detail.slice(0, 220) : row.detail, + }; +} + +function compactPublicSuggestion(suggestion) { + if (!suggestion || typeof suggestion !== "object") return suggestion; + const out = { ...suggestion }; + if (suggestion.trade_ready || suggestion.adaptive_probation || suggestion.bundle_id) { + out.drivers = Array.isArray(suggestion.drivers) ? suggestion.drivers.slice(0, 1).map(value => String(value).slice(0, 80)) : []; + out.rationale = typeof suggestion.rationale === "string" + ? suggestion.rationale.slice(0, 180) + : "Trade-ready opportunity passed the active execution gate."; + } else { + out.drivers = []; + out.rationale = suggestion.jump_risk + ? "Watch only: settlement-gap risk prevents a protected entry." + : suggestion.signal_type && suggestion.signal_type !== "none" + ? "Watch only: gathering independent forward evidence before capital is enabled." + : "Watch only: no independently confirmed direction yet."; + delete out.clob_yes; + delete out.clob_no; + } + return out; +} + +export function compactRuntimeTransportSnapshot(snapshot) { + if (!snapshot || typeof snapshot !== "object" || !snapshot.items) return snapshot; + const out = { ...snapshot, items: { ...snapshot.items } }; + let state; + let suggestions; + try { + state = JSON.parse(out.items[AGENTS_KEY]); + suggestions = JSON.parse(out.items[SUGGESTIONS_KEY]); + } catch { + return out; + } + for (const portfolio of Object.values(state.agents || {})) { + portfolio.history = (portfolio.history || []).slice(-TRANSPORT_HISTORY_LIMIT).map(compactHistoryRow); + portfolio.snapshots = sampleSnapshots(portfolio.snapshots, TRANSPORT_SNAPSHOT_LIMIT); + portfolio.maker_outcomes = (portfolio.maker_outcomes || []).slice(-TRANSPORT_MAKER_OUTCOME_LIMIT); + } + suggestions.suggestions = (suggestions.suggestions || []).slice(0, 300).map(compactPublicSuggestion); + out.items[AGENTS_KEY] = JSON.stringify(state); + out.items[SUGGESTIONS_KEY] = JSON.stringify(suggestions); + return out; +} function required(name, fallback = "") { const value = process.env[name] || fallback; @@ -158,7 +229,8 @@ async function main() { }, null, { timeout: 12 * 60_000 }); await page.evaluate(() => window.PMA_AUTOMATION.runCycle()); await page.waitForFunction(() => !window.PMA_AUTOMATION?.status?.().running, null, { timeout: 12 * 60_000 }); - const snapshot = await page.evaluate(() => window.PMA_AUTOMATION.exportShared()); + const rawSnapshot = await page.evaluate(() => window.PMA_AUTOMATION.exportShared()); + const snapshot = compactRuntimeTransportSnapshot(rawSnapshot); const validated = validateRuntimeSnapshot(snapshot, expectedBuild); await writeRuntimeFile(repository, branch, pathname, snapshot, prior.sha); const status = await page.evaluate(() => window.PMA_AUTOMATION.status()); diff --git a/scripts/test-autonomous-runtime.mjs b/scripts/test-autonomous-runtime.mjs index e2467c9..59e624d 100644 --- a/scripts/test-autonomous-runtime.mjs +++ b/scripts/test-autonomous-runtime.mjs @@ -1,6 +1,6 @@ import assert from "node:assert/strict"; import fs from "node:fs"; -import { ALLOWED_RUNTIME_KEYS, validateRuntimeSnapshot } from "./run-autonomous-cycle.mjs"; +import { ALLOWED_RUNTIME_KEYS, compactRuntimeTransportSnapshot, validateRuntimeSnapshot } from "./run-autonomous-cycle.mjs"; const index = fs.readFileSync(new URL("../index.html", import.meta.url), "utf8"); const api = fs.readFileSync(new URL("../api/state.js", import.meta.url), "utf8"); @@ -78,6 +78,7 @@ assert.match(index, /sizesToLargestVerifiedProfitableFill:/); assert.match(index, /stopsSizingAtShallowestBundleLeg:/); assert.match(index, /!s\.depth_verified\|\|!s\.fees_verified\|\|s\.verification_status!=="executable"/); assert.match(runner, /MAX_STATE_BYTES = 900_000/); +assert.match(runner, /compactRuntimeTransportSnapshot\(rawSnapshot\)/); assert.match(runner, /Production already advanced to Build \$\{status\.build\}; retiring stale Build \$\{expectedBuild\} runner/); assert.equal(resolutionAudit.strategy, "resolution-window-no-50-55-forward-shadow-v3"); assert.deepEqual(resolutionAudit.selection.horizon_days_enabled, []); @@ -117,4 +118,35 @@ assert.throws(() => validateRuntimeSnapshot({ ...snapshot, items: { ...snapshot. assert.throws(() => validateRuntimeSnapshot({ ...snapshot, build_version: build - 1 }, build), /Expected Build/); assert.throws(() => validateRuntimeSnapshot({ ...snapshot, items: { ...snapshot.items, pma_suggestions_v5: JSON.stringify({ suggestions: [] }) } }, build), /no live suggestions/); +const transportState = JSON.parse(snapshot.items.pma_agents_v2); +for (const [index, portfolio] of Object.values(transportState.agents).entries()) { + portfolio.cash = 9000 + index; + portfolio.positions = [{ market_id: `position-${index}`, value: 1000 }]; + portfolio.history = Array.from({ length: 80 }, (_, row) => ({ date: "2026-08-22", action: "WATCH", question: "q".repeat(180), detail: "d".repeat(500 + row) })); + portfolio.snapshots = Array.from({ length: 240 }, (_, row) => ({ timestamp: new Date(1_700_000_000_000 + row * 300_000).toISOString(), equity: 10000 + row })); + portfolio.maker_outcomes = Array.from({ length: 45 }, (_, row) => ({ quote_id: `${index}-${row}`, pnl: row / 100 })); +} +transportState.signal_ledger = { + pending: Array.from({ length: 50 }, (_, index) => ({ key: `pending-${index}`, event_key: `event-${index}` })), + outcomes: Array.from({ length: 144 }, (_, index) => ({ key: `outcome-${index}`, event_key: `event-${index}`, return: 0.01 })), + expired_ungraded: 0, +}; +const transportSuggestions = { + suggestions: Array.from({ length: 300 }, (_, index) => ({ market_id: `${index}`, trade_ready: false, signal_type: "trend", rationale: "r".repeat(500), drivers: ["d".repeat(200)] })), +}; +const transportInput = { ...snapshot, items: { pma_agents_v2: JSON.stringify(transportState), pma_suggestions_v5: JSON.stringify(transportSuggestions) } }; +const transportOutput = compactRuntimeTransportSnapshot(transportInput); +const transportedState = JSON.parse(transportOutput.items.pma_agents_v2); +assert.equal(transportedState.signal_ledger.pending.length, 50); +assert.equal(transportedState.signal_ledger.outcomes.length, 144); +assert.equal(transportedState.agents.value.cash, 9000); +assert.equal(transportedState.agents.value.positions[0].market_id, "position-0"); +assert.equal(transportedState.agents.value.history.length, 24); +assert.equal(transportedState.agents.value.snapshots.length, 96); +assert.equal(transportedState.agents.value.snapshots[0].timestamp, transportState.agents.value.snapshots[0].timestamp); +assert.equal(transportedState.agents.value.snapshots.at(-1).timestamp, transportState.agents.value.snapshots.at(-1).timestamp); +assert.equal(transportedState.agents.value.maker_outcomes.length, 30); +assert.equal(JSON.parse(transportOutput.items.pma_suggestions_v5).suggestions.length, 300); +assert.ok(Buffer.byteLength(JSON.stringify(transportOutput)) < Buffer.byteLength(JSON.stringify(transportInput))); + console.log(`autonomous runtime verified for Build ${build}`);