@tradejs/cli 3.1.21-beta.237 → 3.1.22-beta.238

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 CHANGED
@@ -255,7 +255,7 @@ var init_researchRoots = __esm({
255
255
  resolveResearchRoots = (options = {}) => {
256
256
  const cwd = import_node_path.default.resolve(options.cwd || process.cwd());
257
257
  const env = options.env || process.env;
258
- const projectRoot15 = import_node_path.default.resolve(
258
+ const projectRoot17 = import_node_path.default.resolve(
259
259
  firstNonEmpty(options.projectRoot, env.PROJECT_CWD, cwd) || cwd
260
260
  );
261
261
  const sourceRepositoryRoot = firstNonEmpty(
@@ -263,7 +263,7 @@ var init_researchRoots = __esm({
263
263
  env[SOURCE_REPOSITORY_ROOT_ENV]
264
264
  );
265
265
  return {
266
- projectRoot: projectRoot15,
266
+ projectRoot: projectRoot17,
267
267
  ...sourceRepositoryRoot ? { sourceRepositoryRoot: import_node_path.default.resolve(sourceRepositoryRoot) } : {}
268
268
  };
269
269
  };
@@ -1943,32 +1943,32 @@ var init_commandOptions = __esm({
1943
1943
  (arg) => arg === `--${longName}` || arg.startsWith(`--${longName}=`) || (shortName ? arg === `-${shortName}` : false)
1944
1944
  );
1945
1945
  resolveAiPocketSearchCommandOptions = ({
1946
- flags: flags32,
1946
+ flags: flags34,
1947
1947
  argv: argv2
1948
1948
  }) => {
1949
- const outDir = String(flags32.outDir || "data/ai/export");
1950
- const strategyName = String(flags32.strategy || "").trim() || void 0;
1951
- const explicitFile = String(flags32.file || "").trim();
1952
- const skip = normalizeInt(flags32.skip, 0);
1953
- const minQuality = normalizeInt(flags32.minQuality, 4);
1954
- const sinceInput = parseTimestampFilter(flags32.since);
1955
- const untilTimestamp = parseTimestampFilter(flags32.until);
1956
- const trailingPeriodMs = parseTrailingPeriodMs(flags32.period);
1957
- const periodLabel = String(flags32.period || "").trim() || null;
1949
+ const outDir = String(flags34.outDir || "data/ai/export");
1950
+ const strategyName = String(flags34.strategy || "").trim() || void 0;
1951
+ const explicitFile = String(flags34.file || "").trim();
1952
+ const skip = normalizeInt(flags34.skip, 0);
1953
+ const minQuality = normalizeInt(flags34.minQuality, 4);
1954
+ const sinceInput = parseTimestampFilter(flags34.since);
1955
+ const untilTimestamp = parseTimestampFilter(flags34.until);
1956
+ const trailingPeriodMs = parseTrailingPeriodMs(flags34.period);
1957
+ const periodLabel = String(flags34.period || "").trim() || null;
1958
1958
  const hasDateFilter = trailingPeriodMs != null || sinceInput != null || untilTimestamp != null;
1959
1959
  const recent = resolveAiTrainRecentLimit({
1960
1960
  argv: argv2,
1961
- recentValue: flags32.recent,
1961
+ recentValue: flags34.recent,
1962
1962
  hasDateFilter
1963
1963
  });
1964
- const qualityThresholds = parseQualityThresholds(flags32.qualityThresholds);
1965
- const scope = String(flags32.scope || "all").trim().toLowerCase();
1964
+ const qualityThresholds = parseQualityThresholds(flags34.qualityThresholds);
1965
+ const scope = String(flags34.scope || "all").trim().toLowerCase();
1966
1966
  if (!["all", "approved", "rejected", "candidates"].includes(scope)) {
1967
1967
  throw new Error(
1968
1968
  `Unsupported --scope "${scope}". Use all, approved, rejected, or candidates.`
1969
1969
  );
1970
1970
  }
1971
- const direction = String(flags32.direction || "").trim().toUpperCase();
1971
+ const direction = String(flags34.direction || "").trim().toUpperCase();
1972
1972
  if (direction && !["LONG", "SHORT"].includes(direction)) {
1973
1973
  throw new Error(
1974
1974
  `Unsupported --direction "${direction}". Use LONG or SHORT.`
@@ -1979,14 +1979,14 @@ var init_commandOptions = __esm({
1979
1979
  "maxEventCountShare",
1980
1980
  "U"
1981
1981
  );
1982
- const maxDepth = normalizePositiveInt(flags32.maxDepth, 2);
1983
- const explicitMinSupport = hasCliOption2(argv2, "minSupport", "m") ? normalizePositiveInt(flags32.minSupport, 20) : void 0;
1982
+ const maxDepth = normalizePositiveInt(flags34.maxDepth, 2);
1983
+ const explicitMinSupport = hasCliOption2(argv2, "minSupport", "m") ? normalizePositiveInt(flags34.minSupport, 20) : void 0;
1984
1984
  const minProfitFactor = normalizeNonNegativeNumber(
1985
1985
  readAiPocketSearchCliOption({
1986
1986
  argv: argv2,
1987
1987
  longName: "minProfitFactor",
1988
1988
  shortName: "F"
1989
- }) ?? flags32.minProfitFactor,
1989
+ }) ?? flags34.minProfitFactor,
1990
1990
  1.2
1991
1991
  );
1992
1992
  const minWinRate = normalizeNonNegativeNumber(
@@ -1994,21 +1994,21 @@ var init_commandOptions = __esm({
1994
1994
  argv: argv2,
1995
1995
  longName: "minWinRate",
1996
1996
  shortName: "W"
1997
- }) ?? flags32.minWinRate,
1997
+ }) ?? flags34.minWinRate,
1998
1998
  0
1999
1999
  );
2000
2000
  const minTotalProfitValue = readAiPocketSearchCliOption({
2001
2001
  argv: argv2,
2002
2002
  longName: "minTotalProfit",
2003
2003
  shortName: "R"
2004
- }) ?? flags32.minTotalProfit;
2004
+ }) ?? flags34.minTotalProfit;
2005
2005
  const minTotalProfit = Number.isFinite(Number(minTotalProfitValue)) ? Number(minTotalProfitValue) : 0;
2006
2006
  const validationSplit = hasCliOption2(argv2, "validationSplit", "V") ? normalizeRatio(
2007
2007
  readAiPocketSearchCliOption({
2008
2008
  argv: argv2,
2009
2009
  longName: "validationSplit",
2010
2010
  shortName: "V"
2011
- }) ?? flags32.validationSplit,
2011
+ }) ?? flags34.validationSplit,
2012
2012
  0.25
2013
2013
  ) : 0.25;
2014
2014
  const testSplit = hasCliOption2(argv2, "testSplit", "T") ? normalizeRatio(
@@ -2016,10 +2016,10 @@ var init_commandOptions = __esm({
2016
2016
  argv: argv2,
2017
2017
  longName: "testSplit",
2018
2018
  shortName: "T"
2019
- }) ?? flags32.testSplit,
2019
+ }) ?? flags34.testSplit,
2020
2020
  0
2021
2021
  ) : 0;
2022
- const sealTest = Boolean(flags32.sealTest);
2022
+ const sealTest = Boolean(flags34.sealTest);
2023
2023
  if (sealTest && testSplit <= 0) {
2024
2024
  throw new Error("--sealTest requires a positive --testSplit");
2025
2025
  }
@@ -2028,7 +2028,7 @@ var init_commandOptions = __esm({
2028
2028
  argv: argv2,
2029
2029
  longName: "maxEventCountShare",
2030
2030
  shortName: "U"
2031
- }) ?? flags32.maxEventCountShare,
2031
+ }) ?? flags34.maxEventCountShare,
2032
2032
  0.25
2033
2033
  );
2034
2034
  const maxSymbolCountShare = normalizeUnitRatio(
@@ -2036,10 +2036,10 @@ var init_commandOptions = __esm({
2036
2036
  argv: argv2,
2037
2037
  longName: "maxSymbolCountShare",
2038
2038
  shortName: "Z"
2039
- }) ?? flags32.maxSymbolCountShare,
2039
+ }) ?? flags34.maxSymbolCountShare,
2040
2040
  0.5
2041
2041
  );
2042
- const objective = normalizeObjective(flags32.objective, scope);
2042
+ const objective = normalizeObjective(flags34.objective, scope);
2043
2043
  return {
2044
2044
  outDir,
2045
2045
  strategyName,
@@ -2059,33 +2059,33 @@ var init_commandOptions = __esm({
2059
2059
  minProfitFactor,
2060
2060
  minWinRate,
2061
2061
  minTotalProfit,
2062
- maxAtomicPredicates: normalizePositiveInt(flags32.maxAtomicPredicates, 180),
2063
- maxCombinations: normalizePositiveInt(flags32.maxCombinations, 6e4),
2062
+ maxAtomicPredicates: normalizePositiveInt(flags34.maxAtomicPredicates, 180),
2063
+ maxCombinations: normalizePositiveInt(flags34.maxCombinations, 6e4),
2064
2064
  validationSplit,
2065
2065
  testSplit,
2066
2066
  sealTest,
2067
- explicitMinValidationSupport: normalizeInt(flags32.minValidationSupport, 0),
2068
- explicitMinEvents: normalizeInt(flags32.minEvents, 0),
2069
- explicitMinValidationEvents: normalizeInt(flags32.minValidationEvents, 0),
2070
- maxBatch: normalizeInt(flags32.maxBatch, 5),
2067
+ explicitMinValidationSupport: normalizeInt(flags34.minValidationSupport, 0),
2068
+ explicitMinEvents: normalizeInt(flags34.minEvents, 0),
2069
+ explicitMinValidationEvents: normalizeInt(flags34.minValidationEvents, 0),
2070
+ maxBatch: normalizeInt(flags34.maxBatch, 5),
2071
2071
  maxEventCountShare,
2072
2072
  explicitMaxEventCountShare,
2073
2073
  maxSymbolCountShare,
2074
2074
  objective,
2075
- allowRiskRegression: Boolean(flags32.allowRiskRegression),
2076
- requireValidationEligibility: !Boolean(flags32.allowValidationRegression),
2077
- dedupeEquivalentSelections: Boolean(flags32.dedupeEquivalentSelections),
2078
- top: normalizePositiveInt(flags32.top, 30),
2079
- includeSymbol: Boolean(flags32.includeSymbol),
2080
- includeGateContext: Boolean(flags32.includeGateContext),
2081
- featureProfile: normalizeFeatureProfile(flags32.featureProfile),
2082
- featurePolicy: normalizeFeaturePolicy(flags32.featurePolicy),
2083
- coverageMode: normalizeCoverageMode(flags32.coverageMode),
2084
- cadenceMode: normalizeCadenceMode(flags32.cadenceMode),
2085
- jsonOutput: Boolean(flags32.json),
2086
- outputPath: String(flags32.output || "").trim(),
2087
- reportDir: String(flags32.reportDir || "data/ai/output").trim(),
2088
- explicitReportFile: String(flags32.reportFile || "").trim()
2075
+ allowRiskRegression: Boolean(flags34.allowRiskRegression),
2076
+ requireValidationEligibility: !Boolean(flags34.allowValidationRegression),
2077
+ dedupeEquivalentSelections: Boolean(flags34.dedupeEquivalentSelections),
2078
+ top: normalizePositiveInt(flags34.top, 30),
2079
+ includeSymbol: Boolean(flags34.includeSymbol),
2080
+ includeGateContext: Boolean(flags34.includeGateContext),
2081
+ featureProfile: normalizeFeatureProfile(flags34.featureProfile),
2082
+ featurePolicy: normalizeFeaturePolicy(flags34.featurePolicy),
2083
+ coverageMode: normalizeCoverageMode(flags34.coverageMode),
2084
+ cadenceMode: normalizeCadenceMode(flags34.cadenceMode),
2085
+ jsonOutput: Boolean(flags34.json),
2086
+ outputPath: String(flags34.output || "").trim(),
2087
+ reportDir: String(flags34.reportDir || "data/ai/output").trim(),
2088
+ explicitReportFile: String(flags34.reportFile || "").trim()
2089
2089
  };
2090
2090
  };
2091
2091
  }
@@ -2185,9 +2185,9 @@ var init_features = __esm({
2185
2185
  "targetsymbol",
2186
2186
  "universe"
2187
2187
  ]);
