diff --git a/scripts/run-autonomous-cycle.mjs b/scripts/run-autonomous-cycle.mjs index e5d7562..babbf96 100644 --- a/scripts/run-autonomous-cycle.mjs +++ b/scripts/run-autonomous-cycle.mjs @@ -16,6 +16,10 @@ const MAX_STATE_BYTES = 900_000; const TRANSPORT_HISTORY_LIMIT = 24; const TRANSPORT_SNAPSHOT_LIMIT = 96; const TRANSPORT_MAKER_OUTCOME_LIMIT = 30; +const TRANSPORT_TARGET_BYTES = 875_000; +const TRANSPORT_HISTORY_FLOOR = 12; +const TRANSPORT_MAKER_OUTCOME_FLOOR = 12; +const TRANSPORT_SUGGESTION_FLOOR = 240; function sampleSnapshots(rows, limit = TRANSPORT_SNAPSHOT_LIMIT) { const list = Array.isArray(rows) ? rows : []; @@ -63,6 +67,34 @@ function compactPublicSuggestion(suggestion) { return out; } +function compactDecision(decision) { + if (!decision || typeof decision !== "object") return decision; + const out = { ...decision }; + if (out.makerProfile && typeof out.makerProfile === "object") { + out.makerProfile = { version: out.makerProfile.version, outcomes: out.makerProfile.outcomes, global: out.makerProfile.global }; + } + if (out.learning && typeof out.learning === "object") { + out.learning = { ...out.learning }; + delete out.learning.buckets; + delete out.learning.current_buckets; + } + if (out.marketLearning && typeof out.marketLearning === "object") { + out.marketLearning = { ...out.marketLearning }; + delete out.marketLearning.buckets; + } + return out; +} + +function compactMakerOutcome(row) { + if (!row || typeof row !== "object") return row; + return { + quote_id: row.quote_id, market_id: row.market_id, event_key: row.event_key, category: row.category, + spread: row.spread, spread_band: row.spread_band, reward_yield_band: row.reward_yield_band, status: row.status, + pnl: row.pnl, shadow_only: row.shadow_only, deployed_capital: row.deployed_capital, reserved_capital: row.reserved_capital, + completed_at: row.completed_at, strategy_version: row.strategy_version, maker_strategy_version: row.maker_strategy_version, + }; +} + export function compactRuntimeTransportSnapshot(snapshot) { if (!snapshot || typeof snapshot !== "object" || !snapshot.items) return snapshot; const out = { ...snapshot, items: { ...snapshot.items } }; @@ -77,11 +109,29 @@ export function compactRuntimeTransportSnapshot(snapshot) { 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); + portfolio.maker_outcomes = (portfolio.maker_outcomes || []).slice(-TRANSPORT_MAKER_OUTCOME_LIMIT).map(compactMakerOutcome); + portfolio.lastDecision = compactDecision(portfolio.lastDecision); } suggestions.suggestions = (suggestions.suggestions || []).slice(0, 300).map(compactPublicSuggestion); out.items[AGENTS_KEY] = JSON.stringify(state); out.items[SUGGESTIONS_KEY] = JSON.stringify(suggestions); + if (Buffer.byteLength(JSON.stringify(out)) > TRANSPORT_TARGET_BYTES) { + for (const portfolio of Object.values(state.agents || {})) { + portfolio.history = (portfolio.history || []).slice(-TRANSPORT_HISTORY_FLOOR); + portfolio.maker_outcomes = (portfolio.maker_outcomes || []).slice(-TRANSPORT_MAKER_OUTCOME_FLOOR); + } + suggestions.suggestions = suggestions.suggestions.slice(0, TRANSPORT_SUGGESTION_FLOOR); + out.items[AGENTS_KEY] = JSON.stringify(state); + out.items[SUGGESTIONS_KEY] = JSON.stringify(suggestions); + } + if (out.summary && out.summary.signal_ledger && state.signal_ledger) { + const pending = Array.isArray(state.signal_ledger.pending) ? state.signal_ledger.pending.length : 0; + const outcomes = Array.isArray(state.signal_ledger.outcomes) ? state.signal_ledger.outcomes.length : 0; + out.summary.signal_ledger.pending_retained = pending; + out.summary.signal_ledger.pending_total = Math.max(Number(out.summary.signal_ledger.pending_total || 0), pending); + out.summary.signal_ledger.outcomes_retained = outcomes; + out.summary.signal_ledger.outcomes_total = Math.max(Number(out.summary.signal_ledger.outcomes_total || 0), outcomes); + } return out; } @@ -229,7 +279,14 @@ 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 rawSnapshot = await page.evaluate(() => window.PMA_AUTOMATION.exportShared()); + const rawSnapshot = await page.evaluate(({ agentKey, suggestionsKey }) => { + const snapshot = window.PMA_AUTOMATION.exportShared(); + const agents = localStorage.getItem(agentKey); + const suggestions = localStorage.getItem(suggestionsKey); + if (agents) snapshot.items[agentKey] = agents; + if (suggestions) snapshot.items[suggestionsKey] = suggestions; + return snapshot; + }, { agentKey: AGENTS_KEY, suggestionsKey: SUGGESTIONS_KEY }); const snapshot = compactRuntimeTransportSnapshot(rawSnapshot); const validated = validateRuntimeSnapshot(snapshot, expectedBuild); await writeRuntimeFile(repository, branch, pathname, snapshot, prior.sha); diff --git a/scripts/test-autonomous-runtime.mjs b/scripts/test-autonomous-runtime.mjs index 59e624d..7388f2a 100644 --- a/scripts/test-autonomous-runtime.mjs +++ b/scripts/test-autonomous-runtime.mjs @@ -79,6 +79,10 @@ 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, /localStorage\.getItem\(agentKey\)/); +assert.match(runner, /localStorage\.getItem\(suggestionsKey\)/); +assert.match(runner, /TRANSPORT_TARGET_BYTES = 875_000/); +assert.match(runner, /TRANSPORT_SUGGESTION_FLOOR = 240/); 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, []); @@ -134,7 +138,7 @@ transportState.signal_ledger = { 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 transportInput = { ...snapshot, summary: { signal_ledger: { pending_retained: 0, pending_total: 0, outcomes_retained: 0, outcomes_total: 0 } }, 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); @@ -147,6 +151,8 @@ assert.equal(transportedState.agents.value.snapshots[0].timestamp, transportStat 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.equal(transportOutput.summary.signal_ledger.pending_retained, 50); +assert.equal(transportOutput.summary.signal_ledger.outcomes_retained, 144); assert.ok(Buffer.byteLength(JSON.stringify(transportOutput)) < Buffer.byteLength(JSON.stringify(transportInput))); console.log(`autonomous runtime verified for Build ${build}`);