@tradejs/cli 3.1.29-beta.297 → 3.1.29-beta.299
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 +763 -644
- package/dist/lib/mcpJobOutputs.js +133 -0
- package/dist/lib/mcpReplayProcess.js +5 -3
- package/dist/scripts/backtest.js +8 -2
- package/dist/scripts/coverageBackfill.js +11 -7
- package/dist/scripts/mcpWorker.js +151 -43
- package/package.json +7 -7
package/dist/cli.js
CHANGED
|
@@ -454,10 +454,10 @@ var init_charts = __esm({
|
|
|
454
454
|
const span = Math.max(1e-9, maxY - minY), x = (time2) => 72 + 852 * (time2 - minX) / Math.max(1, maxX - minX), y = (value) => 238 - 196 * (value - minY) / span;
|
|
455
455
|
const paths = populated.map((item) => {
|
|
456
456
|
const points = sampleResearchCurve(item.points);
|
|
457
|
-
const
|
|
457
|
+
const path58 = points.map(
|
|
458
458
|
([time2, value], index) => `${index ? "H" : "M"}${x(time2).toFixed(2)}${index ? "V" : ","}${y(value).toFixed(2)}`
|
|
459
459
|
).join(" ");
|
|
460
|
-
return `<path d="${
|
|
460
|
+
return `<path d="${path58}" fill="none" stroke="${escapeResearchHtml(item.color)}" stroke-width="2.5" stroke-linejoin="round"/>`;
|
|
461
461
|
}).join("");
|
|
462
462
|
return `<figure class="chart"><figcaption>${escapeResearchHtml(title)}</figcaption><svg viewBox="0 0 960 285" role="img" aria-label="${escapeResearchHtml(title)}"><title>${escapeResearchHtml(title)}</title>${[
|
|
463
463
|
4
|
|
@@ -526,7 +526,7 @@ function pricePanel(t, c, step, x, y, w, h) {
|
|
|
526
526
|
["bbLower", "#8898ab"]
|
|
527
527
|
]) {
|
|
528
528
|
let previous = null;
|
|
529
|
-
const
|
|
529
|
+
const path58 = c.map((b) => {
|
|
530
530
|
const v = b[key2];
|
|
531
531
|
if (v == null) {
|
|
532
532
|
previous = null;
|
|
@@ -536,7 +536,7 @@ function pricePanel(t, c, step, x, y, w, h) {
|
|
|
536
536
|
previous = b.timestamp;
|
|
537
537
|
return `${command}${X(b.timestamp)},${Y(v)}`;
|
|
538
538
|
}).join(" ");
|
|
539
|
-
s += `<path d="${
|
|
539
|
+
s += `<path d="${path58}" fill="none" stroke="${color}" stroke-width="1.4"/>`;
|
|
540
540
|
}
|
|
541
541
|
for (const line of t.figures.lines)
|
|
542
542
|
s += `<polyline points="${line.points.map((p) => `${X(p.timestamp)},${Y(p.value)}`).join(" ")}" fill="none" stroke="#0284c7" stroke-width="2"/>`;
|
|
@@ -3822,9 +3822,9 @@ var init_features = __esm({
|
|
|
3822
3822
|
"targetsymbol",
|
|
3823
3823
|
"universe"
|
|
3824
3824
|
]);
|
|
3825
|
-
normalizeFeaturePath = (
|
|
3826
|
-
classifyAiPocketCoverageFeaturePath = (
|
|
3827
|
-
const segments = normalizeFeaturePath(
|
|
3825
|
+
normalizeFeaturePath = (path58) => (Array.isArray(path58) ? path58 : path58.split(".")).filter(Boolean).map((segment) => segment.toLowerCase());
|
|
3826
|
+
classifyAiPocketCoverageFeaturePath = (path58) => {
|
|
3827
|
+
const segments = normalizeFeaturePath(path58);
|
|
3828
3828
|
const normalizedPath = segments.join(".");
|
|
3829
3829
|
if (segments.some(
|
|
3830
3830
|
(segment) => segment.includes("cmc") || segment.includes("coinmarketcap")
|
|
@@ -3998,8 +3998,8 @@ var init_features = __esm({
|
|
|
3998
3998
|
"volumeusd",
|
|
3999
3999
|
"vwap"
|
|
4000
4000
|
]);
|
|
4001
|
-
classifyAiPocketFeaturePath = (
|
|
4002
|
-
const segments = (Array.isArray(
|
|
4001
|
+
classifyAiPocketFeaturePath = (path58) => {
|
|
4002
|
+
const segments = (Array.isArray(path58) ? path58 : path58.split(".")).filter(
|
|
4003
4003
|
Boolean
|
|
4004
4004
|
);
|
|
4005
4005
|
const normalized = segments.map((segment) => segment.toLowerCase());
|
|
@@ -4329,11 +4329,11 @@ var init_features = __esm({
|
|
|
4329
4329
|
excludeFeaturePattern.source,
|
|
4330
4330
|
excludeFeaturePattern.flags.replace(/[gy]/g, "")
|
|
4331
4331
|
) : void 0;
|
|
4332
|
-
const isOperatorExcluded = (
|
|
4333
|
-
if (!exclusion?.test(
|
|
4332
|
+
const isOperatorExcluded = (path58) => {
|
|
4333
|
+
if (!exclusion?.test(path58)) {
|
|
4334
4334
|
return false;
|
|
4335
4335
|
}
|
|
4336
|
-
onFeatureExcluded?.({ path:
|
|
4336
|
+
onFeatureExcluded?.({ path: path58, classification: "operator-excluded" });
|
|
4337
4337
|
return true;
|
|
4338
4338
|
};
|
|
4339
4339
|
const signal = payload.signal ?? {};
|
|
@@ -4416,15 +4416,15 @@ var init_features = __esm({
|
|
|
4416
4416
|
if (registered) {
|
|
4417
4417
|
(0, import_aiFeatures.validateAiFeatureSnapshot)(registered);
|
|
4418
4418
|
for (const definition of registered.definitions) {
|
|
4419
|
-
const
|
|
4420
|
-
if (isOperatorExcluded(
|
|
4419
|
+
const path58 = `registered.${definition.id}`;
|
|
4420
|
+
if (isOperatorExcluded(path58)) continue;
|
|
4421
4421
|
const value = registered.values[definition.id];
|
|
4422
4422
|
const classification = definition.role === "outcome" || definition.role === "policy" ? "derived-policy" : definition.role !== "input" ? definition.role : featurePolicy === "causal-stationary" && !definition.stationary ? "raw-nonstationary" : value === null || value === "unknown" ? "data-quality" : "eligible";
|
|
4423
4423
|
if (classification !== "eligible") {
|
|
4424
|
-
onFeatureExcluded?.({ path:
|
|
4424
|
+
onFeatureExcluded?.({ path: path58, classification });
|
|
4425
4425
|
continue;
|
|
4426
4426
|
}
|
|
4427
|
-
features[
|
|
4427
|
+
features[path58] = value;
|
|
4428
4428
|
}
|
|
4429
4429
|
}
|
|
4430
4430
|
return { features, featureCoverage };
|
|
@@ -8543,7 +8543,7 @@ var init_command = __esm({
|
|
|
8543
8543
|
options.testSince
|
|
8544
8544
|
);
|
|
8545
8545
|
const sources = await Promise.all(
|
|
8546
|
-
filePaths.map(async (
|
|
8546
|
+
filePaths.map(async (path58) => ({ path: path58, sha256: await sha256File(path58) }))
|
|
8547
8547
|
);
|
|
8548
8548
|
const dataset = await evaluateAiPocketSearchDataset({
|
|
8549
8549
|
prepared: preparedDataset,
|
|
@@ -13595,27 +13595,27 @@ var init_coinMarketCapContextBackfill = __esm({
|
|
|
13595
13595
|
totalCredits: 0,
|
|
13596
13596
|
byPath: /* @__PURE__ */ new Map()
|
|
13597
13597
|
});
|
|
13598
|
-
getCoinMarketCapPathLabel = (
|
|
13599
|
-
if (
|
|
13600
|
-
if (
|
|
13601
|
-
if (
|
|
13602
|
-
if (
|
|
13603
|
-
if (
|
|
13604
|
-
if (
|
|
13605
|
-
return
|
|
13606
|
-
};
|
|
13607
|
-
recordCoinMarketCapFetchStats = (stats,
|
|
13598
|
+
getCoinMarketCapPathLabel = (path58) => {
|
|
13599
|
+
if (path58.includes("global-metrics")) return "global";
|
|
13600
|
+
if (path58.includes("cryptocurrency/quotes")) return "reference";
|
|
13601
|
+
if (path58.includes("exchange/quotes")) return "exchangeLiquidity";
|
|
13602
|
+
if (path58.includes("fear-and-greed")) return "fearGreed";
|
|
13603
|
+
if (path58.includes("cmc100")) return "cmc100";
|
|
13604
|
+
if (path58.includes("cmc20")) return "cmc20";
|
|
13605
|
+
return path58;
|
|
13606
|
+
};
|
|
13607
|
+
recordCoinMarketCapFetchStats = (stats, path58, creditCount) => {
|
|
13608
13608
|
if (!stats) return;
|
|
13609
|
-
const existing = stats.byPath.get(
|
|
13609
|
+
const existing = stats.byPath.get(path58) ?? { requests: 0, credits: 0 };
|
|
13610
13610
|
existing.requests += 1;
|
|
13611
13611
|
existing.credits += creditCount ?? 0;
|
|
13612
13612
|
stats.requests += 1;
|
|
13613
13613
|
stats.totalCredits += creditCount ?? 0;
|
|
13614
|
-
stats.byPath.set(
|
|
13614
|
+
stats.byPath.set(path58, existing);
|
|
13615
13615
|
};
|
|
13616
13616
|
formatCoinMarketCapFetchStats = (stats) => {
|
|
13617
13617
|
const byPath = [...stats.byPath.entries()].map(
|
|
13618
|
-
([
|
|
13618
|
+
([path58, item]) => `${getCoinMarketCapPathLabel(path58)}=${item.requests}req/${item.credits}cr`
|
|
13619
13619
|
).join(" ");
|
|
13620
13620
|
return `apiRequests=${stats.requests} apiCredits=${stats.totalCredits}${byPath ? ` ${byPath}` : ""}`;
|
|
13621
13621
|
};
|
|
@@ -17435,8 +17435,14 @@ var init_backtest = __esm({
|
|
|
17435
17435
|
console.log(import_chalk15.default.gray(`full report: ${markdownReportPath}`));
|
|
17436
17436
|
console.log("");
|
|
17437
17437
|
if (!isFastMode || flags5.persistResults) {
|
|
17438
|
-
|
|
17439
|
-
|
|
17438
|
+
const mcpTimestamp = process.env.MCP_WORKER === "true" ? process.env.MCP_BACKTEST_RESULT_TIMESTAMP : void 0;
|
|
17439
|
+
const saveResult = mcpTimestamp ? import_redis8.setDataStrict : import_redis8.setData;
|
|
17440
|
+
await saveResult(
|
|
17441
|
+
import_redis8.redisKeys.backtestResults(
|
|
17442
|
+
userName,
|
|
17443
|
+
flags5.config,
|
|
17444
|
+
mcpTimestamp ?? timestamp
|
|
17445
|
+
),
|
|
17440
17446
|
{
|
|
17441
17447
|
config: flags5.config,
|
|
17442
17448
|
mode: "config",
|
|
@@ -26064,13 +26070,16 @@ async function fetchTarget(userName3, request, target, loaded) {
|
|
|
26064
26070
|
const interval4 = dataset.interval;
|
|
26065
26071
|
const missing = (time2) => time2 >= day && time2 < end && !loaded.has(time2);
|
|
26066
26072
|
if (dataset.provider === "CoinMarketCap") {
|
|
26067
|
-
|
|
26073
|
+
const params = {
|
|
26068
26074
|
userName: userName3,
|
|
26069
26075
|
startMs: day,
|
|
26070
26076
|
preloadStartMs: day,
|
|
26071
26077
|
endMs: end,
|
|
26072
26078
|
repairDataset: dataset.id
|
|
26073
|
-
}
|
|
26079
|
+
};
|
|
26080
|
+
if (resolveCoinMarketCapBackfillWindow(params).fromMs > day)
|
|
26081
|
+
return "outside_configured_history";
|
|
26082
|
+
await backfillCoinMarketCapContext(params);
|
|
26074
26083
|
return;
|
|
26075
26084
|
}
|
|
26076
26085
|
if (dataset.provider === "Coinalyze") {
|
|
@@ -26079,7 +26088,7 @@ async function fetchTarget(userName3, request, target, loaded) {
|
|
|
26079
26088
|
userName3,
|
|
26080
26089
|
series
|
|
26081
26090
|
);
|
|
26082
|
-
if (!marketSymbol) return;
|
|
26091
|
+
if (!marketSymbol) return "no_matching_market";
|
|
26083
26092
|
const { derivativesRows = [] } = await import_connectors11.marketDataProviders.coinalyze.fetchWindow({
|
|
26084
26093
|
symbol: series,
|
|
26085
26094
|
marketSymbol,
|
|
@@ -26171,8 +26180,7 @@ async function fetchTarget(userName3, request, target, loaded) {
|
|
|
26171
26180
|
const universe = (0, import_strategies11.getBinanceBreadthUniverses)().find(
|
|
26172
26181
|
(item) => item.universe === series
|
|
26173
26182
|
);
|
|
26174
|
-
if (!universe)
|
|
26175
|
-
throw new Error("The historical Binance basket is unavailable.");
|
|
26183
|
+
if (!universe) return "historical_basket_unavailable";
|
|
26176
26184
|
const candlesBySymbol = {};
|
|
26177
26185
|
const warmup = day - 2 * DAY_MS11;
|
|
26178
26186
|
for (let offset = 0; offset < universe.symbols.length; offset += 4) {
|
|
@@ -26201,14 +26209,16 @@ async function main17() {
|
|
|
26201
26209
|
);
|
|
26202
26210
|
await (0, import_client5.waitForDbReady)();
|
|
26203
26211
|
const before = await (0, import_dataCoverage.readDataBackfillSlots)(request, target.end);
|
|
26204
|
-
|
|
26205
|
-
await fetchTarget(userName3, request, target, before.loaded);
|
|
26212
|
+
const outcome = before.loaded.size < before.expected ? await fetchTarget(userName3, request, target, before.loaded) : void 0;
|
|
26206
26213
|
const after = await (0, import_dataCoverage.readDataBackfillSlots)(request, target.end);
|
|
26207
26214
|
const result = {
|
|
26208
26215
|
loaded: after.loaded.size,
|
|
26209
26216
|
added: Math.max(0, after.loaded.size - before.loaded.size),
|
|
26210
26217
|
missing: Math.max(0, after.expected - after.loaded.size)
|
|
26211
26218
|
};
|
|
26219
|
+
if (result.missing) {
|
|
26220
|
+
result.outcome = outcome ?? (result.added ? "some_missing_slots_filled" : "no_missing_slots_filled");
|
|
26221
|
+
}
|
|
26212
26222
|
console.log(`TRADEJS_DATA_BACKFILL ${JSON.stringify(result)}`);
|
|
26213
26223
|
}
|
|
26214
26224
|
var import_connectors11, import_candles3, import_client5, import_dataCoverage, import_derivatives2, import_marketContext5, import_spread, import_strategies11, DAY_MS11;
|
|
@@ -28446,12 +28456,11 @@ var init_runtimeEvidenceArtifacts = __esm({
|
|
|
28446
28456
|
});
|
|
28447
28457
|
|
|
28448
28458
|
// src/lib/mcpReplayProcess.ts
|
|
28449
|
-
var import_node_path19,
|
|
28459
|
+
var import_node_path19, import_promises22, client, buildMcpReplayProcess;
|
|
28450
28460
|
var init_mcpReplayProcess = __esm({
|
|
28451
28461
|
"src/lib/mcpReplayProcess.ts"() {
|
|
28452
28462
|
"use strict";
|
|
28453
28463
|
import_node_path19 = __toESM(require("path"));
|
|
28454
|
-
import_node_crypto14 = require("crypto");
|
|
28455
28464
|
import_promises22 = __toESM(require("fs/promises"));
|
|
28456
28465
|
init_runtimeEvidenceArtifacts();
|
|
28457
28466
|
client = `
|
|
@@ -28492,6 +28501,7 @@ const timer = setInterval(() => {
|
|
|
28492
28501
|
`;
|
|
28493
28502
|
buildMcpReplayProcess = async ({
|
|
28494
28503
|
evidencePath,
|
|
28504
|
+
expectedEvidenceSha256,
|
|
28495
28505
|
outDir,
|
|
28496
28506
|
runId,
|
|
28497
28507
|
projectRoot: projectRoot18,
|
|
@@ -28502,6 +28512,9 @@ const timer = setInterval(() => {
|
|
|
28502
28512
|
const bundle = await (0, runtimeEvidenceArtifacts_exports.verifyRuntimeEvidenceBundle)(import_node_path19.default.dirname(evidencePath));
|
|
28503
28513
|
if (import_node_path19.default.resolve(evidencePath) !== import_node_path19.default.resolve(bundle.payloadPath))
|
|
28504
28514
|
throw new Error("Replay requires the verified bundle payload");
|
|
28515
|
+
const payloadSha256 = bundle.manifest.payload.sha256;
|
|
28516
|
+
if (expectedEvidenceSha256 && expectedEvidenceSha256 !== payloadSha256)
|
|
28517
|
+
throw new Error("Runtime evidence changed since job submission");
|
|
28505
28518
|
const relative = import_node_path19.default.relative(import_node_path19.default.join(projectRoot18, "data"), evidencePath);
|
|
28506
28519
|
if (relative.startsWith("..") || import_node_path19.default.isAbsolute(relative))
|
|
28507
28520
|
throw new Error("Evidence must be inside Project data");
|
|
@@ -28511,14 +28524,13 @@ const timer = setInterval(() => {
|
|
|
28511
28524
|
);
|
|
28512
28525
|
if (heartbeat.protocolVersion !== 2 || !Number.isFinite(heartbeat.observedAt) || Date.now() - heartbeat.observedAt < 0 || Date.now() - heartbeat.observedAt > 12e4)
|
|
28513
28526
|
throw new Error("Host replay runner heartbeat is stale");
|
|
28514
|
-
const bytes = await import_promises22.default.readFile(evidencePath);
|
|
28515
28527
|
const request = JSON.stringify({
|
|
28516
28528
|
schemaVersion: 1,
|
|
28517
28529
|
id: runId,
|
|
28518
28530
|
evidence: relative,
|
|
28519
28531
|
artifactId: bundle.manifest.artifactId,
|
|
28520
28532
|
deploymentId: bundle.manifest.deploymentId,
|
|
28521
|
-
payloadSha256
|
|
28533
|
+
payloadSha256
|
|
28522
28534
|
});
|
|
28523
28535
|
void outDir;
|
|
28524
28536
|
return {
|
|
@@ -28529,28 +28541,123 @@ const timer = setInterval(() => {
|
|
|
28529
28541
|
}
|
|
28530
28542
|
});
|
|
28531
28543
|
|
|
28544
|
+
// src/lib/mcpJobOutputs.ts
|
|
28545
|
+
var import_promises23, import_node_path20, import_redis16, import_diagnostics, import_mcp, mcpBacktestResultTimestamp, collectEvidence, collectReplay, collectMcpJobOutputs;
|
|
28546
|
+
var init_mcpJobOutputs = __esm({
|
|
28547
|
+
"src/lib/mcpJobOutputs.ts"() {
|
|
28548
|
+
"use strict";
|
|
28549
|
+
import_promises23 = require("fs/promises");
|
|
28550
|
+
import_node_path20 = __toESM(require("path"));
|
|
28551
|
+
import_redis16 = require("@tradejs/infra/redis");
|
|
28552
|
+
import_diagnostics = require("@tradejs/node/diagnostics");
|
|
28553
|
+
import_mcp = require("@tradejs/node/mcp");
|
|
28554
|
+
init_runFormatting();
|
|
28555
|
+
mcpBacktestResultTimestamp = (job) => createTimestamp(new Date(job.createdAt));
|
|
28556
|
+
collectEvidence = async (job) => Promise.all(
|
|
28557
|
+
(await (0, import_diagnostics.discoverRuntimeEvidenceBundles)((0, import_mcp.mcpJobDirectory)(job))).map(
|
|
28558
|
+
async (bundleDir) => {
|
|
28559
|
+
const { manifest } = await (0, import_diagnostics.verifyRuntimeEvidenceBundle)(bundleDir);
|
|
28560
|
+
if (manifest.userName !== job.userName || manifest.deploymentId !== job.request.deploymentId || manifest.window.startTime !== job.request.startTime || manifest.window.endTime !== job.request.endTime)
|
|
28561
|
+
throw new Error("Runtime evidence does not match the job");
|
|
28562
|
+
return {
|
|
28563
|
+
bundleDir,
|
|
28564
|
+
id: (0, import_mcp.mcpId)(`${manifest.artifactId}:${manifest.payload.sha256}`)
|
|
28565
|
+
};
|
|
28566
|
+
}
|
|
28567
|
+
)
|
|
28568
|
+
);
|
|
28569
|
+
collectReplay = async (job) => {
|
|
28570
|
+
const sourceDir = import_node_path20.default.dirname(String(job.request.verifiedEvidencePath));
|
|
28571
|
+
const source = await (0, import_diagnostics.verifyRuntimeEvidenceBundle)(sourceDir);
|
|
28572
|
+
const { artifactId, deploymentId, userName: userName3, window } = source.manifest;
|
|
28573
|
+
if (userName3 !== job.userName || deploymentId !== job.request.deploymentId || job.request.verifiedEvidenceSha256 !== void 0 && job.request.verifiedEvidenceSha256 !== source.manifest.payload.sha256 || !/^[A-Za-z0-9._-]+$/.test(artifactId) || !/^[A-Za-z0-9._-]+$/.test(deploymentId) || [".", ".."].includes(artifactId) || [".", ".."].includes(deploymentId))
|
|
28574
|
+
throw new Error("Runtime evidence does not match the replay job");
|
|
28575
|
+
const root = import_node_path20.default.join((0, import_mcp.mcpProjectRoot)(), "data/runtime-feedback");
|
|
28576
|
+
const receipt = JSON.parse(
|
|
28577
|
+
await (0, import_promises23.readFile)(
|
|
28578
|
+
import_node_path20.default.join(root, "completed", deploymentId, `${artifactId}.json`),
|
|
28579
|
+
"utf8"
|
|
28580
|
+
)
|
|
28581
|
+
);
|
|
28582
|
+
if (!(0, import_mcp.isMcpRecord)(receipt) || receipt.schemaVersion !== 1 || receipt.runtimeEvidenceArtifactId !== artifactId || typeof receipt.runtimeFeedbackBundle !== "string")
|
|
28583
|
+
throw new Error("Invalid replay completion receipt");
|
|
28584
|
+
const runId = import_node_path20.default.basename(receipt.runtimeFeedbackBundle);
|
|
28585
|
+
if (!/^[A-Za-z0-9_-]+$/.test(runId))
|
|
28586
|
+
throw new Error("Invalid replay bundle name");
|
|
28587
|
+
const day = new Date(window.endTime).toISOString().slice(0, 10).split("-");
|
|
28588
|
+
const bundleDir = import_node_path20.default.join(
|
|
28589
|
+
root,
|
|
28590
|
+
"ready",
|
|
28591
|
+
deploymentId,
|
|
28592
|
+
...day,
|
|
28593
|
+
artifactId,
|
|
28594
|
+
runId
|
|
28595
|
+
);
|
|
28596
|
+
const { feedback } = await (0, import_diagnostics.verifyRuntimeFeedbackReplaySource)({
|
|
28597
|
+
bundleDir,
|
|
28598
|
+
runtimeEvidenceBundleDir: sourceDir
|
|
28599
|
+
});
|
|
28600
|
+
const { manifest } = feedback;
|
|
28601
|
+
return [
|
|
28602
|
+
{
|
|
28603
|
+
bundleDir,
|
|
28604
|
+
id: (0, import_mcp.mcpId)(
|
|
28605
|
+
`${manifest.artifactId}:${manifest.payloads.replayEvidence.sha256}`
|
|
28606
|
+
)
|
|
28607
|
+
}
|
|
28608
|
+
];
|
|
28609
|
+
};
|
|
28610
|
+
collectMcpJobOutputs = async (job) => {
|
|
28611
|
+
if (job.kind === "backtest") {
|
|
28612
|
+
const config2 = job.request.frozenConfigId;
|
|
28613
|
+
if (typeof config2 !== "string")
|
|
28614
|
+
throw new Error("Invalid frozen backtest config");
|
|
28615
|
+
const timestamp = mcpBacktestResultTimestamp(job);
|
|
28616
|
+
if (!await (0, import_redis16.getDataStrict)(
|
|
28617
|
+
import_redis16.redisKeys.backtestResults(job.userName, config2, timestamp)
|
|
28618
|
+
))
|
|
28619
|
+
throw new Error("Backtest result was not saved");
|
|
28620
|
+
return { resultId: `${config2}:${timestamp}` };
|
|
28621
|
+
}
|
|
28622
|
+
const bundles = job.kind === "runtime-evidence" ? await collectEvidence(job) : await collectReplay(job);
|
|
28623
|
+
if (!bundles.length)
|
|
28624
|
+
throw new Error("No verified diagnostic report was saved");
|
|
28625
|
+
for (const { id, bundleDir } of bundles) {
|
|
28626
|
+
if (!await import_redis16.mcpStorage.put(
|
|
28627
|
+
(0, import_mcp.mcpArtifactLocationId)(job.userName, id),
|
|
28628
|
+
bundleDir,
|
|
28629
|
+
import_mcp.MCP_JOB_TTL
|
|
28630
|
+
))
|
|
28631
|
+
throw new Error("Diagnostic report location could not be saved");
|
|
28632
|
+
}
|
|
28633
|
+
return { artifactIds: bundles.map(({ id }) => id) };
|
|
28634
|
+
};
|
|
28635
|
+
}
|
|
28636
|
+
});
|
|
28637
|
+
|
|
28532
28638
|
// src/scripts/mcpWorker.ts
|
|
28533
28639
|
var mcpWorker_exports = {};
|
|
28534
28640
|
__export(mcpWorker_exports, {
|
|
28535
28641
|
main: () => main29
|
|
28536
28642
|
});
|
|
28537
|
-
var import_node_child_process4,
|
|
28643
|
+
var import_node_child_process4, import_node_crypto14, import_promises24, import_redis17, import_mcp2, pause, leaseKey, LEASE_SECONDS, JOB_TIMEOUT_MS, main29;
|
|
28538
28644
|
var init_mcpWorker = __esm({
|
|
28539
28645
|
"src/scripts/mcpWorker.ts"() {
|
|
28540
28646
|
"use strict";
|
|
28541
28647
|
import_node_child_process4 = require("child_process");
|
|
28542
|
-
|
|
28543
|
-
|
|
28544
|
-
|
|
28545
|
-
|
|
28648
|
+
import_node_crypto14 = require("crypto");
|
|
28649
|
+
import_promises24 = require("fs/promises");
|
|
28650
|
+
import_redis17 = require("@tradejs/infra/redis");
|
|
28651
|
+
import_mcp2 = require("@tradejs/node/mcp");
|
|
28546
28652
|
init_mcpReplayProcess();
|
|
28653
|
+
init_mcpJobOutputs();
|
|
28547
28654
|
pause = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
28548
28655
|
leaseKey = "worker:lease";
|
|
28549
28656
|
LEASE_SECONDS = 15;
|
|
28550
28657
|
JOB_TIMEOUT_MS = 60 * 60 * 1e3;
|
|
28551
28658
|
main29 = async (options = {}) => {
|
|
28552
|
-
const owner = (0,
|
|
28553
|
-
if (!await
|
|
28659
|
+
const owner = (0, import_node_crypto14.randomUUID)();
|
|
28660
|
+
if (!await import_redis17.mcpStorage.put(leaseKey, owner, LEASE_SECONDS, true))
|
|
28554
28661
|
throw new Error("Another MCP worker owns this storage");
|
|
28555
28662
|
let stopping = false;
|
|
28556
28663
|
let child;
|
|
@@ -28565,7 +28672,7 @@ var init_mcpWorker = __esm({
|
|
|
28565
28672
|
try {
|
|
28566
28673
|
const root = process.env.MCP_REPLAY_REQUEST_ROOT || `${process.env.PROJECT_CWD || process.cwd()}/data/mcp-replay-requests`;
|
|
28567
28674
|
const heartbeat2 = JSON.parse(
|
|
28568
|
-
await (0,
|
|
28675
|
+
await (0, import_promises24.readFile)(`${root}/heartbeat.json`, "utf8")
|
|
28569
28676
|
);
|
|
28570
28677
|
replayReady = heartbeat2.protocolVersion === 2 && Number.isFinite(heartbeat2.observedAt) && Date.now() - heartbeat2.observedAt >= 0 && Date.now() - heartbeat2.observedAt < 12e4;
|
|
28571
28678
|
replayReadiness = replayReady && (heartbeat2.readiness === "ready" || heartbeat2.readiness === "waiting_resources") ? heartbeat2.readiness : "unknown";
|
|
@@ -28614,10 +28721,10 @@ var init_mcpWorker = __esm({
|
|
|
28614
28721
|
if (renewing || leaseLost) return;
|
|
28615
28722
|
renewing = true;
|
|
28616
28723
|
try {
|
|
28617
|
-
if (!await
|
|
28724
|
+
if (!await import_redis17.mcpStorage.compare(leaseKey, owner, owner, LEASE_SECONDS))
|
|
28618
28725
|
throw new Error("Worker lease lost");
|
|
28619
28726
|
await updateReplayReady();
|
|
28620
|
-
await
|
|
28727
|
+
await import_redis17.mcpStorage.put("worker:heartbeat", heartbeatValue(), LEASE_SECONDS);
|
|
28621
28728
|
} catch {
|
|
28622
28729
|
leaseLost = true;
|
|
28623
28730
|
stop();
|
|
@@ -28626,17 +28733,17 @@ var init_mcpWorker = __esm({
|
|
|
28626
28733
|
}
|
|
28627
28734
|
}, 2e3);
|
|
28628
28735
|
try {
|
|
28629
|
-
manifestHash = await (0,
|
|
28736
|
+
manifestHash = await (0, import_mcp2.mcpPackageManifestHash)();
|
|
28630
28737
|
await updateReplayReady();
|
|
28631
|
-
await
|
|
28738
|
+
await import_redis17.mcpStorage.put("worker:heartbeat", heartbeatValue(), LEASE_SECONDS);
|
|
28632
28739
|
let cursor = "0";
|
|
28633
28740
|
do {
|
|
28634
|
-
const page = await
|
|
28741
|
+
const page = await import_redis17.mcpStorage.scan("jobs:", cursor);
|
|
28635
28742
|
cursor = page.cursor;
|
|
28636
28743
|
for (const key2 of page.ids) {
|
|
28637
|
-
const job = await
|
|
28744
|
+
const job = await import_redis17.mcpStorage.get(key2);
|
|
28638
28745
|
if (job?.status === "running")
|
|
28639
|
-
await
|
|
28746
|
+
await import_redis17.mcpStorage.compare(
|
|
28640
28747
|
key2,
|
|
28641
28748
|
job,
|
|
28642
28749
|
{
|
|
@@ -28646,7 +28753,7 @@ var init_mcpWorker = __esm({
|
|
|
28646
28753
|
finishedAt: Date.now(),
|
|
28647
28754
|
updatedAt: Date.now()
|
|
28648
28755
|
},
|
|
28649
|
-
|
|
28756
|
+
import_mcp2.MCP_JOB_TTL
|
|
28650
28757
|
);
|
|
28651
28758
|
}
|
|
28652
28759
|
} while (cursor !== "0" && !stopping);
|
|
@@ -28657,10 +28764,10 @@ var init_mcpWorker = __esm({
|
|
|
28657
28764
|
let queued;
|
|
28658
28765
|
cursor = "0";
|
|
28659
28766
|
do {
|
|
28660
|
-
const page = await
|
|
28767
|
+
const page = await import_redis17.mcpStorage.scan("jobs:", cursor);
|
|
28661
28768
|
cursor = page.cursor;
|
|
28662
28769
|
for (const key2 of page.ids) {
|
|
28663
|
-
const job = await
|
|
28770
|
+
const job = await import_redis17.mcpStorage.get(key2);
|
|
28664
28771
|
if (job && ["queued", "waiting_resources", "waiting_executor"].includes(
|
|
28665
28772
|
job.status
|
|
28666
28773
|
) && (!queued || job.createdAt < queued.createdAt))
|
|
@@ -28671,17 +28778,17 @@ var init_mcpWorker = __esm({
|
|
|
28671
28778
|
await pause(1e3);
|
|
28672
28779
|
continue;
|
|
28673
28780
|
}
|
|
28674
|
-
const jobKey = (0,
|
|
28781
|
+
const jobKey = (0, import_mcp2.mcpJobStorageId)(queued.userName, queued.id);
|
|
28675
28782
|
const started = {
|
|
28676
28783
|
...queued,
|
|
28677
28784
|
status: queued.kind === "runtime-feedback-replay" ? "waiting_executor" : "running",
|
|
28678
28785
|
...queued.kind === "runtime-feedback-replay" ? {} : { startedAt: Date.now() },
|
|
28679
28786
|
updatedAt: Date.now()
|
|
28680
28787
|
};
|
|
28681
|
-
if (!await
|
|
28788
|
+
if (!await import_redis17.mcpStorage.compare(jobKey, queued, started, import_mcp2.MCP_JOB_TTL))
|
|
28682
28789
|
continue;
|
|
28683
28790
|
if (started.kind !== "runtime-feedback-replay" && started.packageManifestSha256 !== manifestHash) {
|
|
28684
|
-
await
|
|
28791
|
+
await import_redis17.mcpStorage.compare(
|
|
28685
28792
|
jobKey,
|
|
28686
28793
|
started,
|
|
28687
28794
|
{
|
|
@@ -28690,19 +28797,19 @@ var init_mcpWorker = __esm({
|
|
|
28690
28797
|
error: "Package composition changed since submission",
|
|
28691
28798
|
finishedAt: Date.now()
|
|
28692
28799
|
},
|
|
28693
|
-
|
|
28800
|
+
import_mcp2.MCP_JOB_TTL
|
|
28694
28801
|
);
|
|
28695
28802
|
continue;
|
|
28696
28803
|
}
|
|
28697
|
-
await (0,
|
|
28804
|
+
await (0, import_promises24.mkdir)((0, import_mcp2.mcpJobDirectory)(started), { recursive: true });
|
|
28698
28805
|
if (started.kind === "backtest")
|
|
28699
|
-
await (0,
|
|
28700
|
-
|
|
28806
|
+
await (0, import_redis17.setDataStrict)(
|
|
28807
|
+
import_redis17.redisKeys.backtestConfig(
|
|
28701
28808
|
started.userName,
|
|
28702
28809
|
String(started.request.frozenConfigId)
|
|
28703
28810
|
),
|
|
28704
28811
|
started.request.resolvedConfig,
|
|
28705
|
-
{ expire:
|
|
28812
|
+
{ expire: import_mcp2.MCP_JOB_TTL }
|
|
28706
28813
|
);
|
|
28707
28814
|
const jobEnv = {
|
|
28708
28815
|
...process.env,
|
|
@@ -28715,6 +28822,8 @@ var init_mcpWorker = __esm({
|
|
|
28715
28822
|
MAKE_ORDERS: "false",
|
|
28716
28823
|
TRADEJS_EXTERNAL_ORDER_PLACEMENT: "false"
|
|
28717
28824
|
};
|
|
28825
|
+
if (started.kind === "backtest")
|
|
28826
|
+
jobEnv.MCP_BACKTEST_RESULT_TIMESTAMP = mcpBacktestResultTimestamp(started);
|
|
28718
28827
|
if (started.kind === "runtime-feedback-replay") {
|
|
28719
28828
|
for (const name of Object.keys(jobEnv)) {
|
|
28720
28829
|
if (/secret|password|token|api.?key|private.?key|cookie|credential/i.test(
|
|
@@ -28740,13 +28849,14 @@ var init_mcpWorker = __esm({
|
|
|
28740
28849
|
if (started.kind === "runtime-feedback-replay")
|
|
28741
28850
|
command = await buildMcpReplayProcess({
|
|
28742
28851
|
evidencePath: String(started.request.verifiedEvidencePath),
|
|
28743
|
-
|
|
28852
|
+
expectedEvidenceSha256: typeof started.request.verifiedEvidenceSha256 === "string" ? started.request.verifiedEvidenceSha256 : void 0,
|
|
28853
|
+
outDir: (0, import_mcp2.mcpJobDirectory)(started),
|
|
28744
28854
|
runId: started.id,
|
|
28745
28855
|
projectRoot: process.env.PROJECT_CWD || process.cwd(),
|
|
28746
28856
|
env: process.env
|
|
28747
28857
|
});
|
|
28748
28858
|
} catch (error) {
|
|
28749
|
-
await
|
|
28859
|
+
await import_redis17.mcpStorage.compare(
|
|
28750
28860
|
jobKey,
|
|
28751
28861
|
started,
|
|
28752
28862
|
{
|
|
@@ -28754,9 +28864,9 @@ var init_mcpWorker = __esm({
|
|
|
28754
28864
|
status: "failed",
|
|
28755
28865
|
finishedAt: Date.now(),
|
|
28756
28866
|
updatedAt: Date.now(),
|
|
28757
|
-
error: error instanceof Error ? (0,
|
|
28867
|
+
error: error instanceof Error ? (0, import_mcp2.redactMcpJobLog)(error.message) : "Replay preparation failed"
|
|
28758
28868
|
},
|
|
28759
|
-
|
|
28869
|
+
import_mcp2.MCP_JOB_TTL
|
|
28760
28870
|
);
|
|
28761
28871
|
continue;
|
|
28762
28872
|
}
|
|
@@ -28776,7 +28886,7 @@ var init_mcpWorker = __esm({
|
|
|
28776
28886
|
const logs = [];
|
|
28777
28887
|
const log = (chunk) => {
|
|
28778
28888
|
const lines = chunk.toString().replace(/\u001b\[[0-9;]*m/g, "").split(/[\r\n]+/).filter(Boolean);
|
|
28779
|
-
logs.push(...lines.map(
|
|
28889
|
+
logs.push(...lines.map(import_mcp2.redactMcpJobLog));
|
|
28780
28890
|
if (logs.length > 150) logs.splice(0, logs.length - 150);
|
|
28781
28891
|
};
|
|
28782
28892
|
currentChild.stdout?.on("data", log);
|
|
@@ -28784,7 +28894,7 @@ var init_mcpWorker = __esm({
|
|
|
28784
28894
|
let killAt;
|
|
28785
28895
|
const monitor = setInterval(async () => {
|
|
28786
28896
|
try {
|
|
28787
|
-
const latest = await
|
|
28897
|
+
const latest = await import_redis17.mcpStorage.get(jobKey);
|
|
28788
28898
|
if (!latest || latest.cancelRequested || stopping || timedOut) {
|
|
28789
28899
|
killAt ??= Date.now();
|
|
28790
28900
|
signalChild(Date.now() - killAt > 8e3 ? "SIGKILL" : "SIGTERM");
|
|
@@ -28794,7 +28904,7 @@ var init_mcpWorker = __esm({
|
|
|
28794
28904
|
try {
|
|
28795
28905
|
const root = process.env.MCP_REPLAY_REQUEST_ROOT || `${process.env.PROJECT_CWD || process.cwd()}/data/mcp-replay-requests`;
|
|
28796
28906
|
const state = JSON.parse(
|
|
28797
|
-
await (0,
|
|
28907
|
+
await (0, import_promises24.readFile)(`${root}/${latest.id}.state`, "utf8")
|
|
28798
28908
|
);
|
|
28799
28909
|
if (state && typeof state === "object" && "status" in state && (state.status === "waiting_resources" || state.status === "waiting_executor" || state.status === "running"))
|
|
28800
28910
|
replayStatus = state.status;
|
|
@@ -28809,7 +28919,7 @@ var init_mcpWorker = __esm({
|
|
|
28809
28919
|
}
|
|
28810
28920
|
}
|
|
28811
28921
|
if (latest && !leaseLost)
|
|
28812
|
-
await
|
|
28922
|
+
await import_redis17.mcpStorage.compare(
|
|
28813
28923
|
jobKey,
|
|
28814
28924
|
latest,
|
|
28815
28925
|
{
|
|
@@ -28821,7 +28931,7 @@ var init_mcpWorker = __esm({
|
|
|
28821
28931
|
logs: [...logs],
|
|
28822
28932
|
updatedAt: Date.now()
|
|
28823
28933
|
},
|
|
28824
|
-
|
|
28934
|
+
import_mcp2.MCP_JOB_TTL
|
|
28825
28935
|
);
|
|
28826
28936
|
} catch {
|
|
28827
28937
|
leaseLost = true;
|
|
@@ -28838,25 +28948,34 @@ var init_mcpWorker = __esm({
|
|
|
28838
28948
|
clearTimeout(timeout);
|
|
28839
28949
|
clearInterval(monitor);
|
|
28840
28950
|
child = void 0;
|
|
28951
|
+
let outputs = {};
|
|
28952
|
+
if (!leaseLost && outcome.code === 0 && !outcome.error && !timedOut && !stopping) {
|
|
28953
|
+
try {
|
|
28954
|
+
outputs = await collectMcpJobOutputs(started);
|
|
28955
|
+
} catch {
|
|
28956
|
+
outcome.error = "Job finished but its saved output could not be verified";
|
|
28957
|
+
}
|
|
28958
|
+
}
|
|
28841
28959
|
if (!leaseLost) {
|
|
28842
28960
|
for (let attempt = 0; attempt < 4; attempt++) {
|
|
28843
|
-
const latest = await
|
|
28961
|
+
const latest = await import_redis17.mcpStorage.get(jobKey);
|
|
28844
28962
|
if (!latest) break;
|
|
28845
28963
|
const cancelled = latest.cancelRequested;
|
|
28846
28964
|
const next = {
|
|
28847
28965
|
...latest,
|
|
28848
28966
|
logs,
|
|
28849
|
-
status: cancelled ? "cancelled" : outcome.code === 0 && !timedOut && !stopping ? "completed" : "failed",
|
|
28967
|
+
status: cancelled ? "cancelled" : outcome.code === 0 && !outcome.error && !timedOut && !stopping ? "completed" : "failed",
|
|
28968
|
+
...cancelled || stopping ? {} : outputs,
|
|
28850
28969
|
exitCode: outcome.code,
|
|
28851
28970
|
updatedAt: Date.now(),
|
|
28852
28971
|
finishedAt: Date.now(),
|
|
28853
|
-
...cancelled ? {} : timedOut ? { error: "Job exceeded one hour" } : stopping ? { error: "Worker stopped; this job was not replayed" } : outcome.code !== 0 ? {
|
|
28972
|
+
...cancelled ? {} : timedOut ? { error: "Job exceeded one hour" } : stopping ? { error: "Worker stopped; this job was not replayed" } : outcome.code !== 0 || outcome.error ? {
|
|
28854
28973
|
error: outcome.error || (started.kind === "runtime-feedback-replay" ? logs.find(
|
|
28855
28974
|
(line) => line.startsWith("Host replay: ")
|
|
28856
28975
|
) || logs.at(-1) : void 0) || "Research process failed"
|
|
28857
28976
|
} : {}
|
|
28858
28977
|
};
|
|
28859
|
-
if (await
|
|
28978
|
+
if (await import_redis17.mcpStorage.compare(jobKey, latest, next, import_mcp2.MCP_JOB_TTL))
|
|
28860
28979
|
break;
|
|
28861
28980
|
}
|
|
28862
28981
|
}
|
|
@@ -28866,8 +28985,8 @@ var init_mcpWorker = __esm({
|
|
|
28866
28985
|
options.signal?.removeEventListener("abort", stop);
|
|
28867
28986
|
process.removeListener("SIGINT", stop);
|
|
28868
28987
|
process.removeListener("SIGTERM", stop);
|
|
28869
|
-
if (await
|
|
28870
|
-
await
|
|
28988
|
+
if (await import_redis17.mcpStorage.release(leaseKey, owner))
|
|
28989
|
+
await import_redis17.mcpStorage.remove("worker:heartbeat");
|
|
28871
28990
|
}
|
|
28872
28991
|
if (leaseLost)
|
|
28873
28992
|
throw new Error("Worker lease lost; active computation was stopped");
|
|
@@ -29230,13 +29349,13 @@ var hyperliquidWhalesUpdate_exports = {};
|
|
|
29230
29349
|
__export(hyperliquidWhalesUpdate_exports, {
|
|
29231
29350
|
main: () => main32
|
|
29232
29351
|
});
|
|
29233
|
-
var import_config8, import_args21,
|
|
29352
|
+
var import_config8, import_args21, import_node_crypto15, import_strategies13, LEADERBOARD_URL, DAY_MS12, CANDIDATE_LIMIT, flags19, fingerprint, runConcurrent2, main32;
|
|
29234
29353
|
var init_hyperliquidWhalesUpdate = __esm({
|
|
29235
29354
|
"src/scripts/hyperliquidWhalesUpdate.ts"() {
|
|
29236
29355
|
"use strict";
|
|
29237
29356
|
import_config8 = require("dotenv/config");
|
|
29238
29357
|
import_args21 = __toESM(require("args"));
|
|
29239
|
-
|
|
29358
|
+
import_node_crypto15 = require("crypto");
|
|
29240
29359
|
import_strategies13 = require("@tradejs/node/strategies");
|
|
29241
29360
|
init_hyperliquidWhaleBackfill();
|
|
29242
29361
|
init_hyperliquidRateLimiter();
|
|
@@ -29250,7 +29369,7 @@ var init_hyperliquidWhalesUpdate = __esm({
|
|
|
29250
29369
|
);
|
|
29251
29370
|
import_args21.default.option(["d", "days"], "Calibration window in days", 7);
|
|
29252
29371
|
flags19 = import_args21.default.parse(process.argv);
|
|
29253
|
-
fingerprint = (addresses) => (0,
|
|
29372
|
+
fingerprint = (addresses) => (0, import_node_crypto15.createHash)("sha256").update(JSON.stringify(addresses)).digest("hex").slice(0, 16);
|
|
29254
29373
|
runConcurrent2 = async (params) => {
|
|
29255
29374
|
let nextIndex = 0;
|
|
29256
29375
|
await Promise.all(
|
|
@@ -29359,13 +29478,13 @@ var mlExport_exports = {};
|
|
|
29359
29478
|
__export(mlExport_exports, {
|
|
29360
29479
|
main: () => main33
|
|
29361
29480
|
});
|
|
29362
|
-
var import_args22, import_chalk37,
|
|
29481
|
+
var import_args22, import_chalk37, import_promises25, import_path8, import_ml, flags20, resolveRunScopedMlChunks, main33;
|
|
29363
29482
|
var init_mlExport = __esm({
|
|
29364
29483
|
"src/scripts/mlExport.ts"() {
|
|
29365
29484
|
"use strict";
|
|
29366
29485
|
import_args22 = __toESM(require("args"));
|
|
29367
29486
|
import_chalk37 = __toESM(require("chalk"));
|
|
29368
|
-
|
|
29487
|
+
import_promises25 = __toESM(require("fs/promises"));
|
|
29369
29488
|
import_path8 = __toESM(require("path"));
|
|
29370
29489
|
import_ml = require("@tradejs/infra/ml");
|
|
29371
29490
|
init_checkpoint();
|
|
@@ -29416,7 +29535,7 @@ var init_mlExport = __esm({
|
|
|
29416
29535
|
};
|
|
29417
29536
|
main33 = async () => {
|
|
29418
29537
|
const outDir = String(flags20.outDir || "data/ml/export");
|
|
29419
|
-
await
|
|
29538
|
+
await import_promises25.default.mkdir(outDir, { recursive: true });
|
|
29420
29539
|
const strategyName = await resolveExportStrategy({
|
|
29421
29540
|
explicitStrategy: String(flags20.strategy || ""),
|
|
29422
29541
|
outDir,
|
|
@@ -29461,7 +29580,7 @@ var init_mlExport = __esm({
|
|
|
29461
29580
|
const shouldDeleteChunks = !Boolean(flags20.keepChunks);
|
|
29462
29581
|
if (shouldDeleteChunks) {
|
|
29463
29582
|
for (const filePath of chunkFiles) {
|
|
29464
|
-
await
|
|
29583
|
+
await import_promises25.default.rm(filePath, { force: true });
|
|
29465
29584
|
}
|
|
29466
29585
|
}
|
|
29467
29586
|
console.log(import_chalk37.default.green(`Merged dataset saved: ${mergedPath}`));
|
|
@@ -29482,13 +29601,13 @@ var mlInspect_exports = {};
|
|
|
29482
29601
|
__export(mlInspect_exports, {
|
|
29483
29602
|
main: () => main34
|
|
29484
29603
|
});
|
|
29485
|
-
var import_args23, import_chalk38,
|
|
29604
|
+
var import_args23, import_chalk38, import_promises26, import_fs3, import_path9, import_readline2, import_child_process2, flags21, toMode, toInspectTool, selectInspectTool, asPositiveInt, readRowsHead, readRowsTail, readRowsSample, quantileSorted, mean2, std, findLatestDataset, buildNumericStats, formatNumber5, runQuickInspect, runYDataInspect, main34;
|
|
29486
29605
|
var init_mlInspect = __esm({
|
|
29487
29606
|
"src/scripts/mlInspect.ts"() {
|
|
29488
29607
|
"use strict";
|
|
29489
29608
|
import_args23 = __toESM(require("args"));
|
|
29490
29609
|
import_chalk38 = __toESM(require("chalk"));
|
|
29491
|
-
|
|
29610
|
+
import_promises26 = __toESM(require("fs/promises"));
|
|
29492
29611
|
import_fs3 = require("fs");
|
|
29493
29612
|
import_path9 = __toESM(require("path"));
|
|
29494
29613
|
import_readline2 = __toESM(require("readline"));
|
|
@@ -29665,7 +29784,7 @@ var init_mlInspect = __esm({
|
|
|
29665
29784
|
};
|
|
29666
29785
|
findLatestDataset = async (params) => {
|
|
29667
29786
|
const { dir, strategy } = params;
|
|
29668
|
-
const entries = await
|
|
29787
|
+
const entries = await import_promises26.default.readdir(dir, { withFileTypes: true });
|
|
29669
29788
|
const strategyToken = strategy.trim().toLowerCase();
|
|
29670
29789
|
const files = entries.filter((entry) => entry.isFile()).map((entry) => entry.name).filter((name) => name.endsWith(".jsonl")).filter(
|
|
29671
29790
|
(name) => !name.includes(".train.") && !name.includes(".test.")
|
|
@@ -29677,7 +29796,7 @@ var init_mlInspect = __esm({
|
|
|
29677
29796
|
}
|
|
29678
29797
|
const withMtime = await Promise.all(
|
|
29679
29798
|
files.map(async (name) => {
|
|
29680
|
-
const stat = await
|
|
29799
|
+
const stat = await import_promises26.default.stat(import_path9.default.join(dir, name));
|
|
29681
29800
|
return { name, mtime: stat.mtimeMs };
|
|
29682
29801
|
})
|
|
29683
29802
|
);
|
|
@@ -29922,7 +30041,7 @@ var init_mlInspect = __esm({
|
|
|
29922
30041
|
const relToData = import_path9.default.relative(dataRoot, absDatasetPath);
|
|
29923
30042
|
const inputInContainer = `/app/data/${relToData}`;
|
|
29924
30043
|
const reportDir = import_path9.default.dirname(absDatasetPath);
|
|
29925
|
-
await
|
|
30044
|
+
await import_promises26.default.mkdir(reportDir, { recursive: true });
|
|
29926
30045
|
const reportPath = import_path9.default.join(
|
|
29927
30046
|
reportDir,
|
|
29928
30047
|
`${import_path9.default.basename(datasetPath, import_path9.default.extname(datasetPath))}.profile.html`
|
|
@@ -30018,12 +30137,12 @@ var mlTrainLatestSelect_exports = {};
|
|
|
30018
30137
|
__export(mlTrainLatestSelect_exports, {
|
|
30019
30138
|
main: () => main35
|
|
30020
30139
|
});
|
|
30021
|
-
var import_path10,
|
|
30140
|
+
var import_path10, import_promises27, import_fs4, import_crypto2, import_child_process3, import_events, import_readline3, import_args24, import_chalk39, import_ml2, toFileToken6, asBool, asInt7, asNonNegativeInt, formatBytes, getMlContainerMemUsage, MODEL_TYPES, STRATEGIES, flags22, parseStrategy, parseModelType, selectModelType, listDatasetFiles, concatFiles, pipeNormalized, DAY_MS13, SPLIT_PROGRESS_EVERY, parseTimestampMs, scanMaxLabeledTimestampMs, scanMaxTrainTimestampMs, hashFileNameSha1, prepareTrainWindowFiles, main35;
|
|
30022
30141
|
var init_mlTrainLatestSelect = __esm({
|
|
30023
30142
|
"src/scripts/mlTrainLatestSelect.ts"() {
|
|
30024
30143
|
"use strict";
|
|
30025
30144
|
import_path10 = __toESM(require("path"));
|
|
30026
|
-
|
|
30145
|
+
import_promises27 = __toESM(require("fs/promises"));
|
|
30027
30146
|
import_fs4 = require("fs");
|
|
30028
30147
|
import_crypto2 = require("crypto");
|
|
30029
30148
|
import_child_process3 = require("child_process");
|
|
@@ -30152,7 +30271,7 @@ var init_mlTrainLatestSelect = __esm({
|
|
|
30152
30271
|
return defaultModel;
|
|
30153
30272
|
};
|
|
30154
30273
|
listDatasetFiles = async (dir, strategyName) => {
|
|
30155
|
-
const entries = await
|
|
30274
|
+
const entries = await import_promises27.default.readdir(dir, { withFileTypes: true });
|
|
30156
30275
|
const prefix = `ml-dataset-${toFileToken6(strategyName)}-`;
|
|
30157
30276
|
const legacyPrefix = "ml-dataset-";
|
|
30158
30277
|
const fileNames = entries.filter((entry) => entry.isFile()).map((entry) => entry.name);
|
|
@@ -30163,7 +30282,7 @@ var init_mlTrainLatestSelect = __esm({
|
|
|
30163
30282
|
).filter((name) => !name.includes(".train.") && !name.includes(".test.")).filter((name) => !name.includes(".holdout-train.")).filter((name) => !name.includes(".holdout-test.")).filter((name) => !name.includes(".walk-forward.")).filter((name) => !name.includes(".prod."));
|
|
30164
30283
|
const withMtime = await Promise.all(
|
|
30165
30284
|
jsonlFiles.map(async (name) => {
|
|
30166
|
-
const stat = await
|
|
30285
|
+
const stat = await import_promises27.default.stat(import_path10.default.join(dir, name));
|
|
30167
30286
|
return { name, mtime: stat.mtimeMs };
|
|
30168
30287
|
})
|
|
30169
30288
|
);
|
|
@@ -30339,13 +30458,13 @@ var init_mlTrainLatestSelect = __esm({
|
|
|
30339
30458
|
const metaPath = import_path10.default.join(dir, `${parsed.name}.windows.${key2}.meta.json`);
|
|
30340
30459
|
try {
|
|
30341
30460
|
const [metaRaw] = await Promise.all([
|
|
30342
|
-
|
|
30343
|
-
|
|
30344
|
-
|
|
30345
|
-
|
|
30461
|
+
import_promises27.default.readFile(metaPath, "utf8"),
|
|
30462
|
+
import_promises27.default.access(holdoutTrainPath),
|
|
30463
|
+
import_promises27.default.access(holdoutTestPath),
|
|
30464
|
+
import_promises27.default.access(prodPath),
|
|
30346
30465
|
...walkForwardFoldDefs.flatMap((entry) => [
|
|
30347
|
-
|
|
30348
|
-
|
|
30466
|
+
import_promises27.default.access(entry.trainPath),
|
|
30467
|
+
import_promises27.default.access(entry.testPath)
|
|
30349
30468
|
])
|
|
30350
30469
|
]);
|
|
30351
30470
|
const meta2 = JSON.parse(metaRaw);
|
|
@@ -30712,7 +30831,7 @@ var init_mlTrainLatestSelect = __esm({
|
|
|
30712
30831
|
},
|
|
30713
30832
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
30714
30833
|
};
|
|
30715
|
-
await
|
|
30834
|
+
await import_promises27.default.writeFile(metaPath, `${JSON.stringify(meta, null, 2)}
|
|
30716
30835
|
`, "utf8");
|
|
30717
30836
|
return {
|
|
30718
30837
|
holdoutTrainPath,
|
|
@@ -30770,7 +30889,7 @@ var init_mlTrainLatestSelect = __esm({
|
|
|
30770
30889
|
process.exit(1);
|
|
30771
30890
|
}
|
|
30772
30891
|
try {
|
|
30773
|
-
const inputStat = await
|
|
30892
|
+
const inputStat = await import_promises27.default.stat(inputPath);
|
|
30774
30893
|
const totalInputBytes = inputStat.size;
|
|
30775
30894
|
const autoIncrementalThresholdGb = asInt7(
|
|
30776
30895
|
process.env.ML_TRAIN_INCREMENTAL_THRESHOLD_GB,
|
|
@@ -30959,7 +31078,7 @@ var init_mlTrainLatestSelect = __esm({
|
|
|
30959
31078
|
const modelDir = import_path10.default.join(modelDirRoot, "models");
|
|
30960
31079
|
let savedModels = [];
|
|
30961
31080
|
try {
|
|
30962
|
-
const entries = await
|
|
31081
|
+
const entries = await import_promises27.default.readdir(modelDir, { withFileTypes: true });
|
|
30963
31082
|
savedModels = entries.filter((entry) => entry.isFile()).map((entry) => entry.name).filter(
|
|
30964
31083
|
(name) => name === `${selected}.joblib` || /^.+\.model\d+\.joblib$/.test(name)
|
|
30965
31084
|
).filter((name) => name.startsWith(`${selected}.`)).sort();
|
|
@@ -30981,7 +31100,7 @@ var init_mlTrainLatestSelect = __esm({
|
|
|
30981
31100
|
process.exitCode = finalCode;
|
|
30982
31101
|
} finally {
|
|
30983
31102
|
for (const file of cleanupFiles) {
|
|
30984
|
-
await
|
|
31103
|
+
await import_promises27.default.rm(file, { force: true });
|
|
30985
31104
|
}
|
|
30986
31105
|
}
|
|
30987
31106
|
process.exit(process.exitCode ?? 1);
|
|
@@ -31013,20 +31132,20 @@ __export(researchAuto_exports, {
|
|
|
31013
31132
|
toStrategyConfigGrid: () => toStrategyConfigGrid2,
|
|
31014
31133
|
trimTextTail: () => trimTextTail2
|
|
31015
31134
|
});
|
|
31016
|
-
var import_args25, import_chalk40, import_node_child_process5,
|
|
31135
|
+
var import_args25, import_chalk40, import_node_child_process5, import_promises28, import_node_os2, import_node_path21, import_constants19, import_ai8, import_logger7, import_redis18, import_registry4, flags23, projectRoot8, dotenvPath, getResearchAutoLockPath, readResearchAutoLock, isProcessAlive, acquireResearchAutoLock, releaseResearchAutoLock, resolvePositiveInteger, resolveHeapMbFromEnv, buildNodeOptions, RESEARCH_AUTO_PARENT_HEAP_MB, RESEARCH_AUTO_BACKTEST_PARENT_HEAP_MB, RESEARCH_AUTO_AI_TRAIN_PARENT_HEAP_MB, RESEARCH_AUTO_AGENT_PARENT_HEAP_MB, trimTextTail2, escapeHtml3, createEmptySteps, saveRun, listMergedFiles3, getBacktestResultsPrefix, listRuntimeStrategyNames, toStrategyConfigGrid2, formatMskDateTime, buildTelegramReport, runCliCommand, resolveTarget, parseJsonOutput, logResearch, executeNonBlockingStep, main36;
|
|
31017
31136
|
var init_researchAuto = __esm({
|
|
31018
31137
|
"src/scripts/researchAuto.ts"() {
|
|
31019
31138
|
"use strict";
|
|
31020
31139
|
import_args25 = __toESM(require("args"));
|
|
31021
31140
|
import_chalk40 = __toESM(require("chalk"));
|
|
31022
31141
|
import_node_child_process5 = require("child_process");
|
|
31023
|
-
|
|
31142
|
+
import_promises28 = __toESM(require("fs/promises"));
|
|
31024
31143
|
import_node_os2 = __toESM(require("os"));
|
|
31025
|
-
|
|
31144
|
+
import_node_path21 = __toESM(require("path"));
|
|
31026
31145
|
import_constants19 = require("@tradejs/core/constants");
|
|
31027
31146
|
import_ai8 = require("@tradejs/infra/ai");
|
|
31028
31147
|
import_logger7 = require("@tradejs/infra/logger");
|
|
31029
|
-
|
|
31148
|
+
import_redis18 = require("@tradejs/infra/redis");
|
|
31030
31149
|
import_registry4 = require("@tradejs/node/registry");
|
|
31031
31150
|
init_runtimeRedis();
|
|
31032
31151
|
init_runtimeStrategyBacktest();
|
|
@@ -31056,9 +31175,9 @@ var init_researchAuto = __esm({
|
|
|
31056
31175
|
flags23 = import_args25.default.parse(process.argv);
|
|
31057
31176
|
({ projectRoot: projectRoot8 } = resolveResearchRoots());
|
|
31058
31177
|
dotenvPath = String(
|
|
31059
|
-
process.env.DOTENV_CONFIG_PATH ||
|
|
31060
|
-
).trim() ||
|
|
31061
|
-
getResearchAutoLockPath = (userName3) =>
|
|
31178
|
+
process.env.DOTENV_CONFIG_PATH || import_node_path21.default.join(projectRoot8, ".env")
|
|
31179
|
+
).trim() || import_node_path21.default.join(projectRoot8, ".env");
|
|
31180
|
+
getResearchAutoLockPath = (userName3) => import_node_path21.default.join(
|
|
31062
31181
|
projectRoot8,
|
|
31063
31182
|
"data",
|
|
31064
31183
|
"cache",
|
|
@@ -31067,7 +31186,7 @@ var init_researchAuto = __esm({
|
|
|
31067
31186
|
);
|
|
31068
31187
|
readResearchAutoLock = async (lockPath) => {
|
|
31069
31188
|
try {
|
|
31070
|
-
const raw = await
|
|
31189
|
+
const raw = await import_promises28.default.readFile(lockPath, "utf8");
|
|
31071
31190
|
return JSON.parse(raw);
|
|
31072
31191
|
} catch {
|
|
31073
31192
|
return null;
|
|
@@ -31102,9 +31221,9 @@ var init_researchAuto = __esm({
|
|
|
31102
31221
|
startedAt,
|
|
31103
31222
|
argv: [...process.argv]
|
|
31104
31223
|
};
|
|
31105
|
-
await
|
|
31224
|
+
await import_promises28.default.mkdir(import_node_path21.default.dirname(lockPath), { recursive: true });
|
|
31106
31225
|
const writeLock = async () => {
|
|
31107
|
-
await
|
|
31226
|
+
await import_promises28.default.writeFile(lockPath, JSON.stringify(nextLock, null, 2), {
|
|
31108
31227
|
flag: "wx"
|
|
31109
31228
|
});
|
|
31110
31229
|
};
|
|
@@ -31123,7 +31242,7 @@ var init_researchAuto = __esm({
|
|
|
31123
31242
|
`research:auto is already running for user ${userName3} (runId=${existingLock.runId}, strategy=${existingLock.strategy}, pid=${existingLock.pid}, ppid=${existingLock.ppid}, startedAt=${existingLock.startedAt}, host=${existingLock.hostname})`
|
|
31124
31243
|
);
|
|
31125
31244
|
}
|
|
31126
|
-
await
|
|
31245
|
+
await import_promises28.default.unlink(lockPath).catch(() => void 0);
|
|
31127
31246
|
await writeLock();
|
|
31128
31247
|
return lockPath;
|
|
31129
31248
|
};
|
|
@@ -31135,7 +31254,7 @@ var init_researchAuto = __esm({
|
|
|
31135
31254
|
if (existingLock && existingLock.pid !== process.pid) {
|
|
31136
31255
|
return;
|
|
31137
31256
|
}
|
|
31138
|
-
await
|
|
31257
|
+
await import_promises28.default.unlink(lockPath).catch(() => void 0);
|
|
31139
31258
|
};
|
|
31140
31259
|
resolvePositiveInteger = (value, fallback) => {
|
|
31141
31260
|
const parsed = Number.parseInt(String(value ?? ""), 10);
|
|
@@ -31228,18 +31347,18 @@ var init_researchAuto = __esm({
|
|
|
31228
31347
|
}
|
|
31229
31348
|
});
|
|
31230
31349
|
saveRun = async (run) => {
|
|
31231
|
-
await (0,
|
|
31350
|
+
await (0, import_redis18.setData)(import_redis18.redisKeys.researchRun(run.userName, run.runId), run, {
|
|
31232
31351
|
expire: import_constants19.TTL_1M
|
|
31233
31352
|
});
|
|
31234
|
-
await (0,
|
|
31353
|
+
await (0, import_redis18.setData)(import_redis18.redisKeys.researchLatestRun(run.userName, run.strategy), run, {
|
|
31235
31354
|
expire: import_constants19.TTL_1M
|
|
31236
31355
|
});
|
|
31237
31356
|
};
|
|
31238
31357
|
listMergedFiles3 = async (outDir, strategyName) => {
|
|
31239
31358
|
try {
|
|
31240
|
-
const entries = await
|
|
31359
|
+
const entries = await import_promises28.default.readdir(outDir);
|
|
31241
31360
|
const prefix = `ai-dataset-${(0, import_ai8.toFileToken)(strategyName)}-merged-`;
|
|
31242
|
-
return entries.filter((name) => name.startsWith(prefix) && name.endsWith(".jsonl")).sort().map((name) =>
|
|
31361
|
+
return entries.filter((name) => name.startsWith(prefix) && name.endsWith(".jsonl")).sort().map((name) => import_node_path21.default.join(outDir, name));
|
|
31243
31362
|
} catch {
|
|
31244
31363
|
return [];
|
|
31245
31364
|
}
|
|
@@ -31373,7 +31492,7 @@ var init_researchAuto = __esm({
|
|
|
31373
31492
|
return new Promise((resolve, reject) => {
|
|
31374
31493
|
const child = (0, import_node_child_process5.spawn)(
|
|
31375
31494
|
process.execPath,
|
|
31376
|
-
[
|
|
31495
|
+
[import_node_path21.default.resolve(process.argv[1]), params.command, ...params.args],
|
|
31377
31496
|
{
|
|
31378
31497
|
cwd: projectRoot8,
|
|
31379
31498
|
env,
|
|
@@ -31461,8 +31580,8 @@ var init_researchAuto = __esm({
|
|
|
31461
31580
|
const candidates = [];
|
|
31462
31581
|
for (const strategy of availableStrategies) {
|
|
31463
31582
|
const config2 = `${strategy}:research`;
|
|
31464
|
-
const latestRun = await (0,
|
|
31465
|
-
|
|
31583
|
+
const latestRun = await (0, import_redis18.getData)(
|
|
31584
|
+
import_redis18.redisKeys.researchLatestRun(userName3, strategy),
|
|
31466
31585
|
null
|
|
31467
31586
|
);
|
|
31468
31587
|
const lastFinishedAt = latestRun?.finishedAt ? Date.parse(latestRun.finishedAt) : 0;
|
|
@@ -31556,8 +31675,8 @@ var init_researchAuto = __esm({
|
|
|
31556
31675
|
const jsonOutput = Boolean(flags23.json);
|
|
31557
31676
|
const skipAgent = Boolean(flags23.skipAgent);
|
|
31558
31677
|
const outDirArg = String(flags23.outDir || "data/ai/export").trim() || "data/ai/export";
|
|
31559
|
-
const outDir =
|
|
31560
|
-
const cleanDirArg =
|
|
31678
|
+
const outDir = import_node_path21.default.resolve(projectRoot8, outDirArg);
|
|
31679
|
+
const cleanDirArg = import_node_path21.default.relative(import_node_path21.default.join(projectRoot8, "data"), outDir).replace(/\\/g, "/");
|
|
31561
31680
|
const target = await resolveTarget();
|
|
31562
31681
|
const runId = `${Date.now()}-${(0, import_ai8.toFileToken)(target.strategy)}`;
|
|
31563
31682
|
const run = {
|
|
@@ -31641,13 +31760,13 @@ var init_researchAuto = __esm({
|
|
|
31641
31760
|
startedAt
|
|
31642
31761
|
};
|
|
31643
31762
|
await saveRun(run);
|
|
31644
|
-
const strategyConfigKey =
|
|
31763
|
+
const strategyConfigKey = import_redis18.redisKeys.strategyConfig(
|
|
31645
31764
|
userName3,
|
|
31646
31765
|
target.strategy
|
|
31647
31766
|
);
|
|
31648
|
-
const backtestConfigKey =
|
|
31767
|
+
const backtestConfigKey = import_redis18.redisKeys.backtestConfig(userName3, target.config);
|
|
31649
31768
|
const defaults = await (0, import_registry4.getStrategyDefaults)(target.strategy, projectRoot8) || {};
|
|
31650
|
-
const userStrategyConfig = await (0,
|
|
31769
|
+
const userStrategyConfig = await (0, import_redis18.getData)(
|
|
31651
31770
|
strategyConfigKey,
|
|
31652
31771
|
{}
|
|
31653
31772
|
);
|
|
@@ -31661,7 +31780,7 @@ var init_researchAuto = __esm({
|
|
|
31661
31780
|
);
|
|
31662
31781
|
}
|
|
31663
31782
|
const backtestConfig = toStrategyConfigGrid2(strategyConfig);
|
|
31664
|
-
await (0,
|
|
31783
|
+
await (0, import_redis18.setData)(backtestConfigKey, backtestConfig, { expire: 0 });
|
|
31665
31784
|
logResearch(
|
|
31666
31785
|
`stored backtest config at ${backtestConfigKey} with ${Object.keys(strategyConfig).length} top-level fields`
|
|
31667
31786
|
);
|
|
@@ -31701,7 +31820,7 @@ var init_researchAuto = __esm({
|
|
|
31701
31820
|
`resource knobs: researchAutoHeapMb=${RESEARCH_AUTO_PARENT_HEAP_MB}, backtestParentHeapMb=${RESEARCH_AUTO_BACKTEST_PARENT_HEAP_MB}, aiTrainParentHeapMb=${RESEARCH_AUTO_AI_TRAIN_PARENT_HEAP_MB}, agentParentHeapMb=${RESEARCH_AUTO_AGENT_PARENT_HEAP_MB}, backtestWorkerHeapMb=${process.env.BACKTEST_WORKER_HEAP_MB || "auto"}, backtestMaxParallel=${process.env.BACKTEST_MAX_PARALLEL || "auto"}, klineConcurrency=${process.env.KLINE_CONCURRENCY_LIMIT || "default"}`
|
|
31702
31821
|
);
|
|
31703
31822
|
const backtestKeysBefore = new Set(
|
|
31704
|
-
await (0,
|
|
31823
|
+
await (0, import_redis18.getKeys)(getBacktestResultsPrefix(userName3, target.config))
|
|
31705
31824
|
);
|
|
31706
31825
|
const aiFilesBefore = new Set(
|
|
31707
31826
|
await listMergedFiles3(outDir, target.strategy)
|
|
@@ -31763,14 +31882,14 @@ var init_researchAuto = __esm({
|
|
|
31763
31882
|
captureMode: "full"
|
|
31764
31883
|
}
|
|
31765
31884
|
);
|
|
31766
|
-
const backtestKeysAfter = await (0,
|
|
31885
|
+
const backtestKeysAfter = await (0, import_redis18.getKeys)(
|
|
31767
31886
|
getBacktestResultsPrefix(userName3, target.config)
|
|
31768
31887
|
);
|
|
31769
31888
|
const newBacktestKeys = backtestKeysAfter.filter((key2) => !backtestKeysBefore.has(key2)).sort();
|
|
31770
31889
|
const backtestResultKey = newBacktestKeys[newBacktestKeys.length - 1] || backtestKeysAfter.sort().at(-1);
|
|
31771
31890
|
if (backtestResultKey) {
|
|
31772
31891
|
logResearch(`detected backtest result key ${backtestResultKey}`);
|
|
31773
|
-
const backtestResult = await (0,
|
|
31892
|
+
const backtestResult = await (0, import_redis18.getData)(backtestResultKey, null);
|
|
31774
31893
|
run.artifacts.backtestResultKey = backtestResultKey;
|
|
31775
31894
|
run.artifacts.backtestResult = backtestResult ? {
|
|
31776
31895
|
finishedAt: backtestResult.finishedAt,
|
|
@@ -31891,14 +32010,14 @@ Telegram report failed: ${suffix}`;
|
|
|
31891
32010
|
});
|
|
31892
32011
|
|
|
31893
32012
|
// src/lib/coreResearch/artifacts.ts
|
|
31894
|
-
var import_node_fs7, import_node_events2,
|
|
32013
|
+
var import_node_fs7, import_node_events2, import_promises29, import_node_path22, csv, writeLine, closeOutput, writeCoreResearchMatches, writeCoreResearchTrades, summarizeCoreResearchComparison;
|
|
31895
32014
|
var init_artifacts = __esm({
|
|
31896
32015
|
"src/lib/coreResearch/artifacts.ts"() {
|
|
31897
32016
|
"use strict";
|
|
31898
32017
|
import_node_fs7 = require("fs");
|
|
31899
32018
|
import_node_events2 = require("events");
|
|
31900
|
-
|
|
31901
|
-
|
|
32019
|
+
import_promises29 = __toESM(require("fs/promises"));
|
|
32020
|
+
import_node_path22 = __toESM(require("path"));
|
|
31902
32021
|
init_io();
|
|
31903
32022
|
csv = (value) => {
|
|
31904
32023
|
const text3 = String(value ?? "");
|
|
@@ -31912,7 +32031,7 @@ var init_artifacts = __esm({
|
|
|
31912
32031
|
await (0, import_node_events2.once)(output, "close");
|
|
31913
32032
|
};
|
|
31914
32033
|
writeCoreResearchMatches = async (params) => {
|
|
31915
|
-
await
|
|
32034
|
+
await import_promises29.default.mkdir(import_node_path22.default.dirname(params.filePath), { recursive: true });
|
|
31916
32035
|
const output = (0, import_node_fs7.createWriteStream)(params.filePath, { encoding: "utf8" });
|
|
31917
32036
|
await writeLine(
|
|
31918
32037
|
output,
|
|
@@ -31963,7 +32082,7 @@ var init_artifacts = __esm({
|
|
|
31963
32082
|
await closeOutput(output);
|
|
31964
32083
|
};
|
|
31965
32084
|
writeCoreResearchTrades = async (params) => {
|
|
31966
|
-
await
|
|
32085
|
+
await import_promises29.default.mkdir(import_node_path22.default.dirname(params.filePath), { recursive: true });
|
|
31967
32086
|
const output = (0, import_node_fs7.createWriteStream)(params.filePath, { encoding: "utf8" });
|
|
31968
32087
|
for (const variant of params.variants) {
|
|
31969
32088
|
for (const trade of variant.trades) {
|
|
@@ -32251,13 +32370,13 @@ var init_comparison = __esm({
|
|
|
32251
32370
|
});
|
|
32252
32371
|
|
|
32253
32372
|
// src/lib/coreResearch/dataset.ts
|
|
32254
|
-
var
|
|
32373
|
+
var import_node_crypto16, import_node_fs8, import_node_path23, import_node_readline3, asRecord4, finiteNumber4, normalizeDirection, findStrategySetupIdentity, classifyBreadth, classifyDerivatives, resolveCoreResearchRegime, normalizeCompletedTrade, completedTradeIdentity, positionCycleIdentity, sumBy, weightedPrice, aggregatePositionCycles, compareText, compareTrades, readCoreResearchVariant;
|
|
32255
32374
|
var init_dataset2 = __esm({
|
|
32256
32375
|
"src/lib/coreResearch/dataset.ts"() {
|
|
32257
32376
|
"use strict";
|
|
32258
|
-
|
|
32377
|
+
import_node_crypto16 = require("crypto");
|
|
32259
32378
|
import_node_fs8 = require("fs");
|
|
32260
|
-
|
|
32379
|
+
import_node_path23 = __toESM(require("path"));
|
|
32261
32380
|
import_node_readline3 = __toESM(require("readline"));
|
|
32262
32381
|
asRecord4 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
32263
32382
|
finiteNumber4 = (value, field) => {
|
|
@@ -32468,9 +32587,9 @@ var init_dataset2 = __esm({
|
|
|
32468
32587
|
const seen = /* @__PURE__ */ new Map();
|
|
32469
32588
|
let duplicateRowsDropped = 0;
|
|
32470
32589
|
for (const inputPath of variant.files) {
|
|
32471
|
-
const filePath =
|
|
32590
|
+
const filePath = import_node_path23.default.resolve(inputPath);
|
|
32472
32591
|
const input = (0, import_node_fs8.createReadStream)(filePath);
|
|
32473
|
-
const hash2 = (0,
|
|
32592
|
+
const hash2 = (0, import_node_crypto16.createHash)("sha256");
|
|
32474
32593
|
input.on("data", (chunk) => hash2.update(chunk));
|
|
32475
32594
|
const lines = import_node_readline3.default.createInterface({ input, crlfDelay: Infinity });
|
|
32476
32595
|
const fileTrades = [];
|
|
@@ -32960,14 +33079,14 @@ var init_selection = __esm({
|
|
|
32960
33079
|
});
|
|
32961
33080
|
|
|
32962
33081
|
// src/lib/coreResearch/orchestrator.ts
|
|
32963
|
-
var
|
|
33082
|
+
var import_promises30, import_node_path24, import_node_child_process6, import_node_crypto17, import_coreResearch, summarizeSupplementalFiles, analyzeCoreResearchPrepared, analyzeCoreResearch, createCoreResearchSpecTemplate, runCommand2, commandValue, commandHas, validateCoreResearchRunCommand, runCoreResearch;
|
|
32964
33083
|
var init_orchestrator = __esm({
|
|
32965
33084
|
"src/lib/coreResearch/orchestrator.ts"() {
|
|
32966
33085
|
"use strict";
|
|
32967
|
-
|
|
32968
|
-
|
|
33086
|
+
import_promises30 = __toESM(require("fs/promises"));
|
|
33087
|
+
import_node_path24 = __toESM(require("path"));
|
|
32969
33088
|
import_node_child_process6 = require("child_process");
|
|
32970
|
-
|
|
33089
|
+
import_node_crypto17 = require("crypto");
|
|
32971
33090
|
import_coreResearch = require("@tradejs/infra/coreResearch");
|
|
32972
33091
|
init_artifacts();
|
|
32973
33092
|
init_io();
|
|
@@ -33173,7 +33292,7 @@ var init_orchestrator = __esm({
|
|
|
33173
33292
|
const primarySourceHashes = Object.fromEntries(
|
|
33174
33293
|
analyses.flatMap(
|
|
33175
33294
|
(analysis) => analysis.files.map((file) => [
|
|
33176
|
-
|
|
33295
|
+
import_node_path24.default.relative(paths.researchDir, file.path),
|
|
33177
33296
|
file.sha256
|
|
33178
33297
|
])
|
|
33179
33298
|
)
|
|
@@ -33192,8 +33311,8 @@ var init_orchestrator = __esm({
|
|
|
33192
33311
|
const supplementalSourceHashes = Object.fromEntries(
|
|
33193
33312
|
await Promise.all(
|
|
33194
33313
|
supplementalSourcePaths.map(async (filePath) => [
|
|
33195
|
-
|
|
33196
|
-
await sha256File(
|
|
33314
|
+
import_node_path24.default.relative(paths.researchDir, import_node_path24.default.resolve(filePath)),
|
|
33315
|
+
await sha256File(import_node_path24.default.resolve(filePath))
|
|
33197
33316
|
])
|
|
33198
33317
|
)
|
|
33199
33318
|
);
|
|
@@ -33264,7 +33383,7 @@ var init_orchestrator = __esm({
|
|
|
33264
33383
|
const tradesByVariant = new Map(
|
|
33265
33384
|
windowed.map((entry) => [entry.variant.id, entry.trades])
|
|
33266
33385
|
);
|
|
33267
|
-
await
|
|
33386
|
+
await import_promises30.default.writeFile(
|
|
33268
33387
|
paths.reportPath,
|
|
33269
33388
|
buildCoreResearchHtml({ spec, result, tradesByVariant }),
|
|
33270
33389
|
"utf8"
|
|
@@ -33278,17 +33397,17 @@ var init_orchestrator = __esm({
|
|
|
33278
33397
|
"trades.jsonl": await sha256File(paths.tradesPath),
|
|
33279
33398
|
"report.html": await sha256File(paths.reportPath)
|
|
33280
33399
|
};
|
|
33281
|
-
const resolvedRunsPath =
|
|
33400
|
+
const resolvedRunsPath = import_node_path24.default.join(paths.researchDir, "resolved-runs.json");
|
|
33282
33401
|
try {
|
|
33283
33402
|
artifactHashes["resolved-runs.json"] = await sha256File(resolvedRunsPath);
|
|
33284
33403
|
} catch (error) {
|
|
33285
33404
|
if (error.code !== "ENOENT") throw error;
|
|
33286
33405
|
}
|
|
33287
33406
|
try {
|
|
33288
|
-
for (const name of await
|
|
33407
|
+
for (const name of await import_promises30.default.readdir(paths.runLogDir)) {
|
|
33289
33408
|
if (!name.endsWith(".log")) continue;
|
|
33290
33409
|
artifactHashes[`runs/${name}`] = await sha256File(
|
|
33291
|
-
|
|
33410
|
+
import_node_path24.default.join(paths.runLogDir, name)
|
|
33292
33411
|
);
|
|
33293
33412
|
}
|
|
33294
33413
|
} catch (error) {
|
|
@@ -33345,9 +33464,9 @@ var init_orchestrator = __esm({
|
|
|
33345
33464
|
}
|
|
33346
33465
|
};
|
|
33347
33466
|
createCoreResearchSpecTemplate = (params) => {
|
|
33348
|
-
const rootDir =
|
|
33349
|
-
|
|
33350
|
-
|
|
33467
|
+
const rootDir = import_node_path24.default.relative(
|
|
33468
|
+
import_node_path24.default.resolve(params.projectRoot),
|
|
33469
|
+
import_node_path24.default.join(import_node_path24.default.resolve(params.projectRoot), "data", "research", "core")
|
|
33351
33470
|
).replace(/\\/g, "/");
|
|
33352
33471
|
const lineage = (() => {
|
|
33353
33472
|
try {
|
|
@@ -33378,7 +33497,7 @@ var init_orchestrator = __esm({
|
|
|
33378
33497
|
gitSha,
|
|
33379
33498
|
...sourceRepository ? { sourceRepository } : {},
|
|
33380
33499
|
...dirtyDiff ? {
|
|
33381
|
-
dirtyDiffSha256: (0,
|
|
33500
|
+
dirtyDiffSha256: (0, import_node_crypto17.createHash)("sha256").update(dirtyDiff).digest("hex")
|
|
33382
33501
|
} : {}
|
|
33383
33502
|
};
|
|
33384
33503
|
} catch {
|
|
@@ -33485,7 +33604,7 @@ var init_orchestrator = __esm({
|
|
|
33485
33604
|
};
|
|
33486
33605
|
runCommand2 = async (params) => {
|
|
33487
33606
|
if (!params.command.length) throw new Error("Cannot run an empty command");
|
|
33488
|
-
await
|
|
33607
|
+
await import_promises30.default.mkdir(import_node_path24.default.dirname(params.logPath), { recursive: true });
|
|
33489
33608
|
const chunks = [];
|
|
33490
33609
|
const child = (0, import_node_child_process6.spawn)(params.command[0], params.command.slice(1), {
|
|
33491
33610
|
cwd: params.cwd,
|
|
@@ -33505,7 +33624,7 @@ var init_orchestrator = __esm({
|
|
|
33505
33624
|
child.once("close", (code) => resolve(code ?? 1));
|
|
33506
33625
|
});
|
|
33507
33626
|
const output = chunks.join("");
|
|
33508
|
-
await
|
|
33627
|
+
await import_promises30.default.writeFile(params.logPath, output, "utf8");
|
|
33509
33628
|
if (exitCode !== 0) {
|
|
33510
33629
|
throw new Error(
|
|
33511
33630
|
`Command failed with exit ${exitCode}: ${params.command.join(" ")}`
|
|
@@ -33559,7 +33678,7 @@ var init_orchestrator = __esm({
|
|
|
33559
33678
|
};
|
|
33560
33679
|
runCoreResearch = async (params) => {
|
|
33561
33680
|
const { spec } = params;
|
|
33562
|
-
const cwd =
|
|
33681
|
+
const cwd = import_node_path24.default.resolve(params.cwd ?? process.cwd());
|
|
33563
33682
|
const prepared = await prepareCoreResearch(spec);
|
|
33564
33683
|
await verifyPreparedSupport(prepared);
|
|
33565
33684
|
const resolvedVariants = [];
|
|
@@ -33578,7 +33697,7 @@ var init_orchestrator = __esm({
|
|
|
33578
33697
|
artifactHashes: { variant: sha256Json(variant) }
|
|
33579
33698
|
});
|
|
33580
33699
|
let runId = "";
|
|
33581
|
-
const backtestLogPath =
|
|
33700
|
+
const backtestLogPath = import_node_path24.default.join(
|
|
33582
33701
|
prepared.paths.runLogDir,
|
|
33583
33702
|
`${variant.id}-backtest.log`
|
|
33584
33703
|
);
|
|
@@ -33594,7 +33713,7 @@ var init_orchestrator = __esm({
|
|
|
33594
33713
|
env: {
|
|
33595
33714
|
PROJECT_CWD: cwd,
|
|
33596
33715
|
...params.sourceRepositoryRoot ? {
|
|
33597
|
-
[SOURCE_REPOSITORY_ROOT_ENV]:
|
|
33716
|
+
[SOURCE_REPOSITORY_ROOT_ENV]: import_node_path24.default.resolve(
|
|
33598
33717
|
params.sourceRepositoryRoot
|
|
33599
33718
|
)
|
|
33600
33719
|
} : {}
|
|
@@ -33609,12 +33728,12 @@ var init_orchestrator = __esm({
|
|
|
33609
33728
|
if (!runId) {
|
|
33610
33729
|
throw new Error(`Backtest for ${variant.id} did not report a run id`);
|
|
33611
33730
|
}
|
|
33612
|
-
const exportLogPath =
|
|
33731
|
+
const exportLogPath = import_node_path24.default.join(
|
|
33613
33732
|
prepared.paths.runLogDir,
|
|
33614
33733
|
`${variant.id}-export.log`
|
|
33615
33734
|
);
|
|
33616
33735
|
const exportParts = [];
|
|
33617
|
-
const cliPath =
|
|
33736
|
+
const cliPath = import_node_path24.default.resolve(process.argv[1]);
|
|
33618
33737
|
await runCommand2({
|
|
33619
33738
|
command: [
|
|
33620
33739
|
process.execPath,
|
|
@@ -33634,14 +33753,14 @@ var init_orchestrator = __esm({
|
|
|
33634
33753
|
env: {
|
|
33635
33754
|
PROJECT_CWD: cwd,
|
|
33636
33755
|
...params.sourceRepositoryRoot ? {
|
|
33637
|
-
[SOURCE_REPOSITORY_ROOT_ENV]:
|
|
33756
|
+
[SOURCE_REPOSITORY_ROOT_ENV]: import_node_path24.default.resolve(
|
|
33638
33757
|
params.sourceRepositoryRoot
|
|
33639
33758
|
)
|
|
33640
33759
|
} : {}
|
|
33641
33760
|
},
|
|
33642
33761
|
onLine: (line) => {
|
|
33643
33762
|
const match = line.match(/^part\d+:\s+(.+)$/);
|
|
33644
|
-
if (match) exportParts.push(
|
|
33763
|
+
if (match) exportParts.push(import_node_path24.default.resolve(cwd, match[1].trim()));
|
|
33645
33764
|
}
|
|
33646
33765
|
});
|
|
33647
33766
|
if (!exportParts.length) {
|
|
@@ -33652,7 +33771,7 @@ var init_orchestrator = __esm({
|
|
|
33652
33771
|
const traceFiles = await (0, import_coreResearch.listCoreResearchTraceFiles)({
|
|
33653
33772
|
strategyName: spec.strategy,
|
|
33654
33773
|
runId,
|
|
33655
|
-
outDir:
|
|
33774
|
+
outDir: import_node_path24.default.resolve(cwd, "data/research/core/trace")
|
|
33656
33775
|
});
|
|
33657
33776
|
resolvedVariants.push({
|
|
33658
33777
|
...variant,
|
|
@@ -33672,7 +33791,7 @@ var init_orchestrator = __esm({
|
|
|
33672
33791
|
...Object.fromEntries(
|
|
33673
33792
|
await Promise.all(
|
|
33674
33793
|
exportParts.map(async (filePath) => [
|
|
33675
|
-
|
|
33794
|
+
import_node_path24.default.basename(filePath),
|
|
33676
33795
|
await sha256File(filePath)
|
|
33677
33796
|
])
|
|
33678
33797
|
)
|
|
@@ -33691,7 +33810,7 @@ var init_orchestrator = __esm({
|
|
|
33691
33810
|
}
|
|
33692
33811
|
}
|
|
33693
33812
|
await writeJsonAtomic(
|
|
33694
|
-
|
|
33813
|
+
import_node_path24.default.join(prepared.paths.researchDir, "resolved-runs.json"),
|
|
33695
33814
|
{
|
|
33696
33815
|
schema: "tradejs-core-research-resolved-runs/v1",
|
|
33697
33816
|
researchId: spec.researchId,
|
|
@@ -33711,12 +33830,12 @@ var coreResearch_exports = {};
|
|
|
33711
33830
|
__export(coreResearch_exports, {
|
|
33712
33831
|
main: () => main37
|
|
33713
33832
|
});
|
|
33714
|
-
var
|
|
33833
|
+
var import_promises31, import_node_path25, import_chalk41, valueAfter, required, parseTimestamp, readSymbols, printUsage, main37;
|
|
33715
33834
|
var init_coreResearch = __esm({
|
|
33716
33835
|
"src/scripts/coreResearch.ts"() {
|
|
33717
33836
|
"use strict";
|
|
33718
|
-
|
|
33719
|
-
|
|
33837
|
+
import_promises31 = __toESM(require("fs/promises"));
|
|
33838
|
+
import_node_path25 = __toESM(require("path"));
|
|
33720
33839
|
import_chalk41 = __toESM(require("chalk"));
|
|
33721
33840
|
init_io();
|
|
33722
33841
|
init_orchestrator();
|
|
@@ -33740,7 +33859,7 @@ var init_coreResearch = __esm({
|
|
|
33740
33859
|
const symbolsFile = valueAfter(argv2, "--symbolsFile");
|
|
33741
33860
|
if (symbolsFile) {
|
|
33742
33861
|
const parsed = JSON.parse(
|
|
33743
|
-
await
|
|
33862
|
+
await import_promises31.default.readFile(import_node_path25.default.resolve(projectRoot18, symbolsFile), "utf8")
|
|
33744
33863
|
);
|
|
33745
33864
|
if (!Array.isArray(parsed) || parsed.some((symbol) => typeof symbol !== "string")) {
|
|
33746
33865
|
throw new Error("--symbolsFile must contain a JSON string array");
|
|
@@ -33771,14 +33890,14 @@ The run command executes only variants with an explicit command[] in the preregi
|
|
|
33771
33890
|
return;
|
|
33772
33891
|
}
|
|
33773
33892
|
if (command === "index") {
|
|
33774
|
-
const rootDir =
|
|
33893
|
+
const rootDir = import_node_path25.default.resolve(
|
|
33775
33894
|
roots.projectRoot,
|
|
33776
33895
|
required(valueAfter(argv2, "--root"), "--root")
|
|
33777
33896
|
);
|
|
33778
33897
|
const index = await writeCoreResearchStageIndex(rootDir);
|
|
33779
33898
|
console.log(
|
|
33780
33899
|
import_chalk41.default.green(
|
|
33781
|
-
`Core research index: ${
|
|
33900
|
+
`Core research index: ${import_node_path25.default.join(rootDir, "index.json")} (${index.families.length} families)`
|
|
33782
33901
|
)
|
|
33783
33902
|
);
|
|
33784
33903
|
return;
|
|
@@ -33787,7 +33906,7 @@ The run command executes only variants with an explicit command[] in the preregi
|
|
|
33787
33906
|
projectRoot: roots.projectRoot
|
|
33788
33907
|
});
|
|
33789
33908
|
if (command === "init") {
|
|
33790
|
-
const outputPath =
|
|
33909
|
+
const outputPath = import_node_path25.default.resolve(
|
|
33791
33910
|
roots.projectRoot,
|
|
33792
33911
|
required(valueAfter(argv2, "--out"), "--out")
|
|
33793
33912
|
);
|
|
@@ -33811,7 +33930,7 @@ The run command executes only variants with an explicit command[] in the preregi
|
|
|
33811
33930
|
);
|
|
33812
33931
|
return;
|
|
33813
33932
|
}
|
|
33814
|
-
const specPath =
|
|
33933
|
+
const specPath = import_node_path25.default.resolve(
|
|
33815
33934
|
roots.projectRoot,
|
|
33816
33935
|
required(valueAfter(argv2, "--spec"), "--spec")
|
|
33817
33936
|
);
|
|
@@ -33961,7 +34080,7 @@ var init_specification = __esm({
|
|
|
33961
34080
|
if (!spec.budget || !spec.selection || !spec.diagnostics)
|
|
33962
34081
|
throw new Error("Missing research budgets or criteria");
|
|
33963
34082
|
if (spec.featurePaths !== void 0 && (!Array.isArray(spec.featurePaths) || !spec.featurePaths.length || spec.featurePaths.length > 64 || new Set(spec.featurePaths).size !== spec.featurePaths.length || spec.featurePaths.some(
|
|
33964
|
-
(
|
|
34083
|
+
(path58) => typeof path58 !== "string" || !/^additionalIndicators\.[a-zA-Z0-9_.]+$/.test(path58) || classifyAiPocketFeaturePath(path58.split(".")) !== "eligible"
|
|
33965
34084
|
)))
|
|
33966
34085
|
throw new Error("Feature paths must be unique causal market features");
|
|
33967
34086
|
positive(spec.budget.maxVariants, "maxVariants", 12);
|
|
@@ -34044,10 +34163,10 @@ var init_specification = __esm({
|
|
|
34044
34163
|
))
|
|
34045
34164
|
throw new Error("Invalid event horizons");
|
|
34046
34165
|
if (!Array.isArray(spec.diagnostics.requiredPaths) || !spec.diagnostics.requiredPaths.length || spec.diagnostics.requiredPaths.some(
|
|
34047
|
-
(
|
|
34166
|
+
(path58) => !/^[a-zA-Z0-9_.]+$/.test(path58) || classifyAiPocketFeaturePath([
|
|
34048
34167
|
"additionalIndicators",
|
|
34049
34168
|
"baseContext",
|
|
34050
|
-
...
|
|
34169
|
+
...path58.split(".")
|
|
34051
34170
|
]) !== "eligible"
|
|
34052
34171
|
))
|
|
34053
34172
|
throw new Error("Required context paths must be causal market features");
|
|
@@ -34092,30 +34211,30 @@ __export(io_exports, {
|
|
|
34092
34211
|
verifyResearchState: () => verifyResearchState,
|
|
34093
34212
|
withResearchLock: () => withResearchLock
|
|
34094
34213
|
});
|
|
34095
|
-
var
|
|
34214
|
+
var import_promises32, import_node_path26, import_node_os3, import_node_crypto18, researchDirectory, readJson, boundResearchPath, withResearchLock, verifyResearchState, verifyCompletedResearch, initializeResearchState, isRetainedDeletion;
|
|
34096
34215
|
var init_io2 = __esm({
|
|
34097
34216
|
"src/lib/strategyResearch/io.ts"() {
|
|
34098
34217
|
"use strict";
|
|
34099
|
-
|
|
34100
|
-
|
|
34218
|
+
import_promises32 = __toESM(require("fs/promises"));
|
|
34219
|
+
import_node_path26 = __toESM(require("path"));
|
|
34101
34220
|
import_node_os3 = __toESM(require("os"));
|
|
34102
|
-
|
|
34221
|
+
import_node_crypto18 = require("crypto");
|
|
34103
34222
|
init_io();
|
|
34104
|
-
researchDirectory = (projectRoot18, spec) =>
|
|
34105
|
-
readJson = async (file) => JSON.parse(await
|
|
34223
|
+
researchDirectory = (projectRoot18, spec) => import_node_path26.default.join(projectRoot18, "data/research/strategy", spec.core.researchId);
|
|
34224
|
+
readJson = async (file) => JSON.parse(await import_promises32.default.readFile(file, "utf8"));
|
|
34106
34225
|
boundResearchPath = async (root, relative) => {
|
|
34107
|
-
const target =
|
|
34108
|
-
const realRoot = await
|
|
34226
|
+
const target = import_node_path26.default.resolve(root, relative);
|
|
34227
|
+
const realRoot = await import_promises32.default.realpath(root);
|
|
34109
34228
|
let ancestor = target;
|
|
34110
34229
|
while (true) {
|
|
34111
34230
|
try {
|
|
34112
|
-
const real = await
|
|
34113
|
-
if (real !== realRoot && !real.startsWith(`${realRoot}${
|
|
34231
|
+
const real = await import_promises32.default.realpath(ancestor);
|
|
34232
|
+
if (real !== realRoot && !real.startsWith(`${realRoot}${import_node_path26.default.sep}`))
|
|
34114
34233
|
throw new Error(`Research path escapes Project: ${relative}`);
|
|
34115
34234
|
break;
|
|
34116
34235
|
} catch (error) {
|
|
34117
34236
|
if (error.code !== "ENOENT") throw error;
|
|
34118
|
-
const parent =
|
|
34237
|
+
const parent = import_node_path26.default.dirname(ancestor);
|
|
34119
34238
|
if (parent === ancestor) throw error;
|
|
34120
34239
|
ancestor = parent;
|
|
34121
34240
|
}
|
|
@@ -34127,9 +34246,9 @@ var init_io2 = __esm({
|
|
|
34127
34246
|
projectRoot18,
|
|
34128
34247
|
"data/research/strategy/.lock"
|
|
34129
34248
|
);
|
|
34130
|
-
await
|
|
34131
|
-
const token = (0,
|
|
34132
|
-
const acquire = () =>
|
|
34249
|
+
await import_promises32.default.mkdir(import_node_path26.default.dirname(file), { recursive: true });
|
|
34250
|
+
const token = (0, import_node_crypto18.randomUUID)();
|
|
34251
|
+
const acquire = () => import_promises32.default.writeFile(
|
|
34133
34252
|
file,
|
|
34134
34253
|
JSON.stringify({ pid: process.pid, host: import_node_os3.default.hostname(), token }),
|
|
34135
34254
|
{ flag: "wx", mode: 384 }
|
|
@@ -34150,18 +34269,18 @@ var init_io2 = __esm({
|
|
|
34150
34269
|
if (probe.code === "ESRCH") alive = false;
|
|
34151
34270
|
}
|
|
34152
34271
|
if (alive) throw new Error(`Research is already running (pid=${lock.pid})`);
|
|
34153
|
-
await
|
|
34272
|
+
await import_promises32.default.unlink(file);
|
|
34154
34273
|
await acquire();
|
|
34155
34274
|
}
|
|
34156
34275
|
try {
|
|
34157
34276
|
return await work();
|
|
34158
34277
|
} finally {
|
|
34159
34278
|
const owner = await readJson(file);
|
|
34160
|
-
if (owner.token === token) await
|
|
34279
|
+
if (owner.token === token) await import_promises32.default.unlink(file);
|
|
34161
34280
|
}
|
|
34162
34281
|
};
|
|
34163
34282
|
verifyResearchState = async (directory, state) => {
|
|
34164
|
-
const frozenSpec = await readJson(
|
|
34283
|
+
const frozenSpec = await readJson(import_node_path26.default.join(directory, "spec.json"));
|
|
34165
34284
|
if (sha256Json(frozenSpec) !== state.specSha256)
|
|
34166
34285
|
throw new Error("Frozen research spec changed");
|
|
34167
34286
|
for (const [name, stage] of Object.entries(state.stages)) {
|
|
@@ -34180,14 +34299,14 @@ var init_io2 = __esm({
|
|
|
34180
34299
|
};
|
|
34181
34300
|
verifyCompletedResearch = async (directory, state) => {
|
|
34182
34301
|
await verifyResearchState(directory, state);
|
|
34183
|
-
const manifest = await readJson(
|
|
34302
|
+
const manifest = await readJson(import_node_path26.default.join(directory, "manifest.json"));
|
|
34184
34303
|
if (manifest.specSha256 !== state.specSha256)
|
|
34185
34304
|
throw new Error("Final manifest spec mismatch");
|
|
34186
34305
|
for (const [relative, expected] of Object.entries(manifest.artifacts))
|
|
34187
34306
|
if (await sha256File(await boundResearchPath(directory, relative)) !== expected)
|
|
34188
34307
|
throw new Error(`Changed final research artifact: ${relative}`);
|
|
34189
|
-
const inventory = await readJson(
|
|
34190
|
-
const projectRoot18 =
|
|
34308
|
+
const inventory = await readJson(import_node_path26.default.join(directory, "retention.json"));
|
|
34309
|
+
const projectRoot18 = import_node_path26.default.resolve(directory, "../../../..");
|
|
34191
34310
|
for (const artifact of inventory.research.permanentArtifacts) {
|
|
34192
34311
|
const file = await boundResearchPath(projectRoot18, artifact.path);
|
|
34193
34312
|
if (await sha256File(file) !== artifact.sha256)
|
|
@@ -34195,8 +34314,8 @@ var init_io2 = __esm({
|
|
|
34195
34314
|
}
|
|
34196
34315
|
};
|
|
34197
34316
|
initializeResearchState = async (directory, spec, lineage) => {
|
|
34198
|
-
await
|
|
34199
|
-
const file =
|
|
34317
|
+
await import_promises32.default.mkdir(directory, { recursive: true });
|
|
34318
|
+
const file = import_node_path26.default.join(directory, "state.json");
|
|
34200
34319
|
let previous;
|
|
34201
34320
|
try {
|
|
34202
34321
|
previous = await readJson(file);
|
|
@@ -34220,18 +34339,18 @@ var init_io2 = __esm({
|
|
|
34220
34339
|
status: "running",
|
|
34221
34340
|
stages: {}
|
|
34222
34341
|
};
|
|
34223
|
-
await writeJsonAtomic(
|
|
34342
|
+
await writeJsonAtomic(import_node_path26.default.join(directory, "spec.json"), spec);
|
|
34224
34343
|
await writeJsonAtomic(file, state);
|
|
34225
34344
|
return state;
|
|
34226
34345
|
};
|
|
34227
34346
|
isRetainedDeletion = async (directory, file, hash2) => {
|
|
34228
34347
|
try {
|
|
34229
|
-
const inventory = await readJson(
|
|
34348
|
+
const inventory = await readJson(import_node_path26.default.join(directory, "retention.json"));
|
|
34230
34349
|
const index = inventory.entries.findIndex(
|
|
34231
34350
|
(entry) => entry.path === file && entry.sha256 === hash2
|
|
34232
34351
|
);
|
|
34233
34352
|
if (index < 0) return false;
|
|
34234
|
-
const receipt = await readJson(
|
|
34353
|
+
const receipt = await readJson(import_node_path26.default.join(directory, "retention", `${index}.json`));
|
|
34235
34354
|
return ["applying", "completed"].includes(receipt.status) && receipt.files[0]?.path === file && receipt.files[0]?.sha256 === hash2;
|
|
34236
34355
|
} catch (error) {
|
|
34237
34356
|
if (error.code === "ENOENT") return false;
|
|
@@ -35271,11 +35390,11 @@ var init_report2 = __esm({
|
|
|
35271
35390
|
});
|
|
35272
35391
|
|
|
35273
35392
|
// src/lib/strategyRelease/researchFileConsumers.ts
|
|
35274
|
-
var
|
|
35393
|
+
var import_node_path27, import_node_child_process7, import_node_util, execFileAsync, runCommand3, GUEST_FILE_CHECK, assertNoResearchFileConsumers;
|
|
35275
35394
|
var init_researchFileConsumers = __esm({
|
|
35276
35395
|
"src/lib/strategyRelease/researchFileConsumers.ts"() {
|
|
35277
35396
|
"use strict";
|
|
35278
|
-
|
|
35397
|
+
import_node_path27 = __toESM(require("path"));
|
|
35279
35398
|
import_node_child_process7 = require("child_process");
|
|
35280
35399
|
import_node_util = require("util");
|
|
35281
35400
|
execFileAsync = (0, import_node_util.promisify)(import_node_child_process7.execFile);
|
|
@@ -35306,15 +35425,15 @@ print(json.dumps(sorted(opened)))
|
|
|
35306
35425
|
`;
|
|
35307
35426
|
assertNoResearchFileConsumers = async (files, run = runCommand3) => {
|
|
35308
35427
|
const virtualPids = /* @__PURE__ */ new Set();
|
|
35309
|
-
const wanted = new Set(files.map((file) =>
|
|
35310
|
-
let commonRoot = files.length ?
|
|
35428
|
+
const wanted = new Set(files.map((file) => import_node_path27.default.resolve(file)));
|
|
35429
|
+
let commonRoot = files.length ? import_node_path27.default.dirname(files[0]) : "";
|
|
35311
35430
|
while (commonRoot && files.some((file) => {
|
|
35312
|
-
const relative =
|
|
35313
|
-
return relative === ".." || relative.startsWith(`..${
|
|
35431
|
+
const relative = import_node_path27.default.relative(commonRoot, file);
|
|
35432
|
+
return relative === ".." || relative.startsWith(`..${import_node_path27.default.sep}`) || import_node_path27.default.isAbsolute(relative);
|
|
35314
35433
|
}))
|
|
35315
|
-
commonRoot =
|
|
35434
|
+
commonRoot = import_node_path27.default.dirname(commonRoot);
|
|
35316
35435
|
const selectors = [];
|
|
35317
|
-
if (files.length > 1e3 && commonRoot !==
|
|
35436
|
+
if (files.length > 1e3 && commonRoot !== import_node_path27.default.parse(commonRoot).root) {
|
|
35318
35437
|
selectors.push(["+D", commonRoot]);
|
|
35319
35438
|
} else {
|
|
35320
35439
|
for (let offset = 0; offset < files.length; offset += 100)
|
|
@@ -35338,7 +35457,7 @@ print(json.dumps(sorted(opened)))
|
|
|
35338
35457
|
if (line.startsWith("c"))
|
|
35339
35458
|
virtual = line.startsWith("ccom.apple.Virtualization.");
|
|
35340
35459
|
if (line.startsWith("n")) {
|
|
35341
|
-
if (!wanted.has(
|
|
35460
|
+
if (!wanted.has(import_node_path27.default.resolve(line.slice(1)))) continue;
|
|
35342
35461
|
if (!virtual || !/^\d+$/.test(pid))
|
|
35343
35462
|
throw new Error(
|
|
35344
35463
|
`Research cleanup found open files: ${line.slice(1)}`
|
|
@@ -35372,9 +35491,9 @@ print(json.dumps(sorted(opened)))
|
|
|
35372
35491
|
for (const mount of container.Mounts) {
|
|
35373
35492
|
if (mount.Type !== "bind") continue;
|
|
35374
35493
|
for (const file of files) {
|
|
35375
|
-
const relative =
|
|
35376
|
-
if (relative === "" || !relative.startsWith(`..${
|
|
35377
|
-
guestFiles.add(
|
|
35494
|
+
const relative = import_node_path27.default.relative(mount.Source, file);
|
|
35495
|
+
if (relative === "" || !relative.startsWith(`..${import_node_path27.default.sep}`) && relative !== ".." && !import_node_path27.default.isAbsolute(relative)) {
|
|
35496
|
+
guestFiles.add(import_node_path27.default.posix.join(mount.Destination, relative));
|
|
35378
35497
|
covered.add(file);
|
|
35379
35498
|
}
|
|
35380
35499
|
}
|
|
@@ -35455,14 +35574,14 @@ var init_evidenceRetention = __esm({
|
|
|
35455
35574
|
});
|
|
35456
35575
|
|
|
35457
35576
|
// src/lib/strategyRelease/researchRetention.ts
|
|
35458
|
-
var
|
|
35577
|
+
var import_promises33, import_researchMetricSnapshot, import_node_path28, import_node_crypto19, import_strategyReleaseEvidence2, SHA256_RE2, mapFiles, fileSha256, inside, applyResearchRetention;
|
|
35459
35578
|
var init_researchRetention = __esm({
|
|
35460
35579
|
"src/lib/strategyRelease/researchRetention.ts"() {
|
|
35461
35580
|
"use strict";
|
|
35462
|
-
|
|
35581
|
+
import_promises33 = __toESM(require("fs/promises"));
|
|
35463
35582
|
import_researchMetricSnapshot = require("@tradejs/infra/researchMetricSnapshot");
|
|
35464
|
-
|
|
35465
|
-
|
|
35583
|
+
import_node_path28 = __toESM(require("path"));
|
|
35584
|
+
import_node_crypto19 = require("crypto");
|
|
35466
35585
|
import_strategyReleaseEvidence2 = require("@tradejs/infra/strategyReleaseEvidence");
|
|
35467
35586
|
init_researchFileConsumers();
|
|
35468
35587
|
init_evidenceRetention();
|
|
@@ -35482,15 +35601,15 @@ var init_researchRetention = __esm({
|
|
|
35482
35601
|
if (worker.status === "rejected") throw worker.reason;
|
|
35483
35602
|
return results2;
|
|
35484
35603
|
};
|
|
35485
|
-
fileSha256 = async (file, bytes) => bytes <= 1024 * 1024 ? (0,
|
|
35604
|
+
fileSha256 = async (file, bytes) => bytes <= 1024 * 1024 ? (0, import_node_crypto19.createHash)("sha256").update(await import_promises33.default.readFile(file)).digest("hex") : (0, import_strategyReleaseEvidence2.strategyEvidenceFileSha256)(file);
|
|
35486
35605
|
inside = (root, file) => {
|
|
35487
|
-
const relative =
|
|
35488
|
-
return relative !== "" && !relative.startsWith(`..${
|
|
35606
|
+
const relative = import_node_path28.default.relative(root, file);
|
|
35607
|
+
return relative !== "" && !relative.startsWith(`..${import_node_path28.default.sep}`) && relative !== ".." && !import_node_path28.default.isAbsolute(relative);
|
|
35489
35608
|
};
|
|
35490
35609
|
applyResearchRetention = async (options) => {
|
|
35491
|
-
const projectRoot18 = await
|
|
35492
|
-
const dataRoot =
|
|
35493
|
-
const resolve = (file) =>
|
|
35610
|
+
const projectRoot18 = await import_promises33.default.realpath(options.projectRoot);
|
|
35611
|
+
const dataRoot = import_node_path28.default.join(projectRoot18, "data");
|
|
35612
|
+
const resolve = (file) => import_node_path28.default.resolve(projectRoot18, file);
|
|
35494
35613
|
const receiptPath2 = resolve(options.receiptPath);
|
|
35495
35614
|
const journalPath = `${receiptPath2}.deleted.jsonl`;
|
|
35496
35615
|
const permanent = new Set(
|
|
@@ -35515,13 +35634,13 @@ var init_researchRetention = __esm({
|
|
|
35515
35634
|
}
|
|
35516
35635
|
await mapFiles(options.research.permanentArtifacts, async (artifact) => {
|
|
35517
35636
|
const file = resolve(artifact.path);
|
|
35518
|
-
if (!inside(projectRoot18, await
|
|
35637
|
+
if (!inside(projectRoot18, await import_promises33.default.realpath(file)) || !SHA256_RE2.test(artifact.sha256) || await fileSha256(file, (await import_promises33.default.stat(file)).size) !== artifact.sha256) {
|
|
35519
35638
|
throw new Error(
|
|
35520
35639
|
`Permanent research artifact checksum/path mismatch: ${file}`
|
|
35521
35640
|
);
|
|
35522
35641
|
}
|
|
35523
35642
|
if (artifact.role === "note") {
|
|
35524
|
-
const handle = await
|
|
35643
|
+
const handle = await import_promises33.default.open(file, "r");
|
|
35525
35644
|
try {
|
|
35526
35645
|
const header = Buffer.alloc(4096);
|
|
35527
35646
|
const { bytesRead } = await handle.read(header, 0, header.length, 0);
|
|
@@ -35534,9 +35653,9 @@ var init_researchRetention = __esm({
|
|
|
35534
35653
|
);
|
|
35535
35654
|
}
|
|
35536
35655
|
if (!retired && /^schema:\s*tradejs-research\/v2\s*$/m.test(frontmatter[1])) {
|
|
35537
|
-
if ((await
|
|
35656
|
+
if ((await import_promises33.default.stat(file)).size > 8 * 1024 * 1024)
|
|
35538
35657
|
throw new Error("Compact permanent note exceeds 8 MiB");
|
|
35539
|
-
const content = await
|
|
35658
|
+
const content = await import_promises33.default.readFile(file, "utf8");
|
|
35540
35659
|
const section = content.split("## Metrics snapshot (machine-readable)")[1]?.split("## Reported metrics")[0] ?? "";
|
|
35541
35660
|
const blocks = [
|
|
35542
35661
|
...section.matchAll(/```json\r?\n([\s\S]*?)\r?\n```/g)
|
|
@@ -35561,9 +35680,9 @@ var init_researchRetention = __esm({
|
|
|
35561
35680
|
if (checkedPaths.has(file))
|
|
35562
35681
|
throw new Error(`Duplicate cleanup path: ${file}`);
|
|
35563
35682
|
checkedPaths.add(file);
|
|
35564
|
-
if (await
|
|
35683
|
+
if (await import_promises33.default.realpath(file) !== file)
|
|
35565
35684
|
throw new Error(`Research cleanup refuses symlinks: ${file}`);
|
|
35566
|
-
const stat = await
|
|
35685
|
+
const stat = await import_promises33.default.lstat(file);
|
|
35567
35686
|
if (!stat.isFile() || stat.size !== entry.bytes || await fileSha256(file, stat.size) !== entry.sha256) {
|
|
35568
35687
|
throw new Error(
|
|
35569
35688
|
`Disposable research file checksum/size mismatch: ${file}`
|
|
@@ -35589,29 +35708,29 @@ var init_researchRetention = __esm({
|
|
|
35589
35708
|
}))
|
|
35590
35709
|
};
|
|
35591
35710
|
if (!options.apply) return receipt;
|
|
35592
|
-
await
|
|
35593
|
-
if (await
|
|
35711
|
+
await import_promises33.default.mkdir(import_node_path28.default.dirname(receiptPath2), { recursive: true });
|
|
35712
|
+
if (await import_promises33.default.realpath(import_node_path28.default.dirname(receiptPath2)) !== import_node_path28.default.dirname(receiptPath2)) {
|
|
35594
35713
|
throw new Error("Cleanup receipt refuses symlinked directories");
|
|
35595
35714
|
}
|
|
35596
|
-
const lock = await
|
|
35715
|
+
const lock = await import_promises33.default.open(`${receiptPath2}.lock`, "wx");
|
|
35597
35716
|
let journal;
|
|
35598
35717
|
const writeReceipt = async () => {
|
|
35599
35718
|
const temp = `${receiptPath2}.${process.pid}.tmp`;
|
|
35600
|
-
await
|
|
35719
|
+
await import_promises33.default.writeFile(temp, `${JSON.stringify(receipt, null, 2)}
|
|
35601
35720
|
`, "utf8");
|
|
35602
|
-
await
|
|
35721
|
+
await import_promises33.default.rename(temp, receiptPath2);
|
|
35603
35722
|
};
|
|
35604
35723
|
try {
|
|
35605
|
-
journal = await
|
|
35724
|
+
journal = await import_promises33.default.open(journalPath, "wx");
|
|
35606
35725
|
receipt.status = "applying";
|
|
35607
35726
|
await writeReceipt();
|
|
35608
35727
|
for (let index = 0; index < checked.length; index += 1) {
|
|
35609
35728
|
const { file, entry, ino, mtimeMs } = checked[index];
|
|
35610
|
-
const stat = await
|
|
35729
|
+
const stat = await import_promises33.default.lstat(file);
|
|
35611
35730
|
if (!stat.isFile() || stat.ino !== ino || stat.mtimeMs !== mtimeMs || stat.size !== entry.bytes) {
|
|
35612
35731
|
throw new Error(`Research file changed during cleanup: ${file}`);
|
|
35613
35732
|
}
|
|
35614
|
-
await
|
|
35733
|
+
await import_promises33.default.unlink(file);
|
|
35615
35734
|
receipt.files[index].removed = true;
|
|
35616
35735
|
await journal.write(`${JSON.stringify(receipt.files[index])}
|
|
35617
35736
|
`);
|
|
@@ -35625,19 +35744,19 @@ var init_researchRetention = __esm({
|
|
|
35625
35744
|
} finally {
|
|
35626
35745
|
await journal?.close();
|
|
35627
35746
|
await lock.close();
|
|
35628
|
-
await
|
|
35747
|
+
await import_promises33.default.unlink(`${receiptPath2}.lock`);
|
|
35629
35748
|
}
|
|
35630
35749
|
};
|
|
35631
35750
|
}
|
|
35632
35751
|
});
|
|
35633
35752
|
|
|
35634
35753
|
// src/lib/strategyResearch/retention.ts
|
|
35635
|
-
var
|
|
35754
|
+
var import_promises34, import_node_path29, createResearchRetentionInventory, applyRetentionInventory, finishResearchRetention;
|
|
35636
35755
|
var init_retention = __esm({
|
|
35637
35756
|
"src/lib/strategyResearch/retention.ts"() {
|
|
35638
35757
|
"use strict";
|
|
35639
|
-
|
|
35640
|
-
|
|
35758
|
+
import_promises34 = __toESM(require("fs/promises"));
|
|
35759
|
+
import_node_path29 = __toESM(require("path"));
|
|
35641
35760
|
init_researchRetention();
|
|
35642
35761
|
init_io();
|
|
35643
35762
|
init_io2();
|
|
@@ -35645,17 +35764,17 @@ var init_retention = __esm({
|
|
|
35645
35764
|
const permanentArtifacts = [];
|
|
35646
35765
|
for (const [role, file] of [
|
|
35647
35766
|
["note", notePath],
|
|
35648
|
-
["metrics",
|
|
35649
|
-
["candidates",
|
|
35650
|
-
["candidates",
|
|
35651
|
-
["ledger",
|
|
35652
|
-
["chart",
|
|
35767
|
+
["metrics", import_node_path29.default.join(directory, "result.json")],
|
|
35768
|
+
["candidates", import_node_path29.default.join(directory, "03-freeze-gates/result.json")],
|
|
35769
|
+
["candidates", import_node_path29.default.join(directory, "resolved-spec.json")],
|
|
35770
|
+
["ledger", import_node_path29.default.join(directory, "05-freeze-primary/result.json")],
|
|
35771
|
+
["chart", import_node_path29.default.join(directory, "report.html")],
|
|
35653
35772
|
...[
|
|
35654
35773
|
"source.patch",
|
|
35655
35774
|
"source-baseline.tar",
|
|
35656
35775
|
"source-untracked.json",
|
|
35657
35776
|
"source-jev-models.json"
|
|
35658
|
-
].map((file2) => ["source",
|
|
35777
|
+
].map((file2) => ["source", import_node_path29.default.join(directory, file2)])
|
|
35659
35778
|
]) {
|
|
35660
35779
|
try {
|
|
35661
35780
|
permanentArtifacts.push({
|
|
@@ -35682,7 +35801,7 @@ var init_retention = __esm({
|
|
|
35682
35801
|
(variant) => variant.files.includes(source)
|
|
35683
35802
|
))
|
|
35684
35803
|
files.set(
|
|
35685
|
-
await
|
|
35804
|
+
await import_promises34.default.realpath(await boundResearchPath(projectRoot18, source)),
|
|
35686
35805
|
sha2
|
|
35687
35806
|
);
|
|
35688
35807
|
}
|
|
@@ -35691,7 +35810,7 @@ var init_retention = __esm({
|
|
|
35691
35810
|
}
|
|
35692
35811
|
const entries = [];
|
|
35693
35812
|
for (const [file, hash2] of files) {
|
|
35694
|
-
const stat = await
|
|
35813
|
+
const stat = await import_promises34.default.stat(file);
|
|
35695
35814
|
entries.push({
|
|
35696
35815
|
path: file,
|
|
35697
35816
|
kind: "research_payload",
|
|
@@ -35715,13 +35834,13 @@ var init_retention = __esm({
|
|
|
35715
35834
|
};
|
|
35716
35835
|
applyRetentionInventory = async (projectRoot18, directory) => {
|
|
35717
35836
|
const inventory = await readJson(
|
|
35718
|
-
|
|
35837
|
+
import_node_path29.default.join(directory, "retention.json")
|
|
35719
35838
|
);
|
|
35720
|
-
const receipts =
|
|
35721
|
-
await
|
|
35839
|
+
const receipts = import_node_path29.default.join(directory, "retention");
|
|
35840
|
+
await import_promises34.default.mkdir(receipts, { recursive: true });
|
|
35722
35841
|
for (let index = 0; index < inventory.entries.length; index++) {
|
|
35723
35842
|
const entry = inventory.entries[index];
|
|
35724
|
-
const receiptPath2 =
|
|
35843
|
+
const receiptPath2 = import_node_path29.default.join(receipts, `${index}.json`);
|
|
35725
35844
|
let receipt;
|
|
35726
35845
|
try {
|
|
35727
35846
|
receipt = await readJson(receiptPath2);
|
|
@@ -35736,7 +35855,7 @@ var init_retention = __esm({
|
|
|
35736
35855
|
);
|
|
35737
35856
|
if (receipt.status === "completed" && recorded.removed) continue;
|
|
35738
35857
|
try {
|
|
35739
|
-
await
|
|
35858
|
+
await import_promises34.default.stat(entry.path);
|
|
35740
35859
|
} catch (error) {
|
|
35741
35860
|
if (error.code !== "ENOENT") throw error;
|
|
35742
35861
|
if (receipt.status !== "applying") throw error;
|
|
@@ -35757,13 +35876,13 @@ var init_retention = __esm({
|
|
|
35757
35876
|
entries: [entry],
|
|
35758
35877
|
receiptPath: receiptPath2,
|
|
35759
35878
|
apply: true,
|
|
35760
|
-
protectedPaths: [
|
|
35879
|
+
protectedPaths: [import_node_path29.default.join(directory, "retention.json")]
|
|
35761
35880
|
});
|
|
35762
35881
|
}
|
|
35763
35882
|
return { status: "completed", files: inventory.entries.length };
|
|
35764
35883
|
};
|
|
35765
35884
|
finishResearchRetention = async (projectRoot18, directory) => {
|
|
35766
|
-
const statusPath =
|
|
35885
|
+
const statusPath = import_node_path29.default.join(directory, "retention-status.json");
|
|
35767
35886
|
try {
|
|
35768
35887
|
const result = await applyRetentionInventory(projectRoot18, directory);
|
|
35769
35888
|
await writeJsonAtomic(statusPath, result);
|
|
@@ -35780,13 +35899,13 @@ var init_retention = __esm({
|
|
|
35780
35899
|
});
|
|
35781
35900
|
|
|
35782
35901
|
// src/lib/strategyResearch/orchestrator.ts
|
|
35783
|
-
var
|
|
35902
|
+
var import_promises35, import_researchMetricSnapshot2, import_node_path30, runStrategyResearch;
|
|
35784
35903
|
var init_orchestrator2 = __esm({
|
|
35785
35904
|
"src/lib/strategyResearch/orchestrator.ts"() {
|
|
35786
35905
|
"use strict";
|
|
35787
|
-
|
|
35906
|
+
import_promises35 = __toESM(require("fs/promises"));
|
|
35788
35907
|
import_researchMetricSnapshot2 = require("@tradejs/infra/researchMetricSnapshot");
|
|
35789
|
-
|
|
35908
|
+
import_node_path30 = __toESM(require("path"));
|
|
35790
35909
|
init_metrics();
|
|
35791
35910
|
init_io();
|
|
35792
35911
|
init_specification();
|
|
@@ -35801,7 +35920,7 @@ var init_orchestrator2 = __esm({
|
|
|
35801
35920
|
runStrategyResearch = async (parameters) => {
|
|
35802
35921
|
let spec = validateStrategyResearchSpec(parameters.spec);
|
|
35803
35922
|
const { backend } = parameters;
|
|
35804
|
-
const projectRoot18 = await
|
|
35923
|
+
const projectRoot18 = await import_promises35.default.realpath(parameters.projectRoot);
|
|
35805
35924
|
await boundResearchPath(
|
|
35806
35925
|
projectRoot18,
|
|
35807
35926
|
`data/research/strategy/${spec.core.researchId}`
|
|
@@ -35810,7 +35929,7 @@ var init_orchestrator2 = __esm({
|
|
|
35810
35929
|
const directory = researchDirectory(projectRoot18, spec);
|
|
35811
35930
|
const lineage = await backend.lineage();
|
|
35812
35931
|
const state = await initializeResearchState(directory, spec, lineage);
|
|
35813
|
-
const statePath =
|
|
35932
|
+
const statePath = import_node_path30.default.join(directory, "state.json");
|
|
35814
35933
|
const elapsedBefore = state.elapsedMs ?? 0;
|
|
35815
35934
|
const activeStart = Date.now();
|
|
35816
35935
|
const elapsed = () => elapsedBefore + Date.now() - activeStart;
|
|
@@ -35820,7 +35939,7 @@ var init_orchestrator2 = __esm({
|
|
|
35820
35939
|
directory,
|
|
35821
35940
|
state,
|
|
35822
35941
|
conclusion: await readJson(
|
|
35823
|
-
|
|
35942
|
+
import_node_path30.default.join(directory, "result.json")
|
|
35824
35943
|
)
|
|
35825
35944
|
};
|
|
35826
35945
|
}
|
|
@@ -35829,14 +35948,14 @@ var init_orchestrator2 = __esm({
|
|
|
35829
35948
|
state.elapsedMs = elapsed();
|
|
35830
35949
|
return writeJsonAtomic(statePath, state);
|
|
35831
35950
|
};
|
|
35832
|
-
const event = async (stage2, status) =>
|
|
35833
|
-
|
|
35951
|
+
const event = async (stage2, status) => import_promises35.default.appendFile(
|
|
35952
|
+
import_node_path30.default.join(directory, "events.jsonl"),
|
|
35834
35953
|
`${JSON.stringify({ at: (/* @__PURE__ */ new Date()).toISOString(), stage: stage2, status, specSha256: state.specSha256 })}
|
|
35835
35954
|
`
|
|
35836
35955
|
);
|
|
35837
35956
|
const stage = async (name, work) => {
|
|
35838
35957
|
const stageDirectory = await boundResearchPath(directory, name);
|
|
35839
|
-
const resultPath =
|
|
35958
|
+
const resultPath = import_node_path30.default.join(stageDirectory, "result.json");
|
|
35840
35959
|
if (state.stages[name]?.status === "completed")
|
|
35841
35960
|
return readJson(resultPath);
|
|
35842
35961
|
if (elapsed() > spec.budget.maxMinutes * 6e4)
|
|
@@ -35851,20 +35970,20 @@ var init_orchestrator2 = __esm({
|
|
|
35851
35970
|
};
|
|
35852
35971
|
state.status = "running";
|
|
35853
35972
|
delete state.error;
|
|
35854
|
-
await
|
|
35973
|
+
await import_promises35.default.mkdir(stageDirectory, { recursive: true });
|
|
35855
35974
|
await save();
|
|
35856
35975
|
await event(name, "started");
|
|
35857
|
-
await
|
|
35858
|
-
|
|
35976
|
+
await import_promises35.default.writeFile(
|
|
35977
|
+
import_node_path30.default.join(directory, "report.html"),
|
|
35859
35978
|
buildStrategyResearchReport({ spec, state, diagnostics })
|
|
35860
35979
|
);
|
|
35861
35980
|
try {
|
|
35862
35981
|
const result = await work(stageDirectory);
|
|
35863
35982
|
await writeJsonAtomic(resultPath, result);
|
|
35864
35983
|
const artifacts = {};
|
|
35865
|
-
for (const file of await
|
|
35866
|
-
const full =
|
|
35867
|
-
if ((await
|
|
35984
|
+
for (const file of await import_promises35.default.readdir(stageDirectory)) {
|
|
35985
|
+
const full = import_node_path30.default.join(stageDirectory, file);
|
|
35986
|
+
if ((await import_promises35.default.stat(full)).isFile())
|
|
35868
35987
|
artifacts[`${name}/${file}`] = await sha256File(full);
|
|
35869
35988
|
}
|
|
35870
35989
|
if (name === "01-preflight") {
|
|
@@ -35875,7 +35994,7 @@ var init_orchestrator2 = __esm({
|
|
|
35875
35994
|
"source-jev-models.json"
|
|
35876
35995
|
]) {
|
|
35877
35996
|
try {
|
|
35878
|
-
artifacts[file] = await sha256File(
|
|
35997
|
+
artifacts[file] = await sha256File(import_node_path30.default.join(directory, file));
|
|
35879
35998
|
} catch (error) {
|
|
35880
35999
|
if (error.code !== "ENOENT")
|
|
35881
36000
|
throw error;
|
|
@@ -35908,14 +36027,14 @@ var init_orchestrator2 = __esm({
|
|
|
35908
36027
|
let previousRunId;
|
|
35909
36028
|
try {
|
|
35910
36029
|
previousRunId = (await readJson(
|
|
35911
|
-
|
|
36030
|
+
import_node_path30.default.join(folder, "native-run.json")
|
|
35912
36031
|
)).runId;
|
|
35913
36032
|
} catch (error) {
|
|
35914
36033
|
if (error.code !== "ENOENT") throw error;
|
|
35915
36034
|
}
|
|
35916
36035
|
if (!previousRunId) {
|
|
35917
36036
|
try {
|
|
35918
|
-
if ((await
|
|
36037
|
+
if ((await import_promises35.default.stat(import_node_path30.default.join(folder, "backtest.log"))).size)
|
|
35919
36038
|
throw new Error(
|
|
35920
36039
|
"Previous native attempt has no recorded run identity; inspect its log before another launch"
|
|
35921
36040
|
);
|
|
@@ -35936,7 +36055,7 @@ var init_orchestrator2 = __esm({
|
|
|
35936
36055
|
},
|
|
35937
36056
|
variant,
|
|
35938
36057
|
folder,
|
|
35939
|
-
async (runId) => writeJsonAtomic(
|
|
36058
|
+
async (runId) => writeJsonAtomic(import_node_path30.default.join(folder, "native-run.json"), { runId }),
|
|
35940
36059
|
previousRunId,
|
|
35941
36060
|
confirmation
|
|
35942
36061
|
);
|
|
@@ -35951,15 +36070,15 @@ var init_orchestrator2 = __esm({
|
|
|
35951
36070
|
try {
|
|
35952
36071
|
const inventory = await stage("01-preflight", async () => {
|
|
35953
36072
|
const prior = [];
|
|
35954
|
-
const root =
|
|
35955
|
-
for (const id of await
|
|
36073
|
+
const root = import_node_path30.default.dirname(directory);
|
|
36074
|
+
for (const id of await import_promises35.default.readdir(root)) {
|
|
35956
36075
|
if (id === spec.core.researchId || id.startsWith(".")) continue;
|
|
35957
36076
|
try {
|
|
35958
36077
|
const previous = await readJson(
|
|
35959
|
-
|
|
36078
|
+
import_node_path30.default.join(root, id, "spec.json")
|
|
35960
36079
|
);
|
|
35961
36080
|
const previousState = await readJson(
|
|
35962
|
-
|
|
36081
|
+
import_node_path30.default.join(root, id, "state.json")
|
|
35963
36082
|
);
|
|
35964
36083
|
const overlap = previous.core.strategy === spec.core.strategy && previous.core.window.start < spec.core.window.end && previous.core.window.end > (spec.testSince || spec.core.window.start);
|
|
35965
36084
|
if (overlap && previousState.holdoutOpenedAt)
|
|
@@ -35985,7 +36104,7 @@ var init_orchestrator2 = __esm({
|
|
|
35985
36104
|
let previous;
|
|
35986
36105
|
try {
|
|
35987
36106
|
previous = (await readJson(
|
|
35988
|
-
|
|
36107
|
+
import_node_path30.default.join(folder, "native-run.json")
|
|
35989
36108
|
)).runId;
|
|
35990
36109
|
} catch (error) {
|
|
35991
36110
|
if (error.code !== "ENOENT")
|
|
@@ -35995,7 +36114,7 @@ var init_orchestrator2 = __esm({
|
|
|
35995
36114
|
spec,
|
|
35996
36115
|
control,
|
|
35997
36116
|
folder,
|
|
35998
|
-
async (runId) => writeJsonAtomic(
|
|
36117
|
+
async (runId) => writeJsonAtomic(import_node_path30.default.join(folder, "native-run.json"), {
|
|
35999
36118
|
runId
|
|
36000
36119
|
}),
|
|
36001
36120
|
previous
|
|
@@ -36009,7 +36128,7 @@ var init_orchestrator2 = __esm({
|
|
|
36009
36128
|
);
|
|
36010
36129
|
spec = { ...spec, testSince: partition.testSince };
|
|
36011
36130
|
}
|
|
36012
|
-
await writeJsonAtomic(
|
|
36131
|
+
await writeJsonAtomic(import_node_path30.default.join(directory, "resolved-spec.json"), spec);
|
|
36013
36132
|
let gates = [];
|
|
36014
36133
|
let primaryId = null;
|
|
36015
36134
|
let frozenSelection;
|
|
@@ -36065,10 +36184,10 @@ var init_orchestrator2 = __esm({
|
|
|
36065
36184
|
core: { ...spec.core, researchId: spec.frozenFrom }
|
|
36066
36185
|
});
|
|
36067
36186
|
const parentState = await readJson(
|
|
36068
|
-
|
|
36187
|
+
import_node_path30.default.join(parentDirectory, "state.json")
|
|
36069
36188
|
);
|
|
36070
36189
|
const parentSpec = await readJson(
|
|
36071
|
-
|
|
36190
|
+
import_node_path30.default.join(parentDirectory, "spec.json")
|
|
36072
36191
|
);
|
|
36073
36192
|
const { verifyCompletedResearch: verifyCompletedResearch2 } = await Promise.resolve().then(() => (init_io2(), io_exports));
|
|
36074
36193
|
await verifyCompletedResearch2(parentDirectory, parentState);
|
|
@@ -36095,10 +36214,10 @@ var init_orchestrator2 = __esm({
|
|
|
36095
36214
|
"Frozen revalidation requires complete, unchanged rules/runtime and a strictly new period"
|
|
36096
36215
|
);
|
|
36097
36216
|
gates = await readJson(
|
|
36098
|
-
|
|
36217
|
+
import_node_path30.default.join(parentDirectory, "03-freeze-gates/result.json")
|
|
36099
36218
|
);
|
|
36100
36219
|
frozenSelection = await readJson(
|
|
36101
|
-
|
|
36220
|
+
import_node_path30.default.join(parentDirectory, "05-freeze-primary/result.json")
|
|
36102
36221
|
);
|
|
36103
36222
|
if (frozenSelection.schema !== "tradejs-research-selection/v1" || !Array.isArray(frozenSelection.compositions))
|
|
36104
36223
|
throw new Error(
|
|
@@ -36227,7 +36346,7 @@ var init_orchestrator2 = __esm({
|
|
|
36227
36346
|
`06-raw-metrics-${variant.id}`,
|
|
36228
36347
|
async (folder) => {
|
|
36229
36348
|
const resolved = spec.frozenFrom ? (await run(spec, variant, `06-raw-revalidation-${variant.id}`)).variant : (await readJson(
|
|
36230
|
-
|
|
36349
|
+
import_node_path30.default.join(directory, `02-raw-${variant.id}`, "result.json")
|
|
36231
36350
|
)).variant;
|
|
36232
36351
|
const dataset = await backend.loadDataset(
|
|
36233
36352
|
spec,
|
|
@@ -36404,7 +36523,7 @@ var init_orchestrator2 = __esm({
|
|
|
36404
36523
|
for (const name of Object.keys(state.stages)) {
|
|
36405
36524
|
try {
|
|
36406
36525
|
const result = await readJson(
|
|
36407
|
-
|
|
36526
|
+
import_node_path30.default.join(directory, name, "result.json")
|
|
36408
36527
|
);
|
|
36409
36528
|
if (result?.variant)
|
|
36410
36529
|
executions.push({ stage: name, ...result.variant });
|
|
@@ -36412,7 +36531,7 @@ var init_orchestrator2 = __esm({
|
|
|
36412
36531
|
if (error.code !== "ENOENT") throw error;
|
|
36413
36532
|
}
|
|
36414
36533
|
}
|
|
36415
|
-
await writeJsonAtomic(
|
|
36534
|
+
await writeJsonAtomic(import_node_path30.default.join(directory, "result.json"), {
|
|
36416
36535
|
...conclusion,
|
|
36417
36536
|
executions,
|
|
36418
36537
|
rawCore: Object.entries(rawReports).map(([id, windows]) => ({
|
|
@@ -36425,8 +36544,8 @@ var init_orchestrator2 = __esm({
|
|
|
36425
36544
|
state.status = "completed";
|
|
36426
36545
|
delete state.error;
|
|
36427
36546
|
await save();
|
|
36428
|
-
await
|
|
36429
|
-
|
|
36547
|
+
await import_promises35.default.writeFile(
|
|
36548
|
+
import_node_path30.default.join(directory, "report.html"),
|
|
36430
36549
|
buildStrategyResearchReport({
|
|
36431
36550
|
spec,
|
|
36432
36551
|
state,
|
|
@@ -36439,7 +36558,7 @@ var init_orchestrator2 = __esm({
|
|
|
36439
36558
|
projectRoot18,
|
|
36440
36559
|
`notes/${spec.core.strategy}`
|
|
36441
36560
|
);
|
|
36442
|
-
await
|
|
36561
|
+
await import_promises35.default.mkdir(noteDirectory, { recursive: true });
|
|
36443
36562
|
const compact = {
|
|
36444
36563
|
...conclusion,
|
|
36445
36564
|
gates,
|
|
@@ -36513,8 +36632,8 @@ ${conclusion.nextAction} Current-snapshot universe; no deployment authorization.
|
|
|
36513
36632
|
throw new Error(
|
|
36514
36633
|
"Compact permanent note exceeds 8 MiB; archive source separately, never truncate metrics"
|
|
36515
36634
|
);
|
|
36516
|
-
await
|
|
36517
|
-
|
|
36635
|
+
await import_promises35.default.writeFile(
|
|
36636
|
+
import_node_path30.default.join(
|
|
36518
36637
|
noteDirectory,
|
|
36519
36638
|
`${spec.core.createdAt.slice(0, 10)}-${spec.core.researchId}.md`
|
|
36520
36639
|
),
|
|
@@ -36522,8 +36641,8 @@ ${conclusion.nextAction} Current-snapshot universe; no deployment authorization.
|
|
|
36522
36641
|
{ flag: "wx" }
|
|
36523
36642
|
).catch(async (error) => {
|
|
36524
36643
|
if (error.code !== "EEXIST") throw error;
|
|
36525
|
-
const existing = await
|
|
36526
|
-
|
|
36644
|
+
const existing = await import_promises35.default.readFile(
|
|
36645
|
+
import_node_path30.default.join(
|
|
36527
36646
|
noteDirectory,
|
|
36528
36647
|
`${spec.core.createdAt.slice(0, 10)}-${spec.core.researchId}.md`
|
|
36529
36648
|
),
|
|
@@ -36535,19 +36654,19 @@ ${conclusion.nextAction} Current-snapshot universe; no deployment authorization.
|
|
|
36535
36654
|
);
|
|
36536
36655
|
});
|
|
36537
36656
|
await writeJsonAtomic(
|
|
36538
|
-
|
|
36657
|
+
import_node_path30.default.join(directory, "retention.json"),
|
|
36539
36658
|
await createResearchRetentionInventory(
|
|
36540
36659
|
projectRoot18,
|
|
36541
36660
|
directory,
|
|
36542
36661
|
spec,
|
|
36543
36662
|
state,
|
|
36544
|
-
|
|
36663
|
+
import_node_path30.default.join(
|
|
36545
36664
|
noteDirectory,
|
|
36546
36665
|
`${spec.core.createdAt.slice(0, 10)}-${spec.core.researchId}.md`
|
|
36547
36666
|
)
|
|
36548
36667
|
)
|
|
36549
36668
|
);
|
|
36550
|
-
await writeJsonAtomic(
|
|
36669
|
+
await writeJsonAtomic(import_node_path30.default.join(directory, "manifest.json"), {
|
|
36551
36670
|
schema: "tradejs-strategy-research-manifest/v1",
|
|
36552
36671
|
specSha256: state.specSha256,
|
|
36553
36672
|
artifacts: Object.fromEntries(
|
|
@@ -36561,7 +36680,7 @@ ${conclusion.nextAction} Current-snapshot universe; no deployment authorization.
|
|
|
36561
36680
|
"retention.json"
|
|
36562
36681
|
].map(async (file) => [
|
|
36563
36682
|
file,
|
|
36564
|
-
await sha256File(
|
|
36683
|
+
await sha256File(import_node_path30.default.join(directory, file))
|
|
36565
36684
|
])
|
|
36566
36685
|
)
|
|
36567
36686
|
)
|
|
@@ -36574,7 +36693,7 @@ ${conclusion.nextAction} Current-snapshot universe; no deployment authorization.
|
|
|
36574
36693
|
);
|
|
36575
36694
|
}
|
|
36576
36695
|
parameters.onProgress?.(
|
|
36577
|
-
`\u0418\u0442\u043E\u0433: ${conclusion.status}. \u041E\u0442\u0447\u0451\u0442: ${
|
|
36696
|
+
`\u0418\u0442\u043E\u0433: ${conclusion.status}. \u041E\u0442\u0447\u0451\u0442: ${import_node_path30.default.join(directory, "report.html")}`
|
|
36578
36697
|
);
|
|
36579
36698
|
return { directory, state, conclusion };
|
|
36580
36699
|
} catch (error) {
|
|
@@ -36595,9 +36714,9 @@ ${conclusion.nextAction} Current-snapshot universe; no deployment authorization.
|
|
|
36595
36714
|
frozenGates: 0
|
|
36596
36715
|
}
|
|
36597
36716
|
};
|
|
36598
|
-
await writeJsonAtomic(
|
|
36599
|
-
await
|
|
36600
|
-
|
|
36717
|
+
await writeJsonAtomic(import_node_path30.default.join(directory, "result.json"), conclusion);
|
|
36718
|
+
await import_promises35.default.writeFile(
|
|
36719
|
+
import_node_path30.default.join(directory, "report.html"),
|
|
36601
36720
|
buildStrategyResearchReport({ spec, state, conclusion, diagnostics })
|
|
36602
36721
|
);
|
|
36603
36722
|
throw error;
|
|
@@ -36608,18 +36727,18 @@ ${conclusion.nextAction} Current-snapshot universe; no deployment authorization.
|
|
|
36608
36727
|
});
|
|
36609
36728
|
|
|
36610
36729
|
// src/lib/strategyResearch/native.ts
|
|
36611
|
-
var
|
|
36730
|
+
var import_promises36, import_node_fs9, import_node_path31, import_node_os4, import_node_readline4, import_node_child_process8, import_node_module3, import_redis19, import_ai9, import_backtest7, import_registry5, import_connectors15, import_data9, import_coreResearch2, import_jev6, validateResearchJevTraining, nativeConfig, runResearchCommand, createNativeStrategyResearchBackend;
|
|
36612
36731
|
var init_native = __esm({
|
|
36613
36732
|
"src/lib/strategyResearch/native.ts"() {
|
|
36614
36733
|
"use strict";
|
|
36615
|
-
|
|
36734
|
+
import_promises36 = __toESM(require("fs/promises"));
|
|
36616
36735
|
import_node_fs9 = require("fs");
|
|
36617
|
-
|
|
36736
|
+
import_node_path31 = __toESM(require("path"));
|
|
36618
36737
|
import_node_os4 = __toESM(require("os"));
|
|
36619
36738
|
import_node_readline4 = __toESM(require("readline"));
|
|
36620
36739
|
import_node_child_process8 = require("child_process");
|
|
36621
36740
|
import_node_module3 = require("module");
|
|
36622
|
-
|
|
36741
|
+
import_redis19 = require("@tradejs/infra/redis");
|
|
36623
36742
|
import_ai9 = require("@tradejs/node/ai");
|
|
36624
36743
|
import_backtest7 = require("@tradejs/node/backtest");
|
|
36625
36744
|
import_registry5 = require("@tradejs/node/registry");
|
|
@@ -36780,7 +36899,7 @@ var init_native = __esm({
|
|
|
36780
36899
|
};
|
|
36781
36900
|
createNativeStrategyResearchBackend = (parameters) => {
|
|
36782
36901
|
const { projectRoot: projectRoot18, sourceRepositoryRoot } = parameters;
|
|
36783
|
-
const cliPath =
|
|
36902
|
+
const cliPath = import_node_path31.default.resolve(parameters.cliPath ?? process.argv[1]);
|
|
36784
36903
|
let connector;
|
|
36785
36904
|
const getConnector = async (spec) => {
|
|
36786
36905
|
if (connector) return connector;
|
|
@@ -36859,57 +36978,57 @@ var init_native = __esm({
|
|
|
36859
36978
|
const untrackedHashes = await Promise.all(
|
|
36860
36979
|
untracked.map(async (file) => [
|
|
36861
36980
|
file,
|
|
36862
|
-
await sha256File(
|
|
36981
|
+
await sha256File(import_node_path31.default.join(sourceRepositoryRoot, file))
|
|
36863
36982
|
])
|
|
36864
36983
|
);
|
|
36865
36984
|
const requireFromRuntime = (0, import_node_module3.createRequire)(cliPath);
|
|
36866
36985
|
const hashes = {};
|
|
36867
36986
|
const hashRuntimeDirectory = async (directory, label, root = directory) => {
|
|
36868
|
-
for (const entry of await
|
|
36987
|
+
for (const entry of await import_promises36.default.readdir(directory, {
|
|
36869
36988
|
withFileTypes: true
|
|
36870
36989
|
})) {
|
|
36871
|
-
const file =
|
|
36990
|
+
const file = import_node_path31.default.join(directory, entry.name);
|
|
36872
36991
|
if (entry.isDirectory())
|
|
36873
36992
|
await hashRuntimeDirectory(file, label, root);
|
|
36874
36993
|
else if (/\.(?:m?js|cjs|json)$/.test(entry.name))
|
|
36875
|
-
hashes[`${label}:${
|
|
36994
|
+
hashes[`${label}:${import_node_path31.default.relative(root, file)}`] = await sha256File(file);
|
|
36876
36995
|
}
|
|
36877
36996
|
};
|
|
36878
|
-
await hashRuntimeDirectory(
|
|
36997
|
+
await hashRuntimeDirectory(import_node_path31.default.dirname(cliPath), "cli-runtime");
|
|
36879
36998
|
for (const entry of [
|
|
36880
36999
|
"@tradejs/node/backtest",
|
|
36881
37000
|
"@tradejs/node/ai",
|
|
36882
37001
|
"@tradejs/core/strategies"
|
|
36883
37002
|
]) {
|
|
36884
37003
|
const resolved = requireFromRuntime.resolve(entry);
|
|
36885
|
-
const directory =
|
|
37004
|
+
const directory = import_node_path31.default.dirname(resolved);
|
|
36886
37005
|
await hashRuntimeDirectory(directory, entry);
|
|
36887
37006
|
}
|
|
36888
|
-
const projectPackages =
|
|
36889
|
-
for (const name of (await
|
|
36890
|
-
const packageRoot =
|
|
37007
|
+
const projectPackages = import_node_path31.default.join(projectRoot18, "node_modules/@tradejs");
|
|
37008
|
+
for (const name of (await import_promises36.default.readdir(projectPackages)).sort()) {
|
|
37009
|
+
const packageRoot = import_node_path31.default.join(projectPackages, name);
|
|
36891
37010
|
const visit = async (directory) => {
|
|
36892
|
-
for (const entry of await
|
|
37011
|
+
for (const entry of await import_promises36.default.readdir(directory, {
|
|
36893
37012
|
withFileTypes: true
|
|
36894
37013
|
})) {
|
|
36895
|
-
const file =
|
|
37014
|
+
const file = import_node_path31.default.join(directory, entry.name);
|
|
36896
37015
|
if (entry.isDirectory()) await visit(file);
|
|
36897
37016
|
else if (/\.(?:m?js|cjs|json)$/.test(entry.name))
|
|
36898
|
-
hashes[`installed:${name}:${
|
|
37017
|
+
hashes[`installed:${name}:${import_node_path31.default.relative(packageRoot, file)}`] = await sha256File(file);
|
|
36899
37018
|
}
|
|
36900
37019
|
};
|
|
36901
37020
|
try {
|
|
36902
|
-
await visit(
|
|
37021
|
+
await visit(import_node_path31.default.join(packageRoot, "dist"));
|
|
36903
37022
|
hashes[`installed:${name}:package.json`] = await sha256File(
|
|
36904
|
-
|
|
37023
|
+
import_node_path31.default.join(packageRoot, "package.json")
|
|
36905
37024
|
);
|
|
36906
37025
|
} catch (error) {
|
|
36907
37026
|
if (error.code !== "ENOENT") throw error;
|
|
36908
37027
|
}
|
|
36909
37028
|
}
|
|
36910
37029
|
return {
|
|
36911
|
-
sourceRoot: await
|
|
36912
|
-
projectRoot: await
|
|
37030
|
+
sourceRoot: await import_promises36.default.realpath(sourceRepositoryRoot),
|
|
37031
|
+
projectRoot: await import_promises36.default.realpath(projectRoot18),
|
|
36913
37032
|
sourceGitSha: git(["rev-parse", "HEAD"]).trim(),
|
|
36914
37033
|
sourceDiffSha256: sha256Json(git(["diff", "--binary", "HEAD"])),
|
|
36915
37034
|
sourceUntrackedSha256: sha256Json(untrackedHashes),
|
|
@@ -36934,8 +37053,8 @@ var init_native = __esm({
|
|
|
36934
37053
|
projectRoot18,
|
|
36935
37054
|
`data/research/strategy/${spec.core.researchId}`
|
|
36936
37055
|
);
|
|
36937
|
-
await
|
|
36938
|
-
|
|
37056
|
+
await import_promises36.default.writeFile(
|
|
37057
|
+
import_node_path31.default.join(directory, "source.patch"),
|
|
36939
37058
|
(0, import_node_child_process8.execFileSync)("git", ["diff", "--binary", "HEAD"], {
|
|
36940
37059
|
cwd: sourceRepositoryRoot,
|
|
36941
37060
|
maxBuffer: 32 * 1024 * 1024
|
|
@@ -36948,7 +37067,7 @@ var init_native = __esm({
|
|
|
36948
37067
|
"--format=tar",
|
|
36949
37068
|
"HEAD",
|
|
36950
37069
|
"--output",
|
|
36951
|
-
|
|
37070
|
+
import_node_path31.default.join(directory, "source-baseline.tar")
|
|
36952
37071
|
],
|
|
36953
37072
|
{ cwd: sourceRepositoryRoot }
|
|
36954
37073
|
);
|
|
@@ -36969,7 +37088,7 @@ var init_native = __esm({
|
|
|
36969
37088
|
"Untracked credentials cannot be archived as research source"
|
|
36970
37089
|
);
|
|
36971
37090
|
const file = await boundResearchPath(sourceRepositoryRoot, relative);
|
|
36972
|
-
const content = await
|
|
37091
|
+
const content = await import_promises36.default.readFile(file);
|
|
36973
37092
|
sourceBytes += content.length;
|
|
36974
37093
|
if (sourceBytes > 32 * 1024 * 1024)
|
|
36975
37094
|
throw new Error("Untracked source archive exceeds 32 MiB");
|
|
@@ -36980,7 +37099,7 @@ var init_native = __esm({
|
|
|
36980
37099
|
});
|
|
36981
37100
|
}
|
|
36982
37101
|
await writeJsonAtomic(
|
|
36983
|
-
|
|
37102
|
+
import_node_path31.default.join(directory, "source-untracked.json"),
|
|
36984
37103
|
sourceFiles
|
|
36985
37104
|
);
|
|
36986
37105
|
const models = /* @__PURE__ */ new Map();
|
|
@@ -36988,7 +37107,7 @@ var init_native = __esm({
|
|
|
36988
37107
|
const jev = (0, import_jev6.parseJevConfig)(variant.resolvedConfig.JEV);
|
|
36989
37108
|
if (jev?.source !== "local") continue;
|
|
36990
37109
|
const file = await boundResearchPath(projectRoot18, jev.modelFile);
|
|
36991
|
-
const bytes = await
|
|
37110
|
+
const bytes = await import_promises36.default.readFile(file);
|
|
36992
37111
|
if (bytes.length > 32 * 1024 * 1024 || await sha256File(file) !== jev.modelSha256)
|
|
36993
37112
|
throw new Error("Frozen local Jev model size/checksum mismatch");
|
|
36994
37113
|
validateResearchJevTraining(
|
|
@@ -37002,7 +37121,7 @@ var init_native = __esm({
|
|
|
37002
37121
|
});
|
|
37003
37122
|
}
|
|
37004
37123
|
if (models.size)
|
|
37005
|
-
await writeJsonAtomic(
|
|
37124
|
+
await writeJsonAtomic(import_node_path31.default.join(directory, "source-jev-models.json"), [
|
|
37006
37125
|
...models.values()
|
|
37007
37126
|
]);
|
|
37008
37127
|
const coverage = [];
|
|
@@ -37050,7 +37169,7 @@ var init_native = __esm({
|
|
|
37050
37169
|
};
|
|
37051
37170
|
}
|
|
37052
37171
|
assertResources(spec);
|
|
37053
|
-
await
|
|
37172
|
+
await import_promises36.default.mkdir(directory, { recursive: true });
|
|
37054
37173
|
const config2 = nativeConfig(spec, variant);
|
|
37055
37174
|
const jev = (0, import_jev6.parseJevConfig)(config2.JEV);
|
|
37056
37175
|
if (jev?.source === "provider")
|
|
@@ -37083,17 +37202,17 @@ var init_native = __esm({
|
|
|
37083
37202
|
const grid = Object.fromEntries(
|
|
37084
37203
|
Object.entries(config2).map(([key3, value]) => [key3, [value]])
|
|
37085
37204
|
);
|
|
37086
|
-
const key2 =
|
|
37087
|
-
const existing = await (0,
|
|
37205
|
+
const key2 = import_redis19.redisKeys.backtestConfig("root", configName);
|
|
37206
|
+
const existing = await (0, import_redis19.getData)(key2, null);
|
|
37088
37207
|
if (existing != null && sha256Json(existing) !== sha256Json(grid))
|
|
37089
37208
|
throw new Error(`Frozen research config changed: ${configName}`);
|
|
37090
|
-
if (existing == null) await (0,
|
|
37209
|
+
if (existing == null) await (0, import_redis19.setData)(key2, grid, { expire: 0 });
|
|
37091
37210
|
let runId = previousRunId ?? "";
|
|
37092
37211
|
const common = {
|
|
37093
37212
|
executable: process.execPath,
|
|
37094
37213
|
cwd: projectRoot18,
|
|
37095
37214
|
timeoutMs: spec.budget.maxMinutes * 6e4,
|
|
37096
|
-
processReceipt:
|
|
37215
|
+
processReceipt: import_node_path31.default.join(directory, "native-process.json"),
|
|
37097
37216
|
env: {
|
|
37098
37217
|
PROJECT_CWD: projectRoot18,
|
|
37099
37218
|
TRADEJS_SOURCE_REPOSITORY_ROOT: sourceRepositoryRoot,
|
|
@@ -37111,7 +37230,7 @@ var init_native = __esm({
|
|
|
37111
37230
|
if (previousManifest?.status !== "completed")
|
|
37112
37231
|
await runResearchCommand({
|
|
37113
37232
|
...common,
|
|
37114
|
-
log:
|
|
37233
|
+
log: import_node_path31.default.join(directory, "backtest.log"),
|
|
37115
37234
|
args: [
|
|
37116
37235
|
cliPath,
|
|
37117
37236
|
"backtest",
|
|
@@ -37168,13 +37287,13 @@ var init_native = __esm({
|
|
|
37168
37287
|
userName: "root"
|
|
37169
37288
|
});
|
|
37170
37289
|
if (completed.length === manifest.testSuite.length && completed.every((entry) => Number(entry.result.stat.orders) === 0)) {
|
|
37171
|
-
const empty =
|
|
37172
|
-
await
|
|
37290
|
+
const empty = import_node_path31.default.join(directory, "verified-empty.jsonl");
|
|
37291
|
+
await import_promises36.default.writeFile(empty, "");
|
|
37173
37292
|
files.push(empty);
|
|
37174
37293
|
} else
|
|
37175
37294
|
await runResearchCommand({
|
|
37176
37295
|
...common,
|
|
37177
|
-
log:
|
|
37296
|
+
log: import_node_path31.default.join(directory, "export.log"),
|
|
37178
37297
|
args: [
|
|
37179
37298
|
cliPath,
|
|
37180
37299
|
"ai-export",
|
|
@@ -37189,7 +37308,7 @@ var init_native = __esm({
|
|
|
37189
37308
|
],
|
|
37190
37309
|
onLine: (line) => {
|
|
37191
37310
|
const match = line.match(/^part\d+:\s+(.+)$/);
|
|
37192
|
-
if (match) files.push(
|
|
37311
|
+
if (match) files.push(import_node_path31.default.resolve(projectRoot18, match[1].trim()));
|
|
37193
37312
|
}
|
|
37194
37313
|
});
|
|
37195
37314
|
if (!files.length)
|
|
@@ -37205,7 +37324,7 @@ var init_native = __esm({
|
|
|
37205
37324
|
configSha256: sha256Json(config2)
|
|
37206
37325
|
};
|
|
37207
37326
|
await writeJsonAtomic(
|
|
37208
|
-
|
|
37327
|
+
import_node_path31.default.join(directory, "sources.json"),
|
|
37209
37328
|
Object.fromEntries(
|
|
37210
37329
|
await Promise.all(
|
|
37211
37330
|
files.map(async (file) => [file, await sha256File(file)])
|
|
@@ -37250,7 +37369,7 @@ var init_native = __esm({
|
|
|
37250
37369
|
)
|
|
37251
37370
|
});
|
|
37252
37371
|
await writeJsonAtomic(
|
|
37253
|
-
|
|
37372
|
+
import_node_path31.default.join(directory, "reconciliation.json"),
|
|
37254
37373
|
reconciliation
|
|
37255
37374
|
);
|
|
37256
37375
|
if (reconciliation.status !== "match")
|
|
@@ -37469,12 +37588,12 @@ var init_native = __esm({
|
|
|
37469
37588
|
const traceFiles = variant.runId ? await (0, import_coreResearch2.listCoreResearchTraceFiles)({
|
|
37470
37589
|
strategyName: spec.core.strategy,
|
|
37471
37590
|
runId: variant.runId,
|
|
37472
|
-
outDir:
|
|
37591
|
+
outDir: import_node_path31.default.join(projectRoot18, "data/research/core/trace")
|
|
37473
37592
|
}) : [];
|
|
37474
37593
|
const funnel2 = traceFiles.length ? await summarizeCoreResearchTrace(traceFiles) : null;
|
|
37475
37594
|
if (variant.configName === `${spec.core.strategy}:auto-${spec.core.researchId}-${variant.id}`)
|
|
37476
37595
|
await writeJsonAtomic(
|
|
37477
|
-
|
|
37596
|
+
import_node_path31.default.join(directory, "payloads.json"),
|
|
37478
37597
|
Object.fromEntries(
|
|
37479
37598
|
await Promise.all(
|
|
37480
37599
|
traceFiles.map(async (file) => [file, await sha256File(file)])
|
|
@@ -37521,17 +37640,17 @@ var strategyResearch_exports = {};
|
|
|
37521
37640
|
__export(strategyResearch_exports, {
|
|
37522
37641
|
main: () => main38
|
|
37523
37642
|
});
|
|
37524
|
-
var
|
|
37643
|
+
var import_promises37, import_node_path32, import_redis20, usage, main38;
|
|
37525
37644
|
var init_strategyResearch2 = __esm({
|
|
37526
37645
|
"src/scripts/strategyResearch.ts"() {
|
|
37527
37646
|
"use strict";
|
|
37528
|
-
|
|
37529
|
-
|
|
37647
|
+
import_promises37 = __toESM(require("fs/promises"));
|
|
37648
|
+
import_node_path32 = __toESM(require("path"));
|
|
37530
37649
|
init_strategyResearch();
|
|
37531
37650
|
init_researchRoots();
|
|
37532
37651
|
init_io();
|
|
37533
37652
|
init_orchestrator();
|
|
37534
|
-
|
|
37653
|
+
import_redis20 = require("@tradejs/infra/redis");
|
|
37535
37654
|
init_io2();
|
|
37536
37655
|
usage = `Usage:
|
|
37537
37656
|
tradejs research:strategy init --coreSpec <core-spec.json> --out <workflow.json>
|
|
@@ -37584,7 +37703,7 @@ Revalidate keeps the frozen rule and evaluates a new period without fitting.
|
|
|
37584
37703
|
const resolve = (key2) => boundResearchPath(projectRoot18, required4(key2));
|
|
37585
37704
|
if (command === "init") {
|
|
37586
37705
|
const output = await resolve("--out");
|
|
37587
|
-
await
|
|
37706
|
+
await import_promises37.default.mkdir(import_node_path32.default.dirname(output), { recursive: true });
|
|
37588
37707
|
const timestamp = (key2) => {
|
|
37589
37708
|
const text3 = required4(key2);
|
|
37590
37709
|
const value = /^\d+$/.test(text3) ? Number(text3) : Date.parse(text3);
|
|
@@ -37619,8 +37738,8 @@ Revalidate keeps the frozen rule and evaluates a new period without fitting.
|
|
|
37619
37738
|
throw new Error(
|
|
37620
37739
|
"Every config must belong to the selected strategy"
|
|
37621
37740
|
);
|
|
37622
|
-
const grid = await (0,
|
|
37623
|
-
|
|
37741
|
+
const grid = await (0, import_redis20.getData)(
|
|
37742
|
+
import_redis20.redisKeys.backtestConfig("root", configName),
|
|
37624
37743
|
null
|
|
37625
37744
|
);
|
|
37626
37745
|
if (!grid || typeof grid !== "object" || Array.isArray(grid) || !Object.keys(grid).length)
|
|
@@ -37661,7 +37780,7 @@ Revalidate keeps the frozen rule and evaluates a new period without fitting.
|
|
|
37661
37780
|
const spec2 = validateStrategyResearchSpec(
|
|
37662
37781
|
createStrategyResearchSpec(loaded.spec)
|
|
37663
37782
|
);
|
|
37664
|
-
await
|
|
37783
|
+
await import_promises37.default.writeFile(output, `${JSON.stringify(spec2, null, 2)}
|
|
37665
37784
|
`, {
|
|
37666
37785
|
flag: "wx"
|
|
37667
37786
|
});
|
|
@@ -37676,7 +37795,7 @@ Revalidate keeps the frozen rule and evaluates a new period without fitting.
|
|
|
37676
37795
|
const directory = researchDirectory(projectRoot18, spec);
|
|
37677
37796
|
if (command === "status") {
|
|
37678
37797
|
const state = await readJson(
|
|
37679
|
-
|
|
37798
|
+
import_node_path32.default.join(directory, "state.json")
|
|
37680
37799
|
);
|
|
37681
37800
|
console.log(
|
|
37682
37801
|
JSON.stringify(
|
|
@@ -37684,9 +37803,9 @@ Revalidate keeps the frozen rule and evaluates a new period without fitting.
|
|
|
37684
37803
|
status: state.status,
|
|
37685
37804
|
stages: state.stages,
|
|
37686
37805
|
error: state.error,
|
|
37687
|
-
report:
|
|
37806
|
+
report: import_node_path32.default.join(directory, "report.html"),
|
|
37688
37807
|
retention: await readJson(
|
|
37689
|
-
|
|
37808
|
+
import_node_path32.default.join(directory, "retention-status.json")
|
|
37690
37809
|
).catch((error) => {
|
|
37691
37810
|
if (error.code === "ENOENT") return { status: "not-started" };
|
|
37692
37811
|
throw error;
|
|
@@ -37700,7 +37819,7 @@ Revalidate keeps the frozen rule and evaluates a new period without fitting.
|
|
|
37700
37819
|
}
|
|
37701
37820
|
if (command === "verify" || command === "revalidate") {
|
|
37702
37821
|
const state = await readJson(
|
|
37703
|
-
|
|
37822
|
+
import_node_path32.default.join(directory, "state.json")
|
|
37704
37823
|
);
|
|
37705
37824
|
await verifyCompletedResearch(directory, state);
|
|
37706
37825
|
if (command === "verify") {
|
|
@@ -37735,8 +37854,8 @@ Revalidate keeps the frozen rule and evaluates a new period without fitting.
|
|
|
37735
37854
|
}
|
|
37736
37855
|
});
|
|
37737
37856
|
const output = await resolve("--out");
|
|
37738
|
-
await
|
|
37739
|
-
await
|
|
37857
|
+
await import_promises37.default.mkdir(import_node_path32.default.dirname(output), { recursive: true });
|
|
37858
|
+
await import_promises37.default.writeFile(output, `${JSON.stringify(next, null, 2)}
|
|
37740
37859
|
`, {
|
|
37741
37860
|
flag: "wx"
|
|
37742
37861
|
});
|
|
@@ -37760,7 +37879,7 @@ __export(results_exports, {
|
|
|
37760
37879
|
main: () => main39,
|
|
37761
37880
|
results: () => results
|
|
37762
37881
|
});
|
|
37763
|
-
var import_args26, import_chalk42, import_connectors16, import_cli11,
|
|
37882
|
+
var import_args26, import_chalk42, import_connectors16, import_cli11, import_redis21, ListIt4, flags24, MIN_PROFIT, MIN_WIN_RATE, MIN_ORDERS_PER_MONTH, createListIt4, formatPercent4, getMonthlyReturn, toStrategyResultEntry, toStrategyResults, getTestConfigs, buildBestResults, getSavedProfitsBySymbol, getCoverageRow, results, main39;
|
|
37764
37883
|
var init_results = __esm({
|
|
37765
37884
|
"src/scripts/results.ts"() {
|
|
37766
37885
|
"use strict";
|
|
@@ -37768,7 +37887,7 @@ var init_results = __esm({
|
|
|
37768
37887
|
import_chalk42 = __toESM(require("chalk"));
|
|
37769
37888
|
import_connectors16 = require("@tradejs/connectors");
|
|
37770
37889
|
import_cli11 = require("@tradejs/node/cli");
|
|
37771
|
-
|
|
37890
|
+
import_redis21 = require("@tradejs/infra/redis");
|
|
37772
37891
|
ListIt4 = require("list-it");
|
|
37773
37892
|
import_args26.default.example(
|
|
37774
37893
|
"yarn results --strategy TrendLine --coverage",
|
|
@@ -37808,8 +37927,8 @@ var init_results = __esm({
|
|
|
37808
37927
|
[...rows].map((row) => [row.symbol, toStrategyResultEntry(row)])
|
|
37809
37928
|
);
|
|
37810
37929
|
getTestConfigs = async (userName3) => {
|
|
37811
|
-
const testSummariesKey = typeof
|
|
37812
|
-
const indexedItems = testSummariesKey ? await (0,
|
|
37930
|
+
const testSummariesKey = typeof import_redis21.redisKeys.testSummaries === "function" ? import_redis21.redisKeys.testSummaries(userName3) : null;
|
|
37931
|
+
const indexedItems = testSummariesKey ? await (0, import_redis21.getData)(testSummariesKey, null) : null;
|
|
37813
37932
|
if (Array.isArray(indexedItems) && indexedItems.length) {
|
|
37814
37933
|
return indexedItems.map((item) => {
|
|
37815
37934
|
const testName = typeof item?.value === "string" ? item.value : null;
|
|
@@ -37820,8 +37939,8 @@ var init_results = __esm({
|
|
|
37820
37939
|
return { strategyName, testName };
|
|
37821
37940
|
}).filter(Boolean);
|
|
37822
37941
|
}
|
|
37823
|
-
const testsPrefix =
|
|
37824
|
-
const keys = await (0,
|
|
37942
|
+
const testsPrefix = import_redis21.redisKeys.tests(userName3);
|
|
37943
|
+
const keys = await (0, import_redis21.getKeys)(testsPrefix);
|
|
37825
37944
|
const configKeys = keys.filter((key2) => key2.endsWith(":config"));
|
|
37826
37945
|
return configKeys.map((key2) => {
|
|
37827
37946
|
const parts = key2.split(":");
|
|
@@ -37840,15 +37959,15 @@ var init_results = __esm({
|
|
|
37840
37959
|
testName,
|
|
37841
37960
|
strategyName: strategyFromIndex
|
|
37842
37961
|
} of testConfigs) {
|
|
37843
|
-
const config2 = await (0,
|
|
37844
|
-
|
|
37962
|
+
const config2 = await (0, import_redis21.getData)(
|
|
37963
|
+
import_redis21.redisKeys.testConfig(userName3, strategyFromIndex, testName),
|
|
37845
37964
|
null
|
|
37846
37965
|
);
|
|
37847
37966
|
if (!config2 || config2.strategyName !== strategyName) {
|
|
37848
37967
|
continue;
|
|
37849
37968
|
}
|
|
37850
|
-
const stat = await (0,
|
|
37851
|
-
|
|
37969
|
+
const stat = await (0, import_redis21.getData)(
|
|
37970
|
+
import_redis21.redisKeys.testStat(userName3, strategyFromIndex, testName),
|
|
37852
37971
|
null
|
|
37853
37972
|
);
|
|
37854
37973
|
if (!stat) {
|
|
@@ -37893,8 +38012,8 @@ var init_results = __esm({
|
|
|
37893
38012
|
return savedProfitBySymbol;
|
|
37894
38013
|
};
|
|
37895
38014
|
getCoverageRow = async (strategyName, userName3, goodSymbols) => {
|
|
37896
|
-
const currentResults = await (0,
|
|
37897
|
-
|
|
38015
|
+
const currentResults = await (0, import_redis21.getData)(
|
|
38016
|
+
import_redis21.redisKeys.strategyResults(userName3, strategyName),
|
|
37898
38017
|
{}
|
|
37899
38018
|
);
|
|
37900
38019
|
const existingSymbols = new Set(Object.keys(currentResults));
|
|
@@ -37928,8 +38047,8 @@ var init_results = __esm({
|
|
|
37928
38047
|
const strategyName = flags24.strategy;
|
|
37929
38048
|
const userName3 = flags24.user;
|
|
37930
38049
|
if (flags24.clear) {
|
|
37931
|
-
const cleared = await (0,
|
|
37932
|
-
|
|
38050
|
+
const cleared = await (0, import_redis21.delKey)(
|
|
38051
|
+
import_redis21.redisKeys.strategyResults(userName3, strategyName)
|
|
37933
38052
|
);
|
|
37934
38053
|
console.log(
|
|
37935
38054
|
cleared ? import_chalk42.default.green(`Cleared results:${strategyName}`) : import_chalk42.default.yellow(`No results to clear for ${strategyName}`)
|
|
@@ -37977,8 +38096,8 @@ var init_results = __esm({
|
|
|
37977
38096
|
console.log(import_chalk42.default.yellow("No good results to merge."));
|
|
37978
38097
|
process.exit(0);
|
|
37979
38098
|
}
|
|
37980
|
-
const current = await (0,
|
|
37981
|
-
|
|
38099
|
+
const current = await (0, import_redis21.getData)(
|
|
38100
|
+
import_redis21.redisKeys.strategyResults(userName3, strategyName),
|
|
37982
38101
|
{}
|
|
37983
38102
|
);
|
|
37984
38103
|
const savedProfitBySymbol = await getSavedProfitsBySymbol(current);
|
|
@@ -38000,7 +38119,7 @@ var init_results = __esm({
|
|
|
38000
38119
|
...current,
|
|
38001
38120
|
...toStrategyResults(updates)
|
|
38002
38121
|
};
|
|
38003
|
-
await (0,
|
|
38122
|
+
await (0, import_redis21.setData)(import_redis21.redisKeys.strategyResults(userName3, strategyName), merged, {
|
|
38004
38123
|
expire: 0
|
|
38005
38124
|
});
|
|
38006
38125
|
if (flags24.verbose) {
|
|
@@ -38041,8 +38160,8 @@ var init_results = __esm({
|
|
|
38041
38160
|
);
|
|
38042
38161
|
process.exit(0);
|
|
38043
38162
|
}
|
|
38044
|
-
await (0,
|
|
38045
|
-
|
|
38163
|
+
await (0, import_redis21.setData)(
|
|
38164
|
+
import_redis21.redisKeys.strategyResults(userName3, strategyName),
|
|
38046
38165
|
resultsConfig,
|
|
38047
38166
|
{
|
|
38048
38167
|
expire: 0
|
|
@@ -38061,11 +38180,11 @@ var init_results = __esm({
|
|
|
38061
38180
|
});
|
|
38062
38181
|
|
|
38063
38182
|
// src/lib/runtimeDebugEvidence.ts
|
|
38064
|
-
var
|
|
38183
|
+
var import_redis22, RUNTIME_DEBUG_TIMEZONE, RUNTIME_DEBUG_TIMEZONE_LABEL, formatRuntimeDebugDateTime, getRuntimeDebugDateParts, formatRuntimeDebugIsoDayKey, buildRuntimeDebugEvaluationId, filterByStrategies, collectRuntimeDebugEvidence, buildRuntimeDebugReportPayload, buildRuntimeEvidenceReportPayload, buildRuntimeDebugReportAttachment;
|
|
38065
38184
|
var init_runtimeDebugEvidence = __esm({
|
|
38066
38185
|
"src/lib/runtimeDebugEvidence.ts"() {
|
|
38067
38186
|
"use strict";
|
|
38068
|
-
|
|
38187
|
+
import_redis22 = require("@tradejs/infra/redis");
|
|
38069
38188
|
init_runtimeRedis();
|
|
38070
38189
|
init_runtimeSignalsLoader();
|
|
38071
38190
|
init_runtimeSignalsStorage();
|
|
@@ -38172,24 +38291,24 @@ var init_runtimeDebugEvidence = __esm({
|
|
|
38172
38291
|
const tradeDayKey = (0, import_time5.getRuntimeStorageDayKey)(trade.entryTimestamp);
|
|
38173
38292
|
const signalDayKey = signal != null ? (0, import_time5.getRuntimeStorageDayKey)(signal.timestamp) : tradeDayKey;
|
|
38174
38293
|
const evaluationDayKey = knownEvaluation != null ? (0, import_time5.getRuntimeStorageDayKey)(knownEvaluation.timestamp) : signalDayKey;
|
|
38175
|
-
const tradeKey =
|
|
38176
|
-
const tradeBucketKey =
|
|
38294
|
+
const tradeKey = import_redis22.redisKeys.runtimeTrade(userName3, trade.orderId);
|
|
38295
|
+
const tradeBucketKey = import_redis22.redisKeys.runtimeTradeBucket(
|
|
38177
38296
|
userName3,
|
|
38178
38297
|
tradeDayKey
|
|
38179
38298
|
);
|
|
38180
|
-
const activeTradeKey =
|
|
38299
|
+
const activeTradeKey = import_redis22.redisKeys.runtimeActiveTrade(
|
|
38181
38300
|
userName3,
|
|
38182
38301
|
trade.symbol,
|
|
38183
38302
|
trade.deploymentId ?? trade.accountId
|
|
38184
38303
|
);
|
|
38185
|
-
const signalKey = trade.signalId != null ?
|
|
38186
|
-
const evaluationBucketKey =
|
|
38304
|
+
const signalKey = trade.signalId != null ? import_redis22.redisKeys.storeSignal(trade.symbol, trade.signalId) : null;
|
|
38305
|
+
const evaluationBucketKey = import_redis22.redisKeys.runtimeSignalEvaluationBucket(
|
|
38187
38306
|
userName3,
|
|
38188
38307
|
evaluationDayKey,
|
|
38189
38308
|
knownEvaluation?.strategy ?? trade.strategy
|
|
38190
38309
|
);
|
|
38191
38310
|
const evaluationField = knownEvaluation?.evaluationId ?? evaluationId;
|
|
38192
|
-
const evaluationKey =
|
|
38311
|
+
const evaluationKey = import_redis22.redisKeys.runtimeSignalEvaluation(
|
|
38193
38312
|
userName3,
|
|
38194
38313
|
evaluationField
|
|
38195
38314
|
);
|
|
@@ -38200,11 +38319,11 @@ var init_runtimeDebugEvidence = __esm({
|
|
|
38200
38319
|
directEvaluationValue,
|
|
38201
38320
|
bucketEvaluationValue
|
|
38202
38321
|
] = await Promise.all([
|
|
38203
|
-
(0,
|
|
38204
|
-
(0,
|
|
38205
|
-
signalKey ? (0,
|
|
38206
|
-
(0,
|
|
38207
|
-
knownEvaluation ? Promise.resolve(knownEvaluation) : (0,
|
|
38322
|
+
(0, import_redis22.getData)(tradeKey, null),
|
|
38323
|
+
(0, import_redis22.getData)(activeTradeKey, null),
|
|
38324
|
+
signalKey ? (0, import_redis22.getData)(signalKey, null) : Promise.resolve(null),
|
|
38325
|
+
(0, import_redis22.getData)(evaluationKey, null),
|
|
38326
|
+
knownEvaluation ? Promise.resolve(knownEvaluation) : (0, import_redis22.getHashJsonField)(
|
|
38208
38327
|
evaluationBucketKey,
|
|
38209
38328
|
evaluationField,
|
|
38210
38329
|
null
|
|
@@ -38261,12 +38380,12 @@ var init_runtimeDebugEvidence = __esm({
|
|
|
38261
38380
|
dayKeys
|
|
38262
38381
|
},
|
|
38263
38382
|
redisPrefixes: {
|
|
38264
|
-
runtimeTrades:
|
|
38265
|
-
runtimeTradeBuckets:
|
|
38266
|
-
runtimeActiveTrades:
|
|
38267
|
-
runtimeSignals:
|
|
38268
|
-
runtimeSignalEvaluations:
|
|
38269
|
-
runtimeSignalEvaluationStats:
|
|
38383
|
+
runtimeTrades: import_redis22.redisKeys.runtimeTrades(userName3),
|
|
38384
|
+
runtimeTradeBuckets: import_redis22.redisKeys.runtimeTradeBuckets(userName3),
|
|
38385
|
+
runtimeActiveTrades: import_redis22.redisKeys.runtimeActiveTrades(userName3),
|
|
38386
|
+
runtimeSignals: import_redis22.redisKeys.runtimeSignalBuckets(userName3),
|
|
38387
|
+
runtimeSignalEvaluations: import_redis22.redisKeys.runtimeSignalEvaluationBuckets(userName3),
|
|
38388
|
+
runtimeSignalEvaluationStats: import_redis22.redisKeys.runtimeSignalEvaluationStatsBuckets(userName3)
|
|
38270
38389
|
},
|
|
38271
38390
|
counts: {
|
|
38272
38391
|
trades: trades.length,
|
|
@@ -38277,18 +38396,18 @@ var init_runtimeDebugEvidence = __esm({
|
|
|
38277
38396
|
},
|
|
38278
38397
|
trades: debugTrades,
|
|
38279
38398
|
signals: signals2.map((signal) => ({
|
|
38280
|
-
redisKey:
|
|
38399
|
+
redisKey: import_redis22.redisKeys.storeSignal(signal.symbol, signal.signalId),
|
|
38281
38400
|
signal
|
|
38282
38401
|
})),
|
|
38283
38402
|
evaluations: reportEvaluations.map((evaluation) => ({
|
|
38284
38403
|
redisDebug: {
|
|
38285
|
-
key:
|
|
38404
|
+
key: import_redis22.redisKeys.runtimeSignalEvaluationBucket(
|
|
38286
38405
|
userName3,
|
|
38287
38406
|
(0, import_time5.getRuntimeStorageDayKey)(evaluation.timestamp),
|
|
38288
38407
|
evaluation.strategy
|
|
38289
38408
|
),
|
|
38290
38409
|
field: evaluation.evaluationId,
|
|
38291
|
-
directKey:
|
|
38410
|
+
directKey: import_redis22.redisKeys.runtimeSignalEvaluation(
|
|
38292
38411
|
userName3,
|
|
38293
38412
|
evaluation.evaluationId
|
|
38294
38413
|
)
|
|
@@ -38353,17 +38472,17 @@ __export(replayRuntimeEvidence_exports, {
|
|
|
38353
38472
|
replayRuntimeEvidence: () => replayRuntimeEvidence,
|
|
38354
38473
|
summarizeReplayComparison: () => summarizeReplayComparison
|
|
38355
38474
|
});
|
|
38356
|
-
var
|
|
38475
|
+
var import_promises38, import_node_path33, import_args27, import_chalk43, import_redis23, toEpochMs2, resolveWindow, parseStrategyFilter, asRecord5, asArray2, sum, groupCount, compactMatched, resolveItemStrategy, summarizeReplayComparison, loadReplayResult, getReplayStrategies, loadRuntimePayload, replayRuntimeEvidence, main40;
|
|
38357
38476
|
var init_replayRuntimeEvidence = __esm({
|
|
38358
38477
|
"src/scripts/replayRuntimeEvidence.ts"() {
|
|
38359
38478
|
"use strict";
|
|
38360
38479
|
init_jsonFile();
|
|
38361
38480
|
init_memoryProfile();
|
|
38362
|
-
|
|
38363
|
-
|
|
38481
|
+
import_promises38 = __toESM(require("fs/promises"));
|
|
38482
|
+
import_node_path33 = __toESM(require("path"));
|
|
38364
38483
|
import_args27 = __toESM(require("args"));
|
|
38365
38484
|
import_chalk43 = __toESM(require("chalk"));
|
|
38366
|
-
|
|
38485
|
+
import_redis23 = require("@tradejs/infra/redis");
|
|
38367
38486
|
init_runtimeDebugEvidence();
|
|
38368
38487
|
init_support2();
|
|
38369
38488
|
import_args27.default.option(["u", "user"], "Use user config", "root");
|
|
@@ -38586,18 +38705,18 @@ var init_replayRuntimeEvidence = __esm({
|
|
|
38586
38705
|
return {
|
|
38587
38706
|
key: replayKey,
|
|
38588
38707
|
availableKeys: void 0,
|
|
38589
|
-
value: await (0,
|
|
38708
|
+
value: await (0, import_redis23.getData)(replayKey, null)
|
|
38590
38709
|
};
|
|
38591
38710
|
}
|
|
38592
|
-
const prefix =
|
|
38593
|
-
const keys = (await (0,
|
|
38711
|
+
const prefix = import_redis23.redisKeys.backtestResults(userName3, REPLAY_RESULTS_CONFIG, "");
|
|
38712
|
+
const keys = (await (0, import_redis23.getKeys)(prefix)).sort(
|
|
38594
38713
|
(left, right) => left.localeCompare(right)
|
|
38595
38714
|
);
|
|
38596
38715
|
const key2 = keys[keys.length - 1] ?? null;
|
|
38597
38716
|
return {
|
|
38598
38717
|
key: key2,
|
|
38599
38718
|
availableKeys: keys.slice(-10),
|
|
38600
|
-
value: key2 ? await (0,
|
|
38719
|
+
value: key2 ? await (0, import_redis23.getData)(key2, null) : null
|
|
38601
38720
|
};
|
|
38602
38721
|
};
|
|
38603
38722
|
getReplayStrategies = (replayValue) => {
|
|
@@ -38622,10 +38741,10 @@ var init_replayRuntimeEvidence = __esm({
|
|
|
38622
38741
|
runtimeEvidenceFile,
|
|
38623
38742
|
projectRoot: projectRoot18
|
|
38624
38743
|
}) => {
|
|
38625
|
-
const runtimeEvidencePath = typeof runtimeEvidenceFile === "string" && runtimeEvidenceFile.trim() ?
|
|
38744
|
+
const runtimeEvidencePath = typeof runtimeEvidenceFile === "string" && runtimeEvidenceFile.trim() ? import_node_path33.default.resolve(projectRoot18, runtimeEvidenceFile.trim()) : null;
|
|
38626
38745
|
if (runtimeEvidencePath) {
|
|
38627
38746
|
const artifact = JSON.parse(
|
|
38628
|
-
await
|
|
38747
|
+
await import_promises38.default.readFile(runtimeEvidencePath, "utf8")
|
|
38629
38748
|
);
|
|
38630
38749
|
return {
|
|
38631
38750
|
source: "file",
|
|
@@ -38711,8 +38830,8 @@ var init_replayRuntimeEvidence = __esm({
|
|
|
38711
38830
|
},
|
|
38712
38831
|
runtime: runtime.payload
|
|
38713
38832
|
};
|
|
38714
|
-
const outPath =
|
|
38715
|
-
await
|
|
38833
|
+
const outPath = import_node_path33.default.resolve(projectRoot18, String(flags36.out));
|
|
38834
|
+
await import_promises38.default.mkdir(import_node_path33.default.dirname(outPath), { recursive: true });
|
|
38716
38835
|
const memory = createReplayMemoryProfile();
|
|
38717
38836
|
memory?.("evidence:write:start");
|
|
38718
38837
|
await writeReplayJsonFile(outPath, artifact);
|
|
@@ -38756,14 +38875,14 @@ var init_runtimeFeedbackArtifacts = __esm({
|
|
|
38756
38875
|
});
|
|
38757
38876
|
|
|
38758
38877
|
// src/lib/runtimeFeedbackReplay.ts
|
|
38759
|
-
var import_node_child_process9,
|
|
38878
|
+
var import_node_child_process9, import_promises39, import_node_path34, import_mcp3, REQUIRED_ENV, FORBIDDEN_SECRET_ENV, unsafeRedisHosts, safeSegment, assertRuntimeFeedbackReplaySafety, buildRuntimeFeedbackReplayCommands, runLoggedCommand, runRuntimeFeedbackReplay;
|
|
38760
38879
|
var init_runtimeFeedbackReplay = __esm({
|
|
38761
38880
|
"src/lib/runtimeFeedbackReplay.ts"() {
|
|
38762
38881
|
"use strict";
|
|
38763
38882
|
import_node_child_process9 = require("child_process");
|
|
38764
|
-
|
|
38765
|
-
|
|
38766
|
-
|
|
38883
|
+
import_promises39 = __toESM(require("fs/promises"));
|
|
38884
|
+
import_node_path34 = __toESM(require("path"));
|
|
38885
|
+
import_mcp3 = require("@tradejs/node/mcp");
|
|
38767
38886
|
init_runtimeEvidenceDeployment();
|
|
38768
38887
|
init_runtimeEvidenceArtifacts();
|
|
38769
38888
|
init_runtimeEvidenceProducer();
|
|
@@ -38898,7 +39017,7 @@ var init_runtimeFeedbackReplay = __esm({
|
|
|
38898
39017
|
logHandle
|
|
38899
39018
|
}) => {
|
|
38900
39019
|
await logHandle.writeFile(
|
|
38901
|
-
"\n" + (0,
|
|
39020
|
+
"\n" + (0, import_mcp3.formatMcpArtifactLogLine)(`$ ${[executable, ...command].join(" ")}`)
|
|
38902
39021
|
);
|
|
38903
39022
|
const child = (0, import_node_child_process9.spawn)(executable, command, {
|
|
38904
39023
|
cwd,
|
|
@@ -38921,7 +39040,7 @@ var init_runtimeFeedbackReplay = __esm({
|
|
|
38921
39040
|
let pendingLogWrite = Promise.resolve();
|
|
38922
39041
|
const copyLog = async (input, output) => {
|
|
38923
39042
|
const writeLine2 = async (line) => {
|
|
38924
|
-
const formatted = (0,
|
|
39043
|
+
const formatted = (0, import_mcp3.formatMcpArtifactLogLine)(line);
|
|
38925
39044
|
pendingLogWrite = pendingLogWrite.then(
|
|
38926
39045
|
() => logHandle.writeFile(formatted)
|
|
38927
39046
|
);
|
|
@@ -38964,9 +39083,9 @@ var init_runtimeFeedbackReplay = __esm({
|
|
|
38964
39083
|
throw new Error("Cannot resolve the TradeJS CLI executable path");
|
|
38965
39084
|
}
|
|
38966
39085
|
const runtimeEvidenceBundle = await (0, runtimeEvidenceArtifacts_exports.verifyRuntimeEvidenceBundle)(
|
|
38967
|
-
|
|
39086
|
+
import_node_path34.default.dirname(runtimeEvidencePath)
|
|
38968
39087
|
);
|
|
38969
|
-
if (
|
|
39088
|
+
if (import_node_path34.default.resolve(runtimeEvidenceBundle.payloadPath) !== runtimeEvidencePath) {
|
|
38970
39089
|
throw new Error(
|
|
38971
39090
|
`Runtime evidence must be the verified bundle payload: ${runtimeEvidenceBundle.payloadPath}`
|
|
38972
39091
|
);
|
|
@@ -38993,16 +39112,16 @@ var init_runtimeFeedbackReplay = __esm({
|
|
|
38993
39112
|
if (!intervals.size) {
|
|
38994
39113
|
throw new Error("Runtime feedback replay requires an active interval");
|
|
38995
39114
|
}
|
|
38996
|
-
await
|
|
38997
|
-
const existing = await
|
|
39115
|
+
await import_promises39.default.mkdir(outDir, { recursive: true });
|
|
39116
|
+
const existing = await import_promises39.default.readdir(outDir);
|
|
38998
39117
|
if (existing.length) {
|
|
38999
39118
|
throw new Error(
|
|
39000
39119
|
`Runtime feedback output directory must be empty: ${outDir}`
|
|
39001
39120
|
);
|
|
39002
39121
|
}
|
|
39003
|
-
const replayEvidencePath =
|
|
39004
|
-
const logHandle = await
|
|
39005
|
-
|
|
39122
|
+
const replayEvidencePath = import_node_path34.default.join(outDir, runtimeFeedbackArtifacts_exports.RUNTIME_FEEDBACK_REPLAY_FILE);
|
|
39123
|
+
const logHandle = await import_promises39.default.open(
|
|
39124
|
+
import_node_path34.default.join(outDir, runtimeFeedbackArtifacts_exports.RUNTIME_FEEDBACK_LOG_FILE),
|
|
39006
39125
|
"wx"
|
|
39007
39126
|
);
|
|
39008
39127
|
const commands = buildRuntimeFeedbackReplayCommands({
|
|
@@ -39044,11 +39163,11 @@ __export(runtimeFeedbackReplay_exports, {
|
|
|
39044
39163
|
main: () => main41,
|
|
39045
39164
|
runtimeFeedbackReplay: () => runtimeFeedbackReplay
|
|
39046
39165
|
});
|
|
39047
|
-
var
|
|
39166
|
+
var import_node_path35, import_args28, import_chalk44, flags25, projectRoot9, runtimeFeedbackReplay, main41;
|
|
39048
39167
|
var init_runtimeFeedbackReplay2 = __esm({
|
|
39049
39168
|
"src/scripts/runtimeFeedbackReplay.ts"() {
|
|
39050
39169
|
"use strict";
|
|
39051
|
-
|
|
39170
|
+
import_node_path35 = __toESM(require("path"));
|
|
39052
39171
|
import_args28 = __toESM(require("args"));
|
|
39053
39172
|
import_chalk44 = __toESM(require("chalk"));
|
|
39054
39173
|
init_runtimeFeedbackReplay();
|
|
@@ -39066,8 +39185,8 @@ var init_runtimeFeedbackReplay2 = __esm({
|
|
|
39066
39185
|
);
|
|
39067
39186
|
}
|
|
39068
39187
|
const verified = await runRuntimeFeedbackReplay({
|
|
39069
|
-
runtimeEvidencePath:
|
|
39070
|
-
outDir:
|
|
39188
|
+
runtimeEvidencePath: import_node_path35.default.resolve(projectRoot9, runtimeEvidence2),
|
|
39189
|
+
outDir: import_node_path35.default.resolve(projectRoot9, outDir),
|
|
39071
39190
|
runId: String(flags25.runId ?? "").trim() || void 0,
|
|
39072
39191
|
projectRoot: projectRoot9
|
|
39073
39192
|
});
|
|
@@ -39229,11 +39348,11 @@ __export(runtimeFeedbackNotify_exports, {
|
|
|
39229
39348
|
main: () => main42,
|
|
39230
39349
|
runtimeFeedbackNotify: () => runtimeFeedbackNotify
|
|
39231
39350
|
});
|
|
39232
|
-
var
|
|
39351
|
+
var import_node_path36, import_args29, import_chalk45, flags26, projectRoot10, runtimeFeedbackNotify, main42;
|
|
39233
39352
|
var init_runtimeFeedbackNotify = __esm({
|
|
39234
39353
|
"src/scripts/runtimeFeedbackNotify.ts"() {
|
|
39235
39354
|
"use strict";
|
|
39236
|
-
|
|
39355
|
+
import_node_path36 = __toESM(require("path"));
|
|
39237
39356
|
import_args29 = __toESM(require("args"));
|
|
39238
39357
|
import_chalk45 = __toESM(require("chalk"));
|
|
39239
39358
|
init_runtimeFeedbackNotification();
|
|
@@ -39247,7 +39366,7 @@ var init_runtimeFeedbackNotify = __esm({
|
|
|
39247
39366
|
if (!bundle) {
|
|
39248
39367
|
throw new Error("Provide --bundle for runtime feedback notification.");
|
|
39249
39368
|
}
|
|
39250
|
-
const bundleDir =
|
|
39369
|
+
const bundleDir = import_node_path36.default.resolve(projectRoot10, bundle);
|
|
39251
39370
|
if (flags26.dryRun) {
|
|
39252
39371
|
const verified = await (0, runtimeFeedbackArtifacts_exports.verifyRuntimeFeedbackReplayBundle)(bundleDir);
|
|
39253
39372
|
console.log(buildRuntimeFeedbackTelegramMessage(verified.replayEvidence));
|
|
@@ -40060,13 +40179,13 @@ ${reactions}
|
|
|
40060
40179
|
});
|
|
40061
40180
|
|
|
40062
40181
|
// src/lib/runtimeEvidenceSync.ts
|
|
40063
|
-
var import_node_child_process10,
|
|
40182
|
+
var import_node_child_process10, import_promises40, import_node_path37, import_node_util2, execFileAsync2, isExistingDestinationError, safeSegment2, withTrailingSlash, dateParts, buildRuntimeEvidenceRsyncArgs, receiptPath, compareBundles, listPendingRuntimeEvidenceBundles, markRuntimeEvidenceBundleProcessed, syncRuntimeEvidenceBundles;
|
|
40064
40183
|
var init_runtimeEvidenceSync = __esm({
|
|
40065
40184
|
"src/lib/runtimeEvidenceSync.ts"() {
|
|
40066
40185
|
"use strict";
|
|
40067
40186
|
import_node_child_process10 = require("child_process");
|
|
40068
|
-
|
|
40069
|
-
|
|
40187
|
+
import_promises40 = __toESM(require("fs/promises"));
|
|
40188
|
+
import_node_path37 = __toESM(require("path"));
|
|
40070
40189
|
import_node_util2 = require("util");
|
|
40071
40190
|
init_runtimeEvidenceArtifacts();
|
|
40072
40191
|
init_runtimeEvidenceDeployment();
|
|
@@ -40100,15 +40219,15 @@ var init_runtimeEvidenceSync = __esm({
|
|
|
40100
40219
|
withTrailingSlash(source),
|
|
40101
40220
|
withTrailingSlash(destination)
|
|
40102
40221
|
];
|
|
40103
|
-
receiptPath = (receiptsRoot, artifactId) =>
|
|
40222
|
+
receiptPath = (receiptsRoot, artifactId) => import_node_path37.default.join(receiptsRoot, `${safeSegment2(artifactId, "artifact")}.json`);
|
|
40104
40223
|
compareBundles = (left, right) => left.manifest.window.endTime - right.manifest.window.endTime || left.manifest.createdAt - right.manifest.createdAt;
|
|
40105
40224
|
listPendingRuntimeEvidenceBundles = async ({
|
|
40106
40225
|
evidenceRoot,
|
|
40107
40226
|
deploymentId
|
|
40108
40227
|
}) => {
|
|
40109
40228
|
const safeDeploymentId = safeSegment2(deploymentId, "production");
|
|
40110
|
-
const artifactsRoot =
|
|
40111
|
-
const receiptsRoot =
|
|
40229
|
+
const artifactsRoot = import_node_path37.default.join(evidenceRoot, "artifacts", safeDeploymentId);
|
|
40230
|
+
const receiptsRoot = import_node_path37.default.join(evidenceRoot, "receipts", safeDeploymentId);
|
|
40112
40231
|
const bundles = await (0, runtimeEvidenceArtifacts_exports.discoverRuntimeEvidenceBundles)(artifactsRoot);
|
|
40113
40232
|
const pending = [];
|
|
40114
40233
|
for (const bundleDir of bundles) {
|
|
@@ -40116,7 +40235,7 @@ var init_runtimeEvidenceSync = __esm({
|
|
|
40116
40235
|
if (verified.manifest.deploymentId !== safeDeploymentId) continue;
|
|
40117
40236
|
(0, runtimeEvidenceDeployment_exports.assertCurrentRuntimeEvidenceArtifact)(verified.artifact);
|
|
40118
40237
|
try {
|
|
40119
|
-
await
|
|
40238
|
+
await import_promises40.default.access(receiptPath(receiptsRoot, verified.manifest.artifactId));
|
|
40120
40239
|
continue;
|
|
40121
40240
|
} catch (error) {
|
|
40122
40241
|
if (error.code !== "ENOENT") throw error;
|
|
@@ -40139,7 +40258,7 @@ var init_runtimeEvidenceSync = __esm({
|
|
|
40139
40258
|
`Artifact deployment mismatch: expected ${safeDeploymentId}, received ${verified.manifest.deploymentId}`
|
|
40140
40259
|
);
|
|
40141
40260
|
}
|
|
40142
|
-
const receiptsRoot =
|
|
40261
|
+
const receiptsRoot = import_node_path37.default.join(evidenceRoot, "receipts", safeDeploymentId);
|
|
40143
40262
|
const finalPath = receiptPath(receiptsRoot, verified.manifest.artifactId);
|
|
40144
40263
|
const temporaryPath = `${finalPath}.tmp-${process.pid}`;
|
|
40145
40264
|
const receipt = {
|
|
@@ -40153,14 +40272,14 @@ var init_runtimeEvidenceSync = __esm({
|
|
|
40153
40272
|
replayEvidenceSha256: runtimeFeedback.replayEvidenceSha256
|
|
40154
40273
|
} : {}
|
|
40155
40274
|
};
|
|
40156
|
-
await
|
|
40157
|
-
await
|
|
40275
|
+
await import_promises40.default.mkdir(receiptsRoot, { recursive: true });
|
|
40276
|
+
await import_promises40.default.writeFile(
|
|
40158
40277
|
temporaryPath,
|
|
40159
40278
|
`${JSON.stringify(receipt, null, 2)}
|
|
40160
40279
|
`,
|
|
40161
40280
|
"utf8"
|
|
40162
40281
|
);
|
|
40163
|
-
await
|
|
40282
|
+
await import_promises40.default.rename(temporaryPath, finalPath);
|
|
40164
40283
|
return finalPath;
|
|
40165
40284
|
};
|
|
40166
40285
|
syncRuntimeEvidenceBundles = async ({
|
|
@@ -40175,11 +40294,11 @@ var init_runtimeEvidenceSync = __esm({
|
|
|
40175
40294
|
}
|
|
40176
40295
|
}) => {
|
|
40177
40296
|
const safeDeploymentId = safeSegment2(deploymentId, "production");
|
|
40178
|
-
const inboxRoot =
|
|
40179
|
-
const artifactsRoot =
|
|
40297
|
+
const inboxRoot = import_node_path37.default.join(evidenceRoot, "inbox", safeDeploymentId);
|
|
40298
|
+
const artifactsRoot = import_node_path37.default.join(evidenceRoot, "artifacts", safeDeploymentId);
|
|
40180
40299
|
await Promise.all([
|
|
40181
|
-
|
|
40182
|
-
|
|
40300
|
+
import_promises40.default.mkdir(inboxRoot, { recursive: true }),
|
|
40301
|
+
import_promises40.default.mkdir(artifactsRoot, { recursive: true })
|
|
40183
40302
|
]);
|
|
40184
40303
|
const rsyncArgs = buildRuntimeEvidenceRsyncArgs({
|
|
40185
40304
|
source,
|
|
@@ -40196,14 +40315,14 @@ var init_runtimeEvidenceSync = __esm({
|
|
|
40196
40315
|
);
|
|
40197
40316
|
}
|
|
40198
40317
|
(0, runtimeEvidenceDeployment_exports.assertCurrentRuntimeEvidenceArtifact)(verified.artifact);
|
|
40199
|
-
const destinationDir =
|
|
40318
|
+
const destinationDir = import_node_path37.default.join(
|
|
40200
40319
|
artifactsRoot,
|
|
40201
40320
|
...dateParts(verified.manifest.window.endTime),
|
|
40202
40321
|
safeSegment2(verified.manifest.artifactId, "artifact")
|
|
40203
40322
|
);
|
|
40204
|
-
await
|
|
40323
|
+
await import_promises40.default.mkdir(import_node_path37.default.dirname(destinationDir), { recursive: true });
|
|
40205
40324
|
try {
|
|
40206
|
-
await
|
|
40325
|
+
await import_promises40.default.rename(bundleDir, destinationDir);
|
|
40207
40326
|
} catch (error) {
|
|
40208
40327
|
if (!isExistingDestinationError(error)) throw error;
|
|
40209
40328
|
const existing = await (0, runtimeEvidenceArtifacts_exports.verifyRuntimeEvidenceBundle)(destinationDir);
|
|
@@ -40212,7 +40331,7 @@ var init_runtimeEvidenceSync = __esm({
|
|
|
40212
40331
|
`Conflicting runtime evidence artifact ${verified.manifest.artifactId}`
|
|
40213
40332
|
);
|
|
40214
40333
|
}
|
|
40215
|
-
await
|
|
40334
|
+
await import_promises40.default.rm(bundleDir, { recursive: true, force: true });
|
|
40216
40335
|
}
|
|
40217
40336
|
received.push(await (0, runtimeEvidenceArtifacts_exports.verifyRuntimeEvidenceBundle)(destinationDir));
|
|
40218
40337
|
}
|
|
@@ -40232,14 +40351,14 @@ var init_runtimeEvidenceSync = __esm({
|
|
|
40232
40351
|
});
|
|
40233
40352
|
|
|
40234
40353
|
// src/lib/runtimeFeedbackProcess.ts
|
|
40235
|
-
var
|
|
40354
|
+
var import_promises41, import_node_path38, import_node_crypto20, import_diagnostics3, processRuntimeFeedbackPair;
|
|
40236
40355
|
var init_runtimeFeedbackProcess = __esm({
|
|
40237
40356
|
"src/lib/runtimeFeedbackProcess.ts"() {
|
|
40238
40357
|
"use strict";
|
|
40239
|
-
|
|
40240
|
-
|
|
40241
|
-
|
|
40242
|
-
|
|
40358
|
+
import_promises41 = __toESM(require("fs/promises"));
|
|
40359
|
+
import_node_path38 = __toESM(require("path"));
|
|
40360
|
+
import_node_crypto20 = require("crypto");
|
|
40361
|
+
import_diagnostics3 = require("@tradejs/node/diagnostics");
|
|
40243
40362
|
init_executionCalibration();
|
|
40244
40363
|
init_runtimeScorecard();
|
|
40245
40364
|
init_runtimeEvidenceSync();
|
|
@@ -40250,16 +40369,16 @@ var init_runtimeFeedbackProcess = __esm({
|
|
|
40250
40369
|
outputRoot,
|
|
40251
40370
|
historyDir
|
|
40252
40371
|
}) => {
|
|
40253
|
-
const { runtimeEvidence: runtimeEvidence2, feedback } = await (0,
|
|
40372
|
+
const { runtimeEvidence: runtimeEvidence2, feedback } = await (0, import_diagnostics3.verifyRuntimeFeedbackReplaySource)(
|
|
40254
40373
|
{ bundleDir: replayDir, runtimeEvidenceBundleDir: runtimeDir }
|
|
40255
40374
|
);
|
|
40256
40375
|
const { artifactId, deploymentId } = runtimeEvidence2.manifest;
|
|
40257
|
-
const snapshot = (0,
|
|
40376
|
+
const snapshot = (0, import_diagnostics3.parseRuntimeEvidenceDeploymentSnapshot)(
|
|
40258
40377
|
runtimeEvidence2.artifact.deployment
|
|
40259
40378
|
);
|
|
40260
40379
|
if (!snapshot)
|
|
40261
40380
|
throw new Error("Runtime evidence requires a deployment snapshot");
|
|
40262
|
-
const strategies = (0,
|
|
40381
|
+
const strategies = (0, import_diagnostics3.activeRuntimeEvidenceStrategies)(snapshot);
|
|
40263
40382
|
for (const segment of [
|
|
40264
40383
|
artifactId,
|
|
40265
40384
|
deploymentId,
|
|
@@ -40268,17 +40387,17 @@ var init_runtimeFeedbackProcess = __esm({
|
|
|
40268
40387
|
if (!/^[A-Za-z0-9._:-]+$/.test(segment) || segment === "." || segment === "..")
|
|
40269
40388
|
throw new Error("Invalid feedback output path identity");
|
|
40270
40389
|
}
|
|
40271
|
-
const receiptPath2 =
|
|
40390
|
+
const receiptPath2 = import_node_path38.default.join(
|
|
40272
40391
|
evidenceRoot,
|
|
40273
40392
|
"receipts",
|
|
40274
40393
|
deploymentId,
|
|
40275
40394
|
`${artifactId}.json`
|
|
40276
40395
|
);
|
|
40277
|
-
await
|
|
40396
|
+
await import_promises41.default.mkdir(import_node_path38.default.dirname(receiptPath2), { recursive: true });
|
|
40278
40397
|
const lock = receiptPath2 + ".processing";
|
|
40279
|
-
await
|
|
40398
|
+
await import_promises41.default.mkdir(lock);
|
|
40280
40399
|
try {
|
|
40281
|
-
const previous = await
|
|
40400
|
+
const previous = await import_promises41.default.readFile(receiptPath2, "utf8").catch((error) => {
|
|
40282
40401
|
if (error.code !== "ENOENT") throw error;
|
|
40283
40402
|
return null;
|
|
40284
40403
|
});
|
|
@@ -40286,7 +40405,7 @@ var init_runtimeFeedbackProcess = __esm({
|
|
|
40286
40405
|
const receipt = JSON.parse(previous);
|
|
40287
40406
|
if (!receipt || typeof receipt !== "object" || !("schemaVersion" in receipt) || receipt.schemaVersion !== 2 || !("payloadSha256" in receipt) || !("runtimeFeedbackArtifactId" in receipt) || !("replayEvidenceSha256" in receipt) || !("scorecardPath" in receipt) || receipt.payloadSha256 !== runtimeEvidence2.manifest.payload.sha256 || receipt.runtimeFeedbackArtifactId !== feedback.manifest.artifactId || receipt.replayEvidenceSha256 !== feedback.manifest.payloads.replayEvidence.sha256 || typeof receipt.scorecardPath !== "string")
|
|
40288
40407
|
throw new Error("Processing receipt conflicts with the exact pair");
|
|
40289
|
-
await
|
|
40408
|
+
await import_promises41.default.access(receipt.scorecardPath);
|
|
40290
40409
|
return {
|
|
40291
40410
|
processed: false,
|
|
40292
40411
|
receiptPath: receiptPath2,
|
|
@@ -40295,17 +40414,17 @@ var init_runtimeFeedbackProcess = __esm({
|
|
|
40295
40414
|
}
|
|
40296
40415
|
const history = [];
|
|
40297
40416
|
if (historyDir)
|
|
40298
|
-
for (const directory of await (0,
|
|
40299
|
-
history.push((await (0,
|
|
40300
|
-
const runId = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:.]/g, "") + "-" + (0,
|
|
40301
|
-
const runDir =
|
|
40302
|
-
await
|
|
40417
|
+
for (const directory of await (0, import_diagnostics3.discoverRuntimeEvidenceBundles)(historyDir))
|
|
40418
|
+
history.push((await (0, import_diagnostics3.verifyRuntimeEvidenceBundle)(directory)).artifact);
|
|
40419
|
+
const runId = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:.]/g, "") + "-" + (0, import_node_crypto20.randomUUID)();
|
|
40420
|
+
const runDir = import_node_path38.default.join(outputRoot, artifactId, runId);
|
|
40421
|
+
await import_promises41.default.mkdir(runDir, { recursive: true });
|
|
40303
40422
|
const calibration = buildExecutionCalibrationReport({
|
|
40304
40423
|
runtimeArtifact: runtimeEvidence2.artifact,
|
|
40305
40424
|
replayEvidenceArtifact: feedback.replayEvidence
|
|
40306
40425
|
});
|
|
40307
|
-
await
|
|
40308
|
-
|
|
40426
|
+
await import_promises41.default.writeFile(
|
|
40427
|
+
import_node_path38.default.join(runDir, "execution-calibration.json"),
|
|
40309
40428
|
JSON.stringify(calibration, null, 2)
|
|
40310
40429
|
);
|
|
40311
40430
|
const inputs = {
|
|
@@ -40316,21 +40435,21 @@ var init_runtimeFeedbackProcess = __esm({
|
|
|
40316
40435
|
};
|
|
40317
40436
|
for (const strategy of [...strategies.map((s) => s.strategyName), null]) {
|
|
40318
40437
|
const scorecard = buildRuntimeScorecard({ ...inputs, strategy });
|
|
40319
|
-
const base =
|
|
40438
|
+
const base = import_node_path38.default.join(
|
|
40320
40439
|
runDir,
|
|
40321
40440
|
strategy ? `runtime-scorecard-${strategy}` : "runtime-scorecard"
|
|
40322
40441
|
);
|
|
40323
|
-
await
|
|
40324
|
-
await
|
|
40442
|
+
await import_promises41.default.writeFile(base + ".json", JSON.stringify(scorecard, null, 2));
|
|
40443
|
+
await import_promises41.default.writeFile(
|
|
40325
40444
|
base + ".md",
|
|
40326
40445
|
formatRuntimeScorecardMarkdown(scorecard)
|
|
40327
40446
|
);
|
|
40328
40447
|
}
|
|
40329
|
-
await (0,
|
|
40448
|
+
await (0, import_diagnostics3.verifyRuntimeFeedbackReplaySource)({
|
|
40330
40449
|
bundleDir: replayDir,
|
|
40331
40450
|
runtimeEvidenceBundleDir: runtimeDir
|
|
40332
40451
|
});
|
|
40333
|
-
const scorecardPath =
|
|
40452
|
+
const scorecardPath = import_node_path38.default.join(runDir, "runtime-scorecard.json");
|
|
40334
40453
|
await markRuntimeEvidenceBundleProcessed({
|
|
40335
40454
|
evidenceRoot,
|
|
40336
40455
|
deploymentId,
|
|
@@ -40343,7 +40462,7 @@ var init_runtimeFeedbackProcess = __esm({
|
|
|
40343
40462
|
});
|
|
40344
40463
|
return { processed: true, receiptPath: receiptPath2, scorecardPath };
|
|
40345
40464
|
} finally {
|
|
40346
|
-
await
|
|
40465
|
+
await import_promises41.default.rmdir(lock);
|
|
40347
40466
|
}
|
|
40348
40467
|
};
|
|
40349
40468
|
}
|
|
@@ -40354,12 +40473,12 @@ var runtimeFeedbackProcess_exports = {};
|
|
|
40354
40473
|
__export(runtimeFeedbackProcess_exports, {
|
|
40355
40474
|
main: () => main43
|
|
40356
40475
|
});
|
|
40357
|
-
var import_args30,
|
|
40476
|
+
var import_args30, import_node_path39, flags27, main43;
|
|
40358
40477
|
var init_runtimeFeedbackProcess2 = __esm({
|
|
40359
40478
|
"src/scripts/runtimeFeedbackProcess.ts"() {
|
|
40360
40479
|
"use strict";
|
|
40361
40480
|
import_args30 = __toESM(require("args"));
|
|
40362
|
-
|
|
40481
|
+
import_node_path39 = __toESM(require("path"));
|
|
40363
40482
|
init_runtimeFeedbackProcess();
|
|
40364
40483
|
import_args30.default.option(
|
|
40365
40484
|
"runtimeDir",
|
|
@@ -40382,11 +40501,11 @@ var init_runtimeFeedbackProcess2 = __esm({
|
|
|
40382
40501
|
console.log(
|
|
40383
40502
|
JSON.stringify(
|
|
40384
40503
|
await processRuntimeFeedbackPair({
|
|
40385
|
-
runtimeDir:
|
|
40386
|
-
replayDir:
|
|
40387
|
-
evidenceRoot:
|
|
40388
|
-
outputRoot:
|
|
40389
|
-
historyDir:
|
|
40504
|
+
runtimeDir: import_node_path39.default.resolve(root, String(flags27.runtimeDir)),
|
|
40505
|
+
replayDir: import_node_path39.default.resolve(root, String(flags27.replayDir)),
|
|
40506
|
+
evidenceRoot: import_node_path39.default.join(root, "data/runtime-evidence"),
|
|
40507
|
+
outputRoot: import_node_path39.default.join(root, "output/runtime-feedback"),
|
|
40508
|
+
historyDir: import_node_path39.default.resolve(root, String(flags27.historyDir))
|
|
40390
40509
|
})
|
|
40391
40510
|
)
|
|
40392
40511
|
);
|
|
@@ -40395,13 +40514,13 @@ var init_runtimeFeedbackProcess2 = __esm({
|
|
|
40395
40514
|
});
|
|
40396
40515
|
|
|
40397
40516
|
// src/lib/runtimeFeedbackSync.ts
|
|
40398
|
-
var import_node_child_process11,
|
|
40517
|
+
var import_node_child_process11, import_promises42, import_node_path40, import_node_util3, execFileAsync3, isExistingDestinationError2, safeSegment3, dateParts2, syncRuntimeFeedbackReplayBundles;
|
|
40399
40518
|
var init_runtimeFeedbackSync = __esm({
|
|
40400
40519
|
"src/lib/runtimeFeedbackSync.ts"() {
|
|
40401
40520
|
"use strict";
|
|
40402
40521
|
import_node_child_process11 = require("child_process");
|
|
40403
|
-
|
|
40404
|
-
|
|
40522
|
+
import_promises42 = __toESM(require("fs/promises"));
|
|
40523
|
+
import_node_path40 = __toESM(require("path"));
|
|
40405
40524
|
import_node_util3 = require("util");
|
|
40406
40525
|
init_runtimeFeedbackArtifacts();
|
|
40407
40526
|
init_runtimeEvidenceSync();
|
|
@@ -40434,11 +40553,11 @@ var init_runtimeFeedbackSync = __esm({
|
|
|
40434
40553
|
}
|
|
40435
40554
|
}) => {
|
|
40436
40555
|
const safeDeploymentId = safeSegment3(deploymentId, "production");
|
|
40437
|
-
const inboxRoot =
|
|
40438
|
-
const artifactsRoot =
|
|
40556
|
+
const inboxRoot = import_node_path40.default.join(feedbackRoot, "inbox", safeDeploymentId);
|
|
40557
|
+
const artifactsRoot = import_node_path40.default.join(feedbackRoot, "artifacts", safeDeploymentId);
|
|
40439
40558
|
await Promise.all([
|
|
40440
|
-
|
|
40441
|
-
|
|
40559
|
+
import_promises42.default.mkdir(inboxRoot, { recursive: true }),
|
|
40560
|
+
import_promises42.default.mkdir(artifactsRoot, { recursive: true })
|
|
40442
40561
|
]);
|
|
40443
40562
|
const rsyncArgs = buildRuntimeEvidenceRsyncArgs({
|
|
40444
40563
|
source,
|
|
@@ -40454,15 +40573,15 @@ var init_runtimeFeedbackSync = __esm({
|
|
|
40454
40573
|
`Runtime feedback deployment mismatch: expected ${safeDeploymentId}, received ${verified.manifest.deploymentId}`
|
|
40455
40574
|
);
|
|
40456
40575
|
}
|
|
40457
|
-
const destinationDir =
|
|
40576
|
+
const destinationDir = import_node_path40.default.join(
|
|
40458
40577
|
artifactsRoot,
|
|
40459
40578
|
...dateParts2(verified.manifest.window.endTime),
|
|
40460
40579
|
safeSegment3(verified.manifest.runtimeEvidence.artifactId, "artifact"),
|
|
40461
40580
|
safeSegment3(verified.manifest.runId, "run")
|
|
40462
40581
|
);
|
|
40463
|
-
await
|
|
40582
|
+
await import_promises42.default.mkdir(import_node_path40.default.dirname(destinationDir), { recursive: true });
|
|
40464
40583
|
try {
|
|
40465
|
-
await
|
|
40584
|
+
await import_promises42.default.rename(bundleDir, destinationDir);
|
|
40466
40585
|
} catch (error) {
|
|
40467
40586
|
if (!isExistingDestinationError2(error)) throw error;
|
|
40468
40587
|
const existing = await (0, runtimeFeedbackArtifacts_exports.verifyRuntimeFeedbackReplayBundle)(destinationDir);
|
|
@@ -40471,7 +40590,7 @@ var init_runtimeFeedbackSync = __esm({
|
|
|
40471
40590
|
`Conflicting runtime feedback replay ${verified.manifest.artifactId}`
|
|
40472
40591
|
);
|
|
40473
40592
|
}
|
|
40474
|
-
await
|
|
40593
|
+
await import_promises42.default.rm(bundleDir, { recursive: true, force: true });
|
|
40475
40594
|
}
|
|
40476
40595
|
received.push(await (0, runtimeFeedbackArtifacts_exports.verifyRuntimeFeedbackReplayBundle)(destinationDir));
|
|
40477
40596
|
}
|
|
@@ -40491,11 +40610,11 @@ __export(runtimeFeedbackSync_exports, {
|
|
|
40491
40610
|
main: () => main44,
|
|
40492
40611
|
runtimeFeedbackSync: () => runtimeFeedbackSync
|
|
40493
40612
|
});
|
|
40494
|
-
var
|
|
40613
|
+
var import_node_path41, import_args31, import_chalk46, flags28, projectRoot11, runtimeFeedbackSync, main44;
|
|
40495
40614
|
var init_runtimeFeedbackSync2 = __esm({
|
|
40496
40615
|
"src/scripts/runtimeFeedbackSync.ts"() {
|
|
40497
40616
|
"use strict";
|
|
40498
|
-
|
|
40617
|
+
import_node_path41 = __toESM(require("path"));
|
|
40499
40618
|
import_args31 = __toESM(require("args"));
|
|
40500
40619
|
import_chalk46 = __toESM(require("chalk"));
|
|
40501
40620
|
init_runtimeFeedbackSync();
|
|
@@ -40523,7 +40642,7 @@ var init_runtimeFeedbackSync2 = __esm({
|
|
|
40523
40642
|
"Provide --source or RUNTIME_FEEDBACK_RSYNC_SOURCE for runtime feedback sync."
|
|
40524
40643
|
);
|
|
40525
40644
|
}
|
|
40526
|
-
const feedbackRoot =
|
|
40645
|
+
const feedbackRoot = import_node_path41.default.resolve(projectRoot11, String(flags28.dir));
|
|
40527
40646
|
const result = await syncRuntimeFeedbackReplayBundles({
|
|
40528
40647
|
source,
|
|
40529
40648
|
feedbackRoot,
|
|
@@ -40555,13 +40674,13 @@ var init_runtimeFeedbackSync2 = __esm({
|
|
|
40555
40674
|
});
|
|
40556
40675
|
|
|
40557
40676
|
// src/lib/runtimeEvidenceCompositionSnapshots.ts
|
|
40558
|
-
var
|
|
40677
|
+
var import_node_crypto21, import_promises43, import_node_path42, SNAPSHOT_FILE, MANIFEST_FILE, COMPLETE_FILE, createRuntimeEvidenceCompositionSnapshotRecorder, isRecord2, sha256, safeSegment4, isExistingDestinationError3, parseManifest, verifyRuntimeEvidenceCompositionSnapshot, sameSnapshot, publishRuntimeEvidenceCompositionSnapshot, captureRuntimeEvidenceCompositionSnapshot, discoverRuntimeEvidenceCompositionSnapshots;
|
|
40559
40678
|
var init_runtimeEvidenceCompositionSnapshots = __esm({
|
|
40560
40679
|
"src/lib/runtimeEvidenceCompositionSnapshots.ts"() {
|
|
40561
40680
|
"use strict";
|
|
40562
|
-
|
|
40563
|
-
|
|
40564
|
-
|
|
40681
|
+
import_node_crypto21 = require("crypto");
|
|
40682
|
+
import_promises43 = __toESM(require("fs/promises"));
|
|
40683
|
+
import_node_path42 = __toESM(require("path"));
|
|
40565
40684
|
init_runtimeEvidenceDeployment();
|
|
40566
40685
|
init_runtimeEvidenceProducer();
|
|
40567
40686
|
SNAPSHOT_FILE = "snapshot.json";
|
|
@@ -40582,7 +40701,7 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
|
|
|
40582
40701
|
};
|
|
40583
40702
|
};
|
|
40584
40703
|
isRecord2 = (value) => value != null && typeof value === "object" && !Array.isArray(value);
|
|
40585
|
-
sha256 = (value) => (0,
|
|
40704
|
+
sha256 = (value) => (0, import_node_crypto21.createHash)("sha256").update(value).digest("hex");
|
|
40586
40705
|
safeSegment4 = (value, label) => {
|
|
40587
40706
|
const normalized = value.trim();
|
|
40588
40707
|
if (!normalized || !/^[a-zA-Z0-9._:-]+$/.test(normalized)) {
|
|
@@ -40604,9 +40723,9 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
|
|
|
40604
40723
|
};
|
|
40605
40724
|
verifyRuntimeEvidenceCompositionSnapshot = async (bundleDir) => {
|
|
40606
40725
|
const [manifestText, payload, completeText] = await Promise.all([
|
|
40607
|
-
|
|
40608
|
-
|
|
40609
|
-
|
|
40726
|
+
import_promises43.default.readFile(import_node_path42.default.join(bundleDir, MANIFEST_FILE), "utf8"),
|
|
40727
|
+
import_promises43.default.readFile(import_node_path42.default.join(bundleDir, SNAPSHOT_FILE)),
|
|
40728
|
+
import_promises43.default.readFile(import_node_path42.default.join(bundleDir, COMPLETE_FILE), "utf8")
|
|
40610
40729
|
]);
|
|
40611
40730
|
const manifest = parseManifest(JSON.parse(manifestText));
|
|
40612
40731
|
if (completeText.trim() !== manifest.deploymentCompositionId) {
|
|
@@ -40669,39 +40788,39 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
|
|
|
40669
40788
|
bytes: Buffer.byteLength(payload)
|
|
40670
40789
|
}
|
|
40671
40790
|
};
|
|
40672
|
-
const snapshotsRoot =
|
|
40673
|
-
const bundleDir =
|
|
40674
|
-
const temporaryDir =
|
|
40791
|
+
const snapshotsRoot = import_node_path42.default.join(evidenceRoot, "snapshots", deploymentId);
|
|
40792
|
+
const bundleDir = import_node_path42.default.join(snapshotsRoot, compositionId);
|
|
40793
|
+
const temporaryDir = import_node_path42.default.join(
|
|
40675
40794
|
evidenceRoot,
|
|
40676
40795
|
"incoming",
|
|
40677
|
-
`snapshot-${compositionId}.tmp-${(0,
|
|
40796
|
+
`snapshot-${compositionId}.tmp-${(0, import_node_crypto21.randomUUID)()}`
|
|
40678
40797
|
);
|
|
40679
|
-
await
|
|
40798
|
+
await import_promises43.default.mkdir(temporaryDir, { recursive: true });
|
|
40680
40799
|
try {
|
|
40681
40800
|
await Promise.all([
|
|
40682
|
-
|
|
40683
|
-
|
|
40684
|
-
|
|
40801
|
+
import_promises43.default.writeFile(import_node_path42.default.join(temporaryDir, SNAPSHOT_FILE), payload, "utf8"),
|
|
40802
|
+
import_promises43.default.writeFile(
|
|
40803
|
+
import_node_path42.default.join(temporaryDir, MANIFEST_FILE),
|
|
40685
40804
|
`${JSON.stringify(manifest, null, 2)}
|
|
40686
40805
|
`,
|
|
40687
40806
|
"utf8"
|
|
40688
40807
|
)
|
|
40689
40808
|
]);
|
|
40690
|
-
await
|
|
40691
|
-
|
|
40809
|
+
await import_promises43.default.writeFile(
|
|
40810
|
+
import_node_path42.default.join(temporaryDir, COMPLETE_FILE),
|
|
40692
40811
|
`${compositionId}
|
|
40693
40812
|
`,
|
|
40694
40813
|
"utf8"
|
|
40695
40814
|
);
|
|
40696
|
-
await
|
|
40815
|
+
await import_promises43.default.mkdir(snapshotsRoot, { recursive: true });
|
|
40697
40816
|
try {
|
|
40698
|
-
await
|
|
40817
|
+
await import_promises43.default.rename(temporaryDir, bundleDir);
|
|
40699
40818
|
} catch (error) {
|
|
40700
40819
|
if (!isExistingDestinationError3(error)) throw error;
|
|
40701
|
-
await
|
|
40820
|
+
await import_promises43.default.rm(temporaryDir, { recursive: true, force: true });
|
|
40702
40821
|
}
|
|
40703
40822
|
} catch (error) {
|
|
40704
|
-
await
|
|
40823
|
+
await import_promises43.default.rm(temporaryDir, { recursive: true, force: true });
|
|
40705
40824
|
throw error;
|
|
40706
40825
|
}
|
|
40707
40826
|
const verified = await verifyRuntimeEvidenceCompositionSnapshot(bundleDir);
|
|
@@ -40735,31 +40854,31 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
|
|
|
40735
40854
|
);
|
|
40736
40855
|
}
|
|
40737
40856
|
await publishRuntimeEvidenceCompositionSnapshot({
|
|
40738
|
-
evidenceRoot:
|
|
40857
|
+
evidenceRoot: import_node_path42.default.join(projectRoot18, "data", "runtime-evidence"),
|
|
40739
40858
|
userName: userName3,
|
|
40740
40859
|
deployment,
|
|
40741
40860
|
producer
|
|
40742
40861
|
});
|
|
40743
40862
|
};
|
|
40744
40863
|
discoverRuntimeEvidenceCompositionSnapshots = async (evidenceRoot) => {
|
|
40745
|
-
const rootDir =
|
|
40864
|
+
const rootDir = import_node_path42.default.join(evidenceRoot, "snapshots");
|
|
40746
40865
|
const bundleDirs = [];
|
|
40747
40866
|
let deployments;
|
|
40748
40867
|
try {
|
|
40749
|
-
deployments = await
|
|
40868
|
+
deployments = await import_promises43.default.readdir(rootDir, { withFileTypes: true });
|
|
40750
40869
|
} catch (error) {
|
|
40751
40870
|
if (error.code === "ENOENT") return [];
|
|
40752
40871
|
throw error;
|
|
40753
40872
|
}
|
|
40754
40873
|
for (const deployment of deployments.filter((entry) => entry.isDirectory())) {
|
|
40755
|
-
const deploymentDir =
|
|
40756
|
-
const compositions = await
|
|
40874
|
+
const deploymentDir = import_node_path42.default.join(rootDir, deployment.name);
|
|
40875
|
+
const compositions = await import_promises43.default.readdir(deploymentDir, {
|
|
40757
40876
|
withFileTypes: true
|
|
40758
40877
|
});
|
|
40759
40878
|
bundleDirs.push(
|
|
40760
40879
|
...compositions.filter(
|
|
40761
40880
|
(entry) => entry.isDirectory() && !entry.name.startsWith(".") && !entry.name.includes(".tmp-")
|
|
40762
|
-
).map((entry) =>
|
|
40881
|
+
).map((entry) => import_node_path42.default.join(deploymentDir, entry.name))
|
|
40763
40882
|
);
|
|
40764
40883
|
}
|
|
40765
40884
|
return Promise.all(
|
|
@@ -40960,12 +41079,12 @@ __export(runtimeEvidence_exports, {
|
|
|
40960
41079
|
main: () => main45,
|
|
40961
41080
|
runtimeEvidence: () => runtimeEvidence
|
|
40962
41081
|
});
|
|
40963
|
-
var
|
|
41082
|
+
var import_promises44, import_node_path43, import_args32, import_chalk47, flags29, projectRoot12, toEpochMs3, resolveWindow2, parseStrategyFilter2, runtimeEvidence, main45;
|
|
40964
41083
|
var init_runtimeEvidence = __esm({
|
|
40965
41084
|
"src/scripts/runtimeEvidence.ts"() {
|
|
40966
41085
|
"use strict";
|
|
40967
|
-
|
|
40968
|
-
|
|
41086
|
+
import_promises44 = __toESM(require("fs/promises"));
|
|
41087
|
+
import_node_path43 = __toESM(require("path"));
|
|
40969
41088
|
import_args32 = __toESM(require("args"));
|
|
40970
41089
|
import_chalk47 = __toESM(require("chalk"));
|
|
40971
41090
|
init_runtimeDebugEvidence();
|
|
@@ -41072,7 +41191,7 @@ var init_runtimeEvidence = __esm({
|
|
|
41072
41191
|
deploymentId
|
|
41073
41192
|
});
|
|
41074
41193
|
const snapshots = publishDir && producer ? await loadRuntimeEvidenceCompositionSnapshots({
|
|
41075
|
-
publishRoot:
|
|
41194
|
+
publishRoot: import_node_path43.default.resolve(projectRoot12, publishDir),
|
|
41076
41195
|
currentDeployment: deploymentSnapshot,
|
|
41077
41196
|
currentProducer: producer
|
|
41078
41197
|
}) : /* @__PURE__ */ new Map([
|
|
@@ -41146,14 +41265,14 @@ var init_runtimeEvidence = __esm({
|
|
|
41146
41265
|
throw new Error("Runtime evidence window has no versioned runtime rows");
|
|
41147
41266
|
}
|
|
41148
41267
|
const artifact = current.artifact;
|
|
41149
|
-
const outPath =
|
|
41150
|
-
await
|
|
41151
|
-
await
|
|
41268
|
+
const outPath = import_node_path43.default.resolve(projectRoot12, String(flags29.out));
|
|
41269
|
+
await import_promises44.default.mkdir(import_node_path43.default.dirname(outPath), { recursive: true });
|
|
41270
|
+
await import_promises44.default.writeFile(outPath, `${JSON.stringify(artifact, null, 2)}
|
|
41152
41271
|
`, "utf8");
|
|
41153
41272
|
const published = publishDir ? await Promise.all(
|
|
41154
41273
|
artifacts.map(
|
|
41155
41274
|
({ artifact: artifact2, composition }) => (0, runtimeEvidenceArtifacts_exports.publishRuntimeEvidenceBundle)({
|
|
41156
|
-
publishRoot:
|
|
41275
|
+
publishRoot: import_node_path43.default.resolve(projectRoot12, publishDir),
|
|
41157
41276
|
deploymentId,
|
|
41158
41277
|
userName: String(flags29.user),
|
|
41159
41278
|
startTime,
|
|
@@ -41199,11 +41318,11 @@ __export(runtimeEvidenceSync_exports, {
|
|
|
41199
41318
|
main: () => main46,
|
|
41200
41319
|
runtimeEvidenceSync: () => runtimeEvidenceSync
|
|
41201
41320
|
});
|
|
41202
|
-
var
|
|
41321
|
+
var import_node_path44, import_args33, import_chalk48, flags30, projectRoot13, runtimeEvidenceSync, main46;
|
|
41203
41322
|
var init_runtimeEvidenceSync2 = __esm({
|
|
41204
41323
|
"src/scripts/runtimeEvidenceSync.ts"() {
|
|
41205
41324
|
"use strict";
|
|
41206
|
-
|
|
41325
|
+
import_node_path44 = __toESM(require("path"));
|
|
41207
41326
|
import_args33 = __toESM(require("args"));
|
|
41208
41327
|
import_chalk48 = __toESM(require("chalk"));
|
|
41209
41328
|
init_runtimeEvidenceSync();
|
|
@@ -41231,7 +41350,7 @@ var init_runtimeEvidenceSync2 = __esm({
|
|
|
41231
41350
|
"Provide --source or RUNTIME_EVIDENCE_RSYNC_SOURCE for runtime evidence sync."
|
|
41232
41351
|
);
|
|
41233
41352
|
}
|
|
41234
|
-
const evidenceRoot =
|
|
41353
|
+
const evidenceRoot = import_node_path44.default.resolve(projectRoot13, String(flags30.dir));
|
|
41235
41354
|
const result = await syncRuntimeEvidenceBundles({
|
|
41236
41355
|
source,
|
|
41237
41356
|
evidenceRoot,
|
|
@@ -41488,7 +41607,7 @@ async function collectReleaseEvidenceReferences(references) {
|
|
|
41488
41607
|
let artifact;
|
|
41489
41608
|
try {
|
|
41490
41609
|
const parsed = JSON.parse(
|
|
41491
|
-
await
|
|
41610
|
+
await import_promises45.default.readFile(reference.path, "utf8")
|
|
41492
41611
|
);
|
|
41493
41612
|
assert3(
|
|
41494
41613
|
parsed != null && typeof parsed === "object" && !Array.isArray(parsed),
|
|
@@ -41641,13 +41760,13 @@ async function collectReleaseEvidenceReferences(references) {
|
|
|
41641
41760
|
})
|
|
41642
41761
|
);
|
|
41643
41762
|
}
|
|
41644
|
-
var
|
|
41763
|
+
var import_node_crypto22, import_promises45, import_node_path45, import_types9, import_strategyReleaseEvidence3, SHA256_RE3, LINEAGE_FINGERPRINT_RE, STRATEGY_REVISION_RE, DEPLOYMENT_COMPOSITION_ID_RE, REQUIRED_LONG_WINDOWS, REQUIRED_DIAGNOSTIC_TERMINAL_WINDOWS, MIN_RECENT_DIRECTION_REPAIR_EVENTS, safeSegment5, compactTimestamp, verifyFullPeriodChartArtifact, readVerifiedJsonArtifact, verifyResearchDecisionLineage, hasExactRuntimeTarget, deriveStrategyReleaseResearchDecision, canonicalStrategyReleaseJson, strategyReleaseSha256, assertFingerprint, assertLineageFingerprint, releaseReasons, deriveReleaseGates, verifyEvidenceComposition, createStrategyReleaseManifest, createStrategyReleaseEnvelope, verifyStrategyReleaseEnvelope, verifyStrategyEvidenceMarkerEnvelope, releaseMarkers, writeJsonAtomic2, publishStrategyRelease, publishStrategyLiveDiagnosis, finiteString3, finiteNumber7, finiteDirectionPolicy, uniqueStrings, incompleteEvidenceLineage, extractEvidenceLineage, verifyCompletedCoreResearchBundle;
|
|
41645
41764
|
var init_strategyRelease = __esm({
|
|
41646
41765
|
"src/lib/strategyRelease.ts"() {
|
|
41647
41766
|
"use strict";
|
|
41648
|
-
|
|
41649
|
-
|
|
41650
|
-
|
|
41767
|
+
import_node_crypto22 = require("crypto");
|
|
41768
|
+
import_promises45 = __toESM(require("fs/promises"));
|
|
41769
|
+
import_node_path45 = __toESM(require("path"));
|
|
41651
41770
|
import_types9 = require("@tradejs/types");
|
|
41652
41771
|
import_strategyReleaseEvidence3 = require("@tradejs/infra/strategyReleaseEvidence");
|
|
41653
41772
|
init_liveDiagnosis();
|
|
@@ -41666,11 +41785,11 @@ var init_strategyRelease = __esm({
|
|
|
41666
41785
|
const artifact = input.chartArtifact;
|
|
41667
41786
|
if (!artifact?.path || !SHA256_RE3.test(artifact.sha256)) return false;
|
|
41668
41787
|
try {
|
|
41669
|
-
const artifactPath =
|
|
41788
|
+
const artifactPath = import_node_path45.default.resolve(artifact.path);
|
|
41670
41789
|
if (await (0, import_strategyReleaseEvidence3.strategyEvidenceFileSha256)(artifactPath) !== artifact.sha256) {
|
|
41671
41790
|
return false;
|
|
41672
41791
|
}
|
|
41673
|
-
const report = JSON.parse(await
|
|
41792
|
+
const report = JSON.parse(await import_promises45.default.readFile(artifactPath, "utf8"));
|
|
41674
41793
|
return Boolean(
|
|
41675
41794
|
report.chart?.persisted === true && report.chart.cardIds?.length && report.errors?.failed === 0 && report.run?.strategy === input.strategy && report.run.mode === "local-deterministic" && report.run.recent === 0 && report.run.since == null && report.run.until == null && Number(report.run.sourceRows) > 0
|
|
41676
41795
|
);
|
|
@@ -41681,11 +41800,11 @@ var init_strategyRelease = __esm({
|
|
|
41681
41800
|
readVerifiedJsonArtifact = async (artifact) => {
|
|
41682
41801
|
if (!artifact?.path || !SHA256_RE3.test(artifact.sha256)) return null;
|
|
41683
41802
|
try {
|
|
41684
|
-
const artifactPath =
|
|
41803
|
+
const artifactPath = import_node_path45.default.resolve(artifact.path);
|
|
41685
41804
|
if (await (0, import_strategyReleaseEvidence3.strategyEvidenceFileSha256)(artifactPath) !== artifact.sha256) {
|
|
41686
41805
|
return null;
|
|
41687
41806
|
}
|
|
41688
|
-
return JSON.parse(await
|
|
41807
|
+
return JSON.parse(await import_promises45.default.readFile(artifactPath, "utf8"));
|
|
41689
41808
|
} catch {
|
|
41690
41809
|
return null;
|
|
41691
41810
|
}
|
|
@@ -42231,7 +42350,7 @@ var init_strategyRelease = __esm({
|
|
|
42231
42350
|
manifest
|
|
42232
42351
|
});
|
|
42233
42352
|
verifyStrategyReleaseEnvelope = async (valueOrPath) => {
|
|
42234
|
-
const value = typeof valueOrPath === "string" ? JSON.parse(await
|
|
42353
|
+
const value = typeof valueOrPath === "string" ? JSON.parse(await import_promises45.default.readFile(valueOrPath, "utf8")) : valueOrPath;
|
|
42235
42354
|
const envelope = value;
|
|
42236
42355
|
assert3(
|
|
42237
42356
|
envelope?.schema === "tradejs-strategy-release-envelope/v1",
|
|
@@ -42282,7 +42401,7 @@ var init_strategyRelease = __esm({
|
|
|
42282
42401
|
return envelope;
|
|
42283
42402
|
};
|
|
42284
42403
|
verifyStrategyEvidenceMarkerEnvelope = async (valueOrPath) => {
|
|
42285
|
-
const value = typeof valueOrPath === "string" ? JSON.parse(await
|
|
42404
|
+
const value = typeof valueOrPath === "string" ? JSON.parse(await import_promises45.default.readFile(valueOrPath, "utf8")) : valueOrPath;
|
|
42286
42405
|
return (0, import_strategyReleaseEvidence3.verifyStrategyEvidenceMarkerEnvelope)(value);
|
|
42287
42406
|
};
|
|
42288
42407
|
releaseMarkers = (manifest) => {
|
|
@@ -42344,14 +42463,14 @@ var init_strategyRelease = __esm({
|
|
|
42344
42463
|
};
|
|
42345
42464
|
writeJsonAtomic2 = async (filePath, value) => {
|
|
42346
42465
|
const temporaryPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
42347
|
-
await
|
|
42348
|
-
await
|
|
42466
|
+
await import_promises45.default.mkdir(import_node_path45.default.dirname(filePath), { recursive: true });
|
|
42467
|
+
await import_promises45.default.writeFile(
|
|
42349
42468
|
temporaryPath,
|
|
42350
42469
|
`${canonicalStrategyReleaseJson(value)}
|
|
42351
42470
|
`,
|
|
42352
42471
|
"utf8"
|
|
42353
42472
|
);
|
|
42354
|
-
await
|
|
42473
|
+
await import_promises45.default.rename(temporaryPath, filePath);
|
|
42355
42474
|
};
|
|
42356
42475
|
publishStrategyRelease = async ({
|
|
42357
42476
|
rootDir,
|
|
@@ -42368,13 +42487,13 @@ var init_strategyRelease = __esm({
|
|
|
42368
42487
|
path: entry.path
|
|
42369
42488
|
}))
|
|
42370
42489
|
});
|
|
42371
|
-
const releasePath =
|
|
42490
|
+
const releasePath = import_node_path45.default.join(
|
|
42372
42491
|
rootDir,
|
|
42373
42492
|
"releases",
|
|
42374
42493
|
safeSegment5(manifest.strategy, "strategy"),
|
|
42375
42494
|
`${manifest.releaseId}.json`
|
|
42376
42495
|
);
|
|
42377
|
-
const markerPath =
|
|
42496
|
+
const markerPath = import_node_path45.default.join(
|
|
42378
42497
|
rootDir,
|
|
42379
42498
|
"markers",
|
|
42380
42499
|
safeSegment5(manifest.strategy, "strategy"),
|
|
@@ -42454,13 +42573,13 @@ var init_strategyRelease = __esm({
|
|
|
42454
42573
|
markers,
|
|
42455
42574
|
sourceArtifacts
|
|
42456
42575
|
});
|
|
42457
|
-
const diagnosisPath =
|
|
42576
|
+
const diagnosisPath = import_node_path45.default.join(
|
|
42458
42577
|
rootDir,
|
|
42459
42578
|
"diagnoses",
|
|
42460
42579
|
safeSegment5(diagnosis.strategy, "strategy"),
|
|
42461
42580
|
`${diagnosisId}.json`
|
|
42462
42581
|
);
|
|
42463
|
-
const markerPath =
|
|
42582
|
+
const markerPath = import_node_path45.default.join(
|
|
42464
42583
|
rootDir,
|
|
42465
42584
|
"markers",
|
|
42466
42585
|
safeSegment5(diagnosis.strategy, "strategy"),
|
|
@@ -42650,11 +42769,11 @@ var init_strategyRelease = __esm({
|
|
|
42650
42769
|
const specSha256 = finiteString3(artifact.specSha256);
|
|
42651
42770
|
assert3(researchId != null, "core result researchId is required");
|
|
42652
42771
|
assert3(specSha256 != null, "core result specSha256 is required");
|
|
42653
|
-
const researchDir =
|
|
42654
|
-
const manifestPath =
|
|
42655
|
-
const specPath =
|
|
42656
|
-
const manifestBytes = await
|
|
42657
|
-
const specBytes = await
|
|
42772
|
+
const researchDir = import_node_path45.default.dirname(resultPath);
|
|
42773
|
+
const manifestPath = import_node_path45.default.join(researchDir, "manifest.json");
|
|
42774
|
+
const specPath = import_node_path45.default.join(researchDir, "spec.json");
|
|
42775
|
+
const manifestBytes = await import_promises45.default.readFile(manifestPath).catch(() => null);
|
|
42776
|
+
const specBytes = await import_promises45.default.readFile(specPath).catch(() => null);
|
|
42658
42777
|
assert3(
|
|
42659
42778
|
manifestBytes != null && specBytes != null,
|
|
42660
42779
|
"core result must belong to a completed core research bundle"
|
|
@@ -42663,14 +42782,14 @@ var init_strategyRelease = __esm({
|
|
|
42663
42782
|
const artifactHashes = manifest.artifactHashes != null && typeof manifest.artifactHashes === "object" && !Array.isArray(manifest.artifactHashes) ? manifest.artifactHashes : null;
|
|
42664
42783
|
const parsedSpec = JSON.parse(specBytes.toString("utf8"));
|
|
42665
42784
|
assert3(
|
|
42666
|
-
manifest.schema === "tradejs-core-research-manifest/v1" && manifest.status === "completed" && manifest.researchId === researchId && manifest.specSha256 === specSha256 && artifactHashes?.["result.json"] === resultSha256 && (0,
|
|
42785
|
+
manifest.schema === "tradejs-core-research-manifest/v1" && manifest.status === "completed" && manifest.researchId === researchId && manifest.specSha256 === specSha256 && artifactHashes?.["result.json"] === resultSha256 && (0, import_node_crypto22.createHash)("sha256").update(canonicalStrategyReleaseJson(parsedSpec)).digest("hex") === specSha256,
|
|
42667
42786
|
"core result is not bound by its completed core research manifest"
|
|
42668
42787
|
);
|
|
42669
42788
|
for (const [relativePath, expectedSha256] of Object.entries(
|
|
42670
42789
|
artifactHashes ?? {}
|
|
42671
42790
|
)) {
|
|
42672
42791
|
assert3(
|
|
42673
|
-
!
|
|
42792
|
+
!import_node_path45.default.isAbsolute(relativePath) && !relativePath.split(/[\\/]/).includes(".."),
|
|
42674
42793
|
`core bundle artifact ${relativePath} escapes its research directory`
|
|
42675
42794
|
);
|
|
42676
42795
|
assert3(
|
|
@@ -42678,7 +42797,7 @@ var init_strategyRelease = __esm({
|
|
|
42678
42797
|
`core bundle artifact ${relativePath} has an invalid checksum`
|
|
42679
42798
|
);
|
|
42680
42799
|
const actualSha256 = await (0, import_strategyReleaseEvidence3.strategyEvidenceFileSha256)(
|
|
42681
|
-
|
|
42800
|
+
import_node_path45.default.join(researchDir, relativePath)
|
|
42682
42801
|
);
|
|
42683
42802
|
assert3(
|
|
42684
42803
|
actualSha256 === expectedSha256,
|
|
@@ -42695,13 +42814,13 @@ __export(runtimeScorecard_exports, {
|
|
|
42695
42814
|
main: () => main47,
|
|
42696
42815
|
runtimeScorecard: () => runtimeScorecard
|
|
42697
42816
|
});
|
|
42698
|
-
var
|
|
42817
|
+
var import_promises46, import_node_crypto23, import_node_path46, import_args34, import_chalk49, flags31, projectRoot14, resolveOptionalPath, readJson2, assertReportType, sha256File2, loadHistoryArtifacts, runtimeScorecard, main47;
|
|
42699
42818
|
var init_runtimeScorecard2 = __esm({
|
|
42700
42819
|
"src/scripts/runtimeScorecard.ts"() {
|
|
42701
42820
|
"use strict";
|
|
42702
|
-
|
|
42703
|
-
|
|
42704
|
-
|
|
42821
|
+
import_promises46 = __toESM(require("fs/promises"));
|
|
42822
|
+
import_node_crypto23 = require("crypto");
|
|
42823
|
+
import_node_path46 = __toESM(require("path"));
|
|
42705
42824
|
import_args34 = __toESM(require("args"));
|
|
42706
42825
|
import_chalk49 = __toESM(require("chalk"));
|
|
42707
42826
|
init_runtimeEvidenceArtifacts();
|
|
@@ -42771,15 +42890,15 @@ var init_runtimeScorecard2 = __esm({
|
|
|
42771
42890
|
projectRoot14 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
|
|
42772
42891
|
resolveOptionalPath = (value) => {
|
|
42773
42892
|
const raw = String(value ?? "").trim();
|
|
42774
|
-
return raw ?
|
|
42893
|
+
return raw ? import_node_path46.default.resolve(projectRoot14, raw) : null;
|
|
42775
42894
|
};
|
|
42776
|
-
readJson2 = async (filePath) => filePath ? JSON.parse(await
|
|
42895
|
+
readJson2 = async (filePath) => filePath ? JSON.parse(await import_promises46.default.readFile(filePath, "utf8")) : void 0;
|
|
42777
42896
|
assertReportType = (artifact, expected, label) => {
|
|
42778
42897
|
if (artifact != null && (!artifact || typeof artifact !== "object" || Array.isArray(artifact) || artifact.reportType !== expected)) {
|
|
42779
42898
|
throw new Error(`${label} must be a ${expected} artifact`);
|
|
42780
42899
|
}
|
|
42781
42900
|
};
|
|
42782
|
-
sha256File2 = async (filePath) => (0,
|
|
42901
|
+
sha256File2 = async (filePath) => (0, import_node_crypto23.createHash)("sha256").update(await import_promises46.default.readFile(filePath)).digest("hex");
|
|
42783
42902
|
loadHistoryArtifacts = async (historyDir) => {
|
|
42784
42903
|
if (!historyDir) return [];
|
|
42785
42904
|
const bundleDirs = await (0, runtimeEvidenceArtifacts_exports.discoverRuntimeEvidenceBundles)(historyDir);
|
|
@@ -42850,13 +42969,13 @@ var init_runtimeScorecard2 = __esm({
|
|
|
42850
42969
|
strategy: scorecardStrategy,
|
|
42851
42970
|
llmComparatorPolicy: verifiedRelease?.manifest.prospective.llmComparatorPolicy ?? "ai_approved_only"
|
|
42852
42971
|
});
|
|
42853
|
-
const outPath =
|
|
42972
|
+
const outPath = import_node_path46.default.resolve(projectRoot14, String(flags31.out));
|
|
42854
42973
|
const markdownPath = outPath.replace(/\.json$/i, "") + ".md";
|
|
42855
|
-
await
|
|
42974
|
+
await import_promises46.default.mkdir(import_node_path46.default.dirname(outPath), { recursive: true });
|
|
42856
42975
|
await Promise.all([
|
|
42857
|
-
|
|
42976
|
+
import_promises46.default.writeFile(outPath, `${JSON.stringify(scorecard, null, 2)}
|
|
42858
42977
|
`, "utf8"),
|
|
42859
|
-
|
|
42978
|
+
import_promises46.default.writeFile(
|
|
42860
42979
|
markdownPath,
|
|
42861
42980
|
formatRuntimeScorecardMarkdown(scorecard),
|
|
42862
42981
|
"utf8"
|
|
@@ -42870,7 +42989,7 @@ var init_runtimeScorecard2 = __esm({
|
|
|
42870
42989
|
const diagnosisPath = diagnosis ? outPath.replace(/\.json$/i, "") + ".diagnosis.json" : null;
|
|
42871
42990
|
const strategyReleaseRoot = resolveOptionalPath(flags31.strategyReleaseRoot);
|
|
42872
42991
|
if (diagnosis && diagnosisPath) {
|
|
42873
|
-
await
|
|
42992
|
+
await import_promises46.default.writeFile(
|
|
42874
42993
|
diagnosisPath,
|
|
42875
42994
|
`${JSON.stringify(diagnosis, null, 2)}
|
|
42876
42995
|
`,
|
|
@@ -42891,7 +43010,7 @@ var init_runtimeScorecard2 = __esm({
|
|
|
42891
43010
|
composition: verifiedRelease?.manifest.composition,
|
|
42892
43011
|
sourceArtifacts: await Promise.all(
|
|
42893
43012
|
sourcePaths.map(async (sourcePath) => ({
|
|
42894
|
-
artifactId:
|
|
43013
|
+
artifactId: import_node_path46.default.basename(sourcePath),
|
|
42895
43014
|
path: sourcePath,
|
|
42896
43015
|
sha256: await sha256File2(sourcePath)
|
|
42897
43016
|
}))
|
|
@@ -42902,11 +43021,11 @@ var init_runtimeScorecard2 = __esm({
|
|
|
42902
43021
|
let receiptPath2 = null;
|
|
42903
43022
|
if (flags31.markProcessed) {
|
|
42904
43023
|
const runtimeEvidenceBundle = await (0, runtimeEvidenceArtifacts_exports.verifyRuntimeEvidenceBundle)(
|
|
42905
|
-
|
|
43024
|
+
import_node_path46.default.dirname(runtimeEvidencePath)
|
|
42906
43025
|
);
|
|
42907
43026
|
const feedbackSource = replayEvidencePath ? await (0, runtimeFeedbackArtifacts_exports.verifyRuntimeFeedbackReplaySource)({
|
|
42908
|
-
bundleDir:
|
|
42909
|
-
runtimeEvidenceBundleDir:
|
|
43027
|
+
bundleDir: import_node_path46.default.dirname(replayEvidencePath),
|
|
43028
|
+
runtimeEvidenceBundleDir: import_node_path46.default.dirname(runtimeEvidencePath)
|
|
42910
43029
|
}).catch((error) => {
|
|
42911
43030
|
if (runtimeEvidenceBundle.artifact.producer) throw error;
|
|
42912
43031
|
return null;
|
|
@@ -42917,9 +43036,9 @@ var init_runtimeScorecard2 = __esm({
|
|
|
42917
43036
|
);
|
|
42918
43037
|
}
|
|
42919
43038
|
receiptPath2 = await markRuntimeEvidenceBundleProcessed({
|
|
42920
|
-
evidenceRoot:
|
|
43039
|
+
evidenceRoot: import_node_path46.default.resolve(projectRoot14, String(flags31.evidenceDir)),
|
|
42921
43040
|
deploymentId: String(flags31.deployment),
|
|
42922
|
-
bundleDir:
|
|
43041
|
+
bundleDir: import_node_path46.default.dirname(runtimeEvidencePath),
|
|
42923
43042
|
scorecardPath: outPath,
|
|
42924
43043
|
runtimeFeedback: feedbackSource ? {
|
|
42925
43044
|
artifactId: feedbackSource.feedback.manifest.artifactId,
|
|
@@ -43116,14 +43235,14 @@ __export(strategyRelease_exports, {
|
|
|
43116
43235
|
main: () => main49,
|
|
43117
43236
|
runStrategyReleaseCommand: () => runStrategyReleaseCommand
|
|
43118
43237
|
});
|
|
43119
|
-
var
|
|
43238
|
+
var import_promises47, import_node_fs10, import_node_readline5, import_node_path47, import_chalk50, valueAfter2, required3, writeJsonAtomic3, runStrategyReleaseCommand, printUsage2, main49;
|
|
43120
43239
|
var init_strategyRelease2 = __esm({
|
|
43121
43240
|
"src/scripts/strategyRelease.ts"() {
|
|
43122
43241
|
"use strict";
|
|
43123
|
-
|
|
43242
|
+
import_promises47 = __toESM(require("fs/promises"));
|
|
43124
43243
|
import_node_fs10 = require("fs");
|
|
43125
43244
|
import_node_readline5 = require("readline");
|
|
43126
|
-
|
|
43245
|
+
import_node_path47 = __toESM(require("path"));
|
|
43127
43246
|
import_chalk50 = __toESM(require("chalk"));
|
|
43128
43247
|
init_researchRetention();
|
|
43129
43248
|
init_strategyRelease();
|
|
@@ -43137,17 +43256,17 @@ var init_strategyRelease2 = __esm({
|
|
|
43137
43256
|
};
|
|
43138
43257
|
writeJsonAtomic3 = async (filePath, value) => {
|
|
43139
43258
|
const temporaryPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
43140
|
-
await
|
|
43141
|
-
await
|
|
43259
|
+
await import_promises47.default.mkdir(import_node_path47.default.dirname(filePath), { recursive: true });
|
|
43260
|
+
await import_promises47.default.writeFile(
|
|
43142
43261
|
temporaryPath,
|
|
43143
43262
|
`${JSON.stringify(value, null, 2)}
|
|
43144
43263
|
`,
|
|
43145
43264
|
"utf8"
|
|
43146
43265
|
);
|
|
43147
|
-
await
|
|
43266
|
+
await import_promises47.default.rename(temporaryPath, filePath);
|
|
43148
43267
|
};
|
|
43149
43268
|
runStrategyReleaseCommand = async (options) => {
|
|
43150
|
-
const inputPath =
|
|
43269
|
+
const inputPath = import_node_path47.default.resolve(options.inputPath);
|
|
43151
43270
|
if (options.command === "verify") {
|
|
43152
43271
|
const envelope = await verifyStrategyReleaseEnvelope(inputPath);
|
|
43153
43272
|
return {
|
|
@@ -43185,7 +43304,7 @@ var init_strategyRelease2 = __esm({
|
|
|
43185
43304
|
endTime,
|
|
43186
43305
|
days: options.days?.length ? options.days : [7, 30, 90]
|
|
43187
43306
|
});
|
|
43188
|
-
const outputPath =
|
|
43307
|
+
const outputPath = import_node_path47.default.resolve(
|
|
43189
43308
|
options.outputPath ?? "output/strategy-monitoring-profile.json"
|
|
43190
43309
|
);
|
|
43191
43310
|
await writeJsonAtomic3(outputPath, profile);
|
|
@@ -43196,16 +43315,16 @@ var init_strategyRelease2 = __esm({
|
|
|
43196
43315
|
profile
|
|
43197
43316
|
};
|
|
43198
43317
|
}
|
|
43199
|
-
const input = JSON.parse(await
|
|
43318
|
+
const input = JSON.parse(await import_promises47.default.readFile(inputPath, "utf8"));
|
|
43200
43319
|
if (options.command === "decide") {
|
|
43201
43320
|
const decision = await deriveStrategyReleaseResearchDecision(input);
|
|
43202
43321
|
if (options.outputPath) {
|
|
43203
|
-
await writeJsonAtomic3(
|
|
43322
|
+
await writeJsonAtomic3(import_node_path47.default.resolve(options.outputPath), decision);
|
|
43204
43323
|
}
|
|
43205
43324
|
return {
|
|
43206
43325
|
kind: "decided",
|
|
43207
43326
|
...decision,
|
|
43208
|
-
outputPath: options.outputPath ?
|
|
43327
|
+
outputPath: options.outputPath ? import_node_path47.default.resolve(options.outputPath) : null
|
|
43209
43328
|
};
|
|
43210
43329
|
}
|
|
43211
43330
|
if (options.command === "retention") {
|
|
@@ -43229,7 +43348,7 @@ var init_strategyRelease2 = __esm({
|
|
|
43229
43348
|
protectedPaths: [inputPath]
|
|
43230
43349
|
});
|
|
43231
43350
|
} else if (options.apply) {
|
|
43232
|
-
await Promise.all(plan.delete.map((entry) =>
|
|
43351
|
+
await Promise.all(plan.delete.map((entry) => import_promises47.default.rm(entry.path)));
|
|
43233
43352
|
}
|
|
43234
43353
|
return {
|
|
43235
43354
|
kind: "retention",
|
|
@@ -43243,12 +43362,12 @@ var init_strategyRelease2 = __esm({
|
|
|
43243
43362
|
}
|
|
43244
43363
|
if (options.command === "diagnose") {
|
|
43245
43364
|
const diagnosis = buildStrategyLiveDiagnosis(input);
|
|
43246
|
-
const outputPath =
|
|
43365
|
+
const outputPath = import_node_path47.default.resolve(
|
|
43247
43366
|
options.outputPath ?? "output/strategy-live-diagnosis.json"
|
|
43248
43367
|
);
|
|
43249
43368
|
await writeJsonAtomic3(outputPath, diagnosis);
|
|
43250
43369
|
const published2 = options.rootDir ? await publishStrategyLiveDiagnosis({
|
|
43251
|
-
rootDir:
|
|
43370
|
+
rootDir: import_node_path47.default.resolve(options.rootDir),
|
|
43252
43371
|
diagnosis,
|
|
43253
43372
|
sourceArtifacts: input.sourceArtifacts ?? []
|
|
43254
43373
|
}) : null;
|
|
@@ -43265,7 +43384,7 @@ var init_strategyRelease2 = __esm({
|
|
|
43265
43384
|
evidence: await collectReleaseEvidenceReferences(input.evidence ?? [])
|
|
43266
43385
|
});
|
|
43267
43386
|
const published = await publishStrategyRelease({
|
|
43268
|
-
rootDir:
|
|
43387
|
+
rootDir: import_node_path47.default.resolve(options.rootDir ?? "data/strategy-release"),
|
|
43269
43388
|
manifest
|
|
43270
43389
|
});
|
|
43271
43390
|
return {
|
|
@@ -43325,7 +43444,7 @@ __export(serverHealth_exports, {
|
|
|
43325
43444
|
main: () => main50,
|
|
43326
43445
|
resolveServerHealthThresholds: () => resolveServerHealthThresholds
|
|
43327
43446
|
});
|
|
43328
|
-
var import_config10, import_node_child_process12, import_node_os5, import_node_fs11, import_args35,
|
|
43447
|
+
var import_config10, import_node_child_process12, import_node_os5, import_node_fs11, import_args35, import_redis24, DEFAULT_STATE, DEFAULT_THRESHOLDS, escapeHtml6, formatPctValue, formatLoadPerCore, formatGiB, formatDuration2, readDiskUsage, parseMeminfoBytes, readMemorySnapshot, runDiagnosticCommand, runDiagnosticCommands, collectServerHealthSnapshot, buildHumanSummaryLines, evaluateServerHealth, shouldRecover, buildAlertMessage, buildRecoveryMessage, buildServerHealthDiagnostics, getStateKey, toFiniteNumber3, resolveServerHealthThresholds, main50;
|
|
43329
43448
|
var init_serverHealth = __esm({
|
|
43330
43449
|
"src/scripts/serverHealth.ts"() {
|
|
43331
43450
|
"use strict";
|
|
@@ -43334,7 +43453,7 @@ var init_serverHealth = __esm({
|
|
|
43334
43453
|
import_node_os5 = __toESM(require("os"));
|
|
43335
43454
|
import_node_fs11 = require("fs");
|
|
43336
43455
|
import_args35 = __toESM(require("args"));
|
|
43337
|
-
|
|
43456
|
+
import_redis24 = require("@tradejs/infra/redis");
|
|
43338
43457
|
init_telegramReports();
|
|
43339
43458
|
DEFAULT_STATE = {
|
|
43340
43459
|
status: "healthy",
|
|
@@ -43367,21 +43486,21 @@ var init_serverHealth = __esm({
|
|
|
43367
43486
|
}
|
|
43368
43487
|
return `${minutes}m`;
|
|
43369
43488
|
};
|
|
43370
|
-
readDiskUsage = (
|
|
43489
|
+
readDiskUsage = (path58) => {
|
|
43371
43490
|
try {
|
|
43372
|
-
const stats = (0, import_node_fs11.statfsSync)(
|
|
43491
|
+
const stats = (0, import_node_fs11.statfsSync)(path58);
|
|
43373
43492
|
const totalBlocks = Number(stats.blocks ?? 0);
|
|
43374
43493
|
const availableBlocks = Number(stats.bavail ?? 0);
|
|
43375
43494
|
if (totalBlocks <= 0) {
|
|
43376
|
-
return { path:
|
|
43495
|
+
return { path: path58, usedPct: null };
|
|
43377
43496
|
}
|
|
43378
43497
|
const usedPct = (totalBlocks - Math.max(0, availableBlocks)) / totalBlocks * 100;
|
|
43379
43498
|
return {
|
|
43380
|
-
path:
|
|
43499
|
+
path: path58,
|
|
43381
43500
|
usedPct: Number.isFinite(usedPct) ? usedPct : null
|
|
43382
43501
|
};
|
|
43383
43502
|
} catch {
|
|
43384
|
-
return { path:
|
|
43503
|
+
return { path: path58, usedPct: null };
|
|
43385
43504
|
}
|
|
43386
43505
|
};
|
|
43387
43506
|
parseMeminfoBytes = (value) => {
|
|
@@ -43744,7 +43863,7 @@ var init_serverHealth = __esm({
|
|
|
43744
43863
|
const diskPath = String(flags36.diskPath || "/");
|
|
43745
43864
|
const snapshot = collectServerHealthSnapshot(diskPath);
|
|
43746
43865
|
const stateKey = getStateKey(String(flags36.user), snapshot.hostname);
|
|
43747
|
-
const prevState = await (0,
|
|
43866
|
+
const prevState = await (0, import_redis24.getData)(stateKey, DEFAULT_STATE) ?? DEFAULT_STATE;
|
|
43748
43867
|
const evaluation = evaluateServerHealth(snapshot, thresholds);
|
|
43749
43868
|
const cooldownMs = Math.max(60, Number(flags36.cooldownSec)) * 1e3;
|
|
43750
43869
|
const now2 = snapshot.timestamp;
|
|
@@ -43757,7 +43876,7 @@ var init_serverHealth = __esm({
|
|
|
43757
43876
|
lastOkAt: prevState.lastOkAt,
|
|
43758
43877
|
activeIssueCodes: evaluation.issues.map((issue) => issue.code)
|
|
43759
43878
|
};
|
|
43760
|
-
await (0,
|
|
43879
|
+
await (0, import_redis24.setData)(stateKey, nextState2, { expire: 0 });
|
|
43761
43880
|
if (shouldSend) {
|
|
43762
43881
|
const message = buildAlertMessage({
|
|
43763
43882
|
evaluation,
|
|
@@ -43786,7 +43905,7 @@ var init_serverHealth = __esm({
|
|
|
43786
43905
|
lastOkAt: now2,
|
|
43787
43906
|
activeIssueCodes: []
|
|
43788
43907
|
};
|
|
43789
|
-
await (0,
|
|
43908
|
+
await (0, import_redis24.setData)(stateKey, nextState, { expire: 0 });
|
|
43790
43909
|
if (recovered) {
|
|
43791
43910
|
const message = buildRecoveryMessage({ snapshot, prevState });
|
|
43792
43911
|
if (flags36.printOnly) {
|
|
@@ -45133,18 +45252,18 @@ __export(runtimeParity_exports, {
|
|
|
45133
45252
|
main: () => main51,
|
|
45134
45253
|
runtimeParity: () => runtimeParity
|
|
45135
45254
|
});
|
|
45136
|
-
var import_config11,
|
|
45255
|
+
var import_config11, import_node_crypto24, import_args36, import_chalk52, import_constants20, import_time13, import_logger8, import_redis25, import_cli12, import_backtest8, import_connectors17, flags32, interval3, projectRoot16, DEFAULT_LOOKBACK_DAYS, DETAIL_LIMIT2, DEFAULT_REPLAY_ENV, resolveParityConnectorName, createConnector, buildReplayAiAnalyses, formatReplayEnvSummary, buildReplayConfig, warmReplayHistory, runtimeParity, main51;
|
|
45137
45256
|
var init_runtimeParity2 = __esm({
|
|
45138
45257
|
"src/scripts/runtimeParity.ts"() {
|
|
45139
45258
|
"use strict";
|
|
45140
45259
|
import_config11 = require("dotenv/config");
|
|
45141
|
-
|
|
45260
|
+
import_node_crypto24 = require("crypto");
|
|
45142
45261
|
import_args36 = __toESM(require("args"));
|
|
45143
45262
|
import_chalk52 = __toESM(require("chalk"));
|
|
45144
45263
|
import_constants20 = require("@tradejs/core/constants");
|
|
45145
45264
|
import_time13 = require("@tradejs/core/time");
|
|
45146
45265
|
import_logger8 = require("@tradejs/infra/logger");
|
|
45147
|
-
|
|
45266
|
+
import_redis25 = require("@tradejs/infra/redis");
|
|
45148
45267
|
import_cli12 = require("@tradejs/node/cli");
|
|
45149
45268
|
import_backtest8 = require("@tradejs/node/backtest");
|
|
45150
45269
|
import_connectors17 = require("@tradejs/node/connectors");
|
|
@@ -45304,8 +45423,8 @@ var init_runtimeParity2 = __esm({
|
|
|
45304
45423
|
toleranceMs
|
|
45305
45424
|
}) => {
|
|
45306
45425
|
const [userConfig, strategyResults] = await Promise.all([
|
|
45307
|
-
(0,
|
|
45308
|
-
(0,
|
|
45426
|
+
(0, import_redis25.getData)(import_redis25.redisKeys.strategyConfig(userName3, strategy), {}),
|
|
45427
|
+
(0, import_redis25.getData)(import_redis25.redisKeys.strategyResults(userName3, strategy), {})
|
|
45309
45428
|
]);
|
|
45310
45429
|
const typedResults = strategyResults ?? {};
|
|
45311
45430
|
const symbolResult = typedResults?.[symbol];
|
|
@@ -45521,9 +45640,9 @@ var init_runtimeParity2 = __esm({
|
|
|
45521
45640
|
start: window.start,
|
|
45522
45641
|
end: window.end
|
|
45523
45642
|
},
|
|
45524
|
-
name: `${target.symbol}_${target.strategy}_${(0,
|
|
45525
|
-
testId: (0,
|
|
45526
|
-
testSuiteId: (0,
|
|
45643
|
+
name: `${target.symbol}_${target.strategy}_${(0, import_node_crypto24.randomUUID)().slice(0, 8)}`,
|
|
45644
|
+
testId: (0, import_node_crypto24.randomUUID)().slice(0, 8),
|
|
45645
|
+
testSuiteId: (0, import_node_crypto24.randomUUID)().slice(0, 8),
|
|
45527
45646
|
strategyName: target.strategy,
|
|
45528
45647
|
strategyConfig: replayConfig,
|
|
45529
45648
|
connectorName,
|
|
@@ -45741,11 +45860,11 @@ var init_skipStats = __esm({
|
|
|
45741
45860
|
});
|
|
45742
45861
|
|
|
45743
45862
|
// src/lib/signals/evaluations.ts
|
|
45744
|
-
var
|
|
45863
|
+
var import_redis26, runtimeLineageScopeCache, runtimeLineageScopeCacheDayKey, runtimeLineageScopeCacheLoaded, buildRuntimeSignalEvaluationId, buildLineageField, flushRuntimeSignalEvaluations, createRuntimeSignalEvaluationBuffer;
|
|
45745
45864
|
var init_evaluations = __esm({
|
|
45746
45865
|
"src/lib/signals/evaluations.ts"() {
|
|
45747
45866
|
"use strict";
|
|
45748
|
-
|
|
45867
|
+
import_redis26 = require("@tradejs/infra/redis");
|
|
45749
45868
|
init_runtimeSignalsStorage();
|
|
45750
45869
|
init_runtimeLineage();
|
|
45751
45870
|
runtimeLineageScopeCache = /* @__PURE__ */ new Map();
|
|
@@ -45796,7 +45915,7 @@ var init_evaluations = __esm({
|
|
|
45796
45915
|
runtimeLineageScopeCacheDayKey = dayKey;
|
|
45797
45916
|
runtimeLineageScopeCacheLoaded = false;
|
|
45798
45917
|
}
|
|
45799
|
-
const lineageBucket =
|
|
45918
|
+
const lineageBucket = import_redis26.redisKeys.runtimeLineageScopeBucket(
|
|
45800
45919
|
dayEvaluations[0].userName,
|
|
45801
45920
|
dayKey
|
|
45802
45921
|
);
|
|
@@ -45804,7 +45923,7 @@ var init_evaluations = __esm({
|
|
|
45804
45923
|
(evaluation) => evaluation.runtimeLineage != null
|
|
45805
45924
|
);
|
|
45806
45925
|
if (lineageEvaluations.length > 0 && !runtimeLineageScopeCacheLoaded) {
|
|
45807
|
-
const storedScopes = await (0,
|
|
45926
|
+
const storedScopes = await (0, import_redis26.getHashJsonValues)(lineageBucket);
|
|
45808
45927
|
for (const scope of storedScopes) {
|
|
45809
45928
|
const lineageField = buildLineageField(scope);
|
|
45810
45929
|
runtimeLineageScopeCache.set(`${lineageBucket}:${lineageField}`, scope);
|
|
@@ -45849,7 +45968,7 @@ var init_evaluations = __esm({
|
|
|
45849
45968
|
lineageWrites.set(lineageField, scope);
|
|
45850
45969
|
}
|
|
45851
45970
|
if (lineageWrites.size > 0) {
|
|
45852
|
-
await (0,
|
|
45971
|
+
await (0, import_redis26.setHashJsonFields)(
|
|
45853
45972
|
lineageBucket,
|
|
45854
45973
|
[...lineageWrites].map(([field, data]) => ({ field, data })),
|
|
45855
45974
|
{
|
|
@@ -45861,7 +45980,7 @@ var init_evaluations = __esm({
|
|
|
45861
45980
|
const statsIncrements = /* @__PURE__ */ new Map();
|
|
45862
45981
|
for (const evaluation of dayEvaluations) {
|
|
45863
45982
|
if (shouldStoreDetailedRuntimeSignalEvaluation(evaluation)) {
|
|
45864
|
-
const bucket =
|
|
45983
|
+
const bucket = import_redis26.redisKeys.runtimeSignalEvaluationBucket(
|
|
45865
45984
|
evaluation.userName,
|
|
45866
45985
|
dayKey,
|
|
45867
45986
|
evaluation.strategy
|
|
@@ -45873,7 +45992,7 @@ var init_evaluations = __esm({
|
|
|
45873
45992
|
});
|
|
45874
45993
|
detailedWrites.set(bucket, entries);
|
|
45875
45994
|
}
|
|
45876
|
-
const statsBucket =
|
|
45995
|
+
const statsBucket = import_redis26.redisKeys.runtimeSignalEvaluationStatsBucket(
|
|
45877
45996
|
evaluation.userName,
|
|
45878
45997
|
dayKey,
|
|
45879
45998
|
evaluation.strategy,
|
|
@@ -45889,12 +46008,12 @@ var init_evaluations = __esm({
|
|
|
45889
46008
|
}
|
|
45890
46009
|
await Promise.all([
|
|
45891
46010
|
...[...detailedWrites].map(
|
|
45892
|
-
([bucket, entries]) => (0,
|
|
46011
|
+
([bucket, entries]) => (0, import_redis26.setHashJsonFields)(bucket, entries, {
|
|
45893
46012
|
expire: runtimeSignalRetentionTtl
|
|
45894
46013
|
})
|
|
45895
46014
|
),
|
|
45896
46015
|
...[...statsIncrements].map(
|
|
45897
|
-
([bucket, increments]) => (0,
|
|
46016
|
+
([bucket, increments]) => (0, import_redis26.incrHashFields)(bucket, increments, {
|
|
45898
46017
|
expire: runtimeSignalRetentionTtl
|
|
45899
46018
|
})
|
|
45900
46019
|
)
|
|
@@ -45910,7 +46029,7 @@ var init_evaluations = __esm({
|
|
|
45910
46029
|
const runtimeSignalRetentionTtl = getRuntimeSignalRetentionTtlSeconds();
|
|
45911
46030
|
const signalRefsByBucket = /* @__PURE__ */ new Map();
|
|
45912
46031
|
for (const { userName: userName3, signal } of pendingSignals) {
|
|
45913
|
-
const bucket =
|
|
46032
|
+
const bucket = import_redis26.redisKeys.runtimeSignalBucket(
|
|
45914
46033
|
userName3,
|
|
45915
46034
|
(0, import_time5.getRuntimeStorageDayKey)(signal.timestamp),
|
|
45916
46035
|
signal.strategy
|
|
@@ -45924,14 +46043,14 @@ var init_evaluations = __esm({
|
|
|
45924
46043
|
}
|
|
45925
46044
|
await Promise.all([
|
|
45926
46045
|
...pendingSignals.map(
|
|
45927
|
-
({ signal }) => (0,
|
|
45928
|
-
|
|
46046
|
+
({ signal }) => (0, import_redis26.setData)(
|
|
46047
|
+
import_redis26.redisKeys.storeSignal(signal.symbol, signal.signalId),
|
|
45929
46048
|
toStoredRuntimeSignal(signal),
|
|
45930
46049
|
{ expire: runtimeSignalRetentionTtl }
|
|
45931
46050
|
)
|
|
45932
46051
|
),
|
|
45933
46052
|
...[...signalRefsByBucket].map(
|
|
45934
|
-
([bucket, entries]) => (0,
|
|
46053
|
+
([bucket, entries]) => (0, import_redis26.setHashJsonFields)(bucket, entries, {
|
|
45935
46054
|
expire: runtimeSignalRetentionTtl
|
|
45936
46055
|
})
|
|
45937
46056
|
)
|
|
@@ -48511,14 +48630,14 @@ var user_add_exports = {};
|
|
|
48511
48630
|
__export(user_add_exports, {
|
|
48512
48631
|
main: () => main57
|
|
48513
48632
|
});
|
|
48514
|
-
var import_args39, import_chalk55, import_bcryptjs,
|
|
48633
|
+
var import_args39, import_chalk55, import_bcryptjs, import_redis27, flags35, main57;
|
|
48515
48634
|
var init_user_add = __esm({
|
|
48516
48635
|
"src/scripts/user-add.ts"() {
|
|
48517
48636
|
"use strict";
|
|
48518
48637
|
import_args39 = __toESM(require("args"));
|
|
48519
48638
|
import_chalk55 = __toESM(require("chalk"));
|
|
48520
48639
|
import_bcryptjs = __toESM(require("bcryptjs"));
|
|
48521
|
-
|
|
48640
|
+
import_redis27 = require("@tradejs/infra/redis");
|
|
48522
48641
|
import_args39.default.example("yarn user-add -u myname -p 123456", "Create or update user");
|
|
48523
48642
|
import_args39.default.option(["u", "user"], "Username", "");
|
|
48524
48643
|
import_args39.default.option(["p", "password"], "Password (plain text)", "");
|
|
@@ -48531,14 +48650,14 @@ var init_user_add = __esm({
|
|
|
48531
48650
|
process.exit(1);
|
|
48532
48651
|
}
|
|
48533
48652
|
const passwordHash = await import_bcryptjs.default.hash(password, 10);
|
|
48534
|
-
const existing = await (0,
|
|
48653
|
+
const existing = await (0, import_redis27.getData)(import_redis27.redisKeys.user(userName3), null);
|
|
48535
48654
|
const next = {
|
|
48536
48655
|
...existing ?? {},
|
|
48537
48656
|
passwordHash,
|
|
48538
48657
|
userName: userName3,
|
|
48539
48658
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
48540
48659
|
};
|
|
48541
|
-
await (0,
|
|
48660
|
+
await (0, import_redis27.setData)(import_redis27.redisKeys.user(userName3), next, {
|
|
48542
48661
|
expire: 0
|
|
48543
48662
|
});
|
|
48544
48663
|
console.log(import_chalk55.default.green(`User ${userName3} updated`));
|
|
@@ -48557,7 +48676,7 @@ __export(cli_exports, {
|
|
|
48557
48676
|
});
|
|
48558
48677
|
module.exports = __toCommonJS(cli_exports);
|
|
48559
48678
|
var import_config16 = require("dotenv/config");
|
|
48560
|
-
var
|
|
48679
|
+
var import_redis28 = require("@tradejs/infra/redis");
|
|
48561
48680
|
var import_client10 = require("@tradejs/infra/timescale/client");
|
|
48562
48681
|
var scriptLoaders = {
|
|
48563
48682
|
"research-visuals": () => Promise.resolve().then(() => (init_researchVisuals2(), researchVisuals_exports)),
|
|
@@ -48633,7 +48752,7 @@ var runLoadedModule = async (loaded) => {
|
|
|
48633
48752
|
}
|
|
48634
48753
|
};
|
|
48635
48754
|
var cleanupCliResources = async () => {
|
|
48636
|
-
await Promise.allSettled([(0,
|
|
48755
|
+
await Promise.allSettled([(0, import_redis28.closeRedisConnection)(), (0, import_client10.closeTimescalePool)()]);
|
|
48637
48756
|
};
|
|
48638
48757
|
var main58 = async () => {
|
|
48639
48758
|
const [, scriptPath, command = "", ...args40] = process.argv;
|