2188
- normalizeFeaturePath = (path35) => (Array.isArray(path35) ? path35 : path35.split(".")).filter(Boolean).map((segment) => segment.toLowerCase());
2189
- classifyAiPocketCoverageFeaturePath = (path35) => {
2190
- const segments = normalizeFeaturePath(path35);
2188
+ normalizeFeaturePath = (path41) => (Array.isArray(path41) ? path41 : path41.split(".")).filter(Boolean).map((segment) => segment.toLowerCase());
2189
+ classifyAiPocketCoverageFeaturePath = (path41) => {
2190
+ const segments = normalizeFeaturePath(path41);
2191
2191
  const normalizedPath = segments.join(".");
2192
2192
  if (segments.some(
2193
2193
  (segment) => segment.includes("cmc") || segment.includes("coinmarketcap")
@@ -2361,8 +2361,8 @@ var init_features = __esm({
2361
2361
  "volumeusd",
2362
2362
  "vwap"
2363
2363
  ]);
2364
- classifyAiPocketFeaturePath = (path35) => {
2365
- const segments = (Array.isArray(path35) ? path35 : path35.split(".")).filter(
2364
+ classifyAiPocketFeaturePath = (path41) => {
2365
+ const segments = (Array.isArray(path41) ? path41 : path41.split(".")).filter(
2366
2366
  Boolean
2367
2367
  );
2368
2368
  const normalized = segments.map((segment) => segment.toLowerCase());
@@ -5988,10 +5988,10 @@ var init_command = __esm({
5988
5988
  init_dataset();
5989
5989
  init_research();
5990
5990
  runAiPocketSearchCommand = async ({
5991
- flags: flags32
5991
+ flags: flags34
5992
5992
  }) => {
5993
5993
  const options = resolveAiPocketSearchCommandOptions({
5994
- flags: flags32,
5994
+ flags: flags34,
5995
5995
  argv: process.argv
5996
5996
  });
5997
5997
  const {
@@ -6896,11 +6896,11 @@ var init_strategyGateFingerprint = __esm({
6896
6896
  "@tradejs/core/strategies"
6897
6897
  ];
6898
6898
  resolveStrategyGateFingerprint = async ({
6899
- projectRoot: projectRoot15,
6899
+ projectRoot: projectRoot17,
6900
6900
  strategyName,
6901
6901
  gitSha
6902
6902
  }) => {
6903
- const projectManifestPath = import_node_path3.default.join(projectRoot15, "package.json");
6903
+ const projectManifestPath = import_node_path3.default.join(projectRoot17, "package.json");
6904
6904
  const projectExists = await import_promises6.default.access(projectManifestPath).then(() => true).catch(() => false);
6905
6905
  const requireFromProject = projectExists ? (0, import_node_module.createRequire)(projectManifestPath) : null;
6906
6906
  const candidates = requireFromProject ? await Promise.all(
@@ -7079,10 +7079,10 @@ var init_aiTrainResearch = __esm({
7079
7079
  };
7080
7080
  });
7081
7081
  };
7082
- getGitLineage = (projectRoot15) => {
7082
+ getGitLineage = (projectRoot17) => {
7083
7083
  try {
7084
7084
  const gitSha = (0, import_node_child_process2.execFileSync)("git", ["rev-parse", "HEAD"], {
7085
- cwd: projectRoot15,
7085
+ cwd: projectRoot17,
7086
7086
  encoding: "utf8",
7087
7087
  stdio: ["ignore", "pipe", "ignore"]
7088
7088
  }).trim();
@@ -7090,7 +7090,7 @@ var init_aiTrainResearch = __esm({
7090
7090
  "git",
7091
7091
  ["status", "--porcelain", "--untracked-files=no"],
7092
7092
  {
7093
- cwd: projectRoot15,
7093
+ cwd: projectRoot17,
7094
7094
  encoding: "utf8",
7095
7095
  stdio: ["ignore", "pipe", "ignore"]
7096
7096
  }
@@ -7101,16 +7101,16 @@ var init_aiTrainResearch = __esm({
7101
7101
  }
7102
7102
  };
7103
7103
  buildAiTrainLineage = async ({
7104
- projectRoot: projectRoot15,
7104
+ projectRoot: projectRoot17,
7105
7105
  strategyName,
7106
7106
  configIds,
7107
7107
  runContext,
7108
7108
  sourceSha256s = [],
7109
7109
  env = process.env
7110
7110
  }) => {
7111
- const { gitSha, gitDirty } = getGitLineage(projectRoot15);
7111
+ const { gitSha, gitDirty } = getGitLineage(projectRoot17);
7112
7112
  const gate = await resolveStrategyGateFingerprint({
7113
- projectRoot: projectRoot15,
7113
+ projectRoot: projectRoot17,
7114
7114
  strategyName,
7115
7115
  gitSha
7116
7116
  });
@@ -9141,12 +9141,12 @@ var init_binanceMarketContextBackfill = __esm({
9141
9141
  return rows;
9142
9142
  };
9143
9143
  getBinanceConnector = async ({
9144
- projectRoot: projectRoot15,
9144
+ projectRoot: projectRoot17,
9145
9145
  userName: userName3
9146
9146
  }) => {
9147
9147
  const creator = await (0, import_connectors2.getConnectorCreatorByName)(
9148
9148
  import_connectors.ConnectorNames.Binance,
9149
- projectRoot15
9149
+ projectRoot17
9150
9150
  );
9151
9151
  if (!creator) {
9152
9152
  throw new Error(
@@ -10693,27 +10693,27 @@ var init_coinMarketCapContextBackfill = __esm({
10693
10693
  totalCredits: 0,
10694
10694
  byPath: /* @__PURE__ */ new Map()
10695
10695
  });
10696
- getCoinMarketCapPathLabel = (path35) => {
10697
- if (path35.includes("global-metrics")) return "global";
10698
- if (path35.includes("cryptocurrency/quotes")) return "reference";
10699
- if (path35.includes("exchange/quotes")) return "exchangeLiquidity";
10700
- if (path35.includes("fear-and-greed")) return "fearGreed";
10701
- if (path35.includes("cmc100")) return "cmc100";
10702
- if (path35.includes("cmc20")) return "cmc20";
10703
- return path35;
10704
- };
10705
- recordCoinMarketCapFetchStats = (stats, path35, creditCount) => {
10696
+ getCoinMarketCapPathLabel = (path41) => {
10697
+ if (path41.includes("global-metrics")) return "global";
10698
+ if (path41.includes("cryptocurrency/quotes")) return "reference";
10699
+ if (path41.includes("exchange/quotes")) return "exchangeLiquidity";
10700
+ if (path41.includes("fear-and-greed")) return "fearGreed";
10701
+ if (path41.includes("cmc100")) return "cmc100";
10702
+ if (path41.includes("cmc20")) return "cmc20";
10703
+ return path41;
10704
+ };
10705
+ recordCoinMarketCapFetchStats = (stats, path41, creditCount) => {
10706
10706
  if (!stats) return;
10707
- const existing = stats.byPath.get(path35) ?? { requests: 0, credits: 0 };
10707
+ const existing = stats.byPath.get(path41) ?? { requests: 0, credits: 0 };
10708
10708
  existing.requests += 1;
10709
10709
  existing.credits += creditCount ?? 0;
10710
10710
  stats.requests += 1;
10711
10711
  stats.totalCredits += creditCount ?? 0;
10712
- stats.byPath.set(path35, existing);
10712
+ stats.byPath.set(path41, existing);
10713
10713
  };
10714
10714
  formatCoinMarketCapFetchStats = (stats) => {
10715
10715
  const byPath = [...stats.byPath.entries()].map(
10716
- ([path35, item]) => `${getCoinMarketCapPathLabel(path35)}=${item.requests}req/${item.credits}cr`
10716
+ ([path41, item]) => `${getCoinMarketCapPathLabel(path41)}=${item.requests}req/${item.credits}cr`
10717
10717
  ).join(" ");
10718
10718
  return `apiRequests=${stats.requests} apiCredits=${stats.totalCredits}${byPath ? ` ${byPath}` : ""}`;
10719
10719
  };
@@ -12471,7 +12471,7 @@ var init_historyPrepare = __esm({
12471
12471
  connectorName,
12472
12472
  marketConnector,
12473
12473
  userName: userName3,
12474
- projectRoot: projectRoot15,
12474
+ projectRoot: projectRoot17,
12475
12475
  shouldUseDedicatedReferences,
12476
12476
  requireDedicatedReferences = false,
12477
12477
  warn
@@ -12483,8 +12483,8 @@ var init_historyPrepare = __esm({
12483
12483
  };
12484
12484
  }
12485
12485
  const [binanceFactory, coinbaseFactory] = await Promise.all([
12486
- (0, import_connectors4.getConnectorCreatorByName)(import_connectors3.ConnectorNames.Binance, projectRoot15),
12487
- (0, import_connectors4.getConnectorCreatorByName)(import_connectors3.ConnectorNames.Coinbase, projectRoot15)
12486
+ (0, import_connectors4.getConnectorCreatorByName)(import_connectors3.ConnectorNames.Binance, projectRoot17),
12487
+ (0, import_connectors4.getConnectorCreatorByName)(import_connectors3.ConnectorNames.Coinbase, projectRoot17)
12488
12488
  ]);
12489
12489
  const binance = binanceFactory ? await binanceFactory({ userName: userName3 }) : marketConnector;
12490
12490
  if (!binanceFactory) {
@@ -12742,9 +12742,9 @@ var init_runEnvironment = __esm({
12742
12742
  };
12743
12743
  resolveRunConnectorName = async ({
12744
12744
  value,
12745
- projectRoot: projectRoot15
12745
+ projectRoot: projectRoot17
12746
12746
  }) => {
12747
- const connectorName = await (0, import_connectors5.resolveConnectorName)(value, projectRoot15);
12747
+ const connectorName = await (0, import_connectors5.resolveConnectorName)(value, projectRoot17);
12748
12748
  if (connectorName) {
12749
12749
  return connectorName;
12750
12750
  }
@@ -12769,12 +12769,12 @@ var init_runEnvironment = __esm({
12769
12769
  };
12770
12770
  loadDeploymentReplayStrategies = async ({
12771
12771
  userName: userName3,
12772
- projectRoot: projectRoot15,
12772
+ projectRoot: projectRoot17,
12773
12773
  deploymentId
12774
12774
  }) => {
12775
12775
  const [deployment, runtimeStrategies] = await Promise.all([
12776
- (0, import_runtimeStrategies.getRuntimeDeployment)({ userName: userName3, projectRoot: projectRoot15, deploymentId }),
12777
- (0, import_runtimeStrategies.loadResolvedRuntimeStrategies)({ userName: userName3, projectRoot: projectRoot15, deploymentId })
12776
+ (0, import_runtimeStrategies.getRuntimeDeployment)({ userName: userName3, projectRoot: projectRoot17, deploymentId }),
12777
+ (0, import_runtimeStrategies.loadResolvedRuntimeStrategies)({ userName: userName3, projectRoot: projectRoot17, deploymentId })
12778
12778
  ]);
12779
12779
  if (!deployment) {
12780
12780
  throw new Error(`Runtime deployment not found: ${deploymentId}`);
@@ -12823,7 +12823,7 @@ var init_runEnvironment = __esm({
12823
12823
  endTime,
12824
12824
  cacheOnly,
12825
12825
  interval: interval4,
12826
- projectRoot: projectRoot15,
12826
+ projectRoot: projectRoot17,
12827
12827
  universe = "crypto",
12828
12828
  accountId,
12829
12829
  deploymentId,
@@ -12833,11 +12833,11 @@ var init_runEnvironment = __esm({
12833
12833
  }) => {
12834
12834
  const connectorName = await resolveRunConnectorName({
12835
12835
  value: connector,
12836
- projectRoot: projectRoot15
12836
+ projectRoot: projectRoot17
12837
12837
  });
12838
12838
  const connectorFactory = await (0, import_connectors5.getConnectorCreatorByName)(
12839
12839
  connectorName,
12840
- projectRoot15
12840
+ projectRoot17
12841
12841
  );
12842
12842
  if (!connectorFactory) {
12843
12843
  throw new Error(`Connector "${connectorName}" is not registered`);
@@ -12904,7 +12904,7 @@ var init_runEnvironment = __esm({
12904
12904
  connectorName,
12905
12905
  marketConnector,
12906
12906
  userName: userName3,
12907
- projectRoot: projectRoot15,
12907
+ projectRoot: projectRoot17,
12908
12908
  shouldUseDedicatedReferences: universe === "crypto",
12909
12909
  requireDedicatedReferences: universe === "crypto",
12910
12910
  warn: (message) => console.log(import_chalk12.default.yellow(message))
@@ -14578,10 +14578,10 @@ var init_binanceBreadthUniversesUpdate = __esm({
14578
14578
  flags6 = import_args6.default.parse(process.argv);
14579
14579
  BINANCE_BREADTH_UNIVERSES_RELATIVE_PATH = "packages/node/src/config/binanceBreadthUniverses.json";
14580
14580
  main6 = async () => {
14581
- const projectRoot15 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
14581
+ const projectRoot17 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
14582
14582
  const connectorCreator = await (0, import_connectors7.getConnectorCreatorByName)(
14583
14583
  import_connectors6.ConnectorNames.Binance,
14584
- projectRoot15
14584
+ projectRoot17
14585
14585
  );
14586
14586
  if (!connectorCreator) {
14587
14587
  throw new Error("Binance connector is not registered");
@@ -14614,7 +14614,7 @@ var init_binanceBreadthUniversesUpdate = __esm({
14614
14614
  return snapshot;
14615
14615
  }
14616
14616
  const outputPath = import_node_path5.default.join(
14617
- projectRoot15,
14617
+ projectRoot17,
14618
14618
  BINANCE_BREADTH_UNIVERSES_RELATIVE_PATH
14619
14619
  );
14620
14620
  await import_promises9.default.writeFile(outputPath, serialized, "utf8");
@@ -15448,14 +15448,14 @@ var init_cleanTests = __esm({
15448
15448
  cleanUserTests = async (userName3) => {
15449
15449
  const testsPrefix = `users:${userName3}:tests:`;
15450
15450
  const testsCachePrefix = `users:${userName3}:cache:tests:`;
15451
- const projectRoot15 = process.env.PROJECT_CWD || process.cwd();
15451
+ const projectRoot17 = process.env.PROJECT_CWD || process.cwd();
15452
15452
  const persistedArtifactsDir = import_path7.default.relative(
15453
- projectRoot15,
15454
- (0, import_backtestArtifacts2.getPersistedBacktestArtifactsDirForUser)(userName3, projectRoot15)
15453
+ projectRoot17,
15454
+ (0, import_backtestArtifacts2.getPersistedBacktestArtifactsDirForUser)(userName3, projectRoot17)
15455
15455
  );
15456
15456
  const cacheArtifactsDir = import_path7.default.relative(
15457
- projectRoot15,
15458
- (0, import_backtestArtifacts2.getBacktestCacheArtifactsDirForUser)(userName3, projectRoot15)
15457
+ projectRoot17,
15458
+ (0, import_backtestArtifacts2.getBacktestCacheArtifactsDirForUser)(userName3, projectRoot17)
15459
15459
  );
15460
15460
  if (flags11.cache) {
15461
15461
  console.log(import_chalk19.default.yellow(`clean user cache: ${userName3}`));
@@ -15468,11 +15468,11 @@ var init_cleanTests = __esm({
15468
15468
  await (0, import_cli7.cleanRedis)(testsCachePrefix);
15469
15469
  await (0, import_cli7.cleanFiles)(persistedArtifactsDir);
15470
15470
  await (0, import_cli7.cleanFiles)(cacheArtifactsDir);
15471
- await import_promises10.default.rm(import_path7.default.join(projectRoot15, persistedArtifactsDir), {
15471
+ await import_promises10.default.rm(import_path7.default.join(projectRoot17, persistedArtifactsDir), {
15472
15472
  recursive: true,
15473
15473
  force: true
15474
15474
  });
15475
- await import_promises10.default.rm(import_path7.default.join(projectRoot15, cacheArtifactsDir), {
15475
+ await import_promises10.default.rm(import_path7.default.join(projectRoot17, cacheArtifactsDir), {
15476
15476
  recursive: true,
15477
15477
  force: true
15478
15478
  });
@@ -17309,8 +17309,8 @@ volumes:
17309
17309
  `${DEV_COMPOSE_FILE} not found in project root. Run "npx @tradejs/cli infra-init" first.`
17310
17310
  );
17311
17311
  };
17312
- runDockerCompose = (composePath, args35) => {
17313
- const result = (0, import_node_child_process3.spawnSync)("docker", ["compose", "-f", composePath, ...args35], {
17312
+ runDockerCompose = (composePath, args37) => {
17313
+ const result = (0, import_node_child_process3.spawnSync)("docker", ["compose", "-f", composePath, ...args37], {
17314
17314
  stdio: "inherit"
17315
17315
  });
17316
17316
  if (result.error) {
@@ -23584,11 +23584,11 @@ var init_coreResearch = __esm({
23584
23584
  if (!Number.isFinite(numeric)) throw new Error(`${name} is invalid: ${text}`);
23585
23585
  return numeric;
23586
23586
  };
23587
- readSymbols = async (argv2, projectRoot15) => {
23587
+ readSymbols = async (argv2, projectRoot17) => {
23588
23588
  const symbolsFile = valueAfter(argv2, "--symbolsFile");
23589
23589
  if (symbolsFile) {
23590
23590
  const parsed = JSON.parse(
23591
- await import_promises20.default.readFile(import_node_path14.default.resolve(projectRoot15, symbolsFile), "utf8")
23591
+ await import_promises20.default.readFile(import_node_path14.default.resolve(projectRoot17, symbolsFile), "utf8")
23592
23592
  );
23593
23593
  if (!Array.isArray(parsed) || parsed.some((symbol) => typeof symbol !== "string")) {
23594
23594
  throw new Error("--symbolsFile must contain a JSON string array");
@@ -24654,12 +24654,15 @@ var init_support = __esm({
24654
24654
  buildReplayStrategyConfig = ({
24655
24655
  strategyConfig,
24656
24656
  interval: interval4
24657
- }) => buildRuntimeModeStrategyConfig({
24658
- strategyConfig,
24659
- env: "PARITY",
24660
- interval: interval4,
24661
- makeOrders: true,
24662
- recordRuntimeTrades: false
24657
+ }) => ({
24658
+ ...buildRuntimeModeStrategyConfig({
24659
+ strategyConfig,
24660
+ env: "PARITY",
24661
+ interval: interval4,
24662
+ makeOrders: false,
24663
+ recordRuntimeTrades: false
24664
+ }),
24665
+ SIMULATE_ORDERS: true
24663
24666
  });
24664
24667
  toRecord = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
24665
24668
  compactReplayAdditionalIndicators = (additionalIndicators) => {
@@ -24765,13 +24768,13 @@ var init_replayRuntimeEvidence = __esm({
24765
24768
  const parsed = Date.parse(raw);
24766
24769
  return Number.isFinite(parsed) ? parsed : null;
24767
24770
  };
24768
- resolveWindow = (flags32) => {
24769
- const endTime = toEpochMs2(flags32.endTime) ?? Date.now();
24771
+ resolveWindow = (flags34) => {
24772
+ const endTime = toEpochMs2(flags34.endTime) ?? Date.now();
24770
24773
  const hours = Math.max(
24771
24774
  1,
24772
- Number.parseInt(String(flags32.hours ?? 24), 10) || 24
24775
+ Number.parseInt(String(flags34.hours ?? 24), 10) || 24
24773
24776
  );
24774
- const startTime = toEpochMs2(flags32.startTime) ?? endTime - hours * 60 * 60 * 1e3;
24777
+ const startTime = toEpochMs2(flags34.startTime) ?? endTime - hours * 60 * 60 * 1e3;
24775
24778
  if (startTime >= endTime) {
24776
24779
  throw new Error(
24777
24780
  `Invalid window: startTime (${startTime}) must be less than endTime (${endTime})`
@@ -24780,7 +24783,7 @@ var init_replayRuntimeEvidence = __esm({
24780
24783
  return {
24781
24784
  startTime,
24782
24785
  endTime,
24783
- source: flags32.startTime != null || flags32.endTime != null ? "explicit" : "hours"
24786
+ source: flags34.startTime != null || flags34.endTime != null ? "explicit" : "hours"
24784
24787
  };
24785
24788
  };
24786
24789
  parseStrategyFilter = (value) => String(value ?? "").split(",").map((item) => item.trim()).filter(Boolean);
@@ -24970,9 +24973,9 @@ var init_replayRuntimeEvidence = __esm({
24970
24973
  strategies,
24971
24974
  userName: userName3,
24972
24975
  runtimeEvidenceFile,
24973
- projectRoot: projectRoot15
24976
+ projectRoot: projectRoot17
24974
24977
  }) => {
24975
- const runtimeEvidencePath = typeof runtimeEvidenceFile === "string" && runtimeEvidenceFile.trim() ? import_node_path15.default.resolve(projectRoot15, runtimeEvidenceFile.trim()) : null;
24978
+ const runtimeEvidencePath = typeof runtimeEvidenceFile === "string" && runtimeEvidenceFile.trim() ? import_node_path15.default.resolve(projectRoot17, runtimeEvidenceFile.trim()) : null;
24976
24979
  if (runtimeEvidencePath) {
24977
24980
  const artifact = JSON.parse(
24978
24981
  await import_promises21.default.readFile(runtimeEvidencePath, "utf8")
@@ -25006,23 +25009,23 @@ var init_replayRuntimeEvidence = __esm({
25006
25009
  };
25007
25010
  };
25008
25011
  replayRuntimeEvidence = async () => {
25009
- const flags32 = import_args25.default.parse(process.argv);
25010
- const projectRoot15 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
25011
- const userName3 = String(flags32.user ?? "root");
25012
- const { startTime, endTime, source } = resolveWindow(flags32);
25012
+ const flags34 = import_args25.default.parse(process.argv);
25013
+ const projectRoot17 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
25014
+ const userName3 = String(flags34.user ?? "root");
25015
+ const { startTime, endTime, source } = resolveWindow(flags34);
25013
25016
  const replay = await loadReplayResult({
25014
25017
  userName: userName3,
25015
- replayKey: typeof flags32.replayKey === "string" && flags32.replayKey.trim() ? flags32.replayKey.trim() : void 0
25018
+ replayKey: typeof flags34.replayKey === "string" && flags34.replayKey.trim() ? flags34.replayKey.trim() : void 0
25016
25019
  });
25017
- const explicitStrategies = parseStrategyFilter(flags32.strategy);
25020
+ const explicitStrategies = parseStrategyFilter(flags34.strategy);
25018
25021
  const strategies = explicitStrategies.length ? explicitStrategies : getReplayStrategies(replay.value);
25019
25022
  const runtime = await loadRuntimePayload({
25020
25023
  startTime,
25021
25024
  endTime,
25022
25025
  strategies,
25023
25026
  userName: userName3,
25024
- runtimeEvidenceFile: flags32.runtimeEvidence,
25025
- projectRoot: projectRoot15
25027
+ runtimeEvidenceFile: flags34.runtimeEvidence,
25028
+ projectRoot: projectRoot17
25026
25029
  });
25027
25030
  const replayValue = asRecord4(replay.value);
25028
25031
  const artifact = {
@@ -25047,6 +25050,10 @@ var init_replayRuntimeEvidence = __esm({
25047
25050
  availableKeys: replay.availableKeys,
25048
25051
  startedAt: replayValue.startedAt ?? null,
25049
25052
  finishedAt: replayValue.finishedAt ?? null,
25053
+ durationSeconds: replayValue.durationSeconds ?? null,
25054
+ cycleCount: replayValue.cycleCount ?? null,
25055
+ abortedCycles: replayValue.abortedCycles ?? null,
25056
+ signalsCount: replayValue.signalsCount ?? null,
25050
25057
  resultsByStrategies: asArray2(replayValue.resultsByStrategies).filter(
25051
25058
  (row) => !strategies.length || strategies.includes(String(row.strategyName ?? ""))
25052
25059
  ),
@@ -25057,7 +25064,7 @@ var init_replayRuntimeEvidence = __esm({
25057
25064
  },
25058
25065
  runtime: runtime.payload
25059
25066
  };
25060
- const outPath = import_node_path15.default.resolve(projectRoot15, String(flags32.out));
25067
+ const outPath = import_node_path15.default.resolve(projectRoot17, String(flags34.out));
25061
25068
  await import_promises21.default.mkdir(import_node_path15.default.dirname(outPath), { recursive: true });
25062
25069
  await import_promises21.default.writeFile(outPath, `${JSON.stringify(artifact, null, 2)}
25063
25070
  `, "utf8");
@@ -25317,12 +25324,12 @@ var init_runtimeEvidenceDeployment = __esm({
25317
25324
  });
25318
25325
  resolveRuntimeEvidenceDeploymentSnapshot = async ({
25319
25326
  userName: userName3,
25320
- projectRoot: projectRoot15,
25327
+ projectRoot: projectRoot17,
25321
25328
  deploymentId
25322
25329
  }) => {
25323
25330
  const [deployment, strategies] = await Promise.all([
25324
- (0, import_runtimeStrategies3.getRuntimeDeployment)({ userName: userName3, projectRoot: projectRoot15, deploymentId }),
25325
- (0, import_runtimeStrategies3.loadResolvedRuntimeStrategies)({ userName: userName3, projectRoot: projectRoot15, deploymentId })
25331
+ (0, import_runtimeStrategies3.getRuntimeDeployment)({ userName: userName3, projectRoot: projectRoot17, deploymentId }),
25332
+ (0, import_runtimeStrategies3.loadResolvedRuntimeStrategies)({ userName: userName3, projectRoot: projectRoot17, deploymentId })
25326
25333
  ]);
25327
25334
  if (!deployment) {
25328
25335
  throw new Error(`Runtime deployment not found: ${deploymentId}`);
@@ -25606,12 +25613,981 @@ var init_runtimeEvidenceArtifacts = __esm({
25606
25613
  }
25607
25614
  });
25608
25615
 
25616
+ // src/lib/runtimeEvidenceProducer.ts
25617
+ var import_node_crypto11, import_promises23, import_node_path17, isRecord2, sha2562, parseRuntimeEvidenceProducer, resolveRuntimeEvidenceProducer;
25618
+ var init_runtimeEvidenceProducer = __esm({
25619
+ "src/lib/runtimeEvidenceProducer.ts"() {
25620
+ "use strict";
25621
+ import_node_crypto11 = require("crypto");
25622
+ import_promises23 = __toESM(require("fs/promises"));
25623
+ import_node_path17 = __toESM(require("path"));
25624
+ isRecord2 = (value) => value != null && typeof value === "object" && !Array.isArray(value);
25625
+ sha2562 = (value) => (0, import_node_crypto11.createHash)("sha256").update(value).digest("hex");
25626
+ parseRuntimeEvidenceProducer = (value) => {
25627
+ const producer = isRecord2(value) ? value : null;
25628
+ const runtimePackageManifest = isRecord2(producer?.runtimePackageManifest) ? producer.runtimePackageManifest : null;
25629
+ if (producer?.schemaVersion !== 1 || typeof producer.projectSha !== "string" || !/^[a-f0-9]{40}$/.test(producer.projectSha) || typeof producer.imageDigest !== "string" || !/^sha256:[a-f0-9]{64}$/.test(producer.imageDigest) || runtimePackageManifest?.file !== "runtime-package-manifest.json" || typeof runtimePackageManifest.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(runtimePackageManifest.sha256)) {
25630
+ throw new Error("Runtime evidence producer image identity is invalid");
25631
+ }
25632
+ return producer;
25633
+ };
25634
+ resolveRuntimeEvidenceProducer = async ({
25635
+ projectRoot: projectRoot17,
25636
+ required: required4
25637
+ }) => {
25638
+ const projectSha = String(process.env.TRADEJS_PROJECT_SHA ?? "").trim();
25639
+ const imageDigest = String(
25640
+ process.env.TRADEJS_PROJECT_IMAGE_DIGEST ?? ""
25641
+ ).trim();
25642
+ if (!projectSha && !imageDigest && !required4) {
25643
+ return null;
25644
+ }
25645
+ if (!/^[a-f0-9]{40}$/.test(projectSha)) {
25646
+ throw new Error(
25647
+ "TRADEJS_PROJECT_SHA must be a full lowercase Git SHA before publishing runtime evidence"
25648
+ );
25649
+ }
25650
+ if (!/^sha256:[a-f0-9]{64}$/.test(imageDigest)) {
25651
+ throw new Error(
25652
+ "TRADEJS_PROJECT_IMAGE_DIGEST must be an immutable sha256 digest before publishing runtime evidence"
25653
+ );
25654
+ }
25655
+ const manifestPath = import_node_path17.default.join(projectRoot17, "runtime-package-manifest.json");
25656
+ let manifest;
25657
+ try {
25658
+ manifest = await import_promises23.default.readFile(manifestPath);
25659
+ } catch (error) {
25660
+ if (!required4 && error.code === "ENOENT") {
25661
+ return null;
25662
+ }
25663
+ throw new Error(
25664
+ `Runtime package manifest is required for runtime evidence: ${manifestPath}`,
25665
+ { cause: error }
25666
+ );
25667
+ }
25668
+ return {
25669
+ schemaVersion: 1,
25670
+ projectSha,
25671
+ imageDigest,
25672
+ runtimePackageManifest: {
25673
+ file: "runtime-package-manifest.json",
25674
+ sha256: sha2562(manifest)
25675
+ }
25676
+ };
25677
+ };
25678
+ }
25679
+ });
25680
+
25681
+ // src/lib/runtimeFeedbackArtifacts.ts
25682
+ var import_node_crypto12, import_promises24, import_node_path18, RUNTIME_FEEDBACK_MANIFEST_FILE, RUNTIME_FEEDBACK_REPLAY_FILE, RUNTIME_FEEDBACK_LOG_FILE, RUNTIME_FEEDBACK_COMPLETE_FILE, isRecord3, sha2563, safeSegment2, parsePayload, parseManifest2, assertReplayMatchesRuntimeEvidence, sealRuntimeFeedbackReplayBundle, verifyRuntimeFeedbackReplayBundle, discoverRuntimeFeedbackReplayBundles, verifyRuntimeFeedbackReplaySource;
25683
+ var init_runtimeFeedbackArtifacts = __esm({
25684
+ "src/lib/runtimeFeedbackArtifacts.ts"() {
25685
+ "use strict";
25686
+ import_node_crypto12 = require("crypto");
25687
+ import_promises24 = __toESM(require("fs/promises"));
25688
+ import_node_path18 = __toESM(require("path"));
25689
+ init_runtimeEvidenceDeployment();
25690
+ init_runtimeEvidenceArtifacts();
25691
+ init_runtimeEvidenceProducer();
25692
+ RUNTIME_FEEDBACK_MANIFEST_FILE = "manifest.json";
25693
+ RUNTIME_FEEDBACK_REPLAY_FILE = "replay-runtime-evidence.json";
25694
+ RUNTIME_FEEDBACK_LOG_FILE = "replay.log";
25695
+ RUNTIME_FEEDBACK_COMPLETE_FILE = ".complete";
25696
+ isRecord3 = (value) => value != null && typeof value === "object" && !Array.isArray(value);
25697
+ sha2563 = (value) => (0, import_node_crypto12.createHash)("sha256").update(value).digest("hex");
25698
+ safeSegment2 = (value, fallback) => {
25699
+ const normalized = value.trim().replace(/[^a-zA-Z0-9._-]+/g, "-");
25700
+ return normalized && normalized !== "." && normalized !== ".." ? normalized : fallback;
25701
+ };
25702
+ parsePayload = (value, expectedFile) => {
25703
+ const payload = isRecord3(value) ? value : null;
25704
+ if (payload?.file !== expectedFile || typeof payload.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(payload.sha256) || typeof payload.bytes !== "number" || !Number.isFinite(payload.bytes) || payload.bytes < 0) {
25705
+ throw new Error(`Invalid runtime feedback payload: ${expectedFile}`);
25706
+ }
25707
+ return payload;
25708
+ };
25709
+ parseManifest2 = (value) => {
25710
+ const manifest = isRecord3(value) ? value : null;
25711
+ const window = isRecord3(manifest?.window) ? manifest.window : null;
25712
+ const runtimeEvidence2 = isRecord3(manifest?.runtimeEvidence) ? manifest.runtimeEvidence : null;
25713
+ const safety = isRecord3(manifest?.safety) ? manifest.safety : null;
25714
+ const payloads = isRecord3(manifest?.payloads) ? manifest.payloads : null;
25715
+ if (manifest?.schemaVersion !== 1 || manifest.reportType !== "runtime-feedback-replay" || typeof manifest.artifactId !== "string" || !manifest.artifactId.trim() || typeof manifest.runId !== "string" || !manifest.runId.trim() || typeof manifest.deploymentId !== "string" || !manifest.deploymentId.trim() || typeof manifest.deploymentCompositionId !== "string" || !/^dc1:[a-f0-9]{16}$/.test(manifest.deploymentCompositionId) || typeof manifest.userName !== "string" || !manifest.userName.trim() || typeof manifest.createdAt !== "number" || typeof window?.startTime !== "number" || typeof window.endTime !== "number" || typeof runtimeEvidence2?.artifactId !== "string" || typeof runtimeEvidence2.payloadSha256 !== "string" || !/^[a-f0-9]{64}$/.test(runtimeEvidence2.payloadSha256) || !Array.isArray(manifest.activeStrategies) || manifest.activeStrategies.length === 0 || !manifest.activeStrategies.every(
25716
+ (strategy) => typeof strategy === "string" && strategy.trim()
25717
+ ) || typeof manifest.cycleCount !== "number" || !Number.isFinite(manifest.cycleCount) || manifest.cycleCount <= 0 || safety?.cacheOnly !== true || safety.externalOrderPlacement !== false || safety.redis !== "isolated" || safety.timescale !== "read_only") {
25718
+ throw new Error("Invalid runtime feedback replay manifest");
25719
+ }
25720
+ const replayEvidence = parsePayload(
25721
+ payloads?.replayEvidence,
25722
+ RUNTIME_FEEDBACK_REPLAY_FILE
25723
+ );
25724
+ const log = parsePayload(payloads?.log, RUNTIME_FEEDBACK_LOG_FILE);
25725
+ return {
25726
+ ...manifest,
25727
+ producer: parseRuntimeEvidenceProducer(manifest.producer),
25728
+ payloads: {
25729
+ replayEvidence: {
25730
+ ...replayEvidence,
25731
+ file: RUNTIME_FEEDBACK_REPLAY_FILE
25732
+ },
25733
+ log: { ...log, file: RUNTIME_FEEDBACK_LOG_FILE }
25734
+ }
25735
+ };
25736
+ };
25737
+ assertReplayMatchesRuntimeEvidence = ({
25738
+ replayEvidence,
25739
+ runtimeEvidence: runtimeEvidence2
25740
+ }) => {
25741
+ if (replayEvidence.reportType !== "replay-runtime-evidence") {
25742
+ throw new Error("Runtime feedback replay payload has the wrong reportType");
25743
+ }
25744
+ const replayWindow = isRecord3(replayEvidence.window) ? replayEvidence.window : null;
25745
+ if (replayWindow?.startTime !== runtimeEvidence2.manifest.window.startTime || replayWindow.endTime !== runtimeEvidence2.manifest.window.endTime) {
25746
+ throw new Error("Runtime feedback replay window does not match evidence");
25747
+ }
25748
+ const runtimeDeployment = parseRuntimeEvidenceDeploymentSnapshot(
25749
+ runtimeEvidence2.artifact.deployment
25750
+ );
25751
+ const replayDeployment = parseRuntimeEvidenceDeploymentSnapshot(
25752
+ replayEvidence.deployment
25753
+ );
25754
+ if (replayDeployment.id !== runtimeDeployment.id || replayDeployment.deploymentCompositionId !== runtimeDeployment.deploymentCompositionId) {
25755
+ throw new Error(
25756
+ "Runtime feedback replay deployment does not match evidence"
25757
+ );
25758
+ }
25759
+ };
25760
+ sealRuntimeFeedbackReplayBundle = async ({
25761
+ bundleDir,
25762
+ runId,
25763
+ runtimeEvidenceBundle
25764
+ }) => {
25765
+ const replayEvidencePath = import_node_path18.default.join(bundleDir, RUNTIME_FEEDBACK_REPLAY_FILE);
25766
+ const logPath = import_node_path18.default.join(bundleDir, RUNTIME_FEEDBACK_LOG_FILE);
25767
+ const [replayPayload, logPayload] = await Promise.all([
25768
+ import_promises24.default.readFile(replayEvidencePath),
25769
+ import_promises24.default.readFile(logPath)
25770
+ ]);
25771
+ const replayEvidence = JSON.parse(replayPayload.toString("utf8"));
25772
+ assertReplayMatchesRuntimeEvidence({
25773
+ replayEvidence,
25774
+ runtimeEvidence: runtimeEvidenceBundle
25775
+ });
25776
+ const replay = isRecord3(replayEvidence.replay) ? replayEvidence.replay : null;
25777
+ const cycleCount = Number(replay?.cycleCount);
25778
+ if (!Number.isFinite(cycleCount) || cycleCount <= 0) {
25779
+ throw new Error(
25780
+ `Runtime feedback replay produced no comparable cycles: ${String(replay?.cycleCount ?? "missing")}`
25781
+ );
25782
+ }
25783
+ const deployment = parseRuntimeEvidenceDeploymentSnapshot(
25784
+ runtimeEvidenceBundle.artifact.deployment
25785
+ );
25786
+ const producer = parseRuntimeEvidenceProducer(
25787
+ runtimeEvidenceBundle.artifact.producer
25788
+ );
25789
+ const safeRunId = safeSegment2(runId, "run");
25790
+ const artifactId = `${runtimeEvidenceBundle.manifest.artifactId}_${safeRunId}`;
25791
+ const manifest = {
25792
+ schemaVersion: 1,
25793
+ reportType: "runtime-feedback-replay",
25794
+ artifactId,
25795
+ runId: safeRunId,
25796
+ deploymentId: deployment.id,
25797
+ deploymentCompositionId: deployment.deploymentCompositionId,
25798
+ userName: runtimeEvidenceBundle.manifest.userName,
25799
+ createdAt: Date.now(),
25800
+ window: { ...runtimeEvidenceBundle.manifest.window },
25801
+ runtimeEvidence: {
25802
+ artifactId: runtimeEvidenceBundle.manifest.artifactId,
25803
+ payloadSha256: runtimeEvidenceBundle.manifest.payload.sha256
25804
+ },
25805
+ producer,
25806
+ activeStrategies: activeRuntimeEvidenceStrategies(deployment).map(
25807
+ ({ strategyName }) => strategyName
25808
+ ),
25809
+ cycleCount,
25810
+ safety: {
25811
+ cacheOnly: true,
25812
+ externalOrderPlacement: false,
25813
+ redis: "isolated",
25814
+ timescale: "read_only"
25815
+ },
25816
+ payloads: {
25817
+ replayEvidence: {
25818
+ file: RUNTIME_FEEDBACK_REPLAY_FILE,
25819
+ sha256: sha2563(replayPayload),
25820
+ bytes: replayPayload.byteLength
25821
+ },
25822
+ log: {
25823
+ file: RUNTIME_FEEDBACK_LOG_FILE,
25824
+ sha256: sha2563(logPayload),
25825
+ bytes: logPayload.byteLength
25826
+ }
25827
+ }
25828
+ };
25829
+ await import_promises24.default.writeFile(
25830
+ import_node_path18.default.join(bundleDir, RUNTIME_FEEDBACK_MANIFEST_FILE),
25831
+ `${JSON.stringify(manifest, null, 2)}
25832
+ `,
25833
+ "utf8"
25834
+ );
25835
+ await import_promises24.default.writeFile(
25836
+ import_node_path18.default.join(bundleDir, RUNTIME_FEEDBACK_COMPLETE_FILE),
25837
+ `${artifactId}
25838
+ `,
25839
+ "utf8"
25840
+ );
25841
+ return verifyRuntimeFeedbackReplayBundle(bundleDir);
25842
+ };
25843
+ verifyRuntimeFeedbackReplayBundle = async (bundleDir) => {
25844
+ const manifestPath = import_node_path18.default.join(bundleDir, RUNTIME_FEEDBACK_MANIFEST_FILE);
25845
+ const replayEvidencePath = import_node_path18.default.join(bundleDir, RUNTIME_FEEDBACK_REPLAY_FILE);
25846
+ const logPath = import_node_path18.default.join(bundleDir, RUNTIME_FEEDBACK_LOG_FILE);
25847
+ const completePath = import_node_path18.default.join(bundleDir, RUNTIME_FEEDBACK_COMPLETE_FILE);
25848
+ const [manifestText, replayPayload, logPayload, completeText] = await Promise.all([
25849
+ import_promises24.default.readFile(manifestPath, "utf8"),
25850
+ import_promises24.default.readFile(replayEvidencePath),
25851
+ import_promises24.default.readFile(logPath),
25852
+ import_promises24.default.readFile(completePath, "utf8")
25853
+ ]);
25854
+ const manifest = parseManifest2(JSON.parse(manifestText));
25855
+ if (completeText.trim() !== manifest.artifactId) {
25856
+ throw new Error(`Invalid runtime feedback completion marker: ${bundleDir}`);
25857
+ }
25858
+ for (const [payload, descriptor] of [
25859
+ [replayPayload, manifest.payloads.replayEvidence],
25860
+ [logPayload, manifest.payloads.log]
25861
+ ]) {
25862
+ if (payload.byteLength !== descriptor.bytes) {
25863
+ throw new Error(
25864
+ `Runtime feedback payload size mismatch: ${descriptor.file}`
25865
+ );
25866
+ }
25867
+ if (sha2563(payload) !== descriptor.sha256) {
25868
+ throw new Error(
25869
+ `Runtime feedback payload checksum mismatch: ${descriptor.file}`
25870
+ );
25871
+ }
25872
+ }
25873
+ const replayEvidence = JSON.parse(replayPayload.toString("utf8"));
25874
+ if (replayEvidence.reportType !== "replay-runtime-evidence") {
25875
+ throw new Error("Invalid runtime feedback replay evidence payload");
25876
+ }
25877
+ const replayWindow = isRecord3(replayEvidence.window) ? replayEvidence.window : null;
25878
+ const replay = isRecord3(replayEvidence.replay) ? replayEvidence.replay : null;
25879
+ const replayDeployment = parseRuntimeEvidenceDeploymentSnapshot(
25880
+ replayEvidence.deployment
25881
+ );
25882
+ const replayStrategies = activeRuntimeEvidenceStrategies(replayDeployment).map(({ strategyName }) => strategyName).sort();
25883
+ if (replayEvidence.userName !== manifest.userName || replayWindow?.startTime !== manifest.window.startTime || replayWindow.endTime !== manifest.window.endTime || replayDeployment.id !== manifest.deploymentId || replayDeployment.deploymentCompositionId !== manifest.deploymentCompositionId || Number(replay?.cycleCount) !== manifest.cycleCount || JSON.stringify(replayStrategies) !== JSON.stringify([...manifest.activeStrategies].sort())) {
25884
+ throw new Error("Runtime feedback replay payload does not match manifest");
25885
+ }
25886
+ return {
25887
+ bundleDir,
25888
+ manifestPath,
25889
+ replayEvidencePath,
25890
+ logPath,
25891
+ manifest,
25892
+ replayEvidence
25893
+ };
25894
+ };
25895
+ discoverRuntimeFeedbackReplayBundles = async (rootDir) => {
25896
+ const bundles = [];
25897
+ const visit = async (directory, depth) => {
25898
+ if (depth > 10) return;
25899
+ let entries;
25900
+ try {
25901
+ entries = await import_promises24.default.readdir(directory, { withFileTypes: true });
25902
+ } catch (error) {
25903
+ if (error.code === "ENOENT") return;
25904
+ throw error;
25905
+ }
25906
+ const names = new Set(entries.map((entry) => entry.name));
25907
+ if (names.has(RUNTIME_FEEDBACK_MANIFEST_FILE) && names.has(RUNTIME_FEEDBACK_REPLAY_FILE) && names.has(RUNTIME_FEEDBACK_LOG_FILE) && names.has(RUNTIME_FEEDBACK_COMPLETE_FILE)) {
25908
+ bundles.push(directory);
25909
+ return;
25910
+ }
25911
+ await Promise.all(
25912
+ entries.filter(
25913
+ (entry) => entry.isDirectory() && !entry.name.startsWith(".") && !entry.name.includes(".tmp-")
25914
+ ).map((entry) => visit(import_node_path18.default.join(directory, entry.name), depth + 1))
25915
+ );
25916
+ };
25917
+ await visit(rootDir, 0);
25918
+ return bundles.sort();
25919
+ };
25920
+ verifyRuntimeFeedbackReplaySource = async ({
25921
+ bundleDir,
25922
+ runtimeEvidenceBundleDir
25923
+ }) => {
25924
+ const [feedback, runtimeEvidence2] = await Promise.all([
25925
+ verifyRuntimeFeedbackReplayBundle(bundleDir),
25926
+ verifyRuntimeEvidenceBundle(runtimeEvidenceBundleDir)
25927
+ ]);
25928
+ if (feedback.manifest.runtimeEvidence.artifactId !== runtimeEvidence2.manifest.artifactId || feedback.manifest.runtimeEvidence.payloadSha256 !== runtimeEvidence2.manifest.payload.sha256) {
25929
+ throw new Error("Runtime feedback bundle references different evidence");
25930
+ }
25931
+ assertReplayMatchesRuntimeEvidence({
25932
+ replayEvidence: feedback.replayEvidence,
25933
+ runtimeEvidence: runtimeEvidence2
25934
+ });
25935
+ return { feedback, runtimeEvidence: runtimeEvidence2 };
25936
+ };
25937
+ }
25938
+ });
25939
+
25940
+ // src/lib/runtimeFeedbackReplay.ts
25941
+ var import_node_child_process6, import_promises25, import_node_path19, REQUIRED_ENV, FORBIDDEN_SECRET_ENV, unsafeRedisHosts, safeSegment3, assertRuntimeFeedbackReplaySafety, buildRuntimeFeedbackReplayCommands, runLoggedCommand, runRuntimeFeedbackReplay;
25942
+ var init_runtimeFeedbackReplay = __esm({
25943
+ "src/lib/runtimeFeedbackReplay.ts"() {
25944
+ "use strict";
25945
+ import_node_child_process6 = require("child_process");
25946
+ import_promises25 = __toESM(require("fs/promises"));
25947
+ import_node_path19 = __toESM(require("path"));
25948
+ init_runtimeEvidenceDeployment();
25949
+ init_runtimeEvidenceArtifacts();
25950
+ init_runtimeEvidenceProducer();
25951
+ init_runtimeFeedbackArtifacts();
25952
+ REQUIRED_ENV = {
25953
+ RUNTIME_FEEDBACK_ISOLATED_REDIS: "true",
25954
+ MAKE_ORDERS: "false",
25955
+ TRADEJS_EXTERNAL_ORDER_PLACEMENT: "false"
25956
+ };
25957
+ FORBIDDEN_SECRET_ENV = [
25958
+ "AGENT_GITHUB_TOKEN",
25959
+ "AI_API_KEY",
25960
+ "ANTHROPIC_API_KEY",
25961
+ "AUTH_SECRET",
25962
+ "BYBIT_API_KEY",
25963
+ "BYBIT_API_SECRET",
25964
+ "COINALYZE_API_KEY",
25965
+ "COINMARKETCAP_API_KEY",
25966
+ "GITHUB_TOKEN",
25967
+ "GIT_SSH_PRIVATE_KEY",
25968
+ "NEXTAUTH_SECRET",
25969
+ "NPM_TOKEN",
25970
+ "OPENAI_API_KEY",
25971
+ "OPENROUTER_API_KEY",
25972
+ "SSH_PRIVATE_KEY",
25973
+ "TG_BOT_TOKEN"
25974
+ ];
25975
+ unsafeRedisHosts = /* @__PURE__ */ new Set([
25976
+ "127.0.0.1",
25977
+ "::1",
25978
+ "inv-redis",
25979
+ "localhost",
25980
+ "redis"
25981
+ ]);
25982
+ safeSegment3 = (value, fallback) => {
25983
+ const normalized = value.trim().replace(/[^a-zA-Z0-9._-]+/g, "-");
25984
+ return normalized && normalized !== "." && normalized !== ".." ? normalized : fallback;
25985
+ };
25986
+ assertRuntimeFeedbackReplaySafety = (env) => {
25987
+ for (const [name, expected] of Object.entries(REQUIRED_ENV)) {
25988
+ if (env[name] !== expected) {
25989
+ throw new Error(`Runtime feedback replay requires ${name}=${expected}`);
25990
+ }
25991
+ }
25992
+ const redisHost = String(env.REDIS_HOST ?? "").trim().toLowerCase();
25993
+ if (!redisHost || unsafeRedisHosts.has(redisHost)) {
25994
+ throw new Error(
25995
+ `Runtime feedback replay requires a named isolated Redis host, received ${redisHost || "[missing]"}`
25996
+ );
25997
+ }
25998
+ const pgOptions = String(env.PGOPTIONS ?? "");
25999
+ if (!/default_transaction_read_only\s*=\s*on/i.test(pgOptions)) {
26000
+ throw new Error(
26001
+ "Runtime feedback replay requires PGOPTIONS with default_transaction_read_only=on"
26002
+ );
26003
+ }
26004
+ if (env.TRADEJS_TIMESCALE_READ_ONLY !== "true") {
26005
+ throw new Error(
26006
+ "Runtime feedback replay requires TRADEJS_TIMESCALE_READ_ONLY=true"
26007
+ );
26008
+ }
26009
+ const exposedSecrets = FORBIDDEN_SECRET_ENV.filter(
26010
+ (name) => String(env[name] ?? "").trim()
26011
+ );
26012
+ if (exposedSecrets.length) {
26013
+ throw new Error(
26014
+ `Runtime feedback replay received forbidden credentials: ${exposedSecrets.join(", ")}`
26015
+ );
26016
+ }
26017
+ };
26018
+ buildRuntimeFeedbackReplayCommands = ({
26019
+ cliPath,
26020
+ runtimeEvidencePath,
26021
+ replayEvidencePath,
26022
+ userName: userName3,
26023
+ connectorName,
26024
+ deploymentId,
26025
+ interval: interval4,
26026
+ startTime,
26027
+ endTime
26028
+ }) => [
26029
+ [
26030
+ cliPath,
26031
+ "replay",
26032
+ "--user",
26033
+ userName3,
26034
+ "--connector",
26035
+ connectorName,
26036
+ "--deployment",
26037
+ deploymentId,
26038
+ "--timeframe",
26039
+ interval4,
26040
+ "--startTime",
26041
+ String(startTime),
26042
+ "--endTime",
26043
+ String(endTime),
26044
+ "--runtimeEvidence",
26045
+ runtimeEvidencePath,
26046
+ "--cacheOnly"
26047
+ ],
26048
+ [
26049
+ cliPath,
26050
+ "replay-runtime-evidence",
26051
+ "--user",
26052
+ userName3,
26053
+ "--runtimeEvidence",
26054
+ runtimeEvidencePath,
26055
+ "--startTime",
26056
+ String(startTime),
26057
+ "--endTime",
26058
+ String(endTime),
26059
+ "--out",
26060
+ replayEvidencePath
26061
+ ]
26062
+ ];
26063
+ runLoggedCommand = async ({
26064
+ executable,
26065
+ command,
26066
+ cwd,
26067
+ env,
26068
+ logHandle
26069
+ }) => {
26070
+ await logHandle.write(`
26071
+ $ ${[executable, ...command].join(" ")}
26072
+ `);
26073
+ await new Promise((resolve, reject) => {
26074
+ let pendingLogWrite = Promise.resolve();
26075
+ const appendLog = (chunk) => {
26076
+ pendingLogWrite = pendingLogWrite.then(async () => {
26077
+ await logHandle.write(chunk);
26078
+ });
26079
+ };
26080
+ const child = (0, import_node_child_process6.spawn)(executable, command, {
26081
+ cwd,
26082
+ env,
26083
+ stdio: ["ignore", "pipe", "pipe"]
26084
+ });
26085
+ child.stdout.on("data", (chunk) => {
26086
+ process.stdout.write(chunk);
26087
+ appendLog(chunk);
26088
+ });
26089
+ child.stderr.on("data", (chunk) => {
26090
+ process.stderr.write(chunk);
26091
+ appendLog(chunk);
26092
+ });
26093
+ child.once("error", reject);
26094
+ child.once("close", (code, signal) => {
26095
+ void pendingLogWrite.then(() => {
26096
+ if (code === 0) {
26097
+ resolve();
26098
+ return;
26099
+ }
26100
+ reject(
26101
+ new Error(
26102
+ `Runtime feedback command failed: exit=${String(code)} signal=${String(signal)}`
26103
+ )
26104
+ );
26105
+ }, reject);
26106
+ });
26107
+ });
26108
+ };
26109
+ runRuntimeFeedbackReplay = async ({
26110
+ runtimeEvidencePath,
26111
+ outDir,
26112
+ runId = `${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}-${process.pid}`,
26113
+ projectRoot: projectRoot17,
26114
+ env = process.env,
26115
+ executable = process.execPath,
26116
+ cliPath = process.argv[1]
26117
+ }) => {
26118
+ assertRuntimeFeedbackReplaySafety(env);
26119
+ if (!cliPath) {
26120
+ throw new Error("Cannot resolve the TradeJS CLI executable path");
26121
+ }
26122
+ const runtimeEvidenceBundle = await verifyRuntimeEvidenceBundle(
26123
+ import_node_path19.default.dirname(runtimeEvidencePath)
26124
+ );
26125
+ if (import_node_path19.default.resolve(runtimeEvidenceBundle.payloadPath) !== runtimeEvidencePath) {
26126
+ throw new Error(
26127
+ `Runtime evidence must be the verified bundle payload: ${runtimeEvidenceBundle.payloadPath}`
26128
+ );
26129
+ }
26130
+ const deployedProducer = parseRuntimeEvidenceProducer(
26131
+ runtimeEvidenceBundle.artifact.producer
26132
+ );
26133
+ const currentProducer = await resolveRuntimeEvidenceProducer({
26134
+ projectRoot: projectRoot17,
26135
+ required: true
26136
+ });
26137
+ if (!currentProducer || currentProducer.projectSha !== deployedProducer.projectSha || currentProducer.imageDigest !== deployedProducer.imageDigest || currentProducer.runtimePackageManifest.sha256 !== deployedProducer.runtimePackageManifest.sha256) {
26138
+ throw new Error(
26139
+ "Runtime feedback replay image identity does not match runtime evidence"
26140
+ );
26141
+ }
26142
+ const deployment = parseRuntimeEvidenceDeploymentSnapshot(
26143
+ runtimeEvidenceBundle.artifact.deployment
26144
+ );
26145
+ const activeStrategies = activeRuntimeEvidenceStrategies(deployment);
26146
+ const intervals = new Set(
26147
+ activeStrategies.map(({ interval: interval4 }) => String(interval4))
26148
+ );
26149
+ if (intervals.size !== 1) {
26150
+ throw new Error(
26151
+ `Runtime feedback replay requires one interval, received ${[...intervals].join(",")}`
26152
+ );
26153
+ }
26154
+ await import_promises25.default.mkdir(outDir, { recursive: true });
26155
+ const existing = await import_promises25.default.readdir(outDir);
26156
+ if (existing.length) {
26157
+ throw new Error(
26158
+ `Runtime feedback output directory must be empty: ${outDir}`
26159
+ );
26160
+ }
26161
+ const replayEvidencePath = import_node_path19.default.join(outDir, RUNTIME_FEEDBACK_REPLAY_FILE);
26162
+ const logHandle = await import_promises25.default.open(
26163
+ import_node_path19.default.join(outDir, RUNTIME_FEEDBACK_LOG_FILE),
26164
+ "wx"
26165
+ );
26166
+ const commands = buildRuntimeFeedbackReplayCommands({
26167
+ cliPath,
26168
+ runtimeEvidencePath,
26169
+ replayEvidencePath,
26170
+ userName: runtimeEvidenceBundle.manifest.userName,
26171
+ connectorName: deployment.connectorName,
26172
+ deploymentId: deployment.id,
26173
+ interval: [...intervals][0],
26174
+ startTime: runtimeEvidenceBundle.manifest.window.startTime,
26175
+ endTime: runtimeEvidenceBundle.manifest.window.endTime
26176
+ });
26177
+ try {
26178
+ for (const command of commands) {
26179
+ await runLoggedCommand({
26180
+ executable,
26181
+ command,
26182
+ cwd: projectRoot17,
26183
+ env,
26184
+ logHandle
26185
+ });
26186
+ }
26187
+ } finally {
26188
+ await logHandle.close();
26189
+ }
26190
+ return sealRuntimeFeedbackReplayBundle({
26191
+ bundleDir: outDir,
26192
+ runId: safeSegment3(runId, "run"),
26193
+ runtimeEvidenceBundle
26194
+ });
26195
+ };
26196
+ }
26197
+ });
26198
+
26199
+ // src/scripts/runtimeFeedbackReplay.ts
26200
+ var runtimeFeedbackReplay_exports = {};
26201
+ __export(runtimeFeedbackReplay_exports, {
26202
+ main: () => main34,
26203
+ runtimeFeedbackReplay: () => runtimeFeedbackReplay
26204
+ });
26205
+ var import_node_path20, import_args26, import_chalk39, flags25, projectRoot9, runtimeFeedbackReplay, main34;
26206
+ var init_runtimeFeedbackReplay2 = __esm({
26207
+ "src/scripts/runtimeFeedbackReplay.ts"() {
26208
+ "use strict";
26209
+ import_node_path20 = __toESM(require("path"));
26210
+ import_args26 = __toESM(require("args"));
26211
+ import_chalk39 = __toESM(require("chalk"));
26212
+ init_runtimeFeedbackReplay();
26213
+ import_args26.default.option("runtimeEvidence", "Verified runtime evidence JSON");
26214
+ import_args26.default.option("outDir", "New writable directory for replay output");
26215
+ import_args26.default.option("runId", "Stable identifier for this replay attempt");
26216
+ flags25 = import_args26.default.parse(process.argv);
26217
+ projectRoot9 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
26218
+ runtimeFeedbackReplay = async () => {
26219
+ const runtimeEvidence2 = String(flags25.runtimeEvidence ?? "").trim();
26220
+ const outDir = String(flags25.outDir ?? "").trim();
26221
+ if (!runtimeEvidence2 || !outDir) {
26222
+ throw new Error(
26223
+ "Provide --runtimeEvidence and --outDir for runtime feedback replay."
26224
+ );
26225
+ }
26226
+ const verified = await runRuntimeFeedbackReplay({
26227
+ runtimeEvidencePath: import_node_path20.default.resolve(projectRoot9, runtimeEvidence2),
26228
+ outDir: import_node_path20.default.resolve(projectRoot9, outDir),
26229
+ runId: String(flags25.runId ?? "").trim() || void 0,
26230
+ projectRoot: projectRoot9
26231
+ });
26232
+ console.log(
26233
+ import_chalk39.default.green(
26234
+ `Runtime feedback replay sealed: ${verified.manifest.artifactId}`
26235
+ )
26236
+ );
26237
+ console.log(
26238
+ JSON.stringify(
26239
+ {
26240
+ bundleDir: verified.bundleDir,
26241
+ manifestPath: verified.manifestPath,
26242
+ replayEvidencePath: verified.replayEvidencePath
26243
+ },
26244
+ null,
26245
+ 2
26246
+ )
26247
+ );
26248
+ };
26249
+ main34 = runtimeFeedbackReplay;
26250
+ }
26251
+ });
26252
+
26253
+ // src/lib/runtimeEvidenceSync.ts
26254
+ var import_node_child_process7, import_promises26, import_node_path21, import_node_util, execFileAsync, isExistingDestinationError2, safeSegment4, withTrailingSlash, dateParts2, buildRuntimeEvidenceRsyncArgs, receiptPath, compareBundles, listPendingRuntimeEvidenceBundles, markRuntimeEvidenceBundleProcessed, syncRuntimeEvidenceBundles;
26255
+ var init_runtimeEvidenceSync = __esm({
26256
+ "src/lib/runtimeEvidenceSync.ts"() {
26257
+ "use strict";
26258
+ import_node_child_process7 = require("child_process");
26259
+ import_promises26 = __toESM(require("fs/promises"));
26260
+ import_node_path21 = __toESM(require("path"));
26261
+ import_node_util = require("util");
26262
+ init_runtimeEvidenceArtifacts();
26263
+ init_runtimeEvidenceDeployment();
26264
+ execFileAsync = (0, import_node_util.promisify)(import_node_child_process7.execFile);
26265
+ isExistingDestinationError2 = (error) => {
26266
+ const code = error.code;
26267
+ return code === "EEXIST" || code === "ENOTEMPTY";
26268
+ };
26269
+ safeSegment4 = (value, fallback) => {
26270
+ const normalized = value.trim().replace(/[^a-zA-Z0-9._-]+/g, "-");
26271
+ return normalized && normalized !== "." && normalized !== ".." ? normalized : fallback;
26272
+ };
26273
+ withTrailingSlash = (value) => value.endsWith("/") ? value : `${value}/`;
26274
+ dateParts2 = (timestamp) => {
26275
+ const date = new Date(timestamp);
26276
+ return [
26277
+ String(date.getUTCFullYear()),
26278
+ String(date.getUTCMonth() + 1).padStart(2, "0"),
26279
+ String(date.getUTCDate()).padStart(2, "0")
26280
+ ];
26281
+ };
26282
+ buildRuntimeEvidenceRsyncArgs = ({
26283
+ source,
26284
+ destination
26285
+ }) => [
26286
+ "--recursive",
26287
+ "--times",
26288
+ "--partial",
26289
+ "--partial-dir=.rsync-partial",
26290
+ "--prune-empty-dirs",
26291
+ withTrailingSlash(source),
26292
+ withTrailingSlash(destination)
26293
+ ];
26294
+ receiptPath = (receiptsRoot, artifactId) => import_node_path21.default.join(receiptsRoot, `${safeSegment4(artifactId, "artifact")}.json`);
26295
+ compareBundles = (left, right) => left.manifest.window.endTime - right.manifest.window.endTime || left.manifest.createdAt - right.manifest.createdAt;
26296
+ listPendingRuntimeEvidenceBundles = async ({
26297
+ evidenceRoot,
26298
+ deploymentId
26299
+ }) => {
26300
+ const safeDeploymentId = safeSegment4(deploymentId, "production");
26301
+ const artifactsRoot = import_node_path21.default.join(evidenceRoot, "artifacts", safeDeploymentId);
26302
+ const receiptsRoot = import_node_path21.default.join(evidenceRoot, "receipts", safeDeploymentId);
26303
+ const bundles = await discoverRuntimeEvidenceBundles(artifactsRoot);
26304
+ const pending = [];
26305
+ for (const bundleDir of bundles) {
26306
+ const verified = await verifyRuntimeEvidenceBundle(bundleDir);
26307
+ if (verified.manifest.deploymentId !== safeDeploymentId) continue;
26308
+ assertCurrentRuntimeEvidenceArtifact(verified.artifact);
26309
+ try {
26310
+ await import_promises26.default.access(receiptPath(receiptsRoot, verified.manifest.artifactId));
26311
+ continue;
26312
+ } catch (error) {
26313
+ if (error.code !== "ENOENT") throw error;
26314
+ }
26315
+ pending.push(verified);
26316
+ }
26317
+ return pending.sort(compareBundles);
26318
+ };
26319
+ markRuntimeEvidenceBundleProcessed = async ({
26320
+ evidenceRoot,
26321
+ deploymentId,
26322
+ bundleDir,
26323
+ scorecardPath,
26324
+ runtimeFeedback
26325
+ }) => {
26326
+ const safeDeploymentId = safeSegment4(deploymentId, "production");
26327
+ const verified = await verifyRuntimeEvidenceBundle(bundleDir);
26328
+ if (verified.manifest.deploymentId !== safeDeploymentId) {
26329
+ throw new Error(
26330
+ `Artifact deployment mismatch: expected ${safeDeploymentId}, received ${verified.manifest.deploymentId}`
26331
+ );
26332
+ }
26333
+ const receiptsRoot = import_node_path21.default.join(evidenceRoot, "receipts", safeDeploymentId);
26334
+ const finalPath = receiptPath(receiptsRoot, verified.manifest.artifactId);
26335
+ const temporaryPath = `${finalPath}.tmp-${process.pid}`;
26336
+ const receipt = {
26337
+ schemaVersion: runtimeFeedback ? 2 : 1,
26338
+ artifactId: verified.manifest.artifactId,
26339
+ payloadSha256: verified.manifest.payload.sha256,
26340
+ processedAt: Date.now(),
26341
+ scorecardPath: scorecardPath ?? null,
26342
+ ...runtimeFeedback ? {
26343
+ runtimeFeedbackArtifactId: runtimeFeedback.artifactId,
26344
+ replayEvidenceSha256: runtimeFeedback.replayEvidenceSha256
26345
+ } : {}
26346
+ };
26347
+ await import_promises26.default.mkdir(receiptsRoot, { recursive: true });
26348
+ await import_promises26.default.writeFile(
26349
+ temporaryPath,
26350
+ `${JSON.stringify(receipt, null, 2)}
26351
+ `,
26352
+ "utf8"
26353
+ );
26354
+ await import_promises26.default.rename(temporaryPath, finalPath);
26355
+ return finalPath;
26356
+ };
26357
+ syncRuntimeEvidenceBundles = async ({
26358
+ source,
26359
+ evidenceRoot,
26360
+ deploymentId,
26361
+ runRsync = async (args37) => {
26362
+ const result = await execFileAsync("rsync", args37, {
26363
+ maxBuffer: 10 * 1024 * 1024
26364
+ });
26365
+ return { stdout: result.stdout, stderr: result.stderr };
26366
+ }
26367
+ }) => {
26368
+ const safeDeploymentId = safeSegment4(deploymentId, "production");
26369
+ const inboxRoot = import_node_path21.default.join(evidenceRoot, "inbox", safeDeploymentId);
26370
+ const artifactsRoot = import_node_path21.default.join(evidenceRoot, "artifacts", safeDeploymentId);
26371
+ await Promise.all([
26372
+ import_promises26.default.mkdir(inboxRoot, { recursive: true }),
26373
+ import_promises26.default.mkdir(artifactsRoot, { recursive: true })
26374
+ ]);
26375
+ const rsyncArgs = buildRuntimeEvidenceRsyncArgs({
26376
+ source,
26377
+ destination: inboxRoot
26378
+ });
26379
+ const transfer = await runRsync(rsyncArgs);
26380
+ const discovered = await discoverRuntimeEvidenceBundles(inboxRoot);
26381
+ const received = [];
26382
+ for (const bundleDir of discovered) {
26383
+ const verified = await verifyRuntimeEvidenceBundle(bundleDir);
26384
+ if (verified.manifest.deploymentId !== safeDeploymentId) {
26385
+ throw new Error(
26386
+ `Artifact deployment mismatch: expected ${safeDeploymentId}, received ${verified.manifest.deploymentId}`
26387
+ );
26388
+ }
26389
+ assertCurrentRuntimeEvidenceArtifact(verified.artifact);
26390
+ const destinationDir = import_node_path21.default.join(
26391
+ artifactsRoot,
26392
+ ...dateParts2(verified.manifest.window.endTime),
26393
+ safeSegment4(verified.manifest.artifactId, "artifact")
26394
+ );
26395
+ await import_promises26.default.mkdir(import_node_path21.default.dirname(destinationDir), { recursive: true });
26396
+ try {
26397
+ await import_promises26.default.rename(bundleDir, destinationDir);
26398
+ } catch (error) {
26399
+ if (!isExistingDestinationError2(error)) throw error;
26400
+ const existing = await verifyRuntimeEvidenceBundle(destinationDir);
26401
+ if (existing.manifest.payload.sha256 !== verified.manifest.payload.sha256) {
26402
+ throw new Error(
26403
+ `Conflicting runtime evidence artifact ${verified.manifest.artifactId}`
26404
+ );
26405
+ }
26406
+ await import_promises26.default.rm(bundleDir, { recursive: true, force: true });
26407
+ }
26408
+ received.push(await verifyRuntimeEvidenceBundle(destinationDir));
26409
+ }
26410
+ const pending = await listPendingRuntimeEvidenceBundles({
26411
+ evidenceRoot,
26412
+ deploymentId: safeDeploymentId
26413
+ });
26414
+ return {
26415
+ rsyncArgs,
26416
+ stdout: String(transfer.stdout ?? ""),
26417
+ stderr: String(transfer.stderr ?? ""),
26418
+ received,
26419
+ pending
26420
+ };
26421
+ };
26422
+ }
26423
+ });
26424
+
26425
+ // src/lib/runtimeFeedbackSync.ts
26426
+ var import_node_child_process8, import_promises27, import_node_path22, import_node_util2, execFileAsync2, isExistingDestinationError3, safeSegment5, dateParts3, syncRuntimeFeedbackReplayBundles;
26427
+ var init_runtimeFeedbackSync = __esm({
26428
+ "src/lib/runtimeFeedbackSync.ts"() {
26429
+ "use strict";
26430
+ import_node_child_process8 = require("child_process");
26431
+ import_promises27 = __toESM(require("fs/promises"));
26432
+ import_node_path22 = __toESM(require("path"));
26433
+ import_node_util2 = require("util");
26434
+ init_runtimeFeedbackArtifacts();
26435
+ init_runtimeEvidenceSync();
26436
+ execFileAsync2 = (0, import_node_util2.promisify)(import_node_child_process8.execFile);
26437
+ isExistingDestinationError3 = (error) => {
26438
+ const code = error.code;
26439
+ return code === "EEXIST" || code === "ENOTEMPTY";
26440
+ };
26441
+ safeSegment5 = (value, fallback) => {
26442
+ const normalized = value.trim().replace(/[^a-zA-Z0-9._-]+/g, "-");
26443
+ return normalized && normalized !== "." && normalized !== ".." ? normalized : fallback;
26444
+ };
26445
+ dateParts3 = (timestamp) => {
26446
+ const date = new Date(timestamp);
26447
+ return [
26448
+ String(date.getUTCFullYear()),
26449
+ String(date.getUTCMonth() + 1).padStart(2, "0"),
26450
+ String(date.getUTCDate()).padStart(2, "0")
26451
+ ];
26452
+ };
26453
+ syncRuntimeFeedbackReplayBundles = async ({
26454
+ source,
26455
+ feedbackRoot,
26456
+ deploymentId,
26457
+ runRsync = async (args37) => {
26458
+ const result = await execFileAsync2("rsync", args37, {
26459
+ maxBuffer: 10 * 1024 * 1024
26460
+ });
26461
+ return { stdout: result.stdout, stderr: result.stderr };
26462
+ }
26463
+ }) => {
26464
+ const safeDeploymentId = safeSegment5(deploymentId, "production");
26465
+ const inboxRoot = import_node_path22.default.join(feedbackRoot, "inbox", safeDeploymentId);
26466
+ const artifactsRoot = import_node_path22.default.join(feedbackRoot, "artifacts", safeDeploymentId);
26467
+ await Promise.all([
26468
+ import_promises27.default.mkdir(inboxRoot, { recursive: true }),
26469
+ import_promises27.default.mkdir(artifactsRoot, { recursive: true })
26470
+ ]);
26471
+ const rsyncArgs = buildRuntimeEvidenceRsyncArgs({
26472
+ source,
26473
+ destination: inboxRoot
26474
+ });
26475
+ const transfer = await runRsync(rsyncArgs);
26476
+ const discovered = await discoverRuntimeFeedbackReplayBundles(inboxRoot);
26477
+ const received = [];
26478
+ for (const bundleDir of discovered) {
26479
+ const verified = await verifyRuntimeFeedbackReplayBundle(bundleDir);
26480
+ if (verified.manifest.deploymentId !== safeDeploymentId) {
26481
+ throw new Error(
26482
+ `Runtime feedback deployment mismatch: expected ${safeDeploymentId}, received ${verified.manifest.deploymentId}`
26483
+ );
26484
+ }
26485
+ const destinationDir = import_node_path22.default.join(
26486
+ artifactsRoot,
26487
+ ...dateParts3(verified.manifest.window.endTime),
26488
+ safeSegment5(verified.manifest.runtimeEvidence.artifactId, "artifact"),
26489
+ safeSegment5(verified.manifest.runId, "run")
26490
+ );
26491
+ await import_promises27.default.mkdir(import_node_path22.default.dirname(destinationDir), { recursive: true });
26492
+ try {
26493
+ await import_promises27.default.rename(bundleDir, destinationDir);
26494
+ } catch (error) {
26495
+ if (!isExistingDestinationError3(error)) throw error;
26496
+ const existing = await verifyRuntimeFeedbackReplayBundle(destinationDir);
26497
+ if (existing.manifest.payloads.replayEvidence.sha256 !== verified.manifest.payloads.replayEvidence.sha256) {
26498
+ throw new Error(
26499
+ `Conflicting runtime feedback replay ${verified.manifest.artifactId}`
26500
+ );
26501
+ }
26502
+ await import_promises27.default.rm(bundleDir, { recursive: true, force: true });
26503
+ }
26504
+ received.push(await verifyRuntimeFeedbackReplayBundle(destinationDir));
26505
+ }
26506
+ return {
26507
+ rsyncArgs,
26508
+ stdout: String(transfer.stdout ?? ""),
26509
+ stderr: String(transfer.stderr ?? ""),
26510
+ received
26511
+ };
26512
+ };
26513
+ }
26514
+ });
26515
+
26516
+ // src/scripts/runtimeFeedbackSync.ts
26517
+ var runtimeFeedbackSync_exports = {};
26518
+ __export(runtimeFeedbackSync_exports, {
26519
+ main: () => main35,
26520
+ runtimeFeedbackSync: () => runtimeFeedbackSync
26521
+ });
26522
+ var import_node_path23, import_args27, import_chalk40, flags26, projectRoot10, runtimeFeedbackSync, main35;
26523
+ var init_runtimeFeedbackSync2 = __esm({
26524
+ "src/scripts/runtimeFeedbackSync.ts"() {
26525
+ "use strict";
26526
+ import_node_path23 = __toESM(require("path"));
26527
+ import_args27 = __toESM(require("args"));
26528
+ import_chalk40 = __toESM(require("chalk"));
26529
+ init_runtimeFeedbackSync();
26530
+ import_args27.default.option(
26531
+ "source",
26532
+ "Rsync source ending at the runtime feedback ready directory",
26533
+ process.env.RUNTIME_FEEDBACK_RSYNC_SOURCE
26534
+ );
26535
+ import_args27.default.option(
26536
+ "deployment",
26537
+ "Deployment id expected in runtime feedback manifests",
26538
+ process.env.RUNTIME_EVIDENCE_DEPLOYMENT_ID || "production"
26539
+ );
26540
+ import_args27.default.option(
26541
+ "dir",
26542
+ "Local runtime feedback storage root",
26543
+ process.env.RUNTIME_FEEDBACK_LOCAL_DIR || "data/runtime-feedback"
26544
+ );
26545
+ flags26 = import_args27.default.parse(process.argv);
26546
+ projectRoot10 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
26547
+ runtimeFeedbackSync = async () => {
26548
+ const source = String(flags26.source ?? "").trim();
26549
+ if (!source) {
26550
+ throw new Error(
26551
+ "Provide --source or RUNTIME_FEEDBACK_RSYNC_SOURCE for runtime feedback sync."
26552
+ );
26553
+ }
26554
+ const feedbackRoot = import_node_path23.default.resolve(projectRoot10, String(flags26.dir));
26555
+ const result = await syncRuntimeFeedbackReplayBundles({
26556
+ source,
26557
+ feedbackRoot,
26558
+ deploymentId: String(flags26.deployment)
26559
+ });
26560
+ console.log(
26561
+ import_chalk40.default.green(
26562
+ `Runtime feedback sync completed: received=${result.received.length}`
26563
+ )
26564
+ );
26565
+ console.log(
26566
+ JSON.stringify(
26567
+ {
26568
+ feedbackRoot,
26569
+ received: result.received.map((bundle) => ({
26570
+ artifactId: bundle.manifest.artifactId,
26571
+ bundleDir: bundle.bundleDir,
26572
+ replayEvidencePath: bundle.replayEvidencePath,
26573
+ runtimeEvidence: bundle.manifest.runtimeEvidence
26574
+ }))
26575
+ },
26576
+ null,
26577
+ 2
26578
+ )
26579
+ );
26580
+ };
26581
+ main35 = runtimeFeedbackSync;
26582
+ }
26583
+ });
26584
+
25609
26585
  // src/lib/runtimeLineage.ts
25610
- var import_node_crypto11, normalizeForStableJson2, resolveRuntimeMaxLossValue, fingerprintRuntimeValue, buildRuntimeLineage, runtimeLineageKey, runtimeLineagesMatch, runtimeLineagesComparable;
26586
+ var import_node_crypto13, normalizeForStableJson2, resolveRuntimeMaxLossValue, fingerprintRuntimeValue, buildRuntimeLineage, runtimeLineageKey, runtimeLineagesMatch, runtimeLineagesComparable;
25611
26587
  var init_runtimeLineage = __esm({
25612
26588
  "src/lib/runtimeLineage.ts"() {
25613
26589
  "use strict";
25614
- import_node_crypto11 = require("crypto");
26590
+ import_node_crypto13 = require("crypto");
25615
26591
  normalizeForStableJson2 = (value) => {
25616
26592
  if (Array.isArray(value)) {
25617
26593
  return value.map(normalizeForStableJson2);
@@ -25636,7 +26612,7 @@ var init_runtimeLineage = __esm({
25636
26612
  );
25637
26613
  return Number.isFinite(maxLossValue) ? maxLossValue : null;
25638
26614
  };
25639
- fingerprintRuntimeValue = (value) => (0, import_node_crypto11.createHash)("sha256").update(JSON.stringify(normalizeForStableJson2(value))).digest("hex").slice(0, 16);
26615
+ fingerprintRuntimeValue = (value) => (0, import_node_crypto13.createHash)("sha256").update(JSON.stringify(normalizeForStableJson2(value))).digest("hex").slice(0, 16);
25640
26616
  buildRuntimeLineage = async ({
25641
26617
  strategyRevision,
25642
26618
  deploymentCompositionId,
@@ -25687,50 +26663,51 @@ var init_runtimeLineage = __esm({
25687
26663
  // src/scripts/runtimeEvidence.ts
25688
26664
  var runtimeEvidence_exports = {};
25689
26665
  __export(runtimeEvidence_exports, {
25690
- main: () => main34,
26666
+ main: () => main36,
25691
26667
  runtimeEvidence: () => runtimeEvidence
25692
26668
  });
25693
- var import_promises23, import_node_path17, import_args26, import_chalk39, flags25, projectRoot9, toEpochMs3, resolveWindow2, parseStrategyFilter2, runtimeEvidence, main34;
26669
+ var import_promises28, import_node_path24, import_args28, import_chalk41, flags27, projectRoot11, toEpochMs3, resolveWindow2, parseStrategyFilter2, runtimeEvidence, main36;
25694
26670
  var init_runtimeEvidence = __esm({
25695
26671
  "src/scripts/runtimeEvidence.ts"() {
25696
26672
  "use strict";
25697
- import_promises23 = __toESM(require("fs/promises"));
25698
- import_node_path17 = __toESM(require("path"));
25699
- import_args26 = __toESM(require("args"));
25700
- import_chalk39 = __toESM(require("chalk"));
26673
+ import_promises28 = __toESM(require("fs/promises"));
26674
+ import_node_path24 = __toESM(require("path"));
26675
+ import_args28 = __toESM(require("args"));
26676
+ import_chalk41 = __toESM(require("chalk"));
25701
26677
  init_runtimeDebugEvidence();
25702
26678
  init_runtimeEvidenceArtifacts();
25703
26679
  init_runtimeLineage();
26680
+ init_runtimeEvidenceProducer();
25704
26681
  init_runtimeEvidenceDeployment();
25705
- import_args26.default.option(["u", "user"], "Use user config", "root");
25706
- import_args26.default.option(
26682
+ import_args28.default.option(["u", "user"], "Use user config", "root");
26683
+ import_args28.default.option(
25707
26684
  ["S", "startTime"],
25708
26685
  "Window start timestamp, seconds/ms, or ISO date"
25709
26686
  );
25710
- import_args26.default.option(["E", "endTime"], "Window end timestamp, seconds/ms, or ISO date");
25711
- import_args26.default.option(
26687
+ import_args28.default.option(["E", "endTime"], "Window end timestamp, seconds/ms, or ISO date");
26688
+ import_args28.default.option(
25712
26689
  ["H", "hours"],
25713
26690
  "Fallback window in hours when start/end are omitted",
25714
26691
  24
25715
26692
  );
25716
- import_args26.default.option(
26693
+ import_args28.default.option(
25717
26694
  "daily",
25718
26695
  "Use the latest complete 21:00 MSK to 21:00 MSK window",
25719
26696
  false
25720
26697
  );
25721
- import_args26.default.option(["s", "strategy"], "Strategy filter, comma-separated");
25722
- import_args26.default.option(["o", "out"], "Output JSON path", "output/runtime-evidence.json");
25723
- import_args26.default.option(
26698
+ import_args28.default.option(["s", "strategy"], "Strategy filter, comma-separated");
26699
+ import_args28.default.option(["o", "out"], "Output JSON path", "output/runtime-evidence.json");
26700
+ import_args28.default.option(
25724
26701
  "publishDir",
25725
26702
  "Publish an immutable bundle under <dir>/ready/<deployment>"
25726
26703
  );
25727
- import_args26.default.option(
26704
+ import_args28.default.option(
25728
26705
  "deployment",
25729
26706
  "Deployment id used by immutable evidence bundles",
25730
26707
  process.env.RUNTIME_EVIDENCE_DEPLOYMENT_ID || "production"
25731
26708
  );
25732
- flags25 = import_args26.default.parse(process.argv);
25733
- projectRoot9 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
26709
+ flags27 = import_args28.default.parse(process.argv);
26710
+ projectRoot11 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
25734
26711
  toEpochMs3 = (value) => {
25735
26712
  if (value == null || value === "") {
25736
26713
  return null;
@@ -25744,11 +26721,11 @@ var init_runtimeEvidence = __esm({
25744
26721
  return Number.isFinite(parsed) ? parsed : null;
25745
26722
  };
25746
26723
  resolveWindow2 = () => {
25747
- const explicitStartTime = toEpochMs3(flags25.startTime);
25748
- const explicitEndTime = toEpochMs3(flags25.endTime);
26724
+ const explicitStartTime = toEpochMs3(flags27.startTime);
26725
+ const explicitEndTime = toEpochMs3(flags27.endTime);
25749
26726
  const now2 = Date.now();
25750
26727
  const dailyEndTime = (() => {
25751
- if (!flags25.daily || explicitStartTime != null || explicitEndTime != null) {
26728
+ if (!flags27.daily || explicitStartTime != null || explicitEndTime != null) {
25752
26729
  return null;
25753
26730
  }
25754
26731
  const date = new Date(now2);
@@ -25763,7 +26740,7 @@ var init_runtimeEvidence = __esm({
25763
26740
  const endTime = explicitEndTime ?? dailyEndTime ?? now2;
25764
26741
  const hours = Math.max(
25765
26742
  1,
25766
- Number.parseInt(String(flags25.hours ?? 24), 10) || 24
26743
+ Number.parseInt(String(flags27.hours ?? 24), 10) || 24
25767
26744
  );
25768
26745
  const startTime = explicitStartTime ?? endTime - hours * 60 * 60 * 1e3;
25769
26746
  if (startTime >= endTime) {
@@ -25780,16 +26757,21 @@ var init_runtimeEvidence = __esm({
25780
26757
  parseStrategyFilter2 = (value) => String(value ?? "").split(",").map((item) => item.trim()).filter(Boolean);
25781
26758
  runtimeEvidence = async () => {
25782
26759
  const { startTime, endTime, source } = resolveWindow2();
25783
- const deploymentId = String(flags25.deployment);
26760
+ const deploymentId = String(flags27.deployment);
26761
+ const publishDir = String(flags27.publishDir ?? "").trim();
26762
+ const producer = await resolveRuntimeEvidenceProducer({
26763
+ projectRoot: projectRoot11,
26764
+ required: Boolean(publishDir)
26765
+ });
25784
26766
  const deploymentSnapshot = await resolveRuntimeEvidenceDeploymentSnapshot({
25785
- userName: String(flags25.user),
25786
- projectRoot: projectRoot9,
26767
+ userName: String(flags27.user),
26768
+ projectRoot: projectRoot11,
25787
26769
  deploymentId
25788
26770
  });
25789
26771
  const activeStrategies = activeRuntimeEvidenceStrategies(
25790
26772
  deploymentSnapshot
25791
26773
  ).map(({ strategyName }) => strategyName);
25792
- const requestedStrategies = parseStrategyFilter2(flags25.strategy);
26774
+ const requestedStrategies = parseStrategyFilter2(flags27.strategy);
25793
26775
  const strategies = requestedStrategies.length ? requestedStrategies : activeStrategies;
25794
26776
  const declaredStrategies = new Set(
25795
26777
  deploymentSnapshot.strategies.map(({ strategyName }) => strategyName)
@@ -25803,7 +26785,7 @@ var init_runtimeEvidence = __esm({
25803
26785
  );
25804
26786
  }
25805
26787
  const evidence = await collectRuntimeDebugEvidence({
25806
- userName: flags25.user,
26788
+ userName: flags27.user,
25807
26789
  startTime,
25808
26790
  endTime,
25809
26791
  strategies,
@@ -25837,7 +26819,7 @@ var init_runtimeEvidence = __esm({
25837
26819
  })
25838
26820
  );
25839
26821
  const runtime = buildRuntimeEvidenceReportPayload({
25840
- userName: flags25.user,
26822
+ userName: flags27.user,
25841
26823
  startTime,
25842
26824
  endTime,
25843
26825
  signals: currentSignals,
@@ -25852,7 +26834,8 @@ var init_runtimeEvidence = __esm({
25852
26834
  const artifact = {
25853
26835
  reportType: "runtime-evidence",
25854
26836
  generatedAt: Date.now(),
25855
- userName: flags25.user,
26837
+ ...producer ? { producer } : {},
26838
+ userName: flags27.user,
25856
26839
  window: {
25857
26840
  startTime,
25858
26841
  endTime,
@@ -25864,15 +26847,14 @@ var init_runtimeEvidence = __esm({
25864
26847
  deployment,
25865
26848
  runtime
25866
26849
  };
25867
- const outPath = import_node_path17.default.resolve(projectRoot9, String(flags25.out));
25868
- await import_promises23.default.mkdir(import_node_path17.default.dirname(outPath), { recursive: true });
25869
- await import_promises23.default.writeFile(outPath, `${JSON.stringify(artifact, null, 2)}
26850
+ const outPath = import_node_path24.default.resolve(projectRoot11, String(flags27.out));
26851
+ await import_promises28.default.mkdir(import_node_path24.default.dirname(outPath), { recursive: true });
26852
+ await import_promises28.default.writeFile(outPath, `${JSON.stringify(artifact, null, 2)}
25870
26853
  `, "utf8");
25871
- const publishDir = String(flags25.publishDir ?? "").trim();
25872
26854
  const published = publishDir ? await publishRuntimeEvidenceBundle({
25873
- publishRoot: import_node_path17.default.resolve(projectRoot9, publishDir),
26855
+ publishRoot: import_node_path24.default.resolve(projectRoot11, publishDir),
25874
26856
  deploymentId,
25875
- userName: String(flags25.user),
26857
+ userName: String(flags27.user),
25876
26858
  startTime,
25877
26859
  endTime,
25878
26860
  artifact,
@@ -25884,9 +26866,9 @@ var init_runtimeEvidence = __esm({
25884
26866
  ...currentLineageScopes.map((scope) => scope.lineage)
25885
26867
  ].filter((lineage) => lineage != null).map(runtimeLineageKey).filter((key, index, values) => values.indexOf(key) === index)
25886
26868
  }) : null;
25887
- console.log(import_chalk39.default.green(`Wrote ${outPath}`));
26869
+ console.log(import_chalk41.default.green(`Wrote ${outPath}`));
25888
26870
  if (published) {
25889
- console.log(import_chalk39.default.green(`Published ${published.bundleDir}`));
26871
+ console.log(import_chalk41.default.green(`Published ${published.bundleDir}`));
25890
26872
  }
25891
26873
  console.log(
25892
26874
  JSON.stringify(
@@ -25899,223 +26881,56 @@ var init_runtimeEvidence = __esm({
25899
26881
  )
25900
26882
  );
25901
26883
  };
25902
- main34 = runtimeEvidence;
25903
- }
25904
- });
25905
-
25906
- // src/lib/runtimeEvidenceSync.ts
25907
- var import_node_child_process6, import_promises24, import_node_path18, import_node_util, execFileAsync, isExistingDestinationError2, safeSegment2, withTrailingSlash, dateParts2, buildRuntimeEvidenceRsyncArgs, receiptPath, compareBundles, listPendingRuntimeEvidenceBundles, markRuntimeEvidenceBundleProcessed, syncRuntimeEvidenceBundles;
25908
- var init_runtimeEvidenceSync = __esm({
25909
- "src/lib/runtimeEvidenceSync.ts"() {
25910
- "use strict";
25911
- import_node_child_process6 = require("child_process");
25912
- import_promises24 = __toESM(require("fs/promises"));
25913
- import_node_path18 = __toESM(require("path"));
25914
- import_node_util = require("util");
25915
- init_runtimeEvidenceArtifacts();
25916
- init_runtimeEvidenceDeployment();
25917
- execFileAsync = (0, import_node_util.promisify)(import_node_child_process6.execFile);
25918
- isExistingDestinationError2 = (error) => {
25919
- const code = error.code;
25920
- return code === "EEXIST" || code === "ENOTEMPTY";
25921
- };
25922
- safeSegment2 = (value, fallback) => {
25923
- const normalized = value.trim().replace(/[^a-zA-Z0-9._-]+/g, "-");
25924
- return normalized && normalized !== "." && normalized !== ".." ? normalized : fallback;
25925
- };
25926
- withTrailingSlash = (value) => value.endsWith("/") ? value : `${value}/`;
25927
- dateParts2 = (timestamp) => {
25928
- const date = new Date(timestamp);
25929
- return [
25930
- String(date.getUTCFullYear()),
25931
- String(date.getUTCMonth() + 1).padStart(2, "0"),
25932
- String(date.getUTCDate()).padStart(2, "0")
25933
- ];
25934
- };
25935
- buildRuntimeEvidenceRsyncArgs = ({
25936
- source,
25937
- destination
25938
- }) => [
25939
- "--recursive",
25940
- "--times",
25941
- "--partial",
25942
- "--partial-dir=.rsync-partial",
25943
- "--prune-empty-dirs",
25944
- withTrailingSlash(source),
25945
- withTrailingSlash(destination)
25946
- ];
25947
- receiptPath = (receiptsRoot, artifactId) => import_node_path18.default.join(receiptsRoot, `${safeSegment2(artifactId, "artifact")}.json`);
25948
- compareBundles = (left, right) => left.manifest.window.endTime - right.manifest.window.endTime || left.manifest.createdAt - right.manifest.createdAt;
25949
- listPendingRuntimeEvidenceBundles = async ({
25950
- evidenceRoot,
25951
- deploymentId
25952
- }) => {
25953
- const safeDeploymentId = safeSegment2(deploymentId, "production");
25954
- const artifactsRoot = import_node_path18.default.join(evidenceRoot, "artifacts", safeDeploymentId);
25955
- const receiptsRoot = import_node_path18.default.join(evidenceRoot, "receipts", safeDeploymentId);
25956
- const bundles = await discoverRuntimeEvidenceBundles(artifactsRoot);
25957
- const pending = [];
25958
- for (const bundleDir of bundles) {
25959
- const verified = await verifyRuntimeEvidenceBundle(bundleDir);
25960
- if (verified.manifest.deploymentId !== safeDeploymentId) continue;
25961
- assertCurrentRuntimeEvidenceArtifact(verified.artifact);
25962
- try {
25963
- await import_promises24.default.access(receiptPath(receiptsRoot, verified.manifest.artifactId));
25964
- continue;
25965
- } catch (error) {
25966
- if (error.code !== "ENOENT") throw error;
25967
- }
25968
- pending.push(verified);
25969
- }
25970
- return pending.sort(compareBundles);
25971
- };
25972
- markRuntimeEvidenceBundleProcessed = async ({
25973
- evidenceRoot,
25974
- deploymentId,
25975
- bundleDir,
25976
- scorecardPath
25977
- }) => {
25978
- const safeDeploymentId = safeSegment2(deploymentId, "production");
25979
- const verified = await verifyRuntimeEvidenceBundle(bundleDir);
25980
- if (verified.manifest.deploymentId !== safeDeploymentId) {
25981
- throw new Error(
25982
- `Artifact deployment mismatch: expected ${safeDeploymentId}, received ${verified.manifest.deploymentId}`
25983
- );
25984
- }
25985
- const receiptsRoot = import_node_path18.default.join(evidenceRoot, "receipts", safeDeploymentId);
25986
- const finalPath = receiptPath(receiptsRoot, verified.manifest.artifactId);
25987
- const temporaryPath = `${finalPath}.tmp-${process.pid}`;
25988
- const receipt = {
25989
- schemaVersion: 1,
25990
- artifactId: verified.manifest.artifactId,
25991
- payloadSha256: verified.manifest.payload.sha256,
25992
- processedAt: Date.now(),
25993
- scorecardPath: scorecardPath ?? null
25994
- };
25995
- await import_promises24.default.mkdir(receiptsRoot, { recursive: true });
25996
- await import_promises24.default.writeFile(
25997
- temporaryPath,
25998
- `${JSON.stringify(receipt, null, 2)}
25999
- `,
26000
- "utf8"
26001
- );
26002
- await import_promises24.default.rename(temporaryPath, finalPath);
26003
- return finalPath;
26004
- };
26005
- syncRuntimeEvidenceBundles = async ({
26006
- source,
26007
- evidenceRoot,
26008
- deploymentId,
26009
- runRsync = async (args35) => {
26010
- const result = await execFileAsync("rsync", args35, {
26011
- maxBuffer: 10 * 1024 * 1024
26012
- });
26013
- return { stdout: result.stdout, stderr: result.stderr };
26014
- }
26015
- }) => {
26016
- const safeDeploymentId = safeSegment2(deploymentId, "production");
26017
- const inboxRoot = import_node_path18.default.join(evidenceRoot, "inbox", safeDeploymentId);
26018
- const artifactsRoot = import_node_path18.default.join(evidenceRoot, "artifacts", safeDeploymentId);
26019
- await Promise.all([
26020
- import_promises24.default.mkdir(inboxRoot, { recursive: true }),
26021
- import_promises24.default.mkdir(artifactsRoot, { recursive: true })
26022
- ]);
26023
- const rsyncArgs = buildRuntimeEvidenceRsyncArgs({
26024
- source,
26025
- destination: inboxRoot
26026
- });
26027
- const transfer = await runRsync(rsyncArgs);
26028
- const discovered = await discoverRuntimeEvidenceBundles(inboxRoot);
26029
- const received = [];
26030
- for (const bundleDir of discovered) {
26031
- const verified = await verifyRuntimeEvidenceBundle(bundleDir);
26032
- if (verified.manifest.deploymentId !== safeDeploymentId) {
26033
- throw new Error(
26034
- `Artifact deployment mismatch: expected ${safeDeploymentId}, received ${verified.manifest.deploymentId}`
26035
- );
26036
- }
26037
- assertCurrentRuntimeEvidenceArtifact(verified.artifact);
26038
- const destinationDir = import_node_path18.default.join(
26039
- artifactsRoot,
26040
- ...dateParts2(verified.manifest.window.endTime),
26041
- safeSegment2(verified.manifest.artifactId, "artifact")
26042
- );
26043
- await import_promises24.default.mkdir(import_node_path18.default.dirname(destinationDir), { recursive: true });
26044
- try {
26045
- await import_promises24.default.rename(bundleDir, destinationDir);
26046
- } catch (error) {
26047
- if (!isExistingDestinationError2(error)) throw error;
26048
- const existing = await verifyRuntimeEvidenceBundle(destinationDir);
26049
- if (existing.manifest.payload.sha256 !== verified.manifest.payload.sha256) {
26050
- throw new Error(
26051
- `Conflicting runtime evidence artifact ${verified.manifest.artifactId}`
26052
- );
26053
- }
26054
- await import_promises24.default.rm(bundleDir, { recursive: true, force: true });
26055
- }
26056
- received.push(await verifyRuntimeEvidenceBundle(destinationDir));
26057
- }
26058
- const pending = await listPendingRuntimeEvidenceBundles({
26059
- evidenceRoot,
26060
- deploymentId: safeDeploymentId
26061
- });
26062
- return {
26063
- rsyncArgs,
26064
- stdout: String(transfer.stdout ?? ""),
26065
- stderr: String(transfer.stderr ?? ""),
26066
- received,
26067
- pending
26068
- };
26069
- };
26884
+ main36 = runtimeEvidence;
26070
26885
  }
26071
26886
  });
26072
26887
 
26073
26888
  // src/scripts/runtimeEvidenceSync.ts
26074
26889
  var runtimeEvidenceSync_exports = {};
26075
26890
  __export(runtimeEvidenceSync_exports, {
26076
- main: () => main35,
26891
+ main: () => main37,
26077
26892
  runtimeEvidenceSync: () => runtimeEvidenceSync
26078
26893
  });
26079
- var import_node_path19, import_args27, import_chalk40, flags26, projectRoot10, runtimeEvidenceSync, main35;
26894
+ var import_node_path25, import_args29, import_chalk42, flags28, projectRoot12, runtimeEvidenceSync, main37;
26080
26895
  var init_runtimeEvidenceSync2 = __esm({
26081
26896
  "src/scripts/runtimeEvidenceSync.ts"() {
26082
26897
  "use strict";
26083
- import_node_path19 = __toESM(require("path"));
26084
- import_args27 = __toESM(require("args"));
26085
- import_chalk40 = __toESM(require("chalk"));
26898
+ import_node_path25 = __toESM(require("path"));
26899
+ import_args29 = __toESM(require("args"));
26900
+ import_chalk42 = __toESM(require("chalk"));
26086
26901
  init_runtimeEvidenceSync();
26087
- import_args27.default.option(
26902
+ import_args29.default.option(
26088
26903
  "source",
26089
26904
  "Rsync source ending at the deployment ready directory",
26090
26905
  process.env.RUNTIME_EVIDENCE_RSYNC_SOURCE
26091
26906
  );
26092
- import_args27.default.option(
26907
+ import_args29.default.option(
26093
26908
  "deployment",
26094
26909
  "Deployment id expected in artifact manifests",
26095
26910
  process.env.RUNTIME_EVIDENCE_DEPLOYMENT_ID || "production"
26096
26911
  );
26097
- import_args27.default.option(
26912
+ import_args29.default.option(
26098
26913
  "dir",
26099
26914
  "Local evidence storage root",
26100
26915
  process.env.RUNTIME_EVIDENCE_LOCAL_DIR || "data/runtime-evidence"
26101
26916
  );
26102
- flags26 = import_args27.default.parse(process.argv);
26103
- projectRoot10 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
26917
+ flags28 = import_args29.default.parse(process.argv);
26918
+ projectRoot12 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
26104
26919
  runtimeEvidenceSync = async () => {
26105
- const source = String(flags26.source ?? "").trim();
26920
+ const source = String(flags28.source ?? "").trim();
26106
26921
  if (!source) {
26107
26922
  throw new Error(
26108
26923
  "Provide --source or RUNTIME_EVIDENCE_RSYNC_SOURCE for runtime evidence sync."
26109
26924
  );
26110
26925
  }
26111
- const evidenceRoot = import_node_path19.default.resolve(projectRoot10, String(flags26.dir));
26926
+ const evidenceRoot = import_node_path25.default.resolve(projectRoot12, String(flags28.dir));
26112
26927
  const result = await syncRuntimeEvidenceBundles({
26113
26928
  source,
26114
26929
  evidenceRoot,
26115
- deploymentId: String(flags26.deployment)
26930
+ deploymentId: String(flags28.deployment)
26116
26931
  });
26117
26932
  console.log(
26118
- import_chalk40.default.green(
26933
+ import_chalk42.default.green(
26119
26934
  `Runtime evidence sync completed: received=${result.received.length} pending=${result.pending.length}`
26120
26935
  )
26121
26936
  );
@@ -26140,7 +26955,7 @@ var init_runtimeEvidenceSync2 = __esm({
26140
26955
  )
26141
26956
  );
26142
26957
  };
26143
- main35 = runtimeEvidenceSync;
26958
+ main37 = runtimeEvidenceSync;
26144
26959
  }
26145
26960
  });
26146
26961
 
@@ -27112,7 +27927,7 @@ async function collectReleaseEvidenceReferences(references) {
27112
27927
  let artifact;
27113
27928
  try {
27114
27929
  const parsed = JSON.parse(
27115
- await import_promises25.default.readFile(reference.path, "utf8")
27930
+ await import_promises29.default.readFile(reference.path, "utf8")
27116
27931
  );
27117
27932
  assert3(
27118
27933
  parsed != null && typeof parsed === "object" && !Array.isArray(parsed),
@@ -27259,13 +28074,13 @@ async function collectReleaseEvidenceReferences(references) {
27259
28074
  })
27260
28075
  );
27261
28076
  }
27262
- var import_node_crypto12, import_promises25, import_node_path20, 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, safeSegment3, compactTimestamp2, verifyFullPeriodChartArtifact, readVerifiedJsonArtifact, verifyResearchDecisionLineage, hasExactRuntimeTarget, deriveStrategyReleaseResearchDecision, canonicalStrategyReleaseJson, strategyReleaseSha256, assertFingerprint, assertLineageFingerprint, releaseReasons, deriveReleaseGates, verifyEvidenceComposition, createStrategyReleaseManifest, createStrategyReleaseEnvelope, verifyStrategyReleaseEnvelope, verifyStrategyEvidenceMarkerEnvelope, releaseMarkers, writeJsonAtomic2, publishStrategyRelease, publishStrategyLiveDiagnosis, finiteString3, finiteNumber6, finiteDirectionPolicy, uniqueStrings, incompleteEvidenceLineage, extractEvidenceLineage, verifyCompletedCoreResearchBundle;
28077
+ var import_node_crypto14, import_promises29, import_node_path26, 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, safeSegment6, compactTimestamp2, verifyFullPeriodChartArtifact, readVerifiedJsonArtifact, verifyResearchDecisionLineage, hasExactRuntimeTarget, deriveStrategyReleaseResearchDecision, canonicalStrategyReleaseJson, strategyReleaseSha256, assertFingerprint, assertLineageFingerprint, releaseReasons, deriveReleaseGates, verifyEvidenceComposition, createStrategyReleaseManifest, createStrategyReleaseEnvelope, verifyStrategyReleaseEnvelope, verifyStrategyEvidenceMarkerEnvelope, releaseMarkers, writeJsonAtomic2, publishStrategyRelease, publishStrategyLiveDiagnosis, finiteString3, finiteNumber6, finiteDirectionPolicy, uniqueStrings, incompleteEvidenceLineage, extractEvidenceLineage, verifyCompletedCoreResearchBundle;
27263
28078
  var init_strategyRelease = __esm({
27264
28079
  "src/lib/strategyRelease.ts"() {
27265
28080
  "use strict";
27266
- import_node_crypto12 = require("crypto");
27267
- import_promises25 = __toESM(require("fs/promises"));
27268
- import_node_path20 = __toESM(require("path"));
28081
+ import_node_crypto14 = require("crypto");
28082
+ import_promises29 = __toESM(require("fs/promises"));
28083
+ import_node_path26 = __toESM(require("path"));
27269
28084
  import_types9 = require("@tradejs/types");
27270
28085
  import_strategyReleaseEvidence2 = require("@tradejs/infra/strategyReleaseEvidence");
27271
28086
  init_liveDiagnosis();
@@ -27278,17 +28093,17 @@ var init_strategyRelease = __esm({
27278
28093
  REQUIRED_LONG_WINDOWS = [1095, 1460, 1825];
27279
28094
  REQUIRED_DIAGNOSTIC_TERMINAL_WINDOWS = [365, 180, 90];
27280
28095
  MIN_RECENT_DIRECTION_REPAIR_EVENTS = 20;
27281
- safeSegment3 = import_strategyReleaseEvidence2.safeStrategyEvidenceSegment;
28096
+ safeSegment6 = import_strategyReleaseEvidence2.safeStrategyEvidenceSegment;
27282
28097
  compactTimestamp2 = import_strategyReleaseEvidence2.compactStrategyEvidenceTimestamp;
27283
28098
  verifyFullPeriodChartArtifact = async (input) => {
27284
28099
  const artifact = input.chartArtifact;
27285
28100
  if (!artifact?.path || !SHA256_RE2.test(artifact.sha256)) return false;
27286
28101
  try {
27287
- const artifactPath = import_node_path20.default.resolve(artifact.path);
28102
+ const artifactPath = import_node_path26.default.resolve(artifact.path);
27288
28103
  if (await (0, import_strategyReleaseEvidence2.strategyEvidenceFileSha256)(artifactPath) !== artifact.sha256) {
27289
28104
  return false;
27290
28105
  }
27291
- const report = JSON.parse(await import_promises25.default.readFile(artifactPath, "utf8"));
28106
+ const report = JSON.parse(await import_promises29.default.readFile(artifactPath, "utf8"));
27292
28107
  return Boolean(
27293
28108
  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
27294
28109
  );
@@ -27299,11 +28114,11 @@ var init_strategyRelease = __esm({
27299
28114
  readVerifiedJsonArtifact = async (artifact) => {
27300
28115
  if (!artifact?.path || !SHA256_RE2.test(artifact.sha256)) return null;
27301
28116
  try {
27302
- const artifactPath = import_node_path20.default.resolve(artifact.path);
28117
+ const artifactPath = import_node_path26.default.resolve(artifact.path);
27303
28118
  if (await (0, import_strategyReleaseEvidence2.strategyEvidenceFileSha256)(artifactPath) !== artifact.sha256) {
27304
28119
  return null;
27305
28120
  }
27306
- return JSON.parse(await import_promises25.default.readFile(artifactPath, "utf8"));
28121
+ return JSON.parse(await import_promises29.default.readFile(artifactPath, "utf8"));
27307
28122
  } catch {
27308
28123
  return null;
27309
28124
  }
@@ -27794,7 +28609,7 @@ var init_strategyRelease = __esm({
27794
28609
  maxLossValue: input.composition.maxLossValue,
27795
28610
  ...input.composition.directionPolicy == null ? {} : { directionPolicy: input.composition.directionPolicy }
27796
28611
  };
27797
- const compositionId = `${safeSegment3(input.strategy, "strategy")}_${strategyReleaseSha256(compositionIdentity).slice(0, 16)}`;
28612
+ const compositionId = `${safeSegment6(input.strategy, "strategy")}_${strategyReleaseSha256(compositionIdentity).slice(0, 16)}`;
27798
28613
  const reasons = releaseReasons({ ...input, gates: evidenceGates });
27799
28614
  const economicFailure = reasons.some(
27800
28615
  (reason) => [
@@ -27816,16 +28631,16 @@ var init_strategyRelease = __esm({
27816
28631
  strategy: input.strategy,
27817
28632
  createdAt: input.createdAt,
27818
28633
  compositionId,
27819
- evidence: input.evidence.map(({ kind, artifactId, sha256: sha2562 }) => ({
28634
+ evidence: input.evidence.map(({ kind, artifactId, sha256: sha2564 }) => ({
27820
28635
  kind,
27821
28636
  artifactId,
27822
- sha256: sha2562
28637
+ sha256: sha2564
27823
28638
  })),
27824
28639
  verdict
27825
28640
  };
27826
28641
  return {
27827
28642
  schema: import_types9.STRATEGY_RELEASE_SCHEMA,
27828
- releaseId: `${safeSegment3(input.strategy, "strategy")}_${compactTimestamp2(input.createdAt)}_${strategyReleaseSha256(releaseIdentity).slice(0, 16)}`,
28643
+ releaseId: `${safeSegment6(input.strategy, "strategy")}_${compactTimestamp2(input.createdAt)}_${strategyReleaseSha256(releaseIdentity).slice(0, 16)}`,
27829
28644
  strategy: input.strategy,
27830
28645
  createdAt: input.createdAt,
27831
28646
  composition: { ...input.composition, compositionId },
@@ -27849,7 +28664,7 @@ var init_strategyRelease = __esm({
27849
28664
  manifest
27850
28665
  });
27851
28666
  verifyStrategyReleaseEnvelope = async (valueOrPath) => {
27852
- const value = typeof valueOrPath === "string" ? JSON.parse(await import_promises25.default.readFile(valueOrPath, "utf8")) : valueOrPath;
28667
+ const value = typeof valueOrPath === "string" ? JSON.parse(await import_promises29.default.readFile(valueOrPath, "utf8")) : valueOrPath;
27853
28668
  const envelope = value;
27854
28669
  assert3(
27855
28670
  envelope?.schema === "tradejs-strategy-release-envelope/v1",
@@ -27900,7 +28715,7 @@ var init_strategyRelease = __esm({
27900
28715
  return envelope;
27901
28716
  };
27902
28717
  verifyStrategyEvidenceMarkerEnvelope = async (valueOrPath) => {
27903
- const value = typeof valueOrPath === "string" ? JSON.parse(await import_promises25.default.readFile(valueOrPath, "utf8")) : valueOrPath;
28718
+ const value = typeof valueOrPath === "string" ? JSON.parse(await import_promises29.default.readFile(valueOrPath, "utf8")) : valueOrPath;
27904
28719
  return (0, import_strategyReleaseEvidence2.verifyStrategyEvidenceMarkerEnvelope)(value);
27905
28720
  };
27906
28721
  releaseMarkers = (manifest) => {
@@ -27962,14 +28777,14 @@ var init_strategyRelease = __esm({
27962
28777
  };
27963
28778
  writeJsonAtomic2 = async (filePath, value) => {
27964
28779
  const temporaryPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
27965
- await import_promises25.default.mkdir(import_node_path20.default.dirname(filePath), { recursive: true });
27966
- await import_promises25.default.writeFile(
28780
+ await import_promises29.default.mkdir(import_node_path26.default.dirname(filePath), { recursive: true });
28781
+ await import_promises29.default.writeFile(
27967
28782
  temporaryPath,
27968
28783
  `${canonicalStrategyReleaseJson(value)}
27969
28784
  `,
27970
28785
  "utf8"
27971
28786
  );
27972
- await import_promises25.default.rename(temporaryPath, filePath);
28787
+ await import_promises29.default.rename(temporaryPath, filePath);
27973
28788
  };
27974
28789
  publishStrategyRelease = async ({
27975
28790
  rootDir,
@@ -27986,16 +28801,16 @@ var init_strategyRelease = __esm({
27986
28801
  path: entry.path
27987
28802
  }))
27988
28803
  });
27989
- const releasePath = import_node_path20.default.join(
28804
+ const releasePath = import_node_path26.default.join(
27990
28805
  rootDir,
27991
28806
  "releases",
27992
- safeSegment3(manifest.strategy, "strategy"),
28807
+ safeSegment6(manifest.strategy, "strategy"),
27993
28808
  `${manifest.releaseId}.json`
27994
28809
  );
27995
- const markerPath = import_node_path20.default.join(
28810
+ const markerPath = import_node_path26.default.join(
27996
28811
  rootDir,
27997
28812
  "markers",
27998
- safeSegment3(manifest.strategy, "strategy"),
28813
+ safeSegment6(manifest.strategy, "strategy"),
27999
28814
  `${markerEnvelope.artifactId}.json`
28000
28815
  );
28001
28816
  await Promise.all([
@@ -28015,7 +28830,7 @@ var init_strategyRelease = __esm({
28015
28830
  composition
28016
28831
  }) => {
28017
28832
  const diagnosisSha256 = strategyReleaseSha256(diagnosis);
28018
- const diagnosisId = `${safeSegment3(diagnosis.strategy, "strategy")}_${compactTimestamp2(diagnosis.createdAt)}_${diagnosisSha256.slice(0, 16)}`;
28833
+ const diagnosisId = `${safeSegment6(diagnosis.strategy, "strategy")}_${compactTimestamp2(diagnosis.createdAt)}_${diagnosisSha256.slice(0, 16)}`;
28019
28834
  const envelope = {
28020
28835
  schema: "tradejs-strategy-live-diagnosis-envelope/v1",
28021
28836
  diagnosisId,
@@ -28072,16 +28887,16 @@ var init_strategyRelease = __esm({
28072
28887
  markers,
28073
28888
  sourceArtifacts
28074
28889
  });
28075
- const diagnosisPath = import_node_path20.default.join(
28890
+ const diagnosisPath = import_node_path26.default.join(
28076
28891
  rootDir,
28077
28892
  "diagnoses",
28078
- safeSegment3(diagnosis.strategy, "strategy"),
28893
+ safeSegment6(diagnosis.strategy, "strategy"),
28079
28894
  `${diagnosisId}.json`
28080
28895
  );
28081
- const markerPath = import_node_path20.default.join(
28896
+ const markerPath = import_node_path26.default.join(
28082
28897
  rootDir,
28083
28898
  "markers",
28084
- safeSegment3(diagnosis.strategy, "strategy"),
28899
+ safeSegment6(diagnosis.strategy, "strategy"),
28085
28900
  `${markerEnvelope.artifactId}.json`
28086
28901
  );
28087
28902
  await Promise.all([
@@ -28268,11 +29083,11 @@ var init_strategyRelease = __esm({
28268
29083
  const specSha256 = finiteString3(artifact.specSha256);
28269
29084
  assert3(researchId != null, "core result researchId is required");
28270
29085
  assert3(specSha256 != null, "core result specSha256 is required");
28271
- const researchDir = import_node_path20.default.dirname(resultPath);
28272
- const manifestPath = import_node_path20.default.join(researchDir, "manifest.json");
28273
- const specPath = import_node_path20.default.join(researchDir, "spec.json");
28274
- const manifestBytes = await import_promises25.default.readFile(manifestPath).catch(() => null);
28275
- const specBytes = await import_promises25.default.readFile(specPath).catch(() => null);
29086
+ const researchDir = import_node_path26.default.dirname(resultPath);
29087
+ const manifestPath = import_node_path26.default.join(researchDir, "manifest.json");
29088
+ const specPath = import_node_path26.default.join(researchDir, "spec.json");
29089
+ const manifestBytes = await import_promises29.default.readFile(manifestPath).catch(() => null);
29090
+ const specBytes = await import_promises29.default.readFile(specPath).catch(() => null);
28276
29091
  assert3(
28277
29092
  manifestBytes != null && specBytes != null,
28278
29093
  "core result must belong to a completed core research bundle"
@@ -28281,14 +29096,14 @@ var init_strategyRelease = __esm({
28281
29096
  const artifactHashes = manifest.artifactHashes != null && typeof manifest.artifactHashes === "object" && !Array.isArray(manifest.artifactHashes) ? manifest.artifactHashes : null;
28282
29097
  const parsedSpec = JSON.parse(specBytes.toString("utf8"));
28283
29098
  assert3(
28284
- manifest.schema === "tradejs-core-research-manifest/v1" && manifest.status === "completed" && manifest.researchId === researchId && manifest.specSha256 === specSha256 && artifactHashes?.["result.json"] === resultSha256 && (0, import_node_crypto12.createHash)("sha256").update(canonicalStrategyReleaseJson(parsedSpec)).digest("hex") === specSha256,
29099
+ manifest.schema === "tradejs-core-research-manifest/v1" && manifest.status === "completed" && manifest.researchId === researchId && manifest.specSha256 === specSha256 && artifactHashes?.["result.json"] === resultSha256 && (0, import_node_crypto14.createHash)("sha256").update(canonicalStrategyReleaseJson(parsedSpec)).digest("hex") === specSha256,
28285
29100
  "core result is not bound by its completed core research manifest"
28286
29101
  );
28287
29102
  for (const [relativePath, expectedSha256] of Object.entries(
28288
29103
  artifactHashes ?? {}
28289
29104
  )) {
28290
29105
  assert3(
28291
- !import_node_path20.default.isAbsolute(relativePath) && !relativePath.split(/[\\/]/).includes(".."),
29106
+ !import_node_path26.default.isAbsolute(relativePath) && !relativePath.split(/[\\/]/).includes(".."),
28292
29107
  `core bundle artifact ${relativePath} escapes its research directory`
28293
29108
  );
28294
29109
  assert3(
@@ -28296,7 +29111,7 @@ var init_strategyRelease = __esm({
28296
29111
  `core bundle artifact ${relativePath} has an invalid checksum`
28297
29112
  );
28298
29113
  const actualSha256 = await (0, import_strategyReleaseEvidence2.strategyEvidenceFileSha256)(
28299
- import_node_path20.default.join(researchDir, relativePath)
29114
+ import_node_path26.default.join(researchDir, relativePath)
28300
29115
  );
28301
29116
  assert3(
28302
29117
  actualSha256 === expectedSha256,
@@ -28310,88 +29125,89 @@ var init_strategyRelease = __esm({
28310
29125
  // src/scripts/runtimeScorecard.ts
28311
29126
  var runtimeScorecard_exports = {};
28312
29127
  __export(runtimeScorecard_exports, {
28313
- main: () => main36,
29128
+ main: () => main38,
28314
29129
  runtimeScorecard: () => runtimeScorecard
28315
29130
  });
28316
- var import_promises26, import_node_crypto13, import_node_path21, import_args28, import_chalk41, flags27, projectRoot11, resolveOptionalPath, readJson, assertReportType, sha256File2, loadHistoryArtifacts, runtimeScorecard, main36;
29131
+ var import_promises30, import_node_crypto15, import_node_path27, import_args30, import_chalk43, flags29, projectRoot13, resolveOptionalPath, readJson, assertReportType, sha256File2, loadHistoryArtifacts, runtimeScorecard, main38;
28317
29132
  var init_runtimeScorecard2 = __esm({
28318
29133
  "src/scripts/runtimeScorecard.ts"() {
28319
29134
  "use strict";
28320
- import_promises26 = __toESM(require("fs/promises"));
28321
- import_node_crypto13 = require("crypto");
28322
- import_node_path21 = __toESM(require("path"));
28323
- import_args28 = __toESM(require("args"));
28324
- import_chalk41 = __toESM(require("chalk"));
29135
+ import_promises30 = __toESM(require("fs/promises"));
29136
+ import_node_crypto15 = require("crypto");
29137
+ import_node_path27 = __toESM(require("path"));
29138
+ import_args30 = __toESM(require("args"));
29139
+ import_chalk43 = __toESM(require("chalk"));
28325
29140
  init_runtimeEvidenceArtifacts();
29141
+ init_runtimeFeedbackArtifacts();
28326
29142
  init_runtimeEvidenceSync();
28327
29143
  init_runtimeScorecard();
28328
29144
  init_strategyRelease();
28329
- import_args28.default.option(["u", "runtimeEvidence"], "Verified runtime evidence JSON");
28330
- import_args28.default.option(["r", "replayEvidence"], "Replay runtime evidence JSON");
28331
- import_args28.default.option(["c", "calibration"], "Execution calibration JSON");
28332
- import_args28.default.option(
29145
+ import_args30.default.option(["u", "runtimeEvidence"], "Verified runtime evidence JSON");
29146
+ import_args30.default.option(["r", "replayEvidence"], "Replay runtime evidence JSON");
29147
+ import_args30.default.option(["c", "calibration"], "Execution calibration JSON");
29148
+ import_args30.default.option(
28333
29149
  ["q", "prospectiveEvidence"],
28334
29150
  "Verified prospective raw-core/gate/regime summary JSON"
28335
29151
  );
28336
- import_args28.default.option(["s", "strategy"], "Exact strategy to isolate in the scorecard");
28337
- import_args28.default.option(
29152
+ import_args30.default.option(["s", "strategy"], "Exact strategy to isolate in the scorecard");
29153
+ import_args30.default.option(
28338
29154
  ["H", "historyDir"],
28339
29155
  "Directory containing verified evidence bundles"
28340
29156
  );
28341
- import_args28.default.option(
29157
+ import_args30.default.option(
28342
29158
  ["E", "evidenceDir"],
28343
29159
  "Local evidence storage root used for processing receipts",
28344
29160
  process.env.RUNTIME_EVIDENCE_LOCAL_DIR || "data/runtime-evidence"
28345
29161
  );
28346
- import_args28.default.option(
29162
+ import_args30.default.option(
28347
29163
  ["d", "deployment"],
28348
29164
  "Deployment id used for processing receipts",
28349
29165
  process.env.RUNTIME_EVIDENCE_DEPLOYMENT_ID || "production"
28350
29166
  );
28351
- import_args28.default.option(
29167
+ import_args30.default.option(
28352
29168
  ["M", "markProcessed"],
28353
29169
  "Write a processing receipt on success",
28354
29170
  false
28355
29171
  );
28356
- import_args28.default.option(
29172
+ import_args30.default.option(
28357
29173
  ["P", "minimumParityRatio"],
28358
29174
  "Minimum acceptable replay parity",
28359
29175
  0.95
28360
29176
  );
28361
- import_args28.default.option(
29177
+ import_args30.default.option(
28362
29178
  ["S", "maximumSlippageResidualBps"],
28363
29179
  "Maximum acceptable execution residual in bps",
28364
29180
  3
28365
29181
  );
28366
- import_args28.default.option(
29182
+ import_args30.default.option(
28367
29183
  ["T", "minimumClosedTrades"],
28368
29184
  "Minimum 7d closed trades for expectancy reactions",
28369
29185
  20
28370
29186
  );
28371
- import_args28.default.option(["X", "minimumExpectancy"], "Minimum acceptable 7d expectancy", 0);
28372
- import_args28.default.option(["o", "out"], "Output JSON path", "output/runtime-scorecard.json");
28373
- import_args28.default.option(
29187
+ import_args30.default.option(["X", "minimumExpectancy"], "Minimum acceptable 7d expectancy", 0);
29188
+ import_args30.default.option(["o", "out"], "Output JSON path", "output/runtime-scorecard.json");
29189
+ import_args30.default.option(
28374
29190
  ["m", "releaseManifest"],
28375
29191
  "Verified strategy release envelope JSON"
28376
29192
  );
28377
- import_args28.default.option(["D", "diagnosisDays"], "Equal-length release drawdown window", 7);
28378
- import_args28.default.option(
29193
+ import_args30.default.option(["D", "diagnosisDays"], "Equal-length release drawdown window", 7);
29194
+ import_args30.default.option(
28379
29195
  ["z", "strategyReleaseRoot"],
28380
29196
  "Publish advisory diagnosis and immutable chart markers under this root"
28381
29197
  );
28382
- flags27 = import_args28.default.parse(process.argv);
28383
- projectRoot11 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
29198
+ flags29 = import_args30.default.parse(process.argv);
29199
+ projectRoot13 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
28384
29200
  resolveOptionalPath = (value) => {
28385
29201
  const raw = String(value ?? "").trim();
28386
- return raw ? import_node_path21.default.resolve(projectRoot11, raw) : null;
29202
+ return raw ? import_node_path27.default.resolve(projectRoot13, raw) : null;
28387
29203
  };
28388
- readJson = async (filePath) => filePath ? JSON.parse(await import_promises26.default.readFile(filePath, "utf8")) : void 0;
29204
+ readJson = async (filePath) => filePath ? JSON.parse(await import_promises30.default.readFile(filePath, "utf8")) : void 0;
28389
29205
  assertReportType = (artifact, expected, label) => {
28390
29206
  if (artifact != null && (!artifact || typeof artifact !== "object" || Array.isArray(artifact) || artifact.reportType !== expected)) {
28391
29207
  throw new Error(`${label} must be a ${expected} artifact`);
28392
29208
  }
28393
29209
  };
28394
- sha256File2 = async (filePath) => (0, import_node_crypto13.createHash)("sha256").update(await import_promises26.default.readFile(filePath)).digest("hex");
29210
+ sha256File2 = async (filePath) => (0, import_node_crypto15.createHash)("sha256").update(await import_promises30.default.readFile(filePath)).digest("hex");
28395
29211
  loadHistoryArtifacts = async (historyDir) => {
28396
29212
  if (!historyDir) return [];
28397
29213
  const bundleDirs = await discoverRuntimeEvidenceBundles(historyDir);
@@ -28402,17 +29218,17 @@ var init_runtimeScorecard2 = __esm({
28402
29218
  return bundles.map((bundle) => bundle.artifact);
28403
29219
  };
28404
29220
  runtimeScorecard = async () => {
28405
- const runtimeEvidencePath = resolveOptionalPath(flags27.runtimeEvidence);
29221
+ const runtimeEvidencePath = resolveOptionalPath(flags29.runtimeEvidence);
28406
29222
  if (!runtimeEvidencePath) {
28407
29223
  throw new Error("Provide --runtimeEvidence for the runtime scorecard.");
28408
29224
  }
28409
- const replayEvidencePath = resolveOptionalPath(flags27.replayEvidence);
28410
- const calibrationPath = resolveOptionalPath(flags27.calibration);
29225
+ const replayEvidencePath = resolveOptionalPath(flags29.replayEvidence);
29226
+ const calibrationPath = resolveOptionalPath(flags29.calibration);
28411
29227
  const prospectiveEvidencePath = resolveOptionalPath(
28412
- flags27.prospectiveEvidence
29228
+ flags29.prospectiveEvidence
28413
29229
  );
28414
- const historyDir = resolveOptionalPath(flags27.historyDir);
28415
- const releaseManifestPath = resolveOptionalPath(flags27.releaseManifest);
29230
+ const historyDir = resolveOptionalPath(flags29.historyDir);
29231
+ const releaseManifestPath = resolveOptionalPath(flags29.releaseManifest);
28416
29232
  const [
28417
29233
  runtimeArtifact,
28418
29234
  replayEvidenceArtifact,
@@ -28439,7 +29255,7 @@ var init_runtimeScorecard2 = __esm({
28439
29255
  "prospectiveEvidence"
28440
29256
  );
28441
29257
  const verifiedRelease = releaseManifestPath ? await verifyStrategyReleaseEnvelope(releaseManifestPath) : null;
28442
- const requestedStrategy = String(flags27.strategy ?? "").trim() || null;
29258
+ const requestedStrategy = String(flags29.strategy ?? "").trim() || null;
28443
29259
  if (verifiedRelease && requestedStrategy && requestedStrategy !== verifiedRelease.manifest.strategy) {
28444
29260
  throw new Error(
28445
29261
  `Requested strategy ${requestedStrategy} does not match release ${verifiedRelease.manifest.strategy}`
@@ -28453,21 +29269,21 @@ var init_runtimeScorecard2 = __esm({
28453
29269
  prospectiveEvidenceArtifact,
28454
29270
  historyRuntimeArtifacts: history,
28455
29271
  thresholds: {
28456
- minimumParityRatio: Number(flags27.minimumParityRatio),
28457
- maximumSlippageResidualBps: Number(flags27.maximumSlippageResidualBps),
28458
- minimumClosedTrades: Number(flags27.minimumClosedTrades),
28459
- minimumExpectancy: Number(flags27.minimumExpectancy)
29272
+ minimumParityRatio: Number(flags29.minimumParityRatio),
29273
+ maximumSlippageResidualBps: Number(flags29.maximumSlippageResidualBps),
29274
+ minimumClosedTrades: Number(flags29.minimumClosedTrades),
29275
+ minimumExpectancy: Number(flags29.minimumExpectancy)
28460
29276
  },
28461
29277
  strategy: scorecardStrategy,
28462
29278
  llmComparatorPolicy: verifiedRelease?.manifest.prospective.llmComparatorPolicy ?? "ai_approved_only"
28463
29279
  });
28464
- const outPath = import_node_path21.default.resolve(projectRoot11, String(flags27.out));
29280
+ const outPath = import_node_path27.default.resolve(projectRoot13, String(flags29.out));
28465
29281
  const markdownPath = outPath.replace(/\.json$/i, "") + ".md";
28466
- await import_promises26.default.mkdir(import_node_path21.default.dirname(outPath), { recursive: true });
29282
+ await import_promises30.default.mkdir(import_node_path27.default.dirname(outPath), { recursive: true });
28467
29283
  await Promise.all([
28468
- import_promises26.default.writeFile(outPath, `${JSON.stringify(scorecard, null, 2)}
29284
+ import_promises30.default.writeFile(outPath, `${JSON.stringify(scorecard, null, 2)}
28469
29285
  `, "utf8"),
28470
- import_promises26.default.writeFile(
29286
+ import_promises30.default.writeFile(
28471
29287
  markdownPath,
28472
29288
  formatRuntimeScorecardMarkdown(scorecard),
28473
29289
  "utf8"
@@ -28476,12 +29292,12 @@ var init_runtimeScorecard2 = __esm({
28476
29292
  const diagnosis = verifiedRelease ? buildStrategyLiveDiagnosisFromScorecard({
28477
29293
  manifest: verifiedRelease.manifest,
28478
29294
  scorecard,
28479
- days: Number(flags27.diagnosisDays)
29295
+ days: Number(flags29.diagnosisDays)
28480
29296
  }) : null;
28481
29297
  const diagnosisPath = diagnosis ? outPath.replace(/\.json$/i, "") + ".diagnosis.json" : null;
28482
- const strategyReleaseRoot = resolveOptionalPath(flags27.strategyReleaseRoot);
29298
+ const strategyReleaseRoot = resolveOptionalPath(flags29.strategyReleaseRoot);
28483
29299
  if (diagnosis && diagnosisPath) {
28484
- await import_promises26.default.writeFile(
29300
+ await import_promises30.default.writeFile(
28485
29301
  diagnosisPath,
28486
29302
  `${JSON.stringify(diagnosis, null, 2)}
28487
29303
  `,
@@ -28502,7 +29318,7 @@ var init_runtimeScorecard2 = __esm({
28502
29318
  composition: verifiedRelease?.manifest.composition,
28503
29319
  sourceArtifacts: await Promise.all(
28504
29320
  sourcePaths.map(async (sourcePath) => ({
28505
- artifactId: import_node_path21.default.basename(sourcePath),
29321
+ artifactId: import_node_path27.default.basename(sourcePath),
28506
29322
  path: sourcePath,
28507
29323
  sha256: await sha256File2(sourcePath)
28508
29324
  }))
@@ -28511,16 +29327,35 @@ var init_runtimeScorecard2 = __esm({
28511
29327
  }
28512
29328
  }
28513
29329
  let receiptPath2 = null;
28514
- if (flags27.markProcessed) {
29330
+ if (flags29.markProcessed) {
29331
+ const runtimeEvidenceBundle = await verifyRuntimeEvidenceBundle(
29332
+ import_node_path27.default.dirname(runtimeEvidencePath)
29333
+ );
29334
+ const feedbackSource = replayEvidencePath ? await verifyRuntimeFeedbackReplaySource({
29335
+ bundleDir: import_node_path27.default.dirname(replayEvidencePath),
29336
+ runtimeEvidenceBundleDir: import_node_path27.default.dirname(runtimeEvidencePath)
29337
+ }).catch((error) => {
29338
+ if (runtimeEvidenceBundle.artifact.producer) throw error;
29339
+ return null;
29340
+ }) : null;
29341
+ if (runtimeEvidenceBundle.artifact.producer && !feedbackSource) {
29342
+ throw new Error(
29343
+ "Image-bound runtime evidence requires a verified production replay bundle before it can be marked processed"
29344
+ );
29345
+ }
28515
29346
  receiptPath2 = await markRuntimeEvidenceBundleProcessed({
28516
- evidenceRoot: import_node_path21.default.resolve(projectRoot11, String(flags27.evidenceDir)),
28517
- deploymentId: String(flags27.deployment),
28518
- bundleDir: import_node_path21.default.dirname(runtimeEvidencePath),
28519
- scorecardPath: outPath
29347
+ evidenceRoot: import_node_path27.default.resolve(projectRoot13, String(flags29.evidenceDir)),
29348
+ deploymentId: String(flags29.deployment),
29349
+ bundleDir: import_node_path27.default.dirname(runtimeEvidencePath),
29350
+ scorecardPath: outPath,
29351
+ runtimeFeedback: feedbackSource ? {
29352
+ artifactId: feedbackSource.feedback.manifest.artifactId,
29353
+ replayEvidenceSha256: feedbackSource.feedback.manifest.payloads.replayEvidence.sha256
29354
+ } : null
28520
29355
  });
28521
29356
  }
28522
- console.log(import_chalk41.default.green(`Wrote ${outPath}`));
28523
- console.log(import_chalk41.default.green(`Wrote ${markdownPath}`));
29357
+ console.log(import_chalk43.default.green(`Wrote ${outPath}`));
29358
+ console.log(import_chalk43.default.green(`Wrote ${markdownPath}`));
28524
29359
  console.log(
28525
29360
  JSON.stringify(
28526
29361
  {
@@ -28539,7 +29374,7 @@ var init_runtimeScorecard2 = __esm({
28539
29374
  )
28540
29375
  );
28541
29376
  };
28542
- main36 = runtimeScorecard;
29377
+ main38 = runtimeScorecard;
28543
29378
  }
28544
29379
  });
28545
29380
 
@@ -28547,10 +29382,10 @@ var init_runtimeScorecard2 = __esm({
28547
29382
  var runtimeControl_exports = {};
28548
29383
  __export(runtimeControl_exports, {
28549
29384
  RUNTIME_CONTROL_ACTIONS: () => RUNTIME_CONTROL_ACTIONS,
28550
- main: () => main37,
29385
+ main: () => main39,
28551
29386
  runtimeControl: () => runtimeControl
28552
29387
  });
28553
- var import_config9, import_runtimeControls, import_runtimeStrategies4, argv, RUNTIME_CONTROL_ACTIONS, action, option, required2, projectRoot12, userName2, verify, inspect, updateControlState, runtimeControl, main37;
29388
+ var import_config9, import_runtimeControls, import_runtimeStrategies4, argv, RUNTIME_CONTROL_ACTIONS, action, option, required2, projectRoot14, userName2, verify, inspect, updateControlState, runtimeControl, main39;
28554
29389
  var init_runtimeControl = __esm({
28555
29390
  "src/scripts/runtimeControl.ts"() {
28556
29391
  "use strict";
@@ -28574,10 +29409,10 @@ var init_runtimeControl = __esm({
28574
29409
  if (!value) throw new Error(`--${name} is required`);
28575
29410
  return value;
28576
29411
  };
28577
- projectRoot12 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
29412
+ projectRoot14 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
28578
29413
  userName2 = String(option("user") ?? process.env.USER_NAME ?? "root");
28579
29414
  verify = async () => {
28580
- const deployments = await (0, import_runtimeStrategies4.listRuntimeDeployments)({ userName: userName2, projectRoot: projectRoot12 });
29415
+ const deployments = await (0, import_runtimeStrategies4.listRuntimeDeployments)({ userName: userName2, projectRoot: projectRoot14 });
28581
29416
  const requestedDeployment = option("deployment");
28582
29417
  const selected = requestedDeployment ? deployments.filter((deployment) => deployment.id === requestedDeployment) : deployments;
28583
29418
  if (requestedDeployment && !selected.length) {
@@ -28588,7 +29423,7 @@ var init_runtimeControl = __esm({
28588
29423
  try {
28589
29424
  const strategies = await (0, import_runtimeStrategies4.loadResolvedRuntimeStrategies)({
28590
29425
  userName: userName2,
28591
- projectRoot: projectRoot12,
29426
+ projectRoot: projectRoot14,
28592
29427
  deploymentId: deployment.id
28593
29428
  });
28594
29429
  results2.push({
@@ -28621,7 +29456,7 @@ var init_runtimeControl = __esm({
28621
29456
  inspect = async () => {
28622
29457
  const requestedDeployment = option("deployment");
28623
29458
  const requestedStrategy = option("strategy");
28624
- const deployments = (await (0, import_runtimeStrategies4.listRuntimeDeployments)({ userName: userName2, projectRoot: projectRoot12 })).filter(
29459
+ const deployments = (await (0, import_runtimeStrategies4.listRuntimeDeployments)({ userName: userName2, projectRoot: projectRoot14 })).filter(
28625
29460
  (deployment) => !requestedDeployment || deployment.id === requestedDeployment
28626
29461
  ).map((deployment) => ({
28627
29462
  ...deployment,
@@ -28636,7 +29471,7 @@ var init_runtimeControl = __esm({
28636
29471
  const strategyName = required2("strategy");
28637
29472
  const deployment = await (0, import_runtimeStrategies4.getRuntimeDeployment)({
28638
29473
  userName: userName2,
28639
- projectRoot: projectRoot12,
29474
+ projectRoot: projectRoot14,
28640
29475
  deploymentId
28641
29476
  });
28642
29477
  if (!deployment) {
@@ -28666,7 +29501,7 @@ var init_runtimeControl = __esm({
28666
29501
  }
28667
29502
  const updated = await (0, import_runtimeStrategies4.getRuntimeDeployment)({
28668
29503
  userName: userName2,
28669
- projectRoot: projectRoot12,
29504
+ projectRoot: projectRoot14,
28670
29505
  deploymentId
28671
29506
  });
28672
29507
  const updatedReference = updated?.strategies.find(
@@ -28698,25 +29533,25 @@ var init_runtimeControl = __esm({
28698
29533
  `Usage: tradejs runtime-control ${RUNTIME_CONTROL_ACTIONS.join("|")}`
28699
29534
  );
28700
29535
  };
28701
- main37 = runtimeControl;
29536
+ main39 = runtimeControl;
28702
29537
  }
28703
29538
  });
28704
29539
 
28705
29540
  // src/scripts/strategyRelease.ts
28706
29541
  var strategyRelease_exports = {};
28707
29542
  __export(strategyRelease_exports, {
28708
- main: () => main38,
29543
+ main: () => main40,
28709
29544
  runStrategyReleaseCommand: () => runStrategyReleaseCommand
28710
29545
  });
28711
- var import_promises27, import_node_fs5, import_node_readline2, import_node_path22, import_chalk42, valueAfter2, required3, writeJsonAtomic3, runStrategyReleaseCommand, printUsage2, main38;
29546
+ var import_promises31, import_node_fs5, import_node_readline2, import_node_path28, import_chalk44, valueAfter2, required3, writeJsonAtomic3, runStrategyReleaseCommand, printUsage2, main40;
28712
29547
  var init_strategyRelease2 = __esm({
28713
29548
  "src/scripts/strategyRelease.ts"() {
28714
29549
  "use strict";
28715
- import_promises27 = __toESM(require("fs/promises"));
29550
+ import_promises31 = __toESM(require("fs/promises"));
28716
29551
  import_node_fs5 = require("fs");
28717
29552
  import_node_readline2 = require("readline");
28718
- import_node_path22 = __toESM(require("path"));
28719
- import_chalk42 = __toESM(require("chalk"));
29553
+ import_node_path28 = __toESM(require("path"));
29554
+ import_chalk44 = __toESM(require("chalk"));
28720
29555
  init_strategyRelease();
28721
29556
  valueAfter2 = (argv2, name) => {
28722
29557
  const index = argv2.indexOf(name);
@@ -28728,17 +29563,17 @@ var init_strategyRelease2 = __esm({
28728
29563
  };
28729
29564
  writeJsonAtomic3 = async (filePath, value) => {
28730
29565
  const temporaryPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
28731
- await import_promises27.default.mkdir(import_node_path22.default.dirname(filePath), { recursive: true });
28732
- await import_promises27.default.writeFile(
29566
+ await import_promises31.default.mkdir(import_node_path28.default.dirname(filePath), { recursive: true });
29567
+ await import_promises31.default.writeFile(
28733
29568
  temporaryPath,
28734
29569
  `${JSON.stringify(value, null, 2)}
28735
29570
  `,
28736
29571
  "utf8"
28737
29572
  );
28738
- await import_promises27.default.rename(temporaryPath, filePath);
29573
+ await import_promises31.default.rename(temporaryPath, filePath);
28739
29574
  };
28740
29575
  runStrategyReleaseCommand = async (options) => {
28741
- const inputPath = import_node_path22.default.resolve(options.inputPath);
29576
+ const inputPath = import_node_path28.default.resolve(options.inputPath);
28742
29577
  if (options.command === "verify") {
28743
29578
  const envelope = await verifyStrategyReleaseEnvelope(inputPath);
28744
29579
  return {
@@ -28776,7 +29611,7 @@ var init_strategyRelease2 = __esm({
28776
29611
  endTime,
28777
29612
  days: options.days?.length ? options.days : [7, 30, 90]
28778
29613
  });
28779
- const outputPath = import_node_path22.default.resolve(
29614
+ const outputPath = import_node_path28.default.resolve(
28780
29615
  options.outputPath ?? "output/strategy-monitoring-profile.json"
28781
29616
  );
28782
29617
  await writeJsonAtomic3(outputPath, profile);
@@ -28787,22 +29622,22 @@ var init_strategyRelease2 = __esm({
28787
29622
  profile
28788
29623
  };
28789
29624
  }
28790
- const input = JSON.parse(await import_promises27.default.readFile(inputPath, "utf8"));
29625
+ const input = JSON.parse(await import_promises31.default.readFile(inputPath, "utf8"));
28791
29626
  if (options.command === "decide") {
28792
29627
  const decision = await deriveStrategyReleaseResearchDecision(input);
28793
29628
  if (options.outputPath) {
28794
- await writeJsonAtomic3(import_node_path22.default.resolve(options.outputPath), decision);
29629
+ await writeJsonAtomic3(import_node_path28.default.resolve(options.outputPath), decision);
28795
29630
  }
28796
29631
  return {
28797
29632
  kind: "decided",
28798
29633
  ...decision,
28799
- outputPath: options.outputPath ? import_node_path22.default.resolve(options.outputPath) : null
29634
+ outputPath: options.outputPath ? import_node_path28.default.resolve(options.outputPath) : null
28800
29635
  };
28801
29636
  }
28802
29637
  if (options.command === "retention") {
28803
29638
  const plan = planStrategyEvidenceRetention(input);
28804
29639
  if (options.apply) {
28805
- await Promise.all(plan.delete.map((entry) => import_promises27.default.rm(entry.path)));
29640
+ await Promise.all(plan.delete.map((entry) => import_promises31.default.rm(entry.path)));
28806
29641
  }
28807
29642
  return {
28808
29643
  kind: "retention",
@@ -28815,12 +29650,12 @@ var init_strategyRelease2 = __esm({
28815
29650
  }
28816
29651
  if (options.command === "diagnose") {
28817
29652
  const diagnosis = buildStrategyLiveDiagnosis(input);
28818
- const outputPath = import_node_path22.default.resolve(
29653
+ const outputPath = import_node_path28.default.resolve(
28819
29654
  options.outputPath ?? "output/strategy-live-diagnosis.json"
28820
29655
  );
28821
29656
  await writeJsonAtomic3(outputPath, diagnosis);
28822
29657
  const published2 = options.rootDir ? await publishStrategyLiveDiagnosis({
28823
- rootDir: import_node_path22.default.resolve(options.rootDir),
29658
+ rootDir: import_node_path28.default.resolve(options.rootDir),
28824
29659
  diagnosis,
28825
29660
  sourceArtifacts: input.sourceArtifacts ?? []
28826
29661
  }) : null;
@@ -28837,7 +29672,7 @@ var init_strategyRelease2 = __esm({
28837
29672
  evidence: await collectReleaseEvidenceReferences(input.evidence ?? [])
28838
29673
  });
28839
29674
  const published = await publishStrategyRelease({
28840
- rootDir: import_node_path22.default.resolve(options.rootDir ?? "data/strategy-release"),
29675
+ rootDir: import_node_path28.default.resolve(options.rootDir ?? "data/strategy-release"),
28841
29676
  manifest
28842
29677
  });
28843
29678
  return {
@@ -28855,7 +29690,7 @@ var init_strategyRelease2 = __esm({
28855
29690
  yarn strategy:release profile --input <trades.jsonl> --variant <id> --startTime <ms> --endTime <ms> [--days 7,30,90] [--out <profile.json>]
28856
29691
  yarn strategy:release diagnose --input <diagnosis-input.json> [--out output/diagnosis.json]
28857
29692
  yarn strategy:release retention --input <inventory.json> [--apply]`);
28858
- main38 = async () => {
29693
+ main40 = async () => {
28859
29694
  const argv2 = process.argv.slice(2);
28860
29695
  const command = argv2[0];
28861
29696
  if (!command || ![
@@ -28881,7 +29716,7 @@ var init_strategyRelease2 = __esm({
28881
29716
  endTime: Number(valueAfter2(argv2, "--endTime")),
28882
29717
  days: valueAfter2(argv2, "--days")?.split(",").map((entry) => Number(entry.trim()))
28883
29718
  });
28884
- console.log(import_chalk42.default.green(JSON.stringify(result, null, 2)));
29719
+ console.log(import_chalk44.default.green(JSON.stringify(result, null, 2)));
28885
29720
  };
28886
29721
  }
28887
29722
  });
@@ -28894,18 +29729,18 @@ __export(serverHealth_exports, {
28894
29729
  buildServerHealthDiagnostics: () => buildServerHealthDiagnostics,
28895
29730
  collectServerHealthSnapshot: () => collectServerHealthSnapshot,
28896
29731
  evaluateServerHealth: () => evaluateServerHealth,
28897
- main: () => main39,
29732
+ main: () => main41,
28898
29733
  resolveServerHealthThresholds: () => resolveServerHealthThresholds
28899
29734
  });
28900
- var import_config10, import_node_child_process7, import_node_os3, import_node_fs6, import_args29, import_redis16, DEFAULT_STATE, DEFAULT_THRESHOLDS, escapeHtml4, formatPctValue, formatLoadPerCore, formatGiB, formatDuration2, readDiskUsage, parseMeminfoBytes, readMemorySnapshot, runDiagnosticCommand, runDiagnosticCommands, collectServerHealthSnapshot, buildHumanSummaryLines, evaluateServerHealth, shouldRecover, buildAlertMessage, buildRecoveryMessage, buildServerHealthDiagnostics, getStateKey, toFiniteNumber3, resolveServerHealthThresholds, main39;
29735
+ var import_config10, import_node_child_process9, import_node_os3, import_node_fs6, import_args31, import_redis16, DEFAULT_STATE, DEFAULT_THRESHOLDS, escapeHtml4, formatPctValue, formatLoadPerCore, formatGiB, formatDuration2, readDiskUsage, parseMeminfoBytes, readMemorySnapshot, runDiagnosticCommand, runDiagnosticCommands, collectServerHealthSnapshot, buildHumanSummaryLines, evaluateServerHealth, shouldRecover, buildAlertMessage, buildRecoveryMessage, buildServerHealthDiagnostics, getStateKey, toFiniteNumber3, resolveServerHealthThresholds, main41;
28901
29736
  var init_serverHealth = __esm({
28902
29737
  "src/scripts/serverHealth.ts"() {
28903
29738
  "use strict";
28904
29739
  import_config10 = require("dotenv/config");
28905
- import_node_child_process7 = require("child_process");
29740
+ import_node_child_process9 = require("child_process");
28906
29741
  import_node_os3 = __toESM(require("os"));
28907
29742
  import_node_fs6 = require("fs");
28908
- import_args29 = __toESM(require("args"));
29743
+ import_args31 = __toESM(require("args"));
28909
29744
  import_redis16 = require("@tradejs/infra/redis");
28910
29745
  init_telegramReports();
28911
29746
  DEFAULT_STATE = {
@@ -28939,21 +29774,21 @@ var init_serverHealth = __esm({
28939
29774
  }
28940
29775
  return `${minutes}m`;
28941
29776
  };
28942
- readDiskUsage = (path35) => {
29777
+ readDiskUsage = (path41) => {
28943
29778
  try {
28944
- const stats = (0, import_node_fs6.statfsSync)(path35);
29779
+ const stats = (0, import_node_fs6.statfsSync)(path41);
28945
29780
  const totalBlocks = Number(stats.blocks ?? 0);
28946
29781
  const availableBlocks = Number(stats.bavail ?? 0);
28947
29782
  if (totalBlocks <= 0) {
28948
- return { path: path35, usedPct: null };
29783
+ return { path: path41, usedPct: null };
28949
29784
  }
28950
29785
  const usedPct = (totalBlocks - Math.max(0, availableBlocks)) / totalBlocks * 100;
28951
29786
  return {
28952
- path: path35,
29787
+ path: path41,
28953
29788
  usedPct: Number.isFinite(usedPct) ? usedPct : null
28954
29789
  };
28955
29790
  } catch {
28956
- return { path: path35, usedPct: null };
29791
+ return { path: path41, usedPct: null };
28957
29792
  }
28958
29793
  };
28959
29794
  parseMeminfoBytes = (value) => {
@@ -29017,8 +29852,8 @@ var init_serverHealth = __esm({
29017
29852
  };
29018
29853
  }
29019
29854
  };
29020
- runDiagnosticCommand = (command, args35) => {
29021
- const output = (0, import_node_child_process7.execFileSync)(command, args35, {
29855
+ runDiagnosticCommand = (command, args37) => {
29856
+ const output = (0, import_node_child_process9.execFileSync)(command, args37, {
29022
29857
  encoding: "utf8",
29023
29858
  timeout: 5e3,
29024
29859
  maxBuffer: 1024 * 1024,
@@ -29268,57 +30103,57 @@ var init_serverHealth = __esm({
29268
30103
  diskRecoverPct: diskRecoverPct != null && diskRecoverPct > 0 ? diskRecoverPct : DEFAULT_THRESHOLDS.diskRecoverPct
29269
30104
  };
29270
30105
  };
29271
- import_args29.default.option(["u", "user"], "Use user config", "root");
29272
- import_args29.default.option(["P", "printOnly"], "Print report instead of Telegram", false);
29273
- import_args29.default.option(
30106
+ import_args31.default.option(["u", "user"], "Use user config", "root");
30107
+ import_args31.default.option(["P", "printOnly"], "Print report instead of Telegram", false);
30108
+ import_args31.default.option(
29274
30109
  ["d", "diskPath"],
29275
30110
  "Filesystem path to inspect for disk pressure",
29276
30111
  "/"
29277
30112
  );
29278
- import_args29.default.option(
30113
+ import_args31.default.option(
29279
30114
  ["c", "cooldownSec"],
29280
30115
  "Minimum seconds between repeated unhealthy reminders",
29281
30116
  900
29282
30117
  );
29283
- import_args29.default.option(
30118
+ import_args31.default.option(
29284
30119
  ["l", "loadPerCpuWarn"],
29285
30120
  "Alert when 1m load per CPU reaches this value",
29286
30121
  String(DEFAULT_THRESHOLDS.loadPerCpuWarn)
29287
30122
  );
29288
- import_args29.default.option(
30123
+ import_args31.default.option(
29289
30124
  ["L", "loadPerCpuRecover"],
29290
30125
  "Recovery threshold for 1m load per CPU",
29291
30126
  String(DEFAULT_THRESHOLDS.loadPerCpuRecover)
29292
30127
  );
29293
- import_args29.default.option(
30128
+ import_args31.default.option(
29294
30129
  ["m", "memoryWarnPct"],
29295
30130
  "Alert when memory used percent reaches this value",
29296
30131
  String(DEFAULT_THRESHOLDS.memoryWarnPct)
29297
30132
  );
29298
- import_args29.default.option(
30133
+ import_args31.default.option(
29299
30134
  ["M", "memoryRecoverPct"],
29300
30135
  "Recovery threshold for memory used percent",
29301
30136
  String(DEFAULT_THRESHOLDS.memoryRecoverPct)
29302
30137
  );
29303
- import_args29.default.option(
30138
+ import_args31.default.option(
29304
30139
  ["D", "diskWarnPct"],
29305
30140
  "Alert when disk used percent reaches this value",
29306
30141
  String(DEFAULT_THRESHOLDS.diskWarnPct)
29307
30142
  );
29308
- import_args29.default.option(
30143
+ import_args31.default.option(
29309
30144
  ["R", "diskRecoverPct"],
29310
30145
  "Recovery threshold for disk used percent",
29311
30146
  String(DEFAULT_THRESHOLDS.diskRecoverPct)
29312
30147
  );
29313
- main39 = async () => {
29314
- const flags32 = import_args29.default.parse(process.argv);
29315
- const thresholds = resolveServerHealthThresholds(flags32);
29316
- const diskPath = String(flags32.diskPath || "/");
30148
+ main41 = async () => {
30149
+ const flags34 = import_args31.default.parse(process.argv);
30150
+ const thresholds = resolveServerHealthThresholds(flags34);
30151
+ const diskPath = String(flags34.diskPath || "/");
29317
30152
  const snapshot = collectServerHealthSnapshot(diskPath);
29318
- const stateKey = getStateKey(String(flags32.user), snapshot.hostname);
30153
+ const stateKey = getStateKey(String(flags34.user), snapshot.hostname);
29319
30154
  const prevState = await (0, import_redis16.getData)(stateKey, DEFAULT_STATE) ?? DEFAULT_STATE;
29320
30155
  const evaluation = evaluateServerHealth(snapshot, thresholds);
29321
- const cooldownMs = Math.max(60, Number(flags32.cooldownSec)) * 1e3;
30156
+ const cooldownMs = Math.max(60, Number(flags34.cooldownSec)) * 1e3;
29322
30157
  const now2 = snapshot.timestamp;
29323
30158
  if (!evaluation.isHealthy) {
29324
30159
  const reminder = prevState.status === "alerting" && typeof prevState.lastAlertAt === "number" && now2 - prevState.lastAlertAt < cooldownMs ? false : prevState.status === "alerting";
@@ -29336,7 +30171,7 @@ var init_serverHealth = __esm({
29336
30171
  prevState,
29337
30172
  reminder
29338
30173
  });
29339
- if (flags32.printOnly) {
30174
+ if (flags34.printOnly) {
29340
30175
  console.log(message);
29341
30176
  console.log("");
29342
30177
  console.log(
@@ -29346,7 +30181,7 @@ var init_serverHealth = __esm({
29346
30181
  })
29347
30182
  );
29348
30183
  } else {
29349
- await sendTelegramReport(message, { userName: flags32.user });
30184
+ await sendTelegramReport(message, { userName: flags34.user });
29350
30185
  }
29351
30186
  }
29352
30187
  return;
@@ -29361,10 +30196,10 @@ var init_serverHealth = __esm({
29361
30196
  await (0, import_redis16.setData)(stateKey, nextState, { expire: 0 });
29362
30197
  if (recovered) {
29363
30198
  const message = buildRecoveryMessage({ snapshot, prevState });
29364
- if (flags32.printOnly) {
30199
+ if (flags34.printOnly) {
29365
30200
  console.log(message);
29366
30201
  } else {
29367
- await sendTelegramReport(message, { userName: flags32.user });
30202
+ await sendTelegramReport(message, { userName: flags34.user });
29368
30203
  }
29369
30204
  }
29370
30205
  };
@@ -30767,11 +31602,11 @@ var init_reportingJson = __esm({
30767
31602
  });
30768
31603
 
30769
31604
  // src/lib/runtimeParity/reportingTerminal.ts
30770
- var import_chalk43, import_time8, DETAIL_LIMIT, buildRuntimeParityTerminalReport, writeRuntimeParityTerminalReport, printRuntimeDuplicateDetails, printClassifiedBacktestOnlyDetails, printClassifiedRuntimeOnlyDetails;
31605
+ var import_chalk45, import_time8, DETAIL_LIMIT, buildRuntimeParityTerminalReport, writeRuntimeParityTerminalReport, printRuntimeDuplicateDetails, printClassifiedBacktestOnlyDetails, printClassifiedRuntimeOnlyDetails;
30771
31606
  var init_reportingTerminal = __esm({
30772
31607
  "src/lib/runtimeParity/reportingTerminal.ts"() {
30773
31608
  "use strict";
30774
- import_chalk43 = __toESM(require("chalk"));
31609
+ import_chalk45 = __toESM(require("chalk"));
30775
31610
  import_time8 = require("@tradejs/core/time");
30776
31611
  init_classification();
30777
31612
  init_reportingShared();
@@ -30780,7 +31615,7 @@ var init_reportingTerminal = __esm({
30780
31615
  const mismatchRows = buildMismatchSummaryRows(context);
30781
31616
  const strategyIssueRows = buildStrategyIssueRows(context.strategyRows);
30782
31617
  const lines = [
30783
- import_chalk43.default.cyan("TradeJS runtime parity"),
31618
+ import_chalk45.default.cyan("TradeJS runtime parity"),
30784
31619
  `Window: ${(0, import_time8.formatUnix)(context.window.start)} -> ${(0, import_time8.formatUnix)(context.window.end)} (${context.window.source})`,
30785
31620
  `Connector: ${context.connectorName}`,
30786
31621
  `Replay env: ${context.replayEnv}${context.runtimeGatesEnabled ? " (runtime AI/ML gates enabled)" : " (core/backtest gates only)"}`,
@@ -30809,7 +31644,7 @@ var init_reportingTerminal = __esm({
30809
31644
  lines.push(`Runtime evaluations: ${context.runtimeSignalEvaluationsCount}`);
30810
31645
  }
30811
31646
  if (mismatchRows.length) {
30812
- lines.push("", import_chalk43.default.yellow("Signal mismatches"));
31647
+ lines.push("", import_chalk45.default.yellow("Signal mismatches"));
30813
31648
  for (const item of mismatchRows.slice(0, context.detailLimit)) {
30814
31649
  lines.push(`- ${item.line}`);
30815
31650
  }
@@ -30819,14 +31654,14 @@ var init_reportingTerminal = __esm({
30819
31654
  }
30820
31655
  lines.push("");
30821
31656
  if (strategyIssueRows.length) {
30822
- lines.push(import_chalk43.default.cyan("Strategy issues"), ...strategyIssueRows);
31657
+ lines.push(import_chalk45.default.cyan("Strategy issues"), ...strategyIssueRows);
30823
31658
  } else if (context.strategyRows.length) {
30824
31659
  lines.push(
30825
31660
  `Strategies: clean ${context.strategyRows.length}/${context.strategyRows.length}`
30826
31661
  );
30827
31662
  }
30828
31663
  if (context.runtimeGateWarningCounts.size && !context.runtimeGatesRequested) {
30829
- lines.push("", import_chalk43.default.yellow("Warnings"));
31664
+ lines.push("", import_chalk45.default.yellow("Warnings"));
30830
31665
  for (const [strategy, count] of [
30831
31666
  ...context.runtimeGateWarningCounts.entries()
30832
31667
  ].sort(([left], [right]) => left.localeCompare(right))) {
@@ -30836,7 +31671,7 @@ var init_reportingTerminal = __esm({
30836
31671
  }
30837
31672
  }
30838
31673
  if (context.replayErrors.length) {
30839
- lines.push("", import_chalk43.default.red("Replay errors"));
31674
+ lines.push("", import_chalk45.default.red("Replay errors"));
30840
31675
  for (const error of context.replayErrors.slice(0, context.detailLimit)) {
30841
31676
  lines.push(`- ${error.strategy} ${error.symbol}: ${error.message}`);
30842
31677
  }
@@ -30854,7 +31689,7 @@ var init_reportingTerminal = __esm({
30854
31689
  printRuntimeDuplicateDetails = (groups) => {
30855
31690
  if (!groups.length) return;
30856
31691
  console.log("");
30857
- console.log(import_chalk43.default.yellow("Runtime duplicates"));
31692
+ console.log(import_chalk45.default.yellow("Runtime duplicates"));
30858
31693
  for (const group of groups.slice(0, DETAIL_LIMIT)) {
30859
31694
  const ids = group.entries.map((entry) => entry.orderId ?? entry.id);
30860
31695
  console.log(
@@ -30868,7 +31703,7 @@ var init_reportingTerminal = __esm({
30868
31703
  printClassifiedBacktestOnlyDetails = (classifiedEntries) => {
30869
31704
  if (!classifiedEntries.length) return;
30870
31705
  console.log("");
30871
- console.log(import_chalk43.default.yellow("Backtest only"));
31706
+ console.log(import_chalk45.default.yellow("Backtest only"));
30872
31707
  for (const item of classifiedEntries.slice(0, DETAIL_LIMIT)) {
30873
31708
  const evidenceSuffix = item.signal ? ` signalId=${item.signal.signalId} signalDrift=${formatMinutes2(item.signalTimestampDiffMs ?? null)}` : item.evaluation ? ` evaluationId=${item.evaluation.evaluationId} evaluationDrift=${formatMinutes2(item.evaluationTimestampDiffMs ?? null)}` : "";
30874
31709
  const price = item.entry.price == null ? "n/a" : item.entry.price.toFixed(6);
@@ -30883,7 +31718,7 @@ var init_reportingTerminal = __esm({
30883
31718
  printClassifiedRuntimeOnlyDetails = (classifiedEntries) => {
30884
31719
  if (!classifiedEntries.length) return;
30885
31720
  console.log("");
30886
- console.log(import_chalk43.default.yellow("Runtime only"));
31721
+ console.log(import_chalk45.default.yellow("Runtime only"));
30887
31722
  for (const item of classifiedEntries.slice(0, DETAIL_LIMIT)) {
30888
31723
  const evidenceSuffix = item.nearestBacktestEntry ? ` nearestBacktestId=${item.nearestBacktestEntry.id} backtestDrift=${formatMinutes2(item.nearestBacktestEntryTimestampDiffMs ?? null)}` : item.evaluation ? ` replayEvaluationId=${item.evaluation.evaluationId} replayDrift=${formatMinutes2(item.evaluationTimestampDiffMs ?? null)} status=${item.evaluation.status}` : "";
30889
31724
  const price = item.entry.price == null ? "n/a" : item.entry.price.toFixed(6);
@@ -31058,17 +31893,17 @@ var init_reporting = __esm({
31058
31893
  var runtimeParity_exports = {};
31059
31894
  __export(runtimeParity_exports, {
31060
31895
  buildRuntimeParityMessage: () => buildRuntimeParityMessage,
31061
- main: () => main40,
31896
+ main: () => main42,
31062
31897
  runtimeParity: () => runtimeParity
31063
31898
  });
31064
- var import_config11, import_node_crypto14, import_args30, import_chalk44, import_constants15, import_time9, import_logger6, import_redis17, import_cli11, import_backtest3, import_connectors14, flags28, interval3, projectRoot13, DEFAULT_LOOKBACK_DAYS, DETAIL_LIMIT2, DEFAULT_REPLAY_ENV, resolveParityConnectorName, createConnector, buildReplayAiAnalyses, formatReplayEnvSummary, buildReplayConfig, warmReplayHistory, runtimeParity, main40;
31899
+ var import_config11, import_node_crypto16, import_args32, import_chalk46, import_constants15, import_time9, import_logger6, import_redis17, import_cli11, import_backtest3, import_connectors14, flags30, interval3, projectRoot15, DEFAULT_LOOKBACK_DAYS, DETAIL_LIMIT2, DEFAULT_REPLAY_ENV, resolveParityConnectorName, createConnector, buildReplayAiAnalyses, formatReplayEnvSummary, buildReplayConfig, warmReplayHistory, runtimeParity, main42;
31065
31900
  var init_runtimeParity2 = __esm({
31066
31901
  "src/scripts/runtimeParity.ts"() {
31067
31902
  "use strict";
31068
31903
  import_config11 = require("dotenv/config");
31069
- import_node_crypto14 = require("crypto");
31070
- import_args30 = __toESM(require("args"));
31071
- import_chalk44 = __toESM(require("chalk"));
31904
+ import_node_crypto16 = require("crypto");
31905
+ import_args32 = __toESM(require("args"));
31906
+ import_chalk46 = __toESM(require("chalk"));
31072
31907
  import_constants15 = require("@tradejs/core/constants");
31073
31908
  import_time9 = require("@tradejs/core/time");
31074
31909
  import_logger6 = require("@tradejs/infra/logger");
@@ -31091,45 +31926,45 @@ var init_runtimeParity2 = __esm({
31091
31926
  init_reporting();
31092
31927
  init_reporting();
31093
31928
  init_runtimeModeConfig();
31094
- import_args30.default.option(["u", "user"], "Use user config", "root");
31095
- import_args30.default.option(
31929
+ import_args32.default.option(["u", "user"], "Use user config", "root");
31930
+ import_args32.default.option(
31096
31931
  ["o", "connector"],
31097
31932
  "Connector provider or name for parity replay (e.g. bybit, binance, coinbase, custom)",
31098
31933
  "bybit"
31099
31934
  );
31100
- import_args30.default.option(["d", "days"], "Replay window in days", 3);
31101
- import_args30.default.option(
31935
+ import_args32.default.option(["d", "days"], "Replay window in days", 3);
31936
+ import_args32.default.option(
31102
31937
  ["b", "startTime"],
31103
31938
  "Explicit replay start timestamp (ms or seconds)"
31104
31939
  );
31105
- import_args30.default.option(["e", "endTime"], "Explicit replay end timestamp (ms or seconds)");
31106
- import_args30.default.option(["s", "strategy"], "Only compare one strategy");
31107
- import_args30.default.option(
31940
+ import_args32.default.option(["e", "endTime"], "Explicit replay end timestamp (ms or seconds)");
31941
+ import_args32.default.option(["s", "strategy"], "Only compare one strategy");
31942
+ import_args32.default.option(
31108
31943
  ["t", "tickers"],
31109
31944
  "Replay comma-separated symbols for all configured strategies"
31110
31945
  );
31111
- import_args30.default.option(
31946
+ import_args32.default.option(
31112
31947
  ["C", "cacheOnly"],
31113
31948
  "Do not refresh market history before replay",
31114
31949
  false
31115
31950
  );
31116
- import_args30.default.option(
31951
+ import_args32.default.option(
31117
31952
  ["a", "toleranceBars"],
31118
31953
  "Allowed entry timestamp drift in bars when matching runtime vs backtest",
31119
31954
  1
31120
31955
  );
31121
- import_args30.default.option(
31956
+ import_args32.default.option(
31122
31957
  "fullUniverse",
31123
31958
  "Replay every configured strategy across the full connector universe. By default parity replays only runtime-traded and strategy-results symbols unless --tickers is provided.",
31124
31959
  false
31125
31960
  );
31126
- import_args30.default.option(
31961
+ import_args32.default.option(
31127
31962
  "runtimeGates",
31128
31963
  "Force runtime AI/ML gates for all replay targets. Runtime-gated configs are replayed with gates by default.",
31129
31964
  false
31130
31965
  );
31131
- import_args30.default.option(["N", "notify"], "Send parity summary to Telegram", false);
31132
- import_args30.default.option(["D", "details"], "Print unmatched entry details (capped)", false);
31966
+ import_args32.default.option(["N", "notify"], "Send parity summary to Telegram", false);
31967
+ import_args32.default.option(["D", "details"], "Print unmatched entry details (capped)", false);
31133
31968
  process.argv = normalizeCliArgv(process.argv, {
31134
31969
  "-C": "--cacheOnly",
31135
31970
  "-D": "--details",
@@ -31138,14 +31973,14 @@ var init_runtimeParity2 = __esm({
31138
31973
  "-S": "--startTime",
31139
31974
  "-T": "--toleranceBars"
31140
31975
  });
31141
- flags28 = import_args30.default.parse(process.argv);
31976
+ flags30 = import_args32.default.parse(process.argv);
31142
31977
  interval3 = "15";
31143
- projectRoot13 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
31978
+ projectRoot15 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
31144
31979
  DEFAULT_LOOKBACK_DAYS = 3;
31145
31980
  DETAIL_LIMIT2 = 10;
31146
- DEFAULT_REPLAY_ENV = flags28.runtimeGates ? "PARITY" : "BACKTEST";
31981
+ DEFAULT_REPLAY_ENV = flags30.runtimeGates ? "PARITY" : "BACKTEST";
31147
31982
  resolveParityConnectorName = async (value) => {
31148
- const connectorName = await (0, import_connectors14.resolveConnectorName)(value, projectRoot13);
31983
+ const connectorName = await (0, import_connectors14.resolveConnectorName)(value, projectRoot15);
31149
31984
  if (connectorName) {
31150
31985
  return connectorName;
31151
31986
  }
@@ -31162,7 +31997,7 @@ var init_runtimeParity2 = __esm({
31162
31997
  }) => {
31163
31998
  const connectorFactory = await (0, import_connectors14.getConnectorCreatorByName)(
31164
31999
  connectorName,
31165
- projectRoot13
32000
+ projectRoot15
31166
32001
  );
31167
32002
  if (!connectorFactory) {
31168
32003
  throw new Error(`Connector "${connectorName}" is not registered`);
@@ -31254,7 +32089,7 @@ var init_runtimeParity2 = __esm({
31254
32089
  strategyConfig,
31255
32090
  env: resolveReplayStrategyEnv({
31256
32091
  strategyConfig,
31257
- forceRuntimeGates: Boolean(flags28.runtimeGates)
32092
+ forceRuntimeGates: Boolean(flags30.runtimeGates)
31258
32093
  }),
31259
32094
  interval: interval3,
31260
32095
  makeOrders: true,
@@ -31273,7 +32108,7 @@ var init_runtimeParity2 = __esm({
31273
32108
  const symbols = [...new Set(targets.map((target) => target.symbol))];
31274
32109
  const warmStartedAt = Date.now();
31275
32110
  console.log(
31276
- import_chalk44.default.gray(
32111
+ import_chalk46.default.gray(
31277
32112
  `Warm history: ${symbols.length} symbol(s) on ${connectorName}, preload ${(0, import_time9.formatUnix)(preloadStart)} -> ${(0, import_time9.formatUnix)(preloadEnd)}`
31278
32113
  )
31279
32114
  );
@@ -31281,7 +32116,7 @@ var init_runtimeParity2 = __esm({
31281
32116
  connectorName,
31282
32117
  marketConnector: connector,
31283
32118
  userName: userName3,
31284
- projectRoot: projectRoot13,
32119
+ projectRoot: projectRoot15,
31285
32120
  shouldUseDedicatedReferences: true,
31286
32121
  warn: (message) => import_logger6.logger.warn(message)
31287
32122
  });
@@ -31293,39 +32128,39 @@ var init_runtimeParity2 = __esm({
31293
32128
  symbols,
31294
32129
  preloadStart,
31295
32130
  preloadEnd,
31296
- log: (message) => console.log(import_chalk44.default.gray(message))
32131
+ log: (message) => console.log(import_chalk46.default.gray(message))
31297
32132
  });
31298
32133
  console.log(
31299
- import_chalk44.default.gray(`Warm history: done in ${formatDuration(warmStartedAt)}`)
32134
+ import_chalk46.default.gray(`Warm history: done in ${formatDuration(warmStartedAt)}`)
31300
32135
  );
31301
32136
  };
31302
32137
  runtimeParity = async () => {
31303
32138
  const window = resolveTimeWindow({
31304
- days: flags28.days ?? DEFAULT_LOOKBACK_DAYS,
31305
- startTime: flags28.startTime,
31306
- endTime: flags28.endTime,
32139
+ days: flags30.days ?? DEFAULT_LOOKBACK_DAYS,
32140
+ startTime: flags30.startTime,
32141
+ endTime: flags30.endTime,
31307
32142
  defaultStartMs: Date.now() - DEFAULT_LOOKBACK_DAYS * 24 * 60 * 60 * 1e3,
31308
32143
  defaultEndMs: Date.now()
31309
32144
  });
31310
32145
  const toleranceBars = Math.max(
31311
32146
  0,
31312
- Number.parseInt(String(flags28.toleranceBars ?? 1), 10) || 0
32147
+ Number.parseInt(String(flags30.toleranceBars ?? 1), 10) || 0
31313
32148
  );
31314
32149
  const toleranceMs = toleranceBars * 15 * 60 * 1e3;
31315
- const connectorName = await resolveParityConnectorName(flags28.connector);
31316
- const requestedSymbols = parseSymbolsFromCLI2(String(flags28.tickers || ""));
32150
+ const connectorName = await resolveParityConnectorName(flags30.connector);
32151
+ const requestedSymbols = parseSymbolsFromCLI2(String(flags30.tickers || ""));
31317
32152
  const requestedSymbolSet = requestedSymbols.length ? new Set(requestedSymbols) : null;
31318
32153
  let replayErrors = [];
31319
32154
  try {
31320
32155
  const parityConnector = await createConnector({
31321
- userName: flags28.user,
32156
+ userName: flags30.user,
31322
32157
  connectorName
31323
32158
  });
31324
32159
  const { runtimeTrades, runtimeSignals, runtimeSignalEvaluations } = await loadRuntimeParityEvidence(
31325
32160
  {
31326
- userName: flags28.user,
32161
+ userName: flags30.user,
31327
32162
  window,
31328
- strategy: flags28.strategy,
32163
+ strategy: flags30.strategy,
31329
32164
  symbols: requestedSymbolSet
31330
32165
  },
31331
32166
  {
@@ -31340,29 +32175,29 @@ var init_runtimeParity2 = __esm({
31340
32175
  runtimeSignalEvaluations
31341
32176
  });
31342
32177
  const replayTargets = await buildReplayTargets({
31343
- userName: flags28.user,
32178
+ userName: flags30.user,
31344
32179
  runtimeTrades,
31345
32180
  connectorSymbols,
31346
- strategyFilter: String(flags28.strategy || "").trim() || void 0,
32181
+ strategyFilter: String(flags30.strategy || "").trim() || void 0,
31347
32182
  explicitSymbols: requestedSymbols,
31348
- includeConnectorUniverse: Boolean(flags28.fullUniverse)
32183
+ includeConnectorUniverse: Boolean(flags30.fullUniverse)
31349
32184
  });
31350
32185
  if (!replayTargets.length) {
31351
32186
  console.log(
31352
- import_chalk44.default.yellow(
31353
- `No replay targets found for ${flags28.user} in ${(0, import_time9.formatUnix)(window.start)} -> ${(0, import_time9.formatUnix)(window.end)}.`
32187
+ import_chalk46.default.yellow(
32188
+ `No replay targets found for ${flags30.user} in ${(0, import_time9.formatUnix)(window.start)} -> ${(0, import_time9.formatUnix)(window.end)}.`
31354
32189
  )
31355
32190
  );
31356
- if (flags28.notify) {
32191
+ if (flags30.notify) {
31357
32192
  await sendTelegramReport(
31358
32193
  buildRuntimeParityNoTargetsMessage({
31359
32194
  window,
31360
32195
  connectorName,
31361
32196
  replayEnv: DEFAULT_REPLAY_ENV,
31362
- runtimeGatesEnabled: Boolean(flags28.runtimeGates),
31363
- userName: String(flags28.user)
32197
+ runtimeGatesEnabled: Boolean(flags30.runtimeGates),
32198
+ userName: String(flags30.user)
31364
32199
  }),
31365
- { userName: flags28.user }
32200
+ { userName: flags30.user }
31366
32201
  );
31367
32202
  }
31368
32203
  return;
@@ -31377,14 +32212,14 @@ var init_runtimeParity2 = __esm({
31377
32212
  replayTargets.map((target) => target.symbol)
31378
32213
  ).size;
31379
32214
  console.log(
31380
- import_chalk44.default.gray(
31381
- `Replay queue: ${replayTargets.length} target(s), ${replaySymbolsCount} symbol(s), mode=${flags28.fullUniverse ? "full-universe" : requestedSymbols.length ? "explicit-tickers" : "runtime+results"}`
32215
+ import_chalk46.default.gray(
32216
+ `Replay queue: ${replayTargets.length} target(s), ${replaySymbolsCount} symbol(s), mode=${flags30.fullUniverse ? "full-universe" : requestedSymbols.length ? "explicit-tickers" : "runtime+results"}`
31382
32217
  )
31383
32218
  );
31384
32219
  const replayConfigs = /* @__PURE__ */ new Map();
31385
32220
  for (const target of replayTargets) {
31386
32221
  const replayConfig = await buildReplayConfig({
31387
- userName: flags28.user,
32222
+ userName: flags30.user,
31388
32223
  strategy: target.strategy,
31389
32224
  symbol: target.symbol,
31390
32225
  replayInputsIndex,
@@ -31401,22 +32236,22 @@ var init_runtimeParity2 = __esm({
31401
32236
  );
31402
32237
  await prepareMarketContextForRun({
31403
32238
  mode: "parity",
31404
- userName: flags28.user,
31405
- projectRoot: projectRoot13,
32239
+ userName: flags30.user,
32240
+ projectRoot: projectRoot15,
31406
32241
  symbols: replayTargets.map((target) => target.symbol),
31407
32242
  interval: interval3,
31408
32243
  startMs: window.start,
31409
32244
  endMs: window.end,
31410
32245
  preloadStartMs: preloadStart,
31411
- cacheOnly: Boolean(flags28.cacheOnly),
32246
+ cacheOnly: Boolean(flags30.cacheOnly),
31412
32247
  aiEnabled: hasParityAiTargets,
31413
32248
  mlEnabled: hasParityMlTargets,
31414
32249
  strategyNames: replayTargets.map((target) => target.strategy),
31415
- log: (message) => console.log(import_chalk44.default.gray(message))
32250
+ log: (message) => console.log(import_chalk46.default.gray(message))
31416
32251
  });
31417
- if (!flags28.cacheOnly) {
32252
+ if (!flags30.cacheOnly) {
31418
32253
  await warmReplayHistory({
31419
- userName: flags28.user,
32254
+ userName: flags30.user,
31420
32255
  connectorName,
31421
32256
  targets: replayTargets,
31422
32257
  preloadStart,
@@ -31443,15 +32278,15 @@ var init_runtimeParity2 = __esm({
31443
32278
  );
31444
32279
  }
31445
32280
  const result = await (0, import_backtest3.testing)({
31446
- userName: flags28.user,
32281
+ userName: flags30.user,
31447
32282
  symbol: target.symbol,
31448
32283
  options: {
31449
32284
  start: window.start,
31450
32285
  end: window.end
31451
32286
  },
31452
- name: `${target.symbol}_${target.strategy}_${(0, import_node_crypto14.randomUUID)().slice(0, 8)}`,
31453
- testId: (0, import_node_crypto14.randomUUID)().slice(0, 8),
31454
- testSuiteId: (0, import_node_crypto14.randomUUID)().slice(0, 8),
32287
+ name: `${target.symbol}_${target.strategy}_${(0, import_node_crypto16.randomUUID)().slice(0, 8)}`,
32288
+ testId: (0, import_node_crypto16.randomUUID)().slice(0, 8),
32289
+ testSuiteId: (0, import_node_crypto16.randomUUID)().slice(0, 8),
31455
32290
  strategyName: target.strategy,
31456
32291
  strategyConfig: replayConfig,
31457
32292
  connectorName,
@@ -31472,15 +32307,15 @@ var init_runtimeParity2 = __esm({
31472
32307
  });
31473
32308
  } finally {
31474
32309
  (0, import_backtest3.releaseTestingSymbolCache)({
31475
- cwd: projectRoot13,
31476
- userName: flags28.user,
32310
+ cwd: projectRoot15,
32311
+ userName: flags30.user,
31477
32312
  connectorName,
31478
32313
  symbol: target.symbol
31479
32314
  });
31480
32315
  }
31481
32316
  if (progressPosition === 1 || progressPosition === replayTargets.length || progressPosition % 25 === 0) {
31482
32317
  console.log(
31483
- import_chalk44.default.gray(
32318
+ import_chalk46.default.gray(
31484
32319
  `Replay progress: ${progressPosition}/${replayTargets.length}, ok=${successfulTargetKeys.size}, errors=${replayErrors.length}, current=${target.strategy} ${target.symbol}, elapsed=${formatDuration(replayStartedAt)}`
31485
32320
  )
31486
32321
  );
@@ -31511,8 +32346,8 @@ var init_runtimeParity2 = __esm({
31511
32346
  window,
31512
32347
  connectorName,
31513
32348
  replayEnv: replayEnvSummary,
31514
- runtimeGatesEnabled: Boolean(flags28.runtimeGates) || replayEnvSummary.includes("PARITY"),
31515
- runtimeGatesRequested: Boolean(flags28.runtimeGates),
32349
+ runtimeGatesEnabled: Boolean(flags30.runtimeGates) || replayEnvSummary.includes("PARITY"),
32350
+ runtimeGatesRequested: Boolean(flags30.runtimeGates),
31516
32351
  toleranceBars,
31517
32352
  toleranceMs,
31518
32353
  replayTargetsCount: replayTargets.length,
@@ -31535,12 +32370,12 @@ var init_runtimeParity2 = __esm({
31535
32370
  detailLimit: DETAIL_LIMIT2
31536
32371
  })
31537
32372
  );
31538
- if (flags28.details) {
32373
+ if (flags30.details) {
31539
32374
  printRuntimeDuplicateDetails(runtimeDedupe.duplicateGroups);
31540
32375
  printClassifiedRuntimeOnlyDetails(classifiedRuntimeOnly);
31541
32376
  printClassifiedBacktestOnlyDetails(classifiedBacktestOnly);
31542
32377
  }
31543
- if (flags28.notify) {
32378
+ if (flags30.notify) {
31544
32379
  const mismatchAttachment = buildRuntimeParityMismatchAttachment({
31545
32380
  window,
31546
32381
  connectorName,
@@ -31569,7 +32404,7 @@ var init_runtimeParity2 = __esm({
31569
32404
  window,
31570
32405
  connectorName,
31571
32406
  replayEnv: replayEnvSummary,
31572
- runtimeGatesEnabled: Boolean(flags28.runtimeGates) || replayEnvSummary.includes("PARITY"),
32407
+ runtimeGatesEnabled: Boolean(flags30.runtimeGates) || replayEnvSummary.includes("PARITY"),
31573
32408
  toleranceBars,
31574
32409
  toleranceMs,
31575
32410
  replayTargetsCount: replayTargets.length,
@@ -31591,16 +32426,16 @@ var init_runtimeParity2 = __esm({
31591
32426
  runtimeGateWarningCounts
31592
32427
  }),
31593
32428
  {
31594
- userName: flags28.user,
32429
+ userName: flags30.user,
31595
32430
  attachments: mismatchAttachment ? [mismatchAttachment] : void 0
31596
32431
  }
31597
32432
  );
31598
32433
  }
31599
32434
  } finally {
31600
- (0, import_backtest3.resetTestingKlineCache)(projectRoot13);
32435
+ (0, import_backtest3.resetTestingKlineCache)(projectRoot15);
31601
32436
  }
31602
32437
  };
31603
- main40 = runtimeParity;
32438
+ main42 = runtimeParity;
31604
32439
  }
31605
32440
  });
31606
32441
 
@@ -31679,11 +32514,11 @@ var init_runtimeStrategies = __esm({
31679
32514
  });
31680
32515
 
31681
32516
  // src/lib/signals/skipStats.ts
31682
- var import_chalk45, import_logger7, createStrategySkipStats, recordStrategyReason, logStrategySkipStats;
32517
+ var import_chalk47, import_logger7, createStrategySkipStats, recordStrategyReason, logStrategySkipStats;
31683
32518
  var init_skipStats = __esm({
31684
32519
  "src/lib/signals/skipStats.ts"() {
31685
32520
  "use strict";
31686
- import_chalk45 = __toESM(require("chalk"));
32521
+ import_chalk47 = __toESM(require("chalk"));
31687
32522
  import_logger7 = require("@tradejs/infra/logger");
31688
32523
  init_runtimeSignalsStorage();
31689
32524
  createStrategySkipStats = (runtimeStrategies) => new Map(
@@ -31709,7 +32544,7 @@ var init_skipStats = __esm({
31709
32544
  );
31710
32545
  };
31711
32546
  logStrategySkipStats = (runtimeStrategies, strategyStats) => {
31712
- import_logger7.logger.info(import_chalk45.default.yellow("skip stats:"));
32547
+ import_logger7.logger.info(import_chalk47.default.yellow("skip stats:"));
31713
32548
  for (const { strategyName } of runtimeStrategies) {
31714
32549
  const stats = strategyStats.get(strategyName);
31715
32550
  if (!stats) {
@@ -32654,12 +33489,12 @@ var init_configuredScopes = __esm({
32654
33489
  });
32655
33490
 
32656
33491
  // src/lib/signals/runner.ts
32657
- var import_progress11, import_chalk46, import_connectors16, import_cli12, import_async5, import_strategies11, import_constants16, import_time10, import_logger10, import_runtimeHeartbeats, import_runtimeStrategies6, SLOW_SIGNALS_WARNING_MS, formatDuration3, resolvePositiveInteger2, resolveNonNegativeInteger, createSignalsRunner;
33492
+ var import_progress11, import_chalk48, import_connectors16, import_cli12, import_async5, import_strategies11, import_constants16, import_time10, import_logger10, import_runtimeHeartbeats, import_runtimeStrategies6, SLOW_SIGNALS_WARNING_MS, formatDuration3, resolvePositiveInteger2, resolveNonNegativeInteger, createSignalsRunner;
32658
33493
  var init_runner = __esm({
32659
33494
  "src/lib/signals/runner.ts"() {
32660
33495
  "use strict";
32661
33496
  import_progress11 = __toESM(require("progress"));
32662
- import_chalk46 = __toESM(require("chalk"));
33497
+ import_chalk48 = __toESM(require("chalk"));
32663
33498
  import_connectors16 = require("@tradejs/node/connectors");
32664
33499
  import_cli12 = require("@tradejs/node/cli");
32665
33500
  import_async5 = require("@tradejs/core/async");
@@ -32703,7 +33538,7 @@ var init_runner = __esm({
32703
33538
  };
32704
33539
  createSignalsRunner = (config2) => {
32705
33540
  const interval4 = config2.interval;
32706
- const projectRoot15 = config2.projectRoot?.trim() || String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
33541
+ const projectRoot17 = config2.projectRoot?.trim() || String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
32707
33542
  const resolveSignalsDaemonMaxLiveBars = (runtimeInterval = interval4) => {
32708
33543
  const intervalMinutes = Number(runtimeInterval);
32709
33544
  const preloadBars = Math.ceil(
@@ -32726,7 +33561,7 @@ var init_runner = __esm({
32726
33561
  const timeOperation3 = (label, operation) => timeOperation(
32727
33562
  label,
32728
33563
  operation,
32729
- (message) => import_logger10.logger.info(import_chalk46.default.gray(message))
33564
+ (message) => import_logger10.logger.info(import_chalk48.default.gray(message))
32730
33565
  );
32731
33566
  const formatSlowSignalsWarning = (params) => [
32732
33567
  "<b>Slow yarn signals run</b>",
@@ -32736,7 +33571,7 @@ var init_runner = __esm({
32736
33571
  `Found signals: <b>${params.found}</b>`
32737
33572
  ].join("\n");
32738
33573
  const resolveSignalsConnectorName = async (value) => {
32739
- const connectorName = await (0, import_connectors16.resolveConnectorName)(value, projectRoot15);
33574
+ const connectorName = await (0, import_connectors16.resolveConnectorName)(value, projectRoot17);
32740
33575
  if (!connectorName) {
32741
33576
  throw new Error(
32742
33577
  `Unknown runtime connector: ${String(value || "").trim() || String(value)}`
@@ -32747,7 +33582,7 @@ var init_runner = __esm({
32747
33582
  const createSignalsSession2 = async (lifecycle, scope = {}) => {
32748
33583
  const deployment = config2.deploymentId ? await (0, import_runtimeStrategies6.getRuntimeDeployment)({
32749
33584
  userName: config2.userName,
32750
- projectRoot: projectRoot15,
33585
+ projectRoot: projectRoot17,
32751
33586
  deploymentId: config2.deploymentId
32752
33587
  }) : null;
32753
33588
  if (config2.deploymentId && !deployment) {
@@ -32766,7 +33601,7 @@ var init_runner = __esm({
32766
33601
  const requestedAccountId = deployment?.accountId ?? scope.accountId ?? config2.accountId;
32767
33602
  const connectorFactory = await (0, import_connectors16.getConnectorCreatorByName)(
32768
33603
  connectorName,
32769
- projectRoot15
33604
+ projectRoot17
32770
33605
  );
32771
33606
  if (!connectorFactory) {
32772
33607
  throw new Error(`Connector "${connectorName}" is not registered`);
@@ -32781,7 +33616,7 @@ var init_runner = __esm({
32781
33616
  connectorName,
32782
33617
  marketConnector,
32783
33618
  userName: config2.userName,
32784
- projectRoot: projectRoot15,
33619
+ projectRoot: projectRoot17,
32785
33620
  shouldUseDedicatedReferences: universe === "crypto" && connectorName.toLowerCase() === import_connectors16.DEFAULT_CONNECTOR_NAME.toLowerCase(),
32786
33621
  warn: (message) => import_logger10.logger.warn(message)
32787
33622
  });
@@ -32841,7 +33676,7 @@ var init_runner = __esm({
32841
33676
  const selectedTickers = selection?.tickers ? [.../* @__PURE__ */ new Set([...selection.tickers, ...selectedActiveSymbols])] : void 0;
32842
33677
  if (selectedActiveSymbols.length) {
32843
33678
  import_logger10.logger.info(
32844
- import_chalk46.default.gray(
33679
+ import_chalk48.default.gray(
32845
33680
  `strategy selection retained active symbols: ${selectedActiveSymbols.join(", ")}`
32846
33681
  )
32847
33682
  );
@@ -32871,10 +33706,10 @@ var init_runner = __esm({
32871
33706
  instruments.map((instrument) => [instrument.symbol, instrument])
32872
33707
  );
32873
33708
  if (config2.showTickersList) {
32874
- console.log(import_chalk46.default.gray(JSON.stringify(tickers.sort(), null, 2)));
33709
+ console.log(import_chalk48.default.gray(JSON.stringify(tickers.sort(), null, 2)));
32875
33710
  return;
32876
33711
  }
32877
- const projectConfig = await (0, import_cli12.loadTradejsConfig)(projectRoot15);
33712
+ const projectConfig = await (0, import_cli12.loadTradejsConfig)(projectRoot17);
32878
33713
  projectHooks = projectConfig.hooks;
32879
33714
  const currentTimestamp = (0, import_time10.getTimestamp)();
32880
33715
  const preloadStart = (0, import_time10.getTimestamp)(import_constants16.SIGNALS_CLI_PRELOAD_DAYS);
@@ -32892,7 +33727,7 @@ var init_runner = __esm({
32892
33727
  );
32893
33728
  await session.klineFeed.flush();
32894
33729
  import_logger10.logger.info(
32895
- import_chalk46.default.gray(
33730
+ import_chalk48.default.gray(
32896
33731
  `websocket candles: ready=${expectedSymbols.length - missingSymbols.length}/${expectedSymbols.length} missing=${missingSymbols.length}`
32897
33732
  )
32898
33733
  );
@@ -32903,7 +33738,7 @@ var init_runner = __esm({
32903
33738
  symbols: missingSymbols,
32904
33739
  preloadDays: import_constants16.SIGNALS_CLI_PRELOAD_DAYS,
32905
33740
  universe,
32906
- log: (message) => import_logger10.logger.info(import_chalk46.default.gray(message))
33741
+ log: (message) => import_logger10.logger.info(import_chalk48.default.gray(message))
32907
33742
  });
32908
33743
  await updateBtcReferenceHistory({
32909
33744
  marketConnector,
@@ -32911,7 +33746,7 @@ var init_runner = __esm({
32911
33746
  interval: interval5,
32912
33747
  preloadDays: import_constants16.SIGNALS_CLI_PRELOAD_DAYS,
32913
33748
  universe,
32914
- log: (message) => import_logger10.logger.info(import_chalk46.default.gray(message))
33749
+ log: (message) => import_logger10.logger.info(import_chalk48.default.gray(message))
32915
33750
  });
32916
33751
  } else if (!config2.cacheOnly) {
32917
33752
  await updateMarketHistoryWithBtcReferences({
@@ -32922,13 +33757,13 @@ var init_runner = __esm({
32922
33757
  symbols: tickers,
32923
33758
  preloadDays: import_constants16.SIGNALS_CLI_PRELOAD_DAYS,
32924
33759
  universe,
32925
- log: (message) => import_logger10.logger.info(import_chalk46.default.gray(message))
33760
+ log: (message) => import_logger10.logger.info(import_chalk48.default.gray(message))
32926
33761
  });
32927
33762
  }
32928
33763
  await prepareMarketContextForRun({
32929
33764
  mode: "signals",
32930
33765
  userName: config2.userName,
32931
- projectRoot: projectRoot15,
33766
+ projectRoot: projectRoot17,
32932
33767
  symbols: tickers,
32933
33768
  universe,
32934
33769
  interval: interval5,
@@ -32936,7 +33771,7 @@ var init_runner = __esm({
32936
33771
  endMs: currentTimestamp,
32937
33772
  preloadStartMs: preloadStart,
32938
33773
  cacheOnly: config2.cacheOnly,
32939
- log: (message) => import_logger10.logger.info(import_chalk46.default.gray(message))
33774
+ log: (message) => import_logger10.logger.info(import_chalk48.default.gray(message))
32940
33775
  });
32941
33776
  if (config2.updateOnly) {
32942
33777
  return;
@@ -32994,7 +33829,7 @@ var init_runner = __esm({
32994
33829
  );
32995
33830
  const configuredRuntimeStrategies = await (0, import_runtimeStrategies5.loadResolvedRuntimeStrategies)({
32996
33831
  userName: config2.userName,
32997
- projectRoot: projectRoot15,
33832
+ projectRoot: projectRoot17,
32998
33833
  deploymentId: deployment?.id ?? "",
32999
33834
  universe,
33000
33835
  accountId,
@@ -33031,7 +33866,7 @@ var init_runner = __esm({
33031
33866
  )
33032
33867
  );
33033
33868
  import_logger10.logger.info(
33034
- import_chalk46.default.yellow(
33869
+ import_chalk48.default.yellow(
33035
33870
  `loaded strategies (user=${config2.userName}): ${runtimeStrategies.map(formatConfiguredStrategyIdentity).join(", ")}`
33036
33871
  )
33037
33872
  );
@@ -33067,9 +33902,9 @@ var init_runner = __esm({
33067
33902
  width: 30
33068
33903
  }
33069
33904
  );
33070
- import_logger10.logger.info(import_chalk46.default.yellow(`tickers: ${tickers.length}`));
33905
+ import_logger10.logger.info(import_chalk48.default.yellow(`tickers: ${tickers.length}`));
33071
33906
  const signalsParallel = resolvePositiveInteger2(config2.parallel, 4);
33072
- import_logger10.logger.info(import_chalk46.default.yellow(`signal workers: ${signalsParallel}`));
33907
+ import_logger10.logger.info(import_chalk48.default.yellow(`signal workers: ${signalsParallel}`));
33073
33908
  const evaluateTicker = createSignalsTickerEvaluator({
33074
33909
  userName: config2.userName,
33075
33910
  makeOrders: config2.makeOrders,
@@ -33108,8 +33943,8 @@ var init_runner = __esm({
33108
33943
  signals3.push(...strategySignals);
33109
33944
  }
33110
33945
  bar.tick(1, {
33111
- found: import_chalk46.default.cyan(signals3.length),
33112
- symbol: import_chalk46.default.gray(symbol)
33946
+ found: import_chalk48.default.cyan(signals3.length),
33947
+ symbol: import_chalk48.default.gray(symbol)
33113
33948
  });
33114
33949
  });
33115
33950
  });
@@ -33213,7 +34048,7 @@ var init_runner = __esm({
33213
34048
  }
33214
34049
  }
33215
34050
  import_logger10.logger.info(
33216
- import_chalk46.default.yellow(
34051
+ import_chalk48.default.yellow(
33217
34052
  `signals ${status} in ${formatDuration3(durationMs)} (found=${signals3.length})`
33218
34053
  )
33219
34054
  );
@@ -33225,7 +34060,7 @@ var init_runner = __esm({
33225
34060
  const loadConfiguredSignalsScopes = async (deployment) => {
33226
34061
  const configuredStrategies = await (0, import_runtimeStrategies5.loadResolvedRuntimeStrategies)({
33227
34062
  userName: config2.userName,
33228
- projectRoot: projectRoot15,
34063
+ projectRoot: projectRoot17,
33229
34064
  deploymentId: deployment.id
33230
34065
  });
33231
34066
  const connectorName = await resolveSignalsConnectorName(
@@ -33248,7 +34083,7 @@ var init_runner = __esm({
33248
34083
  }
33249
34084
  const configuredDeployment = await (0, import_runtimeStrategies6.getRuntimeDeployment)({
33250
34085
  userName: config2.userName,
33251
- projectRoot: projectRoot15,
34086
+ projectRoot: projectRoot17,
33252
34087
  deploymentId: config2.deploymentId
33253
34088
  });
33254
34089
  if (!configuredDeployment) {
@@ -33282,7 +34117,7 @@ var init_runner = __esm({
33282
34117
  const deploymentId = config2.deploymentId;
33283
34118
  const initialDeployment = await (0, import_runtimeStrategies6.getRuntimeDeployment)({
33284
34119
  userName: config2.userName,
33285
- projectRoot: projectRoot15,
34120
+ projectRoot: projectRoot17,
33286
34121
  deploymentId
33287
34122
  });
33288
34123
  if (!initialDeployment) {
@@ -33307,7 +34142,7 @@ var init_runner = __esm({
33307
34142
  runCycle: async () => {
33308
34143
  const currentDeployment = await (0, import_runtimeStrategies6.getRuntimeDeployment)({
33309
34144
  userName: config2.userName,
33310
- projectRoot: projectRoot15,
34145
+ projectRoot: projectRoot17,
33311
34146
  deploymentId
33312
34147
  });
33313
34148
  if (!currentDeployment) {
@@ -33414,107 +34249,107 @@ var init_runner = __esm({
33414
34249
  var signals_exports = {};
33415
34250
  __export(signals_exports, {
33416
34251
  createSignalsSession: () => createSignalsSession,
33417
- main: () => main41,
34252
+ main: () => main43,
33418
34253
  signals: () => signals,
33419
34254
  signalsConfiguredScopesOnce: () => signalsConfiguredScopesOnce,
33420
34255
  signalsDaemon: () => signalsDaemon
33421
34256
  });
33422
- var import_config12, import_args31, flags29, config, runner, createSignalsSession, signals, signalsConfiguredScopesOnce, signalsDaemon, main41;
34257
+ var import_config12, import_args33, flags31, config, runner, createSignalsSession, signals, signalsConfiguredScopesOnce, signalsDaemon, main43;
33423
34258
  var init_signals = __esm({
33424
34259
  "src/scripts/signals.ts"() {
33425
34260
  "use strict";
33426
34261
  import_config12 = require("dotenv/config");
33427
- import_args31 = __toESM(require("args"));
34262
+ import_args33 = __toESM(require("args"));
33428
34263
  init_runner();
33429
- import_args31.default.option(["t", "tickers"], "Selected tickers");
33430
- import_args31.default.option(["e", "exclude"], "Exclude tickers from tests");
33431
- import_args31.default.option(["l", "tickersLimit"], "Tickers limit");
33432
- import_args31.default.option(["f", "timeframe"], "Timeframe", 15);
33433
- import_args31.default.option(["m", "makeOrders"], "Make orders");
33434
- import_args31.default.option(["N", "notify"], "Send message in Telegram", false);
33435
- import_args31.default.option(["S", "skipScreenshots"], "Skip screenshot generation", false);
33436
- import_args31.default.option(["u", "updateOnly"], "Only update tickers history", false);
33437
- import_args31.default.option(["C", "cacheOnly"], "Do not update tickers history", false);
33438
- import_args31.default.option(["L", "showTickersList"], "Just show only ticker list", false);
33439
- import_args31.default.option(
34264
+ import_args33.default.option(["t", "tickers"], "Selected tickers");
34265
+ import_args33.default.option(["e", "exclude"], "Exclude tickers from tests");
34266
+ import_args33.default.option(["l", "tickersLimit"], "Tickers limit");
34267
+ import_args33.default.option(["f", "timeframe"], "Timeframe", 15);
34268
+ import_args33.default.option(["m", "makeOrders"], "Make orders");
34269
+ import_args33.default.option(["N", "notify"], "Send message in Telegram", false);
34270
+ import_args33.default.option(["S", "skipScreenshots"], "Skip screenshot generation", false);
34271
+ import_args33.default.option(["u", "updateOnly"], "Only update tickers history", false);
34272
+ import_args33.default.option(["C", "cacheOnly"], "Do not update tickers history", false);
34273
+ import_args33.default.option(["L", "showTickersList"], "Just show only ticker list", false);
34274
+ import_args33.default.option(
33440
34275
  ["p", "parallel"],
33441
34276
  "Signal evaluation worker count",
33442
34277
  Number(process.env.SIGNALS_PARALLEL || 4)
33443
34278
  );
33444
- import_args31.default.option(
34279
+ import_args33.default.option(
33445
34280
  ["R", "showSkipStats"],
33446
34281
  "Show aggregated skip stats by strategy",
33447
34282
  false
33448
34283
  );
33449
- import_args31.default.option(["c", "chunk"], "Split by chunks, ex. 1/3");
33450
- import_args31.default.option(["U", "user"], "Use user confg", "root");
33451
- import_args31.default.option(["w", "watch"], "Keep signals running on candle boundaries", false);
33452
- import_args31.default.option(
34284
+ import_args33.default.option(["c", "chunk"], "Split by chunks, ex. 1/3");
34285
+ import_args33.default.option(["U", "user"], "Use user confg", "root");
34286
+ import_args33.default.option(["w", "watch"], "Keep signals running on candle boundaries", false);
34287
+ import_args33.default.option(
33453
34288
  ["d", "settleDelayMs"],
33454
34289
  "Delay after candle close before a daemon cycle",
33455
34290
  Number(process.env.SIGNALS_DAEMON_SETTLE_DELAY_MS || 5e3)
33456
34291
  );
33457
- import_args31.default.option(
34292
+ import_args33.default.option(
33458
34293
  ["o", "connector"],
33459
34294
  "Connector provider or name for signals (e.g. bybit, binance, coinbase, custom)",
33460
34295
  "bybit"
33461
34296
  );
33462
- import_args31.default.option(["V", "universe"], "Market universe (crypto or tradfi)", "crypto");
33463
- import_args31.default.option(["A", "account"], "Trading account id");
33464
- import_args31.default.option(["D", "deployment"], "Runtime deployment id");
33465
- flags29 = import_args31.default.parse(process.argv);
34297
+ import_args33.default.option(["V", "universe"], "Market universe (crypto or tradfi)", "crypto");
34298
+ import_args33.default.option(["A", "account"], "Trading account id");
34299
+ import_args33.default.option(["D", "deployment"], "Runtime deployment id");
34300
+ flags31 = import_args33.default.parse(process.argv);
33466
34301
  config = {
33467
34302
  projectRoot: String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd(),
33468
- userName: String(flags29.user || "root"),
33469
- interval: String(flags29.timeframe ?? 15),
33470
- connectorName: String(flags29.connector || "bybit"),
33471
- universe: flags29.universe,
33472
- accountId: flags29.account ? String(flags29.account) : void 0,
33473
- deploymentId: flags29.deployment ? String(flags29.deployment) : void 0,
33474
- tickers: flags29.tickers,
33475
- exclude: flags29.exclude,
33476
- tickersLimit: flags29.tickersLimit,
33477
- chunk: flags29.chunk,
33478
- makeOrders: Boolean(flags29.makeOrders),
33479
- notify: Boolean(flags29.notify),
33480
- skipScreenshots: Boolean(flags29.skipScreenshots),
33481
- updateOnly: Boolean(flags29.updateOnly),
33482
- cacheOnly: Boolean(flags29.cacheOnly),
33483
- showTickersList: Boolean(flags29.showTickersList),
33484
- showSkipStats: Boolean(flags29.showSkipStats),
33485
- parallel: flags29.parallel,
33486
- watch: Boolean(flags29.watch),
33487
- settleDelayMs: flags29.settleDelayMs
34303
+ userName: String(flags31.user || "root"),
34304
+ interval: String(flags31.timeframe ?? 15),
34305
+ connectorName: String(flags31.connector || "bybit"),
34306
+ universe: flags31.universe,
34307
+ accountId: flags31.account ? String(flags31.account) : void 0,
34308
+ deploymentId: flags31.deployment ? String(flags31.deployment) : void 0,
34309
+ tickers: flags31.tickers,
34310
+ exclude: flags31.exclude,
34311
+ tickersLimit: flags31.tickersLimit,
34312
+ chunk: flags31.chunk,
34313
+ makeOrders: Boolean(flags31.makeOrders),
34314
+ notify: Boolean(flags31.notify),
34315
+ skipScreenshots: Boolean(flags31.skipScreenshots),
34316
+ updateOnly: Boolean(flags31.updateOnly),
34317
+ cacheOnly: Boolean(flags31.cacheOnly),
34318
+ showTickersList: Boolean(flags31.showTickersList),
34319
+ showSkipStats: Boolean(flags31.showSkipStats),
34320
+ parallel: flags31.parallel,
34321
+ watch: Boolean(flags31.watch),
34322
+ settleDelayMs: flags31.settleDelayMs
33488
34323
  };
33489
34324
  runner = createSignalsRunner(config);
33490
34325
  createSignalsSession = runner.createSession;
33491
34326
  signals = runner.runCycle;
33492
34327
  signalsConfiguredScopesOnce = runner.runConfiguredScopesOnce;
33493
34328
  signalsDaemon = runner.runDaemon;
33494
- main41 = () => config.watch ? signalsDaemon() : signalsConfiguredScopesOnce();
34329
+ main43 = () => config.watch ? signalsDaemon() : signalsConfiguredScopesOnce();
33495
34330
  }
33496
34331
  });
33497
34332
 
33498
34333
  // src/scripts/signalsDaemon.ts
33499
34334
  var signalsDaemon_exports = {};
33500
34335
  __export(signalsDaemon_exports, {
33501
- main: () => main42
34336
+ main: () => main44
33502
34337
  });
33503
- var main42;
34338
+ var main44;
33504
34339
  var init_signalsDaemon = __esm({
33505
34340
  "src/scripts/signalsDaemon.ts"() {
33506
34341
  "use strict";
33507
34342
  init_signals();
33508
- main42 = signalsDaemon;
34343
+ main44 = signalsDaemon;
33509
34344
  }
33510
34345
  });
33511
34346
 
33512
34347
  // src/lib/replay/cliConfig.ts
33513
- var import_args32, REPLAY_UNSUPPORTED_FLAGS, hasCliFlag2, assertNoUnsupportedReplayFlags, replayNormalizedArgv, replayFlags, replayInterval, replayUserName, replayProjectRoot, replayRuntimeEvidencePath, replayDeploymentId, isReplayUpdateOnlyRun;
34348
+ var import_args34, REPLAY_UNSUPPORTED_FLAGS, hasCliFlag2, assertNoUnsupportedReplayFlags, replayNormalizedArgv, replayFlags, replayInterval, replayUserName, replayProjectRoot, replayRuntimeEvidencePath, replayDeploymentId, isReplayUpdateOnlyRun;
33514
34349
  var init_cliConfig2 = __esm({
33515
34350
  "src/lib/replay/cliConfig.ts"() {
33516
34351
  "use strict";
33517
- import_args32 = __toESM(require("args"));
34352
+ import_args34 = __toESM(require("args"));
33518
34353
  init_cliArgs();
33519
34354
  REPLAY_UNSUPPORTED_FLAGS = [
33520
34355
  ["--live", "`yarn replay` is already the replacement for legacy `--live`."],
@@ -33548,36 +34383,36 @@ var init_cliConfig2 = __esm({
33548
34383
  }
33549
34384
  }
33550
34385
  };
33551
- import_args32.default.example(
34386
+ import_args34.default.example(
33552
34387
  "yarn replay --days 7 --cacheOnly",
33553
34388
  "Replay active runtime strategies on historical data"
33554
34389
  );
33555
- import_args32.default.option(["t", "tickers"], "Selected tickers");
33556
- import_args32.default.option(["e", "exclude"], "Exclude tickers from replay");
33557
- import_args32.default.option(["l", "tickersLimit"], "Tickers limit");
33558
- import_args32.default.option(["f", "timeframe"], "Timeframe", 15);
33559
- import_args32.default.option(["d", "days"], "Run replay only for the last N days");
33560
- import_args32.default.option("startTime", "Explicit replay start timestamp (ms or seconds)");
33561
- import_args32.default.option("endTime", "Explicit replay end timestamp (ms or seconds)");
33562
- import_args32.default.option(
34390
+ import_args34.default.option(["t", "tickers"], "Selected tickers");
34391
+ import_args34.default.option(["e", "exclude"], "Exclude tickers from replay");
34392
+ import_args34.default.option(["l", "tickersLimit"], "Tickers limit");
34393
+ import_args34.default.option(["f", "timeframe"], "Timeframe", 15);
34394
+ import_args34.default.option(["d", "days"], "Run replay only for the last N days");
34395
+ import_args34.default.option("startTime", "Explicit replay start timestamp (ms or seconds)");
34396
+ import_args34.default.option("endTime", "Explicit replay end timestamp (ms or seconds)");
34397
+ import_args34.default.option(
33563
34398
  "runtimeEvidence",
33564
34399
  "Immutable runtime evidence JSON used for offline runtime comparison"
33565
34400
  );
33566
- import_args32.default.option(
34401
+ import_args34.default.option(
33567
34402
  "deployment",
33568
34403
  "Git-owned runtime deployment used when runtime evidence is omitted",
33569
34404
  "production"
33570
34405
  );
33571
- import_args32.default.option(["u", "updateOnly"], "Only update tickers history", false);
33572
- import_args32.default.option(["C", "cacheOnly"], "Do not update tickers history", false);
33573
- import_args32.default.option(
34406
+ import_args34.default.option(["u", "updateOnly"], "Only update tickers history", false);
34407
+ import_args34.default.option(["C", "cacheOnly"], "Do not update tickers history", false);
34408
+ import_args34.default.option(
33574
34409
  "chart",
33575
34410
  "Save compact replay chart data for the strategies UI",
33576
34411
  false
33577
34412
  );
33578
- import_args32.default.option(["L", "showTickersList"], "Just show only ticker list", false);
33579
- import_args32.default.option(["U", "user"], "Use user config", "root");
33580
- import_args32.default.option(
34413
+ import_args34.default.option(["L", "showTickersList"], "Just show only ticker list", false);
34414
+ import_args34.default.option(["U", "user"], "Use user config", "root");
34415
+ import_args34.default.option(
33581
34416
  ["o", "connector"],
33582
34417
  "Connector provider or name for replay (e.g. bybit, binance, coinbase, custom)",
33583
34418
  "bybit"
@@ -33589,7 +34424,7 @@ var init_cliConfig2 = __esm({
33589
34424
  "-U": "--user"
33590
34425
  });
33591
34426
  assertNoUnsupportedReplayFlags(replayNormalizedArgv);
33592
- replayFlags = import_args32.default.parse(replayNormalizedArgv);
34427
+ replayFlags = import_args34.default.parse(replayNormalizedArgv);
33593
34428
  replayInterval = String(replayFlags.timeframe ?? 15);
33594
34429
  replayUserName = String(replayFlags.user ?? "root");
33595
34430
  replayProjectRoot = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
@@ -33602,12 +34437,12 @@ var init_cliConfig2 = __esm({
33602
34437
  });
33603
34438
 
33604
34439
  // src/lib/replay/runtimeEvidenceSource.ts
33605
- var import_promises28, import_node_path23, asRecord7, asFiniteNumber, unwrapRows2, assertRuntimeRowsMatchDeployment, readRuntimeEvidenceArtifact, loadReplayRuntimeEvidenceMetadata, buildRuntimeEvidenceLineageScopes, loadReplayRuntimeEvidenceSource;
34440
+ var import_promises32, import_node_path29, asRecord7, asFiniteNumber, unwrapRows2, assertRuntimeRowsMatchDeployment, readRuntimeEvidenceArtifact, loadReplayRuntimeEvidenceMetadata, buildRuntimeEvidenceLineageScopes, loadReplayRuntimeEvidenceSource;
33606
34441
  var init_runtimeEvidenceSource = __esm({
33607
34442
  "src/lib/replay/runtimeEvidenceSource.ts"() {
33608
34443
  "use strict";
33609
- import_promises28 = __toESM(require("fs/promises"));
33610
- import_node_path23 = __toESM(require("path"));
34444
+ import_promises32 = __toESM(require("fs/promises"));
34445
+ import_node_path29 = __toESM(require("path"));
33611
34446
  init_runtimeLineage();
33612
34447
  init_runtimeEvidenceDeployment();
33613
34448
  asRecord7 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
@@ -33636,11 +34471,11 @@ var init_runtimeEvidenceSource = __esm({
33636
34471
  };
33637
34472
  readRuntimeEvidenceArtifact = async ({
33638
34473
  filePath,
33639
- projectRoot: projectRoot15
34474
+ projectRoot: projectRoot17
33640
34475
  }) => {
33641
- const resolvedPath = import_node_path23.default.resolve(projectRoot15, filePath);
34476
+ const resolvedPath = import_node_path29.default.resolve(projectRoot17, filePath);
33642
34477
  const root = asRecord7(
33643
- JSON.parse(await import_promises28.default.readFile(resolvedPath, "utf8"))
34478
+ JSON.parse(await import_promises32.default.readFile(resolvedPath, "utf8"))
33644
34479
  );
33645
34480
  const runtime = asRecord7(root?.runtime) ?? root;
33646
34481
  if (!root || !runtime) {
@@ -33737,11 +34572,11 @@ var init_runtimeEvidenceSource = __esm({
33737
34572
  };
33738
34573
  loadReplayRuntimeEvidenceSource = async ({
33739
34574
  filePath,
33740
- projectRoot: projectRoot15,
34575
+ projectRoot: projectRoot17,
33741
34576
  expectedUserName,
33742
34577
  expectedWindow
33743
34578
  }) => {
33744
- const { resolvedPath, runtime, userName: userName3, startTime, endTime, deployment } = await readRuntimeEvidenceArtifact({ filePath, projectRoot: projectRoot15 });
34579
+ const { resolvedPath, runtime, userName: userName3, startTime, endTime, deployment } = await readRuntimeEvidenceArtifact({ filePath, projectRoot: projectRoot17 });
33745
34580
  if (!userName3 || userName3 !== expectedUserName) {
33746
34581
  throw new Error(
33747
34582
  `Runtime evidence user mismatch: expected=${expectedUserName}, actual=${userName3 || "missing"}`
@@ -34282,7 +35117,7 @@ var init_historicalSignalsReplayPreparation = __esm({
34282
35117
  prepareHistoricalReplay = async (context, adapters) => {
34283
35118
  const {
34284
35119
  userName: userName3,
34285
- projectRoot: projectRoot15,
35120
+ projectRoot: projectRoot17,
34286
35121
  preparedRun,
34287
35122
  interval: interval4,
34288
35123
  connectorName,
@@ -34335,7 +35170,7 @@ var init_historicalSignalsReplayPreparation = __esm({
34335
35170
  interval: interval4
34336
35171
  });
34337
35172
  const runtimeLineage = await adapters.buildLineage({
34338
- projectRoot: projectRoot15,
35173
+ projectRoot: projectRoot17,
34339
35174
  strategyName: strategy.strategyName,
34340
35175
  strategyRevision: strategy.strategyRevision,
34341
35176
  deploymentCompositionId: strategy.deploymentCompositionId,
@@ -34558,11 +35393,11 @@ var init_historicalSignalsReplayResults = __esm({
34558
35393
  });
34559
35394
 
34560
35395
  // src/lib/replay/historicalSignalsReplay.ts
34561
- var import_chalk47, import_progress12, import_strategies12, import_time11, import_logger11, import_redis19, import_connectors17, import_cli13, import_strategies13, import_runtimeStrategies8, loadRuntimeStrategies, loadReferenceConnector, buildAfterSignalsContext, getConnectorName, runHistoricalSignalsReplay;
35396
+ var import_chalk49, import_progress12, import_strategies12, import_time11, import_logger11, import_redis19, import_connectors17, import_cli13, import_strategies13, import_runtimeStrategies8, loadRuntimeStrategies, loadReferenceConnector, buildAfterSignalsContext, getConnectorName, runHistoricalSignalsReplay;
34562
35397
  var init_historicalSignalsReplay = __esm({
34563
35398
  "src/lib/replay/historicalSignalsReplay.ts"() {
34564
35399
  "use strict";
34565
- import_chalk47 = __toESM(require("chalk"));
35400
+ import_chalk49 = __toESM(require("chalk"));
34566
35401
  import_progress12 = __toESM(require("progress"));
34567
35402
  import_strategies12 = require("@tradejs/core/strategies");
34568
35403
  import_time11 = require("@tradejs/core/time");
@@ -34738,8 +35573,8 @@ var init_historicalSignalsReplay = __esm({
34738
35573
  tick: (tokens) => prepareBar.tick(1, tokens)
34739
35574
  },
34740
35575
  display: {
34741
- skipped: (value) => import_chalk47.default.yellow(value),
34742
- symbol: (value) => import_chalk47.default.gray(value)
35576
+ skipped: (value) => import_chalk49.default.yellow(value),
35577
+ symbol: (value) => import_chalk49.default.gray(value)
34743
35578
  },
34744
35579
  buildLineage: buildRuntimeLineage
34745
35580
  }
@@ -34771,9 +35606,9 @@ var init_historicalSignalsReplay = __esm({
34771
35606
  tick: (tokens) => cycleBar.tick(1, tokens)
34772
35607
  },
34773
35608
  display: {
34774
- signals: (value) => import_chalk47.default.cyan(value),
34775
- aborted: (value) => import_chalk47.default.yellow(value),
34776
- timestamp: (value) => import_chalk47.default.gray((0, import_time11.formatUnix)(value))
35609
+ signals: (value) => import_chalk49.default.cyan(value),
35610
+ aborted: (value) => import_chalk49.default.yellow(value),
35611
+ timestamp: (value) => import_chalk49.default.gray((0, import_time11.formatUnix)(value))
34777
35612
  },
34778
35613
  invokeBeforeSignals: invokeBeforeSignalsHooks,
34779
35614
  invokeAfterSignals: invokeAfterSignalsHooks,
@@ -34784,7 +35619,7 @@ var init_historicalSignalsReplay = __esm({
34784
35619
  );
34785
35620
  const artifacts = replayConnector.getReplayArtifacts();
34786
35621
  import_logger11.logger.info(
34787
- import_chalk47.default.gray(
35622
+ import_chalk49.default.gray(
34788
35623
  `signals replay historical cycles: ${plan.orderedTimestamps.length} (aborted=${execution.abortedCycles}) done in ${((Date.now() - startedAt) / 1e3).toFixed(1)}s`
34789
35624
  )
34790
35625
  );
@@ -34897,11 +35732,11 @@ var init_chartSnapshot = __esm({
34897
35732
  });
34898
35733
 
34899
35734
  // src/lib/replay/resultsReporting.ts
34900
- var import_chalk48, saveAndPrintReplayResultsByStrategy;
35735
+ var import_chalk50, saveAndPrintReplayResultsByStrategy;
34901
35736
  var init_resultsReporting = __esm({
34902
35737
  "src/lib/replay/resultsReporting.ts"() {
34903
35738
  "use strict";
34904
- import_chalk48 = __toESM(require("chalk"));
35739
+ import_chalk50 = __toESM(require("chalk"));
34905
35740
  init_runtimeParity();
34906
35741
  init_runFormatting();
34907
35742
  init_support();
@@ -34940,14 +35775,14 @@ var init_resultsReporting = __esm({
34940
35775
  const rows = summaries.map((summary) => {
34941
35776
  const profit = `${summary.netProfit.toFixed(2)}$`;
34942
35777
  const avgTrade = `${summary.avgTradeProfit.toFixed(2)}$`;
34943
- const profitColor = summary.netProfit > 0 ? import_chalk48.default.green : summary.netProfit < 0 ? import_chalk48.default.red : import_chalk48.default.gray;
34944
- const avgTradeColor = summary.avgTradeProfit > 0 ? import_chalk48.default.green : summary.avgTradeProfit < 0 ? import_chalk48.default.red : import_chalk48.default.gray;
35778
+ const profitColor = summary.netProfit > 0 ? import_chalk50.default.green : summary.netProfit < 0 ? import_chalk50.default.red : import_chalk50.default.gray;
35779
+ const avgTradeColor = summary.avgTradeProfit > 0 ? import_chalk50.default.green : summary.avgTradeProfit < 0 ? import_chalk50.default.red : import_chalk50.default.gray;
34945
35780
  return [
34946
- import_chalk48.default.blue(summary.strategyName),
34947
- import_chalk48.default.yellow(String(summary.tickers)),
34948
- import_chalk48.default.yellow(String(summary.tickersWithTrades)),
34949
- import_chalk48.default.cyan(String(summary.orders)),
34950
- import_chalk48.default.cyan(
35781
+ import_chalk50.default.blue(summary.strategyName),
35782
+ import_chalk50.default.yellow(String(summary.tickers)),
35783
+ import_chalk50.default.yellow(String(summary.tickersWithTrades)),
35784
+ import_chalk50.default.cyan(String(summary.orders)),
35785
+ import_chalk50.default.cyan(
34951
35786
  `${summary.wins}/${summary.losses} (${summary.winRate.toFixed(2)}%)`
34952
35787
  ),
34953
35788
  profitColor(profit),
@@ -36417,29 +37252,29 @@ var init_runtimeComparisonCalculations = __esm({
36417
37252
  });
36418
37253
 
36419
37254
  // src/lib/replay/runtimeComparisonReporting.ts
36420
- var import_chalk49, import_time13, formatDrilldownSummary, colorizeRows, buildReplayComparisonReport, buildNoExchangeEntriesReport, buildNoRuntimeTradesReport, writeReplayComparisonReport;
37255
+ var import_chalk51, import_time13, formatDrilldownSummary, colorizeRows, buildReplayComparisonReport, buildNoExchangeEntriesReport, buildNoRuntimeTradesReport, writeReplayComparisonReport;
36421
37256
  var init_runtimeComparisonReporting = __esm({
36422
37257
  "src/lib/replay/runtimeComparisonReporting.ts"() {
36423
37258
  "use strict";
36424
- import_chalk49 = __toESM(require("chalk"));
37259
+ import_chalk51 = __toESM(require("chalk"));
36425
37260
  import_time13 = require("@tradejs/core/time");
36426
37261
  init_runFormatting();
36427
37262
  init_support();
36428
37263
  formatDrilldownSummary = (summary) => Object.entries(summary).filter(([, count]) => count > 0).map(([classification, count]) => `${classification}=${count}`).join(", ");
36429
37264
  colorizeRows = (rows) => rows.map((row) => {
36430
- const btPnlColor = row.backtestNetProfit > 0 ? import_chalk49.default.green : row.backtestNetProfit < 0 ? import_chalk49.default.red : import_chalk49.default.gray;
36431
- const rtPnlColor = row.runtimePnl > 0 ? import_chalk49.default.green : row.runtimePnl < 0 ? import_chalk49.default.red : import_chalk49.default.gray;
37265
+ const btPnlColor = row.backtestNetProfit > 0 ? import_chalk51.default.green : row.backtestNetProfit < 0 ? import_chalk51.default.red : import_chalk51.default.gray;
37266
+ const rtPnlColor = row.runtimePnl > 0 ? import_chalk51.default.green : row.runtimePnl < 0 ? import_chalk51.default.red : import_chalk51.default.gray;
36432
37267
  return [
36433
- import_chalk49.default.blue(row.strategyName),
36434
- import_chalk49.default.cyan(String(row.backtestEntries)),
37268
+ import_chalk51.default.blue(row.strategyName),
37269
+ import_chalk51.default.cyan(String(row.backtestEntries)),
36435
37270
  btPnlColor(`${row.backtestNetProfit.toFixed(2)}$`),
36436
- import_chalk49.default.yellow(String(row.runtimeTrades)),
37271
+ import_chalk51.default.yellow(String(row.runtimeTrades)),
36437
37272
  rtPnlColor(`${row.runtimePnl.toFixed(2)}$`),
36438
- import_chalk49.default.green(String(row.matched)),
36439
- import_chalk49.default.red(String(row.orderFailed)),
36440
- import_chalk49.default.yellow(String(row.runtimeOnly)),
36441
- import_chalk49.default.magenta(String(row.backtestOnly)),
36442
- import_chalk49.default.red(String(getReplayRuntimeUnmatchedCount(row)))
37273
+ import_chalk51.default.green(String(row.matched)),
37274
+ import_chalk51.default.red(String(row.orderFailed)),
37275
+ import_chalk51.default.yellow(String(row.runtimeOnly)),
37276
+ import_chalk51.default.magenta(String(row.backtestOnly)),
37277
+ import_chalk51.default.red(String(getReplayRuntimeUnmatchedCount(row)))
36443
37278
  ];
36444
37279
  });
36445
37280
  buildReplayComparisonReport = (context) => {
@@ -36459,7 +37294,7 @@ var init_runtimeComparisonReporting = __esm({
36459
37294
  ];
36460
37295
  if (runtimeOnlyDrilldownSummary || backtestOnlyDrilldownSummary) {
36461
37296
  lines.push(
36462
- import_chalk49.default.gray(
37297
+ import_chalk51.default.gray(
36463
37298
  `Mismatch drilldown: ${runtimeOnlyLabel}=[${runtimeOnlyDrilldownSummary || "none"}], backtestOnly=[${backtestOnlyDrilldownSummary || "none"}]`
36464
37299
  )
36465
37300
  );
@@ -36472,7 +37307,7 @@ var init_runtimeComparisonReporting = __esm({
36472
37307
  window
36473
37308
  }) => [
36474
37309
  "",
36475
- import_chalk49.default.yellow(
37310
+ import_chalk51.default.yellow(
36476
37311
  `SIGNALS REPLAY VS EXCHANGE: no lineage-linked exchange entry executions found for ${connectorName} in ${(0, import_time13.formatUnix)(
36477
37312
  window.start
36478
37313
  )} -> ${(0, import_time13.formatUnix)(window.end)}`
@@ -36484,7 +37319,7 @@ var init_runtimeComparisonReporting = __esm({
36484
37319
  window
36485
37320
  }) => [
36486
37321
  "",
36487
- import_chalk49.default.yellow(
37322
+ import_chalk51.default.yellow(
36488
37323
  `SIGNALS REPLAY VS RUNTIME: no local runtime trades found for ${connectorName} in ${(0, import_time13.formatUnix)(
36489
37324
  window.start
36490
37325
  )} -> ${(0, import_time13.formatUnix)(window.end)} with matching lineage; checking lineage-linked exchange executions`
@@ -36500,11 +37335,11 @@ var init_runtimeComparisonReporting = __esm({
36500
37335
  });
36501
37336
 
36502
37337
  // src/lib/replay/runtimeComparison.ts
36503
- var import_chalk50, getReplayEntryTimestampCompareOffsetMs, buildReplaySignalEvaluations, toFiniteNumberOrNull4, sumOptionalNumbers, firstFiniteNumber, firstString, getExchangeExecutionMergeKey, mergeExchangeExecutionGroup, mergeExchangeEntryExecutions, loadExchangeEntryRows, loadExchangeEntriesForComparison, saveAndPrintReplayExchangeComparison, saveAndPrintReplayRuntimeComparison;
37338
+ var import_chalk52, getReplayEntryTimestampCompareOffsetMs, buildReplaySignalEvaluations, toFiniteNumberOrNull4, sumOptionalNumbers, firstFiniteNumber, firstString, getExchangeExecutionMergeKey, mergeExchangeExecutionGroup, mergeExchangeEntryExecutions, loadExchangeEntryRows, loadExchangeEntriesForComparison, saveAndPrintReplayExchangeComparison, saveAndPrintReplayRuntimeComparison;
36504
37339
  var init_runtimeComparison = __esm({
36505
37340
  "src/lib/replay/runtimeComparison.ts"() {
36506
37341
  "use strict";
36507
- import_chalk50 = __toESM(require("chalk"));
37342
+ import_chalk52 = __toESM(require("chalk"));
36508
37343
  init_runtimeParity();
36509
37344
  init_paritySummary();
36510
37345
  init_runtimeRedis();
@@ -36641,7 +37476,7 @@ var init_runtimeComparison = __esm({
36641
37476
  }) => {
36642
37477
  if (typeof connector.getEntryExecutions !== "function") {
36643
37478
  console.log(
36644
- import_chalk50.default.yellow(
37479
+ import_chalk52.default.yellow(
36645
37480
  "runtime compare: connector does not support entry execution history"
36646
37481
  )
36647
37482
  );
@@ -36658,7 +37493,7 @@ var init_runtimeComparison = __esm({
36658
37493
  });
36659
37494
  if (chunkRows.length >= 100) {
36660
37495
  console.log(
36661
- import_chalk50.default.yellow(
37496
+ import_chalk52.default.yellow(
36662
37497
  "runtime compare: exchange entry executions returned 100 rows (connector cap); older entry trades in this chunk may be truncated"
36663
37498
  )
36664
37499
  );
@@ -36666,7 +37501,7 @@ var init_runtimeComparison = __esm({
36666
37501
  rows.push(...chunkRows);
36667
37502
  } catch (error) {
36668
37503
  console.log(
36669
- import_chalk50.default.yellow(
37504
+ import_chalk52.default.yellow(
36670
37505
  `runtime compare: getEntryExecutions failed: ${formatRuntimeTradeSyncError(error)}`
36671
37506
  )
36672
37507
  );
@@ -36691,21 +37526,21 @@ var init_runtimeComparison = __esm({
36691
37526
  callbacks: {
36692
37527
  onUnsupported: () => {
36693
37528
  console.log(
36694
- import_chalk50.default.yellow(
37529
+ import_chalk52.default.yellow(
36695
37530
  "runtime compare: connector does not support getClosedPnl, using runtime trade records as-is"
36696
37531
  )
36697
37532
  );
36698
37533
  },
36699
37534
  onCapped: () => {
36700
37535
  console.log(
36701
- import_chalk50.default.yellow(
37536
+ import_chalk52.default.yellow(
36702
37537
  "runtime compare: exchange closed pnl returned 100 rows (connector cap); older closed trades in the window may be truncated"
36703
37538
  )
36704
37539
  );
36705
37540
  },
36706
37541
  onError: (error) => {
36707
37542
  console.log(
36708
- import_chalk50.default.yellow(
37543
+ import_chalk52.default.yellow(
36709
37544
  `runtime compare: getClosedPnl failed: ${formatRuntimeTradeSyncError(error)}`
36710
37545
  )
36711
37546
  );
@@ -36927,7 +37762,7 @@ var init_runtimeComparison = __esm({
36927
37762
  ]);
36928
37763
  if (runtimeEvidence2) {
36929
37764
  console.log(
36930
- import_chalk50.default.gray(
37765
+ import_chalk52.default.gray(
36931
37766
  `runtime compare: using immutable evidence ${runtimeEvidence2.path}`
36932
37767
  )
36933
37768
  );
@@ -36941,7 +37776,7 @@ var init_runtimeComparison = __esm({
36941
37776
  openPositionCallbacks: {
36942
37777
  onError: (error) => {
36943
37778
  console.log(
36944
- import_chalk50.default.yellow(
37779
+ import_chalk52.default.yellow(
36945
37780
  `runtime compare: getOpenPositionPnl failed: ${formatRuntimeTradeSyncError(error)}; continuing without open-position mark prices`
36946
37781
  )
36947
37782
  );
@@ -36950,21 +37785,21 @@ var init_runtimeComparison = __esm({
36950
37785
  closedPnlCallbacks: {
36951
37786
  onUnsupported: () => {
36952
37787
  console.log(
36953
- import_chalk50.default.yellow(
37788
+ import_chalk52.default.yellow(
36954
37789
  "runtime compare: connector does not support getClosedPnl, using runtime trade records as-is"
36955
37790
  )
36956
37791
  );
36957
37792
  },
36958
37793
  onCapped: () => {
36959
37794
  console.log(
36960
- import_chalk50.default.yellow(
37795
+ import_chalk52.default.yellow(
36961
37796
  "runtime compare: exchange closed pnl returned 100 rows (connector cap); older closed trades in the window may be truncated"
36962
37797
  )
36963
37798
  );
36964
37799
  },
36965
37800
  onError: (error) => {
36966
37801
  console.log(
36967
- import_chalk50.default.yellow(
37802
+ import_chalk52.default.yellow(
36968
37803
  `runtime compare: getClosedPnl failed: ${formatRuntimeTradeSyncError(error)}`
36969
37804
  )
36970
37805
  );
@@ -37060,12 +37895,12 @@ var init_runtimeComparison = __esm({
37060
37895
  });
37061
37896
 
37062
37897
  // src/lib/replay/outputReport.ts
37063
- var import_promises29, import_node_path24, import_data4, formatMsk, formatNumber5, formatMoney2, formatPct, tableCell, createMarkdownTable2, entryStrategy, entryKey, buildDrilldownMap, buildPerTradeAnalysis, renderMatchedRows, renderRuntimeOnlyRows, renderOrderFailedRows, renderBacktestOnlyRows, renderStrategyRows, renderLineageRows, writeReplayOutputReport;
37898
+ var import_promises33, import_node_path30, import_data4, formatMsk, formatNumber5, formatMoney2, formatPct, tableCell, createMarkdownTable2, entryStrategy, entryKey, buildDrilldownMap, buildPerTradeAnalysis, renderMatchedRows, renderRuntimeOnlyRows, renderOrderFailedRows, renderBacktestOnlyRows, renderStrategyRows, renderLineageRows, writeReplayOutputReport;
37064
37899
  var init_outputReport = __esm({
37065
37900
  "src/lib/replay/outputReport.ts"() {
37066
37901
  "use strict";
37067
- import_promises29 = __toESM(require("fs/promises"));
37068
- import_node_path24 = __toESM(require("path"));
37902
+ import_promises33 = __toESM(require("fs/promises"));
37903
+ import_node_path30 = __toESM(require("path"));
37069
37904
  import_data4 = require("@tradejs/core/data");
37070
37905
  init_support();
37071
37906
  formatMsk = (timestamp) => typeof timestamp === "number" && Number.isFinite(timestamp) ? new Intl.DateTimeFormat("ru-RU", {
@@ -37357,7 +38192,7 @@ var init_outputReport = __esm({
37357
38192
  ) : "_No replay lineage records._";
37358
38193
  };
37359
38194
  writeReplayOutputReport = async ({
37360
- projectRoot: projectRoot15,
38195
+ projectRoot: projectRoot17,
37361
38196
  timestamp,
37362
38197
  replayKey,
37363
38198
  userName: userName3,
@@ -37370,8 +38205,8 @@ var init_outputReport = __esm({
37370
38205
  strategySnapshot,
37371
38206
  runtimeComparison
37372
38207
  }) => {
37373
- const outputDir = import_node_path24.default.resolve(projectRoot15, "data/replay/output");
37374
- await import_promises29.default.mkdir(outputDir, { recursive: true });
38208
+ const outputDir = import_node_path30.default.resolve(projectRoot17, "data/replay/output");
38209
+ await import_promises33.default.mkdir(outputDir, { recursive: true });
37375
38210
  const perTradeAnalysis = buildPerTradeAnalysis(runtimeComparison);
37376
38211
  const report = {
37377
38212
  reportType: "replay-output",
@@ -37406,8 +38241,8 @@ var init_outputReport = __esm({
37406
38241
  runtimeComparison,
37407
38242
  perTradeAnalysis
37408
38243
  };
37409
- const markdownPath = import_node_path24.default.join(outputDir, `${timestamp}-replay-report.md`);
37410
- const jsonPath = import_node_path24.default.join(outputDir, `${timestamp}-replay-report.json`);
38244
+ const markdownPath = import_node_path30.default.join(outputDir, `${timestamp}-replay-report.md`);
38245
+ const jsonPath = import_node_path30.default.join(outputDir, `${timestamp}-replay-report.json`);
37411
38246
  const lines = [
37412
38247
  "# Replay Report",
37413
38248
  "",
@@ -37473,8 +38308,8 @@ var init_outputReport = __esm({
37473
38308
  ""
37474
38309
  ];
37475
38310
  await Promise.all([
37476
- import_promises29.default.writeFile(markdownPath, lines.join("\n"), "utf8"),
37477
- import_promises29.default.writeFile(jsonPath, `${(0, import_data4.toJson)(report, true)}
38311
+ import_promises33.default.writeFile(markdownPath, lines.join("\n"), "utf8"),
38312
+ import_promises33.default.writeFile(jsonPath, `${(0, import_data4.toJson)(report, true)}
37478
38313
  `, "utf8")
37479
38314
  ]);
37480
38315
  return {
@@ -37486,11 +38321,11 @@ var init_outputReport = __esm({
37486
38321
  });
37487
38322
 
37488
38323
  // src/scripts/replayRunner.ts
37489
- var import_chalk51, import_constants19, import_data5, import_time14, import_redis21, prepareReplayBinanceMarketContext, finishReplay, replayBacktest;
38324
+ var import_chalk53, import_constants19, import_data5, import_time14, import_redis21, prepareReplayBinanceMarketContext, finishReplay, replayBacktest;
37490
38325
  var init_replayRunner = __esm({
37491
38326
  "src/scripts/replayRunner.ts"() {
37492
38327
  "use strict";
37493
- import_chalk51 = __toESM(require("chalk"));
38328
+ import_chalk53 = __toESM(require("chalk"));
37494
38329
  import_constants19 = require("@tradejs/core/constants");
37495
38330
  import_data5 = require("@tradejs/core/data");
37496
38331
  import_time14 = require("@tradejs/core/time");
@@ -37524,7 +38359,7 @@ var init_replayRunner = __esm({
37524
38359
  aiEnabled: preparedRun.aiEnabled,
37525
38360
  mlEnabled: preparedRun.mlEnabled,
37526
38361
  strategyNames: preparedRun.strategyNames,
37527
- log: (message) => console.log(import_chalk51.default.gray(message))
38362
+ log: (message) => console.log(import_chalk53.default.gray(message))
37528
38363
  });
37529
38364
  };
37530
38365
  finishReplay = async ({
@@ -37577,8 +38412,8 @@ var init_replayRunner = __esm({
37577
38412
  strategySnapshot: replayStrategySnapshot,
37578
38413
  runtimeComparison: replayRuntimeComparison
37579
38414
  });
37580
- console.log(import_chalk51.default.green(`Replay report: ${outputReport.markdownPath}`));
37581
- console.log(import_chalk51.default.green(`Replay report JSON: ${outputReport.jsonPath}`));
38415
+ console.log(import_chalk53.default.green(`Replay report: ${outputReport.markdownPath}`));
38416
+ console.log(import_chalk53.default.green(`Replay report JSON: ${outputReport.jsonPath}`));
37582
38417
  await (0, import_redis21.setData)(
37583
38418
  replayKey,
37584
38419
  {
@@ -37731,9 +38566,9 @@ var init_replayRunner = __esm({
37731
38566
  ),
37732
38567
  strategyNames: replayStrategies.map(({ strategyName }) => strategyName)
37733
38568
  });
37734
- console.log(import_chalk51.default.yellow(`tickers: ${preparedRun.tickers.length}`));
38569
+ console.log(import_chalk53.default.yellow(`tickers: ${preparedRun.tickers.length}`));
37735
38570
  console.log(
37736
- import_chalk51.default.gray(
38571
+ import_chalk53.default.gray(
37737
38572
  `mode: replay (${replayStrategies.map(({ strategyName }) => strategyName).join(", ")})`
37738
38573
  )
37739
38574
  );
@@ -37761,14 +38596,14 @@ var init_replayRunner = __esm({
37761
38596
  // src/scripts/replay.ts
37762
38597
  var replay_exports = {};
37763
38598
  __export(replay_exports, {
37764
- main: () => main43
38599
+ main: () => main45
37765
38600
  });
37766
- var main43;
38601
+ var main45;
37767
38602
  var init_replay = __esm({
37768
38603
  "src/scripts/replay.ts"() {
37769
38604
  "use strict";
37770
38605
  init_replayRunner();
37771
- main43 = async () => {
38606
+ main45 = async () => {
37772
38607
  await replayBacktest();
37773
38608
  };
37774
38609
  }
@@ -37777,15 +38612,15 @@ var init_replay = __esm({
37777
38612
  // src/scripts/signalsSummary.ts
37778
38613
  var signalsSummary_exports = {};
37779
38614
  __export(signalsSummary_exports, {
37780
- main: () => main44,
38615
+ main: () => main46,
37781
38616
  signalsSummary: () => signalsSummary
37782
38617
  });
37783
- var import_config13, import_args33, import_logger12, import_connectors18, import_runtimeStrategies9, flags30, projectRoot14, SUMMARY_TIMEZONE2, SUMMARY_TIMEZONE_LABEL2, escapeHtml6, formatMskDateTime3, formatSigned3, formatPnlMoneyText, formatWinRateText, resolveSummaryTitle, normalizeStatus, shouldAttachDebugReport, getSummaryDateParts, formatSummaryIsoDayKey, unescapeHtml, stripTelegramHtml, buildSignalsSummaryAttachment, appendReportAttachmentSummary, resolveSummaryConnectorName, groupRuntimeTradesByConnectorScope, syncRuntimeTradeScopes, createRuntimeSignalStats, mergeRuntimeSignalStats, buildSummaryPrelude, resolveTradeStatusEmoji, isTimestampInWindow, isRuntimeTradeClosedInWindow, buildSummaryMessages, signalsSummary, main44;
38618
+ var import_config13, import_args35, import_logger12, import_connectors18, import_runtimeStrategies9, flags32, projectRoot16, SUMMARY_TIMEZONE2, SUMMARY_TIMEZONE_LABEL2, escapeHtml6, formatMskDateTime3, formatSigned3, formatPnlMoneyText, formatWinRateText, resolveSummaryTitle, normalizeStatus, shouldAttachDebugReport, getSummaryDateParts, formatSummaryIsoDayKey, unescapeHtml, stripTelegramHtml, buildSignalsSummaryAttachment, appendReportAttachmentSummary, resolveSummaryConnectorName, groupRuntimeTradesByConnectorScope, syncRuntimeTradeScopes, createRuntimeSignalStats, mergeRuntimeSignalStats, buildSummaryPrelude, resolveTradeStatusEmoji, isTimestampInWindow, isRuntimeTradeClosedInWindow, buildSummaryMessages, signalsSummary, main46;
37784
38619
  var init_signalsSummary = __esm({
37785
38620
  "src/scripts/signalsSummary.ts"() {
37786
38621
  "use strict";
37787
38622
  import_config13 = require("dotenv/config");
37788
- import_args33 = __toESM(require("args"));
38623
+ import_args35 = __toESM(require("args"));
37789
38624
  import_logger12 = require("@tradejs/infra/logger");
37790
38625
  import_connectors18 = require("@tradejs/node/connectors");
37791
38626
  init_runtimeRedis();
@@ -37795,21 +38630,21 @@ var init_signalsSummary = __esm({
37795
38630
  init_runtimeSignalsStorage();
37796
38631
  init_runtimeDebugEvidence();
37797
38632
  import_runtimeStrategies9 = require("@tradejs/node/runtimeStrategies");
37798
- import_args33.default.option(["u", "user"], "Use user config", "root");
37799
- import_args33.default.option(
38633
+ import_args35.default.option(["u", "user"], "Use user config", "root");
38634
+ import_args35.default.option(
37800
38635
  "connector",
37801
38636
  "Connector provider or name for summary (e.g. bybit, binance, coinbase, custom)",
37802
38637
  "bybit"
37803
38638
  );
37804
- import_args33.default.option(["H", "hours"], "Summary window in hours", 24);
37805
- import_args33.default.option(["P", "printOnly"], "Print summary instead of Telegram", false);
37806
- import_args33.default.option(
38639
+ import_args35.default.option(["H", "hours"], "Summary window in hours", 24);
38640
+ import_args35.default.option(["P", "printOnly"], "Print summary instead of Telegram", false);
38641
+ import_args35.default.option(
37807
38642
  "debugAttachment",
37808
38643
  "Attach runtime Redis debug JSON for replay diagnostics",
37809
38644
  true
37810
38645
  );
37811
- flags30 = import_args33.default.parse(process.argv);
37812
- projectRoot14 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
38646
+ flags32 = import_args35.default.parse(process.argv);
38647
+ projectRoot16 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
37813
38648
  SUMMARY_TIMEZONE2 = "Europe/Moscow";
37814
38649
  SUMMARY_TIMEZONE_LABEL2 = "MSK";
37815
38650
  escapeHtml6 = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
@@ -37896,7 +38731,7 @@ var init_signalsSummary = __esm({
37896
38731
  return lines.join("\n");
37897
38732
  };
37898
38733
  resolveSummaryConnectorName = async (value) => {
37899
- const connectorName = await (0, import_connectors18.resolveConnectorName)(value, projectRoot14);
38734
+ const connectorName = await (0, import_connectors18.resolveConnectorName)(value, projectRoot16);
37900
38735
  if (connectorName) {
37901
38736
  return connectorName;
37902
38737
  }
@@ -37961,7 +38796,7 @@ var init_signalsSummary = __esm({
37961
38796
  );
37962
38797
  const connectorFactory = await (0, import_connectors18.getConnectorCreatorByName)(
37963
38798
  connectorName,
37964
- projectRoot14
38799
+ projectRoot16
37965
38800
  );
37966
38801
  if (!connectorFactory) {
37967
38802
  throw new Error(`Connector "${connectorName}" is not registered`);
@@ -38314,12 +39149,12 @@ none`
38314
39149
  signalsSummary = async () => {
38315
39150
  const hours = Math.max(
38316
39151
  1,
38317
- Number.parseInt(String(flags30.hours ?? 24), 10) || 24
39152
+ Number.parseInt(String(flags32.hours ?? 24), 10) || 24
38318
39153
  );
38319
39154
  const endTime = Date.now();
38320
39155
  const startTime = endTime - hours * 60 * 60 * 1e3;
38321
39156
  const fallbackConnectorName = await resolveSummaryConnectorName(
38322
- flags30.connector
39157
+ flags32.connector
38323
39158
  );
38324
39159
  const [
38325
39160
  configuredStrategyNames,
@@ -38328,25 +39163,25 @@ none`
38328
39163
  trades,
38329
39164
  runtimeDeployments
38330
39165
  ] = await Promise.all([
38331
- (0, import_runtimeStrategyConfigs.loadRuntimeStrategyNames)(flags30.user),
38332
- loadRuntimeSignals(flags30.user, { startTime, endTime }),
38333
- loadRuntimeSignalEvaluationStatsBuckets(flags30.user),
38334
- loadRuntimeTrades(flags30.user),
38335
- (0, import_runtimeStrategies9.listRuntimeDeployments)({ userName: flags30.user, projectRoot: projectRoot14 })
39166
+ (0, import_runtimeStrategyConfigs.loadRuntimeStrategyNames)(flags32.user),
39167
+ loadRuntimeSignals(flags32.user, { startTime, endTime }),
39168
+ loadRuntimeSignalEvaluationStatsBuckets(flags32.user),
39169
+ loadRuntimeTrades(flags32.user),
39170
+ (0, import_runtimeStrategies9.listRuntimeDeployments)({ userName: flags32.user, projectRoot: projectRoot16 })
38336
39171
  ]);
38337
39172
  const {
38338
39173
  trades: syncedTrades,
38339
39174
  connectorNames,
38340
39175
  scopesCount
38341
39176
  } = await syncRuntimeTradeScopes({
38342
- userName: flags30.user,
39177
+ userName: flags32.user,
38343
39178
  startTime,
38344
39179
  endTime,
38345
39180
  fallbackConnectorName,
38346
39181
  trades,
38347
39182
  deployments: runtimeDeployments
38348
39183
  });
38349
- const activeTradeOrderIds = await loadRuntimeActiveTradeOrderIds(flags30.user);
39184
+ const activeTradeOrderIds = await loadRuntimeActiveTradeOrderIds(flags32.user);
38350
39185
  const windowSignals = signals2.filter(
38351
39186
  (signal) => signal.timestamp >= startTime && signal.timestamp < endTime
38352
39187
  );
@@ -38394,10 +39229,10 @@ none`
38394
39229
  windowClosedTrades.length,
38395
39230
  connectorNames.join(",") || fallbackConnectorName,
38396
39231
  scopesCount,
38397
- flags30.user
39232
+ flags32.user
38398
39233
  );
38399
- const debugAttachment = shouldAttachDebugReport(flags30.debugAttachment) ? await buildRuntimeDebugReportAttachment({
38400
- userName: flags30.user,
39234
+ const debugAttachment = shouldAttachDebugReport(flags32.debugAttachment) ? await buildRuntimeDebugReportAttachment({
39235
+ userName: flags32.user,
38401
39236
  startTime,
38402
39237
  endTime,
38403
39238
  signals: debugSignals,
@@ -38405,7 +39240,7 @@ none`
38405
39240
  trades: windowTrades
38406
39241
  }) : null;
38407
39242
  const signalsAttachment = buildSignalsSummaryAttachment({
38408
- userName: flags30.user,
39243
+ userName: flags32.user,
38409
39244
  endTime,
38410
39245
  content: signalsMessage
38411
39246
  });
@@ -38421,7 +39256,7 @@ none`
38421
39256
  signalsAttachment,
38422
39257
  ...debugAttachment ? [debugAttachment] : []
38423
39258
  ];
38424
- if (flags30.printOnly) {
39259
+ if (flags32.printOnly) {
38425
39260
  console.log(tradesMessageWithAttachmentSummary);
38426
39261
  console.log("");
38427
39262
  console.log(`Signals attachment: ${signalsAttachment.filename}`);
@@ -38434,20 +39269,20 @@ none`
38434
39269
  return;
38435
39270
  }
38436
39271
  await sendTelegramReport(tradesMessageWithAttachmentSummary, {
38437
- userName: flags30.user,
39272
+ userName: flags32.user,
38438
39273
  attachments
38439
39274
  });
38440
39275
  };
38441
- main44 = signalsSummary;
39276
+ main46 = signalsSummary;
38442
39277
  }
38443
39278
  });
38444
39279
 
38445
39280
  // src/scripts/test-ml.ts
38446
39281
  var test_ml_exports = {};
38447
39282
  __export(test_ml_exports, {
38448
- main: () => main45
39283
+ main: () => main47
38449
39284
  });
38450
- var import_config14, import_constants20, import_ml3, import_registry5, now, INTERVAL_MIN, CANDLES, makeSeries, makeCandles, buildTrendline, main45;
39285
+ var import_config14, import_constants20, import_ml3, import_registry5, now, INTERVAL_MIN, CANDLES, makeSeries, makeCandles, buildTrendline, main47;
38451
39286
  var init_test_ml = __esm({
38452
39287
  "src/scripts/test-ml.ts"() {
38453
39288
  "use strict";
@@ -38497,7 +39332,7 @@ var init_test_ml = __esm({
38497
39332
  { timestamp: entryTs - 2 * INTERVAL_MIN * 6e4, value: price * 0.995 }
38498
39333
  ]
38499
39334
  });
38500
- main45 = async () => {
39335
+ main47 = async () => {
38501
39336
  const defaultConfig = await (0, import_registry5.getStrategyDefaults)("TrendLine", process.cwd());
38502
39337
  if (!defaultConfig) {
38503
39338
  throw new Error(
@@ -38590,9 +39425,9 @@ var init_test_ml = __esm({
38590
39425
  // src/scripts/test.ts
38591
39426
  var test_exports = {};
38592
39427
  __export(test_exports, {
38593
- main: () => main46
39428
+ main: () => main48
38594
39429
  });
38595
- var import_config15, import_connectors19, getPositions, main46;
39430
+ var import_config15, import_connectors19, getPositions, main48;
38596
39431
  var init_test = __esm({
38597
39432
  "src/scripts/test.ts"() {
38598
39433
  "use strict";
@@ -38602,7 +39437,7 @@ var init_test = __esm({
38602
39437
  const res = await connector.getPositions();
38603
39438
  console.log("res", res);
38604
39439
  };
38605
- main46 = async () => {
39440
+ main48 = async () => {
38606
39441
  const byBitConnector = await import_connectors19.connectors.ByBit({
38607
39442
  userName: "root"
38608
39443
  });
@@ -38614,25 +39449,25 @@ var init_test = __esm({
38614
39449
  // src/scripts/user-add.ts
38615
39450
  var user_add_exports = {};
38616
39451
  __export(user_add_exports, {
38617
- main: () => main47
39452
+ main: () => main49
38618
39453
  });
38619
- var import_args34, import_chalk52, import_bcryptjs, import_redis22, flags31, main47;
39454
+ var import_args36, import_chalk54, import_bcryptjs, import_redis22, flags33, main49;
38620
39455
  var init_user_add = __esm({
38621
39456
  "src/scripts/user-add.ts"() {
38622
39457
  "use strict";
38623
- import_args34 = __toESM(require("args"));
38624
- import_chalk52 = __toESM(require("chalk"));
39458
+ import_args36 = __toESM(require("args"));
39459
+ import_chalk54 = __toESM(require("chalk"));
38625
39460
  import_bcryptjs = __toESM(require("bcryptjs"));
38626
39461
  import_redis22 = require("@tradejs/infra/redis");
38627
- import_args34.default.example("yarn user-add -u myname -p 123456", "Create or update user");
38628
- import_args34.default.option(["u", "user"], "Username", "");
38629
- import_args34.default.option(["p", "password"], "Password (plain text)", "");
38630
- flags31 = import_args34.default.parse(process.argv);
38631
- main47 = async () => {
38632
- const userName3 = String(flags31.user || "").trim();
38633
- const password = String(flags31.password || "");
39462
+ import_args36.default.example("yarn user-add -u myname -p 123456", "Create or update user");
39463
+ import_args36.default.option(["u", "user"], "Username", "");
39464
+ import_args36.default.option(["p", "password"], "Password (plain text)", "");
39465
+ flags33 = import_args36.default.parse(process.argv);
39466
+ main49 = async () => {
39467
+ const userName3 = String(flags33.user || "").trim();
39468
+ const password = String(flags33.password || "");
38634
39469
  if (!userName3 || !password) {
38635
- console.error(import_chalk52.default.red("Missing -U <user> or -P <password>"));
39470
+ console.error(import_chalk54.default.red("Missing -U <user> or -P <password>"));
38636
39471
  process.exit(1);
38637
39472
  }
38638
39473
  const passwordHash = await import_bcryptjs.default.hash(password, 10);
@@ -38646,7 +39481,7 @@ var init_user_add = __esm({
38646
39481
  await (0, import_redis22.setData)(import_redis22.redisKeys.user(userName3), next, {
38647
39482
  expire: 0
38648
39483
  });
38649
- console.log(import_chalk52.default.green(`User ${userName3} updated`));
39484
+ console.log(import_chalk54.default.green(`User ${userName3} updated`));
38650
39485
  process.exit(0);
38651
39486
  };
38652
39487
  }
@@ -38656,7 +39491,7 @@ var init_user_add = __esm({
38656
39491
  var cli_exports = {};
38657
39492
  __export(cli_exports, {
38658
39493
  cleanupCliResources: () => cleanupCliResources,
38659
- main: () => main48,
39494
+ main: () => main50,
38660
39495
  printUsage: () => printUsage3,
38661
39496
  runLoadedModule: () => runLoadedModule
38662
39497
  });
@@ -38698,6 +39533,8 @@ var scriptLoaders = {
38698
39533
  "research:core": () => Promise.resolve().then(() => (init_coreResearch(), coreResearch_exports)),
38699
39534
  results: () => Promise.resolve().then(() => (init_results(), results_exports)),
38700
39535
  "replay-runtime-evidence": () => Promise.resolve().then(() => (init_replayRuntimeEvidence(), replayRuntimeEvidence_exports)),
39536
+ "runtime-feedback-replay": () => Promise.resolve().then(() => (init_runtimeFeedbackReplay2(), runtimeFeedbackReplay_exports)),
39537
+ "runtime-feedback-sync": () => Promise.resolve().then(() => (init_runtimeFeedbackSync2(), runtimeFeedbackSync_exports)),
38701
39538
  "runtime-evidence": () => Promise.resolve().then(() => (init_runtimeEvidence(), runtimeEvidence_exports)),
38702
39539
  "runtime-evidence-sync": () => Promise.resolve().then(() => (init_runtimeEvidenceSync2(), runtimeEvidenceSync_exports)),
38703
39540
  "runtime-scorecard": () => Promise.resolve().then(() => (init_runtimeScorecard2(), runtimeScorecard_exports)),
@@ -38729,14 +39566,14 @@ var runLoadedModule = async (loaded) => {
38729
39566
  var cleanupCliResources = async () => {
38730
39567
  await Promise.allSettled([(0, import_redis23.closeRedisConnection)(), (0, import_client9.closeTimescalePool)()]);
38731
39568
  };
38732
- var main48 = async () => {
38733
- const [, scriptPath, command = "", ...args35] = process.argv;
39569
+ var main50 = async () => {
39570
+ const [, scriptPath, command = "", ...args37] = process.argv;
38734
39571
  const loader = scriptLoaders[command];
38735
39572
  if (!loader) {
38736
39573
  printUsage3();
38737
39574
  process.exit(command ? 1 : 0);
38738
39575
  }
38739
- const nextArgs = [...args35];
39576
+ const nextArgs = [...args37];
38740
39577
  if (command === "spread:ingest") {
38741
39578
  nextArgs.push("--provider", "binance_coinbase_spread");
38742
39579
  }
@@ -38749,7 +39586,7 @@ var main48 = async () => {
38749
39586
  }
38750
39587
  };
38751
39588
  if (require.main === module) {
38752
- main48().catch((error) => {
39589
+ main50().catch((error) => {
38753
39590
  console.error(error);
38754
39591
  process.exit(1);
38755
39592
  });