@tradejs/cli 3.1.0 → 3.1.2

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.
@@ -46,7 +46,7 @@ module.exports = __toCommonJS(coreResearch_exports);
46
46
 
47
47
  // src/lib/coreResearch/orchestrator.ts
48
48
  var import_promises4 = __toESM(require("fs/promises"));
49
- var import_node_path5 = __toESM(require("path"));
49
+ var import_node_path6 = __toESM(require("path"));
50
50
  var import_node_child_process = require("child_process");
51
51
  var import_node_crypto5 = require("crypto");
52
52
  var import_coreResearch = require("@tradejs/infra/coreResearch");
@@ -2116,6 +2116,10 @@ var summarizeCoreResearchTrace = async (filePaths = []) => {
2116
2116
  };
2117
2117
  };
2118
2118
 
2119
+ // src/lib/researchRoots.ts
2120
+ var import_node_path5 = __toESM(require("path"));
2121
+ var SOURCE_REPOSITORY_ROOT_ENV = "TRADEJS_SOURCE_REPOSITORY_ROOT";
2122
+
2119
2123
  // src/lib/coreResearch/orchestrator.ts
2120
2124
  var summarizeSupplementalFiles = async (params) => {
2121
2125
  const loaded = await readCoreResearchVariant({
@@ -2308,7 +2312,7 @@ var analyzeCoreResearchPrepared = async (spec, options = {}) => {
2308
2312
  const primarySourceHashes = Object.fromEntries(
2309
2313
  analyses.flatMap(
2310
2314
  (analysis) => analysis.files.map((file) => [
2311
- import_node_path5.default.relative(paths.researchDir, file.path),
2315
+ import_node_path6.default.relative(paths.researchDir, file.path),
2312
2316
  file.sha256
2313
2317
  ])
2314
2318
  )
@@ -2327,8 +2331,8 @@ var analyzeCoreResearchPrepared = async (spec, options = {}) => {
2327
2331
  const supplementalSourceHashes = Object.fromEntries(
2328
2332
  await Promise.all(
2329
2333
  supplementalSourcePaths.map(async (filePath) => [
2330
- import_node_path5.default.relative(paths.researchDir, import_node_path5.default.resolve(filePath)),
2331
- await sha256File(import_node_path5.default.resolve(filePath))
2334
+ import_node_path6.default.relative(paths.researchDir, import_node_path6.default.resolve(filePath)),
2335
+ await sha256File(import_node_path6.default.resolve(filePath))
2332
2336
  ])
2333
2337
  )
2334
2338
  );
@@ -2405,7 +2409,7 @@ var analyzeCoreResearchPrepared = async (spec, options = {}) => {
2405
2409
  "trades.jsonl": await sha256File(paths.tradesPath),
2406
2410
  "report.html": await sha256File(paths.reportPath)
2407
2411
  };
2408
- const resolvedRunsPath = import_node_path5.default.join(paths.researchDir, "resolved-runs.json");
2412
+ const resolvedRunsPath = import_node_path6.default.join(paths.researchDir, "resolved-runs.json");
2409
2413
  try {
2410
2414
  artifactHashes["resolved-runs.json"] = await sha256File(resolvedRunsPath);
2411
2415
  } catch (error) {
@@ -2415,7 +2419,7 @@ var analyzeCoreResearchPrepared = async (spec, options = {}) => {
2415
2419
  for (const name of await import_promises4.default.readdir(paths.runLogDir)) {
2416
2420
  if (!name.endsWith(".log")) continue;
2417
2421
  artifactHashes[`runs/${name}`] = await sha256File(
2418
- import_node_path5.default.join(paths.runLogDir, name)
2422
+ import_node_path6.default.join(paths.runLogDir, name)
2419
2423
  );
2420
2424
  }
2421
2425
  } catch (error) {
@@ -2472,12 +2476,14 @@ var analyzeCoreResearch = async (spec, options = {}) => {
2472
2476
  }
2473
2477
  };
2474
2478
  var createCoreResearchSpecTemplate = (params) => {
2475
- const rootDir = "data/research/core";
2476
- const projectRoot = process.cwd();
2479
+ const rootDir = import_node_path6.default.relative(
2480
+ import_node_path6.default.resolve(params.projectRoot),
2481
+ import_node_path6.default.join(import_node_path6.default.resolve(params.projectRoot), "data", "research", "core")
2482
+ ).replace(/\\/g, "/");
2477
2483
  const lineage = (() => {
2478
2484
  try {
2479
2485
  const gitSha = (0, import_node_child_process.execFileSync)("git", ["rev-parse", "HEAD"], {
2480
- cwd: projectRoot,
2486
+ cwd: params.sourceRepositoryRoot,
2481
2487
  encoding: "utf8",
2482
2488
  stdio: ["ignore", "pipe", "ignore"]
2483
2489
  }).trim();
@@ -2485,13 +2491,23 @@ var createCoreResearchSpecTemplate = (params) => {
2485
2491
  "git",
2486
2492
  ["diff", "--binary", "--no-ext-diff", "HEAD"],
2487
2493
  {
2488
- cwd: projectRoot,
2494
+ cwd: params.sourceRepositoryRoot,
2489
2495
  encoding: "utf8",
2490
2496
  stdio: ["ignore", "pipe", "ignore"]
2491
2497
  }
2492
2498
  );
2499
+ const sourceRepository = (0, import_node_child_process.execFileSync)(
2500
+ "git",
2501
+ ["remote", "get-url", "origin"],
2502
+ {
2503
+ cwd: params.sourceRepositoryRoot,
2504
+ encoding: "utf8",
2505
+ stdio: ["ignore", "pipe", "ignore"]
2506
+ }
2507
+ ).trim();
2493
2508
  return {
2494
2509
  gitSha,
2510
+ ...sourceRepository ? { sourceRepository } : {},
2495
2511
  ...dirtyDiff ? {
2496
2512
  dirtyDiffSha256: (0, import_node_crypto5.createHash)("sha256").update(dirtyDiff).digest("hex")
2497
2513
  } : {}
@@ -2592,11 +2608,11 @@ var createCoreResearchSpecTemplate = (params) => {
2592
2608
  };
2593
2609
  var runCommand = async (params) => {
2594
2610
  if (!params.command.length) throw new Error("Cannot run an empty command");
2595
- await import_promises4.default.mkdir(import_node_path5.default.dirname(params.logPath), { recursive: true });
2611
+ await import_promises4.default.mkdir(import_node_path6.default.dirname(params.logPath), { recursive: true });
2596
2612
  const chunks = [];
2597
2613
  const child = (0, import_node_child_process.spawn)(params.command[0], params.command.slice(1), {
2598
2614
  cwd: params.cwd,
2599
- env: process.env,
2615
+ env: { ...process.env, ...params.env },
2600
2616
  stdio: ["ignore", "pipe", "pipe"]
2601
2617
  });
2602
2618
  const capture = (chunk) => {
@@ -2664,7 +2680,7 @@ var validateCoreResearchRunCommand = (params) => {
2664
2680
  };
2665
2681
  var runCoreResearch = async (params) => {
2666
2682
  const { spec } = params;
2667
- const cwd = import_node_path5.default.resolve(params.cwd ?? process.cwd());
2683
+ const cwd = import_node_path6.default.resolve(params.cwd ?? process.cwd());
2668
2684
  const prepared = await prepareCoreResearch(spec);
2669
2685
  const resolvedVariants = [];
2670
2686
  for (const variant of spec.variants) {
@@ -2682,7 +2698,7 @@ var runCoreResearch = async (params) => {
2682
2698
  artifactHashes: { variant: sha256Json(variant) }
2683
2699
  });
2684
2700
  let runId = "";
2685
- const backtestLogPath = import_node_path5.default.join(
2701
+ const backtestLogPath = import_node_path6.default.join(
2686
2702
  prepared.paths.runLogDir,
2687
2703
  `${variant.id}-backtest.log`
2688
2704
  );
@@ -2691,6 +2707,14 @@ var runCoreResearch = async (params) => {
2691
2707
  command: variant.command,
2692
2708
  cwd,
2693
2709
  logPath: backtestLogPath,
2710
+ env: {
2711
+ PROJECT_CWD: cwd,
2712
+ ...params.sourceRepositoryRoot ? {
2713
+ [SOURCE_REPOSITORY_ROOT_ENV]: import_node_path6.default.resolve(
2714
+ params.sourceRepositoryRoot
2715
+ )
2716
+ } : {}
2717
+ },
2694
2718
  onLine: (line) => {
2695
2719
  const match = line.match(
2696
2720
  /backtest run id:\s*([0-9]{12}-[a-f0-9]{8})/i
@@ -2701,12 +2725,12 @@ var runCoreResearch = async (params) => {
2701
2725
  if (!runId) {
2702
2726
  throw new Error(`Backtest for ${variant.id} did not report a run id`);
2703
2727
  }
2704
- const exportLogPath = import_node_path5.default.join(
2728
+ const exportLogPath = import_node_path6.default.join(
2705
2729
  prepared.paths.runLogDir,
2706
2730
  `${variant.id}-export.log`
2707
2731
  );
2708
2732
  const exportParts = [];
2709
- const cliPath = import_node_path5.default.resolve(process.argv[1]);
2733
+ const cliPath = import_node_path6.default.resolve(process.argv[1]);
2710
2734
  await runCommand({
2711
2735
  command: [
2712
2736
  process.execPath,
@@ -2723,9 +2747,17 @@ var runCoreResearch = async (params) => {
2723
2747
  ],
2724
2748
  cwd,
2725
2749
  logPath: exportLogPath,
2750
+ env: {
2751
+ PROJECT_CWD: cwd,
2752
+ ...params.sourceRepositoryRoot ? {
2753
+ [SOURCE_REPOSITORY_ROOT_ENV]: import_node_path6.default.resolve(
2754
+ params.sourceRepositoryRoot
2755
+ )
2756
+ } : {}
2757
+ },
2726
2758
  onLine: (line) => {
2727
2759
  const match = line.match(/^part\d+:\s+(.+)$/);
2728
- if (match) exportParts.push(import_node_path5.default.resolve(cwd, match[1].trim()));
2760
+ if (match) exportParts.push(import_node_path6.default.resolve(cwd, match[1].trim()));
2729
2761
  }
2730
2762
  });
2731
2763
  if (!exportParts.length) {
@@ -2736,7 +2768,7 @@ var runCoreResearch = async (params) => {
2736
2768
  const traceFiles = await (0, import_coreResearch.listCoreResearchTraceFiles)({
2737
2769
  strategyName: spec.strategy,
2738
2770
  runId,
2739
- outDir: import_node_path5.default.resolve(cwd, "data/research/core/trace")
2771
+ outDir: import_node_path6.default.resolve(cwd, "data/research/core/trace")
2740
2772
  });
2741
2773
  resolvedVariants.push({
2742
2774
  ...variant,
@@ -2756,7 +2788,7 @@ var runCoreResearch = async (params) => {
2756
2788
  ...Object.fromEntries(
2757
2789
  await Promise.all(
2758
2790
  exportParts.map(async (filePath) => [
2759
- import_node_path5.default.basename(filePath),
2791
+ import_node_path6.default.basename(filePath),
2760
2792
  await sha256File(filePath)
2761
2793
  ])
2762
2794
  )
@@ -2775,7 +2807,7 @@ var runCoreResearch = async (params) => {
2775
2807
  }
2776
2808
  }
2777
2809
  await writeJsonAtomic(
2778
- import_node_path5.default.join(prepared.paths.researchDir, "resolved-runs.json"),
2810
+ import_node_path6.default.join(prepared.paths.researchDir, "resolved-runs.json"),
2779
2811
  {
2780
2812
  schema: "tradejs-core-research-resolved-runs/v1",
2781
2813
  researchId: spec.researchId,
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/lib/researchRoots.ts
31
+ var researchRoots_exports = {};
32
+ __export(researchRoots_exports, {
33
+ SOURCE_REPOSITORY_ROOT_ENV: () => SOURCE_REPOSITORY_ROOT_ENV,
34
+ resolveResearchRoots: () => resolveResearchRoots
35
+ });
36
+ module.exports = __toCommonJS(researchRoots_exports);
37
+ var import_node_path = __toESM(require("path"));
38
+ var SOURCE_REPOSITORY_ROOT_ENV = "TRADEJS_SOURCE_REPOSITORY_ROOT";
39
+ var firstNonEmpty = (...values) => values.map((value) => String(value || "").trim()).find(Boolean);
40
+ var resolveResearchRoots = (options = {}) => {
41
+ const cwd = import_node_path.default.resolve(options.cwd || process.cwd());
42
+ const env = options.env || process.env;
43
+ const projectRoot = import_node_path.default.resolve(
44
+ firstNonEmpty(options.projectRoot, env.PROJECT_CWD, cwd) || cwd
45
+ );
46
+ const sourceRepositoryRoot = import_node_path.default.resolve(
47
+ firstNonEmpty(
48
+ options.sourceRepositoryRoot,
49
+ env[SOURCE_REPOSITORY_ROOT_ENV],
50
+ cwd
51
+ ) || cwd
52
+ );
53
+ return { projectRoot, sourceRepositoryRoot };
54
+ };
55
+ // Annotate the CommonJS export names for ESM import in node:
56
+ 0 && (module.exports = {
57
+ SOURCE_REPOSITORY_ROOT_ENV,
58
+ resolveResearchRoots
59
+ });
@@ -272,14 +272,29 @@ var resolveRuntimeGateFingerprint = async ({
272
272
  gateFingerprintCache.set(cacheKey, result);
273
273
  return result;
274
274
  };
275
- var buildRuntimeLineage = async ({
275
+ async function buildRuntimeLineage({
276
276
  projectRoot,
277
277
  strategyName,
278
278
  compositionId,
279
+ releaseVersion,
280
+ strategyPackageVersion,
281
+ runtimePackageVersion,
279
282
  config,
280
283
  runContext,
281
284
  env = process.env
282
- }) => {
285
+ }) {
286
+ if (releaseVersion != null) {
287
+ if (!Number.isSafeInteger(releaseVersion) || releaseVersion <= 0) {
288
+ throw new Error(`Invalid runtime releaseVersion: ${releaseVersion}`);
289
+ }
290
+ return {
291
+ schemaVersion: 2,
292
+ releaseVersion,
293
+ strategyPackageVersion,
294
+ runtimePackageVersion,
295
+ maxLossValue: resolveRuntimeMaxLossValue(config)
296
+ };
297
+ }
283
298
  const git = resolveGitLineage(projectRoot);
284
299
  const hyperliquidPerpUniverseFingerprint = typeof import_strategies.getHyperliquidPerpUniverseSnapshot === "function" ? (0, import_strategies.getHyperliquidPerpUniverseSnapshot)().fingerprint : await resolveSnapshotFingerprint(
285
300
  projectRoot,
@@ -314,8 +329,8 @@ var buildRuntimeLineage = async ({
314
329
  contextFingerprint: fingerprintRuntimeValue(context),
315
330
  maxLossValue: resolveRuntimeMaxLossValue(config)
316
331
  };
317
- };
318
- var runtimeLineageKey = (lineage) => [
332
+ }
333
+ var runtimeLineageKey = (lineage) => lineage.schemaVersion === 2 ? ["v2", lineage.releaseVersion].join(":") : [
319
334
  lineage.schemaVersion,
320
335
  lineage.compositionId ?? "unbound-composition",
321
336
  lineage.gitSha ?? "unknown",
@@ -41,7 +41,7 @@ var buildRuntimeModeStrategyConfig = ({
41
41
  ...strategyConfig,
42
42
  ENV: env,
43
43
  MAKE_ORDERS: makeOrders,
44
- INTERVAL: interval,
44
+ INTERVAL: strategyConfig.INTERVAL ?? interval,
45
45
  ...typeof recordRuntimeTrades === "boolean" ? { RECORD_RUNTIME_TRADES: recordRuntimeTrades } : {},
46
46
  ...aiReplayAnalyses?.length ? { AI_REPLAY_ANALYSES: aiReplayAnalyses } : {}
47
47
  });
@@ -63,7 +63,8 @@ var toRuntimeSignalBucketRef = (signal) => ({
63
63
  symbol: signal.symbol,
64
64
  strategy: signal.strategy,
65
65
  timestamp: signal.timestamp,
66
- ...signal.runtimeConfigId && signal.runtimeConfigId !== "config" ? { runtimeConfigId: signal.runtimeConfigId } : {}
66
+ ...signal.runtimeConfigId && signal.runtimeConfigId !== "config" ? { runtimeConfigId: signal.runtimeConfigId } : {},
67
+ ...signal.runtimeReleaseVersion ? { runtimeReleaseVersion: signal.runtimeReleaseVersion } : {}
67
68
  });
68
69
  var shouldStoreRuntimeSignalDiagnostics = (signal) => signal.orderStatus === "completed" || signal.orderStatus === "failed";
69
70
  var toStoredRuntimeSignal = (signal) => {
@@ -37,7 +37,7 @@ var import_args = __toESM(require("args"));
37
37
  var import_chalk = __toESM(require("chalk"));
38
38
  var import_promises = __toESM(require("fs/promises"));
39
39
  var import_node_os = __toESM(require("os"));
40
- var import_node_path = __toESM(require("path"));
40
+ var import_node_path2 = __toESM(require("path"));
41
41
  var import_node_child_process = require("child_process");
42
42
  var import_constants = require("@tradejs/core/constants");
43
43
  var import_aiEndpoints = require("@tradejs/core/aiEndpoints");
@@ -240,6 +240,26 @@ ${diffText}`)) {
240
240
  return changedFiles;
241
241
  };
242
242
 
243
+ // src/lib/researchRoots.ts
244
+ var import_node_path = __toESM(require("path"));
245
+ var SOURCE_REPOSITORY_ROOT_ENV = "TRADEJS_SOURCE_REPOSITORY_ROOT";
246
+ var firstNonEmpty = (...values) => values.map((value) => String(value || "").trim()).find(Boolean);
247
+ var resolveResearchRoots = (options = {}) => {
248
+ const cwd = import_node_path.default.resolve(options.cwd || process.cwd());
249
+ const env = options.env || process.env;
250
+ const projectRoot2 = import_node_path.default.resolve(
251
+ firstNonEmpty(options.projectRoot, env.PROJECT_CWD, cwd) || cwd
252
+ );
253
+ const sourceRepositoryRoot = import_node_path.default.resolve(
254
+ firstNonEmpty(
255
+ options.sourceRepositoryRoot,
256
+ env[SOURCE_REPOSITORY_ROOT_ENV],
257
+ cwd
258
+ ) || cwd
259
+ );
260
+ return { projectRoot: projectRoot2, sourceRepositoryRoot };
261
+ };
262
+
243
263
  // src/scripts/agentRun.ts
244
264
  import_args.default.example(
245
265
  "yarn cli:node8g agent-run --runId 1710000000000-trendline --strategy TrendLine",
@@ -250,7 +270,7 @@ import_args.default.option(["r", "runId"], "Research run id");
250
270
  import_args.default.option(["s", "strategy"], "Strategy name");
251
271
  import_args.default.option("json", "Print structured JSON summary", false);
252
272
  var flags = import_args.default.parse(process.argv);
253
- var projectRoot = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
273
+ var { projectRoot } = resolveResearchRoots();
254
274
  var AGENT_SYSTEM_PROMPT = `You are a senior TypeScript trading research coding agent working inside a standalone TradeJS strategy repository.
255
275
 
256
276
  Output ONLY one of:
@@ -328,7 +348,7 @@ var listFilesRecursive = async (targetPath) => {
328
348
  const entries = await import_promises.default.readdir(targetPath, { withFileTypes: true });
329
349
  const nested = await Promise.all(
330
350
  entries.map(async (entry) => {
331
- const absolutePath = import_node_path.default.join(targetPath, entry.name);
351
+ const absolutePath = import_node_path2.default.join(targetPath, entry.name);
332
352
  if (entry.isDirectory()) {
333
353
  return listFilesRecursive(absolutePath);
334
354
  }
@@ -341,7 +361,7 @@ var listFilesRecursive = async (targetPath) => {
341
361
  }
342
362
  };
343
363
  var collectStrategyContextFiles = async (worktreePath, strategy) => {
344
- const strategyRoot = import_node_path.default.join(worktreePath, "src", strategy);
364
+ const strategyRoot = import_node_path2.default.join(worktreePath, "src", strategy);
345
365
  const strategyFiles = await listFilesRecursive(strategyRoot);
346
366
  const files = strategyFiles.filter(
347
367
  (filePath) => /\.(ts|tsx|md)$/.test(filePath)
@@ -349,7 +369,7 @@ var collectStrategyContextFiles = async (worktreePath, strategy) => {
349
369
  return [...new Set(files)].sort((left, right) => left.localeCompare(right));
350
370
  };
351
371
  var renderFileContext = async (worktreePath, filePath) => {
352
- const relativePath = import_node_path.default.relative(worktreePath, filePath).replace(/\\/g, "/");
372
+ const relativePath = import_node_path2.default.relative(worktreePath, filePath).replace(/\\/g, "/");
353
373
  const content = await import_promises.default.readFile(filePath, "utf8");
354
374
  return [
355
375
  `=== FILE: ${relativePath} ===`,
@@ -461,8 +481,8 @@ var requestAgentDiff = async (userName, messages) => {
461
481
  return normalized;
462
482
  };
463
483
  var applyDiff = async (worktreePath, diffText) => {
464
- const tempDir = await import_promises.default.mkdtemp(import_node_path.default.join(import_node_os.default.tmpdir(), "tradejs-agent-"));
465
- const patchPath = import_node_path.default.join(tempDir, "agent.patch");
484
+ const tempDir = await import_promises.default.mkdtemp(import_node_path2.default.join(import_node_os.default.tmpdir(), "tradejs-agent-"));
485
+ const patchPath = import_node_path2.default.join(tempDir, "agent.patch");
466
486
  try {
467
487
  await import_promises.default.writeFile(patchPath, diffText, "utf8");
468
488
  await runCommandOrThrow(
@@ -500,7 +520,8 @@ var runValidationSuite = async (worktreePath, agentRun) => {
500
520
  const result = await runCommand(command[0], command.slice(1), {
501
521
  cwd: worktreePath,
502
522
  env: {
503
- PROJECT_CWD: worktreePath,
523
+ PROJECT_CWD: projectRoot,
524
+ [SOURCE_REPOSITORY_ROOT_ENV]: worktreePath,
504
525
  DOTENV_CONFIG_PATH: process.env.DOTENV_CONFIG_PATH
505
526
  }
506
527
  });
@@ -682,10 +703,15 @@ var createStrategyCheckout = async (strategy, branchName) => {
682
703
  const organization = process.env.AGENT_GITHUB_ORGANIZATION?.trim() || "TradeJS-Dev";
683
704
  const repository = getResearchAgentRepository(strategy, organization);
684
705
  const baseBranch = process.env.AGENT_GITHUB_BASE_BRANCH?.trim() || "main";
685
- const checkoutRoot = await import_promises.default.mkdtemp(
686
- import_node_path.default.join(import_node_os.default.tmpdir(), "tradejs-strategy-agent-")
706
+ const checkoutBase = import_node_path2.default.join(
707
+ projectRoot,
708
+ "data",
709
+ "cache",
710
+ "research-agent-checkouts"
687
711
  );
688
- const checkoutPath = import_node_path.default.join(checkoutRoot, "repository");
712
+ await import_promises.default.mkdir(checkoutBase, { recursive: true });
713
+ const checkoutRoot = await import_promises.default.mkdtemp(import_node_path2.default.join(checkoutBase, "strategy-"));
714
+ const checkoutPath = import_node_path2.default.join(checkoutRoot, "repository");
689
715
  await runCommandOrThrow(
690
716
  "git",
691
717
  [