@tradejs/cli 3.1.16-beta.230 → 3.1.17-beta.231

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_promises6 = __toESM(require("fs/promises"));
38
- var import_node_crypto5 = require("crypto");
39
- var import_node_path6 = __toESM(require("path"));
37
+ var import_promises4 = __toESM(require("fs/promises"));
38
+ var import_node_crypto4 = require("crypto");
39
+ var import_node_path4 = __toESM(require("path"));
40
40
  var import_args = __toESM(require("args"));
41
41
  var import_chalk = __toESM(require("chalk"));
42
42
 
@@ -44,6 +44,166 @@ var import_chalk = __toESM(require("chalk"));
44
44
  var import_node_crypto = require("crypto");
45
45
  var import_promises = __toESM(require("fs/promises"));
46
46
  var import_node_path = __toESM(require("path"));
47
+
48
+ // src/lib/runtimeEvidenceDeployment.ts
49
+ var import_runtimeStrategies = require("@tradejs/node/runtimeStrategies");
50
+ var isRecord = (value) => value != null && typeof value === "object" && !Array.isArray(value);
51
+ var isNonEmptyString = (value) => typeof value === "string" && value.trim().length > 0;
52
+ var isPackageVersionMap = (value) => isRecord(value) && Object.keys(value).length > 0 && Object.entries(value).every(
53
+ ([name, version]) => name.startsWith("@tradejs/") && isNonEmptyString(version)
54
+ );
55
+ var INTERVALS = /* @__PURE__ */ new Set([
56
+ "1",
57
+ "3",
58
+ "5",
59
+ "15",
60
+ "30",
61
+ "60",
62
+ "120",
63
+ "240",
64
+ "360",
65
+ "720",
66
+ "D",
67
+ "W",
68
+ "M"
69
+ ]);
70
+ var UNIVERSES = /* @__PURE__ */ new Set(["crypto", "tradfi"]);
71
+ var isRuntimeStrategySelection = (value) => value === void 0 || isRecord(value) && Object.keys(value).length === 1 && Object.keys(value).every((key) => key === "tickers") && Array.isArray(value.tickers) && value.tickers.length > 0 && value.tickers.every((ticker) => isNonEmptyString(ticker));
72
+ var samePackageVersions = (left, right) => {
73
+ if (!left || !right) return false;
74
+ const leftEntries = Object.entries(left).sort(
75
+ ([a], [b]) => a.localeCompare(b)
76
+ );
77
+ const rightEntries = Object.entries(right).sort(
78
+ ([a], [b]) => a.localeCompare(b)
79
+ );
80
+ return JSON.stringify(leftEntries) === JSON.stringify(rightEntries);
81
+ };
82
+ var runtimeLineageMatchesStrategySnapshot = ({
83
+ lineage,
84
+ deployment,
85
+ strategy
86
+ }) => lineage?.schemaVersion === 3 && lineage.strategyRevision === strategy.strategyRevision && lineage.deploymentCompositionId === deployment.deploymentCompositionId && lineage.strategyPackageVersion === strategy.strategyPackageVersion && lineage.runtimePackageVersion === strategy.runtimePackageVersion && samePackageVersions(
87
+ lineage.strategyDependencyVersions,
88
+ strategy.strategyDependencyVersions
89
+ );
90
+ var parseRuntimeEvidenceDeploymentSnapshot = (value) => {
91
+ if (!isRecord(value) || value.schemaVersion !== 2 || !isNonEmptyString(value.id) || !isNonEmptyString(value.deploymentCompositionId) || !/^dc1:[a-f0-9]{16}$/.test(value.deploymentCompositionId) || !isNonEmptyString(value.label) || !isNonEmptyString(value.connectorName) || !isNonEmptyString(value.provider) || !isNonEmptyString(value.accountId) || typeof value.enabled !== "boolean" || !Array.isArray(value.strategies)) {
92
+ throw new Error(
93
+ "Runtime evidence deployment snapshot is missing or invalid"
94
+ );
95
+ }
96
+ const strategies = value.strategies.map((candidate) => {
97
+ if (!isRecord(candidate) || !isNonEmptyString(candidate.strategyName) || !isNonEmptyString(candidate.strategyRevision) || !/^sr1:[a-f0-9]{16}$/.test(candidate.strategyRevision) || typeof candidate.enabled !== "boolean" || !["active", "entries_paused"].includes(String(candidate.controlState)) || !INTERVALS.has(String(candidate.interval)) || !UNIVERSES.has(String(candidate.universe)) || !isNonEmptyString(candidate.strategyPackage) || !isNonEmptyString(candidate.strategyPackageVersion) || !isPackageVersionMap(candidate.strategyDependencyVersions) || !isNonEmptyString(candidate.runtimePackageVersion) || !isRecord(candidate.strategyConfig) || !isRuntimeStrategySelection(candidate.selection)) {
98
+ throw new Error(
99
+ "Runtime evidence deployment strategy snapshot is invalid"
100
+ );
101
+ }
102
+ if (String(candidate.strategyConfig.INTERVAL) !== String(candidate.interval) || String(candidate.strategyConfig.UNIVERSE) !== String(candidate.universe)) {
103
+ throw new Error(
104
+ `Runtime evidence strategy config does not match its scope: ${candidate.strategyName}`
105
+ );
106
+ }
107
+ if (candidate.accountId != null && (!isNonEmptyString(candidate.accountId) || candidate.accountId !== value.accountId)) {
108
+ throw new Error(
109
+ `Runtime evidence strategy account does not match deployment: ${candidate.strategyName}`
110
+ );
111
+ }
112
+ return candidate;
113
+ });
114
+ const identities = /* @__PURE__ */ new Set();
115
+ for (const strategy of strategies) {
116
+ if (identities.has(strategy.strategyName)) {
117
+ throw new Error(
118
+ `Duplicate runtime evidence strategy: ${strategy.strategyName}`
119
+ );
120
+ }
121
+ identities.add(strategy.strategyName);
122
+ }
123
+ return {
124
+ ...value,
125
+ strategies
126
+ };
127
+ };
128
+ var activeRuntimeEvidenceStrategies = (deployment) => deployment.enabled ? deployment.strategies.filter((strategy) => strategy.enabled) : [];
129
+ var unwrapRuntimeEvidenceRows = (value, field) => (Array.isArray(value) ? value : []).map((candidate) => {
130
+ const record = isRecord(candidate) ? candidate : null;
131
+ const nested = record && isRecord(record[field]) ? record[field] : null;
132
+ return nested ?? record;
133
+ }).filter((record) => record != null);
134
+ var assertCurrentRuntimeEvidenceArtifact = (artifact) => {
135
+ if (!isRecord(artifact) || artifact.reportType !== "runtime-evidence") {
136
+ throw new Error("Invalid runtime evidence artifact");
137
+ }
138
+ const deployment = parseRuntimeEvidenceDeploymentSnapshot(
139
+ artifact.deployment
140
+ );
141
+ const activeStrategies = activeRuntimeEvidenceStrategies(deployment);
142
+ if (activeStrategies.length === 0) {
143
+ throw new Error("Runtime evidence deployment has no enabled strategies");
144
+ }
145
+ const runtime = isRecord(artifact.runtime) ? artifact.runtime : null;
146
+ if (!runtime) {
147
+ throw new Error("Runtime evidence payload is missing");
148
+ }
149
+ if ("strategyConfigs" in runtime) {
150
+ throw new Error(
151
+ "Runtime evidence payload contains removed strategyConfigs data"
152
+ );
153
+ }
154
+ const rowFields = [
155
+ "trades",
156
+ "signals",
157
+ "evaluations",
158
+ "lineageScopes"
159
+ ];
160
+ for (const field of rowFields) {
161
+ if (!Array.isArray(runtime[field])) {
162
+ throw new Error(`Runtime evidence payload ${field} must be an array`);
163
+ }
164
+ }
165
+ const snapshots = new Map(
166
+ activeStrategies.map((strategy) => [strategy.strategyName, strategy])
167
+ );
168
+ const assertRows = (label, rows, lineageField) => {
169
+ for (const row of rows) {
170
+ const strategyName = String(row.strategy ?? "").trim();
171
+ const strategy = snapshots.get(strategyName);
172
+ if (!strategy || row.deploymentId !== deployment.id || row.accountId !== deployment.accountId || !runtimeLineageMatchesStrategySnapshot({
173
+ lineage: isRecord(row[lineageField]) ? row[lineageField] : void 0,
174
+ deployment,
175
+ strategy
176
+ })) {
177
+ throw new Error(
178
+ `Runtime evidence ${label} row is outside the current embedded deployment lineage`
179
+ );
180
+ }
181
+ }
182
+ };
183
+ assertRows(
184
+ "trade",
185
+ unwrapRuntimeEvidenceRows(runtime.trades, "trade"),
186
+ "runtimeLineage"
187
+ );
188
+ assertRows(
189
+ "signal",
190
+ unwrapRuntimeEvidenceRows(runtime.signals, "signal"),
191
+ "runtimeLineage"
192
+ );
193
+ assertRows(
194
+ "evaluation",
195
+ unwrapRuntimeEvidenceRows(runtime.evaluations, "evaluation"),
196
+ "runtimeLineage"
197
+ );
198
+ assertRows(
199
+ "lineage scope",
200
+ unwrapRuntimeEvidenceRows(runtime.lineageScopes, "lineageScope"),
201
+ "lineage"
202
+ );
203
+ return deployment;
204
+ };
205
+
206
+ // src/lib/runtimeEvidenceArtifacts.ts
47
207
  var RUNTIME_EVIDENCE_MANIFEST_FILE = "manifest.json";
