@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.
- package/dist/cli.js +581 -839
- package/dist/lib/runtimeDebugEvidence.js +7 -20
- package/dist/lib/runtimeEvidenceArtifacts.js +165 -0
- package/dist/lib/runtimeEvidenceDeployment.js +84 -4
- package/dist/lib/runtimeEvidenceSync.js +171 -112
- package/dist/lib/runtimeLineage.js +28 -306
- package/dist/lib/runtimeRedis.js +1 -3
- package/dist/lib/runtimeScorecard.js +177 -135
- package/dist/lib/strategyRelease.js +1 -1
- package/dist/scripts/replay.js +165 -370
- package/dist/scripts/replayRunner.js +165 -370
- package/dist/scripts/replayRuntimeEvidence.js +5 -16
- package/dist/scripts/runtimeEvidence.js +319 -187
- package/dist/scripts/runtimeEvidenceSync.js +172 -106
- package/dist/scripts/runtimeParity.js +1 -3
- package/dist/scripts/runtimeScorecard.js +220 -167
- package/dist/scripts/signals.js +47 -316
- package/dist/scripts/signalsDaemon.js +47 -316
- package/dist/scripts/signalsSummary.js +3 -8
- package/package.json +7 -7
|
@@ -65,9 +65,7 @@ var loadRuntimeTrades = async (userName, {
|
|
|
65
65
|
dedupedBucketTrades.set(trade.orderId, trade);
|
|
66
66
|
}
|
|
67
67
|
const windowedTrades = [...dedupedBucketTrades.values()].filter(filterByWindow).sort((left, right) => left.entryTimestamp - right.entryTimestamp);
|
|
68
|
-
|
|
69
|
-
return windowedTrades;
|
|
70
|
-
}
|
|
68
|
+
return windowedTrades;
|
|
71
69
|
}
|
|
72
70
|
const tradePrefix = import_redis.redisKeys.runtimeTrades(userName);
|
|
73
71
|
const bucketPrefix = import_redis.redisKeys.runtimeTradeBuckets(userName);
|
|
@@ -325,16 +323,14 @@ var collectRuntimeDebugEvidence = async ({
|
|
|
325
323
|
signals,
|
|
326
324
|
evaluations,
|
|
327
325
|
evaluationStatsBuckets,
|
|
328
|
-
lineageScopes
|
|
329
|
-
configs
|
|
326
|
+
lineageScopes
|
|
330
327
|
] = await Promise.all([
|
|
331
328
|
loadRuntimeTrades(userName, { startTime, endTime }),
|
|
332
329
|
loadRuntimeClosedTrades(userName, { startTime, endTime }),
|
|
333
330
|
loadRuntimeSignals(userName, { startTime, endTime }),
|
|
334
331
|
loadRuntimeSignalEvaluations(userName, { startTime, endTime }),
|
|
335
332
|
loadRuntimeSignalEvaluationStatsBuckets(userName),
|
|
336
|
-
loadRuntimeLineageScopes(userName, { startTime, endTime })
|
|
337
|
-
(0, import_runtimeStrategyConfigs.loadRuntimeStrategyConfigs)(userName)
|
|
333
|
+
loadRuntimeLineageScopes(userName, { startTime, endTime })
|
|
338
334
|
]);
|
|
339
335
|
const tradesByOrderId = new Map(
|
|
340
336
|
entryTrades.map((trade) => [trade.orderId, trade])
|
|
@@ -359,9 +355,6 @@ var collectRuntimeDebugEvidence = async ({
|
|
|
359
355
|
evaluationStatsBuckets: filteredStats,
|
|
360
356
|
lineageScopes: lineageScopes.filter(matchesDeployment).filter(
|
|
361
357
|
(scope) => !strategies?.length || strategies.includes(scope.strategy)
|
|
362
|
-
),
|
|
363
|
-
strategyConfigs: deploymentId ? [] : configs.filter(
|
|
364
|
-
(config) => !strategies?.length || strategies.includes(config.strategyName)
|
|
365
358
|
)
|
|
366
359
|
};
|
|
367
360
|
};
|
|
@@ -372,7 +365,6 @@ var buildRuntimeDebugReportPayload = async ({
|
|
|
372
365
|
signals,
|
|
373
366
|
evaluations,
|
|
374
367
|
trades,
|
|
375
|
-
strategyConfigs,
|
|
376
368
|
evaluationStatsBuckets,
|
|
377
369
|
lineageScopes
|
|
378
370
|
}) => {
|
|
@@ -502,8 +494,7 @@ var buildRuntimeDebugReportPayload = async ({
|
|
|
502
494
|
signals: signals.length,
|
|
503
495
|
evaluations: reportEvaluations.length,
|
|
504
496
|
evaluationStatsBuckets: evaluationStatsBuckets?.length ?? 0,
|
|
505
|
-
lineageScopes: lineageScopes?.length ?? 0
|
|
506
|
-
strategyConfigs: strategyConfigs?.length ?? 0
|
|
497
|
+
lineageScopes: lineageScopes?.length ?? 0
|
|
507
498
|
},
|
|
508
499
|
trades: debugTrades,
|
|
509
500
|
signals: signals.map((signal) => ({
|
|
@@ -526,8 +517,7 @@ var buildRuntimeDebugReportPayload = async ({
|
|
|
526
517
|
evaluation
|
|
527
518
|
})),
|
|
528
519
|
evaluationStatsBuckets: evaluationStatsBuckets ?? [],
|
|
529
|
-
lineageScopes: lineageScopes ?? []
|
|
530
|
-
strategyConfigs: strategyConfigs ?? []
|
|
520
|
+
lineageScopes: lineageScopes ?? []
|
|
531
521
|
};
|
|
532
522
|
};
|
|
533
523
|
var buildRuntimeEvidenceReportPayload = ({
|
|
@@ -537,7 +527,6 @@ var buildRuntimeEvidenceReportPayload = ({
|
|
|
537
527
|
signals,
|
|
538
528
|
evaluations,
|
|
539
529
|
trades,
|
|
540
|
-
strategyConfigs,
|
|
541
530
|
evaluationStatsBuckets,
|
|
542
531
|
lineageScopes
|
|
543
532
|
}) => ({
|
|
@@ -556,15 +545,13 @@ var buildRuntimeEvidenceReportPayload = ({
|
|
|
556
545
|
signals: signals.length,
|
|
557
546
|
evaluations: evaluations.length,
|
|
558
547
|
evaluationStatsBuckets: evaluationStatsBuckets?.length ?? 0,
|
|
559
|
-
lineageScopes: lineageScopes?.length ?? 0
|
|
560
|
-
strategyConfigs: strategyConfigs?.length ?? 0
|
|
548
|
+
lineageScopes: lineageScopes?.length ?? 0
|
|
561
549
|
},
|
|
562
550
|
trades: trades.map((trade) => ({ trade })),
|
|
563
551
|
signals: signals.map((signal) => ({ signal })),
|
|
564
552
|
evaluations: evaluations.map((evaluation) => ({ evaluation })),
|
|
565
553
|
evaluationStatsBuckets: evaluationStatsBuckets ?? [],
|
|
566
|
-
lineageScopes: lineageScopes ?? []
|
|
567
|
-
strategyConfigs: strategyConfigs ?? []
|
|
554
|
+
lineageScopes: lineageScopes ?? []
|
|
568
555
|
});
|
|
569
556
|
var buildRuntimeDebugReportAttachment = async (params) => {
|
|
570
557
|
const payload = await buildRuntimeDebugReportPayload(params);
|
|
@@ -41,6 +41,166 @@ module.exports = __toCommonJS(runtimeEvidenceArtifacts_exports);
|
|
|
41
41
|
var import_node_crypto = require("crypto");
|
|
42
42
|
var import_promises = __toESM(require("fs/promises"));
|
|
43
43
|
var import_node_path = __toESM(require("path"));
|
|
44
|
+
|
|
45
|
+
// src/lib/runtimeEvidenceDeployment.ts
|
|
46
|
+
var import_runtimeStrategies = require("@tradejs/node/runtimeStrategies");
|
|
47
|
+
var isRecord = (value) => value != null && typeof value === "object" && !Array.isArray(value);
|
|
48
|
+
var isNonEmptyString = (value) => typeof value === "string" && value.trim().length > 0;
|
|
49
|
+
var isPackageVersionMap = (value) => isRecord(value) && Object.keys(value).length > 0 && Object.entries(value).every(
|
|
50
|
+
([name, version]) => name.startsWith("@tradejs/") && isNonEmptyString(version)
|
|
51
|
+
);
|
|
52
|
+
var INTERVALS = /* @__PURE__ */ new Set([
|
|
53
|
+
"1",
|
|
54
|
+
"3",
|
|
55
|
+
"5",
|
|
56
|
+
"15",
|
|
57
|
+
"30",
|
|
58
|
+
"60",
|
|
59
|
+
"120",
|
|
60
|
+
"240",
|
|
61
|
+
"360",
|
|
62
|
+
"720",
|
|
63
|
+
"D",
|
|
64
|
+
"W",
|
|
65
|
+
"M"
|
|
66
|
+
]);
|
|
67
|
+
var UNIVERSES = /* @__PURE__ */ new Set(["crypto", "tradfi"]);
|
|
68
|
+
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));
|
|
69
|
+
var samePackageVersions = (left, right) => {
|
|
70
|
+
if (!left || !right) return false;
|
|
71
|
+
const leftEntries = Object.entries(left).sort(
|
|
72
|
+
([a], [b]) => a.localeCompare(b)
|
|
73
|
+
);
|
|
74
|
+
const rightEntries = Object.entries(right).sort(
|
|
75
|
+
([a], [b]) => a.localeCompare(b)
|
|
76
|
+
);
|
|
77
|
+
return JSON.stringify(leftEntries) === JSON.stringify(rightEntries);
|
|
78
|
+
};
|
|
79
|
+
var runtimeLineageMatchesStrategySnapshot = ({
|
|
80
|
+
lineage,
|
|
81
|
+
deployment,
|
|
82
|
+
strategy
|
|
83
|
+
}) => lineage?.schemaVersion === 3 && lineage.strategyRevision === strategy.strategyRevision && lineage.deploymentCompositionId === deployment.deploymentCompositionId && lineage.strategyPackageVersion === strategy.strategyPackageVersion && lineage.runtimePackageVersion === strategy.runtimePackageVersion && samePackageVersions(
|
|
84
|
+
lineage.strategyDependencyVersions,
|
|
85
|
+
strategy.strategyDependencyVersions
|
|
86
|
+
);
|
|
87
|
+
var parseRuntimeEvidenceDeploymentSnapshot = (value) => {
|
|
88
|
+
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)) {
|
|
89
|
+
throw new Error(
|
|
90
|
+
"Runtime evidence deployment snapshot is missing or invalid"
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
const strategies = value.strategies.map((candidate) => {
|
|
94
|
+
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)) {
|
|
95
|
+
throw new Error(
|
|
96
|
+
"Runtime evidence deployment strategy snapshot is invalid"
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
if (String(candidate.strategyConfig.INTERVAL) !== String(candidate.interval) || String(candidate.strategyConfig.UNIVERSE) !== String(candidate.universe)) {
|
|
100
|
+
throw new Error(
|
|
101
|
+
`Runtime evidence strategy config does not match its scope: ${candidate.strategyName}`
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
if (candidate.accountId != null && (!isNonEmptyString(candidate.accountId) || candidate.accountId !== value.accountId)) {
|
|
105
|
+
throw new Error(
|
|
106
|
+
`Runtime evidence strategy account does not match deployment: ${candidate.strategyName}`
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
return candidate;
|
|
110
|
+
});
|
|
111
|
+
const identities = /* @__PURE__ */ new Set();
|
|
112
|
+
for (const strategy of strategies) {
|
|
113
|
+
if (identities.has(strategy.strategyName)) {
|
|
114
|
+
throw new Error(
|
|
115
|
+
`Duplicate runtime evidence strategy: ${strategy.strategyName}`
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
identities.add(strategy.strategyName);
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
...value,
|
|
122
|
+
strategies
|
|
123
|
+
};
|
|
124
|
+
};
|
|
125
|
+
var activeRuntimeEvidenceStrategies = (deployment) => deployment.enabled ? deployment.strategies.filter((strategy) => strategy.enabled) : [];
|
|
126
|
+
var unwrapRuntimeEvidenceRows = (value, field) => (Array.isArray(value) ? value : []).map((candidate) => {
|
|
127
|
+
const record = isRecord(candidate) ? candidate : null;
|
|
128
|
+
const nested = record && isRecord(record[field]) ? record[field] : null;
|
|
129
|
+
return nested ?? record;
|
|
130
|
+
}).filter((record) => record != null);
|
|
131
|
+
var assertCurrentRuntimeEvidenceArtifact = (artifact) => {
|
|
132
|
+
if (!isRecord(artifact) || artifact.reportType !== "runtime-evidence") {
|
|
133
|
+
throw new Error("Invalid runtime evidence artifact");
|
|
134
|
+
}
|
|
135
|
+
const deployment = parseRuntimeEvidenceDeploymentSnapshot(
|
|
136
|
+
artifact.deployment
|
|
137
|
+
);
|
|
138
|
+
const activeStrategies = activeRuntimeEvidenceStrategies(deployment);
|
|
139
|
+
if (activeStrategies.length === 0) {
|
|
140
|
+
throw new Error("Runtime evidence deployment has no enabled strategies");
|
|
141
|
+
}
|
|
142
|
+
const runtime = isRecord(artifact.runtime) ? artifact.runtime : null;
|
|
143
|
+
if (!runtime) {
|
|
144
|
+
throw new Error("Runtime evidence payload is missing");
|
|
145
|
+
}
|
|
146
|
+
if ("strategyConfigs" in runtime) {
|
|
147
|
+
throw new Error(
|
|
148
|
+
"Runtime evidence payload contains removed strategyConfigs data"
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
const rowFields = [
|
|
152
|
+
"trades",
|
|
153
|
+
"signals",
|
|
154
|
+
"evaluations",
|
|
155
|
+
"lineageScopes"
|
|
156
|
+
];
|
|
157
|
+
for (const field of rowFields) {
|
|
158
|
+
if (!Array.isArray(runtime[field])) {
|
|
159
|
+
throw new Error(`Runtime evidence payload ${field} must be an array`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const snapshots = new Map(
|
|
163
|
+
activeStrategies.map((strategy) => [strategy.strategyName, strategy])
|
|
164
|
+
);
|
|
165
|
+
const assertRows = (label, rows, lineageField) => {
|
|
166
|
+
for (const row of rows) {
|
|
167
|
+
const strategyName = String(row.strategy ?? "").trim();
|
|
168
|
+
const strategy = snapshots.get(strategyName);
|
|
169
|
+
if (!strategy || row.deploymentId !== deployment.id || row.accountId !== deployment.accountId || !runtimeLineageMatchesStrategySnapshot({
|
|
170
|
+
lineage: isRecord(row[lineageField]) ? row[lineageField] : void 0,
|
|
171
|
+
deployment,
|
|
172
|
+
strategy
|
|
173
|
+
})) {
|
|
174
|
+
throw new Error(
|
|
175
|
+
`Runtime evidence ${label} row is outside the current embedded deployment lineage`
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
assertRows(
|
|
181
|
+
"trade",
|
|
182
|
+
unwrapRuntimeEvidenceRows(runtime.trades, "trade"),
|
|
183
|
+
"runtimeLineage"
|
|
184
|
+
);
|
|
185
|
+
assertRows(
|
|
186
|
+
"signal",
|
|
187
|
+
unwrapRuntimeEvidenceRows(runtime.signals, "signal"),
|
|
188
|
+
"runtimeLineage"
|
|
189
|
+
);
|
|
190
|
+
assertRows(
|
|
191
|
+
"evaluation",
|
|
192
|
+
unwrapRuntimeEvidenceRows(runtime.evaluations, "evaluation"),
|
|
193
|
+
"runtimeLineage"
|
|
194
|
+
);
|
|
195
|
+
assertRows(
|
|
196
|
+
"lineage scope",
|
|
197
|
+
unwrapRuntimeEvidenceRows(runtime.lineageScopes, "lineageScope"),
|
|
198
|
+
"lineage"
|
|
199
|
+
);
|
|
200
|
+
return deployment;
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
// src/lib/runtimeEvidenceArtifacts.ts
|
|
44
204
|
var RUNTIME_EVIDENCE_MANIFEST_FILE = "manifest.json";
|
|
45
205
|
var RUNTIME_EVIDENCE_PAYLOAD_FILE = "runtime-evidence.json";
|
|
46
206
|
var RUNTIME_EVIDENCE_COMPLETE_FILE = ".complete";
|
|
@@ -124,6 +284,7 @@ var publishRuntimeEvidenceBundle = async ({
|
|
|
124
284
|
counts,
|
|
125
285
|
lineageKeys
|
|
126
286
|
}) => {
|
|
287
|
+
assertCurrentRuntimeEvidenceArtifact(artifact);
|
|
127
288
|
const payload = `${JSON.stringify(artifact, null, 2)}
|
|
128
289
|
`;
|
|
129
290
|
const payloadSha256 = sha256(payload);
|
|
@@ -223,6 +384,10 @@ var verifyRuntimeEvidenceBundle = async (bundleDir) => {
|
|
|
223
384
|
if (artifact?.reportType !== "runtime-evidence" || artifactWindow?.startTime !== manifest.window.startTime || artifactWindow.endTime !== manifest.window.endTime) {
|
|
224
385
|
throw new Error(`Runtime evidence payload mismatch in ${bundleDir}`);
|
|
225
386
|
}
|
|
387
|
+
const deployment = assertCurrentRuntimeEvidenceArtifact(artifact);
|
|
388
|
+
if (deployment.id !== manifest.deploymentId) {
|
|
389
|
+
throw new Error(`Runtime evidence deployment mismatch in ${bundleDir}`);
|
|
390
|
+
}
|
|
226
391
|
return {
|
|
227
392
|
bundleDir,
|
|
228
393
|
manifestPath,
|
|
@@ -21,10 +21,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var runtimeEvidenceDeployment_exports = {};
|
|
22
22
|
__export(runtimeEvidenceDeployment_exports, {
|
|
23
23
|
activeRuntimeEvidenceStrategies: () => activeRuntimeEvidenceStrategies,
|
|
24
|
+
assertCurrentRuntimeEvidenceArtifact: () => assertCurrentRuntimeEvidenceArtifact,
|
|
24
25
|
parseRuntimeEvidenceDeploymentSnapshot: () => parseRuntimeEvidenceDeploymentSnapshot,
|
|
25
26
|
resolveRuntimeEvidenceDeploymentSnapshot: () => resolveRuntimeEvidenceDeploymentSnapshot,
|
|
26
27
|
resolveRuntimeEvidenceTickerUniverse: () => resolveRuntimeEvidenceTickerUniverse,
|
|
27
|
-
runtimeDeploymentFromEvidence: () => runtimeDeploymentFromEvidence
|
|
28
|
+
runtimeDeploymentFromEvidence: () => runtimeDeploymentFromEvidence,
|
|
29
|
+
runtimeLineageMatchesStrategySnapshot: () => runtimeLineageMatchesStrategySnapshot
|
|
28
30
|
});
|
|
29
31
|
module.exports = __toCommonJS(runtimeEvidenceDeployment_exports);
|
|
30
32
|
var import_runtimeStrategies = require("@tradejs/node/runtimeStrategies");
|
|
@@ -60,7 +62,7 @@ var samePackageVersions = (left, right) => {
|
|
|
60
62
|
);
|
|
61
63
|
return JSON.stringify(leftEntries) === JSON.stringify(rightEntries);
|
|
62
64
|
};
|
|
63
|
-
var
|
|
65
|
+
var runtimeLineageMatchesStrategySnapshot = ({
|
|
64
66
|
lineage,
|
|
65
67
|
deployment,
|
|
66
68
|
strategy
|
|
@@ -107,6 +109,82 @@ var parseRuntimeEvidenceDeploymentSnapshot = (value) => {
|
|
|
107
109
|
};
|
|
108
110
|
};
|
|
109
111
|
var activeRuntimeEvidenceStrategies = (deployment) => deployment.enabled ? deployment.strategies.filter((strategy) => strategy.enabled) : [];
|
|
112
|
+
var unwrapRuntimeEvidenceRows = (value, field) => (Array.isArray(value) ? value : []).map((candidate) => {
|
|
113
|
+
const record = isRecord(candidate) ? candidate : null;
|
|
114
|
+
const nested = record && isRecord(record[field]) ? record[field] : null;
|
|
115
|
+
return nested ?? record;
|
|
116
|
+
}).filter((record) => record != null);
|
|
117
|
+
var assertCurrentRuntimeEvidenceArtifact = (artifact) => {
|
|
118
|
+
if (!isRecord(artifact) || artifact.reportType !== "runtime-evidence") {
|
|
119
|
+
throw new Error("Invalid runtime evidence artifact");
|
|
120
|
+
}
|
|
121
|
+
const deployment = parseRuntimeEvidenceDeploymentSnapshot(
|
|
122
|
+
artifact.deployment
|
|
123
|
+
);
|
|
124
|
+
const activeStrategies = activeRuntimeEvidenceStrategies(deployment);
|
|
125
|
+
if (activeStrategies.length === 0) {
|
|
126
|
+
throw new Error("Runtime evidence deployment has no enabled strategies");
|
|
127
|
+
}
|
|
128
|
+
const runtime = isRecord(artifact.runtime) ? artifact.runtime : null;
|
|
129
|
+
if (!runtime) {
|
|
130
|
+
throw new Error("Runtime evidence payload is missing");
|
|
131
|
+
}
|
|
132
|
+
if ("strategyConfigs" in runtime) {
|
|
133
|
+
throw new Error(
|
|
134
|
+
"Runtime evidence payload contains removed strategyConfigs data"
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
const rowFields = [
|
|
138
|
+
"trades",
|
|
139
|
+
"signals",
|
|
140
|
+
"evaluations",
|
|
141
|
+
"lineageScopes"
|
|
142
|
+
];
|
|
143
|
+
for (const field of rowFields) {
|
|
144
|
+
if (!Array.isArray(runtime[field])) {
|
|
145
|
+
throw new Error(`Runtime evidence payload ${field} must be an array`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
const snapshots = new Map(
|
|
149
|
+
activeStrategies.map((strategy) => [strategy.strategyName, strategy])
|
|
150
|
+
);
|
|
151
|
+
const assertRows = (label, rows, lineageField) => {
|
|
152
|
+
for (const row of rows) {
|
|
153
|
+
const strategyName = String(row.strategy ?? "").trim();
|
|
154
|
+
const strategy = snapshots.get(strategyName);
|
|
155
|
+
if (!strategy || row.deploymentId !== deployment.id || row.accountId !== deployment.accountId || !runtimeLineageMatchesStrategySnapshot({
|
|
156
|
+
lineage: isRecord(row[lineageField]) ? row[lineageField] : void 0,
|
|
157
|
+
deployment,
|
|
158
|
+
strategy
|
|
159
|
+
})) {
|
|
160
|
+
throw new Error(
|
|
161
|
+
`Runtime evidence ${label} row is outside the current embedded deployment lineage`
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
assertRows(
|
|
167
|
+
"trade",
|
|
168
|
+
unwrapRuntimeEvidenceRows(runtime.trades, "trade"),
|
|
169
|
+
"runtimeLineage"
|
|
170
|
+
);
|
|
171
|
+
assertRows(
|
|
172
|
+
"signal",
|
|
173
|
+
unwrapRuntimeEvidenceRows(runtime.signals, "signal"),
|
|
174
|
+
"runtimeLineage"
|
|
175
|
+
);
|
|
176
|
+
assertRows(
|
|
177
|
+
"evaluation",
|
|
178
|
+
unwrapRuntimeEvidenceRows(runtime.evaluations, "evaluation"),
|
|
179
|
+
"runtimeLineage"
|
|
180
|
+
);
|
|
181
|
+
assertRows(
|
|
182
|
+
"lineage scope",
|
|
183
|
+
unwrapRuntimeEvidenceRows(runtime.lineageScopes, "lineageScope"),
|
|
184
|
+
"lineage"
|
|
185
|
+
);
|
|
186
|
+
return deployment;
|
|
187
|
+
};
|
|
110
188
|
var resolveRuntimeEvidenceTickerUniverse = ({
|
|
111
189
|
deployment,
|
|
112
190
|
lineageScopes
|
|
@@ -139,7 +217,7 @@ var resolveRuntimeEvidenceTickerUniverse = ({
|
|
|
139
217
|
const tickers = /* @__PURE__ */ new Set();
|
|
140
218
|
for (const scope of lineageScopes) {
|
|
141
219
|
const strategy = strategiesByName.get(scope.strategy);
|
|
142
|
-
if (!strategy || scope.deploymentId !== deployment.id || scope.accountId !== deployment.accountId || !isNonEmptyString(scope.symbol) || !
|
|
220
|
+
if (!strategy || scope.deploymentId !== deployment.id || scope.accountId !== deployment.accountId || !isNonEmptyString(scope.symbol) || !runtimeLineageMatchesStrategySnapshot({
|
|
143
221
|
lineage: scope.lineage,
|
|
144
222
|
deployment,
|
|
145
223
|
strategy
|
|
@@ -234,8 +312,10 @@ var resolveRuntimeEvidenceDeploymentSnapshot = async ({
|
|
|
234
312
|
// Annotate the CommonJS export names for ESM import in node:
|
|
235
313
|
0 && (module.exports = {
|
|
236
314
|
activeRuntimeEvidenceStrategies,
|
|
315
|
+
assertCurrentRuntimeEvidenceArtifact,
|
|
237
316
|
parseRuntimeEvidenceDeploymentSnapshot,
|
|
238
317
|
resolveRuntimeEvidenceDeploymentSnapshot,
|
|
239
318
|
resolveRuntimeEvidenceTickerUniverse,
|
|
240
|
-
runtimeDeploymentFromEvidence
|
|
319
|
+
runtimeDeploymentFromEvidence,
|
|
320
|
+
runtimeLineageMatchesStrategySnapshot
|
|
241
321
|
});
|