@tradejs/cli 3.1.21-beta.237 → 3.1.22-beta.238

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_crypto4 = require("crypto");
39
- var import_node_path4 = __toESM(require("path"));
37
+ var import_promises6 = __toESM(require("fs/promises"));
38
+ var import_node_crypto6 = 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
 
@@ -316,22 +316,177 @@ var discoverRuntimeEvidenceBundles = async (rootDir) => {
316
316
  return bundles.sort();
317
317
  };
318
318
 
319
- // src/lib/runtimeEvidenceSync.ts
320
- var import_node_child_process = require("child_process");
319
+ // src/lib/runtimeFeedbackArtifacts.ts
320
+ var import_node_crypto3 = require("crypto");
321
+ var import_promises3 = __toESM(require("fs/promises"));
322
+ var import_node_path3 = __toESM(require("path"));
323
+
324
+ // src/lib/runtimeEvidenceProducer.ts
325
+ var import_node_crypto2 = require("crypto");
321
326
  var import_promises2 = __toESM(require("fs/promises"));
322
327
  var import_node_path2 = __toESM(require("path"));
328
+ var isRecord2 = (value) => value != null && typeof value === "object" && !Array.isArray(value);
329
+ var parseRuntimeEvidenceProducer = (value) => {
330
+ const producer = isRecord2(value) ? value : null;
331
+ const runtimePackageManifest = isRecord2(producer?.runtimePackageManifest) ? producer.runtimePackageManifest : null;
332
+ if (producer?.schemaVersion !== 1 || typeof producer.projectSha !== "string" || !/^[a-f0-9]{40}$/.test(producer.projectSha) || typeof producer.imageDigest !== "string" || !/^sha256:[a-f0-9]{64}$/.test(producer.imageDigest) || runtimePackageManifest?.file !== "runtime-package-manifest.json" || typeof runtimePackageManifest.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(runtimePackageManifest.sha256)) {
333
+ throw new Error("Runtime evidence producer image identity is invalid");
334
+ }
335
+ return producer;
336
+ };
337
+
338
+ // src/lib/runtimeFeedbackArtifacts.ts
339
+ var RUNTIME_FEEDBACK_MANIFEST_FILE = "manifest.json";
340
+ var RUNTIME_FEEDBACK_REPLAY_FILE = "replay-runtime-evidence.json";
341
+ var RUNTIME_FEEDBACK_LOG_FILE = "replay.log";
342
+ var RUNTIME_FEEDBACK_COMPLETE_FILE = ".complete";
343
+ var isRecord3 = (value) => value != null && typeof value === "object" && !Array.isArray(value);
344
+ var sha2562 = (value) => (0, import_node_crypto3.createHash)("sha256").update(value).digest("hex");
345
+ var parsePayload = (value, expectedFile) => {
346
+ const payload = isRecord3(value) ? value : null;
347
+ if (payload?.file !== expectedFile || typeof payload.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(payload.sha256) || typeof payload.bytes !== "number" || !Number.isFinite(payload.bytes) || payload.bytes < 0) {
348
+ throw new Error(`Invalid runtime feedback payload: ${expectedFile}`);
349
+ }
350
+ return payload;
351
+ };
352
+ var parseManifest2 = (value) => {
353
+ const manifest = isRecord3(value) ? value : null;
354
+ const window = isRecord3(manifest?.window) ? manifest.window : null;
355
+ const runtimeEvidence = isRecord3(manifest?.runtimeEvidence) ? manifest.runtimeEvidence : null;
356
+ const safety = isRecord3(manifest?.safety) ? manifest.safety : null;
357
+ const payloads = isRecord3(manifest?.payloads) ? manifest.payloads : null;
358
+ if (manifest?.schemaVersion !== 1 || manifest.reportType !== "runtime-feedback-replay" || typeof manifest.artifactId !== "string" || !manifest.artifactId.trim() || typeof manifest.runId !== "string" || !manifest.runId.trim() || typeof manifest.deploymentId !== "string" || !manifest.deploymentId.trim() || typeof manifest.deploymentCompositionId !== "string" || !/^dc1:[a-f0-9]{16}$/.test(manifest.deploymentCompositionId) || typeof manifest.userName !== "string" || !manifest.userName.trim() || typeof manifest.createdAt !== "number" || typeof window?.startTime !== "number" || typeof window.endTime !== "number" || typeof runtimeEvidence?.artifactId !== "string" || typeof runtimeEvidence.payloadSha256 !== "string" || !/^[a-f0-9]{64}$/.test(runtimeEvidence.payloadSha256) || !Array.isArray(manifest.activeStrategies) || manifest.activeStrategies.length === 0 || !manifest.activeStrategies.every(
359
+ (strategy) => typeof strategy === "string" && strategy.trim()
360
+ ) || typeof manifest.cycleCount !== "number" || !Number.isFinite(manifest.cycleCount) || manifest.cycleCount <= 0 || safety?.cacheOnly !== true || safety.externalOrderPlacement !== false || safety.redis !== "isolated" || safety.timescale !== "read_only") {
361
+ throw new Error("Invalid runtime feedback replay manifest");
362
+ }
363
+ const replayEvidence = parsePayload(
364
+ payloads?.replayEvidence,
365
+ RUNTIME_FEEDBACK_REPLAY_FILE
366
+ );
367
+ const log = parsePayload(payloads?.log, RUNTIME_FEEDBACK_LOG_FILE);
368
+ return {
369
+ ...manifest,
370
+ producer: parseRuntimeEvidenceProducer(manifest.producer),
371
+ payloads: {
372
+ replayEvidence: {
373
+ ...replayEvidence,
374
+ file: RUNTIME_FEEDBACK_REPLAY_FILE
375
+ },
376
+ log: { ...log, file: RUNTIME_FEEDBACK_LOG_FILE }
377
+ }
378
+ };
379
+ };
380
+ var assertReplayMatchesRuntimeEvidence = ({
381
+ replayEvidence,
382
+ runtimeEvidence
383
+ }) => {
384
+ if (replayEvidence.reportType !== "replay-runtime-evidence") {
385
+ throw new Error("Runtime feedback replay payload has the wrong reportType");
386
+ }
387
+ const replayWindow = isRecord3(replayEvidence.window) ? replayEvidence.window : null;
388
+ if (replayWindow?.startTime !== runtimeEvidence.manifest.window.startTime || replayWindow.endTime !== runtimeEvidence.manifest.window.endTime) {
389
+ throw new Error("Runtime feedback replay window does not match evidence");
390
+ }
391
+ const runtimeDeployment = parseRuntimeEvidenceDeploymentSnapshot(
392
+ runtimeEvidence.artifact.deployment
393
+ );
394
+ const replayDeployment = parseRuntimeEvidenceDeploymentSnapshot(
395
+ replayEvidence.deployment
396
+ );
397
+ if (replayDeployment.id !== runtimeDeployment.id || replayDeployment.deploymentCompositionId !== runtimeDeployment.deploymentCompositionId) {
398
+ throw new Error(
399
+ "Runtime feedback replay deployment does not match evidence"
400
+ );
401
+ }
402
+ };
403
+ var verifyRuntimeFeedbackReplayBundle = async (bundleDir) => {
404
+ const manifestPath = import_node_path3.default.join(bundleDir, RUNTIME_FEEDBACK_MANIFEST_FILE);
405
+ const replayEvidencePath = import_node_path3.default.join(bundleDir, RUNTIME_FEEDBACK_REPLAY_FILE);
406
+ const logPath = import_node_path3.default.join(bundleDir, RUNTIME_FEEDBACK_LOG_FILE);
407
+ const completePath = import_node_path3.default.join(bundleDir, RUNTIME_FEEDBACK_COMPLETE_FILE);
408
+ const [manifestText, replayPayload, logPayload, completeText] = await Promise.all([
409
+ import_promises3.default.readFile(manifestPath, "utf8"),
410
+ import_promises3.default.readFile(replayEvidencePath),
411
+ import_promises3.default.readFile(logPath),
412
+ import_promises3.default.readFile(completePath, "utf8")
413
+ ]);
414
+ const manifest = parseManifest2(JSON.parse(manifestText));
415
+ if (completeText.trim() !== manifest.artifactId) {
416
+ throw new Error(`Invalid runtime feedback completion marker: ${bundleDir}`);
417
+ }
418
+ for (const [payload, descriptor] of [
419
+ [replayPayload, manifest.payloads.replayEvidence],
420
+ [logPayload, manifest.payloads.log]
421
+ ]) {
422
+ if (payload.byteLength !== descriptor.bytes) {
423
+ throw new Error(
424
+ `Runtime feedback payload size mismatch: ${descriptor.file}`
425
+ );
426
+ }
427
+ if (sha2562(payload) !== descriptor.sha256) {
428
+ throw new Error(
429
+ `Runtime feedback payload checksum mismatch: ${descriptor.file}`
430
+ );
431
+ }
432
+ }
433
+ const replayEvidence = JSON.parse(replayPayload.toString("utf8"));
434
+ if (replayEvidence.reportType !== "replay-runtime-evidence") {
435
+ throw new Error("Invalid runtime feedback replay evidence payload");
436
+ }
437
+ const replayWindow = isRecord3(replayEvidence.window) ? replayEvidence.window : null;
438
+ const replay = isRecord3(replayEvidence.replay) ? replayEvidence.replay : null;
439
+ const replayDeployment = parseRuntimeEvidenceDeploymentSnapshot(
440
+ replayEvidence.deployment
441
+ );
442
+ const replayStrategies = activeRuntimeEvidenceStrategies(replayDeployment).map(({ strategyName }) => strategyName).sort();
443
+ if (replayEvidence.userName !== manifest.userName || replayWindow?.startTime !== manifest.window.startTime || replayWindow.endTime !== manifest.window.endTime || replayDeployment.id !== manifest.deploymentId || replayDeployment.deploymentCompositionId !== manifest.deploymentCompositionId || Number(replay?.cycleCount) !== manifest.cycleCount || JSON.stringify(replayStrategies) !== JSON.stringify([...manifest.activeStrategies].sort())) {
444
+ throw new Error("Runtime feedback replay payload does not match manifest");
445
+ }
446
+ return {
447
+ bundleDir,
448
+ manifestPath,
449
+ replayEvidencePath,
450
+ logPath,
451
+ manifest,
452
+ replayEvidence
453
+ };
454
+ };
455
+ var verifyRuntimeFeedbackReplaySource = async ({
456
+ bundleDir,
457
+ runtimeEvidenceBundleDir
458
+ }) => {
459
+ const [feedback, runtimeEvidence] = await Promise.all([
460
+ verifyRuntimeFeedbackReplayBundle(bundleDir),
461
+ verifyRuntimeEvidenceBundle(runtimeEvidenceBundleDir)
462
+ ]);
463
+ if (feedback.manifest.runtimeEvidence.artifactId !== runtimeEvidence.manifest.artifactId || feedback.manifest.runtimeEvidence.payloadSha256 !== runtimeEvidence.manifest.payload.sha256) {
464
+ throw new Error("Runtime feedback bundle references different evidence");
465
+ }
466
+ assertReplayMatchesRuntimeEvidence({
467
+ replayEvidence: feedback.replayEvidence,
468
+ runtimeEvidence
469
+ });
470
+ return { feedback, runtimeEvidence };
471
+ };
472
+
473
+ // src/lib/runtimeEvidenceSync.ts
474
+ var import_node_child_process = require("child_process");
475
+ var import_promises4 = __toESM(require("fs/promises"));
476
+ var import_node_path4 = __toESM(require("path"));
323
477
  var import_node_util = require("util");