48
208
  var RUNTIME_EVIDENCE_PAYLOAD_FILE = "runtime-evidence.json";
49
209
  var RUNTIME_EVIDENCE_COMPLETE_FILE = ".complete";
@@ -113,6 +273,10 @@ var verifyRuntimeEvidenceBundle = async (bundleDir) => {
113
273
  if (artifact?.reportType !== "runtime-evidence" || artifactWindow?.startTime !== manifest.window.startTime || artifactWindow.endTime !== manifest.window.endTime) {
114
274
  throw new Error(`Runtime evidence payload mismatch in ${bundleDir}`);
115
275
  }
276
+ const deployment = assertCurrentRuntimeEvidenceArtifact(artifact);
277
+ if (deployment.id !== manifest.deploymentId) {
278
+ throw new Error(`Runtime evidence deployment mismatch in ${bundleDir}`);
279
+ }
116
280
  return {
117
281
  bundleDir,
118
282
  manifestPath,
@@ -152,11 +316,6 @@ var import_node_child_process = require("child_process");
152
316
  var import_promises2 = __toESM(require("fs/promises"));
153
317
  var import_node_path2 = __toESM(require("path"));
154
318
  var import_node_util = require("util");
155
-
156
- // src/lib/runtimeEvidenceDeployment.ts
157
- var import_runtimeStrategies = require("@tradejs/node/runtimeStrategies");
158
-
159
- // src/lib/runtimeEvidenceSync.ts
160
319
  var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
161
320
  var safeSegment = (value, fallback) => {
162
321
  const normalized = value.trim().replace(/[^a-zA-Z0-9._-]+/g, "-");
@@ -198,21 +357,7 @@ var markRuntimeEvidenceBundleProcessed = async ({
198
357
  };
199
358
 
200
359
  // src/lib/runtimeLineage.ts
201
- var import_node_child_process2 = require("child_process");
202
- var import_node_crypto3 = require("crypto");
203
- var import_promises4 = __toESM(require("fs/promises"));
204
- var import_node_path4 = __toESM(require("path"));
205
- var import_types = require("@tradejs/types");
206
- var import_strategies = require("@tradejs/node/strategies");
207
- var import_strategyReleaseEvidence = require("@tradejs/infra/strategyReleaseEvidence");
208
-
209
- // src/lib/strategyGateFingerprint.ts
210
360
  var import_node_crypto2 = require("crypto");
211
- var import_node_module = require("module");
212
- var import_promises3 = __toESM(require("fs/promises"));
213
- var import_node_path3 = __toESM(require("path"));
214
-
215
- // src/lib/runtimeLineage.ts
216
361
  var normalizeForStableJson = (value) => {
217
362
  if (Array.isArray(value)) {
218
363
  return value.map(normalizeForStableJson);
@@ -224,24 +369,14 @@ var normalizeForStableJson = (value) => {
224
369
  }
225
370
  return value;
226
371
  };
227
- var fingerprintRuntimeValue = (value) => (0, import_node_crypto3.createHash)("sha256").update(JSON.stringify(normalizeForStableJson(value))).digest("hex").slice(0, 16);
228
- var runtimeLineageKey = (lineage) => lineage.schemaVersion === 3 ? [
372
+ var fingerprintRuntimeValue = (value) => (0, import_node_crypto2.createHash)("sha256").update(JSON.stringify(normalizeForStableJson(value))).digest("hex").slice(0, 16);
373
+ var runtimeLineageKey = (lineage) => [
229
374
  "v3",
230
375
  lineage.deploymentCompositionId,
231
376
  lineage.strategyRevision,
232
377
  lineage.strategyPackageVersion,
233
- `deps:${fingerprintRuntimeValue(
234
- lineage.strategyDependencyVersions
235
- ).slice(0, 16)}`,
378
+ `deps:${fingerprintRuntimeValue(lineage.strategyDependencyVersions).slice(0, 16)}`,
236
379
  lineage.runtimePackageVersion
237
- ].join(":") : [
238
- lineage.schemaVersion,
239
- lineage.compositionId ?? "unbound-composition",
240
- lineage.gitSha ?? "unknown",
241
- lineage.gitDirty == null ? "unknown" : lineage.gitDirty ? "dirty" : "clean",
242
- lineage.gateFingerprint,
243
- lineage.configFingerprint,
244
- lineage.contextFingerprint
245
380
  ].join(":");
246
381
 
247
382
  // src/lib/runtimeScorecard.ts
@@ -282,75 +417,6 @@ var extractRuntimeRows = (artifact) => {
282
417
  statsBuckets: asArray(runtime.evaluationStatsBuckets).map(asRecord2).filter((item) => item != null)
283
418
  };
284
419
  };
285
- var buildRuntimeLineageSummary = (rows) => {
286
- const lineageRows = [
287
- ...rows.evaluations,
288
- ...rows.signals,
289
- ...rows.trades,
290
- ...rows.lineageScopes.map((scope) => ({
291
- runtimeLineage: scope.lineage
292
- }))
293
- ];
294
- const lineages = lineageRows.map((row) => asRecord2(row.runtimeLineage)).filter((lineage) => lineage != null);
295
- const identities = /* @__PURE__ */ new Map();
296
- for (const lineage of lineages) {
297
- const identity2 = lineage.schemaVersion === 3 ? {
298
- schemaVersion: 3,
299
- strategyRevision: finiteString(lineage.strategyRevision),
300
- deploymentCompositionId: finiteString(
301
- lineage.deploymentCompositionId
302
- ),
303
- strategyPackageVersion: finiteString(
304
- lineage.strategyPackageVersion
305
- ),
306
- strategyDependencyVersions: packageVersionMap(
307
- lineage.strategyDependencyVersions
308
- ),
309
- runtimePackageVersion: finiteString(lineage.runtimePackageVersion),
310
- maxLossValue: finiteNumber(lineage.maxLossValue)
311
- } : {
312
- schemaVersion: 1,
313
- compositionId: finiteString(lineage.compositionId),
314
- gitSha: finiteString(lineage.gitSha),
315
- gitDirty: typeof lineage.gitDirty === "boolean" ? lineage.gitDirty : null,
316
- gateFingerprint: finiteString(lineage.gateFingerprint),
317
- configFingerprint: finiteString(lineage.configFingerprint),
318
- contextFingerprint: finiteString(lineage.contextFingerprint),
319
- maxLossValue: finiteNumber(lineage.maxLossValue)
320
- };
321
- identities.set(JSON.stringify(identity2), identity2);
322
- }
323
- const identity = identities.size === 1 ? [...identities.values()][0] : null;
324
- const schemaVersion = finiteNumber(identity?.schemaVersion);
325
- const identityComplete = lineages.length > 0 && identity != null && (schemaVersion === 3 && finiteString(identity.strategyRevision) != null && finiteString(identity.deploymentCompositionId) != null && finiteString(identity.strategyPackageVersion) != null && packageVersionMap(identity.strategyDependencyVersions) != 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;
326
- const coverageComplete = lineageRows.length > 0 && lineages.length === lineageRows.length;
327
- const complete = identityComplete && coverageComplete;
328
- const lineageKey = identityComplete ? runtimeLineageKey(identity) : null;
329
- return {
330
- complete,
331
- identityComplete,
332
- coverageComplete,
333
- conflicts: identities.size > 1,
334
- rows: lineageRows.length,
335
- rowsWithLineage: lineages.length,
336
- schemaVersion,
337
- lineageKey,
338
- strategyRevision: finiteString(identity?.strategyRevision),
339
- deploymentCompositionId: finiteString(identity?.deploymentCompositionId),
340
- strategyPackageVersion: finiteString(identity?.strategyPackageVersion),
341
- strategyDependencyVersions: packageVersionMap(
342
- identity?.strategyDependencyVersions
343
- ),
344
- runtimePackageVersion: finiteString(identity?.runtimePackageVersion),
345
- compositionId: finiteString(identity?.compositionId),
346
- gitSha: finiteString(identity?.gitSha),
347
- gitDirty: typeof identity?.gitDirty === "boolean" ? identity.gitDirty : null,
348
- gateFingerprint: finiteString(identity?.gateFingerprint),
349
- configFingerprint: finiteString(identity?.configFingerprint),
350
- contextFingerprint: finiteString(identity?.contextFingerprint),
351
- maxLossValue: finiteNumber(identity?.maxLossValue)
352
- };
353
- };
354
420
  var buildEmbeddedLineageScope = ({
355
421
  artifact,
356
422
  rows,
@@ -462,12 +528,6 @@ var buildEmbeddedLineageScope = ({
462
528
  strategyPackageVersion: singleTarget?.strategyPackageVersion ?? null,
463
529
  strategyDependencyVersions: singleTarget?.strategyDependencyVersions ?? null,
464
530
  runtimePackageVersion: singleTarget?.runtimePackageVersion ?? null,
465
- compositionId: null,
466
- gitSha: null,
467
- gitDirty: null,
468
- gateFingerprint: null,
469
- configFingerprint: null,
470
- contextFingerprint: null,
471
531
  maxLossValue: commonRiskValues.size === 1 ? [...commonRiskValues][0] : null,
472
532
  strategyScopes: Object.fromEntries(
473
533
  targetValues.map((target) => [
@@ -483,12 +543,6 @@ var buildEmbeddedLineageScope = ({
483
543
  }
484
544
  };
485
545
  };
486
- var belongsToRuntimeLineage = (row, summary) => {
487
- if (!summary.identityComplete || !summary.lineageKey) return false;
488
- const lineage = asRecord2(row.runtimeLineage);
489
- if (!lineage) return false;
490
- return runtimeLineageKey(lineage) === summary.lineageKey && finiteNumber(lineage.maxLossValue) === summary.maxLossValue;
491
- };
492
546
  var runtimeDeploymentBinding = (artifact) => {
493
547
  const deployment = asRecord2(asRecord2(artifact)?.deployment);
494
548
  return {
@@ -670,10 +724,6 @@ var replayCountsForStrategy = (replayComparison, strategy) => {
670
724
  runtimeOnly: finiteNumber(counts?.runtimeOnly) ?? 0
671
725
  };
672
726
  };
673
- var getCalibrationSummary = (artifact) => {
674
- const root = asRecord2(artifact) ?? {};
675
- return asRecord2(asRecord2(root.summary)?.all) ?? null;
676
- };
677
727
  var getProspectiveSummary = (artifact) => {
678
728
  const root = asRecord2(artifact);
679
729
  if (!root || root.reportType !== "strategy-prospective-evidence") return null;
@@ -699,6 +749,10 @@ var buildRuntimeScorecard = ({
699
749
  strategy = null,
700
750
  llmComparatorPolicy = "ai_approved_only"
701
751
  }) => {
752
+ assertCurrentRuntimeEvidenceArtifact(runtimeArtifact);
753
+ for (const artifact of historyRuntimeArtifacts) {
754
+ assertCurrentRuntimeEvidenceArtifact(artifact);
755
+ }
702
756
  const scopedRuntimeArtifact = filterArtifactByStrategy(
703
757
  runtimeArtifact,
704
758
  strategy
@@ -713,7 +767,12 @@ var buildRuntimeScorecard = ({
713
767
  rows,
714
768
  strategy
715
769
  });
716
- const runtimeLineage = embeddedLineageScope?.summary ?? buildRuntimeLineageSummary(rows);
770
+ if (!embeddedLineageScope) {
771
+ throw new Error(
772
+ "Runtime scorecard requires the current embedded deployment lineage"
773
+ );
774
+ }
775
+ const runtimeLineage = embeddedLineageScope.summary;
717
776
  const window = runtimeWindow(runtimeArtifact);
718
777
  const startTime = finiteNumber(window.startTime) ?? generatedAt - 864e5;
719
778
  const endTime = finiteNumber(window.endTime) ?? generatedAt;
@@ -761,32 +820,26 @@ var buildRuntimeScorecard = ({
761
820
  const lineage = asRecord2(replayComparison?.lineage);
762
821
  const lineageReason = finiteString(lineage?.reason);
763
822
  const calibrationRoot = asRecord2(calibrationArtifact) ?? {};
764
- const calibrationSummary = asRecord2(calibrationRoot.summary);
765
- const calibrationSamples = asArray(calibrationRoot.samples).map(asRecord2).filter((item) => item != null).filter((item) => !strategy || finiteString(item.strategy) === strategy).filter(
766
- (item) => !embeddedLineageScope || embeddedLineageScope.belongs(item)
767
- );
823
+ const calibrationSamples = asArray(calibrationRoot.samples).map(asRecord2).filter((item) => item != null).filter((item) => !strategy || finiteString(item.strategy) === strategy).filter((item) => embeddedLineageScope.belongs(item));
768
824
  const averageSampleMetric = (field) => {
769
825
  const values = calibrationSamples.map((sample) => finiteNumber(sample[field])).filter((value) => value != null);
770
826
  return values.length ? round(sum(values) / values.length) : null;
771
827
  };
772
- const fallbackCalibration = strategy ? asRecord2(asRecord2(calibrationSummary?.byStrategy)?.[strategy]) : getCalibrationSummary(calibrationArtifact);
773
- const actualSlippageBps = embeddedLineageScope ? averageSampleMetric("signalToFillAdverseBps") : finiteNumber(asRecord2(fallbackCalibration?.signalToFillAdverseBps)?.avg);
774
- const residualVsModelBps = embeddedLineageScope ? averageSampleMetric("residualVsCurrentModelBps") : finiteNumber(
775
- asRecord2(fallbackCalibration?.residualVsCurrentModelBps)?.avg
776
- );
828
+ const actualSlippageBps = averageSampleMetric("signalToFillAdverseBps");
829
+ const residualVsModelBps = averageSampleMetric("residualVsCurrentModelBps");
777
830
  const prospective = getProspectiveSummary(prospectiveEvidenceArtifact);
778
831
  const historyTrades = dedupeTrades([
779
832
  ...scopedHistoryArtifacts,
780
833
  scopedRuntimeArtifact
781
834
  ]);
782
835
  const comparableHistoryTrades = historyTrades.filter(
783
- (trade) => belongsToRuntimeDeployment(trade, deploymentBinding) && (embeddedLineageScope ? embeddedLineageScope.belongs(trade) : belongsToRuntimeLineage(trade, runtimeLineage))
836
+ (trade) => belongsToRuntimeDeployment(trade, deploymentBinding) && embeddedLineageScope.belongs(trade)
784
837
  );
785
838
  const comparableCurrentClosedTrades = currentClosedTrades.filter(
786
- (trade) => belongsToRuntimeDeployment(trade, deploymentBinding) && (embeddedLineageScope ? embeddedLineageScope.belongs(trade) : belongsToRuntimeLineage(trade, runtimeLineage))
839
+ (trade) => belongsToRuntimeDeployment(trade, deploymentBinding) && embeddedLineageScope.belongs(trade)
787
840
  );
788
841
  const comparableFills = rows.trades.filter(
789
- (trade) => belongsToRuntimeDeployment(trade, deploymentBinding) && (embeddedLineageScope ? embeddedLineageScope.belongs(trade) : belongsToRuntimeLineage(trade, runtimeLineage))
842
+ (trade) => belongsToRuntimeDeployment(trade, deploymentBinding) && embeddedLineageScope.belongs(trade)
790
843
  );
791
844
  const currentDistributions = buildDistributions(rows);
792
845
  const previousArtifact = scopedHistoryArtifacts.map((artifact) => ({ artifact, window: runtimeWindow(artifact) })).filter(({ window: candidateWindow }) => {
@@ -1038,14 +1091,14 @@ ${reactions}
1038
1091
  };
1039
1092
 
1040
1093
  // src/lib/strategyRelease.ts
1041
- var import_node_crypto4 = require("crypto");
1042
- var import_promises5 = __toESM(require("fs/promises"));
1043
- var import_node_path5 = __toESM(require("path"));
1044
- var import_types3 = require("@tradejs/types");
1045
- var import_strategyReleaseEvidence2 = require("@tradejs/infra/strategyReleaseEvidence");
1094
+ var import_node_crypto3 = require("crypto");
1095
+ var import_promises3 = __toESM(require("fs/promises"));
1096
+ var import_node_path3 = __toESM(require("path"));
1097
+ var import_types2 = require("@tradejs/types");
1098
+ var import_strategyReleaseEvidence = require("@tradejs/infra/strategyReleaseEvidence");
1046
1099
 
1047
1100
  // src/lib/strategyRelease/liveDiagnosis.ts
1048
- var import_types2 = require("@tradejs/types");
1101
+ var import_types = require("@tradejs/types");
1049
1102
  var buildStrategyLiveDiagnosis = (input) => {
1050
1103
  const minimumClosedTrades = input.minimumClosedTrades ?? 20;
1051
1104
  const minimumParityRatio = input.minimumParityRatio ?? 0.95;
@@ -1073,7 +1126,7 @@ var buildStrategyLiveDiagnosis = (input) => {
1073
1126
  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."
1074
1127
  ];
1075
1128
  return {
1076
- schema: import_types2.STRATEGY_LIVE_DIAGNOSIS_SCHEMA,
1129
+ schema: import_types.STRATEGY_LIVE_DIAGNOSIS_SCHEMA,
1077
1130
  strategy: input.strategy,
1078
1131
  compositionId: input.compositionId,
1079
1132
  createdAt: input.createdAt,
@@ -1113,7 +1166,7 @@ var buildStrategyLiveDiagnosisFromScorecard = ({
1113
1166
  );
1114
1167
  const orderFailureRate = scorecard.funnel.orderAttempts ? scorecard.funnel.orderFailures / scorecard.funnel.orderAttempts : null;
1115
1168
  const lineage = scorecard.lineage;
1116
- const lineageComparable = scorecard.parity.lineageReason == null && lineage?.complete === true && lineage.conflicts === false && lineage.compositionId === manifest.composition.compositionId && lineage.gitDirty === false && lineage.gitSha === manifest.composition.gitSha && lineage.configFingerprint === manifest.composition.runtimeConfigFingerprint && lineage.gateFingerprint === manifest.composition.gateFingerprint && lineage.contextFingerprint === manifest.composition.runtimeContextFingerprint;
1169
+ const lineageComparable = scorecard.parity.lineageReason == null && lineage?.complete === true && lineage.conflicts === false && lineage.schemaVersion === 3 && lineage.strategyRevision != null && lineage.deploymentCompositionId != null && lineage.strategyPackageVersion != null && lineage.strategyDependencyVersions != null && lineage.runtimePackageVersion != null;
1117
1170
  const releaseMaxLossValue = manifest.composition.maxLossValue;
1118
1171
  const runtimeMaxLossValue = lineage?.maxLossValue ?? null;
1119
1172
  const riskScaleComparable = Number.isFinite(releaseMaxLossValue) && releaseMaxLossValue > 0 && runtimeMaxLossValue != null && Number.isFinite(runtimeMaxLossValue) && runtimeMaxLossValue > 0;
@@ -1150,10 +1203,10 @@ var buildStrategyLiveDiagnosisFromScorecard = ({
1150
1203
  // src/lib/strategyRelease.ts
1151
1204
  var SHA256_RE = /^[a-f0-9]{64}$/;
1152
1205
  var LINEAGE_FINGERPRINT_RE = /^[a-f0-9]{16}$/;
1153
- var safeSegment2 = import_strategyReleaseEvidence2.safeStrategyEvidenceSegment;
1154
- var compactTimestamp = import_strategyReleaseEvidence2.compactStrategyEvidenceTimestamp;
1155
- var canonicalStrategyReleaseJson = (value) => (0, import_strategyReleaseEvidence2.canonicalStrategyEvidenceJson)(value);
1156
- var strategyReleaseSha256 = (value) => (0, import_strategyReleaseEvidence2.strategyEvidenceSha256)(value);
1206
+ var safeSegment2 = import_strategyReleaseEvidence.safeStrategyEvidenceSegment;
1207
+ var compactTimestamp = import_strategyReleaseEvidence.compactStrategyEvidenceTimestamp;
1208
+ var canonicalStrategyReleaseJson = (value) => (0, import_strategyReleaseEvidence.canonicalStrategyEvidenceJson)(value);
1209
+ var strategyReleaseSha256 = (value) => (0, import_strategyReleaseEvidence.strategyEvidenceSha256)(value);
1157
1210
  function assert(condition, message) {
1158
1211
  if (!condition) throw new Error(`Invalid strategy release: ${message}`);
1159
1212
  }
@@ -1522,7 +1575,7 @@ var createStrategyReleaseManifest = (input) => {
1522
1575
  verdict
1523
1576
  };
1524
1577
  return {
1525
- schema: import_types3.STRATEGY_RELEASE_SCHEMA,
1578
+ schema: import_types2.STRATEGY_RELEASE_SCHEMA,
1526
1579
  releaseId: `${safeSegment2(input.strategy, "strategy")}_${compactTimestamp(input.createdAt)}_${strategyReleaseSha256(releaseIdentity).slice(0, 16)}`,
1527
1580
  strategy: input.strategy,
1528
1581
  createdAt: input.createdAt,
@@ -1541,7 +1594,7 @@ var createStrategyReleaseManifest = (input) => {
1541
1594
  };
1542
1595
  };
1543
1596
  var verifyStrategyReleaseEnvelope = async (valueOrPath) => {
1544
- const value = typeof valueOrPath === "string" ? JSON.parse(await import_promises5.default.readFile(valueOrPath, "utf8")) : valueOrPath;
1597
+ const value = typeof valueOrPath === "string" ? JSON.parse(await import_promises3.default.readFile(valueOrPath, "utf8")) : valueOrPath;
1545
1598
  const envelope = value;
1546
1599
  assert(
1547
1600
  envelope?.schema === "tradejs-strategy-release-envelope/v1",
@@ -1557,7 +1610,7 @@ var verifyStrategyReleaseEnvelope = async (valueOrPath) => {
1557
1610
  );
1558
1611
  const manifest = envelope.manifest;
1559
1612
  assert(
1560
- manifest.schema === import_types3.STRATEGY_RELEASE_SCHEMA,
1613
+ manifest.schema === import_types2.STRATEGY_RELEASE_SCHEMA,
1561
1614
  "manifest schema mismatch"
1562
1615
  );
1563
1616
  const rebuilt = createStrategyReleaseManifest({
@@ -1592,19 +1645,19 @@ var verifyStrategyReleaseEnvelope = async (valueOrPath) => {
1592
1645
  return envelope;
1593
1646
  };
1594
1647
  var verifyStrategyEvidenceMarkerEnvelope = async (valueOrPath) => {
1595
- const value = typeof valueOrPath === "string" ? JSON.parse(await import_promises5.default.readFile(valueOrPath, "utf8")) : valueOrPath;
1596
- return (0, import_strategyReleaseEvidence2.verifyStrategyEvidenceMarkerEnvelope)(value);
1648
+ const value = typeof valueOrPath === "string" ? JSON.parse(await import_promises3.default.readFile(valueOrPath, "utf8")) : valueOrPath;
1649
+ return (0, import_strategyReleaseEvidence.verifyStrategyEvidenceMarkerEnvelope)(value);
1597
1650
  };
1598
1651
  var writeJsonAtomic = async (filePath, value) => {
1599
1652
  const temporaryPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
1600
- await import_promises5.default.mkdir(import_node_path5.default.dirname(filePath), { recursive: true });
1601
- await import_promises5.default.writeFile(
1653
+ await import_promises3.default.mkdir(import_node_path3.default.dirname(filePath), { recursive: true });
1654
+ await import_promises3.default.writeFile(
1602
1655
  temporaryPath,
1603
1656
  `${canonicalStrategyReleaseJson(value)}
1604
1657
  `,
1605
1658
  "utf8"
1606
1659
  );
1607
- await import_promises5.default.rename(temporaryPath, filePath);
1660
+ await import_promises3.default.rename(temporaryPath, filePath);
1608
1661
  };
1609
1662
  var publishStrategyLiveDiagnosis = async ({
1610
1663
  rootDir,
@@ -1664,19 +1717,19 @@ var publishStrategyLiveDiagnosis = async ({
1664
1717
  severity: diagnosis.verdict === "EXPECTED_DRAWDOWN" ? "info" : "warning"
1665
1718
  }
1666
1719
  ];
1667
- const markerEnvelope = (0, import_strategyReleaseEvidence2.createStrategyEvidenceMarkerEnvelope)({
1720
+ const markerEnvelope = (0, import_strategyReleaseEvidence.createStrategyEvidenceMarkerEnvelope)({
1668
1721
  strategy: diagnosis.strategy,
1669
1722
  createdAt: diagnosis.createdAt,
1670
1723
  markers,
1671
1724
  sourceArtifacts
1672
1725
  });
1673
- const diagnosisPath = import_node_path5.default.join(
1726
+ const diagnosisPath = import_node_path3.default.join(
1674
1727
  rootDir,
1675
1728
  "diagnoses",
1676
1729
  safeSegment2(diagnosis.strategy, "strategy"),
1677
1730
  `${diagnosisId}.json`
1678
1731
  );
1679
- const markerPath = import_node_path5.default.join(
1732
+ const markerPath = import_node_path3.default.join(
1680
1733
  rootDir,
1681
1734
  "markers",
1682
1735
  safeSegment2(diagnosis.strategy, "strategy"),
@@ -1748,15 +1801,15 @@ var flags = import_args.default.parse(process.argv);
1748
1801
  var projectRoot = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
1749
1802
  var resolveOptionalPath = (value) => {
1750
1803
  const raw = String(value ?? "").trim();
1751
- return raw ? import_node_path6.default.resolve(projectRoot, raw) : null;
1804
+ return raw ? import_node_path4.default.resolve(projectRoot, raw) : null;
1752
1805
  };
1753
- var readJson = async (filePath) => filePath ? JSON.parse(await import_promises6.default.readFile(filePath, "utf8")) : void 0;
1806
+ var readJson = async (filePath) => filePath ? JSON.parse(await import_promises4.default.readFile(filePath, "utf8")) : void 0;
1754
1807
  var assertReportType = (artifact, expected, label) => {
1755
1808
  if (artifact != null && (!artifact || typeof artifact !== "object" || Array.isArray(artifact) || artifact.reportType !== expected)) {
1756
1809
  throw new Error(`${label} must be a ${expected} artifact`);
1757
1810
  }
1758
1811
  };
1759
- var sha256File = async (filePath) => (0, import_node_crypto5.createHash)("sha256").update(await import_promises6.default.readFile(filePath)).digest("hex");
1812
+ var sha256File = async (filePath) => (0, import_node_crypto4.createHash)("sha256").update(await import_promises4.default.readFile(filePath)).digest("hex");
1760
1813
  var loadHistoryArtifacts = async (historyDir) => {
1761
1814
  if (!historyDir) return [];
1762
1815
  const bundleDirs = await discoverRuntimeEvidenceBundles(historyDir);
@@ -1826,13 +1879,13 @@ var runtimeScorecard = async () => {
1826
1879
  strategy: scorecardStrategy,
1827
1880
  llmComparatorPolicy: verifiedRelease?.manifest.prospective.llmComparatorPolicy ?? "ai_approved_only"
1828
1881
  });
1829
- const outPath = import_node_path6.default.resolve(projectRoot, String(flags.out));
1882
+ const outPath = import_node_path4.default.resolve(projectRoot, String(flags.out));
1830
1883
  const markdownPath = outPath.replace(/\.json$/i, "") + ".md";
1831
- await import_promises6.default.mkdir(import_node_path6.default.dirname(outPath), { recursive: true });
1884
+ await import_promises4.default.mkdir(import_node_path4.default.dirname(outPath), { recursive: true });
1832
1885
  await Promise.all([
1833
- import_promises6.default.writeFile(outPath, `${JSON.stringify(scorecard, null, 2)}
1886
+ import_promises4.default.writeFile(outPath, `${JSON.stringify(scorecard, null, 2)}
1834
1887
  `, "utf8"),
1835
- import_promises6.default.writeFile(
1888
+ import_promises4.default.writeFile(
1836
1889
  markdownPath,
1837
1890
  formatRuntimeScorecardMarkdown(scorecard),
1838
1891
  "utf8"
@@ -1846,7 +1899,7 @@ var runtimeScorecard = async () => {
1846
1899
  const diagnosisPath = diagnosis ? outPath.replace(/\.json$/i, "") + ".diagnosis.json" : null;
1847
1900
  const strategyReleaseRoot = resolveOptionalPath(flags.strategyReleaseRoot);
1848
1901
  if (diagnosis && diagnosisPath) {
1849
- await import_promises6.default.writeFile(
1902
+ await import_promises4.default.writeFile(
1850
1903
  diagnosisPath,
1851
1904
  `${JSON.stringify(diagnosis, null, 2)}
1852
1905
  `,
@@ -1867,7 +1920,7 @@ var runtimeScorecard = async () => {
1867
1920
  composition: verifiedRelease?.manifest.composition,
1868
1921
  sourceArtifacts: await Promise.all(
1869
1922
  sourcePaths.map(async (sourcePath) => ({
1870
- artifactId: import_node_path6.default.basename(sourcePath),
1923
+ artifactId: import_node_path4.default.basename(sourcePath),
1871
1924
  path: sourcePath,
1872
1925
  sha256: await sha256File(sourcePath)
1873
1926
  }))
@@ -1878,9 +1931,9 @@ var runtimeScorecard = async () => {
1878
1931
  let receiptPath2 = null;
1879
1932
  if (flags.markProcessed) {
1880
1933
  receiptPath2 = await markRuntimeEvidenceBundleProcessed({
1881
- evidenceRoot: import_node_path6.default.resolve(projectRoot, String(flags.evidenceDir)),
1934
+ evidenceRoot: import_node_path4.default.resolve(projectRoot, String(flags.evidenceDir)),
1882
1935
  deploymentId: String(flags.deployment),
1883
- bundleDir: import_node_path6.default.dirname(runtimeEvidencePath),
1936
+ bundleDir: import_node_path4.default.dirname(runtimeEvidencePath),
1884
1937
  scorecardPath: outPath
1885
1938
  });
1886
1939
  }