@tradejs/cli 3.1.29-beta.276 → 3.1.29-beta.278

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -2278,9 +2278,9 @@ var init_features = __esm({
2278
2278
  "targetsymbol",
2279
2279
  "universe"
2280
2280
  ]);
2281
- normalizeFeaturePath = (path44) => (Array.isArray(path44) ? path44 : path44.split(".")).filter(Boolean).map((segment) => segment.toLowerCase());
2282
- classifyAiPocketCoverageFeaturePath = (path44) => {
2283
- const segments = normalizeFeaturePath(path44);
2281
+ normalizeFeaturePath = (path47) => (Array.isArray(path47) ? path47 : path47.split(".")).filter(Boolean).map((segment) => segment.toLowerCase());
2282
+ classifyAiPocketCoverageFeaturePath = (path47) => {
2283
+ const segments = normalizeFeaturePath(path47);
2284
2284
  const normalizedPath = segments.join(".");
2285
2285
  if (segments.some(
2286
2286
  (segment) => segment.includes("cmc") || segment.includes("coinmarketcap")
@@ -2454,8 +2454,8 @@ var init_features = __esm({
2454
2454
  "volumeusd",
2455
2455
  "vwap"
2456
2456
  ]);
2457
- classifyAiPocketFeaturePath = (path44) => {
2458
- const segments = (Array.isArray(path44) ? path44 : path44.split(".")).filter(
2457
+ classifyAiPocketFeaturePath = (path47) => {
2458
+ const segments = (Array.isArray(path47) ? path47 : path47.split(".")).filter(
2459
2459
  Boolean
2460
2460
  );
2461
2461
  const normalized = segments.map((segment) => segment.toLowerCase());
@@ -2772,11 +2772,11 @@ var init_features = __esm({
2772
2772
  excludeFeaturePattern.source,
2773
2773
  excludeFeaturePattern.flags.replace(/[gy]/g, "")
2774
2774
  ) : void 0;
2775
- const isOperatorExcluded = (path44) => {
2776
- if (!exclusion?.test(path44)) {
2775
+ const isOperatorExcluded = (path47) => {
2776
+ if (!exclusion?.test(path47)) {
2777
2777
  return false;
2778
2778
  }
2779
- onFeatureExcluded?.({ path: path44, classification: "operator-excluded" });
2779
+ onFeatureExcluded?.({ path: path47, classification: "operator-excluded" });
2780
2780
  return true;
2781
2781
  };
2782
2782
  const signal = payload.signal ?? {};
@@ -11317,27 +11317,27 @@ var init_coinMarketCapContextBackfill = __esm({
11317
11317
  totalCredits: 0,
11318
11318
  byPath: /* @__PURE__ */ new Map()
11319
11319
  });
11320
- getCoinMarketCapPathLabel = (path44) => {
11321
- if (path44.includes("global-metrics")) return "global";
11322
- if (path44.includes("cryptocurrency/quotes")) return "reference";
11323
- if (path44.includes("exchange/quotes")) return "exchangeLiquidity";
11324
- if (path44.includes("fear-and-greed")) return "fearGreed";
11325
- if (path44.includes("cmc100")) return "cmc100";
11326
- if (path44.includes("cmc20")) return "cmc20";
11327
- return path44;
11328
- };
11329
- recordCoinMarketCapFetchStats = (stats, path44, creditCount) => {
11320
+ getCoinMarketCapPathLabel = (path47) => {
11321
+ if (path47.includes("global-metrics")) return "global";
11322
+ if (path47.includes("cryptocurrency/quotes")) return "reference";
11323
+ if (path47.includes("exchange/quotes")) return "exchangeLiquidity";
11324
+ if (path47.includes("fear-and-greed")) return "fearGreed";
11325
+ if (path47.includes("cmc100")) return "cmc100";
11326
+ if (path47.includes("cmc20")) return "cmc20";
11327
+ return path47;
11328
+ };
11329
+ recordCoinMarketCapFetchStats = (stats, path47, creditCount) => {
11330
11330
  if (!stats) return;
11331
- const existing = stats.byPath.get(path44) ?? { requests: 0, credits: 0 };
11331
+ const existing = stats.byPath.get(path47) ?? { requests: 0, credits: 0 };
11332
11332
  existing.requests += 1;
11333
11333
  existing.credits += creditCount ?? 0;
11334
11334
  stats.requests += 1;
11335
11335
  stats.totalCredits += creditCount ?? 0;
11336
- stats.byPath.set(path44, existing);
11336
+ stats.byPath.set(path47, existing);
11337
11337
  };
11338
11338
  formatCoinMarketCapFetchStats = (stats) => {
11339
11339
  const byPath = [...stats.byPath.entries()].map(
11340
- ([path44, item]) => `${getCoinMarketCapPathLabel(path44)}=${item.requests}req/${item.credits}cr`
11340
+ ([path47, item]) => `${getCoinMarketCapPathLabel(path47)}=${item.requests}req/${item.credits}cr`
11341
11341
  ).join(" ");
11342
11342
  return `apiRequests=${stats.requests} apiCredits=${stats.totalCredits}${byPath ? ` ${byPath}` : ""}`;
11343
11343
  };
@@ -24462,45 +24462,45 @@ var init_marketWsGateway = __esm({
24462
24462
  socket.destroy();
24463
24463
  return;
24464
24464
  }
24465
- wsServer.handleUpgrade(request, socket, head, (client) => {
24466
- wsServer.emit("connection", client, request);
24465
+ wsServer.handleUpgrade(request, socket, head, (client2) => {
24466
+ wsServer.emit("connection", client2, request);
24467
24467
  });
24468
24468
  });
24469
- wsServer.on("connection", (client) => {
24470
- subscriptions.set(client, /* @__PURE__ */ new Set());
24471
- alive.add(client);
24472
- client.on("pong", () => alive.add(client));
24473
- client.on("message", (raw) => {
24469
+ wsServer.on("connection", (client2) => {
24470
+ subscriptions.set(client2, /* @__PURE__ */ new Set());
24471
+ alive.add(client2);
24472
+ client2.on("pong", () => alive.add(client2));
24473
+ client2.on("message", (raw) => {
24474
24474
  const command = parseSubscriptionCommand(raw.toString());
24475
24475
  if (!command) {
24476
- client.send(JSON.stringify({ type: "error", error: "bad_command" }));
24476
+ client2.send(JSON.stringify({ type: "error", error: "bad_command" }));
24477
24477
  return;
24478
24478
  }
24479
24479
  subscriptions.set(
24480
- client,
24480
+ client2,
24481
24481
  applySubscriptionCommand(
24482
- subscriptions.get(client) ?? /* @__PURE__ */ new Set(),
24482
+ subscriptions.get(client2) ?? /* @__PURE__ */ new Set(),
24483
24483
  command
24484
24484
  )
24485
24485
  );
24486
- client.send(
24486
+ client2.send(
24487
24487
  JSON.stringify({
24488
24488
  type: "subscribed",
24489
- topics: [...subscriptions.get(client) ?? []]
24489
+ topics: [...subscriptions.get(client2) ?? []]
24490
24490
  })
24491
24491
  );
24492
24492
  });
24493
- client.on("close", () => subscriptions.delete(client));
24493
+ client2.on("close", () => subscriptions.delete(client2));
24494
24494
  });
24495
24495
  const heartbeat = setInterval(() => {
24496
- for (const client of subscriptions.keys()) {
24497
- if (!alive.has(client)) {
24498
- client.terminate();
24499
- subscriptions.delete(client);
24496
+ for (const client2 of subscriptions.keys()) {
24497
+ if (!alive.has(client2)) {
24498
+ client2.terminate();
24499
+ subscriptions.delete(client2);
24500
24500
  continue;
24501
24501
  }
24502
- alive.delete(client);
24503
- client.ping();
24502
+ alive.delete(client2);
24503
+ client2.ping();
24504
24504
  }
24505
24505
  }, 3e4);
24506
24506
  subscriber.on("message", (channel, payload) => {
@@ -24509,9 +24509,9 @@ var init_marketWsGateway = __esm({
24509
24509
  if (!event) return;
24510
24510
  const topic = buildMarketKlineTopic(event);
24511
24511
  const message = JSON.stringify({ type: "kline", topic, event });
24512
- for (const [client, topics] of subscriptions) {
24513
- if (client.readyState === import_ws.WebSocket.OPEN && topics.has(topic)) {
24514
- client.send(message);
24512
+ for (const [client2, topics] of subscriptions) {
24513
+ if (client2.readyState === import_ws.WebSocket.OPEN && topics.has(topic)) {
24514
+ client2.send(message);
24515
24515
  }
24516
24516
  }
24517
24517
  });
@@ -24527,7 +24527,7 @@ var init_marketWsGateway = __esm({
24527
24527
  return {
24528
24528
  close: async () => {
24529
24529
  clearInterval(heartbeat);
24530
- for (const client of subscriptions.keys()) client.close();
24530
+ for (const client2 of subscriptions.keys()) client2.close();
24531
24531
  subscriptions.clear();
24532
24532
  await subscriber.unsubscribe(MARKET_KLINE_CHANNEL);
24533
24533
  subscriber.disconnect();
@@ -24567,26 +24567,102 @@ var init_marketWs = __esm({
24567
24567
  }
24568
24568
  });
24569
24569
 
24570
+ // src/lib/runtimeEvidenceArtifacts.ts
24571
+ var runtimeEvidenceArtifacts_exports = {};
24572
+ var init_runtimeEvidenceArtifacts = __esm({
24573
+ "src/lib/runtimeEvidenceArtifacts.ts"() {
24574
+ "use strict";
24575
+ __reExport(runtimeEvidenceArtifacts_exports, require("@tradejs/node/diagnostics"));
24576
+ }
24577
+ });
24578
+
24579
+ // src/lib/mcpReplayProcess.ts
24580
+ var import_node_path14, import_node_crypto8, import_promises17, client, buildMcpReplayProcess;
24581
+ var init_mcpReplayProcess = __esm({
24582
+ "src/lib/mcpReplayProcess.ts"() {
24583
+ "use strict";
24584
+ import_node_path14 = __toESM(require("path"));
24585
+ import_node_crypto8 = require("crypto");
24586
+ import_promises17 = __toESM(require("fs/promises"));
24587
+ init_runtimeEvidenceArtifacts();
24588
+ client = `
24589
+ const fs = require('node:fs');
24590
+ const path = require('node:path');
24591
+ const [root, id, request] = process.argv.slice(1);
24592
+ const file = path.join(root, id);
24593
+ fs.mkdirSync(root, {recursive:true});
24594
+ try { fs.writeFileSync(file + '.request', request, {flag:'wx'}); }
24595
+ catch (error) { if (error.code !== 'EEXIST') throw error; if (fs.readFileSync(file + '.request', 'utf8') !== request) throw new Error('Replay request identity conflict'); }
24596
+ process.on('SIGTERM', () => { fs.writeFileSync(file + '.cancel', 'cancel'); process.exit(143); });
24597
+ const timer = setInterval(() => {
24598
+ try {
24599
+ const result = JSON.parse(fs.readFileSync(file + '.result', 'utf8'));
24600
+ console.log(result.message);
24601
+ clearInterval(timer);
24602
+ process.exit(result.exitCode === 0 ? 0 : 1);
24603
+ } catch (error) { if (error.code !== 'ENOENT') throw error; }
24604
+ }, 1000);
24605
+ `;
24606
+ buildMcpReplayProcess = async ({
24607
+ evidencePath,
24608
+ outDir,
24609
+ runId,
24610
+ projectRoot: projectRoot18,
24611
+ env
24612
+ }) => {
24613
+ if (!/^[a-f0-9]{64}$/.test(runId))
24614
+ throw new Error("Invalid replay request id");
24615
+ const bundle = await (0, runtimeEvidenceArtifacts_exports.verifyRuntimeEvidenceBundle)(import_node_path14.default.dirname(evidencePath));
24616
+ if (import_node_path14.default.resolve(evidencePath) !== import_node_path14.default.resolve(bundle.payloadPath))
24617
+ throw new Error("Replay requires the verified bundle payload");
24618
+ const relative = import_node_path14.default.relative(import_node_path14.default.join(projectRoot18, "data"), evidencePath);
24619
+ if (relative.startsWith("..") || import_node_path14.default.isAbsolute(relative))
24620
+ throw new Error("Evidence must be inside Project data");
24621
+ const root = env.MCP_REPLAY_REQUEST_ROOT || import_node_path14.default.join(projectRoot18, "data/mcp-replay-requests");
24622
+ const heartbeat = JSON.parse(
24623
+ await import_promises17.default.readFile(import_node_path14.default.join(root, "heartbeat.json"), "utf8")
24624
+ );
24625
+ if (!Number.isFinite(heartbeat.observedAt) || Date.now() - heartbeat.observedAt < 0 || Date.now() - heartbeat.observedAt > 12e4)
24626
+ throw new Error("Host replay runner heartbeat is stale");
24627
+ const bytes = await import_promises17.default.readFile(evidencePath);
24628
+ const request = JSON.stringify({
24629
+ schemaVersion: 1,
24630
+ id: runId,
24631
+ evidence: relative,
24632
+ artifactId: bundle.manifest.artifactId,
24633
+ deploymentId: bundle.manifest.deploymentId,
24634
+ payloadSha256: (0, import_node_crypto8.createHash)("sha256").update(bytes).digest("hex")
24635
+ });
24636
+ void outDir;
24637
+ return {
24638
+ executable: process.execPath,
24639
+ args: ["-e", client, root, runId, request]
24640
+ };
24641
+ };
24642
+ }
24643
+ });
24644
+
24570
24645
  // src/scripts/mcpWorker.ts
24571
24646
  var mcpWorker_exports = {};
24572
24647
  __export(mcpWorker_exports, {
24573
24648
  main: () => main26
24574
24649
  });
24575
- var import_node_child_process4, import_node_crypto8, import_promises17, import_redis15, import_mcp, pause, leaseKey, LEASE_SECONDS, JOB_TIMEOUT_MS, main26;
24650
+ var import_node_child_process4, import_node_crypto9, import_promises18, import_redis15, import_mcp, pause, leaseKey, LEASE_SECONDS, JOB_TIMEOUT_MS, main26;
24576
24651
  var init_mcpWorker = __esm({
24577
24652
  "src/scripts/mcpWorker.ts"() {
24578
24653
  "use strict";
24579
24654
  import_node_child_process4 = require("child_process");
24580
- import_node_crypto8 = require("crypto");
24581
- import_promises17 = require("fs/promises");
24655
+ import_node_crypto9 = require("crypto");
24656
+ import_promises18 = require("fs/promises");
24582
24657
  import_redis15 = require("@tradejs/infra/redis");
24583
24658
  import_mcp = require("@tradejs/node/mcp");
24659
+ init_mcpReplayProcess();
24584
24660
  pause = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
24585
24661
  leaseKey = "worker:lease";
24586
24662
  LEASE_SECONDS = 15;
24587
24663
  JOB_TIMEOUT_MS = 60 * 60 * 1e3;
24588
24664
  main26 = async (options = {}) => {
24589
- const owner = (0, import_node_crypto8.randomUUID)();
24665
+ const owner = (0, import_node_crypto9.randomUUID)();
24590
24666
  if (!await import_redis15.mcpStorage.put(leaseKey, owner, LEASE_SECONDS, true))
24591
24667
  throw new Error("Another MCP worker owns this storage");
24592
24668
  let stopping = false;
@@ -24594,6 +24670,18 @@ var init_mcpWorker = __esm({
24594
24670
  let renewing = false;
24595
24671
  let leaseLost = false;
24596
24672
  let manifestHash = "";
24673
+ let replayReady = false;
24674
+ const updateReplayReady = async () => {
24675
+ try {
24676
+ const root = process.env.MCP_REPLAY_REQUEST_ROOT || `${process.env.PROJECT_CWD || process.cwd()}/data/mcp-replay-requests`;
24677
+ const heartbeat2 = JSON.parse(
24678
+ await (0, import_promises18.readFile)(`${root}/heartbeat.json`, "utf8")
24679
+ );
24680
+ replayReady = Number.isFinite(heartbeat2.observedAt) && Date.now() - heartbeat2.observedAt >= 0 && Date.now() - heartbeat2.observedAt < 12e4;
24681
+ } catch {
24682
+ replayReady = false;
24683
+ }
24684
+ };
24597
24685
  const signalChild = (signal) => {
24598
24686
  if (!child?.pid) return;
24599
24687
  try {
@@ -24607,7 +24695,7 @@ var init_mcpWorker = __esm({
24607
24695
  const heartbeatValue = () => ({
24608
24696
  observedAt: Date.now(),
24609
24697
  packageManifestSha256: manifestHash,
24610
- replayAvailable: Boolean(process.env.MCP_REPLAY_REDIS_HOST)
24698
+ replayAvailable: replayReady
24611
24699
  });
24612
24700
  const stop = () => {
24613
24701
  stopping = true;
@@ -24623,6 +24711,7 @@ var init_mcpWorker = __esm({
24623
24711
  try {
24624
24712
  if (!await import_redis15.mcpStorage.compare(leaseKey, owner, owner, LEASE_SECONDS))
24625
24713
  throw new Error("Worker lease lost");
24714
+ await updateReplayReady();
24626
24715
  await import_redis15.mcpStorage.put("worker:heartbeat", heartbeatValue(), LEASE_SECONDS);
24627
24716
  } catch {
24628
24717
  leaseLost = true;
@@ -24633,6 +24722,7 @@ var init_mcpWorker = __esm({
24633
24722
  }, 2e3);
24634
24723
  try {
24635
24724
  manifestHash = await (0, import_mcp.mcpPackageManifestHash)();
24725
+ await updateReplayReady();
24636
24726
  await import_redis15.mcpStorage.put("worker:heartbeat", heartbeatValue(), LEASE_SECONDS);
24637
24727
  let cursor = "0";
24638
24728
  do {
@@ -24697,7 +24787,7 @@ var init_mcpWorker = __esm({
24697
24787
  );
24698
24788
  continue;
24699
24789
  }
24700
- await (0, import_promises17.mkdir)((0, import_mcp.mcpJobDirectory)(started), { recursive: true });
24790
+ await (0, import_promises18.mkdir)((0, import_mcp.mcpJobDirectory)(started), { recursive: true });
24701
24791
  if (started.kind === "backtest")
24702
24792
  await (0, import_redis15.setDataStrict)(
24703
24793
  import_redis15.redisKeys.backtestConfig(
@@ -24720,7 +24810,9 @@ var init_mcpWorker = __esm({
24720
24810
  };
24721
24811
  if (started.kind === "runtime-feedback-replay") {
24722
24812
  for (const name of Object.keys(jobEnv)) {
24723
- if (/secret|token|api.?key|private.?key|cookie|credential/i.test(name))
24813
+ if (/secret|password|token|api.?key|private.?key|cookie|credential/i.test(
24814
+ name
24815
+ ))
24724
24816
  delete jobEnv[name];
24725
24817
  }
24726
24818
  Object.assign(jobEnv, {
@@ -24733,7 +24825,35 @@ var init_mcpWorker = __esm({
24733
24825
  TRADEJS_TIMESCALE_READ_ONLY: "true"
24734
24826
  });
24735
24827
  }
24736
- child = (0, import_node_child_process4.spawn)(process.execPath, [process.argv[1], ...started.args], {
24828
+ let command = {
24829
+ executable: process.execPath,
24830
+ args: [process.argv[1], ...started.args]
24831
+ };
24832
+ try {
24833
+ if (started.kind === "runtime-feedback-replay")
24834
+ command = await buildMcpReplayProcess({
24835
+ evidencePath: String(started.request.verifiedEvidencePath),
24836
+ outDir: (0, import_mcp.mcpJobDirectory)(started),
24837
+ runId: started.id,
24838
+ projectRoot: process.env.PROJECT_CWD || process.cwd(),
24839
+ env: process.env
24840
+ });
24841
+ } catch (error) {
24842
+ await import_redis15.mcpStorage.compare(
24843
+ jobKey,
24844
+ started,
24845
+ {
24846
+ ...started,
24847
+ status: "failed",
24848
+ finishedAt: Date.now(),
24849
+ updatedAt: Date.now(),
24850
+ error: error instanceof Error ? error.message : "Replay preparation failed"
24851
+ },
24852
+ import_mcp.MCP_JOB_TTL
24853
+ );
24854
+ continue;
24855
+ }
24856
+ child = (0, import_node_child_process4.spawn)(command.executable, command.args, {
24737
24857
  cwd: process.env.PROJECT_CWD || process.cwd(),
24738
24858
  env: jobEnv,
24739
24859
  detached: process.platform !== "win32",
@@ -25178,13 +25298,13 @@ var hyperliquidWhalesUpdate_exports = {};
25178
25298
  __export(hyperliquidWhalesUpdate_exports, {
25179
25299
  main: () => main29
25180
25300
  });
25181
- var import_config8, import_args21, import_node_crypto9, import_strategies12, LEADERBOARD_URL, DAY_MS10, CANDIDATE_LIMIT, flags19, fingerprint, runConcurrent2, main29;
25301
+ var import_config8, import_args21, import_node_crypto10, import_strategies12, LEADERBOARD_URL, DAY_MS10, CANDIDATE_LIMIT, flags19, fingerprint, runConcurrent2, main29;
25182
25302
  var init_hyperliquidWhalesUpdate = __esm({
25183
25303
  "src/scripts/hyperliquidWhalesUpdate.ts"() {
25184
25304
  "use strict";
25185
25305
  import_config8 = require("dotenv/config");
25186
25306
  import_args21 = __toESM(require("args"));
25187
- import_node_crypto9 = require("crypto");
25307
+ import_node_crypto10 = require("crypto");
25188
25308
  import_strategies12 = require("@tradejs/node/strategies");
25189
25309
  init_hyperliquidWhaleBackfill();
25190
25310
  init_hyperliquidRateLimiter();
@@ -25198,7 +25318,7 @@ var init_hyperliquidWhalesUpdate = __esm({
25198
25318
  );
25199
25319
  import_args21.default.option(["d", "days"], "Calibration window in days", 7);
25200
25320
  flags19 = import_args21.default.parse(process.argv);
25201
- fingerprint = (addresses) => (0, import_node_crypto9.createHash)("sha256").update(JSON.stringify(addresses)).digest("hex").slice(0, 16);
25321
+ fingerprint = (addresses) => (0, import_node_crypto10.createHash)("sha256").update(JSON.stringify(addresses)).digest("hex").slice(0, 16);
25202
25322
  runConcurrent2 = async (params) => {
25203
25323
  let nextIndex = 0;
25204
25324
  await Promise.all(
@@ -25307,13 +25427,13 @@ var mlExport_exports = {};
25307
25427
  __export(mlExport_exports, {
25308
25428
  main: () => main30
25309
25429
  });
25310
- var import_args22, import_chalk37, import_promises18, import_path8, import_ml, flags20, resolveRunScopedMlChunks, main30;
25430
+ var import_args22, import_chalk37, import_promises19, import_path8, import_ml, flags20, resolveRunScopedMlChunks, main30;
25311
25431
  var init_mlExport = __esm({
25312
25432
  "src/scripts/mlExport.ts"() {
25313
25433
  "use strict";
25314
25434
  import_args22 = __toESM(require("args"));
25315
25435
  import_chalk37 = __toESM(require("chalk"));
25316
- import_promises18 = __toESM(require("fs/promises"));
25436
+ import_promises19 = __toESM(require("fs/promises"));
25317
25437
  import_path8 = __toESM(require("path"));
25318
25438
  import_ml = require("@tradejs/infra/ml");
25319
25439
  init_checkpoint();
@@ -25364,7 +25484,7 @@ var init_mlExport = __esm({
25364
25484
  };
25365
25485
  main30 = async () => {
25366
25486
  const outDir = String(flags20.outDir || "data/ml/export");
25367
- await import_promises18.default.mkdir(outDir, { recursive: true });
25487
+ await import_promises19.default.mkdir(outDir, { recursive: true });
25368
25488
  const strategyName = await resolveExportStrategy({
25369
25489
  explicitStrategy: String(flags20.strategy || ""),
25370
25490
  outDir,
@@ -25409,7 +25529,7 @@ var init_mlExport = __esm({
25409
25529
  const shouldDeleteChunks = !Boolean(flags20.keepChunks);
25410
25530
  if (shouldDeleteChunks) {
25411
25531
  for (const filePath of chunkFiles) {
25412
- await import_promises18.default.rm(filePath, { force: true });
25532
+ await import_promises19.default.rm(filePath, { force: true });
25413
25533
  }
25414
25534
  }
25415
25535
  console.log(import_chalk37.default.green(`Merged dataset saved: ${mergedPath}`));
@@ -25430,13 +25550,13 @@ var mlInspect_exports = {};
25430
25550
  __export(mlInspect_exports, {
25431
25551
  main: () => main31
25432
25552
  });
25433
- var import_args23, import_chalk38, import_promises19, import_fs3, import_path9, import_readline2, import_child_process2, flags21, toMode, toInspectTool, selectInspectTool, asPositiveInt, readRowsHead, readRowsTail, readRowsSample, quantileSorted, mean2, std, findLatestDataset, buildNumericStats, formatNumber5, runQuickInspect, runYDataInspect, main31;
25553
+ var import_args23, import_chalk38, import_promises20, import_fs3, import_path9, import_readline2, import_child_process2, flags21, toMode, toInspectTool, selectInspectTool, asPositiveInt, readRowsHead, readRowsTail, readRowsSample, quantileSorted, mean2, std, findLatestDataset, buildNumericStats, formatNumber5, runQuickInspect, runYDataInspect, main31;
25434
25554
  var init_mlInspect = __esm({
25435
25555
  "src/scripts/mlInspect.ts"() {
25436
25556
  "use strict";
25437
25557
  import_args23 = __toESM(require("args"));
25438
25558
  import_chalk38 = __toESM(require("chalk"));
25439
- import_promises19 = __toESM(require("fs/promises"));
25559
+ import_promises20 = __toESM(require("fs/promises"));
25440
25560
  import_fs3 = require("fs");
25441
25561
  import_path9 = __toESM(require("path"));
25442
25562
  import_readline2 = __toESM(require("readline"));
@@ -25613,7 +25733,7 @@ var init_mlInspect = __esm({
25613
25733
  };
25614
25734
  findLatestDataset = async (params) => {
25615
25735
  const { dir, strategy } = params;
25616
- const entries = await import_promises19.default.readdir(dir, { withFileTypes: true });
25736
+ const entries = await import_promises20.default.readdir(dir, { withFileTypes: true });
25617
25737
  const strategyToken = strategy.trim().toLowerCase();
25618
25738
  const files = entries.filter((entry) => entry.isFile()).map((entry) => entry.name).filter((name) => name.endsWith(".jsonl")).filter(
25619
25739
  (name) => !name.includes(".train.") && !name.includes(".test.")
@@ -25625,7 +25745,7 @@ var init_mlInspect = __esm({
25625
25745
  }
25626
25746
  const withMtime = await Promise.all(
25627
25747
  files.map(async (name) => {
25628
- const stat = await import_promises19.default.stat(import_path9.default.join(dir, name));
25748
+ const stat = await import_promises20.default.stat(import_path9.default.join(dir, name));
25629
25749
  return { name, mtime: stat.mtimeMs };
25630
25750
  })
25631
25751
  );
@@ -25870,7 +25990,7 @@ var init_mlInspect = __esm({
25870
25990
  const relToData = import_path9.default.relative(dataRoot, absDatasetPath);
25871
25991
  const inputInContainer = `/app/data/${relToData}`;
25872
25992
  const reportDir = import_path9.default.dirname(absDatasetPath);
25873
- await import_promises19.default.mkdir(reportDir, { recursive: true });
25993
+ await import_promises20.default.mkdir(reportDir, { recursive: true });
25874
25994
  const reportPath = import_path9.default.join(
25875
25995
  reportDir,
25876
25996
  `${import_path9.default.basename(datasetPath, import_path9.default.extname(datasetPath))}.profile.html`
@@ -25966,12 +26086,12 @@ var mlTrainLatestSelect_exports = {};
25966
26086
  __export(mlTrainLatestSelect_exports, {
25967
26087
  main: () => main32
25968
26088
  });
25969
- var import_path10, import_promises20, import_fs4, import_crypto2, import_child_process3, import_events, import_readline3, import_args24, import_chalk39, import_ml2, toFileToken6, asBool, asInt7, asNonNegativeInt, formatBytes, getMlContainerMemUsage, MODEL_TYPES, STRATEGIES, flags22, parseStrategy, parseModelType, selectModelType, listDatasetFiles, concatFiles, pipeNormalized, DAY_MS11, SPLIT_PROGRESS_EVERY, parseTimestampMs, scanMaxLabeledTimestampMs, scanMaxTrainTimestampMs, hashFileNameSha1, prepareTrainWindowFiles, main32;
26089
+ var import_path10, import_promises21, import_fs4, import_crypto2, import_child_process3, import_events, import_readline3, import_args24, import_chalk39, import_ml2, toFileToken6, asBool, asInt7, asNonNegativeInt, formatBytes, getMlContainerMemUsage, MODEL_TYPES, STRATEGIES, flags22, parseStrategy, parseModelType, selectModelType, listDatasetFiles, concatFiles, pipeNormalized, DAY_MS11, SPLIT_PROGRESS_EVERY, parseTimestampMs, scanMaxLabeledTimestampMs, scanMaxTrainTimestampMs, hashFileNameSha1, prepareTrainWindowFiles, main32;
25970
26090
  var init_mlTrainLatestSelect = __esm({
25971
26091
  "src/scripts/mlTrainLatestSelect.ts"() {
25972
26092
  "use strict";
25973
26093
  import_path10 = __toESM(require("path"));
25974
- import_promises20 = __toESM(require("fs/promises"));
26094
+ import_promises21 = __toESM(require("fs/promises"));
25975
26095
  import_fs4 = require("fs");
25976
26096
  import_crypto2 = require("crypto");
25977
26097
  import_child_process3 = require("child_process");
@@ -26100,7 +26220,7 @@ var init_mlTrainLatestSelect = __esm({
26100
26220
  return defaultModel;
26101
26221
  };
26102
26222
  listDatasetFiles = async (dir, strategyName) => {
26103
- const entries = await import_promises20.default.readdir(dir, { withFileTypes: true });
26223
+ const entries = await import_promises21.default.readdir(dir, { withFileTypes: true });
26104
26224
  const prefix = `ml-dataset-${toFileToken6(strategyName)}-`;
26105
26225
  const legacyPrefix = "ml-dataset-";
26106
26226
  const fileNames = entries.filter((entry) => entry.isFile()).map((entry) => entry.name);
@@ -26111,7 +26231,7 @@ var init_mlTrainLatestSelect = __esm({
26111
26231
  ).filter((name) => !name.includes(".train.") && !name.includes(".test.")).filter((name) => !name.includes(".holdout-train.")).filter((name) => !name.includes(".holdout-test.")).filter((name) => !name.includes(".walk-forward.")).filter((name) => !name.includes(".prod."));
26112
26232
  const withMtime = await Promise.all(
26113
26233
  jsonlFiles.map(async (name) => {
26114
- const stat = await import_promises20.default.stat(import_path10.default.join(dir, name));
26234
+ const stat = await import_promises21.default.stat(import_path10.default.join(dir, name));
26115
26235
  return { name, mtime: stat.mtimeMs };
26116
26236
  })
26117
26237
  );
@@ -26287,13 +26407,13 @@ var init_mlTrainLatestSelect = __esm({
26287
26407
  const metaPath = import_path10.default.join(dir, `${parsed.name}.windows.${key}.meta.json`);
26288
26408
  try {
26289
26409
  const [metaRaw] = await Promise.all([
26290
- import_promises20.default.readFile(metaPath, "utf8"),
26291
- import_promises20.default.access(holdoutTrainPath),
26292
- import_promises20.default.access(holdoutTestPath),
26293
- import_promises20.default.access(prodPath),
26410
+ import_promises21.default.readFile(metaPath, "utf8"),
26411
+ import_promises21.default.access(holdoutTrainPath),
26412
+ import_promises21.default.access(holdoutTestPath),
26413
+ import_promises21.default.access(prodPath),
26294
26414
  ...walkForwardFoldDefs.flatMap((entry) => [
26295
- import_promises20.default.access(entry.trainPath),
26296
- import_promises20.default.access(entry.testPath)
26415
+ import_promises21.default.access(entry.trainPath),
26416
+ import_promises21.default.access(entry.testPath)
26297
26417
  ])
26298
26418
  ]);
26299
26419
  const meta2 = JSON.parse(metaRaw);
@@ -26660,7 +26780,7 @@ var init_mlTrainLatestSelect = __esm({
26660
26780
  },
26661
26781
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
26662
26782
  };
26663
- await import_promises20.default.writeFile(metaPath, `${JSON.stringify(meta, null, 2)}
26783
+ await import_promises21.default.writeFile(metaPath, `${JSON.stringify(meta, null, 2)}
26664
26784
  `, "utf8");
26665
26785
  return {
26666
26786
  holdoutTrainPath,
@@ -26718,7 +26838,7 @@ var init_mlTrainLatestSelect = __esm({
26718
26838
  process.exit(1);
26719
26839
  }
26720
26840
  try {
26721
- const inputStat = await import_promises20.default.stat(inputPath);
26841
+ const inputStat = await import_promises21.default.stat(inputPath);
26722
26842
  const totalInputBytes = inputStat.size;
26723
26843
  const autoIncrementalThresholdGb = asInt7(
26724
26844
  process.env.ML_TRAIN_INCREMENTAL_THRESHOLD_GB,
@@ -26907,7 +27027,7 @@ var init_mlTrainLatestSelect = __esm({
26907
27027
  const modelDir = import_path10.default.join(modelDirRoot, "models");
26908
27028
  let savedModels = [];
26909
27029
  try {
26910
- const entries = await import_promises20.default.readdir(modelDir, { withFileTypes: true });
27030
+ const entries = await import_promises21.default.readdir(modelDir, { withFileTypes: true });
26911
27031
  savedModels = entries.filter((entry) => entry.isFile()).map((entry) => entry.name).filter(
26912
27032
  (name) => name === `${selected}.joblib` || /^.+\.model\d+\.joblib$/.test(name)
26913
27033
  ).filter((name) => name.startsWith(`${selected}.`)).sort();
@@ -26929,7 +27049,7 @@ var init_mlTrainLatestSelect = __esm({
26929
27049
  process.exitCode = finalCode;
26930
27050
  } finally {
26931
27051
  for (const file of cleanupFiles) {
26932
- await import_promises20.default.rm(file, { force: true });
27052
+ await import_promises21.default.rm(file, { force: true });
26933
27053
  }
26934
27054
  }
26935
27055
  process.exit(process.exitCode ?? 1);
@@ -26961,16 +27081,16 @@ __export(researchAuto_exports, {
26961
27081
  toStrategyConfigGrid: () => toStrategyConfigGrid2,
26962
27082
  trimTextTail: () => trimTextTail2
26963
27083
  });
26964
- var import_args25, import_chalk40, import_node_child_process5, import_promises21, import_node_os2, import_node_path14, import_constants18, import_ai8, import_logger6, import_redis16, import_registry4, flags23, projectRoot8, dotenvPath, getResearchAutoLockPath, readResearchAutoLock, isProcessAlive, acquireResearchAutoLock, releaseResearchAutoLock, resolvePositiveInteger, resolveHeapMbFromEnv, buildNodeOptions, RESEARCH_AUTO_PARENT_HEAP_MB, RESEARCH_AUTO_BACKTEST_PARENT_HEAP_MB, RESEARCH_AUTO_AI_TRAIN_PARENT_HEAP_MB, RESEARCH_AUTO_AGENT_PARENT_HEAP_MB, trimTextTail2, escapeHtml3, createEmptySteps, saveRun, listMergedFiles3, getBacktestResultsPrefix, listRuntimeStrategyNames, toStrategyConfigGrid2, formatMskDateTime, buildTelegramReport, runCliCommand, resolveTarget, parseJsonOutput, logResearch, executeNonBlockingStep, main33;
27084
+ var import_args25, import_chalk40, import_node_child_process5, import_promises22, import_node_os2, import_node_path15, import_constants18, import_ai8, import_logger6, import_redis16, import_registry4, flags23, projectRoot8, dotenvPath, getResearchAutoLockPath, readResearchAutoLock, isProcessAlive, acquireResearchAutoLock, releaseResearchAutoLock, resolvePositiveInteger, resolveHeapMbFromEnv, buildNodeOptions, RESEARCH_AUTO_PARENT_HEAP_MB, RESEARCH_AUTO_BACKTEST_PARENT_HEAP_MB, RESEARCH_AUTO_AI_TRAIN_PARENT_HEAP_MB, RESEARCH_AUTO_AGENT_PARENT_HEAP_MB, trimTextTail2, escapeHtml3, createEmptySteps, saveRun, listMergedFiles3, getBacktestResultsPrefix, listRuntimeStrategyNames, toStrategyConfigGrid2, formatMskDateTime, buildTelegramReport, runCliCommand, resolveTarget, parseJsonOutput, logResearch, executeNonBlockingStep, main33;
26965
27085
  var init_researchAuto = __esm({
26966
27086
  "src/scripts/researchAuto.ts"() {
26967
27087
  "use strict";
26968
27088
  import_args25 = __toESM(require("args"));
26969
27089
  import_chalk40 = __toESM(require("chalk"));
26970
27090
  import_node_child_process5 = require("child_process");
26971
- import_promises21 = __toESM(require("fs/promises"));
27091
+ import_promises22 = __toESM(require("fs/promises"));
26972
27092
  import_node_os2 = __toESM(require("os"));
26973
- import_node_path14 = __toESM(require("path"));
27093
+ import_node_path15 = __toESM(require("path"));
26974
27094
  import_constants18 = require("@tradejs/core/constants");
26975
27095
  import_ai8 = require("@tradejs/infra/ai");
26976
27096
  import_logger6 = require("@tradejs/infra/logger");
@@ -27004,9 +27124,9 @@ var init_researchAuto = __esm({
27004
27124
  flags23 = import_args25.default.parse(process.argv);
27005
27125
  ({ projectRoot: projectRoot8 } = resolveResearchRoots());
27006
27126
  dotenvPath = String(
27007
- process.env.DOTENV_CONFIG_PATH || import_node_path14.default.join(projectRoot8, ".env")
27008
- ).trim() || import_node_path14.default.join(projectRoot8, ".env");
27009
- getResearchAutoLockPath = (userName3) => import_node_path14.default.join(
27127
+ process.env.DOTENV_CONFIG_PATH || import_node_path15.default.join(projectRoot8, ".env")
27128
+ ).trim() || import_node_path15.default.join(projectRoot8, ".env");
27129
+ getResearchAutoLockPath = (userName3) => import_node_path15.default.join(
27010
27130
  projectRoot8,
27011
27131
  "data",
27012
27132
  "cache",
@@ -27015,7 +27135,7 @@ var init_researchAuto = __esm({
27015
27135
  );
27016
27136
  readResearchAutoLock = async (lockPath) => {
27017
27137
  try {
27018
- const raw = await import_promises21.default.readFile(lockPath, "utf8");
27138
+ const raw = await import_promises22.default.readFile(lockPath, "utf8");
27019
27139
  return JSON.parse(raw);
27020
27140
  } catch {
27021
27141
  return null;
@@ -27050,9 +27170,9 @@ var init_researchAuto = __esm({
27050
27170
  startedAt,
27051
27171
  argv: [...process.argv]
27052
27172
  };
27053
- await import_promises21.default.mkdir(import_node_path14.default.dirname(lockPath), { recursive: true });
27173
+ await import_promises22.default.mkdir(import_node_path15.default.dirname(lockPath), { recursive: true });
27054
27174
  const writeLock = async () => {
27055
- await import_promises21.default.writeFile(lockPath, JSON.stringify(nextLock, null, 2), {
27175
+ await import_promises22.default.writeFile(lockPath, JSON.stringify(nextLock, null, 2), {
27056
27176
  flag: "wx"
27057
27177
  });
27058
27178
  };
@@ -27071,7 +27191,7 @@ var init_researchAuto = __esm({
27071
27191
  `research:auto is already running for user ${userName3} (runId=${existingLock.runId}, strategy=${existingLock.strategy}, pid=${existingLock.pid}, ppid=${existingLock.ppid}, startedAt=${existingLock.startedAt}, host=${existingLock.hostname})`
27072
27192
  );
27073
27193
  }
27074
- await import_promises21.default.unlink(lockPath).catch(() => void 0);
27194
+ await import_promises22.default.unlink(lockPath).catch(() => void 0);
27075
27195
  await writeLock();
27076
27196
  return lockPath;
27077
27197
  };
@@ -27083,7 +27203,7 @@ var init_researchAuto = __esm({
27083
27203
  if (existingLock && existingLock.pid !== process.pid) {
27084
27204
  return;
27085
27205
  }
27086
- await import_promises21.default.unlink(lockPath).catch(() => void 0);
27206
+ await import_promises22.default.unlink(lockPath).catch(() => void 0);
27087
27207
  };
27088
27208
  resolvePositiveInteger = (value, fallback) => {
27089
27209
  const parsed = Number.parseInt(String(value ?? ""), 10);
@@ -27185,9 +27305,9 @@ var init_researchAuto = __esm({
27185
27305
  };
27186
27306
  listMergedFiles3 = async (outDir, strategyName) => {
27187
27307
  try {
27188
- const entries = await import_promises21.default.readdir(outDir);
27308
+ const entries = await import_promises22.default.readdir(outDir);
27189
27309
  const prefix = `ai-dataset-${(0, import_ai8.toFileToken)(strategyName)}-merged-`;
27190
- return entries.filter((name) => name.startsWith(prefix) && name.endsWith(".jsonl")).sort().map((name) => import_node_path14.default.join(outDir, name));
27310
+ return entries.filter((name) => name.startsWith(prefix) && name.endsWith(".jsonl")).sort().map((name) => import_node_path15.default.join(outDir, name));
27191
27311
  } catch {
27192
27312
  return [];
27193
27313
  }
@@ -27321,7 +27441,7 @@ var init_researchAuto = __esm({
27321
27441
  return new Promise((resolve, reject) => {
27322
27442
  const child = (0, import_node_child_process5.spawn)(
27323
27443
  process.execPath,
27324
- [import_node_path14.default.resolve(process.argv[1]), params.command, ...params.args],
27444
+ [import_node_path15.default.resolve(process.argv[1]), params.command, ...params.args],
27325
27445
  {
27326
27446
  cwd: projectRoot8,
27327
27447
  env,
@@ -27504,8 +27624,8 @@ var init_researchAuto = __esm({
27504
27624
  const jsonOutput = Boolean(flags23.json);
27505
27625
  const skipAgent = Boolean(flags23.skipAgent);
27506
27626
  const outDirArg = String(flags23.outDir || "data/ai/export").trim() || "data/ai/export";
27507
- const outDir = import_node_path14.default.resolve(projectRoot8, outDirArg);
27508
- const cleanDirArg = import_node_path14.default.relative(import_node_path14.default.join(projectRoot8, "data"), outDir).replace(/\\/g, "/");
27627
+ const outDir = import_node_path15.default.resolve(projectRoot8, outDirArg);
27628
+ const cleanDirArg = import_node_path15.default.relative(import_node_path15.default.join(projectRoot8, "data"), outDir).replace(/\\/g, "/");
27509
27629
  const target = await resolveTarget();
27510
27630
  const runId = `${Date.now()}-${(0, import_ai8.toFileToken)(target.strategy)}`;
27511
27631
  const run = {
@@ -27853,15 +27973,15 @@ var init_types = __esm({
27853
27973
  function assert(condition, message) {
27854
27974
  if (!condition) throw new Error(`Invalid core research spec: ${message}`);
27855
27975
  }
27856
- var import_node_crypto10, import_node_fs3, import_promises22, import_backtest5, import_node_path15, RESEARCH_ID_RE, SHA256_RE, canonicalJson, sha256Text, sha256Json, sha256File, assertFinite, validateCoreResearchSpec, loadCoreResearchSpec, resolveCoreResearchPaths, writeJsonAtomic, buildLedgerRecordHash, readCoreResearchLedger, verifyCoreResearchLedger, appendCoreResearchLedger, validateCoreResearchParentLineage, prepareCoreResearch, verifyCoreResearchArtifacts, scanCoreResearchStages, writeCoreResearchStageIndex;
27976
+ var import_node_crypto11, import_node_fs3, import_promises23, import_backtest5, import_node_path16, RESEARCH_ID_RE, SHA256_RE, canonicalJson, sha256Text, sha256Json, sha256File, assertFinite, validateCoreResearchSpec, loadCoreResearchSpec, resolveCoreResearchPaths, writeJsonAtomic, buildLedgerRecordHash, readCoreResearchLedger, verifyCoreResearchLedger, appendCoreResearchLedger, validateCoreResearchParentLineage, prepareCoreResearch, verifyCoreResearchArtifacts, scanCoreResearchStages, writeCoreResearchStageIndex;
27857
27977
  var init_io = __esm({
27858
27978
  "src/lib/coreResearch/io.ts"() {
27859
27979
  "use strict";
27860
- import_node_crypto10 = require("crypto");
27980
+ import_node_crypto11 = require("crypto");
27861
27981
  import_node_fs3 = require("fs");
27862
- import_promises22 = __toESM(require("fs/promises"));
27982
+ import_promises23 = __toESM(require("fs/promises"));
27863
27983
  import_backtest5 = require("@tradejs/core/backtest");
27864
- import_node_path15 = __toESM(require("path"));
27984
+ import_node_path16 = __toESM(require("path"));
27865
27985
  init_types();
27866
27986
  RESEARCH_ID_RE = /^[a-z0-9][a-z0-9._-]{2,120}$/;
27867
27987
  SHA256_RE = /^[a-f0-9]{64}$/;
@@ -27877,10 +27997,10 @@ var init_io = __esm({
27877
27997
  };
27878
27998
  return JSON.stringify(normalize(value));
27879
27999
  };
27880
- sha256Text = (value) => (0, import_node_crypto10.createHash)("sha256").update(value).digest("hex");
28000
+ sha256Text = (value) => (0, import_node_crypto11.createHash)("sha256").update(value).digest("hex");
27881
28001
  sha256Json = (value) => sha256Text(canonicalJson(value));
27882
28002
  sha256File = async (filePath) => {
27883
- const hash = (0, import_node_crypto10.createHash)("sha256");
28003
+ const hash = (0, import_node_crypto11.createHash)("sha256");
27884
28004
  const input = (0, import_node_fs3.createReadStream)(filePath);
27885
28005
  for await (const chunk of input) hash.update(chunk);
27886
28006
  return hash.digest("hex");
@@ -28120,40 +28240,40 @@ var init_io = __esm({
28120
28240
  return spec;
28121
28241
  };
28122
28242
  loadCoreResearchSpec = async (specPath) => {
28123
- const resolvedPath = import_node_path15.default.resolve(specPath);
28124
- const parsed = JSON.parse(await import_promises22.default.readFile(resolvedPath, "utf8"));
28243
+ const resolvedPath = import_node_path16.default.resolve(specPath);
28244
+ const parsed = JSON.parse(await import_promises23.default.readFile(resolvedPath, "utf8"));
28125
28245
  const spec = validateCoreResearchSpec(parsed);
28126
28246
  return { resolvedPath, spec, specSha256: sha256Json(spec) };
28127
28247
  };
28128
28248
  resolveCoreResearchPaths = (spec) => {
28129
- const rootDir = import_node_path15.default.resolve(spec.artifacts.rootDir);
28130
- const researchDir = import_node_path15.default.join(rootDir, spec.researchId);
28249
+ const rootDir = import_node_path16.default.resolve(spec.artifacts.rootDir);
28250
+ const researchDir = import_node_path16.default.join(rootDir, spec.researchId);
28131
28251
  return {
28132
28252
  rootDir,
28133
28253
  researchDir,
28134
- ledgerPath: import_node_path15.default.resolve(spec.artifacts.ledgerPath),
28135
- specPath: import_node_path15.default.join(researchDir, "spec.json"),
28136
- manifestPath: import_node_path15.default.join(researchDir, "manifest.json"),
28137
- resultPath: import_node_path15.default.join(researchDir, "result.json"),
28138
- comparisonPath: import_node_path15.default.join(researchDir, "comparison.json"),
28139
- matchesPath: import_node_path15.default.join(researchDir, "matches.csv"),
28140
- tradesPath: import_node_path15.default.join(researchDir, "trades.jsonl"),
28141
- reportPath: import_node_path15.default.join(researchDir, "report.html"),
28142
- runLogDir: import_node_path15.default.join(researchDir, "runs")
28254
+ ledgerPath: import_node_path16.default.resolve(spec.artifacts.ledgerPath),
28255
+ specPath: import_node_path16.default.join(researchDir, "spec.json"),
28256
+ manifestPath: import_node_path16.default.join(researchDir, "manifest.json"),
28257
+ resultPath: import_node_path16.default.join(researchDir, "result.json"),
28258
+ comparisonPath: import_node_path16.default.join(researchDir, "comparison.json"),
28259
+ matchesPath: import_node_path16.default.join(researchDir, "matches.csv"),
28260
+ tradesPath: import_node_path16.default.join(researchDir, "trades.jsonl"),
28261
+ reportPath: import_node_path16.default.join(researchDir, "report.html"),
28262
+ runLogDir: import_node_path16.default.join(researchDir, "runs")
28143
28263
  };
28144
28264
  };
28145
28265
  writeJsonAtomic = async (filePath, value) => {
28146
- await import_promises22.default.mkdir(import_node_path15.default.dirname(filePath), { recursive: true });
28266
+ await import_promises23.default.mkdir(import_node_path16.default.dirname(filePath), { recursive: true });
28147
28267
  const temporaryPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
28148
- await import_promises22.default.writeFile(temporaryPath, `${canonicalJson(value)}
28268
+ await import_promises23.default.writeFile(temporaryPath, `${canonicalJson(value)}
28149
28269
  `, "utf8");
28150
- await import_promises22.default.rename(temporaryPath, filePath);
28270
+ await import_promises23.default.rename(temporaryPath, filePath);
28151
28271
  };
28152
28272
  buildLedgerRecordHash = (record) => sha256Json(record);
28153
28273
  readCoreResearchLedger = async (ledgerPath) => {
28154
28274
  let text = "";
28155
28275
  try {
28156
- text = await import_promises22.default.readFile(ledgerPath, "utf8");
28276
+ text = await import_promises23.default.readFile(ledgerPath, "utf8");
28157
28277
  } catch (error) {
28158
28278
  if (error.code === "ENOENT") return [];
28159
28279
  throw error;
@@ -28190,11 +28310,11 @@ var init_io = __esm({
28190
28310
  };
28191
28311
  appendCoreResearchLedger = async (params) => {
28192
28312
  const { ledgerPath } = params;
28193
- await import_promises22.default.mkdir(import_node_path15.default.dirname(ledgerPath), { recursive: true });
28313
+ await import_promises23.default.mkdir(import_node_path16.default.dirname(ledgerPath), { recursive: true });
28194
28314
  const lockPath = `${ledgerPath}.lock`;
28195
28315
  let lock = null;
28196
28316
  try {
28197
- lock = await import_promises22.default.open(lockPath, "wx");
28317
+ lock = await import_promises23.default.open(lockPath, "wx");
28198
28318
  const records = await readCoreResearchLedger(ledgerPath);
28199
28319
  const verified = verifyCoreResearchLedger(records);
28200
28320
  const payload = {
@@ -28213,7 +28333,7 @@ var init_io = __esm({
28213
28333
  ...payload,
28214
28334
  recordHash: buildLedgerRecordHash(payload)
28215
28335
  };
28216
- await import_promises22.default.appendFile(ledgerPath, `${canonicalJson(record)}
28336
+ await import_promises23.default.appendFile(ledgerPath, `${canonicalJson(record)}
28217
28337
  `, "utf8");
28218
28338
  return record;
28219
28339
  } catch (error) {
@@ -28223,20 +28343,20 @@ var init_io = __esm({
28223
28343
  throw error;
28224
28344
  } finally {
28225
28345
  await lock?.close();
28226
- await import_promises22.default.rm(lockPath, { force: true });
28346
+ await import_promises23.default.rm(lockPath, { force: true });
28227
28347
  }
28228
28348
  };
28229
28349
  validateCoreResearchParentLineage = async (spec) => {
28230
28350
  if (spec.stage === "screen") return;
28231
28351
  const expectedParentStage = spec.stage === "isolated_long" ? "screen" : "isolated_long";
28232
- const rootDir = import_node_path15.default.resolve(spec.artifacts.rootDir);
28352
+ const rootDir = import_node_path16.default.resolve(spec.artifacts.rootDir);
28233
28353
  const passedParentCandidateConfigShas = /* @__PURE__ */ new Set();
28234
28354
  for (const parentResearchId of spec.parentResearchIds ?? []) {
28235
- const parentDir = import_node_path15.default.join(rootDir, parentResearchId);
28355
+ const parentDir = import_node_path16.default.join(rootDir, parentResearchId);
28236
28356
  const [parentSpec, parentManifest, parentResult] = await Promise.all([
28237
- import_promises22.default.readFile(import_node_path15.default.join(parentDir, "spec.json"), "utf8").then((text) => JSON.parse(text)),
28238
- import_promises22.default.readFile(import_node_path15.default.join(parentDir, "manifest.json"), "utf8").then((text) => JSON.parse(text)),
28239
- import_promises22.default.readFile(import_node_path15.default.join(parentDir, "result.json"), "utf8").then((text) => JSON.parse(text))
28357
+ import_promises23.default.readFile(import_node_path16.default.join(parentDir, "spec.json"), "utf8").then((text) => JSON.parse(text)),
28358
+ import_promises23.default.readFile(import_node_path16.default.join(parentDir, "manifest.json"), "utf8").then((text) => JSON.parse(text)),
28359
+ import_promises23.default.readFile(import_node_path16.default.join(parentDir, "result.json"), "utf8").then((text) => JSON.parse(text))
28240
28360
  ]);
28241
28361
  validateCoreResearchSpec(parentSpec);
28242
28362
  if (parentManifest.status !== "completed") {
@@ -28283,12 +28403,12 @@ var init_io = __esm({
28283
28403
  await validateCoreResearchParentLineage(spec);
28284
28404
  const specSha256 = sha256Json(spec);
28285
28405
  const paths = resolveCoreResearchPaths(spec);
28286
- await import_promises22.default.mkdir(paths.researchDir, { recursive: true });
28406
+ await import_promises23.default.mkdir(paths.researchDir, { recursive: true });
28287
28407
  let existing = null;
28288
28408
  let existingManifest = null;
28289
28409
  try {
28290
28410
  existing = JSON.parse(
28291
- await import_promises22.default.readFile(paths.specPath, "utf8")
28411
+ await import_promises23.default.readFile(paths.specPath, "utf8")
28292
28412
  );
28293
28413
  } catch (error) {
28294
28414
  if (error.code !== "ENOENT") throw error;
@@ -28301,7 +28421,7 @@ var init_io = __esm({
28301
28421
  if (existing) {
28302
28422
  try {
28303
28423
  existingManifest = JSON.parse(
28304
- await import_promises22.default.readFile(paths.manifestPath, "utf8")
28424
+ await import_promises23.default.readFile(paths.manifestPath, "utf8")
28305
28425
  );
28306
28426
  } catch (error) {
28307
28427
  if (error.code !== "ENOENT") throw error;
@@ -28340,7 +28460,7 @@ var init_io = __esm({
28340
28460
  verifyCoreResearchArtifacts = async (spec) => {
28341
28461
  const paths = resolveCoreResearchPaths(spec);
28342
28462
  const manifest = JSON.parse(
28343
- await import_promises22.default.readFile(paths.manifestPath, "utf8")
28463
+ await import_promises23.default.readFile(paths.manifestPath, "utf8")
28344
28464
  );
28345
28465
  if (manifest.specSha256 !== sha256Json(spec)) {
28346
28466
  throw new Error("Manifest spec hash does not match the supplied spec");
@@ -28349,7 +28469,7 @@ var init_io = __esm({
28349
28469
  manifest.artifactHashes
28350
28470
  )) {
28351
28471
  const actualHash = await sha256File(
28352
- import_node_path15.default.join(paths.researchDir, relativePath)
28472
+ import_node_path16.default.join(paths.researchDir, relativePath)
28353
28473
  );
28354
28474
  if (actualHash !== expectedHash) {
28355
28475
  throw new Error(`Artifact hash mismatch: ${relativePath}`);
@@ -28365,10 +28485,10 @@ var init_io = __esm({
28365
28485
  };
28366
28486
  };
28367
28487
  scanCoreResearchStages = async (rootDir) => {
28368
- const resolvedRoot = import_node_path15.default.resolve(rootDir);
28488
+ const resolvedRoot = import_node_path16.default.resolve(rootDir);
28369
28489
  let entries = [];
28370
28490
  try {
28371
- entries = await import_promises22.default.readdir(resolvedRoot);
28491
+ entries = await import_promises23.default.readdir(resolvedRoot);
28372
28492
  } catch (error) {
28373
28493
  if (error.code === "ENOENT") {
28374
28494
  return {
@@ -28383,15 +28503,15 @@ var init_io = __esm({
28383
28503
  for (const entry of entries.sort(
28384
28504
  (left, right) => left < right ? -1 : left > right ? 1 : 0
28385
28505
  )) {
28386
- const researchDir = import_node_path15.default.join(resolvedRoot, entry);
28387
- const stats = await import_promises22.default.stat(researchDir);
28506
+ const researchDir = import_node_path16.default.join(resolvedRoot, entry);
28507
+ const stats = await import_promises23.default.stat(researchDir);
28388
28508
  if (!stats.isDirectory()) continue;
28389
28509
  let spec;
28390
28510
  let manifest;
28391
28511
  try {
28392
28512
  [spec, manifest] = await Promise.all([
28393
- import_promises22.default.readFile(import_node_path15.default.join(researchDir, "spec.json"), "utf8").then((text) => JSON.parse(text)),
28394
- import_promises22.default.readFile(import_node_path15.default.join(researchDir, "manifest.json"), "utf8").then((text) => JSON.parse(text))
28513
+ import_promises23.default.readFile(import_node_path16.default.join(researchDir, "spec.json"), "utf8").then((text) => JSON.parse(text)),
28514
+ import_promises23.default.readFile(import_node_path16.default.join(researchDir, "manifest.json"), "utf8").then((text) => JSON.parse(text))
28395
28515
  ]);
28396
28516
  } catch (error) {
28397
28517
  if (error.code === "ENOENT") continue;
@@ -28401,7 +28521,7 @@ var init_io = __esm({
28401
28521
  if (manifest.specSha256 !== sha256Json(spec)) {
28402
28522
  throw new Error(`Stage index found a spec hash mismatch for ${entry}`);
28403
28523
  }
28404
- const result = manifest.status === "completed" ? await import_promises22.default.readFile(import_node_path15.default.join(researchDir, "result.json"), "utf8").then((text) => JSON.parse(text)) : null;
28524
+ const result = manifest.status === "completed" ? await import_promises23.default.readFile(import_node_path16.default.join(researchDir, "result.json"), "utf8").then((text) => JSON.parse(text)) : null;
28405
28525
  familyByResearch.set(spec.researchId, spec.hypothesis.family);
28406
28526
  experiments.push({
28407
28527
  researchId: spec.researchId,
@@ -28432,7 +28552,7 @@ var init_io = __esm({
28432
28552
  return { experiments, familyByResearch };
28433
28553
  };
28434
28554
  writeCoreResearchStageIndex = async (rootDir) => {
28435
- const resolvedRoot = import_node_path15.default.resolve(rootDir);
28555
+ const resolvedRoot = import_node_path16.default.resolve(rootDir);
28436
28556
  const { experiments, familyByResearch } = await scanCoreResearchStages(resolvedRoot);
28437
28557
  const grouped = /* @__PURE__ */ new Map();
28438
28558
  for (const experiment of experiments) {
@@ -28449,21 +28569,21 @@ var init_io = __esm({
28449
28569
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
28450
28570
  families: [...grouped.entries()].sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0).map(([family, experiments2]) => ({ family, experiments: experiments2 }))
28451
28571
  };
28452
- await writeJsonAtomic(import_node_path15.default.join(resolvedRoot, "index.json"), index);
28572
+ await writeJsonAtomic(import_node_path16.default.join(resolvedRoot, "index.json"), index);
28453
28573
  return index;
28454
28574
  };
28455
28575
  }
28456
28576
  });
28457
28577
 
28458
28578
  // src/lib/coreResearch/artifacts.ts
28459
- var import_node_fs4, import_node_events, import_promises23, import_node_path16, csv, writeLine, closeOutput, writeCoreResearchMatches, writeCoreResearchTrades;
28579
+ var import_node_fs4, import_node_events, import_promises24, import_node_path17, csv, writeLine, closeOutput, writeCoreResearchMatches, writeCoreResearchTrades;
28460
28580
  var init_artifacts = __esm({
28461
28581
  "src/lib/coreResearch/artifacts.ts"() {
28462
28582
  "use strict";
28463
28583
  import_node_fs4 = require("fs");
28464
28584
  import_node_events = require("events");
28465
- import_promises23 = __toESM(require("fs/promises"));
28466
- import_node_path16 = __toESM(require("path"));
28585
+ import_promises24 = __toESM(require("fs/promises"));
28586
+ import_node_path17 = __toESM(require("path"));
28467
28587
  init_io();
28468
28588
  csv = (value) => {
28469
28589
  const text = String(value ?? "");
@@ -28477,7 +28597,7 @@ var init_artifacts = __esm({
28477
28597
  await (0, import_node_events.once)(output, "close");
28478
28598
  };
28479
28599
  writeCoreResearchMatches = async (params) => {
28480
- await import_promises23.default.mkdir(import_node_path16.default.dirname(params.filePath), { recursive: true });
28600
+ await import_promises24.default.mkdir(import_node_path17.default.dirname(params.filePath), { recursive: true });
28481
28601
  const output = (0, import_node_fs4.createWriteStream)(params.filePath, { encoding: "utf8" });
28482
28602
  await writeLine(
28483
28603
  output,
@@ -28528,7 +28648,7 @@ var init_artifacts = __esm({
28528
28648
  await closeOutput(output);
28529
28649
  };
28530
28650
  writeCoreResearchTrades = async (params) => {
28531
- await import_promises23.default.mkdir(import_node_path16.default.dirname(params.filePath), { recursive: true });
28651
+ await import_promises24.default.mkdir(import_node_path17.default.dirname(params.filePath), { recursive: true });
28532
28652
  const output = (0, import_node_fs4.createWriteStream)(params.filePath, { encoding: "utf8" });
28533
28653
  for (const variant of params.variants) {
28534
28654
  for (const trade of variant.trades) {
@@ -28768,14 +28888,14 @@ var init_rules = __esm({
28768
28888
  });
28769
28889
 
28770
28890
  // src/lib/coreResearch/statistics.ts
28771
- var import_node_crypto11, createSeededRandom, percentile, calendarClusterBootstrap, applyHolmCorrection, inverseNormalCdf, erf, normalCdf, deflatedSharpeDiagnostic, combinations, probabilityOfBacktestOverfitting;
28891
+ var import_node_crypto12, createSeededRandom, percentile, calendarClusterBootstrap, applyHolmCorrection, inverseNormalCdf, erf, normalCdf, deflatedSharpeDiagnostic, combinations, probabilityOfBacktestOverfitting;
28772
28892
  var init_statistics = __esm({
28773
28893
  "src/lib/coreResearch/statistics.ts"() {
28774
28894
  "use strict";
28775
- import_node_crypto11 = require("crypto");
28895
+ import_node_crypto12 = require("crypto");
28776
28896
  init_metrics();
28777
28897
  createSeededRandom = (seedText) => {
28778
- const digest = (0, import_node_crypto11.createHash)("sha256").update(seedText).digest();
28898
+ const digest = (0, import_node_crypto12.createHash)("sha256").update(seedText).digest();
28779
28899
  let state = digest.readUInt32LE(0) || 1;
28780
28900
  return () => {
28781
28901
  state ^= state << 13;
@@ -29242,13 +29362,13 @@ var init_comparison = __esm({
29242
29362
  });
29243
29363
 
29244
29364
  // src/lib/coreResearch/dataset.ts
29245
- var import_node_crypto12, import_node_fs5, import_node_path17, import_node_readline2, asRecord4, finiteNumber4, normalizeDirection, findStrategySetupIdentity, classifyBreadth, classifyDerivatives, resolveCoreResearchRegime, normalizeCompletedTrade, completedTradeIdentity, positionCycleIdentity, sumBy, weightedPrice, aggregatePositionCycles, compareText, compareTrades, readCoreResearchVariant;
29365
+ var import_node_crypto13, import_node_fs5, import_node_path18, import_node_readline2, asRecord4, finiteNumber4, normalizeDirection, findStrategySetupIdentity, classifyBreadth, classifyDerivatives, resolveCoreResearchRegime, normalizeCompletedTrade, completedTradeIdentity, positionCycleIdentity, sumBy, weightedPrice, aggregatePositionCycles, compareText, compareTrades, readCoreResearchVariant;
29246
29366
  var init_dataset2 = __esm({
29247
29367
  "src/lib/coreResearch/dataset.ts"() {
29248
29368
  "use strict";
29249
- import_node_crypto12 = require("crypto");
29369
+ import_node_crypto13 = require("crypto");
29250
29370
  import_node_fs5 = require("fs");
29251
- import_node_path17 = __toESM(require("path"));
29371
+ import_node_path18 = __toESM(require("path"));
29252
29372
  import_node_readline2 = __toESM(require("readline"));
29253
29373
  asRecord4 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
29254
29374
  finiteNumber4 = (value, field) => {
@@ -29344,7 +29464,7 @@ var init_dataset2 = __esm({
29344
29464
  };
29345
29465
  };
29346
29466
  normalizeCompletedTrade = (params) => {
29347
- const { filePath, fileSha256, lineNumber, row } = params;
29467
+ const { filePath, fileSha256: fileSha2562, lineNumber, row } = params;
29348
29468
  const result = row.tradeResult;
29349
29469
  if (!result) return null;
29350
29470
  const signalTimestamp = finiteNumber4(row.timestamp, "row.timestamp");
@@ -29359,7 +29479,7 @@ var init_dataset2 = __esm({
29359
29479
  return {
29360
29480
  sourceFile: filePath,
29361
29481
  sourceLine: lineNumber,
29362
- sourceSha256: fileSha256,
29482
+ sourceSha256: fileSha2562,
29363
29483
  runId: row.backtestRunId ?? null,
29364
29484
  configId: row.configId?.trim() || "<missing-config-id>",
29365
29485
  signalId,
@@ -29459,9 +29579,9 @@ var init_dataset2 = __esm({
29459
29579
  const seen = /* @__PURE__ */ new Map();
29460
29580
  let duplicateRowsDropped = 0;
29461
29581
  for (const inputPath of variant.files) {
29462
- const filePath = import_node_path17.default.resolve(inputPath);
29582
+ const filePath = import_node_path18.default.resolve(inputPath);
29463
29583
  const input = (0, import_node_fs5.createReadStream)(filePath);
29464
- const hash = (0, import_node_crypto12.createHash)("sha256");
29584
+ const hash = (0, import_node_crypto13.createHash)("sha256");
29465
29585
  input.on("data", (chunk) => hash.update(chunk));
29466
29586
  const lines = import_node_readline2.default.createInterface({ input, crlfDelay: Infinity });
29467
29587
  const fileTrades = [];
@@ -29512,11 +29632,11 @@ var init_dataset2 = __esm({
29512
29632
  trades.push(trade);
29513
29633
  fileTrades.push(trade);
29514
29634
  }
29515
- const fileSha256 = hash.digest("hex");
29516
- for (const trade of fileTrades) trade.sourceSha256 = fileSha256;
29635
+ const fileSha2562 = hash.digest("hex");
29636
+ for (const trade of fileTrades) trade.sourceSha256 = fileSha2562;
29517
29637
  sources.push({
29518
29638
  path: filePath,
29519
- sha256: fileSha256,
29639
+ sha256: fileSha2562,
29520
29640
  rows,
29521
29641
  selectedTrades,
29522
29642
  rowsForDifferentRun,
@@ -29951,19 +30071,19 @@ var init_selection = __esm({
29951
30071
  });
29952
30072
 
29953
30073
  // src/lib/coreResearch/trace.ts
29954
- var import_promises24, import_node_path18, summarizeCoreResearchTrace;
30074
+ var import_promises25, import_node_path19, summarizeCoreResearchTrace;
29955
30075
  var init_trace = __esm({
29956
30076
  "src/lib/coreResearch/trace.ts"() {
29957
30077
  "use strict";
29958
- import_promises24 = __toESM(require("fs/promises"));
29959
- import_node_path18 = __toESM(require("path"));
30078
+ import_promises25 = __toESM(require("fs/promises"));
30079
+ import_node_path19 = __toESM(require("path"));
29960
30080
  summarizeCoreResearchTrace = async (filePaths = []) => {
29961
30081
  const events = /* @__PURE__ */ Object.create(null);
29962
30082
  const skipCounts = /* @__PURE__ */ Object.create(null);
29963
30083
  const exitCodes = /* @__PURE__ */ Object.create(null);
29964
30084
  for (const inputPath of filePaths) {
29965
- const filePath = import_node_path18.default.resolve(inputPath);
29966
- const text = await import_promises24.default.readFile(filePath, "utf8");
30085
+ const filePath = import_node_path19.default.resolve(inputPath);
30086
+ const text = await import_promises25.default.readFile(filePath, "utf8");
29967
30087
  for (const [index, line] of text.split("\n").entries()) {
29968
30088
  if (!line.trim()) continue;
29969
30089
  let event;
@@ -30003,14 +30123,14 @@ var init_trace = __esm({
30003
30123
  });
30004
30124
 
30005
30125
  // src/lib/coreResearch/orchestrator.ts
30006
- var import_promises25, import_node_path19, import_node_child_process6, import_node_crypto13, import_coreResearch, summarizeSupplementalFiles, analyzeCoreResearchPrepared, analyzeCoreResearch, createCoreResearchSpecTemplate, runCommand2, commandValue, commandHas, validateCoreResearchRunCommand, runCoreResearch;
30126
+ var import_promises26, import_node_path20, import_node_child_process6, import_node_crypto14, import_coreResearch, summarizeSupplementalFiles, analyzeCoreResearchPrepared, analyzeCoreResearch, createCoreResearchSpecTemplate, runCommand2, commandValue, commandHas, validateCoreResearchRunCommand, runCoreResearch;
30007
30127
  var init_orchestrator = __esm({
30008
30128
  "src/lib/coreResearch/orchestrator.ts"() {
30009
30129
  "use strict";
30010
- import_promises25 = __toESM(require("fs/promises"));
30011
- import_node_path19 = __toESM(require("path"));
30130
+ import_promises26 = __toESM(require("fs/promises"));
30131
+ import_node_path20 = __toESM(require("path"));
30012
30132
  import_node_child_process6 = require("child_process");
30013
- import_node_crypto13 = require("crypto");
30133
+ import_node_crypto14 = require("crypto");
30014
30134
  import_coreResearch = require("@tradejs/infra/coreResearch");
30015
30135
  init_artifacts();
30016
30136
  init_io();
@@ -30215,7 +30335,7 @@ var init_orchestrator = __esm({
30215
30335
  const primarySourceHashes = Object.fromEntries(
30216
30336
  analyses.flatMap(
30217
30337
  (analysis) => analysis.files.map((file) => [
30218
- import_node_path19.default.relative(paths.researchDir, file.path),
30338
+ import_node_path20.default.relative(paths.researchDir, file.path),
30219
30339
  file.sha256
30220
30340
  ])
30221
30341
  )
@@ -30234,8 +30354,8 @@ var init_orchestrator = __esm({
30234
30354
  const supplementalSourceHashes = Object.fromEntries(
30235
30355
  await Promise.all(
30236
30356
  supplementalSourcePaths.map(async (filePath) => [
30237
- import_node_path19.default.relative(paths.researchDir, import_node_path19.default.resolve(filePath)),
30238
- await sha256File(import_node_path19.default.resolve(filePath))
30357
+ import_node_path20.default.relative(paths.researchDir, import_node_path20.default.resolve(filePath)),
30358
+ await sha256File(import_node_path20.default.resolve(filePath))
30239
30359
  ])
30240
30360
  )
30241
30361
  );
@@ -30299,7 +30419,7 @@ var init_orchestrator = __esm({
30299
30419
  const tradesByVariant = new Map(
30300
30420
  windowed.map((entry) => [entry.variant.id, entry.trades])
30301
30421
  );
30302
- await import_promises25.default.writeFile(
30422
+ await import_promises26.default.writeFile(
30303
30423
  paths.reportPath,
30304
30424
  buildCoreResearchHtml({ spec, result, tradesByVariant }),
30305
30425
  "utf8"
@@ -30312,17 +30432,17 @@ var init_orchestrator = __esm({
30312
30432
  "trades.jsonl": await sha256File(paths.tradesPath),
30313
30433
  "report.html": await sha256File(paths.reportPath)
30314
30434
  };
30315
- const resolvedRunsPath = import_node_path19.default.join(paths.researchDir, "resolved-runs.json");
30435
+ const resolvedRunsPath = import_node_path20.default.join(paths.researchDir, "resolved-runs.json");
30316
30436
  try {
30317
30437
  artifactHashes["resolved-runs.json"] = await sha256File(resolvedRunsPath);
30318
30438
  } catch (error) {
30319
30439
  if (error.code !== "ENOENT") throw error;
30320
30440
  }
30321
30441
  try {
30322
- for (const name of await import_promises25.default.readdir(paths.runLogDir)) {
30442
+ for (const name of await import_promises26.default.readdir(paths.runLogDir)) {
30323
30443
  if (!name.endsWith(".log")) continue;
30324
30444
  artifactHashes[`runs/${name}`] = await sha256File(
30325
- import_node_path19.default.join(paths.runLogDir, name)
30445
+ import_node_path20.default.join(paths.runLogDir, name)
30326
30446
  );
30327
30447
  }
30328
30448
  } catch (error) {
@@ -30379,9 +30499,9 @@ var init_orchestrator = __esm({
30379
30499
  }
30380
30500
  };
30381
30501
  createCoreResearchSpecTemplate = (params) => {
30382
- const rootDir = import_node_path19.default.relative(
30383
- import_node_path19.default.resolve(params.projectRoot),
30384
- import_node_path19.default.join(import_node_path19.default.resolve(params.projectRoot), "data", "research", "core")
30502
+ const rootDir = import_node_path20.default.relative(
30503
+ import_node_path20.default.resolve(params.projectRoot),
30504
+ import_node_path20.default.join(import_node_path20.default.resolve(params.projectRoot), "data", "research", "core")
30385
30505
  ).replace(/\\/g, "/");
30386
30506
  const lineage = (() => {
30387
30507
  try {
@@ -30412,7 +30532,7 @@ var init_orchestrator = __esm({
30412
30532
  gitSha,
30413
30533
  ...sourceRepository ? { sourceRepository } : {},
30414
30534
  ...dirtyDiff ? {
30415
- dirtyDiffSha256: (0, import_node_crypto13.createHash)("sha256").update(dirtyDiff).digest("hex")
30535
+ dirtyDiffSha256: (0, import_node_crypto14.createHash)("sha256").update(dirtyDiff).digest("hex")
30416
30536
  } : {}
30417
30537
  };
30418
30538
  } catch {
@@ -30519,7 +30639,7 @@ var init_orchestrator = __esm({
30519
30639
  };
30520
30640
  runCommand2 = async (params) => {
30521
30641
  if (!params.command.length) throw new Error("Cannot run an empty command");
30522
- await import_promises25.default.mkdir(import_node_path19.default.dirname(params.logPath), { recursive: true });
30642
+ await import_promises26.default.mkdir(import_node_path20.default.dirname(params.logPath), { recursive: true });
30523
30643
  const chunks = [];
30524
30644
  const child = (0, import_node_child_process6.spawn)(params.command[0], params.command.slice(1), {
30525
30645
  cwd: params.cwd,
@@ -30539,7 +30659,7 @@ var init_orchestrator = __esm({
30539
30659
  child.once("close", (code) => resolve(code ?? 1));
30540
30660
  });
30541
30661
  const output = chunks.join("");
30542
- await import_promises25.default.writeFile(params.logPath, output, "utf8");
30662
+ await import_promises26.default.writeFile(params.logPath, output, "utf8");
30543
30663
  if (exitCode !== 0) {
30544
30664
  throw new Error(
30545
30665
  `Command failed with exit ${exitCode}: ${params.command.join(" ")}`
@@ -30593,7 +30713,7 @@ var init_orchestrator = __esm({
30593
30713
  };
30594
30714
  runCoreResearch = async (params) => {
30595
30715
  const { spec } = params;
30596
- const cwd = import_node_path19.default.resolve(params.cwd ?? process.cwd());
30716
+ const cwd = import_node_path20.default.resolve(params.cwd ?? process.cwd());
30597
30717
  const prepared = await prepareCoreResearch(spec);
30598
30718
  const resolvedVariants = [];
30599
30719
  for (const variant of spec.variants) {
@@ -30611,7 +30731,7 @@ var init_orchestrator = __esm({
30611
30731
  artifactHashes: { variant: sha256Json(variant) }
30612
30732
  });
30613
30733
  let runId = "";
30614
- const backtestLogPath = import_node_path19.default.join(
30734
+ const backtestLogPath = import_node_path20.default.join(
30615
30735
  prepared.paths.runLogDir,
30616
30736
  `${variant.id}-backtest.log`
30617
30737
  );
@@ -30627,7 +30747,7 @@ var init_orchestrator = __esm({
30627
30747
  env: {
30628
30748
  PROJECT_CWD: cwd,
30629
30749
  ...params.sourceRepositoryRoot ? {
30630
- [SOURCE_REPOSITORY_ROOT_ENV]: import_node_path19.default.resolve(
30750
+ [SOURCE_REPOSITORY_ROOT_ENV]: import_node_path20.default.resolve(
30631
30751
  params.sourceRepositoryRoot
30632
30752
  )
30633
30753
  } : {}
@@ -30642,12 +30762,12 @@ var init_orchestrator = __esm({
30642
30762
  if (!runId) {
30643
30763
  throw new Error(`Backtest for ${variant.id} did not report a run id`);
30644
30764
  }
30645
- const exportLogPath = import_node_path19.default.join(
30765
+ const exportLogPath = import_node_path20.default.join(
30646
30766
  prepared.paths.runLogDir,
30647
30767
  `${variant.id}-export.log`
30648
30768
  );
30649
30769
  const exportParts = [];
30650
- const cliPath = import_node_path19.default.resolve(process.argv[1]);
30770
+ const cliPath = import_node_path20.default.resolve(process.argv[1]);
30651
30771
  await runCommand2({
30652
30772
  command: [
30653
30773
  process.execPath,
@@ -30667,14 +30787,14 @@ var init_orchestrator = __esm({
30667
30787
  env: {
30668
30788
  PROJECT_CWD: cwd,
30669
30789
  ...params.sourceRepositoryRoot ? {
30670
- [SOURCE_REPOSITORY_ROOT_ENV]: import_node_path19.default.resolve(
30790
+ [SOURCE_REPOSITORY_ROOT_ENV]: import_node_path20.default.resolve(
30671
30791
  params.sourceRepositoryRoot
30672
30792
  )
30673
30793
  } : {}
30674
30794
  },
30675
30795
  onLine: (line) => {
30676
30796
  const match = line.match(/^part\d+:\s+(.+)$/);
30677
- if (match) exportParts.push(import_node_path19.default.resolve(cwd, match[1].trim()));
30797
+ if (match) exportParts.push(import_node_path20.default.resolve(cwd, match[1].trim()));
30678
30798
  }
30679
30799
  });
30680
30800
  if (!exportParts.length) {
@@ -30685,7 +30805,7 @@ var init_orchestrator = __esm({
30685
30805
  const traceFiles = await (0, import_coreResearch.listCoreResearchTraceFiles)({
30686
30806
  strategyName: spec.strategy,
30687
30807
  runId,
30688
- outDir: import_node_path19.default.resolve(cwd, "data/research/core/trace")
30808
+ outDir: import_node_path20.default.resolve(cwd, "data/research/core/trace")
30689
30809
  });
30690
30810
  resolvedVariants.push({
30691
30811
  ...variant,
@@ -30705,7 +30825,7 @@ var init_orchestrator = __esm({
30705
30825
  ...Object.fromEntries(
30706
30826
  await Promise.all(
30707
30827
  exportParts.map(async (filePath) => [
30708
- import_node_path19.default.basename(filePath),
30828
+ import_node_path20.default.basename(filePath),
30709
30829
  await sha256File(filePath)
30710
30830
  ])
30711
30831
  )
@@ -30724,7 +30844,7 @@ var init_orchestrator = __esm({
30724
30844
  }
30725
30845
  }
30726
30846
  await writeJsonAtomic(
30727
- import_node_path19.default.join(prepared.paths.researchDir, "resolved-runs.json"),
30847
+ import_node_path20.default.join(prepared.paths.researchDir, "resolved-runs.json"),
30728
30848
  {
30729
30849
  schema: "tradejs-core-research-resolved-runs/v1",
30730
30850
  researchId: spec.researchId,
@@ -30744,12 +30864,12 @@ var coreResearch_exports = {};
30744
30864
  __export(coreResearch_exports, {
30745
30865
  main: () => main34
30746
30866
  });
30747
- var import_promises26, import_node_path20, import_chalk41, valueAfter, required, parseTimestamp, readSymbols, printUsage, main34;
30867
+ var import_promises27, import_node_path21, import_chalk41, valueAfter, required, parseTimestamp, readSymbols, printUsage, main34;
30748
30868
  var init_coreResearch = __esm({
30749
30869
  "src/scripts/coreResearch.ts"() {
30750
30870
  "use strict";
30751
- import_promises26 = __toESM(require("fs/promises"));
30752
- import_node_path20 = __toESM(require("path"));
30871
+ import_promises27 = __toESM(require("fs/promises"));
30872
+ import_node_path21 = __toESM(require("path"));
30753
30873
  import_chalk41 = __toESM(require("chalk"));
30754
30874
  init_io();
30755
30875
  init_orchestrator();
@@ -30773,7 +30893,7 @@ var init_coreResearch = __esm({
30773
30893
  const symbolsFile = valueAfter(argv2, "--symbolsFile");
30774
30894
  if (symbolsFile) {
30775
30895
  const parsed = JSON.parse(
30776
- await import_promises26.default.readFile(import_node_path20.default.resolve(projectRoot18, symbolsFile), "utf8")
30896
+ await import_promises27.default.readFile(import_node_path21.default.resolve(projectRoot18, symbolsFile), "utf8")
30777
30897
  );
30778
30898
  if (!Array.isArray(parsed) || parsed.some((symbol) => typeof symbol !== "string")) {
30779
30899
  throw new Error("--symbolsFile must contain a JSON string array");
@@ -30804,14 +30924,14 @@ The run command executes only variants with an explicit command[] in the preregi
30804
30924
  return;
30805
30925
  }
30806
30926
  if (command === "index") {
30807
- const rootDir = import_node_path20.default.resolve(
30927
+ const rootDir = import_node_path21.default.resolve(
30808
30928
  roots.projectRoot,
30809
30929
  required(valueAfter(argv2, "--root"), "--root")
30810
30930
  );
30811
30931
  const index = await writeCoreResearchStageIndex(rootDir);
30812
30932
  console.log(
30813
30933
  import_chalk41.default.green(
30814
- `Core research index: ${import_node_path20.default.join(rootDir, "index.json")} (${index.families.length} families)`
30934
+ `Core research index: ${import_node_path21.default.join(rootDir, "index.json")} (${index.families.length} families)`
30815
30935
  )
30816
30936
  );
30817
30937
  return;
@@ -30820,7 +30940,7 @@ The run command executes only variants with an explicit command[] in the preregi
30820
30940
  projectRoot: roots.projectRoot
30821
30941
  });
30822
30942
  if (command === "init") {
30823
- const outputPath = import_node_path20.default.resolve(
30943
+ const outputPath = import_node_path21.default.resolve(
30824
30944
  roots.projectRoot,
30825
30945
  required(valueAfter(argv2, "--out"), "--out")
30826
30946
  );
@@ -30844,7 +30964,7 @@ The run command executes only variants with an explicit command[] in the preregi
30844
30964
  );
30845
30965
  return;
30846
30966
  }
30847
- const specPath = import_node_path20.default.resolve(
30967
+ const specPath = import_node_path21.default.resolve(
30848
30968
  roots.projectRoot,
30849
30969
  required(valueAfter(argv2, "--spec"), "--spec")
30850
30970
  );
@@ -31498,12 +31618,12 @@ __export(replayRuntimeEvidence_exports, {
31498
31618
  replayRuntimeEvidence: () => replayRuntimeEvidence,
31499
31619
  summarizeReplayComparison: () => summarizeReplayComparison
31500
31620
  });
31501
- var import_promises27, import_node_path21, import_args27, import_chalk43, import_redis19, toEpochMs2, resolveWindow, parseStrategyFilter, asRecord5, asArray2, sum, groupCount, compactMatched, resolveItemStrategy, summarizeReplayComparison, loadReplayResult, getReplayStrategies, loadRuntimePayload, replayRuntimeEvidence, main36;
31621
+ var import_promises28, import_node_path22, import_args27, import_chalk43, import_redis19, toEpochMs2, resolveWindow, parseStrategyFilter, asRecord5, asArray2, sum, groupCount, compactMatched, resolveItemStrategy, summarizeReplayComparison, loadReplayResult, getReplayStrategies, loadRuntimePayload, replayRuntimeEvidence, main36;
31502
31622
  var init_replayRuntimeEvidence = __esm({
31503
31623
  "src/scripts/replayRuntimeEvidence.ts"() {
31504
31624
  "use strict";
31505
- import_promises27 = __toESM(require("fs/promises"));
31506
- import_node_path21 = __toESM(require("path"));
31625
+ import_promises28 = __toESM(require("fs/promises"));
31626
+ import_node_path22 = __toESM(require("path"));
31507
31627
  import_args27 = __toESM(require("args"));
31508
31628
  import_chalk43 = __toESM(require("chalk"));
31509
31629
  import_redis19 = require("@tradejs/infra/redis");
@@ -31762,10 +31882,10 @@ var init_replayRuntimeEvidence = __esm({
31762
31882
  runtimeEvidenceFile,
31763
31883
  projectRoot: projectRoot18
31764
31884
  }) => {
31765
- const runtimeEvidencePath = typeof runtimeEvidenceFile === "string" && runtimeEvidenceFile.trim() ? import_node_path21.default.resolve(projectRoot18, runtimeEvidenceFile.trim()) : null;
31885
+ const runtimeEvidencePath = typeof runtimeEvidenceFile === "string" && runtimeEvidenceFile.trim() ? import_node_path22.default.resolve(projectRoot18, runtimeEvidenceFile.trim()) : null;
31766
31886
  if (runtimeEvidencePath) {
31767
31887
  const artifact = JSON.parse(
31768
- await import_promises27.default.readFile(runtimeEvidencePath, "utf8")
31888
+ await import_promises28.default.readFile(runtimeEvidencePath, "utf8")
31769
31889
  );
31770
31890
  return {
31771
31891
  source: "file",
@@ -31851,9 +31971,9 @@ var init_replayRuntimeEvidence = __esm({
31851
31971
  },
31852
31972
  runtime: runtime.payload
31853
31973
  };
31854
- const outPath = import_node_path21.default.resolve(projectRoot18, String(flags35.out));
31855
- await import_promises27.default.mkdir(import_node_path21.default.dirname(outPath), { recursive: true });
31856
- await import_promises27.default.writeFile(outPath, `${JSON.stringify(artifact, null, 2)}
31974
+ const outPath = import_node_path22.default.resolve(projectRoot18, String(flags35.out));
31975
+ await import_promises28.default.mkdir(import_node_path22.default.dirname(outPath), { recursive: true });
31976
+ await import_promises28.default.writeFile(outPath, `${JSON.stringify(artifact, null, 2)}
31857
31977
  `, "utf8");
31858
31978
  console.log(import_chalk43.default.green(`Wrote ${outPath}`));
31859
31979
  console.log(
@@ -31875,15 +31995,6 @@ var init_replayRuntimeEvidence = __esm({
31875
31995
  }
31876
31996
  });
31877
31997
 
31878
- // src/lib/runtimeEvidenceArtifacts.ts
31879
- var runtimeEvidenceArtifacts_exports = {};
31880
- var init_runtimeEvidenceArtifacts = __esm({
31881
- "src/lib/runtimeEvidenceArtifacts.ts"() {
31882
- "use strict";
31883
- __reExport(runtimeEvidenceArtifacts_exports, require("@tradejs/node/diagnostics"));
31884
- }
31885
- });
31886
-
31887
31998
  // src/lib/runtimeEvidenceProducer.ts
31888
31999
  var runtimeEvidenceProducer_exports = {};
31889
32000
  var init_runtimeEvidenceProducer = __esm({
@@ -31903,13 +32014,13 @@ var init_runtimeFeedbackArtifacts = __esm({
31903
32014
  });
31904
32015
 
31905
32016
  // src/lib/runtimeFeedbackReplay.ts
31906
- var import_node_child_process7, import_promises28, import_node_path22, REQUIRED_ENV, FORBIDDEN_SECRET_ENV, unsafeRedisHosts, safeSegment, assertRuntimeFeedbackReplaySafety, buildRuntimeFeedbackReplayCommands, runLoggedCommand, runRuntimeFeedbackReplay;
32017
+ var import_node_child_process7, import_promises29, import_node_path23, REQUIRED_ENV, FORBIDDEN_SECRET_ENV, unsafeRedisHosts, safeSegment, assertRuntimeFeedbackReplaySafety, buildRuntimeFeedbackReplayCommands, runLoggedCommand, runRuntimeFeedbackReplay;
31907
32018
  var init_runtimeFeedbackReplay = __esm({
31908
32019
  "src/lib/runtimeFeedbackReplay.ts"() {
31909
32020
  "use strict";
31910
32021
  import_node_child_process7 = require("child_process");
31911
- import_promises28 = __toESM(require("fs/promises"));
31912
- import_node_path22 = __toESM(require("path"));
32022
+ import_promises29 = __toESM(require("fs/promises"));
32023
+ import_node_path23 = __toESM(require("path"));
31913
32024
  init_runtimeEvidenceDeployment();
31914
32025
  init_runtimeEvidenceArtifacts();
31915
32026
  init_runtimeEvidenceProducer();
@@ -32096,9 +32207,9 @@ $ ${[executable, ...command].join(" ")}
32096
32207
  throw new Error("Cannot resolve the TradeJS CLI executable path");
32097
32208
  }
32098
32209
  const runtimeEvidenceBundle = await (0, runtimeEvidenceArtifacts_exports.verifyRuntimeEvidenceBundle)(
32099
- import_node_path22.default.dirname(runtimeEvidencePath)
32210
+ import_node_path23.default.dirname(runtimeEvidencePath)
32100
32211
  );
32101
- if (import_node_path22.default.resolve(runtimeEvidenceBundle.payloadPath) !== runtimeEvidencePath) {
32212
+ if (import_node_path23.default.resolve(runtimeEvidenceBundle.payloadPath) !== runtimeEvidencePath) {
32102
32213
  throw new Error(
32103
32214
  `Runtime evidence must be the verified bundle payload: ${runtimeEvidenceBundle.payloadPath}`
32104
32215
  );
@@ -32125,16 +32236,16 @@ $ ${[executable, ...command].join(" ")}
32125
32236
  if (!intervals.size) {
32126
32237
  throw new Error("Runtime feedback replay requires an active interval");
32127
32238
  }
32128
- await import_promises28.default.mkdir(outDir, { recursive: true });
32129
- const existing = await import_promises28.default.readdir(outDir);
32239
+ await import_promises29.default.mkdir(outDir, { recursive: true });
32240
+ const existing = await import_promises29.default.readdir(outDir);
32130
32241
  if (existing.length) {
32131
32242
  throw new Error(
32132
32243
  `Runtime feedback output directory must be empty: ${outDir}`
32133
32244
  );
32134
32245
  }
32135
- const replayEvidencePath = import_node_path22.default.join(outDir, runtimeFeedbackArtifacts_exports.RUNTIME_FEEDBACK_REPLAY_FILE);
32136
- const logHandle = await import_promises28.default.open(
32137
- import_node_path22.default.join(outDir, runtimeFeedbackArtifacts_exports.RUNTIME_FEEDBACK_LOG_FILE),
32246
+ const replayEvidencePath = import_node_path23.default.join(outDir, runtimeFeedbackArtifacts_exports.RUNTIME_FEEDBACK_REPLAY_FILE);
32247
+ const logHandle = await import_promises29.default.open(
32248
+ import_node_path23.default.join(outDir, runtimeFeedbackArtifacts_exports.RUNTIME_FEEDBACK_LOG_FILE),
32138
32249
  "wx"
32139
32250
  );
32140
32251
  const commands = buildRuntimeFeedbackReplayCommands({
@@ -32176,11 +32287,11 @@ __export(runtimeFeedbackReplay_exports, {
32176
32287
  main: () => main37,
32177
32288
  runtimeFeedbackReplay: () => runtimeFeedbackReplay
32178
32289
  });
32179
- var import_node_path23, import_args28, import_chalk44, flags25, projectRoot9, runtimeFeedbackReplay, main37;
32290
+ var import_node_path24, import_args28, import_chalk44, flags25, projectRoot9, runtimeFeedbackReplay, main37;
32180
32291
  var init_runtimeFeedbackReplay2 = __esm({
32181
32292
  "src/scripts/runtimeFeedbackReplay.ts"() {
32182
32293
  "use strict";
32183
- import_node_path23 = __toESM(require("path"));
32294
+ import_node_path24 = __toESM(require("path"));
32184
32295
  import_args28 = __toESM(require("args"));
32185
32296
  import_chalk44 = __toESM(require("chalk"));
32186
32297
  init_runtimeFeedbackReplay();
@@ -32198,8 +32309,8 @@ var init_runtimeFeedbackReplay2 = __esm({
32198
32309
  );
32199
32310
  }
32200
32311
  const verified = await runRuntimeFeedbackReplay({
32201
- runtimeEvidencePath: import_node_path23.default.resolve(projectRoot9, runtimeEvidence2),
32202
- outDir: import_node_path23.default.resolve(projectRoot9, outDir),
32312
+ runtimeEvidencePath: import_node_path24.default.resolve(projectRoot9, runtimeEvidence2),
32313
+ outDir: import_node_path24.default.resolve(projectRoot9, outDir),
32203
32314
  runId: String(flags25.runId ?? "").trim() || void 0,
32204
32315
  projectRoot: projectRoot9
32205
32316
  });
@@ -32357,11 +32468,11 @@ __export(runtimeFeedbackNotify_exports, {
32357
32468
  main: () => main38,
32358
32469
  runtimeFeedbackNotify: () => runtimeFeedbackNotify
32359
32470
  });
32360
- var import_node_path24, import_args29, import_chalk45, flags26, projectRoot10, runtimeFeedbackNotify, main38;
32471
+ var import_node_path25, import_args29, import_chalk45, flags26, projectRoot10, runtimeFeedbackNotify, main38;
32361
32472
  var init_runtimeFeedbackNotify = __esm({
32362
32473
  "src/scripts/runtimeFeedbackNotify.ts"() {
32363
32474
  "use strict";
32364
- import_node_path24 = __toESM(require("path"));
32475
+ import_node_path25 = __toESM(require("path"));
32365
32476
  import_args29 = __toESM(require("args"));
32366
32477
  import_chalk45 = __toESM(require("chalk"));
32367
32478
  init_runtimeFeedbackNotification();
@@ -32375,7 +32486,7 @@ var init_runtimeFeedbackNotify = __esm({
32375
32486
  if (!bundle) {
32376
32487
  throw new Error("Provide --bundle for runtime feedback notification.");
32377
32488
  }
32378
- const bundleDir = import_node_path24.default.resolve(projectRoot10, bundle);
32489
+ const bundleDir = import_node_path25.default.resolve(projectRoot10, bundle);
32379
32490
  if (flags26.dryRun) {
32380
32491
  const verified = await (0, runtimeFeedbackArtifacts_exports.verifyRuntimeFeedbackReplayBundle)(bundleDir);
32381
32492
  console.log(buildRuntimeFeedbackTelegramMessage(verified.replayEvidence));
@@ -32391,13 +32502,13 @@ var init_runtimeFeedbackNotify = __esm({
32391
32502
  });
32392
32503
 
32393
32504
  // src/lib/runtimeEvidenceSync.ts
32394
- var import_node_child_process8, import_promises29, import_node_path25, import_node_util, execFileAsync, isExistingDestinationError, safeSegment2, withTrailingSlash, dateParts, buildRuntimeEvidenceRsyncArgs, receiptPath, compareBundles, listPendingRuntimeEvidenceBundles, markRuntimeEvidenceBundleProcessed, syncRuntimeEvidenceBundles;
32505
+ var import_node_child_process8, import_promises30, import_node_path26, import_node_util, execFileAsync, isExistingDestinationError, safeSegment2, withTrailingSlash, dateParts, buildRuntimeEvidenceRsyncArgs, receiptPath, compareBundles, listPendingRuntimeEvidenceBundles, markRuntimeEvidenceBundleProcessed, syncRuntimeEvidenceBundles;
32395
32506
  var init_runtimeEvidenceSync = __esm({
32396
32507
  "src/lib/runtimeEvidenceSync.ts"() {
32397
32508
  "use strict";
32398
32509
  import_node_child_process8 = require("child_process");
32399
- import_promises29 = __toESM(require("fs/promises"));
32400
- import_node_path25 = __toESM(require("path"));
32510
+ import_promises30 = __toESM(require("fs/promises"));
32511
+ import_node_path26 = __toESM(require("path"));
32401
32512
  import_node_util = require("util");
32402
32513
  init_runtimeEvidenceArtifacts();
32403
32514
  init_runtimeEvidenceDeployment();
@@ -32431,15 +32542,15 @@ var init_runtimeEvidenceSync = __esm({
32431
32542
  withTrailingSlash(source),
32432
32543
  withTrailingSlash(destination)
32433
32544
  ];
32434
- receiptPath = (receiptsRoot, artifactId) => import_node_path25.default.join(receiptsRoot, `${safeSegment2(artifactId, "artifact")}.json`);
32545
+ receiptPath = (receiptsRoot, artifactId) => import_node_path26.default.join(receiptsRoot, `${safeSegment2(artifactId, "artifact")}.json`);
32435
32546
  compareBundles = (left, right) => left.manifest.window.endTime - right.manifest.window.endTime || left.manifest.createdAt - right.manifest.createdAt;
32436
32547
  listPendingRuntimeEvidenceBundles = async ({
32437
32548
  evidenceRoot,
32438
32549
  deploymentId
32439
32550
  }) => {
32440
32551
  const safeDeploymentId = safeSegment2(deploymentId, "production");
32441
- const artifactsRoot = import_node_path25.default.join(evidenceRoot, "artifacts", safeDeploymentId);
32442
- const receiptsRoot = import_node_path25.default.join(evidenceRoot, "receipts", safeDeploymentId);
32552
+ const artifactsRoot = import_node_path26.default.join(evidenceRoot, "artifacts", safeDeploymentId);
32553
+ const receiptsRoot = import_node_path26.default.join(evidenceRoot, "receipts", safeDeploymentId);
32443
32554
  const bundles = await (0, runtimeEvidenceArtifacts_exports.discoverRuntimeEvidenceBundles)(artifactsRoot);
32444
32555
  const pending = [];
32445
32556
  for (const bundleDir of bundles) {
@@ -32447,7 +32558,7 @@ var init_runtimeEvidenceSync = __esm({
32447
32558
  if (verified.manifest.deploymentId !== safeDeploymentId) continue;
32448
32559
  (0, runtimeEvidenceDeployment_exports.assertCurrentRuntimeEvidenceArtifact)(verified.artifact);
32449
32560
  try {
32450
- await import_promises29.default.access(receiptPath(receiptsRoot, verified.manifest.artifactId));
32561
+ await import_promises30.default.access(receiptPath(receiptsRoot, verified.manifest.artifactId));
32451
32562
  continue;
32452
32563
  } catch (error) {
32453
32564
  if (error.code !== "ENOENT") throw error;
@@ -32470,7 +32581,7 @@ var init_runtimeEvidenceSync = __esm({
32470
32581
  `Artifact deployment mismatch: expected ${safeDeploymentId}, received ${verified.manifest.deploymentId}`
32471
32582
  );
32472
32583
  }
32473
- const receiptsRoot = import_node_path25.default.join(evidenceRoot, "receipts", safeDeploymentId);
32584
+ const receiptsRoot = import_node_path26.default.join(evidenceRoot, "receipts", safeDeploymentId);
32474
32585
  const finalPath = receiptPath(receiptsRoot, verified.manifest.artifactId);
32475
32586
  const temporaryPath = `${finalPath}.tmp-${process.pid}`;
32476
32587
  const receipt = {
@@ -32484,14 +32595,14 @@ var init_runtimeEvidenceSync = __esm({
32484
32595
  replayEvidenceSha256: runtimeFeedback.replayEvidenceSha256
32485
32596
  } : {}
32486
32597
  };
32487
- await import_promises29.default.mkdir(receiptsRoot, { recursive: true });
32488
- await import_promises29.default.writeFile(
32598
+ await import_promises30.default.mkdir(receiptsRoot, { recursive: true });
32599
+ await import_promises30.default.writeFile(
32489
32600
  temporaryPath,
32490
32601
  `${JSON.stringify(receipt, null, 2)}
32491
32602
  `,
32492
32603
  "utf8"
32493
32604
  );
32494
- await import_promises29.default.rename(temporaryPath, finalPath);
32605
+ await import_promises30.default.rename(temporaryPath, finalPath);
32495
32606
  return finalPath;
32496
32607
  };
32497
32608
  syncRuntimeEvidenceBundles = async ({
@@ -32506,11 +32617,11 @@ var init_runtimeEvidenceSync = __esm({
32506
32617
  }
32507
32618
  }) => {
32508
32619
  const safeDeploymentId = safeSegment2(deploymentId, "production");
32509
- const inboxRoot = import_node_path25.default.join(evidenceRoot, "inbox", safeDeploymentId);
32510
- const artifactsRoot = import_node_path25.default.join(evidenceRoot, "artifacts", safeDeploymentId);
32620
+ const inboxRoot = import_node_path26.default.join(evidenceRoot, "inbox", safeDeploymentId);
32621
+ const artifactsRoot = import_node_path26.default.join(evidenceRoot, "artifacts", safeDeploymentId);
32511
32622
  await Promise.all([
32512
- import_promises29.default.mkdir(inboxRoot, { recursive: true }),
32513
- import_promises29.default.mkdir(artifactsRoot, { recursive: true })
32623
+ import_promises30.default.mkdir(inboxRoot, { recursive: true }),
32624
+ import_promises30.default.mkdir(artifactsRoot, { recursive: true })
32514
32625
  ]);
32515
32626
  const rsyncArgs = buildRuntimeEvidenceRsyncArgs({
32516
32627
  source,
@@ -32527,14 +32638,14 @@ var init_runtimeEvidenceSync = __esm({
32527
32638
  );
32528
32639
  }
32529
32640
  (0, runtimeEvidenceDeployment_exports.assertCurrentRuntimeEvidenceArtifact)(verified.artifact);
32530
- const destinationDir = import_node_path25.default.join(
32641
+ const destinationDir = import_node_path26.default.join(
32531
32642
  artifactsRoot,
32532
32643
  ...dateParts(verified.manifest.window.endTime),
32533
32644
  safeSegment2(verified.manifest.artifactId, "artifact")
32534
32645
  );
32535
- await import_promises29.default.mkdir(import_node_path25.default.dirname(destinationDir), { recursive: true });
32646
+ await import_promises30.default.mkdir(import_node_path26.default.dirname(destinationDir), { recursive: true });
32536
32647
  try {
32537
- await import_promises29.default.rename(bundleDir, destinationDir);
32648
+ await import_promises30.default.rename(bundleDir, destinationDir);
32538
32649
  } catch (error) {
32539
32650
  if (!isExistingDestinationError(error)) throw error;
32540
32651
  const existing = await (0, runtimeEvidenceArtifacts_exports.verifyRuntimeEvidenceBundle)(destinationDir);
@@ -32543,7 +32654,7 @@ var init_runtimeEvidenceSync = __esm({
32543
32654
  `Conflicting runtime evidence artifact ${verified.manifest.artifactId}`
32544
32655
  );
32545
32656
  }
32546
- await import_promises29.default.rm(bundleDir, { recursive: true, force: true });
32657
+ await import_promises30.default.rm(bundleDir, { recursive: true, force: true });
32547
32658
  }
32548
32659
  received.push(await (0, runtimeEvidenceArtifacts_exports.verifyRuntimeEvidenceBundle)(destinationDir));
32549
32660
  }
@@ -32563,13 +32674,13 @@ var init_runtimeEvidenceSync = __esm({
32563
32674
  });
32564
32675
 
32565
32676
  // src/lib/runtimeFeedbackSync.ts
32566
- var import_node_child_process9, import_promises30, import_node_path26, import_node_util2, execFileAsync2, isExistingDestinationError2, safeSegment3, dateParts2, syncRuntimeFeedbackReplayBundles;
32677
+ var import_node_child_process9, import_promises31, import_node_path27, import_node_util2, execFileAsync2, isExistingDestinationError2, safeSegment3, dateParts2, syncRuntimeFeedbackReplayBundles;
32567
32678
  var init_runtimeFeedbackSync = __esm({
32568
32679
  "src/lib/runtimeFeedbackSync.ts"() {
32569
32680
  "use strict";
32570
32681
  import_node_child_process9 = require("child_process");
32571
- import_promises30 = __toESM(require("fs/promises"));
32572
- import_node_path26 = __toESM(require("path"));
32682
+ import_promises31 = __toESM(require("fs/promises"));
32683
+ import_node_path27 = __toESM(require("path"));
32573
32684
  import_node_util2 = require("util");
32574
32685
  init_runtimeFeedbackArtifacts();
32575
32686
  init_runtimeEvidenceSync();
@@ -32602,11 +32713,11 @@ var init_runtimeFeedbackSync = __esm({
32602
32713
  }
32603
32714
  }) => {
32604
32715
  const safeDeploymentId = safeSegment3(deploymentId, "production");
32605
- const inboxRoot = import_node_path26.default.join(feedbackRoot, "inbox", safeDeploymentId);
32606
- const artifactsRoot = import_node_path26.default.join(feedbackRoot, "artifacts", safeDeploymentId);
32716
+ const inboxRoot = import_node_path27.default.join(feedbackRoot, "inbox", safeDeploymentId);
32717
+ const artifactsRoot = import_node_path27.default.join(feedbackRoot, "artifacts", safeDeploymentId);
32607
32718
  await Promise.all([
32608
- import_promises30.default.mkdir(inboxRoot, { recursive: true }),
32609
- import_promises30.default.mkdir(artifactsRoot, { recursive: true })
32719
+ import_promises31.default.mkdir(inboxRoot, { recursive: true }),
32720
+ import_promises31.default.mkdir(artifactsRoot, { recursive: true })
32610
32721
  ]);
32611
32722
  const rsyncArgs = buildRuntimeEvidenceRsyncArgs({
32612
32723
  source,
@@ -32622,15 +32733,15 @@ var init_runtimeFeedbackSync = __esm({
32622
32733
  `Runtime feedback deployment mismatch: expected ${safeDeploymentId}, received ${verified.manifest.deploymentId}`
32623
32734
  );
32624
32735
  }
32625
- const destinationDir = import_node_path26.default.join(
32736
+ const destinationDir = import_node_path27.default.join(
32626
32737
  artifactsRoot,
32627
32738
  ...dateParts2(verified.manifest.window.endTime),
32628
32739
  safeSegment3(verified.manifest.runtimeEvidence.artifactId, "artifact"),
32629
32740
  safeSegment3(verified.manifest.runId, "run")
32630
32741
  );
32631
- await import_promises30.default.mkdir(import_node_path26.default.dirname(destinationDir), { recursive: true });
32742
+ await import_promises31.default.mkdir(import_node_path27.default.dirname(destinationDir), { recursive: true });
32632
32743
  try {
32633
- await import_promises30.default.rename(bundleDir, destinationDir);
32744
+ await import_promises31.default.rename(bundleDir, destinationDir);
32634
32745
  } catch (error) {
32635
32746
  if (!isExistingDestinationError2(error)) throw error;
32636
32747
  const existing = await (0, runtimeFeedbackArtifacts_exports.verifyRuntimeFeedbackReplayBundle)(destinationDir);
@@ -32639,7 +32750,7 @@ var init_runtimeFeedbackSync = __esm({
32639
32750
  `Conflicting runtime feedback replay ${verified.manifest.artifactId}`
32640
32751
  );
32641
32752
  }
32642
- await import_promises30.default.rm(bundleDir, { recursive: true, force: true });
32753
+ await import_promises31.default.rm(bundleDir, { recursive: true, force: true });
32643
32754
  }
32644
32755
  received.push(await (0, runtimeFeedbackArtifacts_exports.verifyRuntimeFeedbackReplayBundle)(destinationDir));
32645
32756
  }
@@ -32659,11 +32770,11 @@ __export(runtimeFeedbackSync_exports, {
32659
32770
  main: () => main39,
32660
32771
  runtimeFeedbackSync: () => runtimeFeedbackSync
32661
32772
  });
32662
- var import_node_path27, import_args30, import_chalk46, flags27, projectRoot11, runtimeFeedbackSync, main39;
32773
+ var import_node_path28, import_args30, import_chalk46, flags27, projectRoot11, runtimeFeedbackSync, main39;
32663
32774
  var init_runtimeFeedbackSync2 = __esm({
32664
32775
  "src/scripts/runtimeFeedbackSync.ts"() {
32665
32776
  "use strict";
32666
- import_node_path27 = __toESM(require("path"));
32777
+ import_node_path28 = __toESM(require("path"));
32667
32778
  import_args30 = __toESM(require("args"));
32668
32779
  import_chalk46 = __toESM(require("chalk"));
32669
32780
  init_runtimeFeedbackSync();
@@ -32691,7 +32802,7 @@ var init_runtimeFeedbackSync2 = __esm({
32691
32802
  "Provide --source or RUNTIME_FEEDBACK_RSYNC_SOURCE for runtime feedback sync."
32692
32803
  );
32693
32804
  }
32694
- const feedbackRoot = import_node_path27.default.resolve(projectRoot11, String(flags27.dir));
32805
+ const feedbackRoot = import_node_path28.default.resolve(projectRoot11, String(flags27.dir));
32695
32806
  const result = await syncRuntimeFeedbackReplayBundles({
32696
32807
  source,
32697
32808
  feedbackRoot,
@@ -32723,13 +32834,13 @@ var init_runtimeFeedbackSync2 = __esm({
32723
32834
  });
32724
32835
 
32725
32836
  // src/lib/runtimeEvidenceCompositionSnapshots.ts
32726
- var import_node_crypto14, import_promises31, import_node_path28, SNAPSHOT_FILE, MANIFEST_FILE, COMPLETE_FILE, createRuntimeEvidenceCompositionSnapshotRecorder, isRecord2, sha256, safeSegment4, isExistingDestinationError3, parseManifest, verifyRuntimeEvidenceCompositionSnapshot, sameSnapshot, publishRuntimeEvidenceCompositionSnapshot, captureRuntimeEvidenceCompositionSnapshot, discoverRuntimeEvidenceCompositionSnapshots;
32837
+ var import_node_crypto15, import_promises32, import_node_path29, SNAPSHOT_FILE, MANIFEST_FILE, COMPLETE_FILE, createRuntimeEvidenceCompositionSnapshotRecorder, isRecord2, sha256, safeSegment4, isExistingDestinationError3, parseManifest, verifyRuntimeEvidenceCompositionSnapshot, sameSnapshot, publishRuntimeEvidenceCompositionSnapshot, captureRuntimeEvidenceCompositionSnapshot, discoverRuntimeEvidenceCompositionSnapshots;
32727
32838
  var init_runtimeEvidenceCompositionSnapshots = __esm({
32728
32839
  "src/lib/runtimeEvidenceCompositionSnapshots.ts"() {
32729
32840
  "use strict";
32730
- import_node_crypto14 = require("crypto");
32731
- import_promises31 = __toESM(require("fs/promises"));
32732
- import_node_path28 = __toESM(require("path"));
32841
+ import_node_crypto15 = require("crypto");
32842
+ import_promises32 = __toESM(require("fs/promises"));
32843
+ import_node_path29 = __toESM(require("path"));
32733
32844
  init_runtimeEvidenceDeployment();
32734
32845
  init_runtimeEvidenceProducer();
32735
32846
  SNAPSHOT_FILE = "snapshot.json";
@@ -32750,7 +32861,7 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
32750
32861
  };
32751
32862
  };
32752
32863
  isRecord2 = (value) => value != null && typeof value === "object" && !Array.isArray(value);
32753
- sha256 = (value) => (0, import_node_crypto14.createHash)("sha256").update(value).digest("hex");
32864
+ sha256 = (value) => (0, import_node_crypto15.createHash)("sha256").update(value).digest("hex");
32754
32865
  safeSegment4 = (value, label) => {
32755
32866
  const normalized = value.trim();
32756
32867
  if (!normalized || !/^[a-zA-Z0-9._:-]+$/.test(normalized)) {
@@ -32772,9 +32883,9 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
32772
32883
  };
32773
32884
  verifyRuntimeEvidenceCompositionSnapshot = async (bundleDir) => {
32774
32885
  const [manifestText, payload, completeText] = await Promise.all([
32775
- import_promises31.default.readFile(import_node_path28.default.join(bundleDir, MANIFEST_FILE), "utf8"),
32776
- import_promises31.default.readFile(import_node_path28.default.join(bundleDir, SNAPSHOT_FILE)),
32777
- import_promises31.default.readFile(import_node_path28.default.join(bundleDir, COMPLETE_FILE), "utf8")
32886
+ import_promises32.default.readFile(import_node_path29.default.join(bundleDir, MANIFEST_FILE), "utf8"),
32887
+ import_promises32.default.readFile(import_node_path29.default.join(bundleDir, SNAPSHOT_FILE)),
32888
+ import_promises32.default.readFile(import_node_path29.default.join(bundleDir, COMPLETE_FILE), "utf8")
32778
32889
  ]);
32779
32890
  const manifest = parseManifest(JSON.parse(manifestText));
32780
32891
  if (completeText.trim() !== manifest.deploymentCompositionId) {
@@ -32837,39 +32948,39 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
32837
32948
  bytes: Buffer.byteLength(payload)
32838
32949
  }
32839
32950
  };
32840
- const snapshotsRoot = import_node_path28.default.join(evidenceRoot, "snapshots", deploymentId);
32841
- const bundleDir = import_node_path28.default.join(snapshotsRoot, compositionId);
32842
- const temporaryDir = import_node_path28.default.join(
32951
+ const snapshotsRoot = import_node_path29.default.join(evidenceRoot, "snapshots", deploymentId);
32952
+ const bundleDir = import_node_path29.default.join(snapshotsRoot, compositionId);
32953
+ const temporaryDir = import_node_path29.default.join(
32843
32954
  evidenceRoot,
32844
32955
  "incoming",
32845
- `snapshot-${compositionId}.tmp-${(0, import_node_crypto14.randomUUID)()}`
32956
+ `snapshot-${compositionId}.tmp-${(0, import_node_crypto15.randomUUID)()}`
32846
32957
  );
32847
- await import_promises31.default.mkdir(temporaryDir, { recursive: true });
32958
+ await import_promises32.default.mkdir(temporaryDir, { recursive: true });
32848
32959
  try {
32849
32960
  await Promise.all([
32850
- import_promises31.default.writeFile(import_node_path28.default.join(temporaryDir, SNAPSHOT_FILE), payload, "utf8"),
32851
- import_promises31.default.writeFile(
32852
- import_node_path28.default.join(temporaryDir, MANIFEST_FILE),
32961
+ import_promises32.default.writeFile(import_node_path29.default.join(temporaryDir, SNAPSHOT_FILE), payload, "utf8"),
32962
+ import_promises32.default.writeFile(
32963
+ import_node_path29.default.join(temporaryDir, MANIFEST_FILE),
32853
32964
  `${JSON.stringify(manifest, null, 2)}
32854
32965
  `,
32855
32966
  "utf8"
32856
32967
  )
32857
32968
  ]);
32858
- await import_promises31.default.writeFile(
32859
- import_node_path28.default.join(temporaryDir, COMPLETE_FILE),
32969
+ await import_promises32.default.writeFile(
32970
+ import_node_path29.default.join(temporaryDir, COMPLETE_FILE),
32860
32971
  `${compositionId}
32861
32972
  `,
32862
32973
  "utf8"
32863
32974
  );
32864
- await import_promises31.default.mkdir(snapshotsRoot, { recursive: true });
32975
+ await import_promises32.default.mkdir(snapshotsRoot, { recursive: true });
32865
32976
  try {
32866
- await import_promises31.default.rename(temporaryDir, bundleDir);
32977
+ await import_promises32.default.rename(temporaryDir, bundleDir);
32867
32978
  } catch (error) {
32868
32979
  if (!isExistingDestinationError3(error)) throw error;
32869
- await import_promises31.default.rm(temporaryDir, { recursive: true, force: true });
32980
+ await import_promises32.default.rm(temporaryDir, { recursive: true, force: true });
32870
32981
  }
32871
32982
  } catch (error) {
32872
- await import_promises31.default.rm(temporaryDir, { recursive: true, force: true });
32983
+ await import_promises32.default.rm(temporaryDir, { recursive: true, force: true });
32873
32984
  throw error;
32874
32985
  }
32875
32986
  const verified = await verifyRuntimeEvidenceCompositionSnapshot(bundleDir);
@@ -32903,31 +33014,31 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
32903
33014
  );
32904
33015
  }
32905
33016
  await publishRuntimeEvidenceCompositionSnapshot({
32906
- evidenceRoot: import_node_path28.default.join(projectRoot18, "data", "runtime-evidence"),
33017
+ evidenceRoot: import_node_path29.default.join(projectRoot18, "data", "runtime-evidence"),
32907
33018
  userName: userName3,
32908
33019
  deployment,
32909
33020
  producer
32910
33021
  });
32911
33022
  };
32912
33023
  discoverRuntimeEvidenceCompositionSnapshots = async (evidenceRoot) => {
32913
- const rootDir = import_node_path28.default.join(evidenceRoot, "snapshots");
33024
+ const rootDir = import_node_path29.default.join(evidenceRoot, "snapshots");
32914
33025
  const bundleDirs = [];
32915
33026
  let deployments;
32916
33027
  try {
32917
- deployments = await import_promises31.default.readdir(rootDir, { withFileTypes: true });
33028
+ deployments = await import_promises32.default.readdir(rootDir, { withFileTypes: true });
32918
33029
  } catch (error) {
32919
33030
  if (error.code === "ENOENT") return [];
32920
33031
  throw error;
32921
33032
  }
32922
33033
  for (const deployment of deployments.filter((entry) => entry.isDirectory())) {
32923
- const deploymentDir = import_node_path28.default.join(rootDir, deployment.name);
32924
- const compositions = await import_promises31.default.readdir(deploymentDir, {
33034
+ const deploymentDir = import_node_path29.default.join(rootDir, deployment.name);
33035
+ const compositions = await import_promises32.default.readdir(deploymentDir, {
32925
33036
  withFileTypes: true
32926
33037
  });
32927
33038
  bundleDirs.push(
32928
33039
  ...compositions.filter(
32929
33040
  (entry) => entry.isDirectory() && !entry.name.startsWith(".") && !entry.name.includes(".tmp-")
32930
- ).map((entry) => import_node_path28.default.join(deploymentDir, entry.name))
33041
+ ).map((entry) => import_node_path29.default.join(deploymentDir, entry.name))
32931
33042
  );
32932
33043
  }
32933
33044
  return Promise.all(
@@ -33106,12 +33217,12 @@ __export(runtimeEvidence_exports, {
33106
33217
  main: () => main40,
33107
33218
  runtimeEvidence: () => runtimeEvidence
33108
33219
  });
33109
- var import_promises32, import_node_path29, import_args31, import_chalk47, flags28, projectRoot12, toEpochMs3, resolveWindow2, parseStrategyFilter2, runtimeEvidence, main40;
33220
+ var import_promises33, import_node_path30, import_args31, import_chalk47, flags28, projectRoot12, toEpochMs3, resolveWindow2, parseStrategyFilter2, runtimeEvidence, main40;
33110
33221
  var init_runtimeEvidence = __esm({
33111
33222
  "src/scripts/runtimeEvidence.ts"() {
33112
33223
  "use strict";
33113
- import_promises32 = __toESM(require("fs/promises"));
33114
- import_node_path29 = __toESM(require("path"));
33224
+ import_promises33 = __toESM(require("fs/promises"));
33225
+ import_node_path30 = __toESM(require("path"));
33115
33226
  import_args31 = __toESM(require("args"));
33116
33227
  import_chalk47 = __toESM(require("chalk"));
33117
33228
  init_runtimeDebugEvidence();
@@ -33218,7 +33329,7 @@ var init_runtimeEvidence = __esm({
33218
33329
  deploymentId
33219
33330
  });
33220
33331
  const snapshots = publishDir && producer ? await loadRuntimeEvidenceCompositionSnapshots({
33221
- publishRoot: import_node_path29.default.resolve(projectRoot12, publishDir),
33332
+ publishRoot: import_node_path30.default.resolve(projectRoot12, publishDir),
33222
33333
  currentDeployment: deploymentSnapshot,
33223
33334
  currentProducer: producer
33224
33335
  }) : /* @__PURE__ */ new Map([
@@ -33292,14 +33403,14 @@ var init_runtimeEvidence = __esm({
33292
33403
  throw new Error("Runtime evidence window has no versioned runtime rows");
33293
33404
  }
33294
33405
  const artifact = current.artifact;
33295
- const outPath = import_node_path29.default.resolve(projectRoot12, String(flags28.out));
33296
- await import_promises32.default.mkdir(import_node_path29.default.dirname(outPath), { recursive: true });
33297
- await import_promises32.default.writeFile(outPath, `${JSON.stringify(artifact, null, 2)}
33406
+ const outPath = import_node_path30.default.resolve(projectRoot12, String(flags28.out));
33407
+ await import_promises33.default.mkdir(import_node_path30.default.dirname(outPath), { recursive: true });
33408
+ await import_promises33.default.writeFile(outPath, `${JSON.stringify(artifact, null, 2)}
33298
33409
  `, "utf8");
33299
33410
  const published = publishDir ? await Promise.all(
33300
33411
  artifacts.map(
33301
33412
  ({ artifact: artifact2, composition }) => (0, runtimeEvidenceArtifacts_exports.publishRuntimeEvidenceBundle)({
33302
- publishRoot: import_node_path29.default.resolve(projectRoot12, publishDir),
33413
+ publishRoot: import_node_path30.default.resolve(projectRoot12, publishDir),
33303
33414
  deploymentId,
33304
33415
  userName: String(flags28.user),
33305
33416
  startTime,
@@ -33345,11 +33456,11 @@ __export(runtimeEvidenceSync_exports, {
33345
33456
  main: () => main41,
33346
33457
  runtimeEvidenceSync: () => runtimeEvidenceSync
33347
33458
  });
33348
- var import_node_path30, import_args32, import_chalk48, flags29, projectRoot13, runtimeEvidenceSync, main41;
33459
+ var import_node_path31, import_args32, import_chalk48, flags29, projectRoot13, runtimeEvidenceSync, main41;
33349
33460
  var init_runtimeEvidenceSync2 = __esm({
33350
33461
  "src/scripts/runtimeEvidenceSync.ts"() {
33351
33462
  "use strict";
33352
- import_node_path30 = __toESM(require("path"));
33463
+ import_node_path31 = __toESM(require("path"));
33353
33464
  import_args32 = __toESM(require("args"));
33354
33465
  import_chalk48 = __toESM(require("chalk"));
33355
33466
  init_runtimeEvidenceSync();
@@ -33377,7 +33488,7 @@ var init_runtimeEvidenceSync2 = __esm({
33377
33488
  "Provide --source or RUNTIME_EVIDENCE_RSYNC_SOURCE for runtime evidence sync."
33378
33489
  );
33379
33490
  }
33380
- const evidenceRoot = import_node_path30.default.resolve(projectRoot13, String(flags29.dir));
33491
+ const evidenceRoot = import_node_path31.default.resolve(projectRoot13, String(flags29.dir));
33381
33492
  const result = await syncRuntimeEvidenceBundles({
33382
33493
  source,
33383
33494
  evidenceRoot,
@@ -34415,26 +34526,43 @@ var init_monitoringProfile = __esm({
34415
34526
  });
34416
34527
 
34417
34528
  // src/lib/strategyRelease/evidenceRetention.ts
34418
- var DAY_MS14, planStrategyEvidenceRetention;
34529
+ var DAY_MS14, isResearchRetired, planStrategyEvidenceRetention;
34419
34530
  var init_evidenceRetention = __esm({
34420
34531
  "src/lib/strategyRelease/evidenceRetention.ts"() {
34421
34532
  "use strict";
34422
34533
  DAY_MS14 = 864e5;
34534
+ isResearchRetired = (research) => research?.status === "retired" && research.retirement?.policy === "discard-unrecoverable-without-rerun" && Boolean(research.retirement.reason.trim()) && Boolean(research.retirement.missingEvidence.length) && research.retirement.missingEvidence.every((item) => Boolean(item.trim()));
34423
34535
  planStrategyEvidenceRetention = ({
34424
34536
  now: now2,
34425
34537
  entries,
34538
+ research,
34426
34539
  retentionDays = {
34427
34540
  operational_redis: 3,
34428
34541
  verbose_payload: 14,
34542
+ research_payload: 0,
34543
+ research_cache: 0,
34429
34544
  verified_runtime_bundle: 90,
34430
34545
  compact_ledger: null
34431
34546
  }
34432
34547
  }) => {
34433
34548
  const keep = [];
34434
34549
  const remove = [];
34550
+ const retired = isResearchRetired(research);
34551
+ const roles = new Set(
34552
+ research?.permanentArtifacts.map((artifact) => artifact.role)
34553
+ );
34554
+ const terminalResearch = Boolean(
34555
+ (research?.status === "completed" || retired) && Number.isFinite(research?.completedAt) && research.completedAt <= now2 && (retired ? ["note"] : ["note", "candidates", "metrics"]).every(
34556
+ (role) => roles.has(role)
34557
+ )
34558
+ );
34435
34559
  for (const entry of entries) {
34436
34560
  const days = retentionDays[entry.kind];
34437
- if (days == null || !entry.verified || !entry.aggregated || now2 - entry.createdAt <= days * DAY_MS14) {
34561
+ const isResearch = entry.kind === "research_payload" || entry.kind === "research_cache";
34562
+ const completedResearch = Boolean(
34563
+ terminalResearch && research?.researchId === entry.researchId && /^[a-f0-9]{64}$/.test(entry.sha256 ?? "")
34564
+ );
34565
+ if (isResearch && !completedResearch || days == null || !entry.verified || !entry.aggregated && !(isResearch && retired) || !isResearch && now2 - entry.createdAt <= days * DAY_MS14) {
34438
34566
  keep.push(entry);
34439
34567
  } else {
34440
34568
  remove.push(entry);
@@ -34464,7 +34592,7 @@ async function collectReleaseEvidenceReferences(references) {
34464
34592
  let artifact;
34465
34593
  try {
34466
34594
  const parsed = JSON.parse(
34467
- await import_promises33.default.readFile(reference.path, "utf8")
34595
+ await import_promises34.default.readFile(reference.path, "utf8")
34468
34596
  );
34469
34597
  assert3(
34470
34598
  parsed != null && typeof parsed === "object" && !Array.isArray(parsed),
@@ -34611,13 +34739,13 @@ async function collectReleaseEvidenceReferences(references) {
34611
34739
  })
34612
34740
  );
34613
34741
  }
34614
- var import_node_crypto15, import_promises33, import_node_path31, import_types9, import_strategyReleaseEvidence2, SHA256_RE2, LINEAGE_FINGERPRINT_RE, STRATEGY_REVISION_RE, DEPLOYMENT_COMPOSITION_ID_RE, REQUIRED_LONG_WINDOWS, REQUIRED_DIAGNOSTIC_TERMINAL_WINDOWS, MIN_RECENT_DIRECTION_REPAIR_EVENTS, safeSegment5, compactTimestamp, verifyFullPeriodChartArtifact, readVerifiedJsonArtifact, verifyResearchDecisionLineage, hasExactRuntimeTarget, deriveStrategyReleaseResearchDecision, canonicalStrategyReleaseJson, strategyReleaseSha256, assertFingerprint, assertLineageFingerprint, releaseReasons, deriveReleaseGates, verifyEvidenceComposition, createStrategyReleaseManifest, createStrategyReleaseEnvelope, verifyStrategyReleaseEnvelope, verifyStrategyEvidenceMarkerEnvelope, releaseMarkers, writeJsonAtomic2, publishStrategyRelease, publishStrategyLiveDiagnosis, finiteString3, finiteNumber7, finiteDirectionPolicy, uniqueStrings, incompleteEvidenceLineage, extractEvidenceLineage, verifyCompletedCoreResearchBundle;
34742
+ var import_node_crypto16, import_promises34, import_node_path32, import_types9, import_strategyReleaseEvidence2, SHA256_RE2, LINEAGE_FINGERPRINT_RE, STRATEGY_REVISION_RE, DEPLOYMENT_COMPOSITION_ID_RE, REQUIRED_LONG_WINDOWS, REQUIRED_DIAGNOSTIC_TERMINAL_WINDOWS, MIN_RECENT_DIRECTION_REPAIR_EVENTS, safeSegment5, compactTimestamp, verifyFullPeriodChartArtifact, readVerifiedJsonArtifact, verifyResearchDecisionLineage, hasExactRuntimeTarget, deriveStrategyReleaseResearchDecision, canonicalStrategyReleaseJson, strategyReleaseSha256, assertFingerprint, assertLineageFingerprint, releaseReasons, deriveReleaseGates, verifyEvidenceComposition, createStrategyReleaseManifest, createStrategyReleaseEnvelope, verifyStrategyReleaseEnvelope, verifyStrategyEvidenceMarkerEnvelope, releaseMarkers, writeJsonAtomic2, publishStrategyRelease, publishStrategyLiveDiagnosis, finiteString3, finiteNumber7, finiteDirectionPolicy, uniqueStrings, incompleteEvidenceLineage, extractEvidenceLineage, verifyCompletedCoreResearchBundle;
34615
34743
  var init_strategyRelease = __esm({
34616
34744
  "src/lib/strategyRelease.ts"() {
34617
34745
  "use strict";
34618
- import_node_crypto15 = require("crypto");
34619
- import_promises33 = __toESM(require("fs/promises"));
34620
- import_node_path31 = __toESM(require("path"));
34746
+ import_node_crypto16 = require("crypto");
34747
+ import_promises34 = __toESM(require("fs/promises"));
34748
+ import_node_path32 = __toESM(require("path"));
34621
34749
  import_types9 = require("@tradejs/types");
34622
34750
  import_strategyReleaseEvidence2 = require("@tradejs/infra/strategyReleaseEvidence");
34623
34751
  init_liveDiagnosis();
@@ -34636,11 +34764,11 @@ var init_strategyRelease = __esm({
34636
34764
  const artifact = input.chartArtifact;
34637
34765
  if (!artifact?.path || !SHA256_RE2.test(artifact.sha256)) return false;
34638
34766
  try {
34639
- const artifactPath = import_node_path31.default.resolve(artifact.path);
34767
+ const artifactPath = import_node_path32.default.resolve(artifact.path);
34640
34768
  if (await (0, import_strategyReleaseEvidence2.strategyEvidenceFileSha256)(artifactPath) !== artifact.sha256) {
34641
34769
  return false;
34642
34770
  }
34643
- const report = JSON.parse(await import_promises33.default.readFile(artifactPath, "utf8"));
34771
+ const report = JSON.parse(await import_promises34.default.readFile(artifactPath, "utf8"));
34644
34772
  return Boolean(
34645
34773
  report.chart?.persisted === true && report.chart.cardIds?.length && report.errors?.failed === 0 && report.run?.strategy === input.strategy && report.run.mode === "local-deterministic" && report.run.recent === 0 && report.run.since == null && report.run.until == null && Number(report.run.sourceRows) > 0
34646
34774
  );
@@ -34651,11 +34779,11 @@ var init_strategyRelease = __esm({
34651
34779
  readVerifiedJsonArtifact = async (artifact) => {
34652
34780
  if (!artifact?.path || !SHA256_RE2.test(artifact.sha256)) return null;
34653
34781
  try {
34654
- const artifactPath = import_node_path31.default.resolve(artifact.path);
34782
+ const artifactPath = import_node_path32.default.resolve(artifact.path);
34655
34783
  if (await (0, import_strategyReleaseEvidence2.strategyEvidenceFileSha256)(artifactPath) !== artifact.sha256) {
34656
34784
  return null;
34657
34785
  }
34658
- return JSON.parse(await import_promises33.default.readFile(artifactPath, "utf8"));
34786
+ return JSON.parse(await import_promises34.default.readFile(artifactPath, "utf8"));
34659
34787
  } catch {
34660
34788
  return null;
34661
34789
  }
@@ -35201,7 +35329,7 @@ var init_strategyRelease = __esm({
35201
35329
  manifest
35202
35330
  });
35203
35331
  verifyStrategyReleaseEnvelope = async (valueOrPath) => {
35204
- const value = typeof valueOrPath === "string" ? JSON.parse(await import_promises33.default.readFile(valueOrPath, "utf8")) : valueOrPath;
35332
+ const value = typeof valueOrPath === "string" ? JSON.parse(await import_promises34.default.readFile(valueOrPath, "utf8")) : valueOrPath;
35205
35333
  const envelope = value;
35206
35334
  assert3(
35207
35335
  envelope?.schema === "tradejs-strategy-release-envelope/v1",
@@ -35252,7 +35380,7 @@ var init_strategyRelease = __esm({
35252
35380
  return envelope;
35253
35381
  };
35254
35382
  verifyStrategyEvidenceMarkerEnvelope = async (valueOrPath) => {
35255
- const value = typeof valueOrPath === "string" ? JSON.parse(await import_promises33.default.readFile(valueOrPath, "utf8")) : valueOrPath;
35383
+ const value = typeof valueOrPath === "string" ? JSON.parse(await import_promises34.default.readFile(valueOrPath, "utf8")) : valueOrPath;
35256
35384
  return (0, import_strategyReleaseEvidence2.verifyStrategyEvidenceMarkerEnvelope)(value);
35257
35385
  };
35258
35386
  releaseMarkers = (manifest) => {
@@ -35314,14 +35442,14 @@ var init_strategyRelease = __esm({
35314
35442
  };
35315
35443
  writeJsonAtomic2 = async (filePath, value) => {
35316
35444
  const temporaryPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
35317
- await import_promises33.default.mkdir(import_node_path31.default.dirname(filePath), { recursive: true });
35318
- await import_promises33.default.writeFile(
35445
+ await import_promises34.default.mkdir(import_node_path32.default.dirname(filePath), { recursive: true });
35446
+ await import_promises34.default.writeFile(
35319
35447
  temporaryPath,
35320
35448
  `${canonicalStrategyReleaseJson(value)}
35321
35449
  `,
35322
35450
  "utf8"
35323
35451
  );
35324
- await import_promises33.default.rename(temporaryPath, filePath);
35452
+ await import_promises34.default.rename(temporaryPath, filePath);
35325
35453
  };
35326
35454
  publishStrategyRelease = async ({
35327
35455
  rootDir,
@@ -35338,13 +35466,13 @@ var init_strategyRelease = __esm({
35338
35466
  path: entry.path
35339
35467
  }))
35340
35468
  });
35341
- const releasePath = import_node_path31.default.join(
35469
+ const releasePath = import_node_path32.default.join(
35342
35470
  rootDir,
35343
35471
  "releases",
35344
35472
  safeSegment5(manifest.strategy, "strategy"),
35345
35473
  `${manifest.releaseId}.json`
35346
35474
  );
35347
- const markerPath = import_node_path31.default.join(
35475
+ const markerPath = import_node_path32.default.join(
35348
35476
  rootDir,
35349
35477
  "markers",
35350
35478
  safeSegment5(manifest.strategy, "strategy"),
@@ -35424,13 +35552,13 @@ var init_strategyRelease = __esm({
35424
35552
  markers,
35425
35553
  sourceArtifacts
35426
35554
  });
35427
- const diagnosisPath = import_node_path31.default.join(
35555
+ const diagnosisPath = import_node_path32.default.join(
35428
35556
  rootDir,
35429
35557
  "diagnoses",
35430
35558
  safeSegment5(diagnosis.strategy, "strategy"),
35431
35559
  `${diagnosisId}.json`
35432
35560
  );
35433
- const markerPath = import_node_path31.default.join(
35561
+ const markerPath = import_node_path32.default.join(
35434
35562
  rootDir,
35435
35563
  "markers",
35436
35564
  safeSegment5(diagnosis.strategy, "strategy"),
@@ -35620,11 +35748,11 @@ var init_strategyRelease = __esm({
35620
35748
  const specSha256 = finiteString3(artifact.specSha256);
35621
35749
  assert3(researchId != null, "core result researchId is required");
35622
35750
  assert3(specSha256 != null, "core result specSha256 is required");
35623
- const researchDir = import_node_path31.default.dirname(resultPath);
35624
- const manifestPath = import_node_path31.default.join(researchDir, "manifest.json");
35625
- const specPath = import_node_path31.default.join(researchDir, "spec.json");
35626
- const manifestBytes = await import_promises33.default.readFile(manifestPath).catch(() => null);
35627
- const specBytes = await import_promises33.default.readFile(specPath).catch(() => null);
35751
+ const researchDir = import_node_path32.default.dirname(resultPath);
35752
+ const manifestPath = import_node_path32.default.join(researchDir, "manifest.json");
35753
+ const specPath = import_node_path32.default.join(researchDir, "spec.json");
35754
+ const manifestBytes = await import_promises34.default.readFile(manifestPath).catch(() => null);
35755
+ const specBytes = await import_promises34.default.readFile(specPath).catch(() => null);
35628
35756
  assert3(
35629
35757
  manifestBytes != null && specBytes != null,
35630
35758
  "core result must belong to a completed core research bundle"
@@ -35633,14 +35761,14 @@ var init_strategyRelease = __esm({
35633
35761
  const artifactHashes = manifest.artifactHashes != null && typeof manifest.artifactHashes === "object" && !Array.isArray(manifest.artifactHashes) ? manifest.artifactHashes : null;
35634
35762
  const parsedSpec = JSON.parse(specBytes.toString("utf8"));
35635
35763
  assert3(
35636
- manifest.schema === "tradejs-core-research-manifest/v1" && manifest.status === "completed" && manifest.researchId === researchId && manifest.specSha256 === specSha256 && artifactHashes?.["result.json"] === resultSha256 && (0, import_node_crypto15.createHash)("sha256").update(canonicalStrategyReleaseJson(parsedSpec)).digest("hex") === specSha256,
35764
+ manifest.schema === "tradejs-core-research-manifest/v1" && manifest.status === "completed" && manifest.researchId === researchId && manifest.specSha256 === specSha256 && artifactHashes?.["result.json"] === resultSha256 && (0, import_node_crypto16.createHash)("sha256").update(canonicalStrategyReleaseJson(parsedSpec)).digest("hex") === specSha256,
35637
35765
  "core result is not bound by its completed core research manifest"
35638
35766
  );
35639
35767
  for (const [relativePath, expectedSha256] of Object.entries(
35640
35768
  artifactHashes ?? {}
35641
35769
  )) {
35642
35770
  assert3(
35643
- !import_node_path31.default.isAbsolute(relativePath) && !relativePath.split(/[\\/]/).includes(".."),
35771
+ !import_node_path32.default.isAbsolute(relativePath) && !relativePath.split(/[\\/]/).includes(".."),
35644
35772
  `core bundle artifact ${relativePath} escapes its research directory`
35645
35773
  );
35646
35774
  assert3(
@@ -35648,7 +35776,7 @@ var init_strategyRelease = __esm({
35648
35776
  `core bundle artifact ${relativePath} has an invalid checksum`
35649
35777
  );
35650
35778
  const actualSha256 = await (0, import_strategyReleaseEvidence2.strategyEvidenceFileSha256)(
35651
- import_node_path31.default.join(researchDir, relativePath)
35779
+ import_node_path32.default.join(researchDir, relativePath)
35652
35780
  );
35653
35781
  assert3(
35654
35782
  actualSha256 === expectedSha256,
@@ -35665,13 +35793,13 @@ __export(runtimeScorecard_exports, {
35665
35793
  main: () => main42,
35666
35794
  runtimeScorecard: () => runtimeScorecard
35667
35795
  });
35668
- var import_promises34, import_node_crypto16, import_node_path32, import_args33, import_chalk49, flags30, projectRoot14, resolveOptionalPath, readJson, assertReportType, sha256File2, loadHistoryArtifacts, runtimeScorecard, main42;
35796
+ var import_promises35, import_node_crypto17, import_node_path33, import_args33, import_chalk49, flags30, projectRoot14, resolveOptionalPath, readJson, assertReportType, sha256File2, loadHistoryArtifacts, runtimeScorecard, main42;
35669
35797
  var init_runtimeScorecard2 = __esm({
35670
35798
  "src/scripts/runtimeScorecard.ts"() {
35671
35799
  "use strict";
35672
- import_promises34 = __toESM(require("fs/promises"));
35673
- import_node_crypto16 = require("crypto");
35674
- import_node_path32 = __toESM(require("path"));
35800
+ import_promises35 = __toESM(require("fs/promises"));
35801
+ import_node_crypto17 = require("crypto");
35802
+ import_node_path33 = __toESM(require("path"));
35675
35803
  import_args33 = __toESM(require("args"));
35676
35804
  import_chalk49 = __toESM(require("chalk"));
35677
35805
  init_runtimeEvidenceArtifacts();
@@ -35741,15 +35869,15 @@ var init_runtimeScorecard2 = __esm({
35741
35869
  projectRoot14 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
35742
35870
  resolveOptionalPath = (value) => {
35743
35871
  const raw = String(value ?? "").trim();
35744
- return raw ? import_node_path32.default.resolve(projectRoot14, raw) : null;
35872
+ return raw ? import_node_path33.default.resolve(projectRoot14, raw) : null;
35745
35873
  };
35746
- readJson = async (filePath) => filePath ? JSON.parse(await import_promises34.default.readFile(filePath, "utf8")) : void 0;
35874
+ readJson = async (filePath) => filePath ? JSON.parse(await import_promises35.default.readFile(filePath, "utf8")) : void 0;
35747
35875
  assertReportType = (artifact, expected, label) => {
35748
35876
  if (artifact != null && (!artifact || typeof artifact !== "object" || Array.isArray(artifact) || artifact.reportType !== expected)) {
35749
35877
  throw new Error(`${label} must be a ${expected} artifact`);
35750
35878
  }
35751
35879
  };
35752
- sha256File2 = async (filePath) => (0, import_node_crypto16.createHash)("sha256").update(await import_promises34.default.readFile(filePath)).digest("hex");
35880
+ sha256File2 = async (filePath) => (0, import_node_crypto17.createHash)("sha256").update(await import_promises35.default.readFile(filePath)).digest("hex");
35753
35881
  loadHistoryArtifacts = async (historyDir) => {
35754
35882
  if (!historyDir) return [];
35755
35883
  const bundleDirs = await (0, runtimeEvidenceArtifacts_exports.discoverRuntimeEvidenceBundles)(historyDir);
@@ -35820,13 +35948,13 @@ var init_runtimeScorecard2 = __esm({
35820
35948
  strategy: scorecardStrategy,
35821
35949
  llmComparatorPolicy: verifiedRelease?.manifest.prospective.llmComparatorPolicy ?? "ai_approved_only"
35822
35950
  });
35823
- const outPath = import_node_path32.default.resolve(projectRoot14, String(flags30.out));
35951
+ const outPath = import_node_path33.default.resolve(projectRoot14, String(flags30.out));
35824
35952
  const markdownPath = outPath.replace(/\.json$/i, "") + ".md";
35825
- await import_promises34.default.mkdir(import_node_path32.default.dirname(outPath), { recursive: true });
35953
+ await import_promises35.default.mkdir(import_node_path33.default.dirname(outPath), { recursive: true });
35826
35954
  await Promise.all([
35827
- import_promises34.default.writeFile(outPath, `${JSON.stringify(scorecard, null, 2)}
35955
+ import_promises35.default.writeFile(outPath, `${JSON.stringify(scorecard, null, 2)}
35828
35956
  `, "utf8"),
35829
- import_promises34.default.writeFile(
35957
+ import_promises35.default.writeFile(
35830
35958
  markdownPath,
35831
35959
  formatRuntimeScorecardMarkdown(scorecard),
35832
35960
  "utf8"
@@ -35840,7 +35968,7 @@ var init_runtimeScorecard2 = __esm({
35840
35968
  const diagnosisPath = diagnosis ? outPath.replace(/\.json$/i, "") + ".diagnosis.json" : null;
35841
35969
  const strategyReleaseRoot = resolveOptionalPath(flags30.strategyReleaseRoot);
35842
35970
  if (diagnosis && diagnosisPath) {
35843
- await import_promises34.default.writeFile(
35971
+ await import_promises35.default.writeFile(
35844
35972
  diagnosisPath,
35845
35973
  `${JSON.stringify(diagnosis, null, 2)}
35846
35974
  `,
@@ -35861,7 +35989,7 @@ var init_runtimeScorecard2 = __esm({
35861
35989
  composition: verifiedRelease?.manifest.composition,
35862
35990
  sourceArtifacts: await Promise.all(
35863
35991
  sourcePaths.map(async (sourcePath) => ({
35864
- artifactId: import_node_path32.default.basename(sourcePath),
35992
+ artifactId: import_node_path33.default.basename(sourcePath),
35865
35993
  path: sourcePath,
35866
35994
  sha256: await sha256File2(sourcePath)
35867
35995
  }))
@@ -35872,11 +36000,11 @@ var init_runtimeScorecard2 = __esm({
35872
36000
  let receiptPath2 = null;
35873
36001
  if (flags30.markProcessed) {
35874
36002
  const runtimeEvidenceBundle = await (0, runtimeEvidenceArtifacts_exports.verifyRuntimeEvidenceBundle)(
35875
- import_node_path32.default.dirname(runtimeEvidencePath)
36003
+ import_node_path33.default.dirname(runtimeEvidencePath)
35876
36004
  );
35877
36005
  const feedbackSource = replayEvidencePath ? await (0, runtimeFeedbackArtifacts_exports.verifyRuntimeFeedbackReplaySource)({
35878
- bundleDir: import_node_path32.default.dirname(replayEvidencePath),
35879
- runtimeEvidenceBundleDir: import_node_path32.default.dirname(runtimeEvidencePath)
36006
+ bundleDir: import_node_path33.default.dirname(replayEvidencePath),
36007
+ runtimeEvidenceBundleDir: import_node_path33.default.dirname(runtimeEvidencePath)
35880
36008
  }).catch((error) => {
35881
36009
  if (runtimeEvidenceBundle.artifact.producer) throw error;
35882
36010
  return null;
@@ -35887,9 +36015,9 @@ var init_runtimeScorecard2 = __esm({
35887
36015
  );
35888
36016
  }
35889
36017
  receiptPath2 = await markRuntimeEvidenceBundleProcessed({
35890
- evidenceRoot: import_node_path32.default.resolve(projectRoot14, String(flags30.evidenceDir)),
36018
+ evidenceRoot: import_node_path33.default.resolve(projectRoot14, String(flags30.evidenceDir)),
35891
36019
  deploymentId: String(flags30.deployment),
35892
- bundleDir: import_node_path32.default.dirname(runtimeEvidencePath),
36020
+ bundleDir: import_node_path33.default.dirname(runtimeEvidencePath),
35893
36021
  scorecardPath: outPath,
35894
36022
  runtimeFeedback: feedbackSource ? {
35895
36023
  artifactId: feedbackSource.feedback.manifest.artifactId,
@@ -36080,21 +36208,316 @@ var init_runtimeControl = __esm({
36080
36208
  }
36081
36209
  });
36082
36210
 
36211
+ // src/lib/strategyRelease/researchFileConsumers.ts
36212
+ var import_node_path34, import_node_child_process10, import_node_util3, execFileAsync3, runCommand3, GUEST_FILE_CHECK, assertNoResearchFileConsumers;
36213
+ var init_researchFileConsumers = __esm({
36214
+ "src/lib/strategyRelease/researchFileConsumers.ts"() {
36215
+ "use strict";
36216
+ import_node_path34 = __toESM(require("path"));
36217
+ import_node_child_process10 = require("child_process");
36218
+ import_node_util3 = require("util");
36219
+ execFileAsync3 = (0, import_node_util3.promisify)(import_node_child_process10.execFile);
36220
+ runCommand3 = (command, args39) => execFileAsync3(command, args39, { maxBuffer: 32 * 1024 * 1024 });
36221
+ GUEST_FILE_CHECK = `
36222
+ import os, sys, json
36223
+ if os.geteuid() != 0:
36224
+ raise RuntimeError('Cannot inspect every container process')
36225
+ wanted = set(json.loads(sys.argv[1]))
36226
+ opened = set()
36227
+ for pid in os.listdir('/proc'):
36228
+ if not pid.isdigit():
36229
+ continue
36230
+ for kind in ('fd', 'map_files'):
36231
+ directory = '/proc/' + pid + '/' + kind
36232
+ try:
36233
+ names = os.listdir(directory)
36234
+ except FileNotFoundError:
36235
+ continue
36236
+ for name in names:
36237
+ try:
36238
+ target = os.readlink(directory + '/' + name)
36239
+ except FileNotFoundError:
36240
+ continue
36241
+ if target in wanted:
36242
+ opened.add(target)
36243
+ print(json.dumps(sorted(opened)))
36244
+ `;
36245
+ assertNoResearchFileConsumers = async (files, run = runCommand3) => {
36246
+ const virtualPids = /* @__PURE__ */ new Set();
36247
+ const wanted = new Set(files.map((file) => import_node_path34.default.resolve(file)));
36248
+ let commonRoot = files.length ? import_node_path34.default.dirname(files[0]) : "";
36249
+ while (commonRoot && files.some((file) => {
36250
+ const relative = import_node_path34.default.relative(commonRoot, file);
36251
+ return relative === ".." || relative.startsWith(`..${import_node_path34.default.sep}`) || import_node_path34.default.isAbsolute(relative);
36252
+ }))
36253
+ commonRoot = import_node_path34.default.dirname(commonRoot);
36254
+ const selectors = [];
36255
+ if (files.length > 1e3 && commonRoot !== import_node_path34.default.parse(commonRoot).root) {
36256
+ selectors.push(["+D", commonRoot]);
36257
+ } else {
36258
+ for (let offset = 0; offset < files.length; offset += 100)
36259
+ selectors.push(["--", ...files.slice(offset, offset + 100)]);
36260
+ }
36261
+ for (const selector of selectors) {
36262
+ let output;
36263
+ try {
36264
+ output = (await run("lsof", ["-F", "pcn", ...selector])).stdout;
36265
+ } catch (error) {
36266
+ if (error.code === 1) continue;
36267
+ throw error;
36268
+ }
36269
+ let pid = "";
36270
+ let virtual = false;
36271
+ for (const line of output.split("\n")) {
36272
+ if (line.startsWith("p")) {
36273
+ pid = line.slice(1);
36274
+ virtual = false;
36275
+ }
36276
+ if (line.startsWith("c"))
36277
+ virtual = line.startsWith("ccom.apple.Virtualization.");
36278
+ if (line.startsWith("n")) {
36279
+ if (!wanted.has(import_node_path34.default.resolve(line.slice(1)))) continue;
36280
+ if (!virtual || !/^\d+$/.test(pid))
36281
+ throw new Error(
36282
+ `Research cleanup found open files: ${line.slice(1)}`
36283
+ );
36284
+ virtualPids.add(pid);
36285
+ }
36286
+ }
36287
+ }
36288
+ if (!virtualPids.size) return;
36289
+ for (const pid of virtualPids) {
36290
+ const comm = (await run("ps", ["-p", pid, "-o", "comm="])).stdout.trim();
36291
+ if (comm !== "/System/Library/Frameworks/Virtualization.framework/Versions/A/XPCServices/com.apple.Virtualization.VirtualMachine.xpc/Contents/MacOS/com.apple.Virtualization.VirtualMachine") {
36292
+ throw new Error("Unrecognized virtual file consumer");
36293
+ }
36294
+ }
36295
+ const contexts = JSON.parse(
36296
+ (await run("docker", ["context", "inspect"])).stdout
36297
+ );
36298
+ if (contexts.length !== 1 || !contexts[0].Endpoints.docker.Host.startsWith("unix://")) {
36299
+ throw new Error("Research file inspection requires a local Docker socket");
36300
+ }
36301
+ const ids = (await run("docker", ["ps", "-q"])).stdout.trim().split(/\s+/).filter(Boolean);
36302
+ if (!ids.length)
36303
+ throw new Error("Cannot resolve virtual research file handles");
36304
+ const containers = JSON.parse(
36305
+ (await run("docker", ["inspect", ...ids])).stdout
36306
+ );
36307
+ const covered = /* @__PURE__ */ new Set();
36308
+ for (const container of containers) {
36309
+ const guestFiles = /* @__PURE__ */ new Set();
36310
+ for (const mount of container.Mounts) {
36311
+ if (mount.Type !== "bind") continue;
36312
+ for (const file of files) {
36313
+ const relative = import_node_path34.default.relative(mount.Source, file);
36314
+ if (relative === "" || !relative.startsWith(`..${import_node_path34.default.sep}`) && relative !== ".." && !import_node_path34.default.isAbsolute(relative)) {
36315
+ guestFiles.add(import_node_path34.default.posix.join(mount.Destination, relative));
36316
+ covered.add(file);
36317
+ }
36318
+ }
36319
+ }
36320
+ if (!guestFiles.size) continue;
36321
+ const paths = [...guestFiles];
36322
+ for (let offset = 0; offset < paths.length; offset += 250) {
36323
+ const opened = JSON.parse(
36324
+ (await run("docker", [
36325
+ "exec",
36326
+ container.Id,
36327
+ "python",
36328
+ "-c",
36329
+ GUEST_FILE_CHECK,
36330
+ JSON.stringify(paths.slice(offset, offset + 250))
36331
+ ])).stdout
36332
+ );
36333
+ if (!Array.isArray(opened) || opened.length)
36334
+ throw new Error("Research cleanup found open files in a container");
36335
+ }
36336
+ }
36337
+ if (covered.size !== files.length)
36338
+ throw new Error("Unresolved virtual research file handles");
36339
+ };
36340
+ }
36341
+ });
36342
+
36343
+ // src/lib/strategyRelease/researchRetention.ts
36344
+ var import_promises36, import_node_path35, import_node_crypto18, import_strategyReleaseEvidence3, SHA256_RE3, mapFiles, fileSha256, inside, applyResearchRetention;
36345
+ var init_researchRetention = __esm({
36346
+ "src/lib/strategyRelease/researchRetention.ts"() {
36347
+ "use strict";
36348
+ import_promises36 = __toESM(require("fs/promises"));
36349
+ import_node_path35 = __toESM(require("path"));
36350
+ import_node_crypto18 = require("crypto");
36351
+ import_strategyReleaseEvidence3 = require("@tradejs/infra/strategyReleaseEvidence");
36352
+ init_researchFileConsumers();
36353
+ init_evidenceRetention();
36354
+ SHA256_RE3 = /^[a-f0-9]{64}$/;
36355
+ mapFiles = async (entries, visit) => {
36356
+ const results2 = new Array(entries.length);
36357
+ let next = 0;
36358
+ const workers = await Promise.allSettled(
36359
+ Array.from({ length: Math.min(8, entries.length) }, async () => {
36360
+ while (next < entries.length) {
36361
+ const index = next++;
36362
+ results2[index] = await visit(entries[index]);
36363
+ }
36364
+ })
36365
+ );
36366
+ for (const worker of workers)
36367
+ if (worker.status === "rejected") throw worker.reason;
36368
+ return results2;
36369
+ };
36370
+ fileSha256 = async (file, bytes) => bytes <= 1024 * 1024 ? (0, import_node_crypto18.createHash)("sha256").update(await import_promises36.default.readFile(file)).digest("hex") : (0, import_strategyReleaseEvidence3.strategyEvidenceFileSha256)(file);
36371
+ inside = (root, file) => {
36372
+ const relative = import_node_path35.default.relative(root, file);
36373
+ return relative !== "" && !relative.startsWith(`..${import_node_path35.default.sep}`) && relative !== ".." && !import_node_path35.default.isAbsolute(relative);
36374
+ };
36375
+ applyResearchRetention = async (options) => {
36376
+ const projectRoot18 = await import_promises36.default.realpath(options.projectRoot);
36377
+ const dataRoot = import_node_path35.default.join(projectRoot18, "data");
36378
+ const resolve = (file) => import_node_path35.default.resolve(projectRoot18, file);
36379
+ const receiptPath2 = resolve(options.receiptPath);
36380
+ const journalPath = `${receiptPath2}.deleted.jsonl`;
36381
+ const permanent = new Set(
36382
+ options.research.permanentArtifacts.map((entry) => resolve(entry.path))
36383
+ );
36384
+ if (!inside(projectRoot18, receiptPath2) || permanent.has(receiptPath2) || permanent.has(journalPath)) {
36385
+ throw new Error(
36386
+ "Cleanup receipt must be separate from permanent research artifacts"
36387
+ );
36388
+ }
36389
+ permanent.add(receiptPath2);
36390
+ permanent.add(journalPath);
36391
+ for (const file of options.protectedPaths ?? []) permanent.add(resolve(file));
36392
+ const retired = isResearchRetired(options.research);
36393
+ if (options.research.status !== "completed" && !retired || !Number.isFinite(options.research.completedAt) || options.research.completedAt > Date.now()) {
36394
+ throw new Error("Research must be completed before cleanup");
36395
+ }
36396
+ for (const role of retired ? ["note"] : ["note", "candidates", "metrics"]) {
36397
+ if (!options.research.permanentArtifacts.some((entry) => entry.role === role)) {
36398
+ throw new Error(`Missing permanent research ${role}`);
36399
+ }
36400
+ }
36401
+ await mapFiles(options.research.permanentArtifacts, async (artifact) => {
36402
+ const file = resolve(artifact.path);
36403
+ if (!inside(projectRoot18, await import_promises36.default.realpath(file)) || !SHA256_RE3.test(artifact.sha256) || await fileSha256(file, (await import_promises36.default.stat(file)).size) !== artifact.sha256) {
36404
+ throw new Error(
36405
+ `Permanent research artifact checksum/path mismatch: ${file}`
36406
+ );
36407
+ }
36408
+ if (artifact.role === "note") {
36409
+ const handle = await import_promises36.default.open(file, "r");
36410
+ try {
36411
+ const header = Buffer.alloc(4096);
36412
+ const { bytesRead } = await handle.read(header, 0, header.length, 0);
36413
+ const frontmatter = header.subarray(0, bytesRead).toString("utf8").match(/^---\r?\n([\s\S]*?)\r?\n---/);
36414
+ if (!frontmatter || !/^schema:\s*tradejs-research\/v1\s*$/m.test(frontmatter[1]) || !(retired ? /^reproduction:\s*(?:complete|partial|blocked|legacy-partial)\s*$/m.test(
36415
+ frontmatter[1]
36416
+ ) : /^reproduction:\s*complete\s*$/m.test(frontmatter[1]))) {
36417
+ throw new Error(
36418
+ `Research note must have reproduction: complete: ${file}`
36419
+ );
36420
+ }
36421
+ } finally {
36422
+ await handle.close();
36423
+ }
36424
+ }
36425
+ });
36426
+ const checkedPaths = /* @__PURE__ */ new Set();
36427
+ const checked = await mapFiles(options.entries, async (entry) => {
36428
+ const file = resolve(entry.path);
36429
+ if (!["research_payload", "research_cache"].includes(entry.kind) || entry.researchId !== options.research.researchId || !entry.verified || !entry.aggregated && !retired || !SHA256_RE3.test(entry.sha256 ?? "") || !inside(dataRoot, file) || permanent.has(file) || /\.(?:md|patch|diff)$/i.test(file)) {
36430
+ throw new Error(`Not a disposable research file: ${file}`);
36431
+ }
36432
+ if (checkedPaths.has(file))
36433
+ throw new Error(`Duplicate cleanup path: ${file}`);
36434
+ checkedPaths.add(file);
36435
+ if (await import_promises36.default.realpath(file) !== file)
36436
+ throw new Error(`Research cleanup refuses symlinks: ${file}`);
36437
+ const stat = await import_promises36.default.lstat(file);
36438
+ if (!stat.isFile() || stat.size !== entry.bytes || await fileSha256(file, stat.size) !== entry.sha256) {
36439
+ throw new Error(
36440
+ `Disposable research file checksum/size mismatch: ${file}`
36441
+ );
36442
+ }
36443
+ return { entry, file, mtimeMs: stat.mtimeMs, ino: stat.ino };
36444
+ });
36445
+ await assertNoResearchFileConsumers(checked.map((entry) => entry.file));
36446
+ const receipt = {
36447
+ schema: "tradejs-research-cleanup-receipt/v1",
36448
+ researchId: options.research.researchId,
36449
+ completedAt: options.research.completedAt,
36450
+ ...retired ? { retirement: options.research.retirement } : {},
36451
+ journalPath,
36452
+ permanentArtifacts: options.research.permanentArtifacts,
36453
+ scope: "reported aggregates and frozen candidates; new trade-level analyses require a rerun",
36454
+ status: "planned",
36455
+ files: checked.map(({ entry, file }) => ({
36456
+ path: file,
36457
+ sha256: entry.sha256,
36458
+ bytes: entry.bytes,
36459
+ removed: false
36460
+ }))
36461
+ };
36462
+ if (!options.apply) return receipt;
36463
+ await import_promises36.default.mkdir(import_node_path35.default.dirname(receiptPath2), { recursive: true });
36464
+ if (await import_promises36.default.realpath(import_node_path35.default.dirname(receiptPath2)) !== import_node_path35.default.dirname(receiptPath2)) {
36465
+ throw new Error("Cleanup receipt refuses symlinked directories");
36466
+ }
36467
+ const lock = await import_promises36.default.open(`${receiptPath2}.lock`, "wx");
36468
+ let journal;
36469
+ const writeReceipt = async () => {
36470
+ const temp = `${receiptPath2}.${process.pid}.tmp`;
36471
+ await import_promises36.default.writeFile(temp, `${JSON.stringify(receipt, null, 2)}
36472
+ `, "utf8");
36473
+ await import_promises36.default.rename(temp, receiptPath2);
36474
+ };
36475
+ try {
36476
+ journal = await import_promises36.default.open(journalPath, "wx");
36477
+ receipt.status = "applying";
36478
+ await writeReceipt();
36479
+ for (let index = 0; index < checked.length; index += 1) {
36480
+ const { file, entry, ino, mtimeMs } = checked[index];
36481
+ const stat = await import_promises36.default.lstat(file);
36482
+ if (!stat.isFile() || stat.ino !== ino || stat.mtimeMs !== mtimeMs || stat.size !== entry.bytes) {
36483
+ throw new Error(`Research file changed during cleanup: ${file}`);
36484
+ }
36485
+ await import_promises36.default.unlink(file);
36486
+ receipt.files[index].removed = true;
36487
+ await journal.write(`${JSON.stringify(receipt.files[index])}
36488
+ `);
36489
+ }
36490
+ receipt.status = "completed";
36491
+ await writeReceipt();
36492
+ return receipt;
36493
+ } catch (error) {
36494
+ if (journal) await writeReceipt();
36495
+ throw error;
36496
+ } finally {
36497
+ await journal?.close();
36498
+ await lock.close();
36499
+ await import_promises36.default.unlink(`${receiptPath2}.lock`);
36500
+ }
36501
+ };
36502
+ }
36503
+ });
36504
+
36083
36505
  // src/scripts/strategyRelease.ts
36084
36506
  var strategyRelease_exports = {};
36085
36507
  __export(strategyRelease_exports, {
36086
36508
  main: () => main44,
36087
36509
  runStrategyReleaseCommand: () => runStrategyReleaseCommand
36088
36510
  });
36089
- var import_promises35, import_node_fs6, import_node_readline3, import_node_path33, import_chalk50, valueAfter2, required3, writeJsonAtomic3, runStrategyReleaseCommand, printUsage2, main44;
36511
+ var import_promises37, import_node_fs6, import_node_readline3, import_node_path36, import_chalk50, valueAfter2, required3, writeJsonAtomic3, runStrategyReleaseCommand, printUsage2, main44;
36090
36512
  var init_strategyRelease2 = __esm({
36091
36513
  "src/scripts/strategyRelease.ts"() {
36092
36514
  "use strict";
36093
- import_promises35 = __toESM(require("fs/promises"));
36515
+ import_promises37 = __toESM(require("fs/promises"));
36094
36516
  import_node_fs6 = require("fs");
36095
36517
  import_node_readline3 = require("readline");
36096
- import_node_path33 = __toESM(require("path"));
36518
+ import_node_path36 = __toESM(require("path"));
36097
36519
  import_chalk50 = __toESM(require("chalk"));
36520
+ init_researchRetention();
36098
36521
  init_strategyRelease();
36099
36522
  valueAfter2 = (argv2, name) => {
36100
36523
  const index = argv2.indexOf(name);
@@ -36106,17 +36529,17 @@ var init_strategyRelease2 = __esm({
36106
36529
  };
36107
36530
  writeJsonAtomic3 = async (filePath, value) => {
36108
36531
  const temporaryPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
36109
- await import_promises35.default.mkdir(import_node_path33.default.dirname(filePath), { recursive: true });
36110
- await import_promises35.default.writeFile(
36532
+ await import_promises37.default.mkdir(import_node_path36.default.dirname(filePath), { recursive: true });
36533
+ await import_promises37.default.writeFile(
36111
36534
  temporaryPath,
36112
36535
  `${JSON.stringify(value, null, 2)}
36113
36536
  `,
36114
36537
  "utf8"
36115
36538
  );
36116
- await import_promises35.default.rename(temporaryPath, filePath);
36539
+ await import_promises37.default.rename(temporaryPath, filePath);
36117
36540
  };
36118
36541
  runStrategyReleaseCommand = async (options) => {
36119
- const inputPath = import_node_path33.default.resolve(options.inputPath);
36542
+ const inputPath = import_node_path36.default.resolve(options.inputPath);
36120
36543
  if (options.command === "verify") {
36121
36544
  const envelope = await verifyStrategyReleaseEnvelope(inputPath);
36122
36545
  return {
@@ -36154,7 +36577,7 @@ var init_strategyRelease2 = __esm({
36154
36577
  endTime,
36155
36578
  days: options.days?.length ? options.days : [7, 30, 90]
36156
36579
  });
36157
- const outputPath = import_node_path33.default.resolve(
36580
+ const outputPath = import_node_path36.default.resolve(
36158
36581
  options.outputPath ?? "output/strategy-monitoring-profile.json"
36159
36582
  );
36160
36583
  await writeJsonAtomic3(outputPath, profile);
@@ -36165,22 +36588,40 @@ var init_strategyRelease2 = __esm({
36165
36588
  profile
36166
36589
  };
36167
36590
  }
36168
- const input = JSON.parse(await import_promises35.default.readFile(inputPath, "utf8"));
36591
+ const input = JSON.parse(await import_promises37.default.readFile(inputPath, "utf8"));
36169
36592
  if (options.command === "decide") {
36170
36593
  const decision = await deriveStrategyReleaseResearchDecision(input);
36171
36594
  if (options.outputPath) {
36172
- await writeJsonAtomic3(import_node_path33.default.resolve(options.outputPath), decision);
36595
+ await writeJsonAtomic3(import_node_path36.default.resolve(options.outputPath), decision);
36173
36596
  }
36174
36597
  return {
36175
36598
  kind: "decided",
36176
36599
  ...decision,
36177
- outputPath: options.outputPath ? import_node_path33.default.resolve(options.outputPath) : null
36600
+ outputPath: options.outputPath ? import_node_path36.default.resolve(options.outputPath) : null
36178
36601
  };
36179
36602
  }
36180
36603
  if (options.command === "retention") {
36181
36604
  const plan = planStrategyEvidenceRetention(input);
36182
- if (options.apply) {
36183
- await Promise.all(plan.delete.map((entry) => import_promises35.default.rm(entry.path)));
36605
+ const researchEntries = plan.delete.filter(
36606
+ (entry) => entry.kind === "research_payload" || entry.kind === "research_cache"
36607
+ );
36608
+ const receiptPath2 = options.outputPath ?? `${inputPath}.receipt.json`;
36609
+ if (researchEntries.length) {
36610
+ if (researchEntries.length !== plan.delete.length) {
36611
+ throw new Error(
36612
+ "Research cleanup requires a separate inventory from runtime retention"
36613
+ );
36614
+ }
36615
+ await applyResearchRetention({
36616
+ projectRoot: process.env.PROJECT_CWD ?? process.cwd(),
36617
+ research: input.research,
36618
+ entries: researchEntries,
36619
+ receiptPath: receiptPath2,
36620
+ apply: Boolean(options.apply),
36621
+ protectedPaths: [inputPath]
36622
+ });
36623
+ } else if (options.apply) {
36624
+ await Promise.all(plan.delete.map((entry) => import_promises37.default.rm(entry.path)));
36184
36625
  }
36185
36626
  return {
36186
36627
  kind: "retention",
@@ -36188,17 +36629,18 @@ var init_strategyRelease2 = __esm({
36188
36629
  keepCount: plan.keep.length,
36189
36630
  deleteCount: plan.delete.length,
36190
36631
  bytesReclaimable: plan.bytesReclaimable,
36191
- delete: plan.delete.map((entry) => entry.path)
36632
+ delete: plan.delete.map((entry) => entry.path),
36633
+ ...researchEntries.length && options.apply ? { receiptPath: receiptPath2 } : {}
36192
36634
  };
36193
36635
  }
36194
36636
  if (options.command === "diagnose") {
36195
36637
  const diagnosis = buildStrategyLiveDiagnosis(input);
36196
- const outputPath = import_node_path33.default.resolve(
36638
+ const outputPath = import_node_path36.default.resolve(
36197
36639
  options.outputPath ?? "output/strategy-live-diagnosis.json"
36198
36640
  );
36199
36641
  await writeJsonAtomic3(outputPath, diagnosis);
36200
36642
  const published2 = options.rootDir ? await publishStrategyLiveDiagnosis({
36201
- rootDir: import_node_path33.default.resolve(options.rootDir),
36643
+ rootDir: import_node_path36.default.resolve(options.rootDir),
36202
36644
  diagnosis,
36203
36645
  sourceArtifacts: input.sourceArtifacts ?? []
36204
36646
  }) : null;
@@ -36215,7 +36657,7 @@ var init_strategyRelease2 = __esm({
36215
36657
  evidence: await collectReleaseEvidenceReferences(input.evidence ?? [])
36216
36658
  });
36217
36659
  const published = await publishStrategyRelease({
36218
- rootDir: import_node_path33.default.resolve(options.rootDir ?? "data/strategy-release"),
36660
+ rootDir: import_node_path36.default.resolve(options.rootDir ?? "data/strategy-release"),
36219
36661
  manifest
36220
36662
  });
36221
36663
  return {
@@ -36275,12 +36717,12 @@ __export(serverHealth_exports, {
36275
36717
  main: () => main45,
36276
36718
  resolveServerHealthThresholds: () => resolveServerHealthThresholds
36277
36719
  });
36278
- var import_config10, import_node_child_process10, import_node_os3, import_node_fs7, import_args34, import_redis20, DEFAULT_STATE, DEFAULT_THRESHOLDS, escapeHtml6, formatPctValue, formatLoadPerCore, formatGiB, formatDuration2, readDiskUsage, parseMeminfoBytes, readMemorySnapshot, runDiagnosticCommand, runDiagnosticCommands, collectServerHealthSnapshot, buildHumanSummaryLines, evaluateServerHealth, shouldRecover, buildAlertMessage, buildRecoveryMessage, buildServerHealthDiagnostics, getStateKey, toFiniteNumber3, resolveServerHealthThresholds, main45;
36720
+ var import_config10, import_node_child_process11, import_node_os3, import_node_fs7, import_args34, import_redis20, DEFAULT_STATE, DEFAULT_THRESHOLDS, escapeHtml6, formatPctValue, formatLoadPerCore, formatGiB, formatDuration2, readDiskUsage, parseMeminfoBytes, readMemorySnapshot, runDiagnosticCommand, runDiagnosticCommands, collectServerHealthSnapshot, buildHumanSummaryLines, evaluateServerHealth, shouldRecover, buildAlertMessage, buildRecoveryMessage, buildServerHealthDiagnostics, getStateKey, toFiniteNumber3, resolveServerHealthThresholds, main45;
36279
36721
  var init_serverHealth = __esm({
36280
36722
  "src/scripts/serverHealth.ts"() {
36281
36723
  "use strict";
36282
36724
  import_config10 = require("dotenv/config");
36283
- import_node_child_process10 = require("child_process");
36725
+ import_node_child_process11 = require("child_process");
36284
36726
  import_node_os3 = __toESM(require("os"));
36285
36727
  import_node_fs7 = require("fs");
36286
36728
  import_args34 = __toESM(require("args"));
@@ -36317,21 +36759,21 @@ var init_serverHealth = __esm({
36317
36759
  }
36318
36760
  return `${minutes}m`;
36319
36761
  };
36320
- readDiskUsage = (path44) => {
36762
+ readDiskUsage = (path47) => {
36321
36763
  try {
36322
- const stats = (0, import_node_fs7.statfsSync)(path44);
36764
+ const stats = (0, import_node_fs7.statfsSync)(path47);
36323
36765
  const totalBlocks = Number(stats.blocks ?? 0);
36324
36766
  const availableBlocks = Number(stats.bavail ?? 0);
36325
36767
  if (totalBlocks <= 0) {
36326
- return { path: path44, usedPct: null };
36768
+ return { path: path47, usedPct: null };
36327
36769
  }
36328
36770
  const usedPct = (totalBlocks - Math.max(0, availableBlocks)) / totalBlocks * 100;
36329
36771
  return {
36330
- path: path44,
36772
+ path: path47,
36331
36773
  usedPct: Number.isFinite(usedPct) ? usedPct : null
36332
36774
  };
36333
36775
  } catch {
36334
- return { path: path44, usedPct: null };
36776
+ return { path: path47, usedPct: null };
36335
36777
  }
36336
36778
  };
36337
36779
  parseMeminfoBytes = (value) => {
@@ -36396,7 +36838,7 @@ var init_serverHealth = __esm({
36396
36838
  }
36397
36839
  };
36398
36840
  runDiagnosticCommand = (command, args39) => {
36399
- const output = (0, import_node_child_process10.execFileSync)(command, args39, {
36841
+ const output = (0, import_node_child_process11.execFileSync)(command, args39, {
36400
36842
  encoding: "utf8",
36401
36843
  timeout: 5e3,
36402
36844
  maxBuffer: 1024 * 1024,
@@ -38083,12 +38525,12 @@ __export(runtimeParity_exports, {
38083
38525
  main: () => main46,
38084
38526
  runtimeParity: () => runtimeParity
38085
38527
  });
38086
- var import_config11, import_node_crypto17, import_args35, import_chalk52, import_constants19, import_time13, import_logger7, import_redis21, import_cli12, import_backtest7, import_connectors15, flags31, interval3, projectRoot16, DEFAULT_LOOKBACK_DAYS, DETAIL_LIMIT2, DEFAULT_REPLAY_ENV, resolveParityConnectorName, createConnector, buildReplayAiAnalyses, formatReplayEnvSummary, buildReplayConfig, warmReplayHistory, runtimeParity, main46;
38528
+ var import_config11, import_node_crypto19, import_args35, import_chalk52, import_constants19, import_time13, import_logger7, import_redis21, import_cli12, import_backtest7, import_connectors15, flags31, interval3, projectRoot16, DEFAULT_LOOKBACK_DAYS, DETAIL_LIMIT2, DEFAULT_REPLAY_ENV, resolveParityConnectorName, createConnector, buildReplayAiAnalyses, formatReplayEnvSummary, buildReplayConfig, warmReplayHistory, runtimeParity, main46;
38087
38529
  var init_runtimeParity2 = __esm({
38088
38530
  "src/scripts/runtimeParity.ts"() {
38089
38531
  "use strict";
38090
38532
  import_config11 = require("dotenv/config");
38091
- import_node_crypto17 = require("crypto");
38533
+ import_node_crypto19 = require("crypto");
38092
38534
  import_args35 = __toESM(require("args"));
38093
38535
  import_chalk52 = __toESM(require("chalk"));
38094
38536
  import_constants19 = require("@tradejs/core/constants");
@@ -38471,9 +38913,9 @@ var init_runtimeParity2 = __esm({
38471
38913
  start: window.start,
38472
38914
  end: window.end
38473
38915
  },
38474
- name: `${target.symbol}_${target.strategy}_${(0, import_node_crypto17.randomUUID)().slice(0, 8)}`,
38475
- testId: (0, import_node_crypto17.randomUUID)().slice(0, 8),
38476
- testSuiteId: (0, import_node_crypto17.randomUUID)().slice(0, 8),
38916
+ name: `${target.symbol}_${target.strategy}_${(0, import_node_crypto19.randomUUID)().slice(0, 8)}`,
38917
+ testId: (0, import_node_crypto19.randomUUID)().slice(0, 8),
38918
+ testSuiteId: (0, import_node_crypto19.randomUUID)().slice(0, 8),
38477
38919
  strategyName: target.strategy,
38478
38920
  strategyConfig: replayConfig,
38479
38921
  connectorName,