324
478
  var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
325
479
  var safeSegment = (value, fallback) => {
326
480
  const normalized = value.trim().replace(/[^a-zA-Z0-9._-]+/g, "-");
327
481
  return normalized && normalized !== "." && normalized !== ".." ? normalized : fallback;
328
482
  };
329
- var receiptPath = (receiptsRoot, artifactId) => import_node_path2.default.join(receiptsRoot, `${safeSegment(artifactId, "artifact")}.json`);
483
+ var receiptPath = (receiptsRoot, artifactId) => import_node_path4.default.join(receiptsRoot, `${safeSegment(artifactId, "artifact")}.json`);
330
484
  var markRuntimeEvidenceBundleProcessed = async ({
331
485
  evidenceRoot,
332
486
  deploymentId,
333
487
  bundleDir,
334
- scorecardPath
488
+ scorecardPath,
489
+ runtimeFeedback
335
490
  }) => {
336
491
  const safeDeploymentId = safeSegment(deploymentId, "production");
337
492
  const verified = await verifyRuntimeEvidenceBundle(bundleDir);
@@ -340,29 +495,33 @@ var markRuntimeEvidenceBundleProcessed = async ({
340
495
  `Artifact deployment mismatch: expected ${safeDeploymentId}, received ${verified.manifest.deploymentId}`
341
496
  );
342
497
  }
343
- const receiptsRoot = import_node_path2.default.join(evidenceRoot, "receipts", safeDeploymentId);
498
+ const receiptsRoot = import_node_path4.default.join(evidenceRoot, "receipts", safeDeploymentId);
344
499
  const finalPath = receiptPath(receiptsRoot, verified.manifest.artifactId);
345
500
  const temporaryPath = `${finalPath}.tmp-${process.pid}`;
346
501
  const receipt = {
347
- schemaVersion: 1,
502
+ schemaVersion: runtimeFeedback ? 2 : 1,
348
503
  artifactId: verified.manifest.artifactId,
349
504
  payloadSha256: verified.manifest.payload.sha256,
350
505
  processedAt: Date.now(),
351
- scorecardPath: scorecardPath ?? null
506
+ scorecardPath: scorecardPath ?? null,
507
+ ...runtimeFeedback ? {
508
+ runtimeFeedbackArtifactId: runtimeFeedback.artifactId,
509
+ replayEvidenceSha256: runtimeFeedback.replayEvidenceSha256
510
+ } : {}
352
511
  };
353
- await import_promises2.default.mkdir(receiptsRoot, { recursive: true });
354
- await import_promises2.default.writeFile(
512
+ await import_promises4.default.mkdir(receiptsRoot, { recursive: true });
513
+ await import_promises4.default.writeFile(
355
514
  temporaryPath,
356
515
  `${JSON.stringify(receipt, null, 2)}
357
516
  `,
358
517
  "utf8"
359
518
  );
360
- await import_promises2.default.rename(temporaryPath, finalPath);
519
+ await import_promises4.default.rename(temporaryPath, finalPath);
361
520
  return finalPath;
362
521
  };
363
522
 
364
523
  // src/lib/runtimeLineage.ts
365
- var import_node_crypto2 = require("crypto");
524
+ var import_node_crypto4 = require("crypto");
366
525
  var normalizeForStableJson = (value) => {
367
526
  if (Array.isArray(value)) {
368
527
  return value.map(normalizeForStableJson);
@@ -374,7 +533,7 @@ var normalizeForStableJson = (value) => {
374
533
  }
375
534
  return value;
376
535
  };
377
- var fingerprintRuntimeValue = (value) => (0, import_node_crypto2.createHash)("sha256").update(JSON.stringify(normalizeForStableJson(value))).digest("hex").slice(0, 16);
536
+ var fingerprintRuntimeValue = (value) => (0, import_node_crypto4.createHash)("sha256").update(JSON.stringify(normalizeForStableJson(value))).digest("hex").slice(0, 16);
378
537
  var runtimeLineageKey = (lineage) => [
379
538
  "v3",
380
539
  lineage.deploymentCompositionId,
@@ -1089,9 +1248,9 @@ ${reactions}
1089
1248
  };
1090
1249
 
1091
1250
  // src/lib/strategyRelease.ts
1092
- var import_node_crypto3 = require("crypto");
1093
- var import_promises3 = __toESM(require("fs/promises"));
1094
- var import_node_path3 = __toESM(require("path"));
1251
+ var import_node_crypto5 = require("crypto");
1252
+ var import_promises5 = __toESM(require("fs/promises"));
1253
+ var import_node_path5 = __toESM(require("path"));
1095
1254
  var import_types2 = require("@tradejs/types");
1096
1255
  var import_strategyReleaseEvidence = require("@tradejs/infra/strategyReleaseEvidence");
1097
1256
 
@@ -1565,10 +1724,10 @@ var createStrategyReleaseManifest = (input) => {
1565
1724
  strategy: input.strategy,
1566
1725
  createdAt: input.createdAt,
1567
1726
  compositionId,
1568
- evidence: input.evidence.map(({ kind, artifactId, sha256: sha2562 }) => ({
1727
+ evidence: input.evidence.map(({ kind, artifactId, sha256: sha2563 }) => ({
1569
1728
  kind,
1570
1729
  artifactId,
1571
- sha256: sha2562
1730
+ sha256: sha2563
1572
1731
  })),
1573
1732
  verdict
1574
1733
  };
@@ -1592,7 +1751,7 @@ var createStrategyReleaseManifest = (input) => {
1592
1751
  };
1593
1752
  };
1594
1753
  var verifyStrategyReleaseEnvelope = async (valueOrPath) => {
1595
- const value = typeof valueOrPath === "string" ? JSON.parse(await import_promises3.default.readFile(valueOrPath, "utf8")) : valueOrPath;
1754
+ const value = typeof valueOrPath === "string" ? JSON.parse(await import_promises5.default.readFile(valueOrPath, "utf8")) : valueOrPath;
1596
1755
  const envelope = value;
1597
1756
  assert(
1598
1757
  envelope?.schema === "tradejs-strategy-release-envelope/v1",
@@ -1643,19 +1802,19 @@ var verifyStrategyReleaseEnvelope = async (valueOrPath) => {
1643
1802
  return envelope;
1644
1803
  };
1645
1804
  var verifyStrategyEvidenceMarkerEnvelope = async (valueOrPath) => {
1646
- const value = typeof valueOrPath === "string" ? JSON.parse(await import_promises3.default.readFile(valueOrPath, "utf8")) : valueOrPath;
1805
+ const value = typeof valueOrPath === "string" ? JSON.parse(await import_promises5.default.readFile(valueOrPath, "utf8")) : valueOrPath;
1647
1806
  return (0, import_strategyReleaseEvidence.verifyStrategyEvidenceMarkerEnvelope)(value);
1648
1807
  };
1649
1808
  var writeJsonAtomic = async (filePath, value) => {
1650
1809
  const temporaryPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
1651
- await import_promises3.default.mkdir(import_node_path3.default.dirname(filePath), { recursive: true });
1652
- await import_promises3.default.writeFile(
1810
+ await import_promises5.default.mkdir(import_node_path5.default.dirname(filePath), { recursive: true });
1811
+ await import_promises5.default.writeFile(
1653
1812
  temporaryPath,
1654
1813
  `${canonicalStrategyReleaseJson(value)}
1655
1814
  `,
1656
1815
  "utf8"
1657
1816
  );
1658
- await import_promises3.default.rename(temporaryPath, filePath);
1817
+ await import_promises5.default.rename(temporaryPath, filePath);
1659
1818
  };
1660
1819
  var publishStrategyLiveDiagnosis = async ({
1661
1820
  rootDir,
@@ -1721,13 +1880,13 @@ var publishStrategyLiveDiagnosis = async ({
1721
1880
  markers,
1722
1881
  sourceArtifacts
1723
1882
  });
1724
- const diagnosisPath = import_node_path3.default.join(
1883
+ const diagnosisPath = import_node_path5.default.join(
1725
1884
  rootDir,
1726
1885
  "diagnoses",
1727
1886
  safeSegment2(diagnosis.strategy, "strategy"),
1728
1887
  `${diagnosisId}.json`
1729
1888
  );
1730
- const markerPath = import_node_path3.default.join(
1889
+ const markerPath = import_node_path5.default.join(
1731
1890
  rootDir,
1732
1891
  "markers",
1733
1892
  safeSegment2(diagnosis.strategy, "strategy"),
@@ -1799,15 +1958,15 @@ var flags = import_args.default.parse(process.argv);
1799
1958
  var projectRoot = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
1800
1959
  var resolveOptionalPath = (value) => {
1801
1960
  const raw = String(value ?? "").trim();
1802
- return raw ? import_node_path4.default.resolve(projectRoot, raw) : null;
1961
+ return raw ? import_node_path6.default.resolve(projectRoot, raw) : null;
1803
1962
  };
1804
- var readJson = async (filePath) => filePath ? JSON.parse(await import_promises4.default.readFile(filePath, "utf8")) : void 0;
1963
+ var readJson = async (filePath) => filePath ? JSON.parse(await import_promises6.default.readFile(filePath, "utf8")) : void 0;
1805
1964
  var assertReportType = (artifact, expected, label) => {
1806
1965
  if (artifact != null && (!artifact || typeof artifact !== "object" || Array.isArray(artifact) || artifact.reportType !== expected)) {
1807
1966
  throw new Error(`${label} must be a ${expected} artifact`);
1808
1967
  }
1809
1968
  };
1810
- var sha256File = async (filePath) => (0, import_node_crypto4.createHash)("sha256").update(await import_promises4.default.readFile(filePath)).digest("hex");
1969
+ var sha256File = async (filePath) => (0, import_node_crypto6.createHash)("sha256").update(await import_promises6.default.readFile(filePath)).digest("hex");
1811
1970
  var loadHistoryArtifacts = async (historyDir) => {
1812
1971
  if (!historyDir) return [];
1813
1972
  const bundleDirs = await discoverRuntimeEvidenceBundles(historyDir);
@@ -1877,13 +2036,13 @@ var runtimeScorecard = async () => {
1877
2036
  strategy: scorecardStrategy,
1878
2037
  llmComparatorPolicy: verifiedRelease?.manifest.prospective.llmComparatorPolicy ?? "ai_approved_only"
1879
2038
  });
1880
- const outPath = import_node_path4.default.resolve(projectRoot, String(flags.out));
2039
+ const outPath = import_node_path6.default.resolve(projectRoot, String(flags.out));
1881
2040
  const markdownPath = outPath.replace(/\.json$/i, "") + ".md";
1882
- await import_promises4.default.mkdir(import_node_path4.default.dirname(outPath), { recursive: true });
2041
+ await import_promises6.default.mkdir(import_node_path6.default.dirname(outPath), { recursive: true });
1883
2042
  await Promise.all([
1884
- import_promises4.default.writeFile(outPath, `${JSON.stringify(scorecard, null, 2)}
2043
+ import_promises6.default.writeFile(outPath, `${JSON.stringify(scorecard, null, 2)}
1885
2044
  `, "utf8"),
1886
- import_promises4.default.writeFile(
2045
+ import_promises6.default.writeFile(
1887
2046
  markdownPath,
1888
2047
  formatRuntimeScorecardMarkdown(scorecard),
1889
2048
  "utf8"
@@ -1897,7 +2056,7 @@ var runtimeScorecard = async () => {
1897
2056
  const diagnosisPath = diagnosis ? outPath.replace(/\.json$/i, "") + ".diagnosis.json" : null;
1898
2057
  const strategyReleaseRoot = resolveOptionalPath(flags.strategyReleaseRoot);
1899
2058
  if (diagnosis && diagnosisPath) {
1900
- await import_promises4.default.writeFile(
2059
+ await import_promises6.default.writeFile(
1901
2060
  diagnosisPath,
1902
2061
  `${JSON.stringify(diagnosis, null, 2)}
1903
2062
  `,
@@ -1918,7 +2077,7 @@ var runtimeScorecard = async () => {
1918
2077
  composition: verifiedRelease?.manifest.composition,
1919
2078
  sourceArtifacts: await Promise.all(
1920
2079
  sourcePaths.map(async (sourcePath) => ({
1921
- artifactId: import_node_path4.default.basename(sourcePath),
2080
+ artifactId: import_node_path6.default.basename(sourcePath),
1922
2081
  path: sourcePath,
1923
2082
  sha256: await sha256File(sourcePath)
1924
2083
  }))
@@ -1928,11 +2087,30 @@ var runtimeScorecard = async () => {
1928
2087
  }
1929
2088
  let receiptPath2 = null;
1930
2089
  if (flags.markProcessed) {
2090
+ const runtimeEvidenceBundle = await verifyRuntimeEvidenceBundle(
2091
+ import_node_path6.default.dirname(runtimeEvidencePath)
2092
+ );
2093
+ const feedbackSource = replayEvidencePath ? await verifyRuntimeFeedbackReplaySource({
2094
+ bundleDir: import_node_path6.default.dirname(replayEvidencePath),
2095
+ runtimeEvidenceBundleDir: import_node_path6.default.dirname(runtimeEvidencePath)
2096
+ }).catch((error) => {
2097
+ if (runtimeEvidenceBundle.artifact.producer) throw error;
2098
+ return null;
2099
+ }) : null;
2100
+ if (runtimeEvidenceBundle.artifact.producer && !feedbackSource) {
2101
+ throw new Error(
2102
+ "Image-bound runtime evidence requires a verified production replay bundle before it can be marked processed"
2103
+ );
2104
+ }
1931
2105
  receiptPath2 = await markRuntimeEvidenceBundleProcessed({
1932
- evidenceRoot: import_node_path4.default.resolve(projectRoot, String(flags.evidenceDir)),
2106
+ evidenceRoot: import_node_path6.default.resolve(projectRoot, String(flags.evidenceDir)),
1933
2107
  deploymentId: String(flags.deployment),
1934
- bundleDir: import_node_path4.default.dirname(runtimeEvidencePath),
1935
- scorecardPath: outPath
2108
+ bundleDir: import_node_path6.default.dirname(runtimeEvidencePath),
2109
+ scorecardPath: outPath,
2110
+ runtimeFeedback: feedbackSource ? {
2111
+ artifactId: feedbackSource.feedback.manifest.artifactId,
2112
+ replayEvidenceSha256: feedbackSource.feedback.manifest.payloads.replayEvidence.sha256
2113
+ } : null
1936
2114
  });
1937
2115
  }
1938
2116
  console.log(import_chalk.default.green(`Wrote ${outPath}`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tradejs/cli",
3
- "version": "3.1.21-beta.237",
3
+ "version": "3.1.22-beta.238",
4
4
  "description": "Official CLI for the TradeJS TypeScript framework: infra setup, backtests, signals, bots, and ML workflows.",
5
5
  "keywords": [
6
6
  "tradejs",
@@ -36,13 +36,13 @@
36
36
  "tradejs": "dist/cli.js"
37
37
  },
38
38
  "dependencies": {
39
- "@tradejs/connectors": "^3.1.21-beta.237",
40
- "@tradejs/core": "^3.1.21-beta.237",
41
- "@tradejs/indicators": "^3.1.21-beta.237",
42
- "@tradejs/infra": "^3.1.21-beta.237",
43
- "@tradejs/node": "^3.1.21-beta.237",
39
+ "@tradejs/connectors": "^3.1.22-beta.238",
40
+ "@tradejs/core": "^3.1.22-beta.238",
41
+ "@tradejs/indicators": "^3.1.22-beta.238",
42
+ "@tradejs/infra": "^3.1.22-beta.238",
43
+ "@tradejs/node": "^3.1.22-beta.238",
44
44
  "@tradejs/strategy-kit": "3.0.3",
45
- "@tradejs/types": "^3.1.21-beta.237",
45
+ "@tradejs/types": "^3.1.22-beta.238",
46
46
  "args": "^5.0.3",
47
47
  "bcryptjs": "^2.4.3",
48
48
  "chalk": "4.1.2",
@@ -84,6 +84,8 @@
84
84
  "signals": "yarn run run:dist signals",
85
85
  "results": "yarn run run:dist results",
86
86
  "replay-runtime-evidence": "yarn run run:dist replay-runtime-evidence",
87
+ "runtime-feedback-replay": "yarn run run:dist runtime-feedback-replay",
88
+ "runtime-feedback-sync": "yarn run run:dist runtime-feedback-sync",
87
89
  "runtime-evidence": "yarn run run:dist runtime-evidence",
88
90
  "runtime-evidence-sync": "yarn run run:dist runtime-evidence-sync",
89
91
  "runtime-scorecard": "yarn run run:dist runtime-scorecard",