@tradejs/cli 2.0.19 → 2.0.20
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 +8787 -3214
- package/dist/lib/aiExport.js +14 -1
- package/dist/lib/aiPocketSearch.js +499 -67
- package/dist/lib/aiPocketSearchCli.js +113 -0
- package/dist/lib/aiTrainCharts.js +14 -1
- package/dist/lib/aiTrainMetrics.js +4 -1
- package/dist/lib/aiTrainResearch.js +88 -54
- package/dist/lib/coreResearch.js +2738 -0
- package/dist/lib/executionCalibration.js +6 -3
- package/dist/lib/runtimeLineage.js +81 -48
- package/dist/lib/runtimeScorecard.js +153 -10
- package/dist/lib/strategyGateFingerprint.js +80 -0
- package/dist/lib/strategyRelease.js +1365 -0
- package/dist/scripts/aiExport.js +16 -3
- package/dist/scripts/aiPocketSearch.js +1069 -163
- package/dist/scripts/aiTrain.js +91 -65
- package/dist/scripts/backtest.js +10 -1
- package/dist/scripts/coreResearch.js +2830 -0
- package/dist/scripts/executionCalibration.js +6 -3
- package/dist/scripts/replay.js +106 -73
- package/dist/scripts/replayRunner.js +106 -73
- package/dist/scripts/replayRuntimeEvidence.js +27 -14
- package/dist/scripts/runtimeEvidence.js +16 -8
- package/dist/scripts/runtimeScorecard.js +883 -29
- package/dist/scripts/signals.js +133 -89
- package/dist/scripts/signalsDaemon.js +133 -89
- package/dist/scripts/strategyRelease.js +1469 -0
- package/package.json +11 -9
|
@@ -22,9 +22,96 @@ var aiPocketSearchCli_exports = {};
|
|
|
22
22
|
__export(aiPocketSearchCli_exports, {
|
|
23
23
|
AI_POCKET_SEARCH_CLI_DECIMAL_DEFAULTS: () => AI_POCKET_SEARCH_CLI_DECIMAL_DEFAULTS,
|
|
24
24
|
readAiPocketSearchCliOption: () => readAiPocketSearchCliOption,
|
|
25
|
+
resolveAiPocketCadenceProfile: () => resolveAiPocketCadenceProfile,
|
|
26
|
+
sealAiPocketTestPartition: () => sealAiPocketTestPartition,
|
|
27
|
+
splitAiPocketCoverageRowsByTimestamp: () => splitAiPocketCoverageRowsByTimestamp,
|
|
25
28
|
splitAiPocketResearchRowsByTimestamp: () => splitAiPocketResearchRowsByTimestamp
|
|
26
29
|
});
|
|
27
30
|
module.exports = __toCommonJS(aiPocketSearchCli_exports);
|
|
31
|
+
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
32
|
+
var DEFAULT_MIN_SUPPORT = 20;
|
|
33
|
+
var LOW_CADENCE_EVENT_LIMIT = 200;
|
|
34
|
+
var LOW_CADENCE_MAX_EVENT_SHARE = 1 / 3;
|
|
35
|
+
var countIndependentEvents = (rows) => {
|
|
36
|
+
const timestampEvents = /* @__PURE__ */ new Set();
|
|
37
|
+
let rowsWithoutTimestamp = 0;
|
|
38
|
+
for (const row of rows) {
|
|
39
|
+
if (typeof row.timestamp === "number" && Number.isFinite(row.timestamp)) {
|
|
40
|
+
timestampEvents.add(row.timestamp);
|
|
41
|
+
} else {
|
|
42
|
+
rowsWithoutTimestamp += 1;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return timestampEvents.size + rowsWithoutTimestamp;
|
|
46
|
+
};
|
|
47
|
+
var getPeriodDays = (rows) => {
|
|
48
|
+
let minTimestamp = null;
|
|
49
|
+
let maxTimestamp = null;
|
|
50
|
+
for (const row of rows) {
|
|
51
|
+
const timestamp = row.timestamp;
|
|
52
|
+
if (typeof timestamp !== "number" || !Number.isFinite(timestamp)) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
minTimestamp = minTimestamp == null ? timestamp : Math.min(minTimestamp, timestamp);
|
|
56
|
+
maxTimestamp = maxTimestamp == null ? timestamp : Math.max(maxTimestamp, timestamp);
|
|
57
|
+
}
|
|
58
|
+
if (minTimestamp == null || maxTimestamp == null) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
return Math.max((maxTimestamp - minTimestamp) / DAY_MS, 1);
|
|
62
|
+
};
|
|
63
|
+
var clampInt = (value, minimum, maximum) => Math.max(minimum, Math.min(maximum, Math.ceil(value)));
|
|
64
|
+
var resolveAiPocketCadenceProfile = ({
|
|
65
|
+
trainRows,
|
|
66
|
+
validationRows = [],
|
|
67
|
+
testRows = [],
|
|
68
|
+
mode = "auto",
|
|
69
|
+
validationSplit = 0.25,
|
|
70
|
+
minSupport,
|
|
71
|
+
minEvents,
|
|
72
|
+
minValidationSupport,
|
|
73
|
+
minValidationEvents,
|
|
74
|
+
maxEventCountShare = 0.25,
|
|
75
|
+
explicitMaxEventCountShare = false
|
|
76
|
+
}) => {
|
|
77
|
+
const trainEvents = countIndependentEvents(trainRows);
|
|
78
|
+
const validationEvents = countIndependentEvents(validationRows);
|
|
79
|
+
const testEvents = countIndependentEvents(testRows);
|
|
80
|
+
const trainPeriodDays = getPeriodDays(trainRows);
|
|
81
|
+
const trainEventsPerDay = trainPeriodDays == null ? null : trainEvents / trainPeriodDays;
|
|
82
|
+
const sparseSample = trainEvents < LOW_CADENCE_EVENT_LIMIT;
|
|
83
|
+
const lowCadence = trainEventsPerDay != null && trainEventsPerDay < 0.25;
|
|
84
|
+
const adaptiveSample = mode === "auto" && sparseSample;
|
|
85
|
+
const adaptiveThresholds = adaptiveSample && (minSupport == null || minEvents == null || validationRows.length > 0 && (minValidationSupport == null || minValidationEvents == null) || !explicitMaxEventCountShare);
|
|
86
|
+
const resolvedMinSupport = minSupport ?? (adaptiveSample ? clampInt(trainEvents * 0.1, 3, DEFAULT_MIN_SUPPORT) : DEFAULT_MIN_SUPPORT);
|
|
87
|
+
const resolvedMinEvents = minEvents ?? (minSupport != null || !adaptiveSample ? Math.max(5, Math.ceil(resolvedMinSupport * 0.5)) : clampInt(resolvedMinSupport * 0.5, 3, 10));
|
|
88
|
+
const hasValidation = validationRows.length > 0;
|
|
89
|
+
const resolvedMinValidationSupport = minValidationSupport ?? (hasValidation ? Math.max(3, Math.ceil(resolvedMinSupport * validationSplit * 0.5)) : 0);
|
|
90
|
+
const resolvedMinValidationEvents = minValidationEvents ?? (hasValidation ? Math.max(
|
|
91
|
+
adaptiveSample ? 3 : 2,
|
|
92
|
+
Math.ceil(resolvedMinEvents * validationSplit * 0.5)
|
|
93
|
+
) : 0);
|
|
94
|
+
const resolvedMaxEventCountShare = adaptiveSample && !explicitMaxEventCountShare ? Math.max(maxEventCountShare, LOW_CADENCE_MAX_EVENT_SHARE) : maxEventCountShare;
|
|
95
|
+
return {
|
|
96
|
+
mode,
|
|
97
|
+
lowCadence,
|
|
98
|
+
sparseSample,
|
|
99
|
+
adaptiveThresholds,
|
|
100
|
+
trainRows: trainRows.length,
|
|
101
|
+
trainEvents,
|
|
102
|
+
trainPeriodDays,
|
|
103
|
+
trainEventsPerDay,
|
|
104
|
+
validationRows: validationRows.length,
|
|
105
|
+
validationEvents,
|
|
106
|
+
testRows: testRows.length,
|
|
107
|
+
testEvents,
|
|
108
|
+
minSupport: resolvedMinSupport,
|
|
109
|
+
minEvents: resolvedMinEvents,
|
|
110
|
+
minValidationSupport: resolvedMinValidationSupport,
|
|
111
|
+
minValidationEvents: resolvedMinValidationEvents,
|
|
112
|
+
maxEventCountShare: resolvedMaxEventCountShare
|
|
113
|
+
};
|
|
114
|
+
};
|
|
28
115
|
var AI_POCKET_SEARCH_CLI_DECIMAL_DEFAULTS = {
|
|
29
116
|
minProfitFactor: "1.2",
|
|
30
117
|
minWinRate: "0",
|
|
@@ -71,6 +158,29 @@ var splitAiPocketResearchRowsByTimestamp = (rows, validationSplit, testSplit = 0
|
|
|
71
158
|
testRows: rows.filter((row) => isIn(testTimestamps, row.timestamp))
|
|
72
159
|
};
|
|
73
160
|
};
|
|
161
|
+
var splitAiPocketCoverageRowsByTimestamp = (rows, family, validationSplit, testSplit = 0) => splitAiPocketResearchRowsByTimestamp(
|
|
162
|
+
rows.filter((row) => row.featureCoverage?.[family] === true),
|
|
163
|
+
validationSplit,
|
|
164
|
+
testSplit
|
|
165
|
+
);
|
|
166
|
+
var sealAiPocketTestPartition = (split, sealed) => {
|
|
167
|
+
const finiteTimestamps = split.testRows.map((row) => row.timestamp).filter((timestamp) => Number.isFinite(timestamp));
|
|
168
|
+
return {
|
|
169
|
+
discoveryRows: [
|
|
170
|
+
...split.trainRows,
|
|
171
|
+
...split.validationRows,
|
|
172
|
+
...sealed ? [] : split.testRows
|
|
173
|
+
],
|
|
174
|
+
searchTestRows: sealed ? [] : split.testRows,
|
|
175
|
+
evidence: {
|
|
176
|
+
sealed,
|
|
177
|
+
rows: split.testRows.length,
|
|
178
|
+
events: countIndependentEvents(split.testRows),
|
|
179
|
+
startTimestamp: finiteTimestamps.length ? Math.min(...finiteTimestamps) : null,
|
|
180
|
+
endTimestamp: finiteTimestamps.length ? Math.max(...finiteTimestamps) : null
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
};
|
|
74
184
|
var readAiPocketSearchCliOption = ({
|
|
75
185
|
argv,
|
|
76
186
|
longName,
|
|
@@ -92,5 +202,8 @@ var readAiPocketSearchCliOption = ({
|
|
|
92
202
|
0 && (module.exports = {
|
|
93
203
|
AI_POCKET_SEARCH_CLI_DECIMAL_DEFAULTS,
|
|
94
204
|
readAiPocketSearchCliOption,
|
|
205
|
+
resolveAiPocketCadenceProfile,
|
|
206
|
+
sealAiPocketTestPartition,
|
|
207
|
+
splitAiPocketCoverageRowsByTimestamp,
|
|
95
208
|
splitAiPocketResearchRowsByTimestamp
|
|
96
209
|
});
|
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/lib/aiTrainCharts.ts
|
|
21
21
|
var aiTrainCharts_exports = {};
|
|
22
22
|
__export(aiTrainCharts_exports, {
|
|
23
|
+
buildAiChartPersistenceReceipt: () => buildAiChartPersistenceReceipt,
|
|
23
24
|
buildAiChartSnapshot: () => buildAiChartSnapshot
|
|
24
25
|
});
|
|
25
26
|
module.exports = __toCommonJS(aiTrainCharts_exports);
|
|
@@ -303,7 +304,10 @@ var getDirectionSortKey = (direction) => {
|
|
|
303
304
|
return 2;
|
|
304
305
|
};
|
|
305
306
|
var summarizeAiTrainEvaluationsByDirection = (evaluations) => {
|
|
306
|
-
const grouped = /* @__PURE__ */ new Map(
|
|
307
|
+
const grouped = /* @__PURE__ */ new Map([
|
|
308
|
+
["LONG", []],
|
|
309
|
+
["SHORT", []]
|
|
310
|
+
]);
|
|
307
311
|
for (const evaluation of evaluations) {
|
|
308
312
|
const direction = typeof evaluation.direction === "string" && evaluation.direction.trim() ? evaluation.direction : "UNKNOWN";
|
|
309
313
|
const bucket = grouped.get(direction) ?? [];
|
|
@@ -752,7 +756,16 @@ var buildAiChartSnapshot = (params) => {
|
|
|
752
756
|
strategies: cards
|
|
753
757
|
};
|
|
754
758
|
};
|
|
759
|
+
var buildAiChartPersistenceReceipt = (params) => ({
|
|
760
|
+
persisted: true,
|
|
761
|
+
mode: params.snapshot.mode,
|
|
762
|
+
datasetId: params.datasetId,
|
|
763
|
+
generatedAt: params.snapshot.generatedAt,
|
|
764
|
+
cardIds: params.snapshot.strategies.map((card) => card.cardId),
|
|
765
|
+
ttlMs: params.ttlMs
|
|
766
|
+
});
|
|
755
767
|
// Annotate the CommonJS export names for ESM import in node:
|
|
756
768
|
0 && (module.exports = {
|
|
769
|
+
buildAiChartPersistenceReceipt,
|
|
757
770
|
buildAiChartSnapshot
|
|
758
771
|
});
|
|
@@ -314,7 +314,10 @@ var isDirectionMatchAtThreshold = (evaluation, threshold) => {
|
|
|
314
314
|
return directionMatches === true && evaluation.quality != null && evaluation.quality >= threshold;
|
|
315
315
|
};
|
|
316
316
|
var summarizeAiTrainEvaluationsByDirection = (evaluations) => {
|
|
317
|
-
const grouped = /* @__PURE__ */ new Map(
|
|
317
|
+
const grouped = /* @__PURE__ */ new Map([
|
|
318
|
+
["LONG", []],
|
|
319
|
+
["SHORT", []]
|
|
320
|
+
]);
|
|
318
321
|
for (const evaluation of evaluations) {
|
|
319
322
|
const direction = typeof evaluation.direction === "string" && evaluation.direction.trim() ? evaluation.direction : "UNKNOWN";
|
|
320
323
|
const bucket = grouped.get(direction) ?? [];
|
|
@@ -39,9 +39,9 @@ __export(aiTrainResearch_exports, {
|
|
|
39
39
|
});
|
|
40
40
|
module.exports = __toCommonJS(aiTrainResearch_exports);
|
|
41
41
|
var import_node_child_process = require("child_process");
|
|
42
|
-
var
|
|
43
|
-
var
|
|
44
|
-
var
|
|
42
|
+
var import_node_crypto2 = require("crypto");
|
|
43
|
+
var import_promises2 = __toESM(require("fs/promises"));
|
|
44
|
+
var import_node_path2 = __toESM(require("path"));
|
|
45
45
|
|
|
46
46
|
// src/lib/aiTrainMetrics.ts
|
|
47
47
|
var divideOrNull = (num, denom) => {
|
|
@@ -312,10 +312,82 @@ var summarizeAiTrainEvaluations = (evaluations) => {
|
|
|
312
312
|
)
|
|
313
313
|
};
|
|
314
314
|
};
|
|
315
|
+
var getDirectionSortKey = (direction) => {
|
|
316
|
+
if (direction === "LONG") {
|
|
317
|
+
return 0;
|
|
318
|
+
}
|
|
319
|
+
if (direction === "SHORT") {
|
|
320
|
+
return 1;
|
|
321
|
+
}
|
|
322
|
+
return 2;
|
|
323
|
+
};
|
|
324
|
+
var summarizeAiTrainEvaluationsByDirection = (evaluations) => {
|
|
325
|
+
const grouped = /* @__PURE__ */ new Map([
|
|
326
|
+
["LONG", []],
|
|
327
|
+
["SHORT", []]
|
|
328
|
+
]);
|
|
329
|
+
for (const evaluation of evaluations) {
|
|
330
|
+
const direction = typeof evaluation.direction === "string" && evaluation.direction.trim() ? evaluation.direction : "UNKNOWN";
|
|
331
|
+
const bucket = grouped.get(direction) ?? [];
|
|
332
|
+
bucket.push(evaluation);
|
|
333
|
+
grouped.set(direction, bucket);
|
|
334
|
+
}
|
|
335
|
+
return [...grouped.entries()].sort(
|
|
336
|
+
([leftDirection], [rightDirection]) => getDirectionSortKey(leftDirection) - getDirectionSortKey(rightDirection) || leftDirection.localeCompare(rightDirection)
|
|
337
|
+
).map(([direction, directionEvaluations]) => ({
|
|
338
|
+
direction,
|
|
339
|
+
summary: summarizeAiTrainEvaluations(directionEvaluations)
|
|
340
|
+
}));
|
|
341
|
+
};
|
|
315
342
|
|
|
316
343
|
// src/lib/aiTrainResearch.ts
|
|
317
344
|
var import_strategies = require("@tradejs/node/strategies");
|
|
318
345
|
var import_types = require("@tradejs/types");
|
|
346
|
+
|
|
347
|
+
// src/lib/strategyGateFingerprint.ts
|
|
348
|
+
var import_node_crypto = require("crypto");
|
|
349
|
+
var import_promises = __toESM(require("fs/promises"));
|
|
350
|
+
var import_node_path = __toESM(require("path"));
|
|
351
|
+
var gateFingerprintRelativePaths = (strategyName) => [
|
|
352
|
+
`packages/strategies/src/${strategyName}/adapters/ai.ts`,
|
|
353
|
+
`packages/strategies/src/${strategyName}/guardrails.ts`,
|
|
354
|
+
`packages/strategies/src/${strategyName}/pockets.ts`,
|
|
355
|
+
`packages/strategies/src/${strategyName}/config.ts`,
|
|
356
|
+
"packages/strategies/src/shared/localAiGate.ts",
|
|
357
|
+
"packages/node/src/ai.ts",
|
|
358
|
+
"packages/core/src/utils/strategyHelpers/signalBuilders.ts"
|
|
359
|
+
];
|
|
360
|
+
var resolveStrategyGateFingerprint = async ({
|
|
361
|
+
projectRoot,
|
|
362
|
+
strategyName,
|
|
363
|
+
gitSha
|
|
364
|
+
}) => {
|
|
365
|
+
const candidates = await Promise.all(
|
|
366
|
+
gateFingerprintRelativePaths(strategyName).map(async (relativePath) => {
|
|
367
|
+
const content = await import_promises.default.readFile(import_node_path.default.join(projectRoot, relativePath)).catch(() => null);
|
|
368
|
+
return content == null ? null : { relativePath, content };
|
|
369
|
+
})
|
|
370
|
+
);
|
|
371
|
+
const sourceEntries = candidates.filter(
|
|
372
|
+
(entry) => entry != null
|
|
373
|
+
);
|
|
374
|
+
const hash = (0, import_node_crypto.createHash)("sha256");
|
|
375
|
+
hash.update(strategyName);
|
|
376
|
+
if (sourceEntries.length) {
|
|
377
|
+
for (const entry of sourceEntries) {
|
|
378
|
+
hash.update(entry.relativePath);
|
|
379
|
+
hash.update(entry.content);
|
|
380
|
+
}
|
|
381
|
+
} else {
|
|
382
|
+
hash.update(gitSha ?? "unknown-git-sha");
|
|
383
|
+
}
|
|
384
|
+
return {
|
|
385
|
+
gateFingerprint: hash.digest("hex").slice(0, 16),
|
|
386
|
+
gateFingerprintFiles: sourceEntries.map((entry) => entry.relativePath)
|
|
387
|
+
};
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
// src/lib/aiTrainResearch.ts
|
|
319
391
|
var DAY_MS2 = 24 * 60 * 60 * 1e3;
|
|
320
392
|
var RESEARCH_CONTEXT_ENV_KEYS = [
|
|
321
393
|
"AI_MODE",
|
|
@@ -355,9 +427,9 @@ var writeAiTrainResearchSnapshot = async ({
|
|
|
355
427
|
outputPath,
|
|
356
428
|
result
|
|
357
429
|
}) => {
|
|
358
|
-
const resolvedPath =
|
|
359
|
-
await
|
|
360
|
-
await
|
|
430
|
+
const resolvedPath = import_node_path2.default.resolve(outputPath);
|
|
431
|
+
await import_promises2.default.mkdir(import_node_path2.default.dirname(resolvedPath), { recursive: true });
|
|
432
|
+
await import_promises2.default.writeFile(
|
|
361
433
|
resolvedPath,
|
|
362
434
|
`${JSON.stringify(result, null, 2)}
|
|
363
435
|
`,
|
|
@@ -376,7 +448,7 @@ var normalizeForStableJson = (value) => {
|
|
|
376
448
|
}
|
|
377
449
|
return value;
|
|
378
450
|
};
|
|
379
|
-
var fingerprintResearchValue = (value) => (0,
|
|
451
|
+
var fingerprintResearchValue = (value) => (0, import_node_crypto2.createHash)("sha256").update(JSON.stringify(normalizeForStableJson(value))).digest("hex").slice(0, 16);
|
|
380
452
|
var getTimestampRange = (evaluations) => {
|
|
381
453
|
let minTimestamp = null;
|
|
382
454
|
let maxTimestamp = null;
|
|
@@ -441,17 +513,11 @@ var summarizeAiTrainTerminalWindows = (evaluations, windowDays) => {
|
|
|
441
513
|
selected: selected.length,
|
|
442
514
|
approvedPerCalendarDay: outcome.approved / coverageDays,
|
|
443
515
|
outcome,
|
|
516
|
+
byDirection: summarizeAiTrainEvaluationsByDirection(selected),
|
|
444
517
|
topRejectReasons: summarizeAiTrainRejectReasons(selected)
|
|
445
518
|
};
|
|
446
519
|
});
|
|
447
520
|
};
|
|
448
|
-
var readOptionalFile = async (filePath) => {
|
|
449
|
-
try {
|
|
450
|
-
return await import_promises.default.readFile(filePath);
|
|
451
|
-
} catch {
|
|
452
|
-
return null;
|
|
453
|
-
}
|
|
454
|
-
};
|
|
455
521
|
var getGitLineage = (projectRoot) => {
|
|
456
522
|
try {
|
|
457
523
|
const gitSha = (0, import_node_child_process.execFileSync)("git", ["rev-parse", "HEAD"], {
|
|
@@ -473,53 +539,20 @@ var getGitLineage = (projectRoot) => {
|
|
|
473
539
|
return { gitSha: null, gitDirty: null };
|
|
474
540
|
}
|
|
475
541
|
};
|
|
476
|
-
var resolveGateFingerprint = async (projectRoot, strategyName, gitSha) => {
|
|
477
|
-
const relativeCandidates = [
|
|
478
|
-
`packages/strategies/src/${strategyName}/adapters/ai.ts`,
|
|
479
|
-
`packages/strategies/src/${strategyName}/guardrails.ts`,
|
|
480
|
-
`packages/strategies/src/${strategyName}/pockets.ts`,
|
|
481
|
-
`packages/strategies/src/${strategyName}/config.ts`,
|
|
482
|
-
"packages/strategies/src/shared/localAiGate.ts",
|
|
483
|
-
"packages/node/src/ai.ts"
|
|
484
|
-
];
|
|
485
|
-
const optionalSourceEntries = await Promise.all(
|
|
486
|
-
relativeCandidates.map(async (relativePath) => {
|
|
487
|
-
const content = await readOptionalFile(
|
|
488
|
-
import_node_path.default.join(projectRoot, relativePath)
|
|
489
|
-
);
|
|
490
|
-
return content == null ? null : { relativePath, content };
|
|
491
|
-
})
|
|
492
|
-
);
|
|
493
|
-
const sourceEntries = [];
|
|
494
|
-
for (const entry of optionalSourceEntries) {
|
|
495
|
-
if (entry != null) {
|
|
496
|
-
sourceEntries.push(entry);
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
const hash = (0, import_node_crypto.createHash)("sha256");
|
|
500
|
-
hash.update(strategyName);
|
|
501
|
-
if (sourceEntries.length) {
|
|
502
|
-
for (const entry of sourceEntries) {
|
|
503
|
-
hash.update(entry.relativePath);
|
|
504
|
-
hash.update(entry.content);
|
|
505
|
-
}
|
|
506
|
-
} else {
|
|
507
|
-
hash.update(gitSha ?? "unknown-git-sha");
|
|
508
|
-
}
|
|
509
|
-
return {
|
|
510
|
-
gateFingerprint: hash.digest("hex").slice(0, 16),
|
|
511
|
-
gateFingerprintFiles: sourceEntries.map((entry) => entry.relativePath)
|
|
512
|
-
};
|
|
513
|
-
};
|
|
514
542
|
var buildAiTrainLineage = async ({
|
|
515
543
|
projectRoot,
|
|
516
544
|
strategyName,
|
|
517
545
|
configIds,
|
|
518
546
|
runContext,
|
|
547
|
+
sourceSha256s = [],
|
|
519
548
|
env = process.env
|
|
520
549
|
}) => {
|
|
521
550
|
const { gitSha, gitDirty } = getGitLineage(projectRoot);
|
|
522
|
-
const gate = await
|
|
551
|
+
const gate = await resolveStrategyGateFingerprint({
|
|
552
|
+
projectRoot,
|
|
553
|
+
strategyName,
|
|
554
|
+
gitSha
|
|
555
|
+
});
|
|
523
556
|
const normalizedConfigIds = [...new Set(configIds.filter(Boolean))].sort();
|
|
524
557
|
const hyperliquidPerpUniverseFingerprint = typeof import_strategies.getHyperliquidPerpUniverseSnapshot === "function" ? (0, import_strategies.getHyperliquidPerpUniverseSnapshot)().fingerprint : null;
|
|
525
558
|
const hyperliquidWhaleRegistryFingerprint = typeof import_strategies.getHyperliquidWhaleRegistrySnapshot === "function" ? (0, import_strategies.getHyperliquidWhaleRegistrySnapshot)().fingerprint : null;
|
|
@@ -539,7 +572,8 @@ var buildAiTrainLineage = async ({
|
|
|
539
572
|
configIdsFingerprint: fingerprintResearchValue(normalizedConfigIds),
|
|
540
573
|
configIds: normalizedConfigIds,
|
|
541
574
|
contextFingerprint: fingerprintResearchValue(context),
|
|
542
|
-
context
|
|
575
|
+
context,
|
|
576
|
+
sourceSha256s: [...new Set(sourceSha256s.filter(Boolean))].sort()
|
|
543
577
|
};
|
|
544
578
|
};
|
|
545
579
|
// Annotate the CommonJS export names for ESM import in node:
|