@tradejs/cli 3.1.8-beta.213 → 3.1.9-beta.214

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.
@@ -34,9 +34,9 @@ __export(runtimeScorecard_exports, {
34
34
  runtimeScorecard: () => runtimeScorecard
35
35
  });
36
36
  module.exports = __toCommonJS(runtimeScorecard_exports);
37
- var import_promises4 = __toESM(require("fs/promises"));
38
- var import_node_crypto3 = require("crypto");
39
- var import_node_path4 = __toESM(require("path"));
37
+ var import_promises6 = __toESM(require("fs/promises"));
38
+ var import_node_crypto5 = require("crypto");
39
+ var import_node_path6 = __toESM(require("path"));
40
40
  var import_args = __toESM(require("args"));
41
41
  var import_chalk = __toESM(require("chalk"));
42
42
 
@@ -192,6 +192,37 @@ var markRuntimeEvidenceBundleProcessed = async ({
192
192
  return finalPath;
193
193
  };
194
194
 
195
+ // src/lib/runtimeLineage.ts
196
+ var import_node_child_process2 = require("child_process");
197
+ var import_node_crypto3 = require("crypto");
198
+ var import_promises4 = __toESM(require("fs/promises"));
199
+ var import_node_path4 = __toESM(require("path"));
200
+ var import_types = require("@tradejs/types");
201
+ var import_strategies = require("@tradejs/node/strategies");
202
+ var import_strategyReleaseEvidence = require("@tradejs/infra/strategyReleaseEvidence");
203
+
204
+ // src/lib/strategyGateFingerprint.ts
205
+ var import_node_crypto2 = require("crypto");
206
+ var import_node_module = require("module");
207
+ var import_promises3 = __toESM(require("fs/promises"));
208
+ var import_node_path3 = __toESM(require("path"));
209
+
210
+ // src/lib/runtimeLineage.ts
211
+ var runtimeLineageKey = (lineage) => lineage.schemaVersion === 2 ? [
212
+ "v2",
213
+ lineage.version,
214
+ lineage.strategyPackageVersion ?? "strategy:unknown",
215
+ lineage.runtimePackageVersion ?? "runtime:unknown"
216
+ ].join(":") : [
217
+ lineage.schemaVersion,
218
+ lineage.compositionId ?? "unbound-composition",
219
+ lineage.gitSha ?? "unknown",
220
+ lineage.gitDirty == null ? "unknown" : lineage.gitDirty ? "dirty" : "clean",
221
+ lineage.gateFingerprint,
222
+ lineage.configFingerprint,
223
+ lineage.contextFingerprint
224
+ ].join(":");
225
+
195
226
  // src/lib/runtimeScorecard.ts
196
227
  var asRecord2 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
197
228
  var asArray = (value) => Array.isArray(value) ? value : [];
@@ -213,15 +244,32 @@ var extractRuntimeRows = (artifact) => {
213
244
  evaluations: unwrapRows(runtime.evaluations, "evaluation"),
214
245
  signals: unwrapRows(runtime.signals, "signal"),
215
246
  trades: unwrapRows(runtime.trades, "trade"),
247
+ lineageScopes: unwrapRows(runtime.lineageScopes, "lineageScope"),
216
248
  statsBuckets: asArray(runtime.evaluationStatsBuckets).map(asRecord2).filter((item) => item != null)
217
249
  };
218
250
  };
