@tradejs/cli 3.1.29-beta.276 → 3.1.29-beta.278
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 +822 -380
- package/dist/lib/mcpReplayProcess.js +103 -0
- package/dist/lib/strategyRelease.js +18 -1
- package/dist/scripts/mcpWorker.js +129 -7
- package/dist/scripts/strategyRelease.js +408 -90
- package/package.json +7 -7
package/dist/cli.js
CHANGED
|
@@ -2278,9 +2278,9 @@ var init_features = __esm({
|
|
|
2278
2278
|
"targetsymbol",
|
|
2279
2279
|
"universe"
|
|
2280
2280
|
]);
|
|
2281
|
-
normalizeFeaturePath = (
|
|
2282
|
-
classifyAiPocketCoverageFeaturePath = (
|
|
2283
|
-
const segments = normalizeFeaturePath(
|
|
2281
|
+
normalizeFeaturePath = (path47) => (Array.isArray(path47) ? path47 : path47.split(".")).filter(Boolean).map((segment) => segment.toLowerCase());
|
|
2282
|
+
classifyAiPocketCoverageFeaturePath = (path47) => {
|
|
2283
|
+
const segments = normalizeFeaturePath(path47);
|
|
2284
2284
|
const normalizedPath = segments.join(".");
|
|
2285
2285
|
if (segments.some(
|
|
2286
2286
|
(segment) => segment.includes("cmc") || segment.includes("coinmarketcap")
|
|
@@ -2454,8 +2454,8 @@ var init_features = __esm({
|
|
|
2454
2454
|
"volumeusd",
|
|
2455
2455
|
"vwap"
|
|
2456
2456
|
]);
|
|
2457
|
-
classifyAiPocketFeaturePath = (
|
|
2458
|
-
const segments = (Array.isArray(
|
|
2457
|
+
classifyAiPocketFeaturePath = (path47) => {
|
|
2458
|
+
const segments = (Array.isArray(path47) ? path47 : path47.split(".")).filter(
|
|
2459
2459
|
Boolean
|
|
2460
2460
|
);
|
|
2461
2461
|
const normalized = segments.map((segment) => segment.toLowerCase());
|
|
@@ -2772,11 +2772,11 @@ var init_features = __esm({
|
|
|
2772
2772
|
excludeFeaturePattern.source,
|
|
2773
2773
|
excludeFeaturePattern.flags.replace(/[gy]/g, "")
|
|
2774
2774
|
) : void 0;
|
|
2775
|
-
const isOperatorExcluded = (
|
|
2776
|
-
if (!exclusion?.test(
|
|
2775
|
+
const isOperatorExcluded = (path47) => {
|
|
2776
|
+
if (!exclusion?.test(path47)) {
|
|
2777
2777
|
return false;
|
|
2778
2778
|
}
|
|
2779
|
-
onFeatureExcluded?.({ path:
|
|
2779
|
+
onFeatureExcluded?.({ path: path47, classification: "operator-excluded" });
|
|
2780
2780
|
return true;
|
|
2781
2781
|
};
|
|
2782
2782
|
const signal = payload.signal ?? {};
|
|
@@ -11317,27 +11317,27 @@ var init_coinMarketCapContextBackfill = __esm({
|
|
|
11317
11317
|
totalCredits: 0,
|
|
11318
11318
|
byPath: /* @__PURE__ */ new Map()
|
|
11319
11319
|
});
|
|
11320
|
-
getCoinMarketCapPathLabel = (
|
|
11321
|
-
if (
|
|
11322
|
-
if (
|
|
11323
|
-
if (
|
|
11324
|
-
if (
|
|
11325
|
-
if (
|
|
11326
|
-
if (
|
|
11327
|
-
return
|
|
11328
|
-
};
|
|
11329
|
-
recordCoinMarketCapFetchStats = (stats,
|
|
11320
|
+
getCoinMarketCapPathLabel = (path47) => {
|
|
11321
|
+
if (path47.includes("global-metrics")) return "global";
|
|
11322
|
+
if (path47.includes("cryptocurrency/quotes")) return "reference";
|
|
11323
|
+
if (path47.includes("exchange/quotes")) return "exchangeLiquidity";
|
|
11324
|
+
if (path47.includes("fear-and-greed")) return "fearGreed";
|
|
11325
|
+
if (path47.includes("cmc100")) return "cmc100";
|
|
11326
|
+
if (path47.includes("cmc20")) return "cmc20";
|
|
11327
|
+
return path47;
|
|
11328
|
+
};
|
|
11329
|
+
recordCoinMarketCapFetchStats = (stats, path47, creditCount) => {
|
|
11330
11330
|
if (!stats) return;
|
|
11331
|
-
const existing = stats.byPath.get(
|
|
11331
|
+
const existing = stats.byPath.get(path47) ?? { requests: 0, credits: 0 };
|
|
11332
11332
|
existing.requests += 1;
|
|
11333
11333
|
existing.credits += creditCount ?? 0;
|
|
11334
11334
|
stats.requests += 1;
|
|
11335
11335
|
stats.totalCredits += creditCount ?? 0;
|
|
11336
|
-
stats.byPath.set(
|
|
11336
|
+
stats.byPath.set(path47, existing);
|
|
11337
11337
|
};
|
|
11338
11338
|
formatCoinMarketCapFetchStats = (stats) => {
|
|
11339
11339
|
const byPath = [...stats.byPath.entries()].map(
|
|
11340
|
-
([
|
|
11340
|
+
([path47, item]) => `${getCoinMarketCapPathLabel(path47)}=${item.requests}req/${item.credits}cr`
|
|
11341
11341
|
).join(" ");
|
|
11342
11342
|
return `apiRequests=${stats.requests} apiCredits=${stats.totalCredits}${byPath ? ` ${byPath}` : ""}`;
|
|
11343
11343
|
};
|
|
@@ -24462,45 +24462,45 @@ var init_marketWsGateway = __esm({
|
|
|
24462
24462
|
socket.destroy();
|
|
24463
24463
|
return;
|
|
24464
24464
|
}
|
|
24465
|
-
wsServer.handleUpgrade(request, socket, head, (
|
|
24466
|
-
wsServer.emit("connection",
|
|
24465
|
+
wsServer.handleUpgrade(request, socket, head, (client2) => {
|
|
24466
|
+
wsServer.emit("connection", client2, request);
|
|
24467
24467
|
});
|
|
24468
24468
|
});
|
|
24469
|
-
wsServer.on("connection", (
|
|
24470
|
-
subscriptions.set(
|
|
24471
|
-
alive.add(
|
|
24472
|
-
|
|
24473
|
-
|
|
24469
|
+
wsServer.on("connection", (client2) => {
|
|
24470
|
+
subscriptions.set(client2, /* @__PURE__ */ new Set());
|
|
24471
|
+
alive.add(client2);
|
|
24472
|
+
client2.on("pong", () => alive.add(client2));
|
|
24473
|
+
client2.on("message", (raw) => {
|
|
24474
24474
|
const command = parseSubscriptionCommand(raw.toString());
|
|
24475
24475
|
if (!command) {
|
|
24476
|
-
|
|
24476
|
+
client2.send(JSON.stringify({ type: "error", error: "bad_command" }));
|
|
24477
24477
|
return;
|
|
24478
24478
|
}
|
|
24479
24479
|
subscriptions.set(
|
|
24480
|
-
|
|
24480
|
+
client2,
|
|
24481
24481
|
applySubscriptionCommand(
|
|
24482
|
-
subscriptions.get(
|
|
24482
|
+
subscriptions.get(client2) ?? /* @__PURE__ */ new Set(),
|
|
24483
24483
|
command
|
|
24484
24484
|
)
|
|
24485
24485
|
);
|
|
24486
|
-
|
|
24486
|
+
client2.send(
|
|
24487
24487
|
JSON.stringify({
|
|
24488
24488
|
type: "subscribed",
|
|
24489
|
-
topics: [...subscriptions.get(
|
|
24489
|
+
topics: [...subscriptions.get(client2) ?? []]
|
|
24490
24490
|
})
|
|
24491
24491
|
);
|
|
24492
24492
|
});
|
|
24493
|
-
|
|
24493
|
+
client2.on("close", () => subscriptions.delete(client2));
|
|
24494
24494
|
});
|
|
24495
24495
|
const heartbeat = setInterval(() => {
|
|
24496
|
-
for (const
|
|
24497
|
-
if (!alive.has(
|
|
24498
|
-
|
|
24499
|
-
subscriptions.delete(
|
|
24496
|
+
for (const client2 of subscriptions.keys()) {
|
|
24497
|
+
if (!alive.has(client2)) {
|
|
24498
|
+
client2.terminate();
|
|
24499
|
+
subscriptions.delete(client2);
|
|
24500
24500
|
continue;
|
|
24501
24501
|
}
|
|
24502
|
-
alive.delete(
|
|
24503
|
-
|
|
24502
|
+
alive.delete(client2);
|
|
24503
|
+
client2.ping();
|
|
24504
24504
|
}
|
|
24505
24505
|
}, 3e4);
|
|
24506
24506
|
subscriber.on("message", (channel, payload) => {
|
|
@@ -24509,9 +24509,9 @@ var init_marketWsGateway = __esm({
|
|
|
24509
24509
|
if (!event) return;
|
|
24510
24510
|
const topic = buildMarketKlineTopic(event);
|
|
24511
24511
|
const message = JSON.stringify({ type: "kline", topic, event });
|
|
24512
|
-
for (const [
|
|
24513
|
-
if (
|
|
24514
|
-
|
|
24512
|
+
for (const [client2, topics] of subscriptions) {
|
|
24513
|
+
if (client2.readyState === import_ws.WebSocket.OPEN && topics.has(topic)) {
|
|
24514
|
+
client2.send(message);
|
|
24515
24515
|
}
|
|
24516
24516
|
}
|
|
24517
24517
|
});
|
|
@@ -24527,7 +24527,7 @@ var init_marketWsGateway = __esm({
|
|
|
24527
24527
|
return {
|
|
24528
24528
|
close: async () => {
|
|
24529
24529
|
clearInterval(heartbeat);
|
|
24530
|
-
for (const
|
|
24530
|
+
for (const client2 of subscriptions.keys()) client2.close();
|
|
24531
24531
|
subscriptions.clear();
|
|
24532
24532
|
await subscriber.unsubscribe(MARKET_KLINE_CHANNEL);
|
|
24533
24533
|
subscriber.disconnect();
|
|
@@ -24567,26 +24567,102 @@ var init_marketWs = __esm({
|
|
|
24567
24567
|
}
|
|
24568
24568
|
});
|
|
24569
24569
|
|
|
24570
|
+
// src/lib/runtimeEvidenceArtifacts.ts
|
|
24571
|
+
var runtimeEvidenceArtifacts_exports = {};
|
|
24572
|
+
var init_runtimeEvidenceArtifacts = __esm({
|
|
24573
|
+
"src/lib/runtimeEvidenceArtifacts.ts"() {
|
|
24574
|
+
"use strict";
|
|
24575
|
+
__reExport(runtimeEvidenceArtifacts_exports, require("@tradejs/node/diagnostics"));
|
|
24576
|
+
}
|
|
24577
|
+
});
|
|
24578
|
+
|
|
24579
|
+
// src/lib/mcpReplayProcess.ts
|
|
24580
|
+
var import_node_path14, import_node_crypto8, import_promises17, client, buildMcpReplayProcess;
|
|
24581
|
+
var init_mcpReplayProcess = __esm({
|
|
24582
|
+
"src/lib/mcpReplayProcess.ts"() {
|
|
24583
|
+
"use strict";
|
|
24584
|
+
import_node_path14 = __toESM(require("path"));
|
|
24585
|
+
import_node_crypto8 = require("crypto");
|
|
24586
|
+
import_promises17 = __toESM(require("fs/promises"));
|
|
24587
|
+
init_runtimeEvidenceArtifacts();
|
|
24588
|
+
client = `
|
|
24589
|
+
const fs = require('node:fs');
|
|
24590
|
+
const path = require('node:path');
|
|
24591
|
+
const [root, id, request] = process.argv.slice(1);
|
|
24592
|
+
const file = path.join(root, id);
|
|
24593
|
+
fs.mkdirSync(root, {recursive:true});
|
|
24594
|
+
try { fs.writeFileSync(file + '.request', request, {flag:'wx'}); }
|
|
24595
|
+
catch (error) { if (error.code !== 'EEXIST') throw error; if (fs.readFileSync(file + '.request', 'utf8') !== request) throw new Error('Replay request identity conflict'); }
|
|
24596
|
+
process.on('SIGTERM', () => { fs.writeFileSync(file + '.cancel', 'cancel'); process.exit(143); });
|
|
24597
|
+
const timer = setInterval(() => {
|
|
24598
|
+
try {
|
|
24599
|
+
const result = JSON.parse(fs.readFileSync(file + '.result', 'utf8'));
|
|
24600
|
+
console.log(result.message);
|
|
24601
|
+
clearInterval(timer);
|
|
24602
|
+
process.exit(result.exitCode === 0 ? 0 : 1);
|
|
24603
|
+
} catch (error) { if (error.code !== 'ENOENT') throw error; }
|
|
24604
|
+
}, 1000);
|
|
24605
|
+
`;
|
|
24606
|
+
buildMcpReplayProcess = async ({
|
|
24607
|
+
evidencePath,
|
|
24608
|
+
outDir,
|
|
24609
|
+
runId,
|
|
24610
|
+
projectRoot: projectRoot18,
|
|
24611
|
+
env
|
|
24612
|
+
}) => {
|
|
24613
|
+
if (!/^[a-f0-9]{64}$/.test(runId))
|
|
24614
|
+
throw new Error("Invalid replay request id");
|
|
24615
|
+
const bundle = await (0, runtimeEvidenceArtifacts_exports.verifyRuntimeEvidenceBundle)(import_node_path14.default.dirname(evidencePath));
|
|
24616
|
+
if (import_node_path14.default.resolve(evidencePath) !== import_node_path14.default.resolve(bundle.payloadPath))
|
|
24617
|
+
throw new Error("Replay requires the verified bundle payload");
|
|
24618
|
+
const relative = import_node_path14.default.relative(import_node_path14.default.join(projectRoot18, "data"), evidencePath);
|
|
24619
|
+
if (relative.startsWith("..") || import_node_path14.default.isAbsolute(relative))
|
|
24620
|
+
throw new Error("Evidence must be inside Project data");
|
|
24621
|
+
const root = env.MCP_REPLAY_REQUEST_ROOT || import_node_path14.default.join(projectRoot18, "data/mcp-replay-requests");
|
|
24622
|
+
const heartbeat = JSON.parse(
|
|
24623
|
+
await import_promises17.default.readFile(import_node_path14.default.join(root, "heartbeat.json"), "utf8")
|
|
24624
|
+
);
|
|
24625
|
+
if (!Number.isFinite(heartbeat.observedAt) || Date.now() - heartbeat.observedAt < 0 || Date.now() - heartbeat.observedAt > 12e4)
|
|
24626
|
+
throw new Error("Host replay runner heartbeat is stale");
|
|
24627
|
+
const bytes = await import_promises17.default.readFile(evidencePath);
|
|
24628
|
+
const request = JSON.stringify({
|
|
24629
|
+
schemaVersion: 1,
|
|
24630
|
+
id: runId,
|
|
24631
|
+
evidence: relative,
|
|
24632
|
+
artifactId: bundle.manifest.artifactId,
|
|
24633
|
+
deploymentId: bundle.manifest.deploymentId,
|
|
24634
|
+
payloadSha256: (0, import_node_crypto8.createHash)("sha256").update(bytes).digest("hex")
|
|
24635
|
+
});
|
|
24636
|
+
void outDir;
|
|
24637
|
+
return {
|
|
24638
|
+
executable: process.execPath,
|
|
24639
|
+
args: ["-e", client, root, runId, request]
|
|
24640
|
+
};
|
|
24641
|
+
};
|
|
24642
|
+
}
|
|
24643
|
+
});
|
|
24644
|
+
|
|
24570
24645
|
// src/scripts/mcpWorker.ts
|
|
24571
24646
|
var mcpWorker_exports = {};
|
|
24572
24647
|
__export(mcpWorker_exports, {
|
|
24573
24648
|
main: () => main26
|
|
24574
24649
|
});
|
|
24575
|
-
var import_node_child_process4,
|
|
24650
|
+
var import_node_child_process4, import_node_crypto9, import_promises18, import_redis15, import_mcp, pause, leaseKey, LEASE_SECONDS, JOB_TIMEOUT_MS, main26;
|
|
24576
24651
|
var init_mcpWorker = __esm({
|
|
24577
24652
|
"src/scripts/mcpWorker.ts"() {
|
|
24578
24653
|
"use strict";
|
|
24579
24654
|
import_node_child_process4 = require("child_process");
|
|
24580
|
-
|
|
24581
|
-
|
|
24655
|
+
import_node_crypto9 = require("crypto");
|
|
24656
|
+
import_promises18 = require("fs/promises");
|
|
24582
24657
|
import_redis15 = require("@tradejs/infra/redis");
|
|
24583
24658
|
import_mcp = require("@tradejs/node/mcp");
|
|
24659
|
+
init_mcpReplayProcess();
|
|
24584
24660
|
pause = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
24585
24661
|
leaseKey = "worker:lease";
|
|
24586
24662
|
LEASE_SECONDS = 15;
|
|
24587
24663
|
JOB_TIMEOUT_MS = 60 * 60 * 1e3;
|
|
24588
24664
|
main26 = async (options = {}) => {
|
|
24589
|
-
const owner = (0,
|
|
24665
|
+
const owner = (0, import_node_crypto9.randomUUID)();
|
|
24590
24666
|
if (!await import_redis15.mcpStorage.put(leaseKey, owner, LEASE_SECONDS, true))
|
|
24591
24667
|
throw new Error("Another MCP worker owns this storage");
|
|
24592
24668
|
let stopping = false;
|
|
@@ -24594,6 +24670,18 @@ var init_mcpWorker = __esm({
|
|
|
24594
24670
|
let renewing = false;
|
|
24595
24671
|
let leaseLost = false;
|
|
24596
24672
|
let manifestHash = "";
|
|
24673
|
+
let replayReady = false;
|
|
24674
|
+
const updateReplayReady = async () => {
|
|
24675
|
+
try {
|
|
24676
|
+
const root = process.env.MCP_REPLAY_REQUEST_ROOT || `${process.env.PROJECT_CWD || process.cwd()}/data/mcp-replay-requests`;
|
|
24677
|
+
const heartbeat2 = JSON.parse(
|
|
24678
|
+
await (0, import_promises18.readFile)(`${root}/heartbeat.json`, "utf8")
|
|
24679
|
+
);
|
|
24680
|
+
replayReady = Number.isFinite(heartbeat2.observedAt) && Date.now() - heartbeat2.observedAt >= 0 && Date.now() - heartbeat2.observedAt < 12e4;
|
|
24681
|
+
} catch {
|
|
24682
|
+
replayReady = false;
|
|
24683
|
+
}
|
|
24684
|
+
};
|
|
24597
24685
|
const signalChild = (signal) => {
|
|
24598
24686
|
if (!child?.pid) return;
|
|
24599
24687
|
try {
|
|
@@ -24607,7 +24695,7 @@ var init_mcpWorker = __esm({
|
|
|
24607
24695
|
const heartbeatValue = () => ({
|
|
24608
24696
|
observedAt: Date.now(),
|
|
24609
24697
|
packageManifestSha256: manifestHash,
|
|
24610
|
-
replayAvailable:
|
|
24698
|
+
replayAvailable: replayReady
|
|
24611
24699
|
});
|
|
24612
24700
|
const stop = () => {
|
|
24613
24701
|
stopping = true;
|
|
@@ -24623,6 +24711,7 @@ var init_mcpWorker = __esm({
|
|
|
24623
24711
|
try {
|
|
24624
24712
|
if (!await import_redis15.mcpStorage.compare(leaseKey, owner, owner, LEASE_SECONDS))
|
|
24625
24713
|
throw new Error("Worker lease lost");
|
|
24714
|
+
await updateReplayReady();
|
|
24626
24715
|
await import_redis15.mcpStorage.put("worker:heartbeat", heartbeatValue(), LEASE_SECONDS);
|
|
24627
24716
|
} catch {
|
|
24628
24717
|
leaseLost = true;
|
|
@@ -24633,6 +24722,7 @@ var init_mcpWorker = __esm({
|
|
|
24633
24722
|
}, 2e3);
|
|
24634
24723
|
try {
|
|
24635
24724
|
manifestHash = await (0, import_mcp.mcpPackageManifestHash)();
|
|
24725
|
+
await updateReplayReady();
|
|
24636
24726
|
await import_redis15.mcpStorage.put("worker:heartbeat", heartbeatValue(), LEASE_SECONDS);
|
|
24637
24727
|
let cursor = "0";
|
|
24638
24728
|
do {
|
|
@@ -24697,7 +24787,7 @@ var init_mcpWorker = __esm({
|
|
|
24697
24787
|
);
|
|
24698
24788
|
continue;
|
|
24699
24789
|
}
|
|
24700
|
-
await (0,
|
|
24790
|
+
await (0, import_promises18.mkdir)((0, import_mcp.mcpJobDirectory)(started), { recursive: true });
|
|
24701
24791
|
if (started.kind === "backtest")
|
|
24702
24792
|
await (0, import_redis15.setDataStrict)(
|
|
24703
24793
|
import_redis15.redisKeys.backtestConfig(
|
|
@@ -24720,7 +24810,9 @@ var init_mcpWorker = __esm({
|
|
|
24720
24810
|
};
|
|
24721
24811
|
if (started.kind === "runtime-feedback-replay") {
|
|
24722
24812
|
for (const name of Object.keys(jobEnv)) {
|
|
24723
|
-
if (/secret|token|api.?key|private.?key|cookie|credential/i.test(
|
|
24813
|
+
if (/secret|password|token|api.?key|private.?key|cookie|credential/i.test(
|
|
24814
|
+
name
|
|
24815
|
+
))
|
|
24724
24816
|
delete jobEnv[name];
|
|
24725
24817
|
}
|
|
24726
24818
|
Object.assign(jobEnv, {
|
|
@@ -24733,7 +24825,35 @@ var init_mcpWorker = __esm({
|
|
|
24733
24825
|
TRADEJS_TIMESCALE_READ_ONLY: "true"
|
|
24734
24826
|
});
|
|
24735
24827
|
}
|
|
24736
|
-
|
|
24828
|
+
let command = {
|
|
24829
|
+
executable: process.execPath,
|
|
24830
|
+
args: [process.argv[1], ...started.args]
|
|
24831
|
+
};
|
|
24832
|
+
try {
|
|
24833
|
+
if (started.kind === "runtime-feedback-replay")
|
|
24834
|
+
command = await buildMcpReplayProcess({
|
|
24835
|
+
evidencePath: String(started.request.verifiedEvidencePath),
|
|
24836
|
+
outDir: (0, import_mcp.mcpJobDirectory)(started),
|
|
24837
|
+
runId: started.id,
|
|
24838
|
+
projectRoot: process.env.PROJECT_CWD || process.cwd(),
|
|
24839
|
+
env: process.env
|
|
24840
|
+
});
|
|
24841
|
+
} catch (error) {
|
|
24842
|
+
await import_redis15.mcpStorage.compare(
|
|
24843
|
+
jobKey,
|
|
24844
|
+
started,
|
|
24845
|
+
{
|
|
24846
|
+
...started,
|
|
24847
|
+
status: "failed",
|
|
24848
|
+
finishedAt: Date.now(),
|
|
24849
|
+
updatedAt: Date.now(),
|
|
24850
|
+
error: error instanceof Error ? error.message : "Replay preparation failed"
|
|
24851
|
+
},
|
|
24852
|
+
import_mcp.MCP_JOB_TTL
|
|
24853
|
+
);
|
|
24854
|
+
continue;
|
|
24855
|
+
}
|
|
24856
|
+
child = (0, import_node_child_process4.spawn)(command.executable, command.args, {
|
|
24737
24857
|
cwd: process.env.PROJECT_CWD || process.cwd(),
|
|
24738
24858
|
env: jobEnv,
|
|
24739
24859
|
detached: process.platform !== "win32",
|
|
@@ -25178,13 +25298,13 @@ var hyperliquidWhalesUpdate_exports = {};
|
|
|
25178
25298
|
__export(hyperliquidWhalesUpdate_exports, {
|
|
25179
25299
|
main: () => main29
|
|
25180
25300
|
});
|
|
25181
|
-
var import_config8, import_args21,
|
|
25301
|
+
var import_config8, import_args21, import_node_crypto10, import_strategies12, LEADERBOARD_URL, DAY_MS10, CANDIDATE_LIMIT, flags19, fingerprint, runConcurrent2, main29;
|
|
25182
25302
|
var init_hyperliquidWhalesUpdate = __esm({
|
|
25183
25303
|
"src/scripts/hyperliquidWhalesUpdate.ts"() {
|
|
25184
25304
|
"use strict";
|
|
25185
25305
|
import_config8 = require("dotenv/config");
|
|
25186
25306
|
import_args21 = __toESM(require("args"));
|
|
25187
|
-
|
|
25307
|
+
import_node_crypto10 = require("crypto");
|
|
25188
25308
|
import_strategies12 = require("@tradejs/node/strategies");
|
|
25189
25309
|
init_hyperliquidWhaleBackfill();
|
|
25190
25310
|
init_hyperliquidRateLimiter();
|
|
@@ -25198,7 +25318,7 @@ var init_hyperliquidWhalesUpdate = __esm({
|
|
|
25198
25318
|
);
|
|
25199
25319
|
import_args21.default.option(["d", "days"], "Calibration window in days", 7);
|
|
25200
25320
|
flags19 = import_args21.default.parse(process.argv);
|
|
25201
|
-
fingerprint = (addresses) => (0,
|
|
25321
|
+
fingerprint = (addresses) => (0, import_node_crypto10.createHash)("sha256").update(JSON.stringify(addresses)).digest("hex").slice(0, 16);
|
|
25202
25322
|
runConcurrent2 = async (params) => {
|
|
25203
25323
|
let nextIndex = 0;
|
|
25204
25324
|
await Promise.all(
|
|
@@ -25307,13 +25427,13 @@ var mlExport_exports = {};
|
|
|
25307
25427
|
__export(mlExport_exports, {
|
|
25308
25428
|
main: () => main30
|
|
25309
25429
|
});
|
|
25310
|
-
var import_args22, import_chalk37,
|
|
25430
|
+
var import_args22, import_chalk37, import_promises19, import_path8, import_ml, flags20, resolveRunScopedMlChunks, main30;
|
|
25311
25431
|
var init_mlExport = __esm({
|
|
25312
25432
|
"src/scripts/mlExport.ts"() {
|
|
25313
25433
|
"use strict";
|
|
25314
25434
|
import_args22 = __toESM(require("args"));
|
|
25315
25435
|
import_chalk37 = __toESM(require("chalk"));
|
|
25316
|
-
|
|
25436
|
+
import_promises19 = __toESM(require("fs/promises"));
|
|
25317
25437
|
import_path8 = __toESM(require("path"));
|
|
25318
25438
|
import_ml = require("@tradejs/infra/ml");
|
|
25319
25439
|
init_checkpoint();
|
|
@@ -25364,7 +25484,7 @@ var init_mlExport = __esm({
|
|
|
25364
25484
|
};
|
|
25365
25485
|
main30 = async () => {
|
|
25366
25486
|
const outDir = String(flags20.outDir || "data/ml/export");
|
|
25367
|
-
await
|
|
25487
|
+
await import_promises19.default.mkdir(outDir, { recursive: true });
|
|
25368
25488
|
const strategyName = await resolveExportStrategy({
|
|
25369
25489
|
explicitStrategy: String(flags20.strategy || ""),
|
|
25370
25490
|
outDir,
|
|
@@ -25409,7 +25529,7 @@ var init_mlExport = __esm({
|
|
|
25409
25529
|
const shouldDeleteChunks = !Boolean(flags20.keepChunks);
|
|
25410
25530
|
if (shouldDeleteChunks) {
|
|
25411
25531
|
for (const filePath of chunkFiles) {
|
|
25412
|
-
await
|
|
25532
|
+
await import_promises19.default.rm(filePath, { force: true });
|
|
25413
25533
|
}
|
|
25414
25534
|
}
|
|
25415
25535
|
console.log(import_chalk37.default.green(`Merged dataset saved: ${mergedPath}`));
|
|
@@ -25430,13 +25550,13 @@ var mlInspect_exports = {};
|
|
|
25430
25550
|
__export(mlInspect_exports, {
|
|
25431
25551
|
main: () => main31
|
|
25432
25552
|
});
|
|
25433
|
-
var import_args23, import_chalk38,
|
|
25553
|
+
var import_args23, import_chalk38, import_promises20, 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, main31;
|
|
25434
25554
|
var init_mlInspect = __esm({
|
|
25435
25555
|
"src/scripts/mlInspect.ts"() {
|
|
25436
25556
|
"use strict";
|
|
25437
25557
|
import_args23 = __toESM(require("args"));
|
|
25438
25558
|
import_chalk38 = __toESM(require("chalk"));
|
|
25439
|
-
|
|
25559
|
+
import_promises20 = __toESM(require("fs/promises"));
|
|
25440
25560
|
import_fs3 = require("fs");
|
|
25441
25561
|
import_path9 = __toESM(require("path"));
|
|
25442
25562
|
import_readline2 = __toESM(require("readline"));
|
|
@@ -25613,7 +25733,7 @@ var init_mlInspect = __esm({
|
|
|
25613
25733
|
};
|
|
25614
25734
|
findLatestDataset = async (params) => {
|
|
25615
25735
|
const { dir, strategy } = params;
|
|
25616
|
-
const entries = await
|
|
25736
|
+
const entries = await import_promises20.default.readdir(dir, { withFileTypes: true });
|
|
25617
25737
|
const strategyToken = strategy.trim().toLowerCase();
|
|
25618
25738
|
const files = entries.filter((entry) => entry.isFile()).map((entry) => entry.name).filter((name) => name.endsWith(".jsonl")).filter(
|
|
25619
25739
|
(name) => !name.includes(".train.") && !name.includes(".test.")
|
|
@@ -25625,7 +25745,7 @@ var init_mlInspect = __esm({
|
|
|
25625
25745
|
}
|
|
25626
25746
|
const withMtime = await Promise.all(
|
|
25627
25747
|
files.map(async (name) => {
|
|
25628
|
-
const stat = await
|
|
25748
|
+
const stat = await import_promises20.default.stat(import_path9.default.join(dir, name));
|
|
25629
25749
|
return { name, mtime: stat.mtimeMs };
|
|
25630
25750
|
})
|
|
25631
25751
|
);
|
|
@@ -25870,7 +25990,7 @@ var init_mlInspect = __esm({
|
|
|
25870
25990
|
const relToData = import_path9.default.relative(dataRoot, absDatasetPath);
|
|
25871
25991
|
const inputInContainer = `/app/data/${relToData}`;
|
|
25872
25992
|
const reportDir = import_path9.default.dirname(absDatasetPath);
|
|
25873
|
-
await
|
|
25993
|
+
await import_promises20.default.mkdir(reportDir, { recursive: true });
|
|
25874
25994
|
const reportPath = import_path9.default.join(
|
|
25875
25995
|
reportDir,
|
|
25876
25996
|
`${import_path9.default.basename(datasetPath, import_path9.default.extname(datasetPath))}.profile.html`
|
|
@@ -25966,12 +26086,12 @@ var mlTrainLatestSelect_exports = {};
|
|
|
25966
26086
|
__export(mlTrainLatestSelect_exports, {
|
|
25967
26087
|
main: () => main32
|
|
25968
26088
|
});
|
|
25969
|
-
var import_path10,
|
|
26089
|
+
var import_path10, import_promises21, 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_MS11, SPLIT_PROGRESS_EVERY, parseTimestampMs, scanMaxLabeledTimestampMs, scanMaxTrainTimestampMs, hashFileNameSha1, prepareTrainWindowFiles, main32;
|
|
25970
26090
|
var init_mlTrainLatestSelect = __esm({
|
|
25971
26091
|
"src/scripts/mlTrainLatestSelect.ts"() {
|
|
25972
26092
|
"use strict";
|
|
25973
26093
|
import_path10 = __toESM(require("path"));
|
|
25974
|
-
|
|
26094
|
+
import_promises21 = __toESM(require("fs/promises"));
|
|
25975
26095
|
import_fs4 = require("fs");
|
|
25976
26096
|
import_crypto2 = require("crypto");
|
|
25977
26097
|
import_child_process3 = require("child_process");
|
|
@@ -26100,7 +26220,7 @@ var init_mlTrainLatestSelect = __esm({
|
|
|
26100
26220
|
return defaultModel;
|
|
26101
26221
|
};
|
|
26102
26222
|
listDatasetFiles = async (dir, strategyName) => {
|
|
26103
|
-
const entries = await
|
|
26223
|
+
const entries = await import_promises21.default.readdir(dir, { withFileTypes: true });
|
|
26104
26224
|
const prefix = `ml-dataset-${toFileToken6(strategyName)}-`;
|
|
26105
26225
|
const legacyPrefix = "ml-dataset-";
|
|
26106
26226
|
const fileNames = entries.filter((entry) => entry.isFile()).map((entry) => entry.name);
|
|
@@ -26111,7 +26231,7 @@ var init_mlTrainLatestSelect = __esm({
|
|
|
26111
26231
|
).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."));
|
|
26112
26232
|
const withMtime = await Promise.all(
|
|
26113
26233
|
jsonlFiles.map(async (name) => {
|
|
26114
|
-
const stat = await
|
|
26234
|
+
const stat = await import_promises21.default.stat(import_path10.default.join(dir, name));
|
|
26115
26235
|
return { name, mtime: stat.mtimeMs };
|
|
26116
26236
|
})
|
|
26117
26237
|
);
|
|
@@ -26287,13 +26407,13 @@ var init_mlTrainLatestSelect = __esm({
|
|
|
26287
26407
|
const metaPath = import_path10.default.join(dir, `${parsed.name}.windows.${key}.meta.json`);
|
|
26288
26408
|
try {
|
|
26289
26409
|
const [metaRaw] = await Promise.all([
|
|
26290
|
-
|
|
26291
|
-
|
|
26292
|
-
|
|
26293
|
-
|
|
26410
|
+
import_promises21.default.readFile(metaPath, "utf8"),
|
|
26411
|
+
import_promises21.default.access(holdoutTrainPath),
|
|
26412
|
+
import_promises21.default.access(holdoutTestPath),
|
|
26413
|
+
import_promises21.default.access(prodPath),
|
|
26294
26414
|
...walkForwardFoldDefs.flatMap((entry) => [
|
|
26295
|
-
|
|
26296
|
-
|
|
26415
|
+
import_promises21.default.access(entry.trainPath),
|
|
26416
|
+
import_promises21.default.access(entry.testPath)
|
|
26297
26417
|
])
|
|
26298
26418
|
]);
|
|
26299
26419
|
const meta2 = JSON.parse(metaRaw);
|
|
@@ -26660,7 +26780,7 @@ var init_mlTrainLatestSelect = __esm({
|
|
|
26660
26780
|
},
|
|
26661
26781
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
26662
26782
|
};
|
|
26663
|
-
await
|
|
26783
|
+
await import_promises21.default.writeFile(metaPath, `${JSON.stringify(meta, null, 2)}
|
|
26664
26784
|
`, "utf8");
|
|
26665
26785
|
return {
|
|
26666
26786
|
holdoutTrainPath,
|
|
@@ -26718,7 +26838,7 @@ var init_mlTrainLatestSelect = __esm({
|
|
|
26718
26838
|
process.exit(1);
|
|
26719
26839
|
}
|
|
26720
26840
|
try {
|
|
26721
|
-
const inputStat = await
|
|
26841
|
+
const inputStat = await import_promises21.default.stat(inputPath);
|
|
26722
26842
|
const totalInputBytes = inputStat.size;
|
|
26723
26843
|
const autoIncrementalThresholdGb = asInt7(
|
|
26724
26844
|
process.env.ML_TRAIN_INCREMENTAL_THRESHOLD_GB,
|
|
@@ -26907,7 +27027,7 @@ var init_mlTrainLatestSelect = __esm({
|
|
|
26907
27027
|
const modelDir = import_path10.default.join(modelDirRoot, "models");
|
|
26908
27028
|
let savedModels = [];
|
|
26909
27029
|
try {
|
|
26910
|
-
const entries = await
|
|
27030
|
+
const entries = await import_promises21.default.readdir(modelDir, { withFileTypes: true });
|
|
26911
27031
|
savedModels = entries.filter((entry) => entry.isFile()).map((entry) => entry.name).filter(
|
|
26912
27032
|
(name) => name === `${selected}.joblib` || /^.+\.model\d+\.joblib$/.test(name)
|
|
26913
27033
|
).filter((name) => name.startsWith(`${selected}.`)).sort();
|
|
@@ -26929,7 +27049,7 @@ var init_mlTrainLatestSelect = __esm({
|
|
|
26929
27049
|
process.exitCode = finalCode;
|
|
26930
27050
|
} finally {
|
|
26931
27051
|
for (const file of cleanupFiles) {
|
|
26932
|
-
await
|
|
27052
|
+
await import_promises21.default.rm(file, { force: true });
|
|
26933
27053
|
}
|
|
26934
27054
|
}
|
|
26935
27055
|
process.exit(process.exitCode ?? 1);
|
|
@@ -26961,16 +27081,16 @@ __export(researchAuto_exports, {
|
|
|
26961
27081
|
toStrategyConfigGrid: () => toStrategyConfigGrid2,
|
|
26962
27082
|
trimTextTail: () => trimTextTail2
|
|
26963
27083
|
});
|
|
26964
|
-
var import_args25, import_chalk40, import_node_child_process5,
|
|
27084
|
+
var import_args25, import_chalk40, import_node_child_process5, import_promises22, import_node_os2, import_node_path15, import_constants18, import_ai8, import_logger6, import_redis16, 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, main33;
|
|
26965
27085
|
var init_researchAuto = __esm({
|
|
26966
27086
|
"src/scripts/researchAuto.ts"() {
|
|
26967
27087
|
"use strict";
|
|
26968
27088
|
import_args25 = __toESM(require("args"));
|
|
26969
27089
|
import_chalk40 = __toESM(require("chalk"));
|
|
26970
27090
|
import_node_child_process5 = require("child_process");
|
|
26971
|
-
|
|
27091
|
+
import_promises22 = __toESM(require("fs/promises"));
|
|
26972
27092
|
import_node_os2 = __toESM(require("os"));
|
|
26973
|
-
|
|
27093
|
+
import_node_path15 = __toESM(require("path"));
|
|
26974
27094
|
import_constants18 = require("@tradejs/core/constants");
|
|
26975
27095
|
import_ai8 = require("@tradejs/infra/ai");
|
|
26976
27096
|
import_logger6 = require("@tradejs/infra/logger");
|
|
@@ -27004,9 +27124,9 @@ var init_researchAuto = __esm({
|
|
|
27004
27124
|
flags23 = import_args25.default.parse(process.argv);
|
|
27005
27125
|
({ projectRoot: projectRoot8 } = resolveResearchRoots());
|
|
27006
27126
|
dotenvPath = String(
|
|
27007
|
-
process.env.DOTENV_CONFIG_PATH ||
|
|
27008
|
-
).trim() ||
|
|
27009
|
-
getResearchAutoLockPath = (userName3) =>
|
|
27127
|
+
process.env.DOTENV_CONFIG_PATH || import_node_path15.default.join(projectRoot8, ".env")
|
|
27128
|
+
).trim() || import_node_path15.default.join(projectRoot8, ".env");
|
|
27129
|
+
getResearchAutoLockPath = (userName3) => import_node_path15.default.join(
|
|
27010
27130
|
projectRoot8,
|
|
27011
27131
|
"data",
|
|
27012
27132
|
"cache",
|
|
@@ -27015,7 +27135,7 @@ var init_researchAuto = __esm({
|
|
|
27015
27135
|
);
|
|
27016
27136
|
readResearchAutoLock = async (lockPath) => {
|
|
27017
27137
|
try {
|
|
27018
|
-
const raw = await
|
|
27138
|
+
const raw = await import_promises22.default.readFile(lockPath, "utf8");
|
|
27019
27139
|
return JSON.parse(raw);
|
|
27020
27140
|
} catch {
|
|
27021
27141
|
return null;
|
|
@@ -27050,9 +27170,9 @@ var init_researchAuto = __esm({
|
|
|
27050
27170
|
startedAt,
|
|
27051
27171
|
argv: [...process.argv]
|
|
27052
27172
|
};
|
|
27053
|
-
await
|
|
27173
|
+
await import_promises22.default.mkdir(import_node_path15.default.dirname(lockPath), { recursive: true });
|
|
27054
27174
|
const writeLock = async () => {
|
|
27055
|
-
await
|
|
27175
|
+
await import_promises22.default.writeFile(lockPath, JSON.stringify(nextLock, null, 2), {
|
|
27056
27176
|
flag: "wx"
|
|
27057
27177
|
});
|
|
27058
27178
|
};
|
|
@@ -27071,7 +27191,7 @@ var init_researchAuto = __esm({
|
|
|
27071
27191
|
`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})`
|
|
27072
27192
|
);
|
|
27073
27193
|
}
|
|
27074
|
-
await
|
|
27194
|
+
await import_promises22.default.unlink(lockPath).catch(() => void 0);
|
|
27075
27195
|
await writeLock();
|
|
27076
27196
|
return lockPath;
|
|
27077
27197
|
};
|
|
@@ -27083,7 +27203,7 @@ var init_researchAuto = __esm({
|
|
|
27083
27203
|
if (existingLock && existingLock.pid !== process.pid) {
|
|
27084
27204
|
return;
|
|
27085
27205
|
}
|
|
27086
|
-
await
|
|
27206
|
+
await import_promises22.default.unlink(lockPath).catch(() => void 0);
|
|
27087
27207
|
};
|
|
27088
27208
|
resolvePositiveInteger = (value, fallback) => {
|
|
27089
27209
|
const parsed = Number.parseInt(String(value ?? ""), 10);
|
|
@@ -27185,9 +27305,9 @@ var init_researchAuto = __esm({
|
|
|
27185
27305
|
};
|
|
27186
27306
|
listMergedFiles3 = async (outDir, strategyName) => {
|
|
27187
27307
|
try {
|
|
27188
|
-
const entries = await
|
|
27308
|
+
const entries = await import_promises22.default.readdir(outDir);
|
|
27189
27309
|
const prefix = `ai-dataset-${(0, import_ai8.toFileToken)(strategyName)}-merged-`;
|
|
27190
|
-
return entries.filter((name) => name.startsWith(prefix) && name.endsWith(".jsonl")).sort().map((name) =>
|
|
27310
|
+
return entries.filter((name) => name.startsWith(prefix) && name.endsWith(".jsonl")).sort().map((name) => import_node_path15.default.join(outDir, name));
|
|
27191
27311
|
} catch {
|
|
27192
27312
|
return [];
|
|
27193
27313
|
}
|
|
@@ -27321,7 +27441,7 @@ var init_researchAuto = __esm({
|
|
|
27321
27441
|
return new Promise((resolve, reject) => {
|
|
27322
27442
|
const child = (0, import_node_child_process5.spawn)(
|
|
27323
27443
|
process.execPath,
|
|
27324
|
-
[
|
|
27444
|
+
[import_node_path15.default.resolve(process.argv[1]), params.command, ...params.args],
|
|
27325
27445
|
{
|
|
27326
27446
|
cwd: projectRoot8,
|
|
27327
27447
|
env,
|
|
@@ -27504,8 +27624,8 @@ var init_researchAuto = __esm({
|
|
|
27504
27624
|
const jsonOutput = Boolean(flags23.json);
|
|
27505
27625
|
const skipAgent = Boolean(flags23.skipAgent);
|
|
27506
27626
|
const outDirArg = String(flags23.outDir || "data/ai/export").trim() || "data/ai/export";
|
|
27507
|
-
const outDir =
|
|
27508
|
-
const cleanDirArg =
|
|
27627
|
+
const outDir = import_node_path15.default.resolve(projectRoot8, outDirArg);
|
|
27628
|
+
const cleanDirArg = import_node_path15.default.relative(import_node_path15.default.join(projectRoot8, "data"), outDir).replace(/\\/g, "/");
|
|
27509
27629
|
const target = await resolveTarget();
|
|
27510
27630
|
const runId = `${Date.now()}-${(0, import_ai8.toFileToken)(target.strategy)}`;
|
|
27511
27631
|
const run = {
|
|
@@ -27853,15 +27973,15 @@ var init_types = __esm({
|
|
|
27853
27973
|
function assert(condition, message) {
|
|
27854
27974
|
if (!condition) throw new Error(`Invalid core research spec: ${message}`);
|
|
27855
27975
|
}
|
|
27856
|
-
var
|
|
27976
|
+
var import_node_crypto11, import_node_fs3, import_promises23, import_backtest5, import_node_path16, RESEARCH_ID_RE, SHA256_RE, canonicalJson, sha256Text, sha256Json, sha256File, assertFinite, validateCoreResearchSpec, loadCoreResearchSpec, resolveCoreResearchPaths, writeJsonAtomic, buildLedgerRecordHash, readCoreResearchLedger, verifyCoreResearchLedger, appendCoreResearchLedger, validateCoreResearchParentLineage, prepareCoreResearch, verifyCoreResearchArtifacts, scanCoreResearchStages, writeCoreResearchStageIndex;
|
|
27857
27977
|
var init_io = __esm({
|
|
27858
27978
|
"src/lib/coreResearch/io.ts"() {
|
|
27859
27979
|
"use strict";
|
|
27860
|
-
|
|
27980
|
+
import_node_crypto11 = require("crypto");
|
|
27861
27981
|
import_node_fs3 = require("fs");
|
|
27862
|
-
|
|
27982
|
+
import_promises23 = __toESM(require("fs/promises"));
|
|
27863
27983
|
import_backtest5 = require("@tradejs/core/backtest");
|
|
27864
|
-
|
|
27984
|
+
import_node_path16 = __toESM(require("path"));
|
|
27865
27985
|
init_types();
|
|
27866
27986
|
RESEARCH_ID_RE = /^[a-z0-9][a-z0-9._-]{2,120}$/;
|
|
27867
27987
|
SHA256_RE = /^[a-f0-9]{64}$/;
|
|
@@ -27877,10 +27997,10 @@ var init_io = __esm({
|
|
|
27877
27997
|
};
|
|
27878
27998
|
return JSON.stringify(normalize(value));
|
|
27879
27999
|
};
|
|
27880
|
-
sha256Text = (value) => (0,
|
|
28000
|
+
sha256Text = (value) => (0, import_node_crypto11.createHash)("sha256").update(value).digest("hex");
|
|
27881
28001
|
sha256Json = (value) => sha256Text(canonicalJson(value));
|
|
27882
28002
|
sha256File = async (filePath) => {
|
|
27883
|
-
const hash = (0,
|
|
28003
|
+
const hash = (0, import_node_crypto11.createHash)("sha256");
|
|
27884
28004
|
const input = (0, import_node_fs3.createReadStream)(filePath);
|
|
27885
28005
|
for await (const chunk of input) hash.update(chunk);
|
|
27886
28006
|
return hash.digest("hex");
|
|
@@ -28120,40 +28240,40 @@ var init_io = __esm({
|
|
|
28120
28240
|
return spec;
|
|
28121
28241
|
};
|
|
28122
28242
|
loadCoreResearchSpec = async (specPath) => {
|
|
28123
|
-
const resolvedPath =
|
|
28124
|
-
const parsed = JSON.parse(await
|
|
28243
|
+
const resolvedPath = import_node_path16.default.resolve(specPath);
|
|
28244
|
+
const parsed = JSON.parse(await import_promises23.default.readFile(resolvedPath, "utf8"));
|
|
28125
28245
|
const spec = validateCoreResearchSpec(parsed);
|
|
28126
28246
|
return { resolvedPath, spec, specSha256: sha256Json(spec) };
|
|
28127
28247
|
};
|
|
28128
28248
|
resolveCoreResearchPaths = (spec) => {
|
|
28129
|
-
const rootDir =
|
|
28130
|
-
const researchDir =
|
|
28249
|
+
const rootDir = import_node_path16.default.resolve(spec.artifacts.rootDir);
|
|
28250
|
+
const researchDir = import_node_path16.default.join(rootDir, spec.researchId);
|
|
28131
28251
|
return {
|
|
28132
28252
|
rootDir,
|
|
28133
28253
|
researchDir,
|
|
28134
|
-
ledgerPath:
|
|
28135
|
-
specPath:
|
|
28136
|
-
manifestPath:
|
|
28137
|
-
resultPath:
|
|
28138
|
-
comparisonPath:
|
|
28139
|
-
matchesPath:
|
|
28140
|
-
tradesPath:
|
|
28141
|
-
reportPath:
|
|
28142
|
-
runLogDir:
|
|
28254
|
+
ledgerPath: import_node_path16.default.resolve(spec.artifacts.ledgerPath),
|
|
28255
|
+
specPath: import_node_path16.default.join(researchDir, "spec.json"),
|
|
28256
|
+
manifestPath: import_node_path16.default.join(researchDir, "manifest.json"),
|
|
28257
|
+
resultPath: import_node_path16.default.join(researchDir, "result.json"),
|
|
28258
|
+
comparisonPath: import_node_path16.default.join(researchDir, "comparison.json"),
|
|
28259
|
+
matchesPath: import_node_path16.default.join(researchDir, "matches.csv"),
|
|
28260
|
+
tradesPath: import_node_path16.default.join(researchDir, "trades.jsonl"),
|
|
28261
|
+
reportPath: import_node_path16.default.join(researchDir, "report.html"),
|
|
28262
|
+
runLogDir: import_node_path16.default.join(researchDir, "runs")
|
|
28143
28263
|
};
|
|
28144
28264
|
};
|
|
28145
28265
|
writeJsonAtomic = async (filePath, value) => {
|
|
28146
|
-
await
|
|
28266
|
+
await import_promises23.default.mkdir(import_node_path16.default.dirname(filePath), { recursive: true });
|
|
28147
28267
|
const temporaryPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
28148
|
-
await
|
|
28268
|
+
await import_promises23.default.writeFile(temporaryPath, `${canonicalJson(value)}
|
|
28149
28269
|
`, "utf8");
|
|
28150
|
-
await
|
|
28270
|
+
await import_promises23.default.rename(temporaryPath, filePath);
|
|
28151
28271
|
};
|
|
28152
28272
|
buildLedgerRecordHash = (record) => sha256Json(record);
|
|
28153
28273
|
readCoreResearchLedger = async (ledgerPath) => {
|
|
28154
28274
|
let text = "";
|
|
28155
28275
|
try {
|
|
28156
|
-
text = await
|
|
28276
|
+
text = await import_promises23.default.readFile(ledgerPath, "utf8");
|
|
28157
28277
|
} catch (error) {
|
|
28158
28278
|
if (error.code === "ENOENT") return [];
|
|
28159
28279
|
throw error;
|
|
@@ -28190,11 +28310,11 @@ var init_io = __esm({
|
|
|
28190
28310
|
};
|
|
28191
28311
|
appendCoreResearchLedger = async (params) => {
|
|
28192
28312
|
const { ledgerPath } = params;
|
|
28193
|
-
await
|
|
28313
|
+
await import_promises23.default.mkdir(import_node_path16.default.dirname(ledgerPath), { recursive: true });
|
|
28194
28314
|
const lockPath = `${ledgerPath}.lock`;
|
|
28195
28315
|
let lock = null;
|
|
28196
28316
|
try {
|
|
28197
|
-
lock = await
|
|
28317
|
+
lock = await import_promises23.default.open(lockPath, "wx");
|
|
28198
28318
|
const records = await readCoreResearchLedger(ledgerPath);
|
|
28199
28319
|
const verified = verifyCoreResearchLedger(records);
|
|
28200
28320
|
const payload = {
|
|
@@ -28213,7 +28333,7 @@ var init_io = __esm({
|
|
|
28213
28333
|
...payload,
|
|
28214
28334
|
recordHash: buildLedgerRecordHash(payload)
|
|
28215
28335
|
};
|
|
28216
|
-
await
|
|
28336
|
+
await import_promises23.default.appendFile(ledgerPath, `${canonicalJson(record)}
|
|
28217
28337
|
`, "utf8");
|
|
28218
28338
|
return record;
|
|
28219
28339
|
} catch (error) {
|
|
@@ -28223,20 +28343,20 @@ var init_io = __esm({
|
|
|
28223
28343
|
throw error;
|
|
28224
28344
|
} finally {
|
|
28225
28345
|
await lock?.close();
|
|
28226
|
-
await
|
|
28346
|
+
await import_promises23.default.rm(lockPath, { force: true });
|
|
28227
28347
|
}
|
|
28228
28348
|
};
|
|
28229
28349
|
validateCoreResearchParentLineage = async (spec) => {
|
|
28230
28350
|
if (spec.stage === "screen") return;
|
|
28231
28351
|
const expectedParentStage = spec.stage === "isolated_long" ? "screen" : "isolated_long";
|
|
28232
|
-
const rootDir =
|
|
28352
|
+
const rootDir = import_node_path16.default.resolve(spec.artifacts.rootDir);
|
|
28233
28353
|
const passedParentCandidateConfigShas = /* @__PURE__ */ new Set();
|
|
28234
28354
|
for (const parentResearchId of spec.parentResearchIds ?? []) {
|
|
28235
|
-
const parentDir =
|
|
28355
|
+
const parentDir = import_node_path16.default.join(rootDir, parentResearchId);
|
|
28236
28356
|
const [parentSpec, parentManifest, parentResult] = await Promise.all([
|
|
28237
|
-
|
|
28238
|
-
|
|
28239
|
-
|
|
28357
|
+
import_promises23.default.readFile(import_node_path16.default.join(parentDir, "spec.json"), "utf8").then((text) => JSON.parse(text)),
|
|
28358
|
+
import_promises23.default.readFile(import_node_path16.default.join(parentDir, "manifest.json"), "utf8").then((text) => JSON.parse(text)),
|
|
28359
|
+
import_promises23.default.readFile(import_node_path16.default.join(parentDir, "result.json"), "utf8").then((text) => JSON.parse(text))
|
|
28240
28360
|
]);
|
|
28241
28361
|
validateCoreResearchSpec(parentSpec);
|
|
28242
28362
|
if (parentManifest.status !== "completed") {
|
|
@@ -28283,12 +28403,12 @@ var init_io = __esm({
|
|
|
28283
28403
|
await validateCoreResearchParentLineage(spec);
|
|
28284
28404
|
const specSha256 = sha256Json(spec);
|
|
28285
28405
|
const paths = resolveCoreResearchPaths(spec);
|
|
28286
|
-
await
|
|
28406
|
+
await import_promises23.default.mkdir(paths.researchDir, { recursive: true });
|
|
28287
28407
|
let existing = null;
|
|
28288
28408
|
let existingManifest = null;
|
|
28289
28409
|
try {
|
|
28290
28410
|
existing = JSON.parse(
|
|
28291
|
-
await
|
|
28411
|
+
await import_promises23.default.readFile(paths.specPath, "utf8")
|
|
28292
28412
|
);
|
|
28293
28413
|
} catch (error) {
|
|
28294
28414
|
if (error.code !== "ENOENT") throw error;
|
|
@@ -28301,7 +28421,7 @@ var init_io = __esm({
|
|
|
28301
28421
|
if (existing) {
|
|
28302
28422
|
try {
|
|
28303
28423
|
existingManifest = JSON.parse(
|
|
28304
|
-
await
|
|
28424
|
+
await import_promises23.default.readFile(paths.manifestPath, "utf8")
|
|
28305
28425
|
);
|
|
28306
28426
|
} catch (error) {
|
|
28307
28427
|
if (error.code !== "ENOENT") throw error;
|
|
@@ -28340,7 +28460,7 @@ var init_io = __esm({
|
|
|
28340
28460
|
verifyCoreResearchArtifacts = async (spec) => {
|
|
28341
28461
|
const paths = resolveCoreResearchPaths(spec);
|
|
28342
28462
|
const manifest = JSON.parse(
|
|
28343
|
-
await
|
|
28463
|
+
await import_promises23.default.readFile(paths.manifestPath, "utf8")
|
|
28344
28464
|
);
|
|
28345
28465
|
if (manifest.specSha256 !== sha256Json(spec)) {
|
|
28346
28466
|
throw new Error("Manifest spec hash does not match the supplied spec");
|
|
@@ -28349,7 +28469,7 @@ var init_io = __esm({
|
|
|
28349
28469
|
manifest.artifactHashes
|
|
28350
28470
|
)) {
|
|
28351
28471
|
const actualHash = await sha256File(
|
|
28352
|
-
|
|
28472
|
+
import_node_path16.default.join(paths.researchDir, relativePath)
|
|
28353
28473
|
);
|
|
28354
28474
|
if (actualHash !== expectedHash) {
|
|
28355
28475
|
throw new Error(`Artifact hash mismatch: ${relativePath}`);
|
|
@@ -28365,10 +28485,10 @@ var init_io = __esm({
|
|
|
28365
28485
|
};
|
|
28366
28486
|
};
|
|
28367
28487
|
scanCoreResearchStages = async (rootDir) => {
|
|
28368
|
-
const resolvedRoot =
|
|
28488
|
+
const resolvedRoot = import_node_path16.default.resolve(rootDir);
|
|
28369
28489
|
let entries = [];
|
|
28370
28490
|
try {
|
|
28371
|
-
entries = await
|
|
28491
|
+
entries = await import_promises23.default.readdir(resolvedRoot);
|
|
28372
28492
|
} catch (error) {
|
|
28373
28493
|
if (error.code === "ENOENT") {
|
|
28374
28494
|
return {
|
|
@@ -28383,15 +28503,15 @@ var init_io = __esm({
|
|
|
28383
28503
|
for (const entry of entries.sort(
|
|
28384
28504
|
(left, right) => left < right ? -1 : left > right ? 1 : 0
|
|
28385
28505
|
)) {
|
|
28386
|
-
const researchDir =
|
|
28387
|
-
const stats = await
|
|
28506
|
+
const researchDir = import_node_path16.default.join(resolvedRoot, entry);
|
|
28507
|
+
const stats = await import_promises23.default.stat(researchDir);
|
|
28388
28508
|
if (!stats.isDirectory()) continue;
|
|
28389
28509
|
let spec;
|
|
28390
28510
|
let manifest;
|
|
28391
28511
|
try {
|
|
28392
28512
|
[spec, manifest] = await Promise.all([
|
|
28393
|
-
|
|
28394
|
-
|
|
28513
|
+
import_promises23.default.readFile(import_node_path16.default.join(researchDir, "spec.json"), "utf8").then((text) => JSON.parse(text)),
|
|
28514
|
+
import_promises23.default.readFile(import_node_path16.default.join(researchDir, "manifest.json"), "utf8").then((text) => JSON.parse(text))
|
|
28395
28515
|
]);
|
|
28396
28516
|
} catch (error) {
|
|
28397
28517
|
if (error.code === "ENOENT") continue;
|
|
@@ -28401,7 +28521,7 @@ var init_io = __esm({
|
|
|
28401
28521
|
if (manifest.specSha256 !== sha256Json(spec)) {
|
|
28402
28522
|
throw new Error(`Stage index found a spec hash mismatch for ${entry}`);
|
|
28403
28523
|
}
|
|
28404
|
-
const result = manifest.status === "completed" ? await
|
|
28524
|
+
const result = manifest.status === "completed" ? await import_promises23.default.readFile(import_node_path16.default.join(researchDir, "result.json"), "utf8").then((text) => JSON.parse(text)) : null;
|
|
28405
28525
|
familyByResearch.set(spec.researchId, spec.hypothesis.family);
|
|
28406
28526
|
experiments.push({
|
|
28407
28527
|
researchId: spec.researchId,
|
|
@@ -28432,7 +28552,7 @@ var init_io = __esm({
|
|
|
28432
28552
|
return { experiments, familyByResearch };
|
|
28433
28553
|
};
|
|
28434
28554
|
writeCoreResearchStageIndex = async (rootDir) => {
|
|
28435
|
-
const resolvedRoot =
|
|
28555
|
+
const resolvedRoot = import_node_path16.default.resolve(rootDir);
|
|
28436
28556
|
const { experiments, familyByResearch } = await scanCoreResearchStages(resolvedRoot);
|
|
28437
28557
|
const grouped = /* @__PURE__ */ new Map();
|
|
28438
28558
|
for (const experiment of experiments) {
|
|
@@ -28449,21 +28569,21 @@ var init_io = __esm({
|
|
|
28449
28569
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
28450
28570
|
families: [...grouped.entries()].sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0).map(([family, experiments2]) => ({ family, experiments: experiments2 }))
|
|
28451
28571
|
};
|
|
28452
|
-
await writeJsonAtomic(
|
|
28572
|
+
await writeJsonAtomic(import_node_path16.default.join(resolvedRoot, "index.json"), index);
|
|
28453
28573
|
return index;
|
|
28454
28574
|
};
|
|
28455
28575
|
}
|
|
28456
28576
|
});
|
|
28457
28577
|
|
|
28458
28578
|
// src/lib/coreResearch/artifacts.ts
|
|
28459
|
-
var import_node_fs4, import_node_events,
|
|
28579
|
+
var import_node_fs4, import_node_events, import_promises24, import_node_path17, csv, writeLine, closeOutput, writeCoreResearchMatches, writeCoreResearchTrades;
|
|
28460
28580
|
var init_artifacts = __esm({
|
|
28461
28581
|
"src/lib/coreResearch/artifacts.ts"() {
|
|
28462
28582
|
"use strict";
|
|
28463
28583
|
import_node_fs4 = require("fs");
|
|
28464
28584
|
import_node_events = require("events");
|
|
28465
|
-
|
|
28466
|
-
|
|
28585
|
+
import_promises24 = __toESM(require("fs/promises"));
|
|
28586
|
+
import_node_path17 = __toESM(require("path"));
|
|
28467
28587
|
init_io();
|
|
28468
28588
|
csv = (value) => {
|
|
28469
28589
|
const text = String(value ?? "");
|
|
@@ -28477,7 +28597,7 @@ var init_artifacts = __esm({
|
|
|
28477
28597
|
await (0, import_node_events.once)(output, "close");
|
|
28478
28598
|
};
|
|
28479
28599
|
writeCoreResearchMatches = async (params) => {
|
|
28480
|
-
await
|
|
28600
|
+
await import_promises24.default.mkdir(import_node_path17.default.dirname(params.filePath), { recursive: true });
|
|
28481
28601
|
const output = (0, import_node_fs4.createWriteStream)(params.filePath, { encoding: "utf8" });
|
|
28482
28602
|
await writeLine(
|
|
28483
28603
|
output,
|
|
@@ -28528,7 +28648,7 @@ var init_artifacts = __esm({
|
|
|
28528
28648
|
await closeOutput(output);
|
|
28529
28649
|
};
|
|
28530
28650
|
writeCoreResearchTrades = async (params) => {
|
|
28531
|
-
await
|
|
28651
|
+
await import_promises24.default.mkdir(import_node_path17.default.dirname(params.filePath), { recursive: true });
|
|
28532
28652
|
const output = (0, import_node_fs4.createWriteStream)(params.filePath, { encoding: "utf8" });
|
|
28533
28653
|
for (const variant of params.variants) {
|
|
28534
28654
|
for (const trade of variant.trades) {
|
|
@@ -28768,14 +28888,14 @@ var init_rules = __esm({
|
|
|
28768
28888
|
});
|
|
28769
28889
|
|
|
28770
28890
|
// src/lib/coreResearch/statistics.ts
|
|
28771
|
-
var
|
|
28891
|
+
var import_node_crypto12, createSeededRandom, percentile, calendarClusterBootstrap, applyHolmCorrection, inverseNormalCdf, erf, normalCdf, deflatedSharpeDiagnostic, combinations, probabilityOfBacktestOverfitting;
|
|
28772
28892
|
var init_statistics = __esm({
|
|
28773
28893
|
"src/lib/coreResearch/statistics.ts"() {
|
|
28774
28894
|
"use strict";
|
|
28775
|
-
|
|
28895
|
+
import_node_crypto12 = require("crypto");
|
|
28776
28896
|
init_metrics();
|
|
28777
28897
|
createSeededRandom = (seedText) => {
|
|
28778
|
-
const digest = (0,
|
|
28898
|
+
const digest = (0, import_node_crypto12.createHash)("sha256").update(seedText).digest();
|
|
28779
28899
|
let state = digest.readUInt32LE(0) || 1;
|
|
28780
28900
|
return () => {
|
|
28781
28901
|
state ^= state << 13;
|
|
@@ -29242,13 +29362,13 @@ var init_comparison = __esm({
|
|
|
29242
29362
|
});
|
|
29243
29363
|
|
|
29244
29364
|
// src/lib/coreResearch/dataset.ts
|
|
29245
|
-
var
|
|
29365
|
+
var import_node_crypto13, import_node_fs5, import_node_path18, import_node_readline2, asRecord4, finiteNumber4, normalizeDirection, findStrategySetupIdentity, classifyBreadth, classifyDerivatives, resolveCoreResearchRegime, normalizeCompletedTrade, completedTradeIdentity, positionCycleIdentity, sumBy, weightedPrice, aggregatePositionCycles, compareText, compareTrades, readCoreResearchVariant;
|
|
29246
29366
|
var init_dataset2 = __esm({
|
|
29247
29367
|
"src/lib/coreResearch/dataset.ts"() {
|
|
29248
29368
|
"use strict";
|
|
29249
|
-
|
|
29369
|
+
import_node_crypto13 = require("crypto");
|
|
29250
29370
|
import_node_fs5 = require("fs");
|
|
29251
|
-
|
|
29371
|
+
import_node_path18 = __toESM(require("path"));
|
|
29252
29372
|
import_node_readline2 = __toESM(require("readline"));
|
|
29253
29373
|
asRecord4 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
29254
29374
|
finiteNumber4 = (value, field) => {
|
|
@@ -29344,7 +29464,7 @@ var init_dataset2 = __esm({
|
|
|
29344
29464
|
};
|
|
29345
29465
|
};
|
|
29346
29466
|
normalizeCompletedTrade = (params) => {
|
|
29347
|
-
const { filePath, fileSha256, lineNumber, row } = params;
|
|
29467
|
+
const { filePath, fileSha256: fileSha2562, lineNumber, row } = params;
|
|
29348
29468
|
const result = row.tradeResult;
|
|
29349
29469
|
if (!result) return null;
|
|
29350
29470
|
const signalTimestamp = finiteNumber4(row.timestamp, "row.timestamp");
|
|
@@ -29359,7 +29479,7 @@ var init_dataset2 = __esm({
|
|
|
29359
29479
|
return {
|
|
29360
29480
|
sourceFile: filePath,
|
|
29361
29481
|
sourceLine: lineNumber,
|
|
29362
|
-
sourceSha256:
|
|
29482
|
+
sourceSha256: fileSha2562,
|
|
29363
29483
|
runId: row.backtestRunId ?? null,
|
|
29364
29484
|
configId: row.configId?.trim() || "<missing-config-id>",
|
|
29365
29485
|
signalId,
|
|
@@ -29459,9 +29579,9 @@ var init_dataset2 = __esm({
|
|
|
29459
29579
|
const seen = /* @__PURE__ */ new Map();
|
|
29460
29580
|
let duplicateRowsDropped = 0;
|
|
29461
29581
|
for (const inputPath of variant.files) {
|
|
29462
|
-
const filePath =
|
|
29582
|
+
const filePath = import_node_path18.default.resolve(inputPath);
|
|
29463
29583
|
const input = (0, import_node_fs5.createReadStream)(filePath);
|
|
29464
|
-
const hash = (0,
|
|
29584
|
+
const hash = (0, import_node_crypto13.createHash)("sha256");
|
|
29465
29585
|
input.on("data", (chunk) => hash.update(chunk));
|
|
29466
29586
|
const lines = import_node_readline2.default.createInterface({ input, crlfDelay: Infinity });
|
|
29467
29587
|
const fileTrades = [];
|
|
@@ -29512,11 +29632,11 @@ var init_dataset2 = __esm({
|
|
|
29512
29632
|
trades.push(trade);
|
|
29513
29633
|
fileTrades.push(trade);
|
|
29514
29634
|
}
|
|
29515
|
-
const
|
|
29516
|
-
for (const trade of fileTrades) trade.sourceSha256 =
|
|
29635
|
+
const fileSha2562 = hash.digest("hex");
|
|
29636
|
+
for (const trade of fileTrades) trade.sourceSha256 = fileSha2562;
|
|
29517
29637
|
sources.push({
|
|
29518
29638
|
path: filePath,
|
|
29519
|
-
sha256:
|
|
29639
|
+
sha256: fileSha2562,
|
|
29520
29640
|
rows,
|
|
29521
29641
|
selectedTrades,
|
|
29522
29642
|
rowsForDifferentRun,
|
|
@@ -29951,19 +30071,19 @@ var init_selection = __esm({
|
|
|
29951
30071
|
});
|
|
29952
30072
|
|
|
29953
30073
|
// src/lib/coreResearch/trace.ts
|
|
29954
|
-
var
|
|
30074
|
+
var import_promises25, import_node_path19, summarizeCoreResearchTrace;
|
|
29955
30075
|
var init_trace = __esm({
|
|
29956
30076
|
"src/lib/coreResearch/trace.ts"() {
|
|
29957
30077
|
"use strict";
|
|
29958
|
-
|
|
29959
|
-
|
|
30078
|
+
import_promises25 = __toESM(require("fs/promises"));
|
|
30079
|
+
import_node_path19 = __toESM(require("path"));
|
|
29960
30080
|
summarizeCoreResearchTrace = async (filePaths = []) => {
|
|
29961
30081
|
const events = /* @__PURE__ */ Object.create(null);
|
|
29962
30082
|
const skipCounts = /* @__PURE__ */ Object.create(null);
|
|
29963
30083
|
const exitCodes = /* @__PURE__ */ Object.create(null);
|
|
29964
30084
|
for (const inputPath of filePaths) {
|
|
29965
|
-
const filePath =
|
|
29966
|
-
const text = await
|
|
30085
|
+
const filePath = import_node_path19.default.resolve(inputPath);
|
|
30086
|
+
const text = await import_promises25.default.readFile(filePath, "utf8");
|
|
29967
30087
|
for (const [index, line] of text.split("\n").entries()) {
|
|
29968
30088
|
if (!line.trim()) continue;
|
|
29969
30089
|
let event;
|
|
@@ -30003,14 +30123,14 @@ var init_trace = __esm({
|
|
|
30003
30123
|
});
|
|
30004
30124
|
|
|
30005
30125
|
// src/lib/coreResearch/orchestrator.ts
|
|
30006
|
-
var
|
|
30126
|
+
var import_promises26, import_node_path20, import_node_child_process6, import_node_crypto14, import_coreResearch, summarizeSupplementalFiles, analyzeCoreResearchPrepared, analyzeCoreResearch, createCoreResearchSpecTemplate, runCommand2, commandValue, commandHas, validateCoreResearchRunCommand, runCoreResearch;
|
|
30007
30127
|
var init_orchestrator = __esm({
|
|
30008
30128
|
"src/lib/coreResearch/orchestrator.ts"() {
|
|
30009
30129
|
"use strict";
|
|
30010
|
-
|
|
30011
|
-
|
|
30130
|
+
import_promises26 = __toESM(require("fs/promises"));
|
|
30131
|
+
import_node_path20 = __toESM(require("path"));
|
|
30012
30132
|
import_node_child_process6 = require("child_process");
|
|
30013
|
-
|
|
30133
|
+
import_node_crypto14 = require("crypto");
|
|
30014
30134
|
import_coreResearch = require("@tradejs/infra/coreResearch");
|
|
30015
30135
|
init_artifacts();
|
|
30016
30136
|
init_io();
|
|
@@ -30215,7 +30335,7 @@ var init_orchestrator = __esm({
|
|
|
30215
30335
|
const primarySourceHashes = Object.fromEntries(
|
|
30216
30336
|
analyses.flatMap(
|
|
30217
30337
|
(analysis) => analysis.files.map((file) => [
|
|
30218
|
-
|
|
30338
|
+
import_node_path20.default.relative(paths.researchDir, file.path),
|
|
30219
30339
|
file.sha256
|
|
30220
30340
|
])
|
|
30221
30341
|
)
|
|
@@ -30234,8 +30354,8 @@ var init_orchestrator = __esm({
|
|
|
30234
30354
|
const supplementalSourceHashes = Object.fromEntries(
|
|
30235
30355
|
await Promise.all(
|
|
30236
30356
|
supplementalSourcePaths.map(async (filePath) => [
|
|
30237
|
-
|
|
30238
|
-
await sha256File(
|
|
30357
|
+
import_node_path20.default.relative(paths.researchDir, import_node_path20.default.resolve(filePath)),
|
|
30358
|
+
await sha256File(import_node_path20.default.resolve(filePath))
|
|
30239
30359
|
])
|
|
30240
30360
|
)
|
|
30241
30361
|
);
|
|
@@ -30299,7 +30419,7 @@ var init_orchestrator = __esm({
|
|
|
30299
30419
|
const tradesByVariant = new Map(
|
|
30300
30420
|
windowed.map((entry) => [entry.variant.id, entry.trades])
|
|
30301
30421
|
);
|
|
30302
|
-
await
|
|
30422
|
+
await import_promises26.default.writeFile(
|
|
30303
30423
|
paths.reportPath,
|
|
30304
30424
|
buildCoreResearchHtml({ spec, result, tradesByVariant }),
|
|
30305
30425
|
"utf8"
|
|
@@ -30312,17 +30432,17 @@ var init_orchestrator = __esm({
|
|
|
30312
30432
|
"trades.jsonl": await sha256File(paths.tradesPath),
|
|
30313
30433
|
"report.html": await sha256File(paths.reportPath)
|
|
30314
30434
|
};
|
|
30315
|
-
const resolvedRunsPath =
|
|
30435
|
+
const resolvedRunsPath = import_node_path20.default.join(paths.researchDir, "resolved-runs.json");
|
|
30316
30436
|
try {
|
|
30317
30437
|
artifactHashes["resolved-runs.json"] = await sha256File(resolvedRunsPath);
|
|
30318
30438
|
} catch (error) {
|
|
30319
30439
|
if (error.code !== "ENOENT") throw error;
|
|
30320
30440
|
}
|
|
30321
30441
|
try {
|
|
30322
|
-
for (const name of await
|
|
30442
|
+
for (const name of await import_promises26.default.readdir(paths.runLogDir)) {
|
|
30323
30443
|
if (!name.endsWith(".log")) continue;
|
|
30324
30444
|
artifactHashes[`runs/${name}`] = await sha256File(
|
|
30325
|
-
|
|
30445
|
+
import_node_path20.default.join(paths.runLogDir, name)
|
|
30326
30446
|
);
|
|
30327
30447
|
}
|
|
30328
30448
|
} catch (error) {
|
|
@@ -30379,9 +30499,9 @@ var init_orchestrator = __esm({
|
|
|
30379
30499
|
}
|
|
30380
30500
|
};
|
|
30381
30501
|
createCoreResearchSpecTemplate = (params) => {
|
|
30382
|
-
const rootDir =
|
|
30383
|
-
|
|
30384
|
-
|
|
30502
|
+
const rootDir = import_node_path20.default.relative(
|
|
30503
|
+
import_node_path20.default.resolve(params.projectRoot),
|
|
30504
|
+
import_node_path20.default.join(import_node_path20.default.resolve(params.projectRoot), "data", "research", "core")
|
|
30385
30505
|
).replace(/\\/g, "/");
|
|
30386
30506
|
const lineage = (() => {
|
|
30387
30507
|
try {
|
|
@@ -30412,7 +30532,7 @@ var init_orchestrator = __esm({
|
|
|
30412
30532
|
gitSha,
|
|
30413
30533
|
...sourceRepository ? { sourceRepository } : {},
|
|
30414
30534
|
...dirtyDiff ? {
|
|
30415
|
-
dirtyDiffSha256: (0,
|
|
30535
|
+
dirtyDiffSha256: (0, import_node_crypto14.createHash)("sha256").update(dirtyDiff).digest("hex")
|
|
30416
30536
|
} : {}
|
|
30417
30537
|
};
|
|
30418
30538
|
} catch {
|
|
@@ -30519,7 +30639,7 @@ var init_orchestrator = __esm({
|
|
|
30519
30639
|
};
|
|
30520
30640
|
runCommand2 = async (params) => {
|
|
30521
30641
|
if (!params.command.length) throw new Error("Cannot run an empty command");
|
|
30522
|
-
await
|
|
30642
|
+
await import_promises26.default.mkdir(import_node_path20.default.dirname(params.logPath), { recursive: true });
|
|
30523
30643
|
const chunks = [];
|
|
30524
30644
|
const child = (0, import_node_child_process6.spawn)(params.command[0], params.command.slice(1), {
|
|
30525
30645
|
cwd: params.cwd,
|
|
@@ -30539,7 +30659,7 @@ var init_orchestrator = __esm({
|
|
|
30539
30659
|
child.once("close", (code) => resolve(code ?? 1));
|
|
30540
30660
|
});
|
|
30541
30661
|
const output = chunks.join("");
|
|
30542
|
-
await
|
|
30662
|
+
await import_promises26.default.writeFile(params.logPath, output, "utf8");
|
|
30543
30663
|
if (exitCode !== 0) {
|
|
30544
30664
|
throw new Error(
|
|
30545
30665
|
`Command failed with exit ${exitCode}: ${params.command.join(" ")}`
|
|
@@ -30593,7 +30713,7 @@ var init_orchestrator = __esm({
|
|
|
30593
30713
|
};
|
|
30594
30714
|
runCoreResearch = async (params) => {
|
|
30595
30715
|
const { spec } = params;
|
|
30596
|
-
const cwd =
|
|
30716
|
+
const cwd = import_node_path20.default.resolve(params.cwd ?? process.cwd());
|
|
30597
30717
|
const prepared = await prepareCoreResearch(spec);
|
|
30598
30718
|
const resolvedVariants = [];
|
|
30599
30719
|
for (const variant of spec.variants) {
|
|
@@ -30611,7 +30731,7 @@ var init_orchestrator = __esm({
|
|
|
30611
30731
|
artifactHashes: { variant: sha256Json(variant) }
|
|
30612
30732
|
});
|
|
30613
30733
|
let runId = "";
|
|
30614
|
-
const backtestLogPath =
|
|
30734
|
+
const backtestLogPath = import_node_path20.default.join(
|
|
30615
30735
|
prepared.paths.runLogDir,
|
|
30616
30736
|
`${variant.id}-backtest.log`
|
|
30617
30737
|
);
|
|
@@ -30627,7 +30747,7 @@ var init_orchestrator = __esm({
|
|
|
30627
30747
|
env: {
|
|
30628
30748
|
PROJECT_CWD: cwd,
|
|
30629
30749
|
...params.sourceRepositoryRoot ? {
|
|
30630
|
-
[SOURCE_REPOSITORY_ROOT_ENV]:
|
|
30750
|
+
[SOURCE_REPOSITORY_ROOT_ENV]: import_node_path20.default.resolve(
|
|
30631
30751
|
params.sourceRepositoryRoot
|
|
30632
30752
|
)
|
|
30633
30753
|
} : {}
|
|
@@ -30642,12 +30762,12 @@ var init_orchestrator = __esm({
|
|
|
30642
30762
|
if (!runId) {
|
|
30643
30763
|
throw new Error(`Backtest for ${variant.id} did not report a run id`);
|
|
30644
30764
|
}
|
|
30645
|
-
const exportLogPath =
|
|
30765
|
+
const exportLogPath = import_node_path20.default.join(
|
|
30646
30766
|
prepared.paths.runLogDir,
|
|
30647
30767
|
`${variant.id}-export.log`
|
|
30648
30768
|
);
|
|
30649
30769
|
const exportParts = [];
|
|
30650
|
-
const cliPath =
|
|
30770
|
+
const cliPath = import_node_path20.default.resolve(process.argv[1]);
|
|
30651
30771
|
await runCommand2({
|
|
30652
30772
|
command: [
|
|
30653
30773
|
process.execPath,
|
|
@@ -30667,14 +30787,14 @@ var init_orchestrator = __esm({
|
|
|
30667
30787
|
env: {
|
|
30668
30788
|
PROJECT_CWD: cwd,
|
|
30669
30789
|
...params.sourceRepositoryRoot ? {
|
|
30670
|
-
[SOURCE_REPOSITORY_ROOT_ENV]:
|
|
30790
|
+
[SOURCE_REPOSITORY_ROOT_ENV]: import_node_path20.default.resolve(
|
|
30671
30791
|
params.sourceRepositoryRoot
|
|
30672
30792
|
)
|
|
30673
30793
|
} : {}
|
|
30674
30794
|
},
|
|
30675
30795
|
onLine: (line) => {
|
|
30676
30796
|
const match = line.match(/^part\d+:\s+(.+)$/);
|
|
30677
|
-
if (match) exportParts.push(
|
|
30797
|
+
if (match) exportParts.push(import_node_path20.default.resolve(cwd, match[1].trim()));
|
|
30678
30798
|
}
|
|
30679
30799
|
});
|
|
30680
30800
|
if (!exportParts.length) {
|
|
@@ -30685,7 +30805,7 @@ var init_orchestrator = __esm({
|
|
|
30685
30805
|
const traceFiles = await (0, import_coreResearch.listCoreResearchTraceFiles)({
|
|
30686
30806
|
strategyName: spec.strategy,
|
|
30687
30807
|
runId,
|
|
30688
|
-
outDir:
|
|
30808
|
+
outDir: import_node_path20.default.resolve(cwd, "data/research/core/trace")
|
|
30689
30809
|
});
|
|
30690
30810
|
resolvedVariants.push({
|
|
30691
30811
|
...variant,
|
|
@@ -30705,7 +30825,7 @@ var init_orchestrator = __esm({
|
|
|
30705
30825
|
...Object.fromEntries(
|
|
30706
30826
|
await Promise.all(
|
|
30707
30827
|
exportParts.map(async (filePath) => [
|
|
30708
|
-
|
|
30828
|
+
import_node_path20.default.basename(filePath),
|
|
30709
30829
|
await sha256File(filePath)
|
|
30710
30830
|
])
|
|
30711
30831
|
)
|
|
@@ -30724,7 +30844,7 @@ var init_orchestrator = __esm({
|
|
|
30724
30844
|
}
|
|
30725
30845
|
}
|
|
30726
30846
|
await writeJsonAtomic(
|
|
30727
|
-
|
|
30847
|
+
import_node_path20.default.join(prepared.paths.researchDir, "resolved-runs.json"),
|
|
30728
30848
|
{
|
|
30729
30849
|
schema: "tradejs-core-research-resolved-runs/v1",
|
|
30730
30850
|
researchId: spec.researchId,
|
|
@@ -30744,12 +30864,12 @@ var coreResearch_exports = {};
|
|
|
30744
30864
|
__export(coreResearch_exports, {
|
|
30745
30865
|
main: () => main34
|
|
30746
30866
|
});
|
|
30747
|
-
var
|
|
30867
|
+
var import_promises27, import_node_path21, import_chalk41, valueAfter, required, parseTimestamp, readSymbols, printUsage, main34;
|
|
30748
30868
|
var init_coreResearch = __esm({
|
|
30749
30869
|
"src/scripts/coreResearch.ts"() {
|
|
30750
30870
|
"use strict";
|
|
30751
|
-
|
|
30752
|
-
|
|
30871
|
+
import_promises27 = __toESM(require("fs/promises"));
|
|
30872
|
+
import_node_path21 = __toESM(require("path"));
|
|
30753
30873
|
import_chalk41 = __toESM(require("chalk"));
|
|
30754
30874
|
init_io();
|
|
30755
30875
|
init_orchestrator();
|
|
@@ -30773,7 +30893,7 @@ var init_coreResearch = __esm({
|
|
|
30773
30893
|
const symbolsFile = valueAfter(argv2, "--symbolsFile");
|
|
30774
30894
|
if (symbolsFile) {
|
|
30775
30895
|
const parsed = JSON.parse(
|
|
30776
|
-
await
|
|
30896
|
+
await import_promises27.default.readFile(import_node_path21.default.resolve(projectRoot18, symbolsFile), "utf8")
|
|
30777
30897
|
);
|
|
30778
30898
|
if (!Array.isArray(parsed) || parsed.some((symbol) => typeof symbol !== "string")) {
|
|
30779
30899
|
throw new Error("--symbolsFile must contain a JSON string array");
|
|
@@ -30804,14 +30924,14 @@ The run command executes only variants with an explicit command[] in the preregi
|
|
|
30804
30924
|
return;
|
|
30805
30925
|
}
|
|
30806
30926
|
if (command === "index") {
|
|
30807
|
-
const rootDir =
|
|
30927
|
+
const rootDir = import_node_path21.default.resolve(
|
|
30808
30928
|
roots.projectRoot,
|
|
30809
30929
|
required(valueAfter(argv2, "--root"), "--root")
|
|
30810
30930
|
);
|
|
30811
30931
|
const index = await writeCoreResearchStageIndex(rootDir);
|
|
30812
30932
|
console.log(
|
|
30813
30933
|
import_chalk41.default.green(
|
|
30814
|
-
`Core research index: ${
|
|
30934
|
+
`Core research index: ${import_node_path21.default.join(rootDir, "index.json")} (${index.families.length} families)`
|
|
30815
30935
|
)
|
|
30816
30936
|
);
|
|
30817
30937
|
return;
|
|
@@ -30820,7 +30940,7 @@ The run command executes only variants with an explicit command[] in the preregi
|
|
|
30820
30940
|
projectRoot: roots.projectRoot
|
|
30821
30941
|
});
|
|
30822
30942
|
if (command === "init") {
|
|
30823
|
-
const outputPath =
|
|
30943
|
+
const outputPath = import_node_path21.default.resolve(
|
|
30824
30944
|
roots.projectRoot,
|
|
30825
30945
|
required(valueAfter(argv2, "--out"), "--out")
|
|
30826
30946
|
);
|
|
@@ -30844,7 +30964,7 @@ The run command executes only variants with an explicit command[] in the preregi
|
|
|
30844
30964
|
);
|
|
30845
30965
|
return;
|
|
30846
30966
|
}
|
|
30847
|
-
const specPath =
|
|
30967
|
+
const specPath = import_node_path21.default.resolve(
|
|
30848
30968
|
roots.projectRoot,
|
|
30849
30969
|
required(valueAfter(argv2, "--spec"), "--spec")
|
|
30850
30970
|
);
|
|
@@ -31498,12 +31618,12 @@ __export(replayRuntimeEvidence_exports, {
|
|
|
31498
31618
|
replayRuntimeEvidence: () => replayRuntimeEvidence,
|
|
31499
31619
|
summarizeReplayComparison: () => summarizeReplayComparison
|
|
31500
31620
|
});
|
|
31501
|
-
var
|
|
31621
|
+
var import_promises28, import_node_path22, import_args27, import_chalk43, import_redis19, toEpochMs2, resolveWindow, parseStrategyFilter, asRecord5, asArray2, sum, groupCount, compactMatched, resolveItemStrategy, summarizeReplayComparison, loadReplayResult, getReplayStrategies, loadRuntimePayload, replayRuntimeEvidence, main36;
|
|
31502
31622
|
var init_replayRuntimeEvidence = __esm({
|
|
31503
31623
|
"src/scripts/replayRuntimeEvidence.ts"() {
|
|
31504
31624
|
"use strict";
|
|
31505
|
-
|
|
31506
|
-
|
|
31625
|
+
import_promises28 = __toESM(require("fs/promises"));
|
|
31626
|
+
import_node_path22 = __toESM(require("path"));
|
|
31507
31627
|
import_args27 = __toESM(require("args"));
|
|
31508
31628
|
import_chalk43 = __toESM(require("chalk"));
|
|
31509
31629
|
import_redis19 = require("@tradejs/infra/redis");
|
|
@@ -31762,10 +31882,10 @@ var init_replayRuntimeEvidence = __esm({
|
|
|
31762
31882
|
runtimeEvidenceFile,
|
|
31763
31883
|
projectRoot: projectRoot18
|
|
31764
31884
|
}) => {
|
|
31765
|
-
const runtimeEvidencePath = typeof runtimeEvidenceFile === "string" && runtimeEvidenceFile.trim() ?
|
|
31885
|
+
const runtimeEvidencePath = typeof runtimeEvidenceFile === "string" && runtimeEvidenceFile.trim() ? import_node_path22.default.resolve(projectRoot18, runtimeEvidenceFile.trim()) : null;
|
|
31766
31886
|
if (runtimeEvidencePath) {
|
|
31767
31887
|
const artifact = JSON.parse(
|
|
31768
|
-
await
|
|
31888
|
+
await import_promises28.default.readFile(runtimeEvidencePath, "utf8")
|
|
31769
31889
|
);
|
|
31770
31890
|
return {
|
|
31771
31891
|
source: "file",
|
|
@@ -31851,9 +31971,9 @@ var init_replayRuntimeEvidence = __esm({
|
|
|
31851
31971
|
},
|
|
31852
31972
|
runtime: runtime.payload
|
|
31853
31973
|
};
|
|
31854
|
-
const outPath =
|
|
31855
|
-
await
|
|
31856
|
-
await
|
|
31974
|
+
const outPath = import_node_path22.default.resolve(projectRoot18, String(flags35.out));
|
|
31975
|
+
await import_promises28.default.mkdir(import_node_path22.default.dirname(outPath), { recursive: true });
|
|
31976
|
+
await import_promises28.default.writeFile(outPath, `${JSON.stringify(artifact, null, 2)}
|
|
31857
31977
|
`, "utf8");
|
|
31858
31978
|
console.log(import_chalk43.default.green(`Wrote ${outPath}`));
|
|
31859
31979
|
console.log(
|
|
@@ -31875,15 +31995,6 @@ var init_replayRuntimeEvidence = __esm({
|
|
|
31875
31995
|
}
|
|
31876
31996
|
});
|
|
31877
31997
|
|
|
31878
|
-
// src/lib/runtimeEvidenceArtifacts.ts
|
|
31879
|
-
var runtimeEvidenceArtifacts_exports = {};
|
|
31880
|
-
var init_runtimeEvidenceArtifacts = __esm({
|
|
31881
|
-
"src/lib/runtimeEvidenceArtifacts.ts"() {
|
|
31882
|
-
"use strict";
|
|
31883
|
-
__reExport(runtimeEvidenceArtifacts_exports, require("@tradejs/node/diagnostics"));
|
|
31884
|
-
}
|
|
31885
|
-
});
|
|
31886
|
-
|
|
31887
31998
|
// src/lib/runtimeEvidenceProducer.ts
|
|
31888
31999
|
var runtimeEvidenceProducer_exports = {};
|
|
31889
32000
|
var init_runtimeEvidenceProducer = __esm({
|
|
@@ -31903,13 +32014,13 @@ var init_runtimeFeedbackArtifacts = __esm({
|
|
|
31903
32014
|
});
|
|
31904
32015
|
|
|
31905
32016
|
// src/lib/runtimeFeedbackReplay.ts
|
|
31906
|
-
var import_node_child_process7,
|
|
32017
|
+
var import_node_child_process7, import_promises29, import_node_path23, REQUIRED_ENV, FORBIDDEN_SECRET_ENV, unsafeRedisHosts, safeSegment, assertRuntimeFeedbackReplaySafety, buildRuntimeFeedbackReplayCommands, runLoggedCommand, runRuntimeFeedbackReplay;
|
|
31907
32018
|
var init_runtimeFeedbackReplay = __esm({
|
|
31908
32019
|
"src/lib/runtimeFeedbackReplay.ts"() {
|
|
31909
32020
|
"use strict";
|
|
31910
32021
|
import_node_child_process7 = require("child_process");
|
|
31911
|
-
|
|
31912
|
-
|
|
32022
|
+
import_promises29 = __toESM(require("fs/promises"));
|
|
32023
|
+
import_node_path23 = __toESM(require("path"));
|
|
31913
32024
|
init_runtimeEvidenceDeployment();
|
|
31914
32025
|
init_runtimeEvidenceArtifacts();
|
|
31915
32026
|
init_runtimeEvidenceProducer();
|
|
@@ -32096,9 +32207,9 @@ $ ${[executable, ...command].join(" ")}
|
|
|
32096
32207
|
throw new Error("Cannot resolve the TradeJS CLI executable path");
|
|
32097
32208
|
}
|
|
32098
32209
|
const runtimeEvidenceBundle = await (0, runtimeEvidenceArtifacts_exports.verifyRuntimeEvidenceBundle)(
|
|
32099
|
-
|
|
32210
|
+
import_node_path23.default.dirname(runtimeEvidencePath)
|
|
32100
32211
|
);
|
|
32101
|
-
if (
|
|
32212
|
+
if (import_node_path23.default.resolve(runtimeEvidenceBundle.payloadPath) !== runtimeEvidencePath) {
|
|
32102
32213
|
throw new Error(
|
|
32103
32214
|
`Runtime evidence must be the verified bundle payload: ${runtimeEvidenceBundle.payloadPath}`
|
|
32104
32215
|
);
|
|
@@ -32125,16 +32236,16 @@ $ ${[executable, ...command].join(" ")}
|
|
|
32125
32236
|
if (!intervals.size) {
|
|
32126
32237
|
throw new Error("Runtime feedback replay requires an active interval");
|
|
32127
32238
|
}
|
|
32128
|
-
await
|
|
32129
|
-
const existing = await
|
|
32239
|
+
await import_promises29.default.mkdir(outDir, { recursive: true });
|
|
32240
|
+
const existing = await import_promises29.default.readdir(outDir);
|
|
32130
32241
|
if (existing.length) {
|
|
32131
32242
|
throw new Error(
|
|
32132
32243
|
`Runtime feedback output directory must be empty: ${outDir}`
|
|
32133
32244
|
);
|
|
32134
32245
|
}
|
|
32135
|
-
const replayEvidencePath =
|
|
32136
|
-
const logHandle = await
|
|
32137
|
-
|
|
32246
|
+
const replayEvidencePath = import_node_path23.default.join(outDir, runtimeFeedbackArtifacts_exports.RUNTIME_FEEDBACK_REPLAY_FILE);
|
|
32247
|
+
const logHandle = await import_promises29.default.open(
|
|
32248
|
+
import_node_path23.default.join(outDir, runtimeFeedbackArtifacts_exports.RUNTIME_FEEDBACK_LOG_FILE),
|
|
32138
32249
|
"wx"
|
|
32139
32250
|
);
|
|
32140
32251
|
const commands = buildRuntimeFeedbackReplayCommands({
|
|
@@ -32176,11 +32287,11 @@ __export(runtimeFeedbackReplay_exports, {
|
|
|
32176
32287
|
main: () => main37,
|
|
32177
32288
|
runtimeFeedbackReplay: () => runtimeFeedbackReplay
|
|
32178
32289
|
});
|
|
32179
|
-
var
|
|
32290
|
+
var import_node_path24, import_args28, import_chalk44, flags25, projectRoot9, runtimeFeedbackReplay, main37;
|
|
32180
32291
|
var init_runtimeFeedbackReplay2 = __esm({
|
|
32181
32292
|
"src/scripts/runtimeFeedbackReplay.ts"() {
|
|
32182
32293
|
"use strict";
|
|
32183
|
-
|
|
32294
|
+
import_node_path24 = __toESM(require("path"));
|
|
32184
32295
|
import_args28 = __toESM(require("args"));
|
|
32185
32296
|
import_chalk44 = __toESM(require("chalk"));
|
|
32186
32297
|
init_runtimeFeedbackReplay();
|
|
@@ -32198,8 +32309,8 @@ var init_runtimeFeedbackReplay2 = __esm({
|
|
|
32198
32309
|
);
|
|
32199
32310
|
}
|
|
32200
32311
|
const verified = await runRuntimeFeedbackReplay({
|
|
32201
|
-
runtimeEvidencePath:
|
|
32202
|
-
outDir:
|
|
32312
|
+
runtimeEvidencePath: import_node_path24.default.resolve(projectRoot9, runtimeEvidence2),
|
|
32313
|
+
outDir: import_node_path24.default.resolve(projectRoot9, outDir),
|
|
32203
32314
|
runId: String(flags25.runId ?? "").trim() || void 0,
|
|
32204
32315
|
projectRoot: projectRoot9
|
|
32205
32316
|
});
|
|
@@ -32357,11 +32468,11 @@ __export(runtimeFeedbackNotify_exports, {
|
|
|
32357
32468
|
main: () => main38,
|
|
32358
32469
|
runtimeFeedbackNotify: () => runtimeFeedbackNotify
|
|
32359
32470
|
});
|
|
32360
|
-
var
|
|
32471
|
+
var import_node_path25, import_args29, import_chalk45, flags26, projectRoot10, runtimeFeedbackNotify, main38;
|
|
32361
32472
|
var init_runtimeFeedbackNotify = __esm({
|
|
32362
32473
|
"src/scripts/runtimeFeedbackNotify.ts"() {
|
|
32363
32474
|
"use strict";
|
|
32364
|
-
|
|
32475
|
+
import_node_path25 = __toESM(require("path"));
|
|
32365
32476
|
import_args29 = __toESM(require("args"));
|
|
32366
32477
|
import_chalk45 = __toESM(require("chalk"));
|
|
32367
32478
|
init_runtimeFeedbackNotification();
|
|
@@ -32375,7 +32486,7 @@ var init_runtimeFeedbackNotify = __esm({
|
|
|
32375
32486
|
if (!bundle) {
|
|
32376
32487
|
throw new Error("Provide --bundle for runtime feedback notification.");
|
|
32377
32488
|
}
|
|
32378
|
-
const bundleDir =
|
|
32489
|
+
const bundleDir = import_node_path25.default.resolve(projectRoot10, bundle);
|
|
32379
32490
|
if (flags26.dryRun) {
|
|
32380
32491
|
const verified = await (0, runtimeFeedbackArtifacts_exports.verifyRuntimeFeedbackReplayBundle)(bundleDir);
|
|
32381
32492
|
console.log(buildRuntimeFeedbackTelegramMessage(verified.replayEvidence));
|
|
@@ -32391,13 +32502,13 @@ var init_runtimeFeedbackNotify = __esm({
|
|
|
32391
32502
|
});
|
|
32392
32503
|
|
|
32393
32504
|
// src/lib/runtimeEvidenceSync.ts
|
|
32394
|
-
var import_node_child_process8,
|
|
32505
|
+
var import_node_child_process8, import_promises30, import_node_path26, import_node_util, execFileAsync, isExistingDestinationError, safeSegment2, withTrailingSlash, dateParts, buildRuntimeEvidenceRsyncArgs, receiptPath, compareBundles, listPendingRuntimeEvidenceBundles, markRuntimeEvidenceBundleProcessed, syncRuntimeEvidenceBundles;
|
|
32395
32506
|
var init_runtimeEvidenceSync = __esm({
|
|
32396
32507
|
"src/lib/runtimeEvidenceSync.ts"() {
|
|
32397
32508
|
"use strict";
|
|
32398
32509
|
import_node_child_process8 = require("child_process");
|
|
32399
|
-
|
|
32400
|
-
|
|
32510
|
+
import_promises30 = __toESM(require("fs/promises"));
|
|
32511
|
+
import_node_path26 = __toESM(require("path"));
|
|
32401
32512
|
import_node_util = require("util");
|
|
32402
32513
|
init_runtimeEvidenceArtifacts();
|
|
32403
32514
|
init_runtimeEvidenceDeployment();
|
|
@@ -32431,15 +32542,15 @@ var init_runtimeEvidenceSync = __esm({
|
|
|
32431
32542
|
withTrailingSlash(source),
|
|
32432
32543
|
withTrailingSlash(destination)
|
|
32433
32544
|
];
|
|
32434
|
-
receiptPath = (receiptsRoot, artifactId) =>
|
|
32545
|
+
receiptPath = (receiptsRoot, artifactId) => import_node_path26.default.join(receiptsRoot, `${safeSegment2(artifactId, "artifact")}.json`);
|
|
32435
32546
|
compareBundles = (left, right) => left.manifest.window.endTime - right.manifest.window.endTime || left.manifest.createdAt - right.manifest.createdAt;
|
|
32436
32547
|
listPendingRuntimeEvidenceBundles = async ({
|
|
32437
32548
|
evidenceRoot,
|
|
32438
32549
|
deploymentId
|
|
32439
32550
|
}) => {
|
|
32440
32551
|
const safeDeploymentId = safeSegment2(deploymentId, "production");
|
|
32441
|
-
const artifactsRoot =
|
|
32442
|
-
const receiptsRoot =
|
|
32552
|
+
const artifactsRoot = import_node_path26.default.join(evidenceRoot, "artifacts", safeDeploymentId);
|
|
32553
|
+
const receiptsRoot = import_node_path26.default.join(evidenceRoot, "receipts", safeDeploymentId);
|
|
32443
32554
|
const bundles = await (0, runtimeEvidenceArtifacts_exports.discoverRuntimeEvidenceBundles)(artifactsRoot);
|
|
32444
32555
|
const pending = [];
|
|
32445
32556
|
for (const bundleDir of bundles) {
|
|
@@ -32447,7 +32558,7 @@ var init_runtimeEvidenceSync = __esm({
|
|
|
32447
32558
|
if (verified.manifest.deploymentId !== safeDeploymentId) continue;
|
|
32448
32559
|
(0, runtimeEvidenceDeployment_exports.assertCurrentRuntimeEvidenceArtifact)(verified.artifact);
|
|
32449
32560
|
try {
|
|
32450
|
-
await
|
|
32561
|
+
await import_promises30.default.access(receiptPath(receiptsRoot, verified.manifest.artifactId));
|
|
32451
32562
|
continue;
|
|
32452
32563
|
} catch (error) {
|
|
32453
32564
|
if (error.code !== "ENOENT") throw error;
|
|
@@ -32470,7 +32581,7 @@ var init_runtimeEvidenceSync = __esm({
|
|
|
32470
32581
|
`Artifact deployment mismatch: expected ${safeDeploymentId}, received ${verified.manifest.deploymentId}`
|
|
32471
32582
|
);
|
|
32472
32583
|
}
|
|
32473
|
-
const receiptsRoot =
|
|
32584
|
+
const receiptsRoot = import_node_path26.default.join(evidenceRoot, "receipts", safeDeploymentId);
|
|
32474
32585
|
const finalPath = receiptPath(receiptsRoot, verified.manifest.artifactId);
|
|
32475
32586
|
const temporaryPath = `${finalPath}.tmp-${process.pid}`;
|
|
32476
32587
|
const receipt = {
|
|
@@ -32484,14 +32595,14 @@ var init_runtimeEvidenceSync = __esm({
|
|
|
32484
32595
|
replayEvidenceSha256: runtimeFeedback.replayEvidenceSha256
|
|
32485
32596
|
} : {}
|
|
32486
32597
|
};
|
|
32487
|
-
await
|
|
32488
|
-
await
|
|
32598
|
+
await import_promises30.default.mkdir(receiptsRoot, { recursive: true });
|
|
32599
|
+
await import_promises30.default.writeFile(
|
|
32489
32600
|
temporaryPath,
|
|
32490
32601
|
`${JSON.stringify(receipt, null, 2)}
|
|
32491
32602
|
`,
|
|
32492
32603
|
"utf8"
|
|
32493
32604
|
);
|
|
32494
|
-
await
|
|
32605
|
+
await import_promises30.default.rename(temporaryPath, finalPath);
|
|
32495
32606
|
return finalPath;
|
|
32496
32607
|
};
|
|
32497
32608
|
syncRuntimeEvidenceBundles = async ({
|
|
@@ -32506,11 +32617,11 @@ var init_runtimeEvidenceSync = __esm({
|
|
|
32506
32617
|
}
|
|
32507
32618
|
}) => {
|
|
32508
32619
|
const safeDeploymentId = safeSegment2(deploymentId, "production");
|
|
32509
|
-
const inboxRoot =
|
|
32510
|
-
const artifactsRoot =
|
|
32620
|
+
const inboxRoot = import_node_path26.default.join(evidenceRoot, "inbox", safeDeploymentId);
|
|
32621
|
+
const artifactsRoot = import_node_path26.default.join(evidenceRoot, "artifacts", safeDeploymentId);
|
|
32511
32622
|
await Promise.all([
|
|
32512
|
-
|
|
32513
|
-
|
|
32623
|
+
import_promises30.default.mkdir(inboxRoot, { recursive: true }),
|
|
32624
|
+
import_promises30.default.mkdir(artifactsRoot, { recursive: true })
|
|
32514
32625
|
]);
|
|
32515
32626
|
const rsyncArgs = buildRuntimeEvidenceRsyncArgs({
|
|
32516
32627
|
source,
|
|
@@ -32527,14 +32638,14 @@ var init_runtimeEvidenceSync = __esm({
|
|
|
32527
32638
|
);
|
|
32528
32639
|
}
|
|
32529
32640
|
(0, runtimeEvidenceDeployment_exports.assertCurrentRuntimeEvidenceArtifact)(verified.artifact);
|
|
32530
|
-
const destinationDir =
|
|
32641
|
+
const destinationDir = import_node_path26.default.join(
|
|
32531
32642
|
artifactsRoot,
|
|
32532
32643
|
...dateParts(verified.manifest.window.endTime),
|
|
32533
32644
|
safeSegment2(verified.manifest.artifactId, "artifact")
|
|
32534
32645
|
);
|
|
32535
|
-
await
|
|
32646
|
+
await import_promises30.default.mkdir(import_node_path26.default.dirname(destinationDir), { recursive: true });
|
|
32536
32647
|
try {
|
|
32537
|
-
await
|
|
32648
|
+
await import_promises30.default.rename(bundleDir, destinationDir);
|
|
32538
32649
|
} catch (error) {
|
|
32539
32650
|
if (!isExistingDestinationError(error)) throw error;
|
|
32540
32651
|
const existing = await (0, runtimeEvidenceArtifacts_exports.verifyRuntimeEvidenceBundle)(destinationDir);
|
|
@@ -32543,7 +32654,7 @@ var init_runtimeEvidenceSync = __esm({
|
|
|
32543
32654
|
`Conflicting runtime evidence artifact ${verified.manifest.artifactId}`
|
|
32544
32655
|
);
|
|
32545
32656
|
}
|
|
32546
|
-
await
|
|
32657
|
+
await import_promises30.default.rm(bundleDir, { recursive: true, force: true });
|
|
32547
32658
|
}
|
|
32548
32659
|
received.push(await (0, runtimeEvidenceArtifacts_exports.verifyRuntimeEvidenceBundle)(destinationDir));
|
|
32549
32660
|
}
|
|
@@ -32563,13 +32674,13 @@ var init_runtimeEvidenceSync = __esm({
|
|
|
32563
32674
|
});
|
|
32564
32675
|
|
|
32565
32676
|
// src/lib/runtimeFeedbackSync.ts
|
|
32566
|
-
var import_node_child_process9,
|
|
32677
|
+
var import_node_child_process9, import_promises31, import_node_path27, import_node_util2, execFileAsync2, isExistingDestinationError2, safeSegment3, dateParts2, syncRuntimeFeedbackReplayBundles;
|
|
32567
32678
|
var init_runtimeFeedbackSync = __esm({
|
|
32568
32679
|
"src/lib/runtimeFeedbackSync.ts"() {
|
|
32569
32680
|
"use strict";
|
|
32570
32681
|
import_node_child_process9 = require("child_process");
|
|
32571
|
-
|
|
32572
|
-
|
|
32682
|
+
import_promises31 = __toESM(require("fs/promises"));
|
|
32683
|
+
import_node_path27 = __toESM(require("path"));
|
|
32573
32684
|
import_node_util2 = require("util");
|
|
32574
32685
|
init_runtimeFeedbackArtifacts();
|
|
32575
32686
|
init_runtimeEvidenceSync();
|
|
@@ -32602,11 +32713,11 @@ var init_runtimeFeedbackSync = __esm({
|
|
|
32602
32713
|
}
|
|
32603
32714
|
}) => {
|
|
32604
32715
|
const safeDeploymentId = safeSegment3(deploymentId, "production");
|
|
32605
|
-
const inboxRoot =
|
|
32606
|
-
const artifactsRoot =
|
|
32716
|
+
const inboxRoot = import_node_path27.default.join(feedbackRoot, "inbox", safeDeploymentId);
|
|
32717
|
+
const artifactsRoot = import_node_path27.default.join(feedbackRoot, "artifacts", safeDeploymentId);
|
|
32607
32718
|
await Promise.all([
|
|
32608
|
-
|
|
32609
|
-
|
|
32719
|
+
import_promises31.default.mkdir(inboxRoot, { recursive: true }),
|
|
32720
|
+
import_promises31.default.mkdir(artifactsRoot, { recursive: true })
|
|
32610
32721
|
]);
|
|
32611
32722
|
const rsyncArgs = buildRuntimeEvidenceRsyncArgs({
|
|
32612
32723
|
source,
|
|
@@ -32622,15 +32733,15 @@ var init_runtimeFeedbackSync = __esm({
|
|
|
32622
32733
|
`Runtime feedback deployment mismatch: expected ${safeDeploymentId}, received ${verified.manifest.deploymentId}`
|
|
32623
32734
|
);
|
|
32624
32735
|
}
|
|
32625
|
-
const destinationDir =
|
|
32736
|
+
const destinationDir = import_node_path27.default.join(
|
|
32626
32737
|
artifactsRoot,
|
|
32627
32738
|
...dateParts2(verified.manifest.window.endTime),
|
|
32628
32739
|
safeSegment3(verified.manifest.runtimeEvidence.artifactId, "artifact"),
|
|
32629
32740
|
safeSegment3(verified.manifest.runId, "run")
|
|
32630
32741
|
);
|
|
32631
|
-
await
|
|
32742
|
+
await import_promises31.default.mkdir(import_node_path27.default.dirname(destinationDir), { recursive: true });
|
|
32632
32743
|
try {
|
|
32633
|
-
await
|
|
32744
|
+
await import_promises31.default.rename(bundleDir, destinationDir);
|
|
32634
32745
|
} catch (error) {
|
|
32635
32746
|
if (!isExistingDestinationError2(error)) throw error;
|
|
32636
32747
|
const existing = await (0, runtimeFeedbackArtifacts_exports.verifyRuntimeFeedbackReplayBundle)(destinationDir);
|
|
@@ -32639,7 +32750,7 @@ var init_runtimeFeedbackSync = __esm({
|
|
|
32639
32750
|
`Conflicting runtime feedback replay ${verified.manifest.artifactId}`
|
|
32640
32751
|
);
|
|
32641
32752
|
}
|
|
32642
|
-
await
|
|
32753
|
+
await import_promises31.default.rm(bundleDir, { recursive: true, force: true });
|
|
32643
32754
|
}
|
|
32644
32755
|
received.push(await (0, runtimeFeedbackArtifacts_exports.verifyRuntimeFeedbackReplayBundle)(destinationDir));
|
|
32645
32756
|
}
|
|
@@ -32659,11 +32770,11 @@ __export(runtimeFeedbackSync_exports, {
|
|
|
32659
32770
|
main: () => main39,
|
|
32660
32771
|
runtimeFeedbackSync: () => runtimeFeedbackSync
|
|
32661
32772
|
});
|
|
32662
|
-
var
|
|
32773
|
+
var import_node_path28, import_args30, import_chalk46, flags27, projectRoot11, runtimeFeedbackSync, main39;
|
|
32663
32774
|
var init_runtimeFeedbackSync2 = __esm({
|
|
32664
32775
|
"src/scripts/runtimeFeedbackSync.ts"() {
|
|
32665
32776
|
"use strict";
|
|
32666
|
-
|
|
32777
|
+
import_node_path28 = __toESM(require("path"));
|
|
32667
32778
|
import_args30 = __toESM(require("args"));
|
|
32668
32779
|
import_chalk46 = __toESM(require("chalk"));
|
|
32669
32780
|
init_runtimeFeedbackSync();
|
|
@@ -32691,7 +32802,7 @@ var init_runtimeFeedbackSync2 = __esm({
|
|
|
32691
32802
|
"Provide --source or RUNTIME_FEEDBACK_RSYNC_SOURCE for runtime feedback sync."
|
|
32692
32803
|
);
|
|
32693
32804
|
}
|
|
32694
|
-
const feedbackRoot =
|
|
32805
|
+
const feedbackRoot = import_node_path28.default.resolve(projectRoot11, String(flags27.dir));
|
|
32695
32806
|
const result = await syncRuntimeFeedbackReplayBundles({
|
|
32696
32807
|
source,
|
|
32697
32808
|
feedbackRoot,
|
|
@@ -32723,13 +32834,13 @@ var init_runtimeFeedbackSync2 = __esm({
|
|
|
32723
32834
|
});
|
|
32724
32835
|
|
|
32725
32836
|
// src/lib/runtimeEvidenceCompositionSnapshots.ts
|
|
32726
|
-
var
|
|
32837
|
+
var import_node_crypto15, import_promises32, import_node_path29, SNAPSHOT_FILE, MANIFEST_FILE, COMPLETE_FILE, createRuntimeEvidenceCompositionSnapshotRecorder, isRecord2, sha256, safeSegment4, isExistingDestinationError3, parseManifest, verifyRuntimeEvidenceCompositionSnapshot, sameSnapshot, publishRuntimeEvidenceCompositionSnapshot, captureRuntimeEvidenceCompositionSnapshot, discoverRuntimeEvidenceCompositionSnapshots;
|
|
32727
32838
|
var init_runtimeEvidenceCompositionSnapshots = __esm({
|
|
32728
32839
|
"src/lib/runtimeEvidenceCompositionSnapshots.ts"() {
|
|
32729
32840
|
"use strict";
|
|
32730
|
-
|
|
32731
|
-
|
|
32732
|
-
|
|
32841
|
+
import_node_crypto15 = require("crypto");
|
|
32842
|
+
import_promises32 = __toESM(require("fs/promises"));
|
|
32843
|
+
import_node_path29 = __toESM(require("path"));
|
|
32733
32844
|
init_runtimeEvidenceDeployment();
|
|
32734
32845
|
init_runtimeEvidenceProducer();
|
|
32735
32846
|
SNAPSHOT_FILE = "snapshot.json";
|
|
@@ -32750,7 +32861,7 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
|
|
|
32750
32861
|
};
|
|
32751
32862
|
};
|
|
32752
32863
|
isRecord2 = (value) => value != null && typeof value === "object" && !Array.isArray(value);
|
|
32753
|
-
sha256 = (value) => (0,
|
|
32864
|
+
sha256 = (value) => (0, import_node_crypto15.createHash)("sha256").update(value).digest("hex");
|
|
32754
32865
|
safeSegment4 = (value, label) => {
|
|
32755
32866
|
const normalized = value.trim();
|
|
32756
32867
|
if (!normalized || !/^[a-zA-Z0-9._:-]+$/.test(normalized)) {
|
|
@@ -32772,9 +32883,9 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
|
|
|
32772
32883
|
};
|
|
32773
32884
|
verifyRuntimeEvidenceCompositionSnapshot = async (bundleDir) => {
|
|
32774
32885
|
const [manifestText, payload, completeText] = await Promise.all([
|
|
32775
|
-
|
|
32776
|
-
|
|
32777
|
-
|
|
32886
|
+
import_promises32.default.readFile(import_node_path29.default.join(bundleDir, MANIFEST_FILE), "utf8"),
|
|
32887
|
+
import_promises32.default.readFile(import_node_path29.default.join(bundleDir, SNAPSHOT_FILE)),
|
|
32888
|
+
import_promises32.default.readFile(import_node_path29.default.join(bundleDir, COMPLETE_FILE), "utf8")
|
|
32778
32889
|
]);
|
|
32779
32890
|
const manifest = parseManifest(JSON.parse(manifestText));
|
|
32780
32891
|
if (completeText.trim() !== manifest.deploymentCompositionId) {
|
|
@@ -32837,39 +32948,39 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
|
|
|
32837
32948
|
bytes: Buffer.byteLength(payload)
|
|
32838
32949
|
}
|
|
32839
32950
|
};
|
|
32840
|
-
const snapshotsRoot =
|
|
32841
|
-
const bundleDir =
|
|
32842
|
-
const temporaryDir =
|
|
32951
|
+
const snapshotsRoot = import_node_path29.default.join(evidenceRoot, "snapshots", deploymentId);
|
|
32952
|
+
const bundleDir = import_node_path29.default.join(snapshotsRoot, compositionId);
|
|
32953
|
+
const temporaryDir = import_node_path29.default.join(
|
|
32843
32954
|
evidenceRoot,
|
|
32844
32955
|
"incoming",
|
|
32845
|
-
`snapshot-${compositionId}.tmp-${(0,
|
|
32956
|
+
`snapshot-${compositionId}.tmp-${(0, import_node_crypto15.randomUUID)()}`
|
|
32846
32957
|
);
|
|
32847
|
-
await
|
|
32958
|
+
await import_promises32.default.mkdir(temporaryDir, { recursive: true });
|
|
32848
32959
|
try {
|
|
32849
32960
|
await Promise.all([
|
|
32850
|
-
|
|
32851
|
-
|
|
32852
|
-
|
|
32961
|
+
import_promises32.default.writeFile(import_node_path29.default.join(temporaryDir, SNAPSHOT_FILE), payload, "utf8"),
|
|
32962
|
+
import_promises32.default.writeFile(
|
|
32963
|
+
import_node_path29.default.join(temporaryDir, MANIFEST_FILE),
|
|
32853
32964
|
`${JSON.stringify(manifest, null, 2)}
|
|
32854
32965
|
`,
|
|
32855
32966
|
"utf8"
|
|
32856
32967
|
)
|
|
32857
32968
|
]);
|
|
32858
|
-
await
|
|
32859
|
-
|
|
32969
|
+
await import_promises32.default.writeFile(
|
|
32970
|
+
import_node_path29.default.join(temporaryDir, COMPLETE_FILE),
|
|
32860
32971
|
`${compositionId}
|
|
32861
32972
|
`,
|
|
32862
32973
|
"utf8"
|
|
32863
32974
|
);
|
|
32864
|
-
await
|
|
32975
|
+
await import_promises32.default.mkdir(snapshotsRoot, { recursive: true });
|
|
32865
32976
|
try {
|
|
32866
|
-
await
|
|
32977
|
+
await import_promises32.default.rename(temporaryDir, bundleDir);
|
|
32867
32978
|
} catch (error) {
|
|
32868
32979
|
if (!isExistingDestinationError3(error)) throw error;
|
|
32869
|
-
await
|
|
32980
|
+
await import_promises32.default.rm(temporaryDir, { recursive: true, force: true });
|
|
32870
32981
|
}
|
|
32871
32982
|
} catch (error) {
|
|
32872
|
-
await
|
|
32983
|
+
await import_promises32.default.rm(temporaryDir, { recursive: true, force: true });
|
|
32873
32984
|
throw error;
|
|
32874
32985
|
}
|
|
32875
32986
|
const verified = await verifyRuntimeEvidenceCompositionSnapshot(bundleDir);
|
|
@@ -32903,31 +33014,31 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
|
|
|
32903
33014
|
);
|
|
32904
33015
|
}
|
|
32905
33016
|
await publishRuntimeEvidenceCompositionSnapshot({
|
|
32906
|
-
evidenceRoot:
|
|
33017
|
+
evidenceRoot: import_node_path29.default.join(projectRoot18, "data", "runtime-evidence"),
|
|
32907
33018
|
userName: userName3,
|
|
32908
33019
|
deployment,
|
|
32909
33020
|
producer
|
|
32910
33021
|
});
|
|
32911
33022
|
};
|
|
32912
33023
|
discoverRuntimeEvidenceCompositionSnapshots = async (evidenceRoot) => {
|
|
32913
|
-
const rootDir =
|
|
33024
|
+
const rootDir = import_node_path29.default.join(evidenceRoot, "snapshots");
|
|
32914
33025
|
const bundleDirs = [];
|
|
32915
33026
|
let deployments;
|
|
32916
33027
|
try {
|
|
32917
|
-
deployments = await
|
|
33028
|
+
deployments = await import_promises32.default.readdir(rootDir, { withFileTypes: true });
|
|
32918
33029
|
} catch (error) {
|
|
32919
33030
|
if (error.code === "ENOENT") return [];
|
|
32920
33031
|
throw error;
|
|
32921
33032
|
}
|
|
32922
33033
|
for (const deployment of deployments.filter((entry) => entry.isDirectory())) {
|
|
32923
|
-
const deploymentDir =
|
|
32924
|
-
const compositions = await
|
|
33034
|
+
const deploymentDir = import_node_path29.default.join(rootDir, deployment.name);
|
|
33035
|
+
const compositions = await import_promises32.default.readdir(deploymentDir, {
|
|
32925
33036
|
withFileTypes: true
|
|
32926
33037
|
});
|
|
32927
33038
|
bundleDirs.push(
|
|
32928
33039
|
...compositions.filter(
|
|
32929
33040
|
(entry) => entry.isDirectory() && !entry.name.startsWith(".") && !entry.name.includes(".tmp-")
|
|
32930
|
-
).map((entry) =>
|
|
33041
|
+
).map((entry) => import_node_path29.default.join(deploymentDir, entry.name))
|
|
32931
33042
|
);
|
|
32932
33043
|
}
|
|
32933
33044
|
return Promise.all(
|
|
@@ -33106,12 +33217,12 @@ __export(runtimeEvidence_exports, {
|
|
|
33106
33217
|
main: () => main40,
|
|
33107
33218
|
runtimeEvidence: () => runtimeEvidence
|
|
33108
33219
|
});
|
|
33109
|
-
var
|
|
33220
|
+
var import_promises33, import_node_path30, import_args31, import_chalk47, flags28, projectRoot12, toEpochMs3, resolveWindow2, parseStrategyFilter2, runtimeEvidence, main40;
|
|
33110
33221
|
var init_runtimeEvidence = __esm({
|
|
33111
33222
|
"src/scripts/runtimeEvidence.ts"() {
|
|
33112
33223
|
"use strict";
|
|
33113
|
-
|
|
33114
|
-
|
|
33224
|
+
import_promises33 = __toESM(require("fs/promises"));
|
|
33225
|
+
import_node_path30 = __toESM(require("path"));
|
|
33115
33226
|
import_args31 = __toESM(require("args"));
|
|
33116
33227
|
import_chalk47 = __toESM(require("chalk"));
|
|
33117
33228
|
init_runtimeDebugEvidence();
|
|
@@ -33218,7 +33329,7 @@ var init_runtimeEvidence = __esm({
|
|
|
33218
33329
|
deploymentId
|
|
33219
33330
|
});
|
|
33220
33331
|
const snapshots = publishDir && producer ? await loadRuntimeEvidenceCompositionSnapshots({
|
|
33221
|
-
publishRoot:
|
|
33332
|
+
publishRoot: import_node_path30.default.resolve(projectRoot12, publishDir),
|
|
33222
33333
|
currentDeployment: deploymentSnapshot,
|
|
33223
33334
|
currentProducer: producer
|
|
33224
33335
|
}) : /* @__PURE__ */ new Map([
|
|
@@ -33292,14 +33403,14 @@ var init_runtimeEvidence = __esm({
|
|
|
33292
33403
|
throw new Error("Runtime evidence window has no versioned runtime rows");
|
|
33293
33404
|
}
|
|
33294
33405
|
const artifact = current.artifact;
|
|
33295
|
-
const outPath =
|
|
33296
|
-
await
|
|
33297
|
-
await
|
|
33406
|
+
const outPath = import_node_path30.default.resolve(projectRoot12, String(flags28.out));
|
|
33407
|
+
await import_promises33.default.mkdir(import_node_path30.default.dirname(outPath), { recursive: true });
|
|
33408
|
+
await import_promises33.default.writeFile(outPath, `${JSON.stringify(artifact, null, 2)}
|
|
33298
33409
|
`, "utf8");
|
|
33299
33410
|
const published = publishDir ? await Promise.all(
|
|
33300
33411
|
artifacts.map(
|
|
33301
33412
|
({ artifact: artifact2, composition }) => (0, runtimeEvidenceArtifacts_exports.publishRuntimeEvidenceBundle)({
|
|
33302
|
-
publishRoot:
|
|
33413
|
+
publishRoot: import_node_path30.default.resolve(projectRoot12, publishDir),
|
|
33303
33414
|
deploymentId,
|
|
33304
33415
|
userName: String(flags28.user),
|
|
33305
33416
|
startTime,
|
|
@@ -33345,11 +33456,11 @@ __export(runtimeEvidenceSync_exports, {
|
|
|
33345
33456
|
main: () => main41,
|
|
33346
33457
|
runtimeEvidenceSync: () => runtimeEvidenceSync
|
|
33347
33458
|
});
|
|
33348
|
-
var
|
|
33459
|
+
var import_node_path31, import_args32, import_chalk48, flags29, projectRoot13, runtimeEvidenceSync, main41;
|
|
33349
33460
|
var init_runtimeEvidenceSync2 = __esm({
|
|
33350
33461
|
"src/scripts/runtimeEvidenceSync.ts"() {
|
|
33351
33462
|
"use strict";
|
|
33352
|
-
|
|
33463
|
+
import_node_path31 = __toESM(require("path"));
|
|
33353
33464
|
import_args32 = __toESM(require("args"));
|
|
33354
33465
|
import_chalk48 = __toESM(require("chalk"));
|
|
33355
33466
|
init_runtimeEvidenceSync();
|
|
@@ -33377,7 +33488,7 @@ var init_runtimeEvidenceSync2 = __esm({
|
|
|
33377
33488
|
"Provide --source or RUNTIME_EVIDENCE_RSYNC_SOURCE for runtime evidence sync."
|
|
33378
33489
|
);
|
|
33379
33490
|
}
|
|
33380
|
-
const evidenceRoot =
|
|
33491
|
+
const evidenceRoot = import_node_path31.default.resolve(projectRoot13, String(flags29.dir));
|
|
33381
33492
|
const result = await syncRuntimeEvidenceBundles({
|
|
33382
33493
|
source,
|
|
33383
33494
|
evidenceRoot,
|
|
@@ -34415,26 +34526,43 @@ var init_monitoringProfile = __esm({
|
|
|
34415
34526
|
});
|
|
34416
34527
|
|
|
34417
34528
|
// src/lib/strategyRelease/evidenceRetention.ts
|
|
34418
|
-
var DAY_MS14, planStrategyEvidenceRetention;
|
|
34529
|
+
var DAY_MS14, isResearchRetired, planStrategyEvidenceRetention;
|
|
34419
34530
|
var init_evidenceRetention = __esm({
|
|
34420
34531
|
"src/lib/strategyRelease/evidenceRetention.ts"() {
|
|
34421
34532
|
"use strict";
|
|
34422
34533
|
DAY_MS14 = 864e5;
|
|
34534
|
+
isResearchRetired = (research) => research?.status === "retired" && research.retirement?.policy === "discard-unrecoverable-without-rerun" && Boolean(research.retirement.reason.trim()) && Boolean(research.retirement.missingEvidence.length) && research.retirement.missingEvidence.every((item) => Boolean(item.trim()));
|
|
34423
34535
|
planStrategyEvidenceRetention = ({
|
|
34424
34536
|
now: now2,
|
|
34425
34537
|
entries,
|
|
34538
|
+
research,
|
|
34426
34539
|
retentionDays = {
|
|
34427
34540
|
operational_redis: 3,
|
|
34428
34541
|
verbose_payload: 14,
|
|
34542
|
+
research_payload: 0,
|
|
34543
|
+
research_cache: 0,
|
|
34429
34544
|
verified_runtime_bundle: 90,
|
|
34430
34545
|
compact_ledger: null
|
|
34431
34546
|
}
|
|
34432
34547
|
}) => {
|
|
34433
34548
|
const keep = [];
|
|
34434
34549
|
const remove = [];
|
|
34550
|
+
const retired = isResearchRetired(research);
|
|
34551
|
+
const roles = new Set(
|
|
34552
|
+
research?.permanentArtifacts.map((artifact) => artifact.role)
|
|
34553
|
+
);
|
|
34554
|
+
const terminalResearch = Boolean(
|
|
34555
|
+
(research?.status === "completed" || retired) && Number.isFinite(research?.completedAt) && research.completedAt <= now2 && (retired ? ["note"] : ["note", "candidates", "metrics"]).every(
|
|
34556
|
+
(role) => roles.has(role)
|
|
34557
|
+
)
|
|
34558
|
+
);
|
|
34435
34559
|
for (const entry of entries) {
|
|
34436
34560
|
const days = retentionDays[entry.kind];
|
|
34437
|
-
|
|
34561
|
+
const isResearch = entry.kind === "research_payload" || entry.kind === "research_cache";
|
|
34562
|
+
const completedResearch = Boolean(
|
|
34563
|
+
terminalResearch && research?.researchId === entry.researchId && /^[a-f0-9]{64}$/.test(entry.sha256 ?? "")
|
|
34564
|
+
);
|
|
34565
|
+
if (isResearch && !completedResearch || days == null || !entry.verified || !entry.aggregated && !(isResearch && retired) || !isResearch && now2 - entry.createdAt <= days * DAY_MS14) {
|
|
34438
34566
|
keep.push(entry);
|
|
34439
34567
|
} else {
|
|
34440
34568
|
remove.push(entry);
|
|
@@ -34464,7 +34592,7 @@ async function collectReleaseEvidenceReferences(references) {
|
|
|
34464
34592
|
let artifact;
|
|
34465
34593
|
try {
|
|
34466
34594
|
const parsed = JSON.parse(
|
|
34467
|
-
await
|
|
34595
|
+
await import_promises34.default.readFile(reference.path, "utf8")
|
|
34468
34596
|
);
|
|
34469
34597
|
assert3(
|
|
34470
34598
|
parsed != null && typeof parsed === "object" && !Array.isArray(parsed),
|
|
@@ -34611,13 +34739,13 @@ async function collectReleaseEvidenceReferences(references) {
|
|
|
34611
34739
|
})
|
|
34612
34740
|
);
|
|
34613
34741
|
}
|
|
34614
|
-
var
|
|
34742
|
+
var import_node_crypto16, import_promises34, import_node_path32, import_types9, import_strategyReleaseEvidence2, SHA256_RE2, 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;
|
|
34615
34743
|
var init_strategyRelease = __esm({
|
|
34616
34744
|
"src/lib/strategyRelease.ts"() {
|
|
34617
34745
|
"use strict";
|
|
34618
|
-
|
|
34619
|
-
|
|
34620
|
-
|
|
34746
|
+
import_node_crypto16 = require("crypto");
|
|
34747
|
+
import_promises34 = __toESM(require("fs/promises"));
|
|
34748
|
+
import_node_path32 = __toESM(require("path"));
|
|
34621
34749
|
import_types9 = require("@tradejs/types");
|
|
34622
34750
|
import_strategyReleaseEvidence2 = require("@tradejs/infra/strategyReleaseEvidence");
|
|
34623
34751
|
init_liveDiagnosis();
|
|
@@ -34636,11 +34764,11 @@ var init_strategyRelease = __esm({
|
|
|
34636
34764
|
const artifact = input.chartArtifact;
|
|
34637
34765
|
if (!artifact?.path || !SHA256_RE2.test(artifact.sha256)) return false;
|
|
34638
34766
|
try {
|
|
34639
|
-
const artifactPath =
|
|
34767
|
+
const artifactPath = import_node_path32.default.resolve(artifact.path);
|
|
34640
34768
|
if (await (0, import_strategyReleaseEvidence2.strategyEvidenceFileSha256)(artifactPath) !== artifact.sha256) {
|
|
34641
34769
|
return false;
|
|
34642
34770
|
}
|
|
34643
|
-
const report = JSON.parse(await
|
|
34771
|
+
const report = JSON.parse(await import_promises34.default.readFile(artifactPath, "utf8"));
|
|
34644
34772
|
return Boolean(
|
|
34645
34773
|
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
|
|
34646
34774
|
);
|
|
@@ -34651,11 +34779,11 @@ var init_strategyRelease = __esm({
|
|
|
34651
34779
|
readVerifiedJsonArtifact = async (artifact) => {
|
|
34652
34780
|
if (!artifact?.path || !SHA256_RE2.test(artifact.sha256)) return null;
|
|
34653
34781
|
try {
|
|
34654
|
-
const artifactPath =
|
|
34782
|
+
const artifactPath = import_node_path32.default.resolve(artifact.path);
|
|
34655
34783
|
if (await (0, import_strategyReleaseEvidence2.strategyEvidenceFileSha256)(artifactPath) !== artifact.sha256) {
|
|
34656
34784
|
return null;
|
|
34657
34785
|
}
|
|
34658
|
-
return JSON.parse(await
|
|
34786
|
+
return JSON.parse(await import_promises34.default.readFile(artifactPath, "utf8"));
|
|
34659
34787
|
} catch {
|
|
34660
34788
|
return null;
|
|
34661
34789
|
}
|
|
@@ -35201,7 +35329,7 @@ var init_strategyRelease = __esm({
|
|
|
35201
35329
|
manifest
|
|
35202
35330
|
});
|
|
35203
35331
|
verifyStrategyReleaseEnvelope = async (valueOrPath) => {
|
|
35204
|
-
const value = typeof valueOrPath === "string" ? JSON.parse(await
|
|
35332
|
+
const value = typeof valueOrPath === "string" ? JSON.parse(await import_promises34.default.readFile(valueOrPath, "utf8")) : valueOrPath;
|
|
35205
35333
|
const envelope = value;
|
|
35206
35334
|
assert3(
|
|
35207
35335
|
envelope?.schema === "tradejs-strategy-release-envelope/v1",
|
|
@@ -35252,7 +35380,7 @@ var init_strategyRelease = __esm({
|
|
|
35252
35380
|
return envelope;
|
|
35253
35381
|
};
|
|
35254
35382
|
verifyStrategyEvidenceMarkerEnvelope = async (valueOrPath) => {
|
|
35255
|
-
const value = typeof valueOrPath === "string" ? JSON.parse(await
|
|
35383
|
+
const value = typeof valueOrPath === "string" ? JSON.parse(await import_promises34.default.readFile(valueOrPath, "utf8")) : valueOrPath;
|
|
35256
35384
|
return (0, import_strategyReleaseEvidence2.verifyStrategyEvidenceMarkerEnvelope)(value);
|
|
35257
35385
|
};
|
|
35258
35386
|
releaseMarkers = (manifest) => {
|
|
@@ -35314,14 +35442,14 @@ var init_strategyRelease = __esm({
|
|
|
35314
35442
|
};
|
|
35315
35443
|
writeJsonAtomic2 = async (filePath, value) => {
|
|
35316
35444
|
const temporaryPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
35317
|
-
await
|
|
35318
|
-
await
|
|
35445
|
+
await import_promises34.default.mkdir(import_node_path32.default.dirname(filePath), { recursive: true });
|
|
35446
|
+
await import_promises34.default.writeFile(
|
|
35319
35447
|
temporaryPath,
|
|
35320
35448
|
`${canonicalStrategyReleaseJson(value)}
|
|
35321
35449
|
`,
|
|
35322
35450
|
"utf8"
|
|
35323
35451
|
);
|
|
35324
|
-
await
|
|
35452
|
+
await import_promises34.default.rename(temporaryPath, filePath);
|
|
35325
35453
|
};
|
|
35326
35454
|
publishStrategyRelease = async ({
|
|
35327
35455
|
rootDir,
|
|
@@ -35338,13 +35466,13 @@ var init_strategyRelease = __esm({
|
|
|
35338
35466
|
path: entry.path
|
|
35339
35467
|
}))
|
|
35340
35468
|
});
|
|
35341
|
-
const releasePath =
|
|
35469
|
+
const releasePath = import_node_path32.default.join(
|
|
35342
35470
|
rootDir,
|
|
35343
35471
|
"releases",
|
|
35344
35472
|
safeSegment5(manifest.strategy, "strategy"),
|
|
35345
35473
|
`${manifest.releaseId}.json`
|
|
35346
35474
|
);
|
|
35347
|
-
const markerPath =
|
|
35475
|
+
const markerPath = import_node_path32.default.join(
|
|
35348
35476
|
rootDir,
|
|
35349
35477
|
"markers",
|
|
35350
35478
|
safeSegment5(manifest.strategy, "strategy"),
|
|
@@ -35424,13 +35552,13 @@ var init_strategyRelease = __esm({
|
|
|
35424
35552
|
markers,
|
|
35425
35553
|
sourceArtifacts
|
|
35426
35554
|
});
|
|
35427
|
-
const diagnosisPath =
|
|
35555
|
+
const diagnosisPath = import_node_path32.default.join(
|
|
35428
35556
|
rootDir,
|
|
35429
35557
|
"diagnoses",
|
|
35430
35558
|
safeSegment5(diagnosis.strategy, "strategy"),
|
|
35431
35559
|
`${diagnosisId}.json`
|
|
35432
35560
|
);
|
|
35433
|
-
const markerPath =
|
|
35561
|
+
const markerPath = import_node_path32.default.join(
|
|
35434
35562
|
rootDir,
|
|
35435
35563
|
"markers",
|
|
35436
35564
|
safeSegment5(diagnosis.strategy, "strategy"),
|
|
@@ -35620,11 +35748,11 @@ var init_strategyRelease = __esm({
|
|
|
35620
35748
|
const specSha256 = finiteString3(artifact.specSha256);
|
|
35621
35749
|
assert3(researchId != null, "core result researchId is required");
|
|
35622
35750
|
assert3(specSha256 != null, "core result specSha256 is required");
|
|
35623
|
-
const researchDir =
|
|
35624
|
-
const manifestPath =
|
|
35625
|
-
const specPath =
|
|
35626
|
-
const manifestBytes = await
|
|
35627
|
-
const specBytes = await
|
|
35751
|
+
const researchDir = import_node_path32.default.dirname(resultPath);
|
|
35752
|
+
const manifestPath = import_node_path32.default.join(researchDir, "manifest.json");
|
|
35753
|
+
const specPath = import_node_path32.default.join(researchDir, "spec.json");
|
|
35754
|
+
const manifestBytes = await import_promises34.default.readFile(manifestPath).catch(() => null);
|
|
35755
|
+
const specBytes = await import_promises34.default.readFile(specPath).catch(() => null);
|
|
35628
35756
|
assert3(
|
|
35629
35757
|
manifestBytes != null && specBytes != null,
|
|
35630
35758
|
"core result must belong to a completed core research bundle"
|
|
@@ -35633,14 +35761,14 @@ var init_strategyRelease = __esm({
|
|
|
35633
35761
|
const artifactHashes = manifest.artifactHashes != null && typeof manifest.artifactHashes === "object" && !Array.isArray(manifest.artifactHashes) ? manifest.artifactHashes : null;
|
|
35634
35762
|
const parsedSpec = JSON.parse(specBytes.toString("utf8"));
|
|
35635
35763
|
assert3(
|
|
35636
|
-
manifest.schema === "tradejs-core-research-manifest/v1" && manifest.status === "completed" && manifest.researchId === researchId && manifest.specSha256 === specSha256 && artifactHashes?.["result.json"] === resultSha256 && (0,
|
|
35764
|
+
manifest.schema === "tradejs-core-research-manifest/v1" && manifest.status === "completed" && manifest.researchId === researchId && manifest.specSha256 === specSha256 && artifactHashes?.["result.json"] === resultSha256 && (0, import_node_crypto16.createHash)("sha256").update(canonicalStrategyReleaseJson(parsedSpec)).digest("hex") === specSha256,
|
|
35637
35765
|
"core result is not bound by its completed core research manifest"
|
|
35638
35766
|
);
|
|
35639
35767
|
for (const [relativePath, expectedSha256] of Object.entries(
|
|
35640
35768
|
artifactHashes ?? {}
|
|
35641
35769
|
)) {
|
|
35642
35770
|
assert3(
|
|
35643
|
-
!
|
|
35771
|
+
!import_node_path32.default.isAbsolute(relativePath) && !relativePath.split(/[\\/]/).includes(".."),
|
|
35644
35772
|
`core bundle artifact ${relativePath} escapes its research directory`
|
|
35645
35773
|
);
|
|
35646
35774
|
assert3(
|
|
@@ -35648,7 +35776,7 @@ var init_strategyRelease = __esm({
|
|
|
35648
35776
|
`core bundle artifact ${relativePath} has an invalid checksum`
|
|
35649
35777
|
);
|
|
35650
35778
|
const actualSha256 = await (0, import_strategyReleaseEvidence2.strategyEvidenceFileSha256)(
|
|
35651
|
-
|
|
35779
|
+
import_node_path32.default.join(researchDir, relativePath)
|
|
35652
35780
|
);
|
|
35653
35781
|
assert3(
|
|
35654
35782
|
actualSha256 === expectedSha256,
|
|
@@ -35665,13 +35793,13 @@ __export(runtimeScorecard_exports, {
|
|
|
35665
35793
|
main: () => main42,
|
|
35666
35794
|
runtimeScorecard: () => runtimeScorecard
|
|
35667
35795
|
});
|
|
35668
|
-
var
|
|
35796
|
+
var import_promises35, import_node_crypto17, import_node_path33, import_args33, import_chalk49, flags30, projectRoot14, resolveOptionalPath, readJson, assertReportType, sha256File2, loadHistoryArtifacts, runtimeScorecard, main42;
|
|
35669
35797
|
var init_runtimeScorecard2 = __esm({
|
|
35670
35798
|
"src/scripts/runtimeScorecard.ts"() {
|
|
35671
35799
|
"use strict";
|
|
35672
|
-
|
|
35673
|
-
|
|
35674
|
-
|
|
35800
|
+
import_promises35 = __toESM(require("fs/promises"));
|
|
35801
|
+
import_node_crypto17 = require("crypto");
|
|
35802
|
+
import_node_path33 = __toESM(require("path"));
|
|
35675
35803
|
import_args33 = __toESM(require("args"));
|
|
35676
35804
|
import_chalk49 = __toESM(require("chalk"));
|
|
35677
35805
|
init_runtimeEvidenceArtifacts();
|
|
@@ -35741,15 +35869,15 @@ var init_runtimeScorecard2 = __esm({
|
|
|
35741
35869
|
projectRoot14 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
|
|
35742
35870
|
resolveOptionalPath = (value) => {
|
|
35743
35871
|
const raw = String(value ?? "").trim();
|
|
35744
|
-
return raw ?
|
|
35872
|
+
return raw ? import_node_path33.default.resolve(projectRoot14, raw) : null;
|
|
35745
35873
|
};
|
|
35746
|
-
readJson = async (filePath) => filePath ? JSON.parse(await
|
|
35874
|
+
readJson = async (filePath) => filePath ? JSON.parse(await import_promises35.default.readFile(filePath, "utf8")) : void 0;
|
|
35747
35875
|
assertReportType = (artifact, expected, label) => {
|
|
35748
35876
|
if (artifact != null && (!artifact || typeof artifact !== "object" || Array.isArray(artifact) || artifact.reportType !== expected)) {
|
|
35749
35877
|
throw new Error(`${label} must be a ${expected} artifact`);
|
|
35750
35878
|
}
|
|
35751
35879
|
};
|
|
35752
|
-
sha256File2 = async (filePath) => (0,
|
|
35880
|
+
sha256File2 = async (filePath) => (0, import_node_crypto17.createHash)("sha256").update(await import_promises35.default.readFile(filePath)).digest("hex");
|
|
35753
35881
|
loadHistoryArtifacts = async (historyDir) => {
|
|
35754
35882
|
if (!historyDir) return [];
|
|
35755
35883
|
const bundleDirs = await (0, runtimeEvidenceArtifacts_exports.discoverRuntimeEvidenceBundles)(historyDir);
|
|
@@ -35820,13 +35948,13 @@ var init_runtimeScorecard2 = __esm({
|
|
|
35820
35948
|
strategy: scorecardStrategy,
|
|
35821
35949
|
llmComparatorPolicy: verifiedRelease?.manifest.prospective.llmComparatorPolicy ?? "ai_approved_only"
|
|
35822
35950
|
});
|
|
35823
|
-
const outPath =
|
|
35951
|
+
const outPath = import_node_path33.default.resolve(projectRoot14, String(flags30.out));
|
|
35824
35952
|
const markdownPath = outPath.replace(/\.json$/i, "") + ".md";
|
|
35825
|
-
await
|
|
35953
|
+
await import_promises35.default.mkdir(import_node_path33.default.dirname(outPath), { recursive: true });
|
|
35826
35954
|
await Promise.all([
|
|
35827
|
-
|
|
35955
|
+
import_promises35.default.writeFile(outPath, `${JSON.stringify(scorecard, null, 2)}
|
|
35828
35956
|
`, "utf8"),
|
|
35829
|
-
|
|
35957
|
+
import_promises35.default.writeFile(
|
|
35830
35958
|
markdownPath,
|
|
35831
35959
|
formatRuntimeScorecardMarkdown(scorecard),
|
|
35832
35960
|
"utf8"
|
|
@@ -35840,7 +35968,7 @@ var init_runtimeScorecard2 = __esm({
|
|
|
35840
35968
|
const diagnosisPath = diagnosis ? outPath.replace(/\.json$/i, "") + ".diagnosis.json" : null;
|
|
35841
35969
|
const strategyReleaseRoot = resolveOptionalPath(flags30.strategyReleaseRoot);
|
|
35842
35970
|
if (diagnosis && diagnosisPath) {
|
|
35843
|
-
await
|
|
35971
|
+
await import_promises35.default.writeFile(
|
|
35844
35972
|
diagnosisPath,
|
|
35845
35973
|
`${JSON.stringify(diagnosis, null, 2)}
|
|
35846
35974
|
`,
|
|
@@ -35861,7 +35989,7 @@ var init_runtimeScorecard2 = __esm({
|
|
|
35861
35989
|
composition: verifiedRelease?.manifest.composition,
|
|
35862
35990
|
sourceArtifacts: await Promise.all(
|
|
35863
35991
|
sourcePaths.map(async (sourcePath) => ({
|
|
35864
|
-
artifactId:
|
|
35992
|
+
artifactId: import_node_path33.default.basename(sourcePath),
|
|
35865
35993
|
path: sourcePath,
|
|
35866
35994
|
sha256: await sha256File2(sourcePath)
|
|
35867
35995
|
}))
|
|
@@ -35872,11 +36000,11 @@ var init_runtimeScorecard2 = __esm({
|
|
|
35872
36000
|
let receiptPath2 = null;
|
|
35873
36001
|
if (flags30.markProcessed) {
|
|
35874
36002
|
const runtimeEvidenceBundle = await (0, runtimeEvidenceArtifacts_exports.verifyRuntimeEvidenceBundle)(
|
|
35875
|
-
|
|
36003
|
+
import_node_path33.default.dirname(runtimeEvidencePath)
|
|
35876
36004
|
);
|
|
35877
36005
|
const feedbackSource = replayEvidencePath ? await (0, runtimeFeedbackArtifacts_exports.verifyRuntimeFeedbackReplaySource)({
|
|
35878
|
-
bundleDir:
|
|
35879
|
-
runtimeEvidenceBundleDir:
|
|
36006
|
+
bundleDir: import_node_path33.default.dirname(replayEvidencePath),
|
|
36007
|
+
runtimeEvidenceBundleDir: import_node_path33.default.dirname(runtimeEvidencePath)
|
|
35880
36008
|
}).catch((error) => {
|
|
35881
36009
|
if (runtimeEvidenceBundle.artifact.producer) throw error;
|
|
35882
36010
|
return null;
|
|
@@ -35887,9 +36015,9 @@ var init_runtimeScorecard2 = __esm({
|
|
|
35887
36015
|
);
|
|
35888
36016
|
}
|
|
35889
36017
|
receiptPath2 = await markRuntimeEvidenceBundleProcessed({
|
|
35890
|
-
evidenceRoot:
|
|
36018
|
+
evidenceRoot: import_node_path33.default.resolve(projectRoot14, String(flags30.evidenceDir)),
|
|
35891
36019
|
deploymentId: String(flags30.deployment),
|
|
35892
|
-
bundleDir:
|
|
36020
|
+
bundleDir: import_node_path33.default.dirname(runtimeEvidencePath),
|
|
35893
36021
|
scorecardPath: outPath,
|
|
35894
36022
|
runtimeFeedback: feedbackSource ? {
|
|
35895
36023
|
artifactId: feedbackSource.feedback.manifest.artifactId,
|
|
@@ -36080,21 +36208,316 @@ var init_runtimeControl = __esm({
|
|
|
36080
36208
|
}
|
|
36081
36209
|
});
|
|
36082
36210
|
|
|
36211
|
+
// src/lib/strategyRelease/researchFileConsumers.ts
|
|
36212
|
+
var import_node_path34, import_node_child_process10, import_node_util3, execFileAsync3, runCommand3, GUEST_FILE_CHECK, assertNoResearchFileConsumers;
|
|
36213
|
+
var init_researchFileConsumers = __esm({
|
|
36214
|
+
"src/lib/strategyRelease/researchFileConsumers.ts"() {
|
|
36215
|
+
"use strict";
|
|
36216
|
+
import_node_path34 = __toESM(require("path"));
|
|
36217
|
+
import_node_child_process10 = require("child_process");
|
|
36218
|
+
import_node_util3 = require("util");
|
|
36219
|
+
execFileAsync3 = (0, import_node_util3.promisify)(import_node_child_process10.execFile);
|
|
36220
|
+
runCommand3 = (command, args39) => execFileAsync3(command, args39, { maxBuffer: 32 * 1024 * 1024 });
|
|
36221
|
+
GUEST_FILE_CHECK = `
|
|
36222
|
+
import os, sys, json
|
|
36223
|
+
if os.geteuid() != 0:
|
|
36224
|
+
raise RuntimeError('Cannot inspect every container process')
|
|
36225
|
+
wanted = set(json.loads(sys.argv[1]))
|
|
36226
|
+
opened = set()
|
|
36227
|
+
for pid in os.listdir('/proc'):
|
|
36228
|
+
if not pid.isdigit():
|
|
36229
|
+
continue
|
|
36230
|
+
for kind in ('fd', 'map_files'):
|
|
36231
|
+
directory = '/proc/' + pid + '/' + kind
|
|
36232
|
+
try:
|
|
36233
|
+
names = os.listdir(directory)
|
|
36234
|
+
except FileNotFoundError:
|
|
36235
|
+
continue
|
|
36236
|
+
for name in names:
|
|
36237
|
+
try:
|
|
36238
|
+
target = os.readlink(directory + '/' + name)
|
|
36239
|
+
except FileNotFoundError:
|
|
36240
|
+
continue
|
|
36241
|
+
if target in wanted:
|
|
36242
|
+
opened.add(target)
|
|
36243
|
+
print(json.dumps(sorted(opened)))
|
|
36244
|
+
`;
|
|
36245
|
+
assertNoResearchFileConsumers = async (files, run = runCommand3) => {
|
|
36246
|
+
const virtualPids = /* @__PURE__ */ new Set();
|
|
36247
|
+
const wanted = new Set(files.map((file) => import_node_path34.default.resolve(file)));
|
|
36248
|
+
let commonRoot = files.length ? import_node_path34.default.dirname(files[0]) : "";
|
|
36249
|
+
while (commonRoot && files.some((file) => {
|
|
36250
|
+
const relative = import_node_path34.default.relative(commonRoot, file);
|
|
36251
|
+
return relative === ".." || relative.startsWith(`..${import_node_path34.default.sep}`) || import_node_path34.default.isAbsolute(relative);
|
|
36252
|
+
}))
|
|
36253
|
+
commonRoot = import_node_path34.default.dirname(commonRoot);
|
|
36254
|
+
const selectors = [];
|
|
36255
|
+
if (files.length > 1e3 && commonRoot !== import_node_path34.default.parse(commonRoot).root) {
|
|
36256
|
+
selectors.push(["+D", commonRoot]);
|
|
36257
|
+
} else {
|
|
36258
|
+
for (let offset = 0; offset < files.length; offset += 100)
|
|
36259
|
+
selectors.push(["--", ...files.slice(offset, offset + 100)]);
|
|
36260
|
+
}
|
|
36261
|
+
for (const selector of selectors) {
|
|
36262
|
+
let output;
|
|
36263
|
+
try {
|
|
36264
|
+
output = (await run("lsof", ["-F", "pcn", ...selector])).stdout;
|
|
36265
|
+
} catch (error) {
|
|
36266
|
+
if (error.code === 1) continue;
|
|
36267
|
+
throw error;
|
|
36268
|
+
}
|
|
36269
|
+
let pid = "";
|
|
36270
|
+
let virtual = false;
|
|
36271
|
+
for (const line of output.split("\n")) {
|
|
36272
|
+
if (line.startsWith("p")) {
|
|
36273
|
+
pid = line.slice(1);
|
|
36274
|
+
virtual = false;
|
|
36275
|
+
}
|
|
36276
|
+
if (line.startsWith("c"))
|
|
36277
|
+
virtual = line.startsWith("ccom.apple.Virtualization.");
|
|
36278
|
+
if (line.startsWith("n")) {
|
|
36279
|
+
if (!wanted.has(import_node_path34.default.resolve(line.slice(1)))) continue;
|
|
36280
|
+
if (!virtual || !/^\d+$/.test(pid))
|
|
36281
|
+
throw new Error(
|
|
36282
|
+
`Research cleanup found open files: ${line.slice(1)}`
|
|
36283
|
+
);
|
|
36284
|
+
virtualPids.add(pid);
|
|
36285
|
+
}
|
|
36286
|
+
}
|
|
36287
|
+
}
|
|
36288
|
+
if (!virtualPids.size) return;
|
|
36289
|
+
for (const pid of virtualPids) {
|
|
36290
|
+
const comm = (await run("ps", ["-p", pid, "-o", "comm="])).stdout.trim();
|
|
36291
|
+
if (comm !== "/System/Library/Frameworks/Virtualization.framework/Versions/A/XPCServices/com.apple.Virtualization.VirtualMachine.xpc/Contents/MacOS/com.apple.Virtualization.VirtualMachine") {
|
|
36292
|
+
throw new Error("Unrecognized virtual file consumer");
|
|
36293
|
+
}
|
|
36294
|
+
}
|
|
36295
|
+
const contexts = JSON.parse(
|
|
36296
|
+
(await run("docker", ["context", "inspect"])).stdout
|
|
36297
|
+
);
|
|
36298
|
+
if (contexts.length !== 1 || !contexts[0].Endpoints.docker.Host.startsWith("unix://")) {
|
|
36299
|
+
throw new Error("Research file inspection requires a local Docker socket");
|
|
36300
|
+
}
|
|
36301
|
+
const ids = (await run("docker", ["ps", "-q"])).stdout.trim().split(/\s+/).filter(Boolean);
|
|
36302
|
+
if (!ids.length)
|
|
36303
|
+
throw new Error("Cannot resolve virtual research file handles");
|
|
36304
|
+
const containers = JSON.parse(
|
|
36305
|
+
(await run("docker", ["inspect", ...ids])).stdout
|
|
36306
|
+
);
|
|
36307
|
+
const covered = /* @__PURE__ */ new Set();
|
|
36308
|
+
for (const container of containers) {
|
|
36309
|
+
const guestFiles = /* @__PURE__ */ new Set();
|
|
36310
|
+
for (const mount of container.Mounts) {
|
|
36311
|
+
if (mount.Type !== "bind") continue;
|
|
36312
|
+
for (const file of files) {
|
|
36313
|
+
const relative = import_node_path34.default.relative(mount.Source, file);
|
|
36314
|
+
if (relative === "" || !relative.startsWith(`..${import_node_path34.default.sep}`) && relative !== ".." && !import_node_path34.default.isAbsolute(relative)) {
|
|
36315
|
+
guestFiles.add(import_node_path34.default.posix.join(mount.Destination, relative));
|
|
36316
|
+
covered.add(file);
|
|
36317
|
+
}
|
|
36318
|
+
}
|
|
36319
|
+
}
|
|
36320
|
+
if (!guestFiles.size) continue;
|
|
36321
|
+
const paths = [...guestFiles];
|
|
36322
|
+
for (let offset = 0; offset < paths.length; offset += 250) {
|
|
36323
|
+
const opened = JSON.parse(
|
|
36324
|
+
(await run("docker", [
|
|
36325
|
+
"exec",
|
|
36326
|
+
container.Id,
|
|
36327
|
+
"python",
|
|
36328
|
+
"-c",
|
|
36329
|
+
GUEST_FILE_CHECK,
|
|
36330
|
+
JSON.stringify(paths.slice(offset, offset + 250))
|
|
36331
|
+
])).stdout
|
|
36332
|
+
);
|
|
36333
|
+
if (!Array.isArray(opened) || opened.length)
|
|
36334
|
+
throw new Error("Research cleanup found open files in a container");
|
|
36335
|
+
}
|
|
36336
|
+
}
|
|
36337
|
+
if (covered.size !== files.length)
|
|
36338
|
+
throw new Error("Unresolved virtual research file handles");
|
|
36339
|
+
};
|
|
36340
|
+
}
|
|
36341
|
+
});
|
|
36342
|
+
|
|
36343
|
+
// src/lib/strategyRelease/researchRetention.ts
|
|
36344
|
+
var import_promises36, import_node_path35, import_node_crypto18, import_strategyReleaseEvidence3, SHA256_RE3, mapFiles, fileSha256, inside, applyResearchRetention;
|
|
36345
|
+
var init_researchRetention = __esm({
|
|
36346
|
+
"src/lib/strategyRelease/researchRetention.ts"() {
|
|
36347
|
+
"use strict";
|
|
36348
|
+
import_promises36 = __toESM(require("fs/promises"));
|
|
36349
|
+
import_node_path35 = __toESM(require("path"));
|
|
36350
|
+
import_node_crypto18 = require("crypto");
|
|
36351
|
+
import_strategyReleaseEvidence3 = require("@tradejs/infra/strategyReleaseEvidence");
|
|
36352
|
+
init_researchFileConsumers();
|
|
36353
|
+
init_evidenceRetention();
|
|
36354
|
+
SHA256_RE3 = /^[a-f0-9]{64}$/;
|
|
36355
|
+
mapFiles = async (entries, visit) => {
|
|
36356
|
+
const results2 = new Array(entries.length);
|
|
36357
|
+
let next = 0;
|
|
36358
|
+
const workers = await Promise.allSettled(
|
|
36359
|
+
Array.from({ length: Math.min(8, entries.length) }, async () => {
|
|
36360
|
+
while (next < entries.length) {
|
|
36361
|
+
const index = next++;
|
|
36362
|
+
results2[index] = await visit(entries[index]);
|
|
36363
|
+
}
|
|
36364
|
+
})
|
|
36365
|
+
);
|
|
36366
|
+
for (const worker of workers)
|
|
36367
|
+
if (worker.status === "rejected") throw worker.reason;
|
|
36368
|
+
return results2;
|
|
36369
|
+
};
|
|
36370
|
+
fileSha256 = async (file, bytes) => bytes <= 1024 * 1024 ? (0, import_node_crypto18.createHash)("sha256").update(await import_promises36.default.readFile(file)).digest("hex") : (0, import_strategyReleaseEvidence3.strategyEvidenceFileSha256)(file);
|
|
36371
|
+
inside = (root, file) => {
|
|
36372
|
+
const relative = import_node_path35.default.relative(root, file);
|
|
36373
|
+
return relative !== "" && !relative.startsWith(`..${import_node_path35.default.sep}`) && relative !== ".." && !import_node_path35.default.isAbsolute(relative);
|
|
36374
|
+
};
|
|
36375
|
+
applyResearchRetention = async (options) => {
|
|
36376
|
+
const projectRoot18 = await import_promises36.default.realpath(options.projectRoot);
|
|
36377
|
+
const dataRoot = import_node_path35.default.join(projectRoot18, "data");
|
|
36378
|
+
const resolve = (file) => import_node_path35.default.resolve(projectRoot18, file);
|
|
36379
|
+
const receiptPath2 = resolve(options.receiptPath);
|
|
36380
|
+
const journalPath = `${receiptPath2}.deleted.jsonl`;
|
|
36381
|
+
const permanent = new Set(
|
|
36382
|
+
options.research.permanentArtifacts.map((entry) => resolve(entry.path))
|
|
36383
|
+
);
|
|
36384
|
+
if (!inside(projectRoot18, receiptPath2) || permanent.has(receiptPath2) || permanent.has(journalPath)) {
|
|
36385
|
+
throw new Error(
|
|
36386
|
+
"Cleanup receipt must be separate from permanent research artifacts"
|
|
36387
|
+
);
|
|
36388
|
+
}
|
|
36389
|
+
permanent.add(receiptPath2);
|
|
36390
|
+
permanent.add(journalPath);
|
|
36391
|
+
for (const file of options.protectedPaths ?? []) permanent.add(resolve(file));
|
|
36392
|
+
const retired = isResearchRetired(options.research);
|
|
36393
|
+
if (options.research.status !== "completed" && !retired || !Number.isFinite(options.research.completedAt) || options.research.completedAt > Date.now()) {
|
|
36394
|
+
throw new Error("Research must be completed before cleanup");
|
|
36395
|
+
}
|
|
36396
|
+
for (const role of retired ? ["note"] : ["note", "candidates", "metrics"]) {
|
|
36397
|
+
if (!options.research.permanentArtifacts.some((entry) => entry.role === role)) {
|
|
36398
|
+
throw new Error(`Missing permanent research ${role}`);
|
|
36399
|
+
}
|
|
36400
|
+
}
|
|
36401
|
+
await mapFiles(options.research.permanentArtifacts, async (artifact) => {
|
|
36402
|
+
const file = resolve(artifact.path);
|
|
36403
|
+
if (!inside(projectRoot18, await import_promises36.default.realpath(file)) || !SHA256_RE3.test(artifact.sha256) || await fileSha256(file, (await import_promises36.default.stat(file)).size) !== artifact.sha256) {
|
|
36404
|
+
throw new Error(
|
|
36405
|
+
`Permanent research artifact checksum/path mismatch: ${file}`
|
|
36406
|
+
);
|
|
36407
|
+
}
|
|
36408
|
+
if (artifact.role === "note") {
|
|
36409
|
+
const handle = await import_promises36.default.open(file, "r");
|
|
36410
|
+
try {
|
|
36411
|
+
const header = Buffer.alloc(4096);
|
|
36412
|
+
const { bytesRead } = await handle.read(header, 0, header.length, 0);
|
|
36413
|
+
const frontmatter = header.subarray(0, bytesRead).toString("utf8").match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
36414
|
+
if (!frontmatter || !/^schema:\s*tradejs-research\/v1\s*$/m.test(frontmatter[1]) || !(retired ? /^reproduction:\s*(?:complete|partial|blocked|legacy-partial)\s*$/m.test(
|
|
36415
|
+
frontmatter[1]
|
|
36416
|
+
) : /^reproduction:\s*complete\s*$/m.test(frontmatter[1]))) {
|
|
36417
|
+
throw new Error(
|
|
36418
|
+
`Research note must have reproduction: complete: ${file}`
|
|
36419
|
+
);
|
|
36420
|
+
}
|
|
36421
|
+
} finally {
|
|
36422
|
+
await handle.close();
|
|
36423
|
+
}
|
|
36424
|
+
}
|
|
36425
|
+
});
|
|
36426
|
+
const checkedPaths = /* @__PURE__ */ new Set();
|
|
36427
|
+
const checked = await mapFiles(options.entries, async (entry) => {
|
|
36428
|
+
const file = resolve(entry.path);
|
|
36429
|
+
if (!["research_payload", "research_cache"].includes(entry.kind) || entry.researchId !== options.research.researchId || !entry.verified || !entry.aggregated && !retired || !SHA256_RE3.test(entry.sha256 ?? "") || !inside(dataRoot, file) || permanent.has(file) || /\.(?:md|patch|diff)$/i.test(file)) {
|
|
36430
|
+
throw new Error(`Not a disposable research file: ${file}`);
|
|
36431
|
+
}
|
|
36432
|
+
if (checkedPaths.has(file))
|
|
36433
|
+
throw new Error(`Duplicate cleanup path: ${file}`);
|
|
36434
|
+
checkedPaths.add(file);
|
|
36435
|
+
if (await import_promises36.default.realpath(file) !== file)
|
|
36436
|
+
throw new Error(`Research cleanup refuses symlinks: ${file}`);
|
|
36437
|
+
const stat = await import_promises36.default.lstat(file);
|
|
36438
|
+
if (!stat.isFile() || stat.size !== entry.bytes || await fileSha256(file, stat.size) !== entry.sha256) {
|
|
36439
|
+
throw new Error(
|
|
36440
|
+
`Disposable research file checksum/size mismatch: ${file}`
|
|
36441
|
+
);
|
|
36442
|
+
}
|
|
36443
|
+
return { entry, file, mtimeMs: stat.mtimeMs, ino: stat.ino };
|
|
36444
|
+
});
|
|
36445
|
+
await assertNoResearchFileConsumers(checked.map((entry) => entry.file));
|
|
36446
|
+
const receipt = {
|
|
36447
|
+
schema: "tradejs-research-cleanup-receipt/v1",
|
|
36448
|
+
researchId: options.research.researchId,
|
|
36449
|
+
completedAt: options.research.completedAt,
|
|
36450
|
+
...retired ? { retirement: options.research.retirement } : {},
|
|
36451
|
+
journalPath,
|
|
36452
|
+
permanentArtifacts: options.research.permanentArtifacts,
|
|
36453
|
+
scope: "reported aggregates and frozen candidates; new trade-level analyses require a rerun",
|
|
36454
|
+
status: "planned",
|
|
36455
|
+
files: checked.map(({ entry, file }) => ({
|
|
36456
|
+
path: file,
|
|
36457
|
+
sha256: entry.sha256,
|
|
36458
|
+
bytes: entry.bytes,
|
|
36459
|
+
removed: false
|
|
36460
|
+
}))
|
|
36461
|
+
};
|
|
36462
|
+
if (!options.apply) return receipt;
|
|
36463
|
+
await import_promises36.default.mkdir(import_node_path35.default.dirname(receiptPath2), { recursive: true });
|
|
36464
|
+
if (await import_promises36.default.realpath(import_node_path35.default.dirname(receiptPath2)) !== import_node_path35.default.dirname(receiptPath2)) {
|
|
36465
|
+
throw new Error("Cleanup receipt refuses symlinked directories");
|
|
36466
|
+
}
|
|
36467
|
+
const lock = await import_promises36.default.open(`${receiptPath2}.lock`, "wx");
|
|
36468
|
+
let journal;
|
|
36469
|
+
const writeReceipt = async () => {
|
|
36470
|
+
const temp = `${receiptPath2}.${process.pid}.tmp`;
|
|
36471
|
+
await import_promises36.default.writeFile(temp, `${JSON.stringify(receipt, null, 2)}
|
|
36472
|
+
`, "utf8");
|
|
36473
|
+
await import_promises36.default.rename(temp, receiptPath2);
|
|
36474
|
+
};
|
|
36475
|
+
try {
|
|
36476
|
+
journal = await import_promises36.default.open(journalPath, "wx");
|
|
36477
|
+
receipt.status = "applying";
|
|
36478
|
+
await writeReceipt();
|
|
36479
|
+
for (let index = 0; index < checked.length; index += 1) {
|
|
36480
|
+
const { file, entry, ino, mtimeMs } = checked[index];
|
|
36481
|
+
const stat = await import_promises36.default.lstat(file);
|
|
36482
|
+
if (!stat.isFile() || stat.ino !== ino || stat.mtimeMs !== mtimeMs || stat.size !== entry.bytes) {
|
|
36483
|
+
throw new Error(`Research file changed during cleanup: ${file}`);
|
|
36484
|
+
}
|
|
36485
|
+
await import_promises36.default.unlink(file);
|
|
36486
|
+
receipt.files[index].removed = true;
|
|
36487
|
+
await journal.write(`${JSON.stringify(receipt.files[index])}
|
|
36488
|
+
`);
|
|
36489
|
+
}
|
|
36490
|
+
receipt.status = "completed";
|
|
36491
|
+
await writeReceipt();
|
|
36492
|
+
return receipt;
|
|
36493
|
+
} catch (error) {
|
|
36494
|
+
if (journal) await writeReceipt();
|
|
36495
|
+
throw error;
|
|
36496
|
+
} finally {
|
|
36497
|
+
await journal?.close();
|
|
36498
|
+
await lock.close();
|
|
36499
|
+
await import_promises36.default.unlink(`${receiptPath2}.lock`);
|
|
36500
|
+
}
|
|
36501
|
+
};
|
|
36502
|
+
}
|
|
36503
|
+
});
|
|
36504
|
+
|
|
36083
36505
|
// src/scripts/strategyRelease.ts
|
|
36084
36506
|
var strategyRelease_exports = {};
|
|
36085
36507
|
__export(strategyRelease_exports, {
|
|
36086
36508
|
main: () => main44,
|
|
36087
36509
|
runStrategyReleaseCommand: () => runStrategyReleaseCommand
|
|
36088
36510
|
});
|
|
36089
|
-
var
|
|
36511
|
+
var import_promises37, import_node_fs6, import_node_readline3, import_node_path36, import_chalk50, valueAfter2, required3, writeJsonAtomic3, runStrategyReleaseCommand, printUsage2, main44;
|
|
36090
36512
|
var init_strategyRelease2 = __esm({
|
|
36091
36513
|
"src/scripts/strategyRelease.ts"() {
|
|
36092
36514
|
"use strict";
|
|
36093
|
-
|
|
36515
|
+
import_promises37 = __toESM(require("fs/promises"));
|
|
36094
36516
|
import_node_fs6 = require("fs");
|
|
36095
36517
|
import_node_readline3 = require("readline");
|
|
36096
|
-
|
|
36518
|
+
import_node_path36 = __toESM(require("path"));
|
|
36097
36519
|
import_chalk50 = __toESM(require("chalk"));
|
|
36520
|
+
init_researchRetention();
|
|
36098
36521
|
init_strategyRelease();
|
|
36099
36522
|
valueAfter2 = (argv2, name) => {
|
|
36100
36523
|
const index = argv2.indexOf(name);
|
|
@@ -36106,17 +36529,17 @@ var init_strategyRelease2 = __esm({
|
|
|
36106
36529
|
};
|
|
36107
36530
|
writeJsonAtomic3 = async (filePath, value) => {
|
|
36108
36531
|
const temporaryPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
36109
|
-
await
|
|
36110
|
-
await
|
|
36532
|
+
await import_promises37.default.mkdir(import_node_path36.default.dirname(filePath), { recursive: true });
|
|
36533
|
+
await import_promises37.default.writeFile(
|
|
36111
36534
|
temporaryPath,
|
|
36112
36535
|
`${JSON.stringify(value, null, 2)}
|
|
36113
36536
|
`,
|
|
36114
36537
|
"utf8"
|
|
36115
36538
|
);
|
|
36116
|
-
await
|
|
36539
|
+
await import_promises37.default.rename(temporaryPath, filePath);
|
|
36117
36540
|
};
|
|
36118
36541
|
runStrategyReleaseCommand = async (options) => {
|
|
36119
|
-
const inputPath =
|
|
36542
|
+
const inputPath = import_node_path36.default.resolve(options.inputPath);
|
|
36120
36543
|
if (options.command === "verify") {
|
|
36121
36544
|
const envelope = await verifyStrategyReleaseEnvelope(inputPath);
|
|
36122
36545
|
return {
|
|
@@ -36154,7 +36577,7 @@ var init_strategyRelease2 = __esm({
|
|
|
36154
36577
|
endTime,
|
|
36155
36578
|
days: options.days?.length ? options.days : [7, 30, 90]
|
|
36156
36579
|
});
|
|
36157
|
-
const outputPath =
|
|
36580
|
+
const outputPath = import_node_path36.default.resolve(
|
|
36158
36581
|
options.outputPath ?? "output/strategy-monitoring-profile.json"
|
|
36159
36582
|
);
|
|
36160
36583
|
await writeJsonAtomic3(outputPath, profile);
|
|
@@ -36165,22 +36588,40 @@ var init_strategyRelease2 = __esm({
|
|
|
36165
36588
|
profile
|
|
36166
36589
|
};
|
|
36167
36590
|
}
|
|
36168
|
-
const input = JSON.parse(await
|
|
36591
|
+
const input = JSON.parse(await import_promises37.default.readFile(inputPath, "utf8"));
|
|
36169
36592
|
if (options.command === "decide") {
|
|
36170
36593
|
const decision = await deriveStrategyReleaseResearchDecision(input);
|
|
36171
36594
|
if (options.outputPath) {
|
|
36172
|
-
await writeJsonAtomic3(
|
|
36595
|
+
await writeJsonAtomic3(import_node_path36.default.resolve(options.outputPath), decision);
|
|
36173
36596
|
}
|
|
36174
36597
|
return {
|
|
36175
36598
|
kind: "decided",
|
|
36176
36599
|
...decision,
|
|
36177
|
-
outputPath: options.outputPath ?
|
|
36600
|
+
outputPath: options.outputPath ? import_node_path36.default.resolve(options.outputPath) : null
|
|
36178
36601
|
};
|
|
36179
36602
|
}
|
|
36180
36603
|
if (options.command === "retention") {
|
|
36181
36604
|
const plan = planStrategyEvidenceRetention(input);
|
|
36182
|
-
|
|
36183
|
-
|
|
36605
|
+
const researchEntries = plan.delete.filter(
|
|
36606
|
+
(entry) => entry.kind === "research_payload" || entry.kind === "research_cache"
|
|
36607
|
+
);
|
|
36608
|
+
const receiptPath2 = options.outputPath ?? `${inputPath}.receipt.json`;
|
|
36609
|
+
if (researchEntries.length) {
|
|
36610
|
+
if (researchEntries.length !== plan.delete.length) {
|
|
36611
|
+
throw new Error(
|
|
36612
|
+
"Research cleanup requires a separate inventory from runtime retention"
|
|
36613
|
+
);
|
|
36614
|
+
}
|
|
36615
|
+
await applyResearchRetention({
|
|
36616
|
+
projectRoot: process.env.PROJECT_CWD ?? process.cwd(),
|
|
36617
|
+
research: input.research,
|
|
36618
|
+
entries: researchEntries,
|
|
36619
|
+
receiptPath: receiptPath2,
|
|
36620
|
+
apply: Boolean(options.apply),
|
|
36621
|
+
protectedPaths: [inputPath]
|
|
36622
|
+
});
|
|
36623
|
+
} else if (options.apply) {
|
|
36624
|
+
await Promise.all(plan.delete.map((entry) => import_promises37.default.rm(entry.path)));
|
|
36184
36625
|
}
|
|
36185
36626
|
return {
|
|
36186
36627
|
kind: "retention",
|
|
@@ -36188,17 +36629,18 @@ var init_strategyRelease2 = __esm({
|
|
|
36188
36629
|
keepCount: plan.keep.length,
|
|
36189
36630
|
deleteCount: plan.delete.length,
|
|
36190
36631
|
bytesReclaimable: plan.bytesReclaimable,
|
|
36191
|
-
delete: plan.delete.map((entry) => entry.path)
|
|
36632
|
+
delete: plan.delete.map((entry) => entry.path),
|
|
36633
|
+
...researchEntries.length && options.apply ? { receiptPath: receiptPath2 } : {}
|
|
36192
36634
|
};
|
|
36193
36635
|
}
|
|
36194
36636
|
if (options.command === "diagnose") {
|
|
36195
36637
|
const diagnosis = buildStrategyLiveDiagnosis(input);
|
|
36196
|
-
const outputPath =
|
|
36638
|
+
const outputPath = import_node_path36.default.resolve(
|
|
36197
36639
|
options.outputPath ?? "output/strategy-live-diagnosis.json"
|
|
36198
36640
|
);
|
|
36199
36641
|
await writeJsonAtomic3(outputPath, diagnosis);
|
|
36200
36642
|
const published2 = options.rootDir ? await publishStrategyLiveDiagnosis({
|
|
36201
|
-
rootDir:
|
|
36643
|
+
rootDir: import_node_path36.default.resolve(options.rootDir),
|
|
36202
36644
|
diagnosis,
|
|
36203
36645
|
sourceArtifacts: input.sourceArtifacts ?? []
|
|
36204
36646
|
}) : null;
|
|
@@ -36215,7 +36657,7 @@ var init_strategyRelease2 = __esm({
|
|
|
36215
36657
|
evidence: await collectReleaseEvidenceReferences(input.evidence ?? [])
|
|
36216
36658
|
});
|
|
36217
36659
|
const published = await publishStrategyRelease({
|
|
36218
|
-
rootDir:
|
|
36660
|
+
rootDir: import_node_path36.default.resolve(options.rootDir ?? "data/strategy-release"),
|
|
36219
36661
|
manifest
|
|
36220
36662
|
});
|
|
36221
36663
|
return {
|
|
@@ -36275,12 +36717,12 @@ __export(serverHealth_exports, {
|
|
|
36275
36717
|
main: () => main45,
|
|
36276
36718
|
resolveServerHealthThresholds: () => resolveServerHealthThresholds
|
|
36277
36719
|
});
|
|
36278
|
-
var import_config10,
|
|
36720
|
+
var import_config10, import_node_child_process11, import_node_os3, import_node_fs7, import_args34, import_redis20, DEFAULT_STATE, DEFAULT_THRESHOLDS, escapeHtml6, formatPctValue, formatLoadPerCore, formatGiB, formatDuration2, readDiskUsage, parseMeminfoBytes, readMemorySnapshot, runDiagnosticCommand, runDiagnosticCommands, collectServerHealthSnapshot, buildHumanSummaryLines, evaluateServerHealth, shouldRecover, buildAlertMessage, buildRecoveryMessage, buildServerHealthDiagnostics, getStateKey, toFiniteNumber3, resolveServerHealthThresholds, main45;
|
|
36279
36721
|
var init_serverHealth = __esm({
|
|
36280
36722
|
"src/scripts/serverHealth.ts"() {
|
|
36281
36723
|
"use strict";
|
|
36282
36724
|
import_config10 = require("dotenv/config");
|
|
36283
|
-
|
|
36725
|
+
import_node_child_process11 = require("child_process");
|
|
36284
36726
|
import_node_os3 = __toESM(require("os"));
|
|
36285
36727
|
import_node_fs7 = require("fs");
|
|
36286
36728
|
import_args34 = __toESM(require("args"));
|
|
@@ -36317,21 +36759,21 @@ var init_serverHealth = __esm({
|
|
|
36317
36759
|
}
|
|
36318
36760
|
return `${minutes}m`;
|
|
36319
36761
|
};
|
|
36320
|
-
readDiskUsage = (
|
|
36762
|
+
readDiskUsage = (path47) => {
|
|
36321
36763
|
try {
|
|
36322
|
-
const stats = (0, import_node_fs7.statfsSync)(
|
|
36764
|
+
const stats = (0, import_node_fs7.statfsSync)(path47);
|
|
36323
36765
|
const totalBlocks = Number(stats.blocks ?? 0);
|
|
36324
36766
|
const availableBlocks = Number(stats.bavail ?? 0);
|
|
36325
36767
|
if (totalBlocks <= 0) {
|
|
36326
|
-
return { path:
|
|
36768
|
+
return { path: path47, usedPct: null };
|
|
36327
36769
|
}
|
|
36328
36770
|
const usedPct = (totalBlocks - Math.max(0, availableBlocks)) / totalBlocks * 100;
|
|
36329
36771
|
return {
|
|
36330
|
-
path:
|
|
36772
|
+
path: path47,
|
|
36331
36773
|
usedPct: Number.isFinite(usedPct) ? usedPct : null
|
|
36332
36774
|
};
|
|
36333
36775
|
} catch {
|
|
36334
|
-
return { path:
|
|
36776
|
+
return { path: path47, usedPct: null };
|
|
36335
36777
|
}
|
|
36336
36778
|
};
|
|
36337
36779
|
parseMeminfoBytes = (value) => {
|
|
@@ -36396,7 +36838,7 @@ var init_serverHealth = __esm({
|
|
|
36396
36838
|
}
|
|
36397
36839
|
};
|
|
36398
36840
|
runDiagnosticCommand = (command, args39) => {
|
|
36399
|
-
const output = (0,
|
|
36841
|
+
const output = (0, import_node_child_process11.execFileSync)(command, args39, {
|
|
36400
36842
|
encoding: "utf8",
|
|
36401
36843
|
timeout: 5e3,
|
|
36402
36844
|
maxBuffer: 1024 * 1024,
|
|
@@ -38083,12 +38525,12 @@ __export(runtimeParity_exports, {
|
|
|
38083
38525
|
main: () => main46,
|
|
38084
38526
|
runtimeParity: () => runtimeParity
|
|
38085
38527
|
});
|
|
38086
|
-
var import_config11,
|
|
38528
|
+
var import_config11, import_node_crypto19, import_args35, import_chalk52, import_constants19, import_time13, import_logger7, import_redis21, import_cli12, import_backtest7, import_connectors15, flags31, interval3, projectRoot16, DEFAULT_LOOKBACK_DAYS, DETAIL_LIMIT2, DEFAULT_REPLAY_ENV, resolveParityConnectorName, createConnector, buildReplayAiAnalyses, formatReplayEnvSummary, buildReplayConfig, warmReplayHistory, runtimeParity, main46;
|
|
38087
38529
|
var init_runtimeParity2 = __esm({
|
|
38088
38530
|
"src/scripts/runtimeParity.ts"() {
|
|
38089
38531
|
"use strict";
|
|
38090
38532
|
import_config11 = require("dotenv/config");
|
|
38091
|
-
|
|
38533
|
+
import_node_crypto19 = require("crypto");
|
|
38092
38534
|
import_args35 = __toESM(require("args"));
|
|
38093
38535
|
import_chalk52 = __toESM(require("chalk"));
|
|
38094
38536
|
import_constants19 = require("@tradejs/core/constants");
|
|
@@ -38471,9 +38913,9 @@ var init_runtimeParity2 = __esm({
|
|
|
38471
38913
|
start: window.start,
|
|
38472
38914
|
end: window.end
|
|
38473
38915
|
},
|
|
38474
|
-
name: `${target.symbol}_${target.strategy}_${(0,
|
|
38475
|
-
testId: (0,
|
|
38476
|
-
testSuiteId: (0,
|
|
38916
|
+
name: `${target.symbol}_${target.strategy}_${(0, import_node_crypto19.randomUUID)().slice(0, 8)}`,
|
|
38917
|
+
testId: (0, import_node_crypto19.randomUUID)().slice(0, 8),
|
|
38918
|
+
testSuiteId: (0, import_node_crypto19.randomUUID)().slice(0, 8),
|
|
38477
38919
|
strategyName: target.strategy,
|
|
38478
38920
|
strategyConfig: replayConfig,
|
|
38479
38921
|
connectorName,
|