219
251
  var buildRuntimeLineageSummary = (rows) => {
220
- const lineageRows = [...rows.evaluations, ...rows.signals, ...rows.trades];
252
+ const lineageRows = [
253
+ ...rows.evaluations,
254
+ ...rows.signals,
255
+ ...rows.trades,
256
+ ...rows.lineageScopes.map((scope) => ({
257
+ runtimeLineage: scope.lineage
258
+ }))
259
+ ];
221
260
  const lineages = lineageRows.map((row) => asRecord2(row.runtimeLineage)).filter((lineage) => lineage != null);
222
261
  const identities = /* @__PURE__ */ new Map();
223
262
  for (const lineage of lineages) {
224
- const identity2 = {
263
+ const identity2 = lineage.schemaVersion === 2 ? {
264
+ schemaVersion: 2,
265
+ version: finiteNumber(lineage.version),
266
+ strategyPackageVersion: finiteString(
267
+ lineage.strategyPackageVersion
268
+ ),
269
+ runtimePackageVersion: finiteString(lineage.runtimePackageVersion),
270
+ maxLossValue: finiteNumber(lineage.maxLossValue)
271
+ } : {
272
+ schemaVersion: 1,
225
273
  compositionId: finiteString(lineage.compositionId),
226
274
  gitSha: finiteString(lineage.gitSha),
227
275
  gitDirty: typeof lineage.gitDirty === "boolean" ? lineage.gitDirty : null,
@@ -233,12 +281,23 @@ var buildRuntimeLineageSummary = (rows) => {
233
281
  identities.set(JSON.stringify(identity2), identity2);
234
282
  }
235
283
  const identity = identities.size === 1 ? [...identities.values()][0] : null;
236
- const complete = lineageRows.length > 0 && lineages.length === lineageRows.length && identity != null && identity.compositionId != null && identity.gitSha != null && identity.gitDirty === false && identity.gateFingerprint != null && identity.configFingerprint != null && identity.contextFingerprint != null && identity.maxLossValue != null;
284
+ const schemaVersion = finiteNumber(identity?.schemaVersion);
285
+ const identityComplete = lineages.length > 0 && identity != null && (schemaVersion === 2 && finiteNumber(identity.version) != null && finiteString(identity.strategyPackageVersion) != null && finiteString(identity.runtimePackageVersion) != null || schemaVersion === 1 && identity.compositionId != null && identity.gitSha != null && identity.gitDirty === false && identity.gateFingerprint != null && identity.configFingerprint != null && identity.contextFingerprint != null) && identity.maxLossValue != null;
286
+ const coverageComplete = lineageRows.length > 0 && lineages.length === lineageRows.length;
287
+ const complete = identityComplete && coverageComplete;
288
+ const lineageKey = identityComplete ? runtimeLineageKey(identity) : null;
237
289
  return {
238
290
  complete,
291
+ identityComplete,
292
+ coverageComplete,
239
293
  conflicts: identities.size > 1,
240
294
  rows: lineageRows.length,
241
295
  rowsWithLineage: lineages.length,
296
+ schemaVersion,
297
+ lineageKey,
298
+ version: finiteNumber(identity?.version),
299
+ strategyPackageVersion: finiteString(identity?.strategyPackageVersion),
300
+ runtimePackageVersion: finiteString(identity?.runtimePackageVersion),
242
301
  compositionId: finiteString(identity?.compositionId),
243
302
  gitSha: finiteString(identity?.gitSha),
244
303
  gitDirty: typeof identity?.gitDirty === "boolean" ? identity.gitDirty : null,
@@ -248,6 +307,20 @@ var buildRuntimeLineageSummary = (rows) => {
248
307
  maxLossValue: finiteNumber(identity?.maxLossValue)
249
308
  };
250
309
  };
310
+ var belongsToRuntimeLineage = (row, summary) => {
311
+ if (!summary.identityComplete || !summary.lineageKey) return false;
312
+ const lineage = asRecord2(row.runtimeLineage);
313
+ if (!lineage) return false;
314
+ return runtimeLineageKey(lineage) === summary.lineageKey && finiteNumber(lineage.maxLossValue) === summary.maxLossValue;
315
+ };
316
+ var runtimeDeploymentBinding = (artifact) => {
317
+ const deployment = asRecord2(asRecord2(artifact)?.deployment);
318
+ return {
319
+ deploymentId: finiteString(deployment?.id),
320
+ accountId: finiteString(deployment?.accountId)
321
+ };
322
+ };
323
+ var belongsToRuntimeDeployment = (row, binding) => binding.deploymentId == null && binding.accountId == null ? true : finiteString(row.deploymentId) === binding.deploymentId && finiteString(row.accountId) === binding.accountId;
251
324
  var belongsToStrategy = (row, strategy) => strategy == null || finiteString(row.strategy) === strategy;
252
325
  var filterArtifactByStrategy = (artifact, strategy) => {
253
326
  if (!strategy) return artifact;
@@ -275,6 +348,9 @@ var filterArtifactByStrategy = (artifact, strategy) => {
275
348
  strategy
276
349
  )
277
350
  ),
351
+ lineageScopes: asArray(runtime.lineageScopes).filter(
352
+ (item) => belongsToStrategy(asRecord2(item) ?? {}, strategy)
353
+ ),
278
354
  evaluationStatsBuckets: asArray(runtime.evaluationStatsBuckets).filter(
279
355
  (item) => belongsToStrategy(asRecord2(item) ?? {}, strategy)
280
356
  )
@@ -454,6 +530,7 @@ var buildRuntimeScorecard = ({
454
530
  const scopedHistoryArtifacts = historyRuntimeArtifacts.map(
455
531
  (artifact) => filterArtifactByStrategy(artifact, strategy)
456
532
  );
533
+ const deploymentBinding = runtimeDeploymentBinding(runtimeArtifact);
457
534
  const rows = extractRuntimeRows(scopedRuntimeArtifact);
458
535
  const runtimeLineage = buildRuntimeLineageSummary(rows);
459
536
  const window = runtimeWindow(runtimeArtifact);
@@ -516,6 +593,12 @@ var buildRuntimeScorecard = ({
516
593
  ...scopedHistoryArtifacts,
517
594
  scopedRuntimeArtifact
518
595
  ]);
596
+ const comparableHistoryTrades = historyTrades.filter(
597
+ (trade) => belongsToRuntimeDeployment(trade, deploymentBinding) && belongsToRuntimeLineage(trade, runtimeLineage)
598
+ );
599
+ const comparableCurrentClosedTrades = currentClosedTrades.filter(
600
+ (trade) => belongsToRuntimeDeployment(trade, deploymentBinding) && belongsToRuntimeLineage(trade, runtimeLineage)
601
+ );
519
602
  const currentDistributions = buildDistributions(rows);
520
603
  const previousArtifact = scopedHistoryArtifacts.map((artifact) => ({ artifact, window: runtimeWindow(artifact) })).filter(({ window: candidateWindow }) => {
521
604
  const candidateEndTime = finiteNumber(candidateWindow.endTime);
@@ -526,7 +609,7 @@ var buildRuntimeScorecard = ({
526
609
  const previousDistributions = previousArtifact ? buildDistributions(extractRuntimeRows(previousArtifact.artifact)) : null;
527
610
  const rolling = [7, 30, 90].map(
528
611
  (days) => buildRollingPerformance({
529
- trades: [...historyTrades],
612
+ trades: [...comparableHistoryTrades],
530
613
  anchorTime: endTime,
531
614
  days
532
615
  })
@@ -540,6 +623,13 @@ var buildRuntimeScorecard = ({
540
623
  message: lineageReason
541
624
  });
542
625
  }
626
+ if (!runtimeLineage.complete) {
627
+ reactions.push({
628
+ code: "RUNTIME_LINEAGE_INCOMPLETE",
629
+ severity: "blocking",
630
+ message: "Runtime rows do not share one complete composition lineage."
631
+ });
632
+ }
543
633
  if (parityRatio != null && parityRatio < thresholds.minimumParityRatio) {
544
634
  reactions.push({
545
635
  code: "PARITY_REGRESSION",
@@ -577,6 +667,7 @@ var buildRuntimeScorecard = ({
577
667
  generatedAt,
578
668
  window: { startTime, endTime },
579
669
  strategy,
670
+ deployment: deploymentBinding,
580
671
  lineage: runtimeLineage,
581
672
  promotionStatus,
582
673
  thresholds,
@@ -621,17 +712,25 @@ var buildRuntimeScorecard = ({
621
712
  )
622
713
  ).length,
623
714
  fills: rows.trades.length,
624
- closedTrades: currentClosedTrades.length
715
+ closedTrades: currentClosedTrades.length,
716
+ comparableClosedTrades: comparableCurrentClosedTrades.length,
717
+ nonComparableClosedTrades: currentClosedTrades.length - comparableCurrentClosedTrades.length
625
718
  },
626
719
  realized: {
627
720
  pnl: sum(
628
- currentClosedTrades.map((trade) => finiteNumber(trade.closedPnl))
721
+ comparableCurrentClosedTrades.map(
722
+ (trade) => finiteNumber(trade.closedPnl)
723
+ )
629
724
  ),
630
725
  fees: sum(
631
- currentClosedTrades.map((trade) => finiteNumber(trade.totalFee))
726
+ comparableCurrentClosedTrades.map(
727
+ (trade) => finiteNumber(trade.totalFee)
728
+ )
632
729
  ),
633
730
  funding: sum(
634
- currentClosedTrades.map((trade) => finiteNumber(trade.fundingFee))
731
+ comparableCurrentClosedTrades.map(
732
+ (trade) => finiteNumber(trade.fundingFee)
733
+ )
635
734
  )
636
735
  },
637
736
  gateComparison: {
@@ -749,14 +848,14 @@ ${reactions}
749
848
  };
750
849
 
751
850
  // src/lib/strategyRelease.ts
752
- var import_node_crypto2 = require("crypto");
753
- var import_promises3 = __toESM(require("fs/promises"));
754
- var import_node_path3 = __toESM(require("path"));
755
- var import_types2 = require("@tradejs/types");
756
- var import_strategyReleaseEvidence = require("@tradejs/infra/strategyReleaseEvidence");
851
+ var import_node_crypto4 = require("crypto");
852
+ var import_promises5 = __toESM(require("fs/promises"));
853
+ var import_node_path5 = __toESM(require("path"));
854
+ var import_types3 = require("@tradejs/types");
855
+ var import_strategyReleaseEvidence2 = require("@tradejs/infra/strategyReleaseEvidence");
757
856
 
758
857
  // src/lib/strategyRelease/liveDiagnosis.ts
759
- var import_types = require("@tradejs/types");
858
+ var import_types2 = require("@tradejs/types");
760
859
  var buildStrategyLiveDiagnosis = (input) => {
761
860
  const minimumClosedTrades = input.minimumClosedTrades ?? 20;
762
861
  const minimumParityRatio = input.minimumParityRatio ?? 0.95;
@@ -784,7 +883,7 @@ var buildStrategyLiveDiagnosis = (input) => {
784
883
  attributionIncomplete && verdict === "GENERALIZATION_FAILURE" ? "Collect matched shadow raw-core, deterministic-gate, and causal regime evidence without changing the composition." : "Collect more verified prospective outcomes without changing the composition."
785
884
  ];
786
885
  return {
787
- schema: import_types.STRATEGY_LIVE_DIAGNOSIS_SCHEMA,
886
+ schema: import_types2.STRATEGY_LIVE_DIAGNOSIS_SCHEMA,
788
887
  strategy: input.strategy,
789
888
  compositionId: input.compositionId,
790
889
  createdAt: input.createdAt,
@@ -861,10 +960,10 @@ var buildStrategyLiveDiagnosisFromScorecard = ({
861
960
  // src/lib/strategyRelease.ts
862
961
  var SHA256_RE = /^[a-f0-9]{64}$/;
863
962
  var LINEAGE_FINGERPRINT_RE = /^[a-f0-9]{16}$/;
864
- var safeSegment2 = import_strategyReleaseEvidence.safeStrategyEvidenceSegment;
865
- var compactTimestamp = import_strategyReleaseEvidence.compactStrategyEvidenceTimestamp;
866
- var canonicalStrategyReleaseJson = (value) => (0, import_strategyReleaseEvidence.canonicalStrategyEvidenceJson)(value);
867
- var strategyReleaseSha256 = (value) => (0, import_strategyReleaseEvidence.strategyEvidenceSha256)(value);
963
+ var safeSegment2 = import_strategyReleaseEvidence2.safeStrategyEvidenceSegment;
964
+ var compactTimestamp = import_strategyReleaseEvidence2.compactStrategyEvidenceTimestamp;
965
+ var canonicalStrategyReleaseJson = (value) => (0, import_strategyReleaseEvidence2.canonicalStrategyEvidenceJson)(value);
966
+ var strategyReleaseSha256 = (value) => (0, import_strategyReleaseEvidence2.strategyEvidenceSha256)(value);
868
967
  function assert(condition, message) {
869
968
  if (!condition) throw new Error(`Invalid strategy release: ${message}`);
870
969
  }
@@ -1233,7 +1332,7 @@ var createStrategyReleaseManifest = (input) => {
1233
1332
  verdict
1234
1333
  };
1235
1334
  return {
1236
- schema: import_types2.STRATEGY_RELEASE_SCHEMA,
1335
+ schema: import_types3.STRATEGY_RELEASE_SCHEMA,
1237
1336
  releaseId: `${safeSegment2(input.strategy, "strategy")}_${compactTimestamp(input.createdAt)}_${strategyReleaseSha256(releaseIdentity).slice(0, 16)}`,
1238
1337
  strategy: input.strategy,
1239
1338
  createdAt: input.createdAt,
@@ -1252,7 +1351,7 @@ var createStrategyReleaseManifest = (input) => {
1252
1351
  };
1253
1352
  };
1254
1353
  var verifyStrategyReleaseEnvelope = async (valueOrPath) => {
1255
- const value = typeof valueOrPath === "string" ? JSON.parse(await import_promises3.default.readFile(valueOrPath, "utf8")) : valueOrPath;
1354
+ const value = typeof valueOrPath === "string" ? JSON.parse(await import_promises5.default.readFile(valueOrPath, "utf8")) : valueOrPath;
1256
1355
  const envelope = value;
1257
1356
  assert(
1258
1357
  envelope?.schema === "tradejs-strategy-release-envelope/v1",
@@ -1268,7 +1367,7 @@ var verifyStrategyReleaseEnvelope = async (valueOrPath) => {
1268
1367
  );
1269
1368
  const manifest = envelope.manifest;
1270
1369
  assert(
1271
- manifest.schema === import_types2.STRATEGY_RELEASE_SCHEMA,
1370
+ manifest.schema === import_types3.STRATEGY_RELEASE_SCHEMA,
1272
1371
  "manifest schema mismatch"
1273
1372
  );
1274
1373
  const rebuilt = createStrategyReleaseManifest({
@@ -1303,19 +1402,19 @@ var verifyStrategyReleaseEnvelope = async (valueOrPath) => {
1303
1402
  return envelope;
1304
1403
  };
1305
1404
  var verifyStrategyEvidenceMarkerEnvelope = async (valueOrPath) => {
1306
- const value = typeof valueOrPath === "string" ? JSON.parse(await import_promises3.default.readFile(valueOrPath, "utf8")) : valueOrPath;
1307
- return (0, import_strategyReleaseEvidence.verifyStrategyEvidenceMarkerEnvelope)(value);
1405
+ const value = typeof valueOrPath === "string" ? JSON.parse(await import_promises5.default.readFile(valueOrPath, "utf8")) : valueOrPath;
1406
+ return (0, import_strategyReleaseEvidence2.verifyStrategyEvidenceMarkerEnvelope)(value);
1308
1407
  };
1309
1408
  var writeJsonAtomic = async (filePath, value) => {
1310
1409
  const temporaryPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
1311
- await import_promises3.default.mkdir(import_node_path3.default.dirname(filePath), { recursive: true });
1312
- await import_promises3.default.writeFile(
1410
+ await import_promises5.default.mkdir(import_node_path5.default.dirname(filePath), { recursive: true });
1411
+ await import_promises5.default.writeFile(
1313
1412
  temporaryPath,
1314
1413
  `${canonicalStrategyReleaseJson(value)}
1315
1414
  `,
1316
1415
  "utf8"
1317
1416
  );
1318
- await import_promises3.default.rename(temporaryPath, filePath);
1417
+ await import_promises5.default.rename(temporaryPath, filePath);
1319
1418
  };
1320
1419
  var publishStrategyLiveDiagnosis = async ({
1321
1420
  rootDir,
@@ -1375,19 +1474,19 @@ var publishStrategyLiveDiagnosis = async ({
1375
1474
  severity: diagnosis.verdict === "EXPECTED_DRAWDOWN" ? "info" : "warning"
1376
1475
  }
1377
1476
  ];
1378
- const markerEnvelope = (0, import_strategyReleaseEvidence.createStrategyEvidenceMarkerEnvelope)({
1477
+ const markerEnvelope = (0, import_strategyReleaseEvidence2.createStrategyEvidenceMarkerEnvelope)({
1379
1478
  strategy: diagnosis.strategy,
1380
1479
  createdAt: diagnosis.createdAt,
1381
1480
  markers,
1382
1481
  sourceArtifacts
1383
1482
  });
1384
- const diagnosisPath = import_node_path3.default.join(
1483
+ const diagnosisPath = import_node_path5.default.join(
1385
1484
  rootDir,
1386
1485
  "diagnoses",
1387
1486
  safeSegment2(diagnosis.strategy, "strategy"),
1388
1487
  `${diagnosisId}.json`
1389
1488
  );
1390
- const markerPath = import_node_path3.default.join(
1489
+ const markerPath = import_node_path5.default.join(
1391
1490
  rootDir,
1392
1491
  "markers",
1393
1492
  safeSegment2(diagnosis.strategy, "strategy"),
@@ -1459,15 +1558,15 @@ var flags = import_args.default.parse(process.argv);
1459
1558
  var projectRoot = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
1460
1559
  var resolveOptionalPath = (value) => {
1461
1560
  const raw = String(value ?? "").trim();
1462
- return raw ? import_node_path4.default.resolve(projectRoot, raw) : null;
1561
+ return raw ? import_node_path6.default.resolve(projectRoot, raw) : null;
1463
1562
  };
1464
- var readJson = async (filePath) => filePath ? JSON.parse(await import_promises4.default.readFile(filePath, "utf8")) : void 0;
1563
+ var readJson = async (filePath) => filePath ? JSON.parse(await import_promises6.default.readFile(filePath, "utf8")) : void 0;
1465
1564
  var assertReportType = (artifact, expected, label) => {
1466
1565
  if (artifact != null && (!artifact || typeof artifact !== "object" || Array.isArray(artifact) || artifact.reportType !== expected)) {
1467
1566
  throw new Error(`${label} must be a ${expected} artifact`);
1468
1567
  }
1469
1568
  };
1470
- var sha256File = async (filePath) => (0, import_node_crypto3.createHash)("sha256").update(await import_promises4.default.readFile(filePath)).digest("hex");
1569
+ var sha256File = async (filePath) => (0, import_node_crypto5.createHash)("sha256").update(await import_promises6.default.readFile(filePath)).digest("hex");
1471
1570
  var loadHistoryArtifacts = async (historyDir) => {
1472
1571
  if (!historyDir) return [];
1473
1572
  const bundleDirs = await discoverRuntimeEvidenceBundles(historyDir);
@@ -1537,13 +1636,13 @@ var runtimeScorecard = async () => {
1537
1636
  strategy: scorecardStrategy,
1538
1637
  llmComparatorPolicy: verifiedRelease?.manifest.prospective.llmComparatorPolicy ?? "ai_approved_only"
1539
1638
  });
1540
- const outPath = import_node_path4.default.resolve(projectRoot, String(flags.out));
1639
+ const outPath = import_node_path6.default.resolve(projectRoot, String(flags.out));
1541
1640
  const markdownPath = outPath.replace(/\.json$/i, "") + ".md";
1542
- await import_promises4.default.mkdir(import_node_path4.default.dirname(outPath), { recursive: true });
1641
+ await import_promises6.default.mkdir(import_node_path6.default.dirname(outPath), { recursive: true });
1543
1642
  await Promise.all([
1544
- import_promises4.default.writeFile(outPath, `${JSON.stringify(scorecard, null, 2)}
1643
+ import_promises6.default.writeFile(outPath, `${JSON.stringify(scorecard, null, 2)}
1545
1644
  `, "utf8"),
1546
- import_promises4.default.writeFile(
1645
+ import_promises6.default.writeFile(
1547
1646
  markdownPath,
1548
1647
  formatRuntimeScorecardMarkdown(scorecard),
1549
1648
  "utf8"
@@ -1557,7 +1656,7 @@ var runtimeScorecard = async () => {
1557
1656
  const diagnosisPath = diagnosis ? outPath.replace(/\.json$/i, "") + ".diagnosis.json" : null;
1558
1657
  const strategyReleaseRoot = resolveOptionalPath(flags.strategyReleaseRoot);
1559
1658
  if (diagnosis && diagnosisPath) {
1560
- await import_promises4.default.writeFile(
1659
+ await import_promises6.default.writeFile(
1561
1660
  diagnosisPath,
1562
1661
  `${JSON.stringify(diagnosis, null, 2)}
1563
1662
  `,
@@ -1578,7 +1677,7 @@ var runtimeScorecard = async () => {
1578
1677
  composition: verifiedRelease?.manifest.composition,
1579
1678
  sourceArtifacts: await Promise.all(
1580
1679
  sourcePaths.map(async (sourcePath) => ({
1581
- artifactId: import_node_path4.default.basename(sourcePath),
1680
+ artifactId: import_node_path6.default.basename(sourcePath),
1582
1681
  path: sourcePath,
1583
1682
  sha256: await sha256File(sourcePath)
1584
1683
  }))
@@ -1589,9 +1688,9 @@ var runtimeScorecard = async () => {
1589
1688
  let receiptPath2 = null;
1590
1689
  if (flags.markProcessed) {
1591
1690
  receiptPath2 = await markRuntimeEvidenceBundleProcessed({
1592
- evidenceRoot: import_node_path4.default.resolve(projectRoot, String(flags.evidenceDir)),
1691
+ evidenceRoot: import_node_path6.default.resolve(projectRoot, String(flags.evidenceDir)),
1593
1692
  deploymentId: String(flags.deployment),
1594
- bundleDir: import_node_path4.default.dirname(runtimeEvidencePath),
1693
+ bundleDir: import_node_path6.default.dirname(runtimeEvidencePath),
1595
1694
  scorecardPath: outPath
1596
1695
  });
1597
1696
  }
@@ -4191,7 +4191,12 @@ async function buildRuntimeLineage({
4191
4191
  maxLossValue: resolveRuntimeMaxLossValue(config2)
4192
4192
  };
4193
4193
  }
4194
- var runtimeLineageKey = (lineage) => lineage.schemaVersion === 2 ? ["v2", lineage.version].join(":") : [
4194
+ var runtimeLineageKey = (lineage) => lineage.schemaVersion === 2 ? [
4195
+ "v2",
4196
+ lineage.version,
4197
+ lineage.strategyPackageVersion ?? "strategy:unknown",
4198
+ lineage.runtimePackageVersion ?? "runtime:unknown"
4199
+ ].join(":") : [
4195
4200
  lineage.schemaVersion,
4196
4201
  lineage.compositionId ?? "unbound-composition",
4197
4202
  lineage.gitSha ?? "unknown",
@@ -4210,9 +4215,28 @@ var buildRuntimeSignalEvaluationId = ({
4210
4215
  symbol,
4211
4216
  timestamp,
4212
4217
  runtimeConfigId,
4213
- runtimeVersion
4214
- }) => runtimeVersion ? [strategyName, `v${runtimeVersion}`, symbol, timestamp].join(":") : runtimeConfigId && runtimeConfigId !== "config" ? [strategyName, runtimeConfigId, symbol, timestamp].join(":") : [strategyName, symbol, timestamp].join(":");
4218
+ runtimeVersion,
4219
+ deploymentId,
4220
+ accountId
4221
+ }) => {
4222
+ const runtimeScope = deploymentId ? [deploymentId, accountId ?? "default-account"] : [];
4223
+ return runtimeVersion ? [
4224
+ ...runtimeScope,
4225
+ strategyName,
4226
+ `v${runtimeVersion}`,
4227
+ symbol,
4228
+ timestamp
4229
+ ].join(":") : runtimeConfigId && runtimeConfigId !== "config" ? [
4230
+ ...runtimeScope,
4231
+ strategyName,
4232
+ runtimeConfigId,
4233
+ symbol,
4234
+ timestamp
4235
+ ].join(":") : [...runtimeScope, strategyName, symbol, timestamp].join(":");
4236
+ };
4215
4237
  var buildLineageField = (scope) => [
4238
+ scope.deploymentId ?? "default-deployment",
4239
+ scope.accountId ?? "default-account",
4216
4240
  scope.strategy,
4217
4241
  scope.runtimeConfigId ?? "config",
4218
4242
  scope.runtimeVersion ? `v${scope.runtimeVersion}` : "legacy",
@@ -4254,6 +4278,8 @@ var flushRuntimeSignalEvaluations = async (evaluations) => {
4254
4278
  for (const evaluation of lineageEvaluations) {
4255
4279
  const lineageField = buildLineageField({
4256
4280
  strategy: evaluation.strategy,
4281
+ deploymentId: evaluation.deploymentId,
4282
+ accountId: evaluation.accountId,
4257
4283
  runtimeConfigId: evaluation.runtimeConfigId,
4258
4284
  runtimeVersion: evaluation.runtimeVersion,
4259
4285
  symbol: evaluation.symbol,
@@ -4264,6 +4290,8 @@ var flushRuntimeSignalEvaluations = async (evaluations) => {
4264
4290
  const scope = {
4265
4291
  strategy: evaluation.strategy,
4266
4292
  symbol: evaluation.symbol,
4293
+ ...evaluation.deploymentId ? { deploymentId: evaluation.deploymentId } : {},
4294
+ ...evaluation.accountId ? { accountId: evaluation.accountId } : {},
4267
4295
  runtimeConfigId: evaluation.runtimeConfigId,
4268
4296
  runtimeVersion: evaluation.runtimeVersion,
4269
4297
  lineage: evaluation.runtimeLineage,
@@ -4307,7 +4335,8 @@ var flushRuntimeSignalEvaluations = async (evaluations) => {
4307
4335
  const statsBucket = import_redis.redisKeys.runtimeSignalEvaluationStatsBucket(
4308
4336
  evaluation.userName,
4309
4337
  dayKey,
4310
- evaluation.strategy
4338
+ evaluation.strategy,
4339
+ evaluation.deploymentId
4311
4340
  );
4312
4341
  const increments = statsIncrements.get(statsBucket) ?? {};
4313
4342
  for (const [field, increment] of Object.entries(
@@ -4920,7 +4949,9 @@ var createSignalsTickerEvaluator = ({
4920
4949
  symbol,
4921
4950
  timestamp: lastCandle.timestamp,
4922
4951
  runtimeConfigId: runtimeIdentity,
4923
- runtimeVersion: version
4952
+ runtimeVersion: version,
4953
+ deploymentId,
4954
+ accountId
4924
4955
  }),
4925
4956
  userName,
4926
4957
  strategy: strategyName,
@@ -4945,8 +4976,14 @@ var createSignalsTickerEvaluator = ({
4945
4976
  signal.runtimeConfigId = runtimeIdentity;
4946
4977
  signal.runtimeVersion = version;
4947
4978
  signal.runtimeLineage = runtimeLineage;
4948
- if (version && !signal.signalId.endsWith(`:v${version}`)) {
4949
- signal.signalId = `${signal.signalId}:v${version}`;
4979
+ signal.deploymentId = deploymentId;
4980
+ signal.accountId = accountId;
4981
+ const signalRuntimeIdentity = [
4982
+ ...deploymentId ? [deploymentId, accountId ?? "default-account"] : [],
4983
+ ...version ? [`v${version}`] : []
4984
+ ].join(":");
4985
+ if (signalRuntimeIdentity && !signal.signalId.endsWith(`:${signalRuntimeIdentity}`)) {
4986
+ signal.signalId = `${signal.signalId}:${signalRuntimeIdentity}`;
4950
4987
  }
4951
4988
  await (0, import_strategies4.enrichSignalWithBinanceMarketContext)({ signal, env: "CRON" });
4952
4989
  if (signal.orderStatus === "skipped" && typeof signal.orderSkipReason === "string" && signal.orderSkipReason.trim()) {
@@ -4965,7 +5002,9 @@ var createSignalsTickerEvaluator = ({
4965
5002
  symbol,
4966
5003
  timestamp: lastCandle.timestamp,
4967
5004
  runtimeConfigId: runtimeIdentity,
4968
- runtimeVersion: version
5005
+ runtimeVersion: version,
5006
+ deploymentId,
5007
+ accountId
4969
5008
  }),
4970
5009
  userName,
4971
5010
  strategy: strategyName,
@@ -4189,7 +4189,12 @@ async function buildRuntimeLineage({
4189
4189
  maxLossValue: resolveRuntimeMaxLossValue(config2)
4190
4190
  };
4191
4191
  }
4192
- var runtimeLineageKey = (lineage) => lineage.schemaVersion === 2 ? ["v2", lineage.version].join(":") : [
4192
+ var runtimeLineageKey = (lineage) => lineage.schemaVersion === 2 ? [
4193
+ "v2",
4194
+ lineage.version,
4195
+ lineage.strategyPackageVersion ?? "strategy:unknown",
4196
+ lineage.runtimePackageVersion ?? "runtime:unknown"
4197
+ ].join(":") : [
4193
4198
  lineage.schemaVersion,
4194
4199
  lineage.compositionId ?? "unbound-composition",
4195
4200
  lineage.gitSha ?? "unknown",
@@ -4208,9 +4213,28 @@ var buildRuntimeSignalEvaluationId = ({
4208
4213
  symbol,
4209
4214
  timestamp,
4210
4215
  runtimeConfigId,
4211
- runtimeVersion
4212
- }) => runtimeVersion ? [strategyName, `v${runtimeVersion}`, symbol, timestamp].join(":") : runtimeConfigId && runtimeConfigId !== "config" ? [strategyName, runtimeConfigId, symbol, timestamp].join(":") : [strategyName, symbol, timestamp].join(":");
4216
+ runtimeVersion,
4217
+ deploymentId,
4218
+ accountId
4219
+ }) => {
4220
+ const runtimeScope = deploymentId ? [deploymentId, accountId ?? "default-account"] : [];
4221
+ return runtimeVersion ? [
4222
+ ...runtimeScope,
4223
+ strategyName,
4224
+ `v${runtimeVersion}`,
4225
+ symbol,
4226
+ timestamp
4227
+ ].join(":") : runtimeConfigId && runtimeConfigId !== "config" ? [
4228
+ ...runtimeScope,
4229
+ strategyName,
4230
+ runtimeConfigId,
4231
+ symbol,
4232
+ timestamp
4233
+ ].join(":") : [...runtimeScope, strategyName, symbol, timestamp].join(":");
4234
+ };
4213
4235
  var buildLineageField = (scope) => [
4236
+ scope.deploymentId ?? "default-deployment",
4237
+ scope.accountId ?? "default-account",
4214
4238
  scope.strategy,
4215
4239
  scope.runtimeConfigId ?? "config",
4216
4240
  scope.runtimeVersion ? `v${scope.runtimeVersion}` : "legacy",
@@ -4252,6 +4276,8 @@ var flushRuntimeSignalEvaluations = async (evaluations) => {
4252
4276
  for (const evaluation of lineageEvaluations) {
4253
4277
  const lineageField = buildLineageField({
4254
4278
  strategy: evaluation.strategy,
4279
+ deploymentId: evaluation.deploymentId,
4280
+ accountId: evaluation.accountId,
4255
4281
  runtimeConfigId: evaluation.runtimeConfigId,
4256
4282
  runtimeVersion: evaluation.runtimeVersion,
4257
4283
  symbol: evaluation.symbol,
@@ -4262,6 +4288,8 @@ var flushRuntimeSignalEvaluations = async (evaluations) => {
4262
4288
  const scope = {
4263
4289
  strategy: evaluation.strategy,
4264
4290
  symbol: evaluation.symbol,
4291
+ ...evaluation.deploymentId ? { deploymentId: evaluation.deploymentId } : {},
4292
+ ...evaluation.accountId ? { accountId: evaluation.accountId } : {},
4265
4293
  runtimeConfigId: evaluation.runtimeConfigId,
4266
4294
  runtimeVersion: evaluation.runtimeVersion,
4267
4295
  lineage: evaluation.runtimeLineage,
@@ -4305,7 +4333,8 @@ var flushRuntimeSignalEvaluations = async (evaluations) => {
4305
4333
  const statsBucket = import_redis.redisKeys.runtimeSignalEvaluationStatsBucket(
4306
4334
  evaluation.userName,
4307
4335
  dayKey,
4308
- evaluation.strategy
4336
+ evaluation.strategy,
4337
+ evaluation.deploymentId
4309
4338
  );
4310
4339
  const increments = statsIncrements.get(statsBucket) ?? {};
4311
4340
  for (const [field, increment] of Object.entries(
@@ -4918,7 +4947,9 @@ var createSignalsTickerEvaluator = ({
4918
4947
  symbol,
4919
4948
  timestamp: lastCandle.timestamp,
4920
4949
  runtimeConfigId: runtimeIdentity,
4921
- runtimeVersion: version
4950
+ runtimeVersion: version,
4951
+ deploymentId,
4952
+ accountId
4922
4953
  }),
4923
4954
  userName,
4924
4955
  strategy: strategyName,
@@ -4943,8 +4974,14 @@ var createSignalsTickerEvaluator = ({
4943
4974
  signal.runtimeConfigId = runtimeIdentity;
4944
4975
  signal.runtimeVersion = version;
4945
4976
  signal.runtimeLineage = runtimeLineage;
4946
- if (version && !signal.signalId.endsWith(`:v${version}`)) {
4947
- signal.signalId = `${signal.signalId}:v${version}`;
4977
+ signal.deploymentId = deploymentId;
4978
+ signal.accountId = accountId;
4979
+ const signalRuntimeIdentity = [
4980
+ ...deploymentId ? [deploymentId, accountId ?? "default-account"] : [],
4981
+ ...version ? [`v${version}`] : []
4982
+ ].join(":");
4983
+ if (signalRuntimeIdentity && !signal.signalId.endsWith(`:${signalRuntimeIdentity}`)) {
4984
+ signal.signalId = `${signal.signalId}:${signalRuntimeIdentity}`;
4948
4985
  }
4949
4986
  await (0, import_strategies4.enrichSignalWithBinanceMarketContext)({ signal, env: "CRON" });
4950
4987
  if (signal.orderStatus === "skipped" && typeof signal.orderSkipReason === "string" && signal.orderSkipReason.trim()) {
@@ -4963,7 +5000,9 @@ var createSignalsTickerEvaluator = ({
4963
5000
  symbol,
4964
5001
  timestamp: lastCandle.timestamp,
4965
5002
  runtimeConfigId: runtimeIdentity,
4966
- runtimeVersion: version
5003
+ runtimeVersion: version,
5004
+ deploymentId,
5005
+ accountId
4967
5006
  }),
4968
5007
  userName,
4969
5008
  strategy: strategyName,
@@ -532,13 +532,17 @@ var parseBucketKey = (prefix, key) => {
532
532
  return null;
533
533
  }
534
534
  const suffix = key.slice(prefix.length);
535
- const firstColon = suffix.indexOf(":");
536
- if (firstColon <= 0 || firstColon >= suffix.length - 1) {
535
+ const parts = suffix.split(":");
536
+ if (parts.length < 2 || parts.some((part) => !part)) {
537
537
  return null;
538
538
  }
539
+ const [dayKey, ...scopeParts] = parts;
540
+ const strategy = scopeParts.at(-1);
541
+ if (!dayKey || !strategy) return null;
539
542
  return {
540
- dayKey: suffix.slice(0, firstColon),
541
- strategy: suffix.slice(firstColon + 1)
543
+ dayKey,
544
+ ...scopeParts.length > 1 ? { deploymentId: scopeParts.slice(0, -1).join(":") } : {},
545
+ strategy
542
546
  };
543
547
  };
544
548
  var loadRuntimeSignalEvaluationStatsBuckets = async (userName) => {
@@ -598,7 +602,8 @@ var buildRuntimeDebugReportPayload = async ({
598
602
  evaluations,
599
603
  trades,
600
604
  strategyConfigs,
601
- evaluationStatsBuckets
605
+ evaluationStatsBuckets,
606
+ lineageScopes
602
607
  }) => {
603
608
  const signalById = new Map(
604
609
  signals.map((signal) => [signal.signalId, signal])
@@ -726,6 +731,7 @@ var buildRuntimeDebugReportPayload = async ({
726
731
  signals: signals.length,
727
732
  evaluations: reportEvaluations.length,
728
733
  evaluationStatsBuckets: evaluationStatsBuckets?.length ?? 0,
734
+ lineageScopes: lineageScopes?.length ?? 0,
729
735
  strategyConfigs: strategyConfigs?.length ?? 0
730
736
  },
731
737
  trades: debugTrades,
@@ -749,6 +755,7 @@ var buildRuntimeDebugReportPayload = async ({
749
755
  evaluation
750
756
  })),
751
757
  evaluationStatsBuckets: evaluationStatsBuckets ?? [],
758
+ lineageScopes: lineageScopes ?? [],
752
759
  strategyConfigs: strategyConfigs ?? []
753
760
  };
754
761
  };