@tradejs/cli 3.1.28-beta.257 → 3.1.28-beta.258

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 projectRoot17 = import_node_path.default.resolve(
258
+ const projectRoot18 = 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: projectRoot17,
266
+ projectRoot: projectRoot18,
267
267
  ...sourceRepositoryRoot ? { sourceRepositoryRoot: import_node_path.default.resolve(sourceRepositoryRoot) } : {}
268
268
  };
269
269
  };
@@ -1967,32 +1967,32 @@ var init_commandOptions = __esm({
1967
1967
  (arg) => arg === `--${longName}` || arg.startsWith(`--${longName}=`) || (shortName ? arg === `-${shortName}` : false)
1968
1968
  );
1969
1969
  resolveAiPocketSearchCommandOptions = ({
1970
- flags: flags34,
1970
+ flags: flags35,
1971
1971
  argv: argv2
1972
1972
  }) => {
1973
- const outDir = String(flags34.outDir || "data/ai/export");
1974
- const strategyName = String(flags34.strategy || "").trim() || void 0;
1975
- const explicitFile = String(flags34.file || "").trim();
1976
- const skip = normalizeInt(flags34.skip, 0);
1977
- const minQuality = normalizeInt(flags34.minQuality, 4);
1978
- const sinceInput = parseTimestampFilter(flags34.since);
1979
- const untilTimestamp = parseTimestampFilter(flags34.until);
1980
- const trailingPeriodMs = parseTrailingPeriodMs(flags34.period);
1981
- const periodLabel = String(flags34.period || "").trim() || null;
1973
+ const outDir = String(flags35.outDir || "data/ai/export");
1974
+ const strategyName = String(flags35.strategy || "").trim() || void 0;
1975
+ const explicitFile = String(flags35.file || "").trim();
1976
+ const skip = normalizeInt(flags35.skip, 0);
1977
+ const minQuality = normalizeInt(flags35.minQuality, 4);
1978
+ const sinceInput = parseTimestampFilter(flags35.since);
1979
+ const untilTimestamp = parseTimestampFilter(flags35.until);
1980
+ const trailingPeriodMs = parseTrailingPeriodMs(flags35.period);
1981
+ const periodLabel = String(flags35.period || "").trim() || null;
1982
1982
  const hasDateFilter = trailingPeriodMs != null || sinceInput != null || untilTimestamp != null;
1983
1983
  const recent = resolveAiTrainRecentLimit({
1984
1984
  argv: argv2,
1985
- recentValue: flags34.recent,
1985
+ recentValue: flags35.recent,
1986
1986
  hasDateFilter
1987
1987
  });
1988
- const qualityThresholds = parseQualityThresholds(flags34.qualityThresholds);
1989
- const scope = String(flags34.scope || "all").trim().toLowerCase();
1988
+ const qualityThresholds = parseQualityThresholds(flags35.qualityThresholds);
1989
+ const scope = String(flags35.scope || "all").trim().toLowerCase();
1990
1990
  if (!["all", "approved", "rejected", "candidates"].includes(scope)) {
1991
1991
  throw new Error(
1992
1992
  `Unsupported --scope "${scope}". Use all, approved, rejected, or candidates.`
1993
1993
  );
1994
1994
  }
1995
- const direction = String(flags34.direction || "").trim().toUpperCase();
1995
+ const direction = String(flags35.direction || "").trim().toUpperCase();
1996
1996
  if (direction && !["LONG", "SHORT"].includes(direction)) {
1997
1997
  throw new Error(
1998
1998
  `Unsupported --direction "${direction}". Use LONG or SHORT.`
@@ -2003,14 +2003,14 @@ var init_commandOptions = __esm({
2003
2003
  "maxEventCountShare",
2004
2004
  "U"
2005
2005
  );
2006
- const maxDepth = normalizePositiveInt(flags34.maxDepth, 2);
2007
- const explicitMinSupport = hasCliOption2(argv2, "minSupport", "m") ? normalizePositiveInt(flags34.minSupport, 20) : void 0;
2006
+ const maxDepth = normalizePositiveInt(flags35.maxDepth, 2);
2007
+ const explicitMinSupport = hasCliOption2(argv2, "minSupport", "m") ? normalizePositiveInt(flags35.minSupport, 20) : void 0;
2008
2008
  const minProfitFactor = normalizeNonNegativeNumber(
2009
2009
  readAiPocketSearchCliOption({
2010
2010
  argv: argv2,
2011
2011
  longName: "minProfitFactor",
2012
2012
  shortName: "F"
2013
- }) ?? flags34.minProfitFactor,
2013
+ }) ?? flags35.minProfitFactor,
2014
2014
  1.2
2015
2015
  );
2016
2016
  const minWinRate = normalizeNonNegativeNumber(
@@ -2018,21 +2018,21 @@ var init_commandOptions = __esm({
2018
2018
  argv: argv2,
2019
2019
  longName: "minWinRate",
2020
2020
  shortName: "W"
2021
- }) ?? flags34.minWinRate,
2021
+ }) ?? flags35.minWinRate,
2022
2022
  0
2023
2023
  );
2024
2024
  const minTotalProfitValue = readAiPocketSearchCliOption({
2025
2025
  argv: argv2,
2026
2026
  longName: "minTotalProfit",
2027
2027
  shortName: "R"
2028
- }) ?? flags34.minTotalProfit;
2028
+ }) ?? flags35.minTotalProfit;
2029
2029
  const minTotalProfit = Number.isFinite(Number(minTotalProfitValue)) ? Number(minTotalProfitValue) : 0;
2030
2030
  const validationSplit = hasCliOption2(argv2, "validationSplit", "V") ? normalizeRatio(
2031
2031
  readAiPocketSearchCliOption({
2032
2032
  argv: argv2,
2033
2033
  longName: "validationSplit",
2034
2034
  shortName: "V"
2035
- }) ?? flags34.validationSplit,
2035
+ }) ?? flags35.validationSplit,
2036
2036
  0.25
2037
2037
  ) : 0.25;
2038
2038
  const testSplit = hasCliOption2(argv2, "testSplit", "T") ? normalizeRatio(
@@ -2040,10 +2040,10 @@ var init_commandOptions = __esm({
2040
2040
  argv: argv2,
2041
2041
  longName: "testSplit",
2042
2042
  shortName: "T"
2043
- }) ?? flags34.testSplit,
2043
+ }) ?? flags35.testSplit,
2044
2044
  0
2045
2045
  ) : 0;
2046
- const sealTest = Boolean(flags34.sealTest);
2046
+ const sealTest = Boolean(flags35.sealTest);
2047
2047
  if (sealTest && testSplit <= 0) {
2048
2048
  throw new Error("--sealTest requires a positive --testSplit");
2049
2049
  }
@@ -2052,7 +2052,7 @@ var init_commandOptions = __esm({
2052
2052
  argv: argv2,
2053
2053
  longName: "maxEventCountShare",
2054
2054
  shortName: "U"
2055
- }) ?? flags34.maxEventCountShare,
2055
+ }) ?? flags35.maxEventCountShare,
2056
2056
  0.25
2057
2057
  );
2058
2058
  const maxSymbolCountShare = normalizeUnitRatio(
@@ -2060,10 +2060,10 @@ var init_commandOptions = __esm({
2060
2060
  argv: argv2,
2061
2061
  longName: "maxSymbolCountShare",
2062
2062
  shortName: "Z"
2063
- }) ?? flags34.maxSymbolCountShare,
2063
+ }) ?? flags35.maxSymbolCountShare,
2064
2064
  0.5
2065
2065
  );
2066
- const objective = normalizeObjective(flags34.objective, scope);
2066
+ const objective = normalizeObjective(flags35.objective, scope);
2067
2067
  return {
2068
2068
  outDir,
2069
2069
  strategyName,
@@ -2083,36 +2083,36 @@ var init_commandOptions = __esm({
2083
2083
  minProfitFactor,
2084
2084
  minWinRate,
2085
2085
  minTotalProfit,
2086
- maxAtomicPredicates: normalizePositiveInt(flags34.maxAtomicPredicates, 180),
2087
- maxCombinations: normalizePositiveInt(flags34.maxCombinations, 6e4),
2086
+ maxAtomicPredicates: normalizePositiveInt(flags35.maxAtomicPredicates, 180),
2087
+ maxCombinations: normalizePositiveInt(flags35.maxCombinations, 6e4),
2088
2088
  validationSplit,
2089
2089
  testSplit,
2090
2090
  sealTest,
2091
- explicitMinValidationSupport: normalizeInt(flags34.minValidationSupport, 0),
2092
- explicitMinEvents: normalizeInt(flags34.minEvents, 0),
2093
- explicitMinValidationEvents: normalizeInt(flags34.minValidationEvents, 0),
2094
- maxBatch: normalizeInt(flags34.maxBatch, 5),
2091
+ explicitMinValidationSupport: normalizeInt(flags35.minValidationSupport, 0),
2092
+ explicitMinEvents: normalizeInt(flags35.minEvents, 0),
2093
+ explicitMinValidationEvents: normalizeInt(flags35.minValidationEvents, 0),
2094
+ maxBatch: normalizeInt(flags35.maxBatch, 5),
2095
2095
  maxEventCountShare,
2096
2096
  explicitMaxEventCountShare,
2097
2097
  maxSymbolCountShare,
2098
2098
  objective,
2099
- allowRiskRegression: Boolean(flags34.allowRiskRegression),
2100
- requireValidationEligibility: !Boolean(flags34.allowValidationRegression),
2101
- dedupeEquivalentSelections: Boolean(flags34.dedupeEquivalentSelections),
2102
- top: normalizePositiveInt(flags34.top, 30),
2103
- includeSymbol: Boolean(flags34.includeSymbol),
2104
- includeGateContext: Boolean(flags34.includeGateContext),
2105
- featureProfile: normalizeFeatureProfile(flags34.featureProfile),
2106
- featurePolicy: normalizeFeaturePolicy(flags34.featurePolicy),
2099
+ allowRiskRegression: Boolean(flags35.allowRiskRegression),
2100
+ requireValidationEligibility: !Boolean(flags35.allowValidationRegression),
2101
+ dedupeEquivalentSelections: Boolean(flags35.dedupeEquivalentSelections),
2102
+ top: normalizePositiveInt(flags35.top, 30),
2103
+ includeSymbol: Boolean(flags35.includeSymbol),
2104
+ includeGateContext: Boolean(flags35.includeGateContext),
2105
+ featureProfile: normalizeFeatureProfile(flags35.featureProfile),
2106
+ featurePolicy: normalizeFeaturePolicy(flags35.featurePolicy),
2107
2107
  excludeFeaturePattern: normalizeExcludeFeaturePattern(
2108
- flags34.excludeFeaturePattern
2108
+ flags35.excludeFeaturePattern
2109
2109
  ),
2110
- coverageMode: normalizeCoverageMode(flags34.coverageMode),
2111
- cadenceMode: normalizeCadenceMode(flags34.cadenceMode),
2112
- jsonOutput: Boolean(flags34.json),
2113
- outputPath: String(flags34.output || "").trim(),
2114
- reportDir: String(flags34.reportDir || "data/ai/output").trim(),
2115
- explicitReportFile: String(flags34.reportFile || "").trim()
2110
+ coverageMode: normalizeCoverageMode(flags35.coverageMode),
2111
+ cadenceMode: normalizeCadenceMode(flags35.cadenceMode),
2112
+ jsonOutput: Boolean(flags35.json),
2113
+ outputPath: String(flags35.output || "").trim(),
2114
+ reportDir: String(flags35.reportDir || "data/ai/output").trim(),
2115
+ explicitReportFile: String(flags35.reportFile || "").trim()
2116
2116
  };
2117
2117
  };
2118
2118
  }
@@ -2212,9 +2212,9 @@ var init_features = __esm({
2212
2212
  "targetsymbol",
2213
2213
  "universe"
2214
2214
  ]);
2215
- normalizeFeaturePath = (path44) => (Array.isArray(path44) ? path44 : path44.split(".")).filter(Boolean).map((segment) => segment.toLowerCase());
2216
- classifyAiPocketCoverageFeaturePath = (path44) => {
2217
- const segments = normalizeFeaturePath(path44);
2215
+ normalizeFeaturePath = (path45) => (Array.isArray(path45) ? path45 : path45.split(".")).filter(Boolean).map((segment) => segment.toLowerCase());
2216
+ classifyAiPocketCoverageFeaturePath = (path45) => {
2217
+ const segments = normalizeFeaturePath(path45);
2218
2218
  const normalizedPath = segments.join(".");
2219
2219
  if (segments.some(
2220
2220
  (segment) => segment.includes("cmc") || segment.includes("coinmarketcap")
@@ -2388,8 +2388,8 @@ var init_features = __esm({
2388
2388
  "volumeusd",
2389
2389
  "vwap"
2390
2390
  ]);
2391
- classifyAiPocketFeaturePath = (path44) => {
2392
- const segments = (Array.isArray(path44) ? path44 : path44.split(".")).filter(
2391
+ classifyAiPocketFeaturePath = (path45) => {
2392
+ const segments = (Array.isArray(path45) ? path45 : path45.split(".")).filter(
2393
2393
  Boolean
2394
2394
  );
2395
2395
  const normalized = segments.map((segment) => segment.toLowerCase());
@@ -2706,11 +2706,11 @@ var init_features = __esm({
2706
2706
  excludeFeaturePattern.source,
2707
2707
  excludeFeaturePattern.flags.replace(/[gy]/g, "")
2708
2708
  ) : void 0;
2709
- const isOperatorExcluded = (path44) => {
2710
- if (!exclusion?.test(path44)) {
2709
+ const isOperatorExcluded = (path45) => {
2710
+ if (!exclusion?.test(path45)) {
2711
2711
  return false;
2712
2712
  }
2713
- onFeatureExcluded?.({ path: path44, classification: "operator-excluded" });
2713
+ onFeatureExcluded?.({ path: path45, classification: "operator-excluded" });
2714
2714
  return true;
2715
2715
  };
2716
2716
  const signal = payload.signal ?? {};
@@ -6043,10 +6043,10 @@ var init_command = __esm({
6043
6043
  init_dataset();
6044
6044
  init_research();
6045
6045
  runAiPocketSearchCommand = async ({
6046
- flags: flags34
6046
+ flags: flags35
6047
6047
  }) => {
6048
6048
  const options = resolveAiPocketSearchCommandOptions({
6049
- flags: flags34,
6049
+ flags: flags35,
6050
6050
  argv: process.argv
6051
6051
  });
6052
6052
  const {
@@ -6958,11 +6958,11 @@ var init_strategyGateFingerprint = __esm({
6958
6958
  "@tradejs/core/strategies"
6959
6959
  ];
6960
6960
  resolveStrategyGateFingerprint = async ({
6961
- projectRoot: projectRoot17,
6961
+ projectRoot: projectRoot18,
6962
6962
  strategyName,
6963
6963
  gitSha
6964
6964
  }) => {
6965
- const projectManifestPath = import_node_path3.default.join(projectRoot17, "package.json");
6965
+ const projectManifestPath = import_node_path3.default.join(projectRoot18, "package.json");
6966
6966
  const projectExists = await import_promises6.default.access(projectManifestPath).then(() => true).catch(() => false);
6967
6967
  const requireFromProject = projectExists ? (0, import_node_module.createRequire)(projectManifestPath) : null;
6968
6968
  const candidates = requireFromProject ? await Promise.all(
@@ -7141,10 +7141,10 @@ var init_aiTrainResearch = __esm({
7141
7141
  };
7142
7142
  });
7143
7143
  };
7144
- getGitLineage = (projectRoot17) => {
7144
+ getGitLineage = (projectRoot18) => {
7145
7145
  try {
7146
7146
  const gitSha = (0, import_node_child_process2.execFileSync)("git", ["rev-parse", "HEAD"], {
7147
- cwd: projectRoot17,
7147
+ cwd: projectRoot18,
7148
7148
  encoding: "utf8",
7149
7149
  stdio: ["ignore", "pipe", "ignore"]
7150
7150
  }).trim();
@@ -7152,7 +7152,7 @@ var init_aiTrainResearch = __esm({
7152
7152
  "git",
7153
7153
  ["status", "--porcelain", "--untracked-files=no"],
7154
7154
  {
7155
- cwd: projectRoot17,
7155
+ cwd: projectRoot18,
7156
7156
  encoding: "utf8",
7157
7157
  stdio: ["ignore", "pipe", "ignore"]
7158
7158
  }
@@ -7163,16 +7163,16 @@ var init_aiTrainResearch = __esm({
7163
7163
  }
7164
7164
  };
7165
7165
  buildAiTrainLineage = async ({
7166
- projectRoot: projectRoot17,
7166
+ projectRoot: projectRoot18,
7167
7167
  strategyName,
7168
7168
  configIds,
7169
7169
  runContext,
7170
7170
  sourceSha256s = [],
7171
7171
  env = process.env
7172
7172
  }) => {
7173
- const { gitSha, gitDirty } = getGitLineage(projectRoot17);
7173
+ const { gitSha, gitDirty } = getGitLineage(projectRoot18);
7174
7174
  const gate = await resolveStrategyGateFingerprint({
7175
- projectRoot: projectRoot17,
7175
+ projectRoot: projectRoot18,
7176
7176
  strategyName,
7177
7177
  gitSha
7178
7178
  });
@@ -9203,12 +9203,12 @@ var init_binanceMarketContextBackfill = __esm({
9203
9203
  return rows;
9204
9204
  };
9205
9205
  getBinanceConnector = async ({
9206
- projectRoot: projectRoot17,
9206
+ projectRoot: projectRoot18,
9207
9207
  userName: userName3
9208
9208
  }) => {
9209
9209
  const creator = await (0, import_connectors2.getConnectorCreatorByName)(
9210
9210
  import_connectors.ConnectorNames.Binance,
9211
- projectRoot17
9211
+ projectRoot18
9212
9212
  );
9213
9213
  if (!creator) {
9214
9214
  throw new Error(
@@ -10755,27 +10755,27 @@ var init_coinMarketCapContextBackfill = __esm({
10755
10755
  totalCredits: 0,
10756
10756
  byPath: /* @__PURE__ */ new Map()
10757
10757
  });
10758
- getCoinMarketCapPathLabel = (path44) => {
10759
- if (path44.includes("global-metrics")) return "global";
10760
- if (path44.includes("cryptocurrency/quotes")) return "reference";
10761
- if (path44.includes("exchange/quotes")) return "exchangeLiquidity";
10762
- if (path44.includes("fear-and-greed")) return "fearGreed";
10763
- if (path44.includes("cmc100")) return "cmc100";
10764
- if (path44.includes("cmc20")) return "cmc20";
10765
- return path44;
10766
- };
10767
- recordCoinMarketCapFetchStats = (stats, path44, creditCount) => {
10758
+ getCoinMarketCapPathLabel = (path45) => {
10759
+ if (path45.includes("global-metrics")) return "global";
10760
+ if (path45.includes("cryptocurrency/quotes")) return "reference";
10761
+ if (path45.includes("exchange/quotes")) return "exchangeLiquidity";
10762
+ if (path45.includes("fear-and-greed")) return "fearGreed";
10763
+ if (path45.includes("cmc100")) return "cmc100";
10764
+ if (path45.includes("cmc20")) return "cmc20";
10765
+ return path45;
10766
+ };
10767
+ recordCoinMarketCapFetchStats = (stats, path45, creditCount) => {
10768
10768
  if (!stats) return;
10769
- const existing = stats.byPath.get(path44) ?? { requests: 0, credits: 0 };
10769
+ const existing = stats.byPath.get(path45) ?? { requests: 0, credits: 0 };
10770
10770
  existing.requests += 1;
10771
10771
  existing.credits += creditCount ?? 0;
10772
10772
  stats.requests += 1;
10773
10773
  stats.totalCredits += creditCount ?? 0;
10774
- stats.byPath.set(path44, existing);
10774
+ stats.byPath.set(path45, existing);
10775
10775
  };
10776
10776
  formatCoinMarketCapFetchStats = (stats) => {
10777
10777
  const byPath = [...stats.byPath.entries()].map(
10778
- ([path44, item]) => `${getCoinMarketCapPathLabel(path44)}=${item.requests}req/${item.credits}cr`
10778
+ ([path45, item]) => `${getCoinMarketCapPathLabel(path45)}=${item.requests}req/${item.credits}cr`
10779
10779
  ).join(" ");
10780
10780
  return `apiRequests=${stats.requests} apiCredits=${stats.totalCredits}${byPath ? ` ${byPath}` : ""}`;
10781
10781
  };
@@ -12533,7 +12533,7 @@ var init_historyPrepare = __esm({
12533
12533
  connectorName,
12534
12534
  marketConnector,
12535
12535
  userName: userName3,
12536
- projectRoot: projectRoot17,
12536
+ projectRoot: projectRoot18,
12537
12537
  shouldUseDedicatedReferences,
12538
12538
  requireDedicatedReferences = false,
12539
12539
  warn
@@ -12545,8 +12545,8 @@ var init_historyPrepare = __esm({
12545
12545
  };
12546
12546
  }
12547
12547
  const [binanceFactory, coinbaseFactory] = await Promise.all([
12548
- (0, import_connectors4.getConnectorCreatorByName)(import_connectors3.ConnectorNames.Binance, projectRoot17),
12549
- (0, import_connectors4.getConnectorCreatorByName)(import_connectors3.ConnectorNames.Coinbase, projectRoot17)
12548
+ (0, import_connectors4.getConnectorCreatorByName)(import_connectors3.ConnectorNames.Binance, projectRoot18),
12549
+ (0, import_connectors4.getConnectorCreatorByName)(import_connectors3.ConnectorNames.Coinbase, projectRoot18)
12550
12550
  ]);
12551
12551
  const binance = binanceFactory ? await binanceFactory({ userName: userName3 }) : marketConnector;
12552
12552
  if (!binanceFactory) {
@@ -12804,9 +12804,9 @@ var init_runEnvironment = __esm({
12804
12804
  };
12805
12805
  resolveRunConnectorName = async ({
12806
12806
  value,
12807
- projectRoot: projectRoot17
12807
+ projectRoot: projectRoot18
12808
12808
  }) => {
12809
- const connectorName = await (0, import_connectors5.resolveConnectorName)(value, projectRoot17);
12809
+ const connectorName = await (0, import_connectors5.resolveConnectorName)(value, projectRoot18);
12810
12810
  if (connectorName) {
12811
12811
  return connectorName;
12812
12812
  }
@@ -12831,12 +12831,12 @@ var init_runEnvironment = __esm({
12831
12831
  };
12832
12832
  loadDeploymentReplayStrategies = async ({
12833
12833
  userName: userName3,
12834
- projectRoot: projectRoot17,
12834
+ projectRoot: projectRoot18,
12835
12835
  deploymentId
12836
12836
  }) => {
12837
12837
  const [deployment, runtimeStrategies] = await Promise.all([
12838
- (0, import_runtimeStrategies.getRuntimeDeployment)({ userName: userName3, projectRoot: projectRoot17, deploymentId }),
12839
- (0, import_runtimeStrategies.loadResolvedRuntimeStrategies)({ userName: userName3, projectRoot: projectRoot17, deploymentId })
12838
+ (0, import_runtimeStrategies.getRuntimeDeployment)({ userName: userName3, projectRoot: projectRoot18, deploymentId }),
12839
+ (0, import_runtimeStrategies.loadResolvedRuntimeStrategies)({ userName: userName3, projectRoot: projectRoot18, deploymentId })
12840
12840
  ]);
12841
12841
  if (!deployment) {
12842
12842
  throw new Error(`Runtime deployment not found: ${deploymentId}`);
@@ -12885,7 +12885,7 @@ var init_runEnvironment = __esm({
12885
12885
  endTime,
12886
12886
  cacheOnly,
12887
12887
  interval: interval4,
12888
- projectRoot: projectRoot17,
12888
+ projectRoot: projectRoot18,
12889
12889
  universe = "crypto",
12890
12890
  accountId,
12891
12891
  deploymentId,
@@ -12895,11 +12895,11 @@ var init_runEnvironment = __esm({
12895
12895
  }) => {
12896
12896
  const connectorName = await resolveRunConnectorName({
12897
12897
  value: connector,
12898
- projectRoot: projectRoot17
12898
+ projectRoot: projectRoot18
12899
12899
  });
12900
12900
  const connectorFactory = await (0, import_connectors5.getConnectorCreatorByName)(
12901
12901
  connectorName,
12902
- projectRoot17
12902
+ projectRoot18
12903
12903
  );
12904
12904
  if (!connectorFactory) {
12905
12905
  throw new Error(`Connector "${connectorName}" is not registered`);
@@ -12966,7 +12966,7 @@ var init_runEnvironment = __esm({
12966
12966
  connectorName,
12967
12967
  marketConnector,
12968
12968
  userName: userName3,
12969
- projectRoot: projectRoot17,
12969
+ projectRoot: projectRoot18,
12970
12970
  shouldUseDedicatedReferences: universe === "crypto",
12971
12971
  requireDedicatedReferences: universe === "crypto",
12972
12972
  warn: (message) => console.log(import_chalk12.default.yellow(message))
@@ -15063,12 +15063,12 @@ var init_runtimeEvidenceDeployment = __esm({
15063
15063
  });
15064
15064
  resolveRuntimeEvidenceDeploymentSnapshot = async ({
15065
15065
  userName: userName3,
15066
- projectRoot: projectRoot17,
15066
+ projectRoot: projectRoot18,
15067
15067
  deploymentId
15068
15068
  }) => {
15069
15069
  const [deployment, strategies] = await Promise.all([
15070
- (0, import_runtimeStrategies3.getRuntimeDeployment)({ userName: userName3, projectRoot: projectRoot17, deploymentId }),
15071
- (0, import_runtimeStrategies3.loadResolvedRuntimeStrategies)({ userName: userName3, projectRoot: projectRoot17, deploymentId })
15070
+ (0, import_runtimeStrategies3.getRuntimeDeployment)({ userName: userName3, projectRoot: projectRoot18, deploymentId }),
15071
+ (0, import_runtimeStrategies3.loadResolvedRuntimeStrategies)({ userName: userName3, projectRoot: projectRoot18, deploymentId })
15072
15072
  ]);
15073
15073
  if (!deployment) {
15074
15074
  throw new Error(`Runtime deployment not found: ${deploymentId}`);
@@ -15155,9 +15155,9 @@ var init_runtimeEvidenceSource = __esm({
15155
15155
  };
15156
15156
  readRuntimeEvidenceArtifact = async ({
15157
15157
  filePath,
15158
- projectRoot: projectRoot17
15158
+ projectRoot: projectRoot18
15159
15159
  }) => {
15160
- const resolvedPath = import_node_path5.default.resolve(projectRoot17, filePath);
15160
+ const resolvedPath = import_node_path5.default.resolve(projectRoot18, filePath);
15161
15161
  const root = asRecord2(
15162
15162
  JSON.parse(await import_promises9.default.readFile(resolvedPath, "utf8"))
15163
15163
  );
@@ -15256,11 +15256,11 @@ var init_runtimeEvidenceSource = __esm({
15256
15256
  };
15257
15257
  loadReplayRuntimeEvidenceSource = async ({
15258
15258
  filePath,
15259
- projectRoot: projectRoot17,
15259
+ projectRoot: projectRoot18,
15260
15260
  expectedUserName,
15261
15261
  expectedWindow
15262
15262
  }) => {
15263
- const { resolvedPath, runtime, userName: userName3, startTime, endTime, deployment } = await readRuntimeEvidenceArtifact({ filePath, projectRoot: projectRoot17 });
15263
+ const { resolvedPath, runtime, userName: userName3, startTime, endTime, deployment } = await readRuntimeEvidenceArtifact({ filePath, projectRoot: projectRoot18 });
15264
15264
  if (!userName3 || userName3 !== expectedUserName) {
15265
15265
  throw new Error(
15266
15266
  `Runtime evidence user mismatch: expected=${expectedUserName}, actual=${userName3 || "missing"}`
@@ -15993,7 +15993,7 @@ var init_historicalSignalsReplayPreparation = __esm({
15993
15993
  prepareHistoricalReplay = async (context, adapters) => {
15994
15994
  const {
15995
15995
  userName: userName3,
15996
- projectRoot: projectRoot17,
15996
+ projectRoot: projectRoot18,
15997
15997
  preparedRun,
15998
15998
  interval: interval4,
15999
15999
  connectorName,
@@ -16047,7 +16047,7 @@ var init_historicalSignalsReplayPreparation = __esm({
16047
16047
  interval: interval4
16048
16048
  });
16049
16049
  const runtimeLineage = await adapters.buildLineage({
16050
- projectRoot: projectRoot17,
16050
+ projectRoot: projectRoot18,
16051
16051
  strategyName: strategy.strategyName,
16052
16052
  strategyRevision: strategy.strategyRevision,
16053
16053
  deploymentCompositionId: strategy.deploymentCompositionId,
@@ -20110,7 +20110,7 @@ var init_outputReport = __esm({
20110
20110
  ) : "_No replay lineage records._";
20111
20111
  };
20112
20112
  writeReplayOutputReport = async ({
20113
- projectRoot: projectRoot17,
20113
+ projectRoot: projectRoot18,
20114
20114
  timestamp,
20115
20115
  replayKey,
20116
20116
  userName: userName3,
@@ -20123,7 +20123,7 @@ var init_outputReport = __esm({
20123
20123
  strategySnapshot,
20124
20124
  runtimeComparison
20125
20125
  }) => {
20126
- const outputDir = import_node_path7.default.resolve(projectRoot17, "data/replay/output");
20126
+ const outputDir = import_node_path7.default.resolve(projectRoot18, "data/replay/output");
20127
20127
  await import_promises10.default.mkdir(outputDir, { recursive: true });
20128
20128
  const perTradeAnalysis = buildPerTradeAnalysis(runtimeComparison);
20129
20129
  const report = {
@@ -20416,14 +20416,14 @@ var init_portfolioReport = __esm({
20416
20416
  )
20417
20417
  ].join("\n");
20418
20418
  writePortfolioReport = async ({
20419
- projectRoot: projectRoot17,
20419
+ projectRoot: projectRoot18,
20420
20420
  timestamp,
20421
20421
  replayResult,
20422
20422
  window,
20423
20423
  lineage,
20424
20424
  command
20425
20425
  }) => {
20426
- const outputDir = import_node_path8.default.resolve(projectRoot17, "data/replay/output");
20426
+ const outputDir = import_node_path8.default.resolve(projectRoot18, "data/replay/output");
20427
20427
  await import_promises11.default.mkdir(outputDir, { recursive: true });
20428
20428
  const trades = replayResult.strategies.flatMap(
20429
20429
  (strategy) => tradesFromPositionLog(strategy.strategyName, strategy.positionLog)
@@ -21122,10 +21122,10 @@ var init_binanceBreadthUniversesUpdate = __esm({
21122
21122
  flags6 = import_args7.default.parse(process.argv);
21123
21123
  BINANCE_BREADTH_UNIVERSES_RELATIVE_PATH = "packages/node/src/config/binanceBreadthUniverses.json";
21124
21124
  main7 = async () => {
21125
- const projectRoot17 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
21125
+ const projectRoot18 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
21126
21126
  const connectorCreator = await (0, import_connectors8.getConnectorCreatorByName)(
21127
21127
  import_connectors7.ConnectorNames.Binance,
21128
- projectRoot17
21128
+ projectRoot18
21129
21129
  );
21130
21130
  if (!connectorCreator) {
21131
21131
  throw new Error("Binance connector is not registered");
@@ -21158,7 +21158,7 @@ var init_binanceBreadthUniversesUpdate = __esm({
21158
21158
  return snapshot;
21159
21159
  }
21160
21160
  const outputPath = import_node_path9.default.join(
21161
- projectRoot17,
21161
+ projectRoot18,
21162
21162
  BINANCE_BREADTH_UNIVERSES_RELATIVE_PATH
21163
21163
  );
21164
21164
  await import_promises12.default.writeFile(outputPath, serialized, "utf8");
@@ -21992,14 +21992,14 @@ var init_cleanTests = __esm({
21992
21992
  cleanUserTests = async (userName3) => {
21993
21993
  const testsPrefix = `users:${userName3}:tests:`;
21994
21994
  const testsCachePrefix = `users:${userName3}:cache:tests:`;
21995
- const projectRoot17 = process.env.PROJECT_CWD || process.cwd();
21995
+ const projectRoot18 = process.env.PROJECT_CWD || process.cwd();
21996
21996
  const persistedArtifactsDir = import_path7.default.relative(
21997
- projectRoot17,
21998
- (0, import_backtestArtifacts2.getPersistedBacktestArtifactsDirForUser)(userName3, projectRoot17)
21997
+ projectRoot18,
21998
+ (0, import_backtestArtifacts2.getPersistedBacktestArtifactsDirForUser)(userName3, projectRoot18)
21999
21999
  );
22000
22000
  const cacheArtifactsDir = import_path7.default.relative(
22001
- projectRoot17,
22002
- (0, import_backtestArtifacts2.getBacktestCacheArtifactsDirForUser)(userName3, projectRoot17)
22001
+ projectRoot18,
22002
+ (0, import_backtestArtifacts2.getBacktestCacheArtifactsDirForUser)(userName3, projectRoot18)
22003
22003
  );
22004
22004
  if (flags11.cache) {
22005
22005
  console.log(import_chalk25.default.yellow(`clean user cache: ${userName3}`));
@@ -22012,11 +22012,11 @@ var init_cleanTests = __esm({
22012
22012
  await (0, import_cli8.cleanRedis)(testsCachePrefix);
22013
22013
  await (0, import_cli8.cleanFiles)(persistedArtifactsDir);
22014
22014
  await (0, import_cli8.cleanFiles)(cacheArtifactsDir);
22015
- await import_promises13.default.rm(import_path7.default.join(projectRoot17, persistedArtifactsDir), {
22015
+ await import_promises13.default.rm(import_path7.default.join(projectRoot18, persistedArtifactsDir), {
22016
22016
  recursive: true,
22017
22017
  force: true
22018
22018
  });
22019
- await import_promises13.default.rm(import_path7.default.join(projectRoot17, cacheArtifactsDir), {
22019
+ await import_promises13.default.rm(import_path7.default.join(projectRoot18, cacheArtifactsDir), {
22020
22020
  recursive: true,
22021
22021
  force: true
22022
22022
  });
@@ -23853,8 +23853,8 @@ volumes:
23853
23853
  `${DEV_COMPOSE_FILE} not found in project root. Run "npx @tradejs/cli infra-init" first.`
23854
23854
  );
23855
23855
  };
23856
- runDockerCompose = (composePath, args37) => {
23857
- const result = (0, import_node_child_process3.spawnSync)("docker", ["compose", "-f", composePath, ...args37], {
23856
+ runDockerCompose = (composePath, args38) => {
23857
+ const result = (0, import_node_child_process3.spawnSync)("docker", ["compose", "-f", composePath, ...args38], {
23858
23858
  stdio: "inherit"
23859
23859
  });
23860
23860
  if (result.error) {
@@ -30166,11 +30166,11 @@ var init_coreResearch = __esm({
30166
30166
  if (!Number.isFinite(numeric)) throw new Error(`${name} is invalid: ${text}`);
30167
30167
  return numeric;
30168
30168
  };
30169
- readSymbols = async (argv2, projectRoot17) => {
30169
+ readSymbols = async (argv2, projectRoot18) => {
30170
30170
  const symbolsFile = valueAfter(argv2, "--symbolsFile");
30171
30171
  if (symbolsFile) {
30172
30172
  const parsed = JSON.parse(
30173
- await import_promises23.default.readFile(import_node_path18.default.resolve(projectRoot17, symbolsFile), "utf8")
30173
+ await import_promises23.default.readFile(import_node_path18.default.resolve(projectRoot18, symbolsFile), "utf8")
30174
30174
  );
30175
30175
  if (!Array.isArray(parsed) || parsed.some((symbol) => typeof symbol !== "string")) {
30176
30176
  throw new Error("--symbolsFile must contain a JSON string array");
@@ -30940,13 +30940,13 @@ var init_replayRuntimeEvidence = __esm({
30940
30940
  const parsed = Date.parse(raw);
30941
30941
  return Number.isFinite(parsed) ? parsed : null;
30942
30942
  };
30943
- resolveWindow = (flags34) => {
30944
- const endTime = toEpochMs2(flags34.endTime) ?? Date.now();
30943
+ resolveWindow = (flags35) => {
30944
+ const endTime = toEpochMs2(flags35.endTime) ?? Date.now();
30945
30945
  const hours = Math.max(
30946
30946
  1,
30947
- Number.parseInt(String(flags34.hours ?? 24), 10) || 24
30947
+ Number.parseInt(String(flags35.hours ?? 24), 10) || 24
30948
30948
  );
30949
- const startTime = toEpochMs2(flags34.startTime) ?? endTime - hours * 60 * 60 * 1e3;
30949
+ const startTime = toEpochMs2(flags35.startTime) ?? endTime - hours * 60 * 60 * 1e3;
30950
30950
  if (startTime >= endTime) {
30951
30951
  throw new Error(
30952
30952
  `Invalid window: startTime (${startTime}) must be less than endTime (${endTime})`
@@ -30955,7 +30955,7 @@ var init_replayRuntimeEvidence = __esm({
30955
30955
  return {
30956
30956
  startTime,
30957
30957
  endTime,
30958
- source: flags34.startTime != null || flags34.endTime != null ? "explicit" : "hours"
30958
+ source: flags35.startTime != null || flags35.endTime != null ? "explicit" : "hours"
30959
30959
  };
30960
30960
  };
30961
30961
  parseStrategyFilter = (value) => String(value ?? "").split(",").map((item) => item.trim()).filter(Boolean);
@@ -31157,9 +31157,9 @@ var init_replayRuntimeEvidence = __esm({
31157
31157
  strategies,
31158
31158
  userName: userName3,
31159
31159
  runtimeEvidenceFile,
31160
- projectRoot: projectRoot17
31160
+ projectRoot: projectRoot18
31161
31161
  }) => {
31162
- const runtimeEvidencePath = typeof runtimeEvidenceFile === "string" && runtimeEvidenceFile.trim() ? import_node_path19.default.resolve(projectRoot17, runtimeEvidenceFile.trim()) : null;
31162
+ const runtimeEvidencePath = typeof runtimeEvidenceFile === "string" && runtimeEvidenceFile.trim() ? import_node_path19.default.resolve(projectRoot18, runtimeEvidenceFile.trim()) : null;
31163
31163
  if (runtimeEvidencePath) {
31164
31164
  const artifact = JSON.parse(
31165
31165
  await import_promises24.default.readFile(runtimeEvidencePath, "utf8")
@@ -31193,23 +31193,23 @@ var init_replayRuntimeEvidence = __esm({
31193
31193
  };
31194
31194
  };
31195
31195
  replayRuntimeEvidence = async () => {
31196
- const flags34 = import_args26.default.parse(process.argv);
31197
- const projectRoot17 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
31198
- const userName3 = String(flags34.user ?? "root");
31199
- const { startTime, endTime, source } = resolveWindow(flags34);
31196
+ const flags35 = import_args26.default.parse(process.argv);
31197
+ const projectRoot18 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
31198
+ const userName3 = String(flags35.user ?? "root");
31199
+ const { startTime, endTime, source } = resolveWindow(flags35);
31200
31200
  const replay = await loadReplayResult({
31201
31201
  userName: userName3,
31202
- replayKey: typeof flags34.replayKey === "string" && flags34.replayKey.trim() ? flags34.replayKey.trim() : void 0
31202
+ replayKey: typeof flags35.replayKey === "string" && flags35.replayKey.trim() ? flags35.replayKey.trim() : void 0
31203
31203
  });
31204
- const explicitStrategies = parseStrategyFilter(flags34.strategy);
31204
+ const explicitStrategies = parseStrategyFilter(flags35.strategy);
31205
31205
  const strategies = explicitStrategies.length ? explicitStrategies : getReplayStrategies(replay.value);
31206
31206
  const runtime = await loadRuntimePayload({
31207
31207
  startTime,
31208
31208
  endTime,
31209
31209
  strategies,
31210
31210
  userName: userName3,
31211
- runtimeEvidenceFile: flags34.runtimeEvidence,
31212
- projectRoot: projectRoot17
31211
+ runtimeEvidenceFile: flags35.runtimeEvidence,
31212
+ projectRoot: projectRoot18
31213
31213
  });
31214
31214
  const replayValue = asRecord5(replay.value);
31215
31215
  const artifact = {
@@ -31248,7 +31248,7 @@ var init_replayRuntimeEvidence = __esm({
31248
31248
  },
31249
31249
  runtime: runtime.payload
31250
31250
  };
31251
- const outPath = import_node_path19.default.resolve(projectRoot17, String(flags34.out));
31251
+ const outPath = import_node_path19.default.resolve(projectRoot18, String(flags35.out));
31252
31252
  await import_promises24.default.mkdir(import_node_path19.default.dirname(outPath), { recursive: true });
31253
31253
  await import_promises24.default.writeFile(outPath, `${JSON.stringify(artifact, null, 2)}
31254
31254
  `, "utf8");
@@ -31523,7 +31523,7 @@ var init_runtimeEvidenceProducer = __esm({
31523
31523
  return producer;
31524
31524
  };
31525
31525
  resolveRuntimeEvidenceProducer = async ({
31526
- projectRoot: projectRoot17,
31526
+ projectRoot: projectRoot18,
31527
31527
  required: required4
31528
31528
  }) => {
31529
31529
  const projectSha = String(process.env.TRADEJS_PROJECT_SHA ?? "").trim();
@@ -31543,7 +31543,7 @@ var init_runtimeEvidenceProducer = __esm({
31543
31543
  "TRADEJS_PROJECT_IMAGE_DIGEST must be an immutable sha256 digest before publishing runtime evidence"
31544
31544
  );
31545
31545
  }
31546
- const manifestPath = import_node_path21.default.join(projectRoot17, "runtime-package-manifest.json");
31546
+ const manifestPath = import_node_path21.default.join(projectRoot18, "runtime-package-manifest.json");
31547
31547
  let manifest;
31548
31548
  try {
31549
31549
  manifest = await import_promises26.default.readFile(manifestPath);
@@ -32001,7 +32001,7 @@ $ ${[executable, ...command].join(" ")}
32001
32001
  runtimeEvidencePath,
32002
32002
  outDir,
32003
32003
  runId = `${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}-${process.pid}`,
32004
- projectRoot: projectRoot17,
32004
+ projectRoot: projectRoot18,
32005
32005
  env = process.env,
32006
32006
  executable = process.execPath,
32007
32007
  cliPath = process.argv[1]
@@ -32022,7 +32022,7 @@ $ ${[executable, ...command].join(" ")}
32022
32022
  runtimeEvidenceBundle.artifact.producer
32023
32023
  );
32024
32024
  const currentProducer = await resolveRuntimeEvidenceProducer({
32025
- projectRoot: projectRoot17,
32025
+ projectRoot: projectRoot18,
32026
32026
  required: true
32027
32027
  });
32028
32028
  if (!currentProducer || currentProducer.projectSha !== deployedProducer.projectSha || currentProducer.imageDigest !== deployedProducer.imageDigest || currentProducer.runtimePackageManifest.sha256 !== deployedProducer.runtimePackageManifest.sha256) {
@@ -32070,7 +32070,7 @@ $ ${[executable, ...command].join(" ")}
32070
32070
  await runLoggedCommand({
32071
32071
  executable,
32072
32072
  command,
32073
- cwd: projectRoot17,
32073
+ cwd: projectRoot18,
32074
32074
  env,
32075
32075
  logHandle
32076
32076
  });
@@ -32141,14 +32141,180 @@ var init_runtimeFeedbackReplay2 = __esm({
32141
32141
  }
32142
32142
  });
32143
32143
 
32144
+ // src/lib/runtimeFeedbackNotification.ts
32145
+ var isRecord4, asRecord7, asArray3, finiteNumber5, requiredTimestamp, escapeHtml5, formatMskDateTime2, formatConnectorName, sumRows, buildRuntimeFeedbackTelegramMessage, notifyRuntimeFeedbackBundle;
32146
+ var init_runtimeFeedbackNotification = __esm({
32147
+ "src/lib/runtimeFeedbackNotification.ts"() {
32148
+ "use strict";
32149
+ init_runtimeFeedbackArtifacts();
32150
+ init_telegramReports();
32151
+ isRecord4 = (value) => value != null && typeof value === "object" && !Array.isArray(value);
32152
+ asRecord7 = (value) => isRecord4(value) ? value : {};
32153
+ asArray3 = (value) => Array.isArray(value) ? value.map(asRecord7) : [];
32154
+ finiteNumber5 = (value, fallback = 0) => {
32155
+ const number = Number(value);
32156
+ return Number.isFinite(number) ? number : fallback;
32157
+ };
32158
+ requiredTimestamp = (value, field) => {
32159
+ const timestamp = Number(value);
32160
+ if (!Number.isFinite(timestamp)) {
32161
+ throw new Error(`Runtime feedback replay is missing ${field}`);
32162
+ }
32163
+ return timestamp;
32164
+ };
32165
+ escapeHtml5 = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
32166
+ formatMskDateTime2 = (timestamp) => new Intl.DateTimeFormat("ru-RU", {
32167
+ timeZone: "Europe/Moscow",
32168
+ year: "numeric",
32169
+ month: "2-digit",
32170
+ day: "2-digit",
32171
+ hour: "2-digit",
32172
+ minute: "2-digit",
32173
+ hour12: false
32174
+ }).format(new Date(timestamp));
32175
+ formatConnectorName = (value) => {
32176
+ const connectorName = String(value ?? "unknown").trim() || "unknown";
32177
+ return connectorName.toLowerCase() === "bybit" ? "ByBit" : connectorName;
32178
+ };
32179
+ sumRows = (rows, field) => rows.reduce((total, row) => total + finiteNumber5(row[field]), 0);
32180
+ buildRuntimeFeedbackTelegramMessage = (replayEvidence) => {
32181
+ if (replayEvidence.reportType !== "replay-runtime-evidence") {
32182
+ throw new Error("Invalid runtime feedback replay evidence payload");
32183
+ }
32184
+ const window = asRecord7(replayEvidence.window);
32185
+ const startTime = requiredTimestamp(window.startTime, "window.startTime");
32186
+ const endTime = requiredTimestamp(window.endTime, "window.endTime");
32187
+ const deployment = asRecord7(replayEvidence.deployment);
32188
+ const replay = asRecord7(replayEvidence.replay);
32189
+ if (!isRecord4(replay.runtimeComparison) || !isRecord4(replay.runtimeComparison.counts) || !Array.isArray(replay.runtimeComparison.rows) || !isRecord4(replay.runtimeComparison.lineage)) {
32190
+ throw new Error("Runtime feedback replay comparison is missing");
32191
+ }
32192
+ const comparison = asRecord7(replay.runtimeComparison);
32193
+ const comparisonCounts = asRecord7(comparison.counts);
32194
+ const runtimeCounts = asRecord7(asRecord7(replayEvidence.runtime).counts);
32195
+ const lineage = asRecord7(comparison.lineage);
32196
+ const rows = asArray3(comparison.rows);
32197
+ const matched = finiteNumber5(comparisonCounts.matched);
32198
+ const runtimeOnly = finiteNumber5(comparisonCounts.runtimeOnly);
32199
+ const backtestOnly = finiteNumber5(comparisonCounts.backtestOnly);
32200
+ const orderFailed = sumRows(rows, "orderFailed");
32201
+ const runtimeEntries = sumRows(rows, "runtimeTrades");
32202
+ const backtestEntries = sumRows(rows, "backtestEntries");
32203
+ const replayScopes = finiteNumber5(lineage.replayScopes);
32204
+ const comparableScopes = finiteNumber5(lineage.comparableScopes);
32205
+ const excludedRuntimeTrades = finiteNumber5(lineage.excludedRuntimeTrades);
32206
+ const issueRows = rows.filter(
32207
+ (row) => finiteNumber5(row.runtimeOnly) > 0 || finiteNumber5(row.backtestOnly) > 0 || finiteNumber5(row.orderFailed) > 0
32208
+ );
32209
+ const lines = [
32210
+ "\u{1F9EA} <b>TradeJS runtime parity</b>",
32211
+ "",
32212
+ "\u{1F552} <b>Window</b>",
32213
+ `<b>${escapeHtml5(formatMskDateTime2(startTime))} - ${escapeHtml5(formatMskDateTime2(endTime))} MSK</b>`,
32214
+ "",
32215
+ `\u{1F50C} Connector: <b>${escapeHtml5(formatConnectorName(deployment.connectorName ?? deployment.provider))}</b>`,
32216
+ "\u{1F9EC} Source: <b>verified runtime feedback</b>",
32217
+ `\u{1F4E6} Deployment: <b>${escapeHtml5(String(deployment.id ?? "unknown"))}</b>`,
32218
+ `\u{1F510} Composition: <code>${escapeHtml5(String(deployment.deploymentCompositionId ?? "unknown"))}</code>`,
32219
+ "",
32220
+ "\u{1F4CC} <b>Overview</b>",
32221
+ `\u2022 Runtime evidence: trades=<b>${finiteNumber5(runtimeCounts.trades)}</b>, signals=<b>${finiteNumber5(runtimeCounts.signals)}</b>, evaluations=<b>${finiteNumber5(runtimeCounts.evaluations)}</b>`,
32222
+ `\u2022 Comparable entries: runtime=<b>${runtimeEntries}</b> / backtest=<b>${backtestEntries}</b>`,
32223
+ `\u2022 Matched: <b>${matched}</b> / order failed: <b>${orderFailed}</b>`,
32224
+ `\u2022 Runtime only: <b>${runtimeOnly}</b> / Backtest only: <b>${backtestOnly}</b>`,
32225
+ `\u2022 Lineage scopes: <b>${comparableScopes} / ${replayScopes}</b>`
32226
+ ];
32227
+ if (excludedRuntimeTrades > 0) {
32228
+ lines.push(
32229
+ `\u2022 Excluded runtime trades outside comparable lineage: <b>${excludedRuntimeTrades}</b>`
32230
+ );
32231
+ }
32232
+ if (issueRows.length) {
32233
+ lines.push("", "\u{1F4CA} <b>Strategy issues</b>");
32234
+ for (const row of issueRows.slice(0, 10)) {
32235
+ const issues = [
32236
+ finiteNumber5(row.orderFailed) > 0 ? `orderFailed=${finiteNumber5(row.orderFailed)}` : null,
32237
+ finiteNumber5(row.runtimeOnly) > 0 ? `runtimeOnly=${finiteNumber5(row.runtimeOnly)}` : null,
32238
+ finiteNumber5(row.backtestOnly) > 0 ? `backtestOnly=${finiteNumber5(row.backtestOnly)}` : null
32239
+ ].filter((value) => value != null);
32240
+ lines.push(
32241
+ `\u2022 ${escapeHtml5(String(row.strategyName ?? "[unknown]"))}: ${issues.join(", ")}`
32242
+ );
32243
+ }
32244
+ if (issueRows.length > 10) {
32245
+ lines.push(`... <b>${issueRows.length - 10}</b> more`);
32246
+ }
32247
+ } else if (rows.length) {
32248
+ lines.push(
32249
+ "",
32250
+ `\u{1F4CA} <b>Strategies</b>: clean <b>${rows.length}</b> / total <b>${rows.length}</b>`
32251
+ );
32252
+ }
32253
+ return lines.join("\n");
32254
+ };
32255
+ notifyRuntimeFeedbackBundle = async ({
32256
+ bundleDir,
32257
+ send = sendTelegramReport
32258
+ }) => {
32259
+ const verified = await verifyRuntimeFeedbackReplayBundle(bundleDir);
32260
+ const message = buildRuntimeFeedbackTelegramMessage(verified.replayEvidence);
32261
+ await send(message, { userName: verified.manifest.userName });
32262
+ return {
32263
+ artifactId: verified.manifest.artifactId,
32264
+ userName: verified.manifest.userName,
32265
+ message
32266
+ };
32267
+ };
32268
+ }
32269
+ });
32270
+
32271
+ // src/scripts/runtimeFeedbackNotify.ts
32272
+ var runtimeFeedbackNotify_exports = {};
32273
+ __export(runtimeFeedbackNotify_exports, {
32274
+ main: () => main36,
32275
+ runtimeFeedbackNotify: () => runtimeFeedbackNotify
32276
+ });
32277
+ var import_node_path25, import_args28, import_chalk45, flags26, projectRoot10, runtimeFeedbackNotify, main36;
32278
+ var init_runtimeFeedbackNotify = __esm({
32279
+ "src/scripts/runtimeFeedbackNotify.ts"() {
32280
+ "use strict";
32281
+ import_node_path25 = __toESM(require("path"));
32282
+ import_args28 = __toESM(require("args"));
32283
+ import_chalk45 = __toESM(require("chalk"));
32284
+ init_runtimeFeedbackNotification();
32285
+ init_runtimeFeedbackArtifacts();
32286
+ import_args28.default.option("bundle", "Verified runtime feedback replay bundle directory");
32287
+ import_args28.default.option("dryRun", "Verify and print the message without sending it", false);
32288
+ flags26 = import_args28.default.parse(process.argv);
32289
+ projectRoot10 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
32290
+ runtimeFeedbackNotify = async () => {
32291
+ const bundle = String(flags26.bundle ?? "").trim();
32292
+ if (!bundle) {
32293
+ throw new Error("Provide --bundle for runtime feedback notification.");
32294
+ }
32295
+ const bundleDir = import_node_path25.default.resolve(projectRoot10, bundle);
32296
+ if (flags26.dryRun) {
32297
+ const verified = await verifyRuntimeFeedbackReplayBundle(bundleDir);
32298
+ console.log(buildRuntimeFeedbackTelegramMessage(verified.replayEvidence));
32299
+ return;
32300
+ }
32301
+ const result = await notifyRuntimeFeedbackBundle({ bundleDir });
32302
+ console.log(
32303
+ import_chalk45.default.green(`Runtime feedback notification sent: ${result.artifactId}`)
32304
+ );
32305
+ };
32306
+ main36 = runtimeFeedbackNotify;
32307
+ }
32308
+ });
32309
+
32144
32310
  // src/lib/runtimeEvidenceSync.ts
32145
- var import_node_child_process7, import_promises29, import_node_path25, import_node_util, execFileAsync, isExistingDestinationError2, safeSegment4, withTrailingSlash, dateParts2, buildRuntimeEvidenceRsyncArgs, receiptPath, compareBundles, listPendingRuntimeEvidenceBundles, markRuntimeEvidenceBundleProcessed, syncRuntimeEvidenceBundles;
32311
+ var import_node_child_process7, import_promises29, import_node_path26, import_node_util, execFileAsync, isExistingDestinationError2, safeSegment4, withTrailingSlash, dateParts2, buildRuntimeEvidenceRsyncArgs, receiptPath, compareBundles, listPendingRuntimeEvidenceBundles, markRuntimeEvidenceBundleProcessed, syncRuntimeEvidenceBundles;
32146
32312
  var init_runtimeEvidenceSync = __esm({
32147
32313
  "src/lib/runtimeEvidenceSync.ts"() {
32148
32314
  "use strict";
32149
32315
  import_node_child_process7 = require("child_process");
32150
32316
  import_promises29 = __toESM(require("fs/promises"));
32151
- import_node_path25 = __toESM(require("path"));
32317
+ import_node_path26 = __toESM(require("path"));
32152
32318
  import_node_util = require("util");
32153
32319
  init_runtimeEvidenceArtifacts();
32154
32320
  init_runtimeEvidenceDeployment();
@@ -32182,15 +32348,15 @@ var init_runtimeEvidenceSync = __esm({
32182
32348
  withTrailingSlash(source),
32183
32349
  withTrailingSlash(destination)
32184
32350
  ];
32185
- receiptPath = (receiptsRoot, artifactId) => import_node_path25.default.join(receiptsRoot, `${safeSegment4(artifactId, "artifact")}.json`);
32351
+ receiptPath = (receiptsRoot, artifactId) => import_node_path26.default.join(receiptsRoot, `${safeSegment4(artifactId, "artifact")}.json`);
32186
32352
  compareBundles = (left, right) => left.manifest.window.endTime - right.manifest.window.endTime || left.manifest.createdAt - right.manifest.createdAt;
32187
32353
  listPendingRuntimeEvidenceBundles = async ({
32188
32354
  evidenceRoot,
32189
32355
  deploymentId
32190
32356
  }) => {
32191
32357
  const safeDeploymentId = safeSegment4(deploymentId, "production");
32192
- const artifactsRoot = import_node_path25.default.join(evidenceRoot, "artifacts", safeDeploymentId);
32193
- const receiptsRoot = import_node_path25.default.join(evidenceRoot, "receipts", safeDeploymentId);
32358
+ const artifactsRoot = import_node_path26.default.join(evidenceRoot, "artifacts", safeDeploymentId);
32359
+ const receiptsRoot = import_node_path26.default.join(evidenceRoot, "receipts", safeDeploymentId);
32194
32360
  const bundles = await discoverRuntimeEvidenceBundles(artifactsRoot);
32195
32361
  const pending = [];
32196
32362
  for (const bundleDir of bundles) {
@@ -32221,7 +32387,7 @@ var init_runtimeEvidenceSync = __esm({
32221
32387
  `Artifact deployment mismatch: expected ${safeDeploymentId}, received ${verified.manifest.deploymentId}`
32222
32388
  );
32223
32389
  }
32224
- const receiptsRoot = import_node_path25.default.join(evidenceRoot, "receipts", safeDeploymentId);
32390
+ const receiptsRoot = import_node_path26.default.join(evidenceRoot, "receipts", safeDeploymentId);
32225
32391
  const finalPath = receiptPath(receiptsRoot, verified.manifest.artifactId);
32226
32392
  const temporaryPath = `${finalPath}.tmp-${process.pid}`;
32227
32393
  const receipt = {
@@ -32249,16 +32415,16 @@ var init_runtimeEvidenceSync = __esm({
32249
32415
  source,
32250
32416
  evidenceRoot,
32251
32417
  deploymentId,
32252
- runRsync = async (args37) => {
32253
- const result = await execFileAsync("rsync", args37, {
32418
+ runRsync = async (args38) => {
32419
+ const result = await execFileAsync("rsync", args38, {
32254
32420
  maxBuffer: 10 * 1024 * 1024
32255
32421
  });
32256
32422
  return { stdout: result.stdout, stderr: result.stderr };
32257
32423
  }
32258
32424
  }) => {
32259
32425
  const safeDeploymentId = safeSegment4(deploymentId, "production");
32260
- const inboxRoot = import_node_path25.default.join(evidenceRoot, "inbox", safeDeploymentId);
32261
- const artifactsRoot = import_node_path25.default.join(evidenceRoot, "artifacts", safeDeploymentId);
32426
+ const inboxRoot = import_node_path26.default.join(evidenceRoot, "inbox", safeDeploymentId);
32427
+ const artifactsRoot = import_node_path26.default.join(evidenceRoot, "artifacts", safeDeploymentId);
32262
32428
  await Promise.all([
32263
32429
  import_promises29.default.mkdir(inboxRoot, { recursive: true }),
32264
32430
  import_promises29.default.mkdir(artifactsRoot, { recursive: true })
@@ -32278,12 +32444,12 @@ var init_runtimeEvidenceSync = __esm({
32278
32444
  );
32279
32445
  }
32280
32446
  assertCurrentRuntimeEvidenceArtifact(verified.artifact);
32281
- const destinationDir = import_node_path25.default.join(
32447
+ const destinationDir = import_node_path26.default.join(
32282
32448
  artifactsRoot,
32283
32449
  ...dateParts2(verified.manifest.window.endTime),
32284
32450
  safeSegment4(verified.manifest.artifactId, "artifact")
32285
32451
  );
32286
- await import_promises29.default.mkdir(import_node_path25.default.dirname(destinationDir), { recursive: true });
32452
+ await import_promises29.default.mkdir(import_node_path26.default.dirname(destinationDir), { recursive: true });
32287
32453
  try {
32288
32454
  await import_promises29.default.rename(bundleDir, destinationDir);
32289
32455
  } catch (error) {
@@ -32314,13 +32480,13 @@ var init_runtimeEvidenceSync = __esm({
32314
32480
  });
32315
32481
 
32316
32482
  // src/lib/runtimeFeedbackSync.ts
32317
- var import_node_child_process8, import_promises30, import_node_path26, import_node_util2, execFileAsync2, isExistingDestinationError3, safeSegment5, dateParts3, syncRuntimeFeedbackReplayBundles;
32483
+ var import_node_child_process8, import_promises30, import_node_path27, import_node_util2, execFileAsync2, isExistingDestinationError3, safeSegment5, dateParts3, syncRuntimeFeedbackReplayBundles;
32318
32484
  var init_runtimeFeedbackSync = __esm({
32319
32485
  "src/lib/runtimeFeedbackSync.ts"() {
32320
32486
  "use strict";
32321
32487
  import_node_child_process8 = require("child_process");
32322
32488
  import_promises30 = __toESM(require("fs/promises"));
32323
- import_node_path26 = __toESM(require("path"));
32489
+ import_node_path27 = __toESM(require("path"));
32324
32490
  import_node_util2 = require("util");
32325
32491
  init_runtimeFeedbackArtifacts();
32326
32492
  init_runtimeEvidenceSync();
@@ -32345,16 +32511,16 @@ var init_runtimeFeedbackSync = __esm({
32345
32511
  source,
32346
32512
  feedbackRoot,
32347
32513
  deploymentId,
32348
- runRsync = async (args37) => {
32349
- const result = await execFileAsync2("rsync", args37, {
32514
+ runRsync = async (args38) => {
32515
+ const result = await execFileAsync2("rsync", args38, {
32350
32516
  maxBuffer: 10 * 1024 * 1024
32351
32517
  });
32352
32518
  return { stdout: result.stdout, stderr: result.stderr };
32353
32519
  }
32354
32520
  }) => {
32355
32521
  const safeDeploymentId = safeSegment5(deploymentId, "production");
32356
- const inboxRoot = import_node_path26.default.join(feedbackRoot, "inbox", safeDeploymentId);
32357
- const artifactsRoot = import_node_path26.default.join(feedbackRoot, "artifacts", safeDeploymentId);
32522
+ const inboxRoot = import_node_path27.default.join(feedbackRoot, "inbox", safeDeploymentId);
32523
+ const artifactsRoot = import_node_path27.default.join(feedbackRoot, "artifacts", safeDeploymentId);
32358
32524
  await Promise.all([
32359
32525
  import_promises30.default.mkdir(inboxRoot, { recursive: true }),
32360
32526
  import_promises30.default.mkdir(artifactsRoot, { recursive: true })
@@ -32373,13 +32539,13 @@ var init_runtimeFeedbackSync = __esm({
32373
32539
  `Runtime feedback deployment mismatch: expected ${safeDeploymentId}, received ${verified.manifest.deploymentId}`
32374
32540
  );
32375
32541
  }
32376
- const destinationDir = import_node_path26.default.join(
32542
+ const destinationDir = import_node_path27.default.join(
32377
32543
  artifactsRoot,
32378
32544
  ...dateParts3(verified.manifest.window.endTime),
32379
32545
  safeSegment5(verified.manifest.runtimeEvidence.artifactId, "artifact"),
32380
32546
  safeSegment5(verified.manifest.runId, "run")
32381
32547
  );
32382
- await import_promises30.default.mkdir(import_node_path26.default.dirname(destinationDir), { recursive: true });
32548
+ await import_promises30.default.mkdir(import_node_path27.default.dirname(destinationDir), { recursive: true });
32383
32549
  try {
32384
32550
  await import_promises30.default.rename(bundleDir, destinationDir);
32385
32551
  } catch (error) {
@@ -32407,49 +32573,49 @@ var init_runtimeFeedbackSync = __esm({
32407
32573
  // src/scripts/runtimeFeedbackSync.ts
32408
32574
  var runtimeFeedbackSync_exports = {};
32409
32575
  __export(runtimeFeedbackSync_exports, {
32410
- main: () => main36,
32576
+ main: () => main37,
32411
32577
  runtimeFeedbackSync: () => runtimeFeedbackSync
32412
32578
  });
32413
- var import_node_path27, import_args28, import_chalk45, flags26, projectRoot10, runtimeFeedbackSync, main36;
32579
+ var import_node_path28, import_args29, import_chalk46, flags27, projectRoot11, runtimeFeedbackSync, main37;
32414
32580
  var init_runtimeFeedbackSync2 = __esm({
32415
32581
  "src/scripts/runtimeFeedbackSync.ts"() {
32416
32582
  "use strict";
32417
- import_node_path27 = __toESM(require("path"));
32418
- import_args28 = __toESM(require("args"));
32419
- import_chalk45 = __toESM(require("chalk"));
32583
+ import_node_path28 = __toESM(require("path"));
32584
+ import_args29 = __toESM(require("args"));
32585
+ import_chalk46 = __toESM(require("chalk"));
32420
32586
  init_runtimeFeedbackSync();
32421
- import_args28.default.option(
32587
+ import_args29.default.option(
32422
32588
  "source",
32423
32589
  "Rsync source ending at the runtime feedback ready directory",
32424
32590
  process.env.RUNTIME_FEEDBACK_RSYNC_SOURCE
32425
32591
  );
32426
- import_args28.default.option(
32592
+ import_args29.default.option(
32427
32593
  "deployment",
32428
32594
  "Deployment id expected in runtime feedback manifests",
32429
32595
  process.env.RUNTIME_EVIDENCE_DEPLOYMENT_ID || "production"
32430
32596
  );
32431
- import_args28.default.option(
32597
+ import_args29.default.option(
32432
32598
  "dir",
32433
32599
  "Local runtime feedback storage root",
32434
32600
  process.env.RUNTIME_FEEDBACK_LOCAL_DIR || "data/runtime-feedback"
32435
32601
  );
32436
- flags26 = import_args28.default.parse(process.argv);
32437
- projectRoot10 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
32602
+ flags27 = import_args29.default.parse(process.argv);
32603
+ projectRoot11 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
32438
32604
  runtimeFeedbackSync = async () => {
32439
- const source = String(flags26.source ?? "").trim();
32605
+ const source = String(flags27.source ?? "").trim();
32440
32606
  if (!source) {
32441
32607
  throw new Error(
32442
32608
  "Provide --source or RUNTIME_FEEDBACK_RSYNC_SOURCE for runtime feedback sync."
32443
32609
  );
32444
32610
  }
32445
- const feedbackRoot = import_node_path27.default.resolve(projectRoot10, String(flags26.dir));
32611
+ const feedbackRoot = import_node_path28.default.resolve(projectRoot11, String(flags27.dir));
32446
32612
  const result = await syncRuntimeFeedbackReplayBundles({
32447
32613
  source,
32448
32614
  feedbackRoot,
32449
- deploymentId: String(flags26.deployment)
32615
+ deploymentId: String(flags27.deployment)
32450
32616
  });
32451
32617
  console.log(
32452
- import_chalk45.default.green(
32618
+ import_chalk46.default.green(
32453
32619
  `Runtime feedback sync completed: received=${result.received.length}`
32454
32620
  )
32455
32621
  );
@@ -32469,18 +32635,18 @@ var init_runtimeFeedbackSync2 = __esm({
32469
32635
  )
32470
32636
  );
32471
32637
  };
32472
- main36 = runtimeFeedbackSync;
32638
+ main37 = runtimeFeedbackSync;
32473
32639
  }
32474
32640
  });
32475
32641
 
32476
32642
  // src/lib/runtimeEvidenceCompositionSnapshots.ts
32477
- var import_node_crypto15, import_promises31, import_node_path28, SNAPSHOT_FILE, MANIFEST_FILE, COMPLETE_FILE, createRuntimeEvidenceCompositionSnapshotRecorder, isRecord4, sha2564, safeSegment6, isExistingDestinationError4, parseManifest3, verifyRuntimeEvidenceCompositionSnapshot, sameSnapshot, publishRuntimeEvidenceCompositionSnapshot, captureRuntimeEvidenceCompositionSnapshot, discoverRuntimeEvidenceCompositionSnapshots;
32643
+ var import_node_crypto15, import_promises31, import_node_path29, SNAPSHOT_FILE, MANIFEST_FILE, COMPLETE_FILE, createRuntimeEvidenceCompositionSnapshotRecorder, isRecord5, sha2564, safeSegment6, isExistingDestinationError4, parseManifest3, verifyRuntimeEvidenceCompositionSnapshot, sameSnapshot, publishRuntimeEvidenceCompositionSnapshot, captureRuntimeEvidenceCompositionSnapshot, discoverRuntimeEvidenceCompositionSnapshots;
32478
32644
  var init_runtimeEvidenceCompositionSnapshots = __esm({
32479
32645
  "src/lib/runtimeEvidenceCompositionSnapshots.ts"() {
32480
32646
  "use strict";
32481
32647
  import_node_crypto15 = require("crypto");
32482
32648
  import_promises31 = __toESM(require("fs/promises"));
32483
- import_node_path28 = __toESM(require("path"));
32649
+ import_node_path29 = __toESM(require("path"));
32484
32650
  init_runtimeEvidenceDeployment();
32485
32651
  init_runtimeEvidenceProducer();
32486
32652
  SNAPSHOT_FILE = "snapshot.json";
@@ -32500,7 +32666,7 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
32500
32666
  }
32501
32667
  };
32502
32668
  };
32503
- isRecord4 = (value) => value != null && typeof value === "object" && !Array.isArray(value);
32669
+ isRecord5 = (value) => value != null && typeof value === "object" && !Array.isArray(value);
32504
32670
  sha2564 = (value) => (0, import_node_crypto15.createHash)("sha256").update(value).digest("hex");
32505
32671
  safeSegment6 = (value, label) => {
32506
32672
  const normalized = value.trim();
@@ -32514,8 +32680,8 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
32514
32680
  return code === "EEXIST" || code === "ENOTEMPTY";
32515
32681
  };
32516
32682
  parseManifest3 = (value) => {
32517
- const manifest = isRecord4(value) ? value : null;
32518
- const payload = isRecord4(manifest?.payload) ? manifest.payload : null;
32683
+ const manifest = isRecord5(value) ? value : null;
32684
+ const payload = isRecord5(manifest?.payload) ? manifest.payload : null;
32519
32685
  if (manifest?.schemaVersion !== 1 || manifest.reportType !== "runtime-evidence-composition-snapshot" || typeof manifest.createdAt !== "number" || typeof manifest.userName !== "string" || typeof manifest.deploymentId !== "string" || typeof manifest.deploymentCompositionId !== "string" || payload?.file !== SNAPSHOT_FILE || typeof payload.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(payload.sha256) || typeof payload.bytes !== "number") {
32520
32686
  throw new Error("Invalid runtime evidence composition snapshot manifest");
32521
32687
  }
@@ -32523,9 +32689,9 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
32523
32689
  };
32524
32690
  verifyRuntimeEvidenceCompositionSnapshot = async (bundleDir) => {
32525
32691
  const [manifestText, payload, completeText] = await Promise.all([
32526
- import_promises31.default.readFile(import_node_path28.default.join(bundleDir, MANIFEST_FILE), "utf8"),
32527
- import_promises31.default.readFile(import_node_path28.default.join(bundleDir, SNAPSHOT_FILE)),
32528
- import_promises31.default.readFile(import_node_path28.default.join(bundleDir, COMPLETE_FILE), "utf8")
32692
+ import_promises31.default.readFile(import_node_path29.default.join(bundleDir, MANIFEST_FILE), "utf8"),
32693
+ import_promises31.default.readFile(import_node_path29.default.join(bundleDir, SNAPSHOT_FILE)),
32694
+ import_promises31.default.readFile(import_node_path29.default.join(bundleDir, COMPLETE_FILE), "utf8")
32529
32695
  ]);
32530
32696
  const manifest = parseManifest3(JSON.parse(manifestText));
32531
32697
  if (completeText.trim() !== manifest.deploymentCompositionId) {
@@ -32537,7 +32703,7 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
32537
32703
  );
32538
32704
  }
32539
32705
  const value = JSON.parse(payload.toString("utf8"));
32540
- const record = isRecord4(value) ? value : null;
32706
+ const record = isRecord5(value) ? value : null;
32541
32707
  if (record?.schemaVersion !== 1 || record.reportType !== "runtime-evidence-composition-snapshot" || record.userName !== manifest.userName) {
32542
32708
  throw new Error(
32543
32709
  `Invalid runtime evidence snapshot payload in ${bundleDir}`
@@ -32588,9 +32754,9 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
32588
32754
  bytes: Buffer.byteLength(payload)
32589
32755
  }
32590
32756
  };
32591
- const snapshotsRoot = import_node_path28.default.join(evidenceRoot, "snapshots", deploymentId);
32592
- const bundleDir = import_node_path28.default.join(snapshotsRoot, compositionId);
32593
- const temporaryDir = import_node_path28.default.join(
32757
+ const snapshotsRoot = import_node_path29.default.join(evidenceRoot, "snapshots", deploymentId);
32758
+ const bundleDir = import_node_path29.default.join(snapshotsRoot, compositionId);
32759
+ const temporaryDir = import_node_path29.default.join(
32594
32760
  evidenceRoot,
32595
32761
  "incoming",
32596
32762
  `snapshot-${compositionId}.tmp-${(0, import_node_crypto15.randomUUID)()}`
@@ -32598,16 +32764,16 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
32598
32764
  await import_promises31.default.mkdir(temporaryDir, { recursive: true });
32599
32765
  try {
32600
32766
  await Promise.all([
32601
- import_promises31.default.writeFile(import_node_path28.default.join(temporaryDir, SNAPSHOT_FILE), payload, "utf8"),
32767
+ import_promises31.default.writeFile(import_node_path29.default.join(temporaryDir, SNAPSHOT_FILE), payload, "utf8"),
32602
32768
  import_promises31.default.writeFile(
32603
- import_node_path28.default.join(temporaryDir, MANIFEST_FILE),
32769
+ import_node_path29.default.join(temporaryDir, MANIFEST_FILE),
32604
32770
  `${JSON.stringify(manifest, null, 2)}
32605
32771
  `,
32606
32772
  "utf8"
32607
32773
  )
32608
32774
  ]);
32609
32775
  await import_promises31.default.writeFile(
32610
- import_node_path28.default.join(temporaryDir, COMPLETE_FILE),
32776
+ import_node_path29.default.join(temporaryDir, COMPLETE_FILE),
32611
32777
  `${compositionId}
32612
32778
  `,
32613
32779
  "utf8"
@@ -32632,7 +32798,7 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
32632
32798
  return verified;
32633
32799
  };
32634
32800
  captureRuntimeEvidenceCompositionSnapshot = async ({
32635
- projectRoot: projectRoot17,
32801
+ projectRoot: projectRoot18,
32636
32802
  userName: userName3,
32637
32803
  deploymentId,
32638
32804
  expectedCompositionId
@@ -32640,10 +32806,10 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
32640
32806
  const [deployment, producer] = await Promise.all([
32641
32807
  resolveRuntimeEvidenceDeploymentSnapshot({
32642
32808
  userName: userName3,
32643
- projectRoot: projectRoot17,
32809
+ projectRoot: projectRoot18,
32644
32810
  deploymentId
32645
32811
  }),
32646
- resolveRuntimeEvidenceProducer({ projectRoot: projectRoot17, required: true })
32812
+ resolveRuntimeEvidenceProducer({ projectRoot: projectRoot18, required: true })
32647
32813
  ]);
32648
32814
  if (!producer) {
32649
32815
  throw new Error("Runtime evidence producer identity is required");
@@ -32654,14 +32820,14 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
32654
32820
  );
32655
32821
  }
32656
32822
  await publishRuntimeEvidenceCompositionSnapshot({
32657
- evidenceRoot: import_node_path28.default.join(projectRoot17, "data", "runtime-evidence"),
32823
+ evidenceRoot: import_node_path29.default.join(projectRoot18, "data", "runtime-evidence"),
32658
32824
  userName: userName3,
32659
32825
  deployment,
32660
32826
  producer
32661
32827
  });
32662
32828
  };
32663
32829
  discoverRuntimeEvidenceCompositionSnapshots = async (evidenceRoot) => {
32664
- const rootDir = import_node_path28.default.join(evidenceRoot, "snapshots");
32830
+ const rootDir = import_node_path29.default.join(evidenceRoot, "snapshots");
32665
32831
  const bundleDirs = [];
32666
32832
  let deployments;
32667
32833
  try {
@@ -32671,14 +32837,14 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
32671
32837
  throw error;
32672
32838
  }
32673
32839
  for (const deployment of deployments.filter((entry) => entry.isDirectory())) {
32674
- const deploymentDir = import_node_path28.default.join(rootDir, deployment.name);
32840
+ const deploymentDir = import_node_path29.default.join(rootDir, deployment.name);
32675
32841
  const compositions = await import_promises31.default.readdir(deploymentDir, {
32676
32842
  withFileTypes: true
32677
32843
  });
32678
32844
  bundleDirs.push(
32679
32845
  ...compositions.filter(
32680
32846
  (entry) => entry.isDirectory() && !entry.name.startsWith(".") && !entry.name.includes(".tmp-")
32681
- ).map((entry) => import_node_path28.default.join(deploymentDir, entry.name))
32847
+ ).map((entry) => import_node_path29.default.join(deploymentDir, entry.name))
32682
32848
  );
32683
32849
  }
32684
32850
  return Promise.all(
@@ -32847,52 +33013,52 @@ var init_runtimeEvidenceCompositions = __esm({
32847
33013
  // src/scripts/runtimeEvidence.ts
32848
33014
  var runtimeEvidence_exports = {};
32849
33015
  __export(runtimeEvidence_exports, {
32850
- main: () => main37,
33016
+ main: () => main38,
32851
33017
  runtimeEvidence: () => runtimeEvidence
32852
33018
  });
32853
- var import_promises32, import_node_path29, import_args29, import_chalk46, flags27, projectRoot11, toEpochMs3, resolveWindow2, parseStrategyFilter2, runtimeEvidence, main37;
33019
+ var import_promises32, import_node_path30, import_args30, import_chalk47, flags28, projectRoot12, toEpochMs3, resolveWindow2, parseStrategyFilter2, runtimeEvidence, main38;
32854
33020
  var init_runtimeEvidence = __esm({
32855
33021
  "src/scripts/runtimeEvidence.ts"() {
32856
33022
  "use strict";
32857
33023
  import_promises32 = __toESM(require("fs/promises"));
32858
- import_node_path29 = __toESM(require("path"));
32859
- import_args29 = __toESM(require("args"));
32860
- import_chalk46 = __toESM(require("chalk"));
33024
+ import_node_path30 = __toESM(require("path"));
33025
+ import_args30 = __toESM(require("args"));
33026
+ import_chalk47 = __toESM(require("chalk"));
32861
33027
  init_runtimeDebugEvidence();
32862
33028
  init_runtimeEvidenceArtifacts();
32863
33029
  init_runtimeEvidenceCompositions();
32864
33030
  init_runtimeLineage();
32865
33031
  init_runtimeEvidenceProducer();
32866
33032
  init_runtimeEvidenceDeployment();
32867
- import_args29.default.option(["u", "user"], "Use user config", "root");
32868
- import_args29.default.option(
33033
+ import_args30.default.option(["u", "user"], "Use user config", "root");
33034
+ import_args30.default.option(
32869
33035
  ["S", "startTime"],
32870
33036
  "Window start timestamp, seconds/ms, or ISO date"
32871
33037
  );
32872
- import_args29.default.option(["E", "endTime"], "Window end timestamp, seconds/ms, or ISO date");
32873
- import_args29.default.option(
33038
+ import_args30.default.option(["E", "endTime"], "Window end timestamp, seconds/ms, or ISO date");
33039
+ import_args30.default.option(
32874
33040
  ["H", "hours"],
32875
33041
  "Fallback window in hours when start/end are omitted",
32876
33042
  24
32877
33043
  );
32878
- import_args29.default.option(
33044
+ import_args30.default.option(
32879
33045
  "daily",
32880
33046
  "Use the latest complete 21:00 MSK to 21:00 MSK window",
32881
33047
  false
32882
33048
  );
32883
- import_args29.default.option(["s", "strategy"], "Strategy filter, comma-separated");
32884
- import_args29.default.option(["o", "out"], "Output JSON path", "output/runtime-evidence.json");
32885
- import_args29.default.option(
33049
+ import_args30.default.option(["s", "strategy"], "Strategy filter, comma-separated");
33050
+ import_args30.default.option(["o", "out"], "Output JSON path", "output/runtime-evidence.json");
33051
+ import_args30.default.option(
32886
33052
  "publishDir",
32887
33053
  "Publish an immutable bundle under <dir>/ready/<deployment>"
32888
33054
  );
32889
- import_args29.default.option(
33055
+ import_args30.default.option(
32890
33056
  "deployment",
32891
33057
  "Deployment id used by immutable evidence bundles",
32892
33058
  process.env.RUNTIME_EVIDENCE_DEPLOYMENT_ID || "production"
32893
33059
  );
32894
- flags27 = import_args29.default.parse(process.argv);
32895
- projectRoot11 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
33060
+ flags28 = import_args30.default.parse(process.argv);
33061
+ projectRoot12 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
32896
33062
  toEpochMs3 = (value) => {
32897
33063
  if (value == null || value === "") {
32898
33064
  return null;
@@ -32906,11 +33072,11 @@ var init_runtimeEvidence = __esm({
32906
33072
  return Number.isFinite(parsed) ? parsed : null;
32907
33073
  };
32908
33074
  resolveWindow2 = () => {
32909
- const explicitStartTime = toEpochMs3(flags27.startTime);
32910
- const explicitEndTime = toEpochMs3(flags27.endTime);
33075
+ const explicitStartTime = toEpochMs3(flags28.startTime);
33076
+ const explicitEndTime = toEpochMs3(flags28.endTime);
32911
33077
  const now2 = Date.now();
32912
33078
  const dailyEndTime = (() => {
32913
- if (!flags27.daily || explicitStartTime != null || explicitEndTime != null) {
33079
+ if (!flags28.daily || explicitStartTime != null || explicitEndTime != null) {
32914
33080
  return null;
32915
33081
  }
32916
33082
  const date = new Date(now2);
@@ -32925,7 +33091,7 @@ var init_runtimeEvidence = __esm({
32925
33091
  const endTime = explicitEndTime ?? dailyEndTime ?? now2;
32926
33092
  const hours = Math.max(
32927
33093
  1,
32928
- Number.parseInt(String(flags27.hours ?? 24), 10) || 24
33094
+ Number.parseInt(String(flags28.hours ?? 24), 10) || 24
32929
33095
  );
32930
33096
  const startTime = explicitStartTime ?? endTime - hours * 60 * 60 * 1e3;
32931
33097
  if (startTime >= endTime) {
@@ -32942,27 +33108,27 @@ var init_runtimeEvidence = __esm({
32942
33108
  parseStrategyFilter2 = (value) => String(value ?? "").split(",").map((item) => item.trim()).filter(Boolean);
32943
33109
  runtimeEvidence = async () => {
32944
33110
  const { startTime, endTime, source } = resolveWindow2();
32945
- const deploymentId = String(flags27.deployment);
32946
- const publishDir = String(flags27.publishDir ?? "").trim();
33111
+ const deploymentId = String(flags28.deployment);
33112
+ const publishDir = String(flags28.publishDir ?? "").trim();
32947
33113
  const producer = await resolveRuntimeEvidenceProducer({
32948
- projectRoot: projectRoot11,
33114
+ projectRoot: projectRoot12,
32949
33115
  required: Boolean(publishDir)
32950
33116
  });
32951
33117
  const deploymentSnapshot = await resolveRuntimeEvidenceDeploymentSnapshot({
32952
- userName: String(flags27.user),
32953
- projectRoot: projectRoot11,
33118
+ userName: String(flags28.user),
33119
+ projectRoot: projectRoot12,
32954
33120
  deploymentId
32955
33121
  });
32956
- const requestedStrategies = parseStrategyFilter2(flags27.strategy);
33122
+ const requestedStrategies = parseStrategyFilter2(flags28.strategy);
32957
33123
  const evidence = await collectRuntimeDebugEvidence({
32958
- userName: flags27.user,
33124
+ userName: flags28.user,
32959
33125
  startTime,
32960
33126
  endTime,
32961
33127
  strategies: requestedStrategies.length ? requestedStrategies : void 0,
32962
33128
  deploymentId
32963
33129
  });
32964
33130
  const snapshots = publishDir && producer ? await loadRuntimeEvidenceCompositionSnapshots({
32965
- publishRoot: import_node_path29.default.resolve(projectRoot11, publishDir),
33131
+ publishRoot: import_node_path30.default.resolve(projectRoot12, publishDir),
32966
33132
  currentDeployment: deploymentSnapshot,
32967
33133
  currentProducer: producer
32968
33134
  }) : /* @__PURE__ */ new Map([
@@ -32995,7 +33161,7 @@ var init_runtimeEvidence = __esm({
32995
33161
  (strategyName) => !requestedStrategies.length || requestedStrategies.includes(strategyName)
32996
33162
  );
32997
33163
  const runtime = buildRuntimeEvidenceReportPayload({
32998
- userName: flags27.user,
33164
+ userName: flags28.user,
32999
33165
  startTime,
33000
33166
  endTime,
33001
33167
  signals: composition.signals,
@@ -33014,7 +33180,7 @@ var init_runtimeEvidence = __esm({
33014
33180
  generatedAt: Date.now(),
33015
33181
  ...composition.producer ? { producer: composition.producer } : {},
33016
33182
  ...producer && composition.producer && composition.producer !== producer ? { collector: producer } : {},
33017
- userName: flags27.user,
33183
+ userName: flags28.user,
33018
33184
  window: {
33019
33185
  startTime,
33020
33186
  endTime,
@@ -33036,16 +33202,16 @@ var init_runtimeEvidence = __esm({
33036
33202
  throw new Error("Runtime evidence window has no versioned runtime rows");
33037
33203
  }
33038
33204
  const artifact = current.artifact;
33039
- const outPath = import_node_path29.default.resolve(projectRoot11, String(flags27.out));
33040
- await import_promises32.default.mkdir(import_node_path29.default.dirname(outPath), { recursive: true });
33205
+ const outPath = import_node_path30.default.resolve(projectRoot12, String(flags28.out));
33206
+ await import_promises32.default.mkdir(import_node_path30.default.dirname(outPath), { recursive: true });
33041
33207
  await import_promises32.default.writeFile(outPath, `${JSON.stringify(artifact, null, 2)}
33042
33208
  `, "utf8");
33043
33209
  const published = publishDir ? await Promise.all(
33044
33210
  artifacts.map(
33045
33211
  ({ artifact: artifact2, composition }) => publishRuntimeEvidenceBundle({
33046
- publishRoot: import_node_path29.default.resolve(projectRoot11, publishDir),
33212
+ publishRoot: import_node_path30.default.resolve(projectRoot12, publishDir),
33047
33213
  deploymentId,
33048
- userName: String(flags27.user),
33214
+ userName: String(flags28.user),
33049
33215
  startTime,
33050
33216
  endTime,
33051
33217
  artifact: artifact2,
@@ -33061,9 +33227,9 @@ var init_runtimeEvidence = __esm({
33061
33227
  })
33062
33228
  )
33063
33229
  ) : [];
33064
- console.log(import_chalk46.default.green(`Wrote ${outPath}`));
33230
+ console.log(import_chalk47.default.green(`Wrote ${outPath}`));
33065
33231
  for (const bundle of published) {
33066
- console.log(import_chalk46.default.green(`Published ${bundle.bundleDir}`));
33232
+ console.log(import_chalk47.default.green(`Published ${bundle.bundleDir}`));
33067
33233
  }
33068
33234
  console.log(
33069
33235
  JSON.stringify(
@@ -33079,56 +33245,56 @@ var init_runtimeEvidence = __esm({
33079
33245
  )
33080
33246
  );
33081
33247
  };
33082
- main37 = runtimeEvidence;
33248
+ main38 = runtimeEvidence;
33083
33249
  }
33084
33250
  });
33085
33251
 
33086
33252
  // src/scripts/runtimeEvidenceSync.ts
33087
33253
  var runtimeEvidenceSync_exports = {};
33088
33254
  __export(runtimeEvidenceSync_exports, {
33089
- main: () => main38,
33255
+ main: () => main39,
33090
33256
  runtimeEvidenceSync: () => runtimeEvidenceSync
33091
33257
  });
33092
- var import_node_path30, import_args30, import_chalk47, flags28, projectRoot12, runtimeEvidenceSync, main38;
33258
+ var import_node_path31, import_args31, import_chalk48, flags29, projectRoot13, runtimeEvidenceSync, main39;
33093
33259
  var init_runtimeEvidenceSync2 = __esm({
33094
33260
  "src/scripts/runtimeEvidenceSync.ts"() {
33095
33261
  "use strict";
33096
- import_node_path30 = __toESM(require("path"));
33097
- import_args30 = __toESM(require("args"));
33098
- import_chalk47 = __toESM(require("chalk"));
33262
+ import_node_path31 = __toESM(require("path"));
33263
+ import_args31 = __toESM(require("args"));
33264
+ import_chalk48 = __toESM(require("chalk"));
33099
33265
  init_runtimeEvidenceSync();
33100
- import_args30.default.option(
33266
+ import_args31.default.option(
33101
33267
  "source",
33102
33268
  "Rsync source ending at the deployment ready directory",
33103
33269
  process.env.RUNTIME_EVIDENCE_RSYNC_SOURCE
33104
33270
  );
33105
- import_args30.default.option(
33271
+ import_args31.default.option(
33106
33272
  "deployment",
33107
33273
  "Deployment id expected in artifact manifests",
33108
33274
  process.env.RUNTIME_EVIDENCE_DEPLOYMENT_ID || "production"
33109
33275
  );
33110
- import_args30.default.option(
33276
+ import_args31.default.option(
33111
33277
  "dir",
33112
33278
  "Local evidence storage root",
33113
33279
  process.env.RUNTIME_EVIDENCE_LOCAL_DIR || "data/runtime-evidence"
33114
33280
  );
33115
- flags28 = import_args30.default.parse(process.argv);
33116
- projectRoot12 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
33281
+ flags29 = import_args31.default.parse(process.argv);
33282
+ projectRoot13 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
33117
33283
  runtimeEvidenceSync = async () => {
33118
- const source = String(flags28.source ?? "").trim();
33284
+ const source = String(flags29.source ?? "").trim();
33119
33285
  if (!source) {
33120
33286
  throw new Error(
33121
33287
  "Provide --source or RUNTIME_EVIDENCE_RSYNC_SOURCE for runtime evidence sync."
33122
33288
  );
33123
33289
  }
33124
- const evidenceRoot = import_node_path30.default.resolve(projectRoot12, String(flags28.dir));
33290
+ const evidenceRoot = import_node_path31.default.resolve(projectRoot13, String(flags29.dir));
33125
33291
  const result = await syncRuntimeEvidenceBundles({
33126
33292
  source,
33127
33293
  evidenceRoot,
33128
- deploymentId: String(flags28.deployment)
33294
+ deploymentId: String(flags29.deployment)
33129
33295
  });
33130
33296
  console.log(
33131
- import_chalk47.default.green(
33297
+ import_chalk48.default.green(
33132
33298
  `Runtime evidence sync completed: received=${result.received.length} pending=${result.pending.length}`
33133
33299
  )
33134
33300
  );
@@ -33153,23 +33319,23 @@ var init_runtimeEvidenceSync2 = __esm({
33153
33319
  )
33154
33320
  );
33155
33321
  };
33156
- main38 = runtimeEvidenceSync;
33322
+ main39 = runtimeEvidenceSync;
33157
33323
  }
33158
33324
  });
33159
33325
 
33160
33326
  // src/lib/runtimeScorecard.ts
33161
- var asRecord7, asArray3, finiteNumber5, finiteString2, packageVersionMap, round3, unwrapRows2, runtimePayload, runtimeWindow, extractRuntimeRows, buildEmbeddedLineageScope, runtimeDeploymentBinding, belongsToRuntimeDeployment, belongsToStrategy, filterArtifactByStrategy, countBy2, resolveGateDecision, buildDistributions, buildDistributionDelta, sum2, tradeTimestamp, dedupeTrades, maxDrawdown2, buildRollingPerformance, getReplayComparison, replayCountsForStrategy, getProspectiveSummary, buildRuntimeScorecard, formatRuntimeScorecardMarkdown;
33327
+ var asRecord8, asArray4, finiteNumber6, finiteString2, packageVersionMap, round3, unwrapRows2, runtimePayload, runtimeWindow, extractRuntimeRows, buildEmbeddedLineageScope, runtimeDeploymentBinding, belongsToRuntimeDeployment, belongsToStrategy, filterArtifactByStrategy, countBy2, resolveGateDecision, buildDistributions, buildDistributionDelta, sum2, tradeTimestamp, dedupeTrades, maxDrawdown2, buildRollingPerformance, getReplayComparison, replayCountsForStrategy, getProspectiveSummary, buildRuntimeScorecard, formatRuntimeScorecardMarkdown;
33162
33328
  var init_runtimeScorecard = __esm({
33163
33329
  "src/lib/runtimeScorecard.ts"() {
33164
33330
  "use strict";
33165
33331
  init_runtimeLineage();
33166
33332
  init_runtimeEvidenceDeployment();
33167
- asRecord7 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
33168
- asArray3 = (value) => Array.isArray(value) ? value : [];
33169
- finiteNumber5 = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
33333
+ asRecord8 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
33334
+ asArray4 = (value) => Array.isArray(value) ? value : [];
33335
+ finiteNumber6 = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
33170
33336
  finiteString2 = (value) => typeof value === "string" && value.trim() ? value.trim() : null;
33171
33337
  packageVersionMap = (value) => {
33172
- const record = asRecord7(value);
33338
+ const record = asRecord8(value);
33173
33339
  if (!record || Object.keys(record).length === 0) return null;
33174
33340
  const entries = Object.entries(record);
33175
33341
  if (entries.some(
@@ -33182,14 +33348,14 @@ var init_runtimeScorecard = __esm({
33182
33348
  );
33183
33349
  };
33184
33350
  round3 = (value, decimals = 6) => Number(value.toFixed(decimals));
33185
- unwrapRows2 = (value, key) => asArray3(value).map((item) => asRecord7(asRecord7(item)?.[key]) ?? asRecord7(item)).filter((item) => item != null);
33351
+ unwrapRows2 = (value, key) => asArray4(value).map((item) => asRecord8(asRecord8(item)?.[key]) ?? asRecord8(item)).filter((item) => item != null);
33186
33352
  runtimePayload = (artifact) => {
33187
- const root = asRecord7(artifact) ?? {};
33188
- return asRecord7(root.runtime) ?? root;
33353
+ const root = asRecord8(artifact) ?? {};
33354
+ return asRecord8(root.runtime) ?? root;
33189
33355
  };
33190
33356
  runtimeWindow = (artifact) => {
33191
- const root = asRecord7(artifact) ?? {};
33192
- return asRecord7(root.window) ?? asRecord7(runtimePayload(artifact).window) ?? {};
33357
+ const root = asRecord8(artifact) ?? {};
33358
+ return asRecord8(root.window) ?? asRecord8(runtimePayload(artifact).window) ?? {};
33193
33359
  };
33194
33360
  extractRuntimeRows = (artifact) => {
33195
33361
  const runtime = runtimePayload(artifact);
@@ -33205,15 +33371,15 @@ var init_runtimeScorecard = __esm({
33205
33371
  rows,
33206
33372
  strategy
33207
33373
  }) => {
33208
- const deployment = asRecord7(asRecord7(artifact)?.deployment);
33209
- if (finiteNumber5(deployment?.schemaVersion) !== 2) return null;
33374
+ const deployment = asRecord8(asRecord8(artifact)?.deployment);
33375
+ if (finiteNumber6(deployment?.schemaVersion) !== 2) return null;
33210
33376
  const deploymentId = finiteString2(deployment?.id);
33211
33377
  const accountId = finiteString2(deployment?.accountId);
33212
33378
  const deploymentCompositionId = finiteString2(
33213
33379
  deployment?.deploymentCompositionId
33214
33380
  );
33215
33381
  if (!deploymentId || !accountId || !deploymentCompositionId) return null;
33216
- const snapshots = asArray3(deployment?.strategies).map(asRecord7).filter((item) => item != null).filter((item) => item.enabled === true).filter(
33382
+ const snapshots = asArray4(deployment?.strategies).map(asRecord8).filter((item) => item != null).filter((item) => item.enabled === true).filter(
33217
33383
  (item) => !strategy || finiteString2(item.strategyName) === strategy
33218
33384
  );
33219
33385
  const targetSeeds = snapshots.map((snapshot) => {
@@ -33251,14 +33417,14 @@ var init_runtimeScorecard = __esm({
33251
33417
  runtimeLineage: scope.lineage
33252
33418
  }))
33253
33419
  ];
33254
- const identityMatches = (lineage, target) => finiteNumber5(lineage?.schemaVersion) === 3 && finiteString2(lineage?.strategyRevision) === target.strategyRevision && finiteString2(lineage?.deploymentCompositionId) === target.deploymentCompositionId && finiteString2(lineage?.strategyPackageVersion) === target.strategyPackageVersion && JSON.stringify(packageVersionMap(lineage?.strategyDependencyVersions)) === JSON.stringify(target.strategyDependencyVersions) && finiteString2(lineage?.runtimePackageVersion) === target.runtimePackageVersion;
33420
+ const identityMatches = (lineage, target) => finiteNumber6(lineage?.schemaVersion) === 3 && finiteString2(lineage?.strategyRevision) === target.strategyRevision && finiteString2(lineage?.deploymentCompositionId) === target.deploymentCompositionId && finiteString2(lineage?.strategyPackageVersion) === target.strategyPackageVersion && JSON.stringify(packageVersionMap(lineage?.strategyDependencyVersions)) === JSON.stringify(target.strategyDependencyVersions) && finiteString2(lineage?.runtimePackageVersion) === target.runtimePackageVersion;
33255
33421
  const targets = /* @__PURE__ */ new Map();
33256
33422
  for (const seed of targetSeeds) {
33257
33423
  const matchingRows = lineageRows.filter(
33258
- (row) => finiteString2(row.strategy) === seed.strategyName && finiteString2(row.deploymentId) === deploymentId && finiteString2(row.accountId) === accountId && identityMatches(asRecord7(row.runtimeLineage), seed)
33424
+ (row) => finiteString2(row.strategy) === seed.strategyName && finiteString2(row.deploymentId) === deploymentId && finiteString2(row.accountId) === accountId && identityMatches(asRecord8(row.runtimeLineage), seed)
33259
33425
  );
33260
33426
  const riskValues = new Set(
33261
- matchingRows.map((row) => finiteNumber5(asRecord7(row.runtimeLineage)?.maxLossValue)).filter((value) => value != null)
33427
+ matchingRows.map((row) => finiteNumber6(asRecord8(row.runtimeLineage)?.maxLossValue)).filter((value) => value != null)
33262
33428
  );
33263
33429
  targets.set(seed.strategyName, {
33264
33430
  ...seed,
@@ -33270,9 +33436,9 @@ var init_runtimeScorecard = __esm({
33270
33436
  const belongs = (row) => {
33271
33437
  const strategyName = finiteString2(row.strategy);
33272
33438
  const target = strategyName ? targets.get(strategyName) : null;
33273
- const lineage = asRecord7(row.runtimeLineage);
33439
+ const lineage = asRecord8(row.runtimeLineage);
33274
33440
  return Boolean(
33275
- target && target.maxLossValue != null && identityMatches(lineage, target) && finiteNumber5(lineage?.maxLossValue) === target.maxLossValue
33441
+ target && target.maxLossValue != null && identityMatches(lineage, target) && finiteNumber6(lineage?.maxLossValue) === target.maxLossValue
33276
33442
  );
33277
33443
  };
33278
33444
  const targetValues = [...targets.values()];
@@ -33327,7 +33493,7 @@ var init_runtimeScorecard = __esm({
33327
33493
  };
33328
33494
  };
33329
33495
  runtimeDeploymentBinding = (artifact) => {
33330
- const deployment = asRecord7(asRecord7(artifact)?.deployment);
33496
+ const deployment = asRecord8(asRecord8(artifact)?.deployment);
33331
33497
  return {
33332
33498
  deploymentId: finiteString2(deployment?.id),
33333
33499
  accountId: finiteString2(deployment?.accountId)
@@ -33337,32 +33503,32 @@ var init_runtimeScorecard = __esm({
33337
33503
  belongsToStrategy = (row, strategy) => strategy == null || finiteString2(row.strategy) === strategy;
33338
33504
  filterArtifactByStrategy = (artifact, strategy) => {
33339
33505
  if (!strategy) return artifact;
33340
- const root = asRecord7(artifact) ?? {};
33506
+ const root = asRecord8(artifact) ?? {};
33341
33507
  const runtime = runtimePayload(artifact);
33342
33508
  return {
33343
33509
  ...root,
33344
33510
  runtime: {
33345
33511
  ...runtime,
33346
- evaluations: asArray3(runtime.evaluations).filter(
33512
+ evaluations: asArray4(runtime.evaluations).filter(
33347
33513
  (item) => belongsToStrategy(
33348
- asRecord7(asRecord7(item)?.evaluation) ?? asRecord7(item) ?? {},
33514
+ asRecord8(asRecord8(item)?.evaluation) ?? asRecord8(item) ?? {},
33349
33515
  strategy
33350
33516
  )
33351
33517
  ),
33352
- signals: asArray3(runtime.signals).filter(
33518
+ signals: asArray4(runtime.signals).filter(
33353
33519
  (item) => belongsToStrategy(
33354
- asRecord7(asRecord7(item)?.signal) ?? asRecord7(item) ?? {},
33520
+ asRecord8(asRecord8(item)?.signal) ?? asRecord8(item) ?? {},
33355
33521
  strategy
33356
33522
  )
33357
33523
  ),
33358
- trades: asArray3(runtime.trades).filter(
33524
+ trades: asArray4(runtime.trades).filter(
33359
33525
  (item) => belongsToStrategy(
33360
- asRecord7(asRecord7(item)?.trade) ?? asRecord7(item) ?? {},
33526
+ asRecord8(asRecord8(item)?.trade) ?? asRecord8(item) ?? {},
33361
33527
  strategy
33362
33528
  )
33363
33529
  ),
33364
- lineageScopes: asArray3(runtime.lineageScopes).filter(
33365
- (item) => belongsToStrategy(asRecord7(item) ?? {}, strategy)
33530
+ lineageScopes: asArray4(runtime.lineageScopes).filter(
33531
+ (item) => belongsToStrategy(asRecord8(item) ?? {}, strategy)
33366
33532
  )
33367
33533
  }
33368
33534
  };
@@ -33379,7 +33545,7 @@ var init_runtimeScorecard = __esm({
33379
33545
  );
33380
33546
  };
33381
33547
  resolveGateDecision = (evaluation) => {
33382
- const analysis = asRecord7(evaluation.aiAnalysis);
33548
+ const analysis = asRecord8(evaluation.aiAnalysis);
33383
33549
  const explicit = finiteString2(analysis?.gateDecision);
33384
33550
  if (explicit === "approved" || explicit === "rejected") {
33385
33551
  return { decision: explicit, source: "gate_decision" };
@@ -33410,7 +33576,7 @@ var init_runtimeScorecard = __esm({
33410
33576
  (signal) => finiteString2(signal.orderSkipReason)
33411
33577
  ),
33412
33578
  aiQuality: countBy2(candidates, (evaluation) => {
33413
- const quality = finiteNumber5(asRecord7(evaluation.aiAnalysis)?.quality);
33579
+ const quality = finiteNumber6(asRecord8(evaluation.aiAnalysis)?.quality);
33414
33580
  return quality == null ? null : String(quality);
33415
33581
  })
33416
33582
  };
@@ -33447,7 +33613,7 @@ var init_runtimeScorecard = __esm({
33447
33613
  );
33448
33614
  };
33449
33615
  sum2 = (values) => round3(values.reduce((total, value) => total + (value ?? 0), 0));
33450
- tradeTimestamp = (trade) => finiteNumber5(trade.exitTimestamp) ?? finiteNumber5(trade.lastSyncedAt) ?? finiteNumber5(trade.entryTimestamp) ?? 0;
33616
+ tradeTimestamp = (trade) => finiteNumber6(trade.exitTimestamp) ?? finiteNumber6(trade.lastSyncedAt) ?? finiteNumber6(trade.entryTimestamp) ?? 0;
33451
33617
  dedupeTrades = (artifacts) => {
33452
33618
  const tradesByOrderId = /* @__PURE__ */ new Map();
33453
33619
  for (const artifact of artifacts) {
@@ -33469,7 +33635,7 @@ var init_runtimeScorecard = __esm({
33469
33635
  for (const trade of trades.sort(
33470
33636
  (left, right) => tradeTimestamp(left) - tradeTimestamp(right)
33471
33637
  )) {
33472
- cumulative += finiteNumber5(trade.closedPnl) ?? 0;
33638
+ cumulative += finiteNumber6(trade.closedPnl) ?? 0;
33473
33639
  peak = Math.max(peak, cumulative);
33474
33640
  drawdown = Math.max(drawdown, peak - cumulative);
33475
33641
  }
@@ -33482,10 +33648,10 @@ var init_runtimeScorecard = __esm({
33482
33648
  }) => {
33483
33649
  const startTime = anchorTime - days * 24 * 60 * 60 * 1e3;
33484
33650
  const closed = trades.filter((trade) => {
33485
- const exitTimestamp = finiteNumber5(trade.exitTimestamp);
33651
+ const exitTimestamp = finiteNumber6(trade.exitTimestamp);
33486
33652
  return trade.status === "closed" && exitTimestamp != null && exitTimestamp >= startTime && exitTimestamp < anchorTime;
33487
33653
  });
33488
- const realizedPnl = sum2(closed.map((trade) => finiteNumber5(trade.closedPnl)));
33654
+ const realizedPnl = sum2(closed.map((trade) => finiteNumber6(trade.closedPnl)));
33489
33655
  return {
33490
33656
  days,
33491
33657
  closedTrades: closed.length,
@@ -33495,35 +33661,35 @@ var init_runtimeScorecard = __esm({
33495
33661
  };
33496
33662
  };
33497
33663
  getReplayComparison = (artifact) => {
33498
- const root = asRecord7(artifact) ?? {};
33499
- return asRecord7(asRecord7(root.replay)?.runtimeComparison) ?? null;
33664
+ const root = asRecord8(artifact) ?? {};
33665
+ return asRecord8(asRecord8(root.replay)?.runtimeComparison) ?? null;
33500
33666
  };
33501
33667
  replayCountsForStrategy = (replayComparison, strategy) => {
33502
33668
  if (strategy) {
33503
- const byStrategy = asRecord7(replayComparison?.byStrategy);
33504
- const strategyCounts = asRecord7(byStrategy?.[strategy]);
33669
+ const byStrategy = asRecord8(replayComparison?.byStrategy);
33670
+ const strategyCounts = asRecord8(byStrategy?.[strategy]);
33505
33671
  if (strategyCounts) {
33506
33672
  return {
33507
- matched: finiteNumber5(strategyCounts.matched) ?? 0,
33508
- backtestOnly: finiteNumber5(strategyCounts.backtestOnly) ?? 0,
33509
- runtimeOnly: finiteNumber5(strategyCounts.runtimeOnly) ?? 0
33673
+ matched: finiteNumber6(strategyCounts.matched) ?? 0,
33674
+ backtestOnly: finiteNumber6(strategyCounts.backtestOnly) ?? 0,
33675
+ runtimeOnly: finiteNumber6(strategyCounts.runtimeOnly) ?? 0
33510
33676
  };
33511
33677
  }
33512
33678
  }
33513
- const counts = asRecord7(replayComparison?.counts);
33679
+ const counts = asRecord8(replayComparison?.counts);
33514
33680
  return {
33515
- matched: finiteNumber5(counts?.matched) ?? 0,
33516
- backtestOnly: finiteNumber5(counts?.backtestOnly) ?? 0,
33517
- runtimeOnly: finiteNumber5(counts?.runtimeOnly) ?? 0
33681
+ matched: finiteNumber6(counts?.matched) ?? 0,
33682
+ backtestOnly: finiteNumber6(counts?.backtestOnly) ?? 0,
33683
+ runtimeOnly: finiteNumber6(counts?.runtimeOnly) ?? 0
33518
33684
  };
33519
33685
  };
33520
33686
  getProspectiveSummary = (artifact) => {
33521
- const root = asRecord7(artifact);
33687
+ const root = asRecord8(artifact);
33522
33688
  if (!root || root.reportType !== "strategy-prospective-evidence") return null;
33523
33689
  return {
33524
- rawCoreExpectancy: finiteNumber5(root.rawCoreExpectancy),
33525
- aiGateExpectancy: finiteNumber5(root.aiGateExpectancy),
33526
- regimeCoverage: finiteNumber5(root.regimeCoverage)
33690
+ rawCoreExpectancy: finiteNumber6(root.rawCoreExpectancy),
33691
+ aiGateExpectancy: finiteNumber6(root.aiGateExpectancy),
33692
+ regimeCoverage: finiteNumber6(root.regimeCoverage)
33527
33693
  };
33528
33694
  };
33529
33695
  buildRuntimeScorecard = ({
@@ -33567,8 +33733,8 @@ var init_runtimeScorecard = __esm({
33567
33733
  }
33568
33734
  const runtimeLineage = embeddedLineageScope.summary;
33569
33735
  const window = runtimeWindow(runtimeArtifact);
33570
- const startTime = finiteNumber5(window.startTime) ?? generatedAt - 864e5;
33571
- const endTime = finiteNumber5(window.endTime) ?? generatedAt;
33736
+ const startTime = finiteNumber6(window.startTime) ?? generatedAt - 864e5;
33737
+ const endTime = finiteNumber6(window.endTime) ?? generatedAt;
33572
33738
  const signalEvaluations = rows.evaluations.filter(
33573
33739
  (evaluation) => evaluation.status === "signal"
33574
33740
  );
@@ -33579,7 +33745,7 @@ var init_runtimeScorecard = __esm({
33579
33745
  (evaluation) => resolveGateDecision(evaluation)?.decision === "approved"
33580
33746
  ) : signalEvaluations;
33581
33747
  const gateComparisons = llmEligibleEvaluations.map((evaluation) => {
33582
- const analysis = asRecord7(evaluation.aiAnalysis);
33748
+ const analysis = asRecord8(evaluation.aiAnalysis);
33583
33749
  const gateDecision = resolveGateDecision(evaluation)?.decision ?? null;
33584
33750
  const llmDecision = finiteString2(analysis?.llmDecision);
33585
33751
  if (gateDecision !== "approved" && gateDecision !== "rejected" || llmDecision !== "approved" && llmDecision !== "rejected") {
@@ -33589,13 +33755,13 @@ var init_runtimeScorecard = __esm({
33589
33755
  }).filter(
33590
33756
  (comparison) => Boolean(comparison)
33591
33757
  );
33592
- const allocatorDecisions = signalEvaluations.map((evaluation) => asRecord7(evaluation.allocatorDecision)).filter((item) => item != null);
33593
- const riskDecisions = signalEvaluations.map((evaluation) => asRecord7(evaluation.riskDecision)).filter((item) => item != null);
33758
+ const allocatorDecisions = signalEvaluations.map((evaluation) => asRecord8(evaluation.allocatorDecision)).filter((item) => item != null);
33759
+ const riskDecisions = signalEvaluations.map((evaluation) => asRecord8(evaluation.riskDecision)).filter((item) => item != null);
33594
33760
  const orderAttempts = rows.signals.filter(
33595
33761
  (signal) => signal.orderStatus === "completed" || signal.orderStatus === "failed"
33596
33762
  );
33597
33763
  const currentClosedTrades = rows.trades.filter((trade) => {
33598
- const exitTimestamp = finiteNumber5(trade.exitTimestamp);
33764
+ const exitTimestamp = finiteNumber6(trade.exitTimestamp);
33599
33765
  return trade.status === "closed" && exitTimestamp != null && exitTimestamp >= startTime && exitTimestamp < endTime;
33600
33766
  });
33601
33767
  const replayComparison = getReplayComparison(replayEvidenceArtifact);
@@ -33605,12 +33771,12 @@ var init_runtimeScorecard = __esm({
33605
33771
  const runtimeOnly = replayCounts.runtimeOnly;
33606
33772
  const comparisonTotal = matched + backtestOnly + runtimeOnly;
33607
33773
  const parityRatio = comparisonTotal > 0 ? matched / comparisonTotal : null;
33608
- const lineage = asRecord7(replayComparison?.lineage);
33774
+ const lineage = asRecord8(replayComparison?.lineage);
33609
33775
  const lineageReason = finiteString2(lineage?.reason);
33610
- const calibrationRoot = asRecord7(calibrationArtifact) ?? {};
33611
- const calibrationSamples = asArray3(calibrationRoot.samples).map(asRecord7).filter((item) => item != null).filter((item) => !strategy || finiteString2(item.strategy) === strategy).filter((item) => embeddedLineageScope.belongs(item));
33776
+ const calibrationRoot = asRecord8(calibrationArtifact) ?? {};
33777
+ const calibrationSamples = asArray4(calibrationRoot.samples).map(asRecord8).filter((item) => item != null).filter((item) => !strategy || finiteString2(item.strategy) === strategy).filter((item) => embeddedLineageScope.belongs(item));
33612
33778
  const averageSampleMetric = (field) => {
33613
- const values = calibrationSamples.map((sample) => finiteNumber5(sample[field])).filter((value) => value != null);
33779
+ const values = calibrationSamples.map((sample) => finiteNumber6(sample[field])).filter((value) => value != null);
33614
33780
  return values.length ? round3(sum2(values) / values.length) : null;
33615
33781
  };
33616
33782
  const actualSlippageBps = averageSampleMetric("signalToFillAdverseBps");
@@ -33629,7 +33795,7 @@ var init_runtimeScorecard = __esm({
33629
33795
  (sample) => finiteString2(sample.telemetryQuality) === "full"
33630
33796
  ).length;
33631
33797
  const arrivalQuoteTrades = calibrationSamples.filter(
33632
- (sample) => finiteNumber5(sample.arrivalMid) != null
33798
+ (sample) => finiteNumber6(sample.arrivalMid) != null
33633
33799
  ).length;
33634
33800
  const arrivalQuoteCoverage = calibrationSamples.length ? round3(arrivalQuoteTrades / calibrationSamples.length) : null;
33635
33801
  const hasTelemetryQuality = calibrationSamples.some(
@@ -33652,10 +33818,10 @@ var init_runtimeScorecard = __esm({
33652
33818
  );
33653
33819
  const currentDistributions = buildDistributions(rows);
33654
33820
  const previousArtifact = scopedHistoryArtifacts.map((artifact) => ({ artifact, window: runtimeWindow(artifact) })).filter(({ window: candidateWindow }) => {
33655
- const candidateEndTime = finiteNumber5(candidateWindow.endTime);
33821
+ const candidateEndTime = finiteNumber6(candidateWindow.endTime);
33656
33822
  return candidateEndTime != null && candidateEndTime <= startTime;
33657
33823
  }).sort(
33658
- (left, right) => (finiteNumber5(right.window.endTime) ?? 0) - (finiteNumber5(left.window.endTime) ?? 0)
33824
+ (left, right) => (finiteNumber6(right.window.endTime) ?? 0) - (finiteNumber6(left.window.endTime) ?? 0)
33659
33825
  )[0];
33660
33826
  const previousDistributions = previousArtifact ? buildDistributions(extractRuntimeRows(previousArtifact.artifact)) : null;
33661
33827
  const rolling = [7, 30, 90].map(
@@ -33808,17 +33974,17 @@ var init_runtimeScorecard = __esm({
33808
33974
  realized: {
33809
33975
  pnl: sum2(
33810
33976
  comparableCurrentClosedTrades.map(
33811
- (trade) => finiteNumber5(trade.closedPnl)
33977
+ (trade) => finiteNumber6(trade.closedPnl)
33812
33978
  )
33813
33979
  ),
33814
33980
  fees: sum2(
33815
33981
  comparableCurrentClosedTrades.map(
33816
- (trade) => finiteNumber5(trade.totalFee)
33982
+ (trade) => finiteNumber6(trade.totalFee)
33817
33983
  )
33818
33984
  ),
33819
33985
  funding: sum2(
33820
33986
  comparableCurrentClosedTrades.map(
33821
- (trade) => finiteNumber5(trade.fundingFee)
33987
+ (trade) => finiteNumber6(trade.fundingFee)
33822
33988
  )
33823
33989
  )
33824
33990
  },
@@ -33867,8 +34033,8 @@ var init_runtimeScorecard = __esm({
33867
34033
  distributionChanges: {
33868
34034
  available: previousDistributions != null,
33869
34035
  baselineWindow: previousArtifact ? {
33870
- startTime: finiteNumber5(previousArtifact.window.startTime),
33871
- endTime: finiteNumber5(previousArtifact.window.endTime)
34036
+ startTime: finiteNumber6(previousArtifact.window.startTime),
34037
+ endTime: finiteNumber6(previousArtifact.window.endTime)
33872
34038
  } : null,
33873
34039
  metrics: previousDistributions ? Object.fromEntries(
33874
34040
  Object.entries(currentDistributions).map(([name, current]) => [
@@ -34355,13 +34521,13 @@ async function collectReleaseEvidenceReferences(references) {
34355
34521
  })
34356
34522
  );
34357
34523
  }
34358
- var import_node_crypto16, import_promises33, import_node_path31, 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, safeSegment7, 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;
34524
+ var import_node_crypto16, import_promises33, import_node_path32, import_types9, import_strategyReleaseEvidence2, SHA256_RE2, LINEAGE_FINGERPRINT_RE, STRATEGY_REVISION_RE, DEPLOYMENT_COMPOSITION_ID_RE, REQUIRED_LONG_WINDOWS, REQUIRED_DIAGNOSTIC_TERMINAL_WINDOWS, MIN_RECENT_DIRECTION_REPAIR_EVENTS, safeSegment7, compactTimestamp2, verifyFullPeriodChartArtifact, readVerifiedJsonArtifact, verifyResearchDecisionLineage, hasExactRuntimeTarget, deriveStrategyReleaseResearchDecision, canonicalStrategyReleaseJson, strategyReleaseSha256, assertFingerprint, assertLineageFingerprint, releaseReasons, deriveReleaseGates, verifyEvidenceComposition, createStrategyReleaseManifest, createStrategyReleaseEnvelope, verifyStrategyReleaseEnvelope, verifyStrategyEvidenceMarkerEnvelope, releaseMarkers, writeJsonAtomic2, publishStrategyRelease, publishStrategyLiveDiagnosis, finiteString3, finiteNumber7, finiteDirectionPolicy, uniqueStrings, incompleteEvidenceLineage, extractEvidenceLineage, verifyCompletedCoreResearchBundle;
34359
34525
  var init_strategyRelease = __esm({
34360
34526
  "src/lib/strategyRelease.ts"() {
34361
34527
  "use strict";
34362
34528
  import_node_crypto16 = require("crypto");
34363
34529
  import_promises33 = __toESM(require("fs/promises"));
34364
- import_node_path31 = __toESM(require("path"));
34530
+ import_node_path32 = __toESM(require("path"));
34365
34531
  import_types9 = require("@tradejs/types");
34366
34532
  import_strategyReleaseEvidence2 = require("@tradejs/infra/strategyReleaseEvidence");
34367
34533
  init_liveDiagnosis();
@@ -34380,7 +34546,7 @@ var init_strategyRelease = __esm({
34380
34546
  const artifact = input.chartArtifact;
34381
34547
  if (!artifact?.path || !SHA256_RE2.test(artifact.sha256)) return false;
34382
34548
  try {
34383
- const artifactPath = import_node_path31.default.resolve(artifact.path);
34549
+ const artifactPath = import_node_path32.default.resolve(artifact.path);
34384
34550
  if (await (0, import_strategyReleaseEvidence2.strategyEvidenceFileSha256)(artifactPath) !== artifact.sha256) {
34385
34551
  return false;
34386
34552
  }
@@ -34395,7 +34561,7 @@ var init_strategyRelease = __esm({
34395
34561
  readVerifiedJsonArtifact = async (artifact) => {
34396
34562
  if (!artifact?.path || !SHA256_RE2.test(artifact.sha256)) return null;
34397
34563
  try {
34398
- const artifactPath = import_node_path31.default.resolve(artifact.path);
34564
+ const artifactPath = import_node_path32.default.resolve(artifact.path);
34399
34565
  if (await (0, import_strategyReleaseEvidence2.strategyEvidenceFileSha256)(artifactPath) !== artifact.sha256) {
34400
34566
  return null;
34401
34567
  }
@@ -35058,7 +35224,7 @@ var init_strategyRelease = __esm({
35058
35224
  };
35059
35225
  writeJsonAtomic2 = async (filePath, value) => {
35060
35226
  const temporaryPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
35061
- await import_promises33.default.mkdir(import_node_path31.default.dirname(filePath), { recursive: true });
35227
+ await import_promises33.default.mkdir(import_node_path32.default.dirname(filePath), { recursive: true });
35062
35228
  await import_promises33.default.writeFile(
35063
35229
  temporaryPath,
35064
35230
  `${canonicalStrategyReleaseJson(value)}
@@ -35082,13 +35248,13 @@ var init_strategyRelease = __esm({
35082
35248
  path: entry.path
35083
35249
  }))
35084
35250
  });
35085
- const releasePath = import_node_path31.default.join(
35251
+ const releasePath = import_node_path32.default.join(
35086
35252
  rootDir,
35087
35253
  "releases",
35088
35254
  safeSegment7(manifest.strategy, "strategy"),
35089
35255
  `${manifest.releaseId}.json`
35090
35256
  );
35091
- const markerPath = import_node_path31.default.join(
35257
+ const markerPath = import_node_path32.default.join(
35092
35258
  rootDir,
35093
35259
  "markers",
35094
35260
  safeSegment7(manifest.strategy, "strategy"),
@@ -35168,13 +35334,13 @@ var init_strategyRelease = __esm({
35168
35334
  markers,
35169
35335
  sourceArtifacts
35170
35336
  });
35171
- const diagnosisPath = import_node_path31.default.join(
35337
+ const diagnosisPath = import_node_path32.default.join(
35172
35338
  rootDir,
35173
35339
  "diagnoses",
35174
35340
  safeSegment7(diagnosis.strategy, "strategy"),
35175
35341
  `${diagnosisId}.json`
35176
35342
  );
35177
- const markerPath = import_node_path31.default.join(
35343
+ const markerPath = import_node_path32.default.join(
35178
35344
  rootDir,
35179
35345
  "markers",
35180
35346
  safeSegment7(diagnosis.strategy, "strategy"),
@@ -35188,7 +35354,7 @@ var init_strategyRelease = __esm({
35188
35354
  return { diagnosisPath, markerPath, envelope, markerEnvelope };
35189
35355
  };
35190
35356
  finiteString3 = (value) => typeof value === "string" && value.trim() ? value.trim() : null;
35191
- finiteNumber6 = (value) => {
35357
+ finiteNumber7 = (value) => {
35192
35358
  const number = Number(value);
35193
35359
  return Number.isFinite(number) ? number : null;
35194
35360
  };
@@ -35235,7 +35401,7 @@ var init_strategyRelease = __esm({
35235
35401
  const maxLossValues = [
35236
35402
  ...new Set(
35237
35403
  selectedVariants.map(
35238
- (variant) => finiteNumber6(
35404
+ (variant) => finiteNumber7(
35239
35405
  nested(nested(variant.variant)?.resolvedConfig)?.MAX_LOSS_VALUE
35240
35406
  )
35241
35407
  ).filter((value) => value != null)
@@ -35285,7 +35451,7 @@ var init_strategyRelease = __esm({
35285
35451
  };
35286
35452
  const maxLossValues = [
35287
35453
  ...new Set(
35288
- replayLineages.map((entry) => finiteNumber6(entry.maxLossValue)).filter((value) => value != null)
35454
+ replayLineages.map((entry) => finiteNumber7(entry.maxLossValue)).filter((value) => value != null)
35289
35455
  )
35290
35456
  ];
35291
35457
  const dirtyValues = [
@@ -35329,7 +35495,7 @@ var init_strategyRelease = __esm({
35329
35495
  ];
35330
35496
  const maxLossValues = [
35331
35497
  ...new Set(
35332
- lineages.map((lineage) => finiteNumber6(lineage.maxLossValue)).filter((value) => value != null)
35498
+ lineages.map((lineage) => finiteNumber7(lineage.maxLossValue)).filter((value) => value != null)
35333
35499
  )
35334
35500
  ];
35335
35501
  return {
@@ -35364,9 +35530,9 @@ var init_strategyRelease = __esm({
35364
35530
  const specSha256 = finiteString3(artifact.specSha256);
35365
35531
  assert3(researchId != null, "core result researchId is required");
35366
35532
  assert3(specSha256 != null, "core result specSha256 is required");
35367
- const researchDir = import_node_path31.default.dirname(resultPath);
35368
- const manifestPath = import_node_path31.default.join(researchDir, "manifest.json");
35369
- const specPath = import_node_path31.default.join(researchDir, "spec.json");
35533
+ const researchDir = import_node_path32.default.dirname(resultPath);
35534
+ const manifestPath = import_node_path32.default.join(researchDir, "manifest.json");
35535
+ const specPath = import_node_path32.default.join(researchDir, "spec.json");
35370
35536
  const manifestBytes = await import_promises33.default.readFile(manifestPath).catch(() => null);
35371
35537
  const specBytes = await import_promises33.default.readFile(specPath).catch(() => null);
35372
35538
  assert3(
@@ -35384,7 +35550,7 @@ var init_strategyRelease = __esm({
35384
35550
  artifactHashes ?? {}
35385
35551
  )) {
35386
35552
  assert3(
35387
- !import_node_path31.default.isAbsolute(relativePath) && !relativePath.split(/[\\/]/).includes(".."),
35553
+ !import_node_path32.default.isAbsolute(relativePath) && !relativePath.split(/[\\/]/).includes(".."),
35388
35554
  `core bundle artifact ${relativePath} escapes its research directory`
35389
35555
  );
35390
35556
  assert3(
@@ -35392,7 +35558,7 @@ var init_strategyRelease = __esm({
35392
35558
  `core bundle artifact ${relativePath} has an invalid checksum`
35393
35559
  );
35394
35560
  const actualSha256 = await (0, import_strategyReleaseEvidence2.strategyEvidenceFileSha256)(
35395
- import_node_path31.default.join(researchDir, relativePath)
35561
+ import_node_path32.default.join(researchDir, relativePath)
35396
35562
  );
35397
35563
  assert3(
35398
35564
  actualSha256 === expectedSha256,
@@ -35406,86 +35572,86 @@ var init_strategyRelease = __esm({
35406
35572
  // src/scripts/runtimeScorecard.ts
35407
35573
  var runtimeScorecard_exports = {};
35408
35574
  __export(runtimeScorecard_exports, {
35409
- main: () => main39,
35575
+ main: () => main40,
35410
35576
  runtimeScorecard: () => runtimeScorecard
35411
35577
  });
35412
- var import_promises34, import_node_crypto17, import_node_path32, import_args31, import_chalk48, flags29, projectRoot13, resolveOptionalPath, readJson, assertReportType, sha256File2, loadHistoryArtifacts, runtimeScorecard, main39;
35578
+ var import_promises34, import_node_crypto17, import_node_path33, import_args32, import_chalk49, flags30, projectRoot14, resolveOptionalPath, readJson, assertReportType, sha256File2, loadHistoryArtifacts, runtimeScorecard, main40;
35413
35579
  var init_runtimeScorecard2 = __esm({
35414
35580
  "src/scripts/runtimeScorecard.ts"() {
35415
35581
  "use strict";
35416
35582
  import_promises34 = __toESM(require("fs/promises"));
35417
35583
  import_node_crypto17 = require("crypto");
35418
- import_node_path32 = __toESM(require("path"));
35419
- import_args31 = __toESM(require("args"));
35420
- import_chalk48 = __toESM(require("chalk"));
35584
+ import_node_path33 = __toESM(require("path"));
35585
+ import_args32 = __toESM(require("args"));
35586
+ import_chalk49 = __toESM(require("chalk"));
35421
35587
  init_runtimeEvidenceArtifacts();
35422
35588
  init_runtimeFeedbackArtifacts();
35423
35589
  init_runtimeEvidenceSync();
35424
35590
  init_runtimeScorecard();
35425
35591
  init_strategyRelease();
35426
- import_args31.default.option(["u", "runtimeEvidence"], "Verified runtime evidence JSON");
35427
- import_args31.default.option(["r", "replayEvidence"], "Replay runtime evidence JSON");
35428
- import_args31.default.option(["c", "calibration"], "Execution calibration JSON");
35429
- import_args31.default.option(
35592
+ import_args32.default.option(["u", "runtimeEvidence"], "Verified runtime evidence JSON");
35593
+ import_args32.default.option(["r", "replayEvidence"], "Replay runtime evidence JSON");
35594
+ import_args32.default.option(["c", "calibration"], "Execution calibration JSON");
35595
+ import_args32.default.option(
35430
35596
  ["q", "prospectiveEvidence"],
35431
35597
  "Verified prospective raw-core/gate/regime summary JSON"
35432
35598
  );
35433
- import_args31.default.option(["s", "strategy"], "Exact strategy to isolate in the scorecard");
35434
- import_args31.default.option(
35599
+ import_args32.default.option(["s", "strategy"], "Exact strategy to isolate in the scorecard");
35600
+ import_args32.default.option(
35435
35601
  ["H", "historyDir"],
35436
35602
  "Directory containing verified evidence bundles"
35437
35603
  );
35438
- import_args31.default.option(
35604
+ import_args32.default.option(
35439
35605
  ["E", "evidenceDir"],
35440
35606
  "Local evidence storage root used for processing receipts",
35441
35607
  process.env.RUNTIME_EVIDENCE_LOCAL_DIR || "data/runtime-evidence"
35442
35608
  );
35443
- import_args31.default.option(
35609
+ import_args32.default.option(
35444
35610
  ["d", "deployment"],
35445
35611
  "Deployment id used for processing receipts",
35446
35612
  process.env.RUNTIME_EVIDENCE_DEPLOYMENT_ID || "production"
35447
35613
  );
35448
- import_args31.default.option(
35614
+ import_args32.default.option(
35449
35615
  ["M", "markProcessed"],
35450
35616
  "Write a processing receipt on success",
35451
35617
  false
35452
35618
  );
35453
- import_args31.default.option(
35619
+ import_args32.default.option(
35454
35620
  ["P", "minimumParityRatio"],
35455
35621
  "Minimum acceptable replay parity",
35456
35622
  0.95
35457
35623
  );
35458
- import_args31.default.option(
35624
+ import_args32.default.option(
35459
35625
  ["S", "maximumSlippageResidualBps"],
35460
35626
  "Maximum acceptable execution residual in bps",
35461
35627
  3
35462
35628
  );
35463
- import_args31.default.option(
35629
+ import_args32.default.option(
35464
35630
  ["L", "maximumSignalCloseToSubmitMs"],
35465
35631
  "Maximum acceptable average signal-close-to-submit latency in milliseconds",
35466
35632
  3e4
35467
35633
  );
35468
- import_args31.default.option(
35634
+ import_args32.default.option(
35469
35635
  ["T", "minimumClosedTrades"],
35470
35636
  "Minimum 7d closed trades for expectancy reactions",
35471
35637
  20
35472
35638
  );
35473
- import_args31.default.option(["X", "minimumExpectancy"], "Minimum acceptable 7d expectancy", 0);
35474
- import_args31.default.option(["o", "out"], "Output JSON path", "output/runtime-scorecard.json");
35475
- import_args31.default.option(
35639
+ import_args32.default.option(["X", "minimumExpectancy"], "Minimum acceptable 7d expectancy", 0);
35640
+ import_args32.default.option(["o", "out"], "Output JSON path", "output/runtime-scorecard.json");
35641
+ import_args32.default.option(
35476
35642
  ["m", "releaseManifest"],
35477
35643
  "Verified strategy release envelope JSON"
35478
35644
  );
35479
- import_args31.default.option(["D", "diagnosisDays"], "Equal-length release drawdown window", 7);
35480
- import_args31.default.option(
35645
+ import_args32.default.option(["D", "diagnosisDays"], "Equal-length release drawdown window", 7);
35646
+ import_args32.default.option(
35481
35647
  ["z", "strategyReleaseRoot"],
35482
35648
  "Publish advisory diagnosis and immutable chart markers under this root"
35483
35649
  );
35484
- flags29 = import_args31.default.parse(process.argv);
35485
- projectRoot13 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
35650
+ flags30 = import_args32.default.parse(process.argv);
35651
+ projectRoot14 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
35486
35652
  resolveOptionalPath = (value) => {
35487
35653
  const raw = String(value ?? "").trim();
35488
- return raw ? import_node_path32.default.resolve(projectRoot13, raw) : null;
35654
+ return raw ? import_node_path33.default.resolve(projectRoot14, raw) : null;
35489
35655
  };
35490
35656
  readJson = async (filePath) => filePath ? JSON.parse(await import_promises34.default.readFile(filePath, "utf8")) : void 0;
35491
35657
  assertReportType = (artifact, expected, label) => {
@@ -35504,17 +35670,17 @@ var init_runtimeScorecard2 = __esm({
35504
35670
  return bundles.map((bundle) => bundle.artifact);
35505
35671
  };
35506
35672
  runtimeScorecard = async () => {
35507
- const runtimeEvidencePath = resolveOptionalPath(flags29.runtimeEvidence);
35673
+ const runtimeEvidencePath = resolveOptionalPath(flags30.runtimeEvidence);
35508
35674
  if (!runtimeEvidencePath) {
35509
35675
  throw new Error("Provide --runtimeEvidence for the runtime scorecard.");
35510
35676
  }
35511
- const replayEvidencePath = resolveOptionalPath(flags29.replayEvidence);
35512
- const calibrationPath = resolveOptionalPath(flags29.calibration);
35677
+ const replayEvidencePath = resolveOptionalPath(flags30.replayEvidence);
35678
+ const calibrationPath = resolveOptionalPath(flags30.calibration);
35513
35679
  const prospectiveEvidencePath = resolveOptionalPath(
35514
- flags29.prospectiveEvidence
35680
+ flags30.prospectiveEvidence
35515
35681
  );
35516
- const historyDir = resolveOptionalPath(flags29.historyDir);
35517
- const releaseManifestPath = resolveOptionalPath(flags29.releaseManifest);
35682
+ const historyDir = resolveOptionalPath(flags30.historyDir);
35683
+ const releaseManifestPath = resolveOptionalPath(flags30.releaseManifest);
35518
35684
  const [
35519
35685
  runtimeArtifact,
35520
35686
  replayEvidenceArtifact,
@@ -35541,7 +35707,7 @@ var init_runtimeScorecard2 = __esm({
35541
35707
  "prospectiveEvidence"
35542
35708
  );
35543
35709
  const verifiedRelease = releaseManifestPath ? await verifyStrategyReleaseEnvelope(releaseManifestPath) : null;
35544
- const requestedStrategy = String(flags29.strategy ?? "").trim() || null;
35710
+ const requestedStrategy = String(flags30.strategy ?? "").trim() || null;
35545
35711
  if (verifiedRelease && requestedStrategy && requestedStrategy !== verifiedRelease.manifest.strategy) {
35546
35712
  throw new Error(
35547
35713
  `Requested strategy ${requestedStrategy} does not match release ${verifiedRelease.manifest.strategy}`
@@ -35555,18 +35721,18 @@ var init_runtimeScorecard2 = __esm({
35555
35721
  prospectiveEvidenceArtifact,
35556
35722
  historyRuntimeArtifacts: history,
35557
35723
  thresholds: {
35558
- minimumParityRatio: Number(flags29.minimumParityRatio),
35559
- maximumSlippageResidualBps: Number(flags29.maximumSlippageResidualBps),
35560
- maximumSignalCloseToSubmitMs: Number(flags29.maximumSignalCloseToSubmitMs),
35561
- minimumClosedTrades: Number(flags29.minimumClosedTrades),
35562
- minimumExpectancy: Number(flags29.minimumExpectancy)
35724
+ minimumParityRatio: Number(flags30.minimumParityRatio),
35725
+ maximumSlippageResidualBps: Number(flags30.maximumSlippageResidualBps),
35726
+ maximumSignalCloseToSubmitMs: Number(flags30.maximumSignalCloseToSubmitMs),
35727
+ minimumClosedTrades: Number(flags30.minimumClosedTrades),
35728
+ minimumExpectancy: Number(flags30.minimumExpectancy)
35563
35729
  },
35564
35730
  strategy: scorecardStrategy,
35565
35731
  llmComparatorPolicy: verifiedRelease?.manifest.prospective.llmComparatorPolicy ?? "ai_approved_only"
35566
35732
  });
35567
- const outPath = import_node_path32.default.resolve(projectRoot13, String(flags29.out));
35733
+ const outPath = import_node_path33.default.resolve(projectRoot14, String(flags30.out));
35568
35734
  const markdownPath = outPath.replace(/\.json$/i, "") + ".md";
35569
- await import_promises34.default.mkdir(import_node_path32.default.dirname(outPath), { recursive: true });
35735
+ await import_promises34.default.mkdir(import_node_path33.default.dirname(outPath), { recursive: true });
35570
35736
  await Promise.all([
35571
35737
  import_promises34.default.writeFile(outPath, `${JSON.stringify(scorecard, null, 2)}
35572
35738
  `, "utf8"),
@@ -35579,10 +35745,10 @@ var init_runtimeScorecard2 = __esm({
35579
35745
  const diagnosis = verifiedRelease ? buildStrategyLiveDiagnosisFromScorecard({
35580
35746
  manifest: verifiedRelease.manifest,
35581
35747
  scorecard,
35582
- days: Number(flags29.diagnosisDays)
35748
+ days: Number(flags30.diagnosisDays)
35583
35749
  }) : null;
35584
35750
  const diagnosisPath = diagnosis ? outPath.replace(/\.json$/i, "") + ".diagnosis.json" : null;
35585
- const strategyReleaseRoot = resolveOptionalPath(flags29.strategyReleaseRoot);
35751
+ const strategyReleaseRoot = resolveOptionalPath(flags30.strategyReleaseRoot);
35586
35752
  if (diagnosis && diagnosisPath) {
35587
35753
  await import_promises34.default.writeFile(
35588
35754
  diagnosisPath,
@@ -35605,7 +35771,7 @@ var init_runtimeScorecard2 = __esm({
35605
35771
  composition: verifiedRelease?.manifest.composition,
35606
35772
  sourceArtifacts: await Promise.all(
35607
35773
  sourcePaths.map(async (sourcePath) => ({
35608
- artifactId: import_node_path32.default.basename(sourcePath),
35774
+ artifactId: import_node_path33.default.basename(sourcePath),
35609
35775
  path: sourcePath,
35610
35776
  sha256: await sha256File2(sourcePath)
35611
35777
  }))
@@ -35614,13 +35780,13 @@ var init_runtimeScorecard2 = __esm({
35614
35780
  }
35615
35781
  }
35616
35782
  let receiptPath2 = null;
35617
- if (flags29.markProcessed) {
35783
+ if (flags30.markProcessed) {
35618
35784
  const runtimeEvidenceBundle = await verifyRuntimeEvidenceBundle(
35619
- import_node_path32.default.dirname(runtimeEvidencePath)
35785
+ import_node_path33.default.dirname(runtimeEvidencePath)
35620
35786
  );
35621
35787
  const feedbackSource = replayEvidencePath ? await verifyRuntimeFeedbackReplaySource({
35622
- bundleDir: import_node_path32.default.dirname(replayEvidencePath),
35623
- runtimeEvidenceBundleDir: import_node_path32.default.dirname(runtimeEvidencePath)
35788
+ bundleDir: import_node_path33.default.dirname(replayEvidencePath),
35789
+ runtimeEvidenceBundleDir: import_node_path33.default.dirname(runtimeEvidencePath)
35624
35790
  }).catch((error) => {
35625
35791
  if (runtimeEvidenceBundle.artifact.producer) throw error;
35626
35792
  return null;
@@ -35631,9 +35797,9 @@ var init_runtimeScorecard2 = __esm({
35631
35797
  );
35632
35798
  }
35633
35799
  receiptPath2 = await markRuntimeEvidenceBundleProcessed({
35634
- evidenceRoot: import_node_path32.default.resolve(projectRoot13, String(flags29.evidenceDir)),
35635
- deploymentId: String(flags29.deployment),
35636
- bundleDir: import_node_path32.default.dirname(runtimeEvidencePath),
35800
+ evidenceRoot: import_node_path33.default.resolve(projectRoot14, String(flags30.evidenceDir)),
35801
+ deploymentId: String(flags30.deployment),
35802
+ bundleDir: import_node_path33.default.dirname(runtimeEvidencePath),
35637
35803
  scorecardPath: outPath,
35638
35804
  runtimeFeedback: feedbackSource ? {
35639
35805
  artifactId: feedbackSource.feedback.manifest.artifactId,
@@ -35641,8 +35807,8 @@ var init_runtimeScorecard2 = __esm({
35641
35807
  } : null
35642
35808
  });
35643
35809
  }
35644
- console.log(import_chalk48.default.green(`Wrote ${outPath}`));
35645
- console.log(import_chalk48.default.green(`Wrote ${markdownPath}`));
35810
+ console.log(import_chalk49.default.green(`Wrote ${outPath}`));
35811
+ console.log(import_chalk49.default.green(`Wrote ${markdownPath}`));
35646
35812
  console.log(
35647
35813
  JSON.stringify(
35648
35814
  {
@@ -35661,7 +35827,7 @@ var init_runtimeScorecard2 = __esm({
35661
35827
  )
35662
35828
  );
35663
35829
  };
35664
- main39 = runtimeScorecard;
35830
+ main40 = runtimeScorecard;
35665
35831
  }
35666
35832
  });
35667
35833
 
@@ -35669,10 +35835,10 @@ var init_runtimeScorecard2 = __esm({
35669
35835
  var runtimeControl_exports = {};
35670
35836
  __export(runtimeControl_exports, {
35671
35837
  RUNTIME_CONTROL_ACTIONS: () => RUNTIME_CONTROL_ACTIONS,
35672
- main: () => main40,
35838
+ main: () => main41,
35673
35839
  runtimeControl: () => runtimeControl
35674
35840
  });
35675
- var import_config9, import_runtimeControls, import_runtimeStrategies6, argv, RUNTIME_CONTROL_ACTIONS, action, option, required2, projectRoot14, userName2, verify, inspect, updateControlState, runtimeControl, main40;
35841
+ var import_config9, import_runtimeControls, import_runtimeStrategies6, argv, RUNTIME_CONTROL_ACTIONS, action, option, required2, projectRoot15, userName2, verify, inspect, updateControlState, runtimeControl, main41;
35676
35842
  var init_runtimeControl = __esm({
35677
35843
  "src/scripts/runtimeControl.ts"() {
35678
35844
  "use strict";
@@ -35696,10 +35862,10 @@ var init_runtimeControl = __esm({
35696
35862
  if (!value) throw new Error(`--${name} is required`);
35697
35863
  return value;
35698
35864
  };
35699
- projectRoot14 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
35865
+ projectRoot15 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
35700
35866
  userName2 = String(option("user") ?? process.env.USER_NAME ?? "root");
35701
35867
  verify = async () => {
35702
- const deployments = await (0, import_runtimeStrategies6.listRuntimeDeployments)({ userName: userName2, projectRoot: projectRoot14 });
35868
+ const deployments = await (0, import_runtimeStrategies6.listRuntimeDeployments)({ userName: userName2, projectRoot: projectRoot15 });
35703
35869
  const requestedDeployment = option("deployment");
35704
35870
  const selected = requestedDeployment ? deployments.filter((deployment) => deployment.id === requestedDeployment) : deployments;
35705
35871
  if (requestedDeployment && !selected.length) {
@@ -35710,7 +35876,7 @@ var init_runtimeControl = __esm({
35710
35876
  try {
35711
35877
  const strategies = await (0, import_runtimeStrategies6.loadResolvedRuntimeStrategies)({
35712
35878
  userName: userName2,
35713
- projectRoot: projectRoot14,
35879
+ projectRoot: projectRoot15,
35714
35880
  deploymentId: deployment.id
35715
35881
  });
35716
35882
  results2.push({
@@ -35743,7 +35909,7 @@ var init_runtimeControl = __esm({
35743
35909
  inspect = async () => {
35744
35910
  const requestedDeployment = option("deployment");
35745
35911
  const requestedStrategy = option("strategy");
35746
- const deployments = (await (0, import_runtimeStrategies6.listRuntimeDeployments)({ userName: userName2, projectRoot: projectRoot14 })).filter(
35912
+ const deployments = (await (0, import_runtimeStrategies6.listRuntimeDeployments)({ userName: userName2, projectRoot: projectRoot15 })).filter(
35747
35913
  (deployment) => !requestedDeployment || deployment.id === requestedDeployment
35748
35914
  ).map((deployment) => ({
35749
35915
  ...deployment,
@@ -35758,7 +35924,7 @@ var init_runtimeControl = __esm({
35758
35924
  const strategyName = required2("strategy");
35759
35925
  const deployment = await (0, import_runtimeStrategies6.getRuntimeDeployment)({
35760
35926
  userName: userName2,
35761
- projectRoot: projectRoot14,
35927
+ projectRoot: projectRoot15,
35762
35928
  deploymentId
35763
35929
  });
35764
35930
  if (!deployment) {
@@ -35788,7 +35954,7 @@ var init_runtimeControl = __esm({
35788
35954
  }
35789
35955
  const updated = await (0, import_runtimeStrategies6.getRuntimeDeployment)({
35790
35956
  userName: userName2,
35791
- projectRoot: projectRoot14,
35957
+ projectRoot: projectRoot15,
35792
35958
  deploymentId
35793
35959
  });
35794
35960
  const updatedReference = updated?.strategies.find(
@@ -35820,25 +35986,25 @@ var init_runtimeControl = __esm({
35820
35986
  `Usage: tradejs runtime-control ${RUNTIME_CONTROL_ACTIONS.join("|")}`
35821
35987
  );
35822
35988
  };
35823
- main40 = runtimeControl;
35989
+ main41 = runtimeControl;
35824
35990
  }
35825
35991
  });
35826
35992
 
35827
35993
  // src/scripts/strategyRelease.ts
35828
35994
  var strategyRelease_exports = {};
35829
35995
  __export(strategyRelease_exports, {
35830
- main: () => main41,
35996
+ main: () => main42,
35831
35997
  runStrategyReleaseCommand: () => runStrategyReleaseCommand
35832
35998
  });
35833
- var import_promises35, import_node_fs5, import_node_readline2, import_node_path33, import_chalk49, valueAfter2, required3, writeJsonAtomic3, runStrategyReleaseCommand, printUsage2, main41;
35999
+ var import_promises35, import_node_fs5, import_node_readline2, import_node_path34, import_chalk50, valueAfter2, required3, writeJsonAtomic3, runStrategyReleaseCommand, printUsage2, main42;
35834
36000
  var init_strategyRelease2 = __esm({
35835
36001
  "src/scripts/strategyRelease.ts"() {
35836
36002
  "use strict";
35837
36003
  import_promises35 = __toESM(require("fs/promises"));
35838
36004
  import_node_fs5 = require("fs");
35839
36005
  import_node_readline2 = require("readline");
35840
- import_node_path33 = __toESM(require("path"));
35841
- import_chalk49 = __toESM(require("chalk"));
36006
+ import_node_path34 = __toESM(require("path"));
36007
+ import_chalk50 = __toESM(require("chalk"));
35842
36008
  init_strategyRelease();
35843
36009
  valueAfter2 = (argv2, name) => {
35844
36010
  const index = argv2.indexOf(name);
@@ -35850,7 +36016,7 @@ var init_strategyRelease2 = __esm({
35850
36016
  };
35851
36017
  writeJsonAtomic3 = async (filePath, value) => {
35852
36018
  const temporaryPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
35853
- await import_promises35.default.mkdir(import_node_path33.default.dirname(filePath), { recursive: true });
36019
+ await import_promises35.default.mkdir(import_node_path34.default.dirname(filePath), { recursive: true });
35854
36020
  await import_promises35.default.writeFile(
35855
36021
  temporaryPath,
35856
36022
  `${JSON.stringify(value, null, 2)}
@@ -35860,7 +36026,7 @@ var init_strategyRelease2 = __esm({
35860
36026
  await import_promises35.default.rename(temporaryPath, filePath);
35861
36027
  };
35862
36028
  runStrategyReleaseCommand = async (options) => {
35863
- const inputPath = import_node_path33.default.resolve(options.inputPath);
36029
+ const inputPath = import_node_path34.default.resolve(options.inputPath);
35864
36030
  if (options.command === "verify") {
35865
36031
  const envelope = await verifyStrategyReleaseEnvelope(inputPath);
35866
36032
  return {
@@ -35898,7 +36064,7 @@ var init_strategyRelease2 = __esm({
35898
36064
  endTime,
35899
36065
  days: options.days?.length ? options.days : [7, 30, 90]
35900
36066
  });
35901
- const outputPath = import_node_path33.default.resolve(
36067
+ const outputPath = import_node_path34.default.resolve(
35902
36068
  options.outputPath ?? "output/strategy-monitoring-profile.json"
35903
36069
  );
35904
36070
  await writeJsonAtomic3(outputPath, profile);
@@ -35913,12 +36079,12 @@ var init_strategyRelease2 = __esm({
35913
36079
  if (options.command === "decide") {
35914
36080
  const decision = await deriveStrategyReleaseResearchDecision(input);
35915
36081
  if (options.outputPath) {
35916
- await writeJsonAtomic3(import_node_path33.default.resolve(options.outputPath), decision);
36082
+ await writeJsonAtomic3(import_node_path34.default.resolve(options.outputPath), decision);
35917
36083
  }
35918
36084
  return {
35919
36085
  kind: "decided",
35920
36086
  ...decision,
35921
- outputPath: options.outputPath ? import_node_path33.default.resolve(options.outputPath) : null
36087
+ outputPath: options.outputPath ? import_node_path34.default.resolve(options.outputPath) : null
35922
36088
  };
35923
36089
  }
35924
36090
  if (options.command === "retention") {
@@ -35937,12 +36103,12 @@ var init_strategyRelease2 = __esm({
35937
36103
  }
35938
36104
  if (options.command === "diagnose") {
35939
36105
  const diagnosis = buildStrategyLiveDiagnosis(input);
35940
- const outputPath = import_node_path33.default.resolve(
36106
+ const outputPath = import_node_path34.default.resolve(
35941
36107
  options.outputPath ?? "output/strategy-live-diagnosis.json"
35942
36108
  );
35943
36109
  await writeJsonAtomic3(outputPath, diagnosis);
35944
36110
  const published2 = options.rootDir ? await publishStrategyLiveDiagnosis({
35945
- rootDir: import_node_path33.default.resolve(options.rootDir),
36111
+ rootDir: import_node_path34.default.resolve(options.rootDir),
35946
36112
  diagnosis,
35947
36113
  sourceArtifacts: input.sourceArtifacts ?? []
35948
36114
  }) : null;
@@ -35959,7 +36125,7 @@ var init_strategyRelease2 = __esm({
35959
36125
  evidence: await collectReleaseEvidenceReferences(input.evidence ?? [])
35960
36126
  });
35961
36127
  const published = await publishStrategyRelease({
35962
- rootDir: import_node_path33.default.resolve(options.rootDir ?? "data/strategy-release"),
36128
+ rootDir: import_node_path34.default.resolve(options.rootDir ?? "data/strategy-release"),
35963
36129
  manifest
35964
36130
  });
35965
36131
  return {
@@ -35977,7 +36143,7 @@ var init_strategyRelease2 = __esm({
35977
36143
  yarn strategy:release profile --input <trades.jsonl> --variant <id> --startTime <ms> --endTime <ms> [--days 7,30,90] [--out <profile.json>]
35978
36144
  yarn strategy:release diagnose --input <diagnosis-input.json> [--out output/diagnosis.json]
35979
36145
  yarn strategy:release retention --input <inventory.json> [--apply]`);
35980
- main41 = async () => {
36146
+ main42 = async () => {
35981
36147
  const argv2 = process.argv.slice(2);
35982
36148
  const command = argv2[0];
35983
36149
  if (!command || ![
@@ -36003,7 +36169,7 @@ var init_strategyRelease2 = __esm({
36003
36169
  endTime: Number(valueAfter2(argv2, "--endTime")),
36004
36170
  days: valueAfter2(argv2, "--days")?.split(",").map((entry) => Number(entry.trim()))
36005
36171
  });
36006
- console.log(import_chalk49.default.green(JSON.stringify(result, null, 2)));
36172
+ console.log(import_chalk50.default.green(JSON.stringify(result, null, 2)));
36007
36173
  };
36008
36174
  }
36009
36175
  });
@@ -36016,10 +36182,10 @@ __export(serverHealth_exports, {
36016
36182
  buildServerHealthDiagnostics: () => buildServerHealthDiagnostics,
36017
36183
  collectServerHealthSnapshot: () => collectServerHealthSnapshot,
36018
36184
  evaluateServerHealth: () => evaluateServerHealth,
36019
- main: () => main42,
36185
+ main: () => main43,
36020
36186
  resolveServerHealthThresholds: () => resolveServerHealthThresholds
36021
36187
  });
36022
- var import_config10, import_node_child_process9, import_node_os3, import_node_fs6, import_args32, import_redis19, DEFAULT_STATE, DEFAULT_THRESHOLDS, escapeHtml5, formatPctValue, formatLoadPerCore, formatGiB, formatDuration2, readDiskUsage, parseMeminfoBytes, readMemorySnapshot, runDiagnosticCommand, runDiagnosticCommands, collectServerHealthSnapshot, buildHumanSummaryLines, evaluateServerHealth, shouldRecover, buildAlertMessage, buildRecoveryMessage, buildServerHealthDiagnostics, getStateKey, toFiniteNumber3, resolveServerHealthThresholds, main42;
36188
+ var import_config10, import_node_child_process9, import_node_os3, import_node_fs6, import_args33, import_redis19, DEFAULT_STATE, DEFAULT_THRESHOLDS, escapeHtml6, formatPctValue, formatLoadPerCore, formatGiB, formatDuration2, readDiskUsage, parseMeminfoBytes, readMemorySnapshot, runDiagnosticCommand, runDiagnosticCommands, collectServerHealthSnapshot, buildHumanSummaryLines, evaluateServerHealth, shouldRecover, buildAlertMessage, buildRecoveryMessage, buildServerHealthDiagnostics, getStateKey, toFiniteNumber3, resolveServerHealthThresholds, main43;
36023
36189
  var init_serverHealth = __esm({
36024
36190
  "src/scripts/serverHealth.ts"() {
36025
36191
  "use strict";
@@ -36027,7 +36193,7 @@ var init_serverHealth = __esm({
36027
36193
  import_node_child_process9 = require("child_process");
36028
36194
  import_node_os3 = __toESM(require("os"));
36029
36195
  import_node_fs6 = require("fs");
36030
- import_args32 = __toESM(require("args"));
36196
+ import_args33 = __toESM(require("args"));
36031
36197
  import_redis19 = require("@tradejs/infra/redis");
36032
36198
  init_telegramReports();
36033
36199
  DEFAULT_STATE = {
@@ -36044,7 +36210,7 @@ var init_serverHealth = __esm({
36044
36210
  diskWarnPct: 95,
36045
36211
  diskRecoverPct: 92
36046
36212
  };
36047
- escapeHtml5 = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
36213
+ escapeHtml6 = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
36048
36214
  formatPctValue = (value) => `${value.toFixed(1)}%`;
36049
36215
  formatLoadPerCore = (value) => value.toFixed(2);
36050
36216
  formatGiB = (bytes) => `${(bytes / 1024 ** 3).toFixed(1)} GB`;
@@ -36061,21 +36227,21 @@ var init_serverHealth = __esm({
36061
36227
  }
36062
36228
  return `${minutes}m`;
36063
36229
  };
36064
- readDiskUsage = (path44) => {
36230
+ readDiskUsage = (path45) => {
36065
36231
  try {
36066
- const stats = (0, import_node_fs6.statfsSync)(path44);
36232
+ const stats = (0, import_node_fs6.statfsSync)(path45);
36067
36233
  const totalBlocks = Number(stats.blocks ?? 0);
36068
36234
  const availableBlocks = Number(stats.bavail ?? 0);
36069
36235
  if (totalBlocks <= 0) {
36070
- return { path: path44, usedPct: null };
36236
+ return { path: path45, usedPct: null };
36071
36237
  }
36072
36238
  const usedPct = (totalBlocks - Math.max(0, availableBlocks)) / totalBlocks * 100;
36073
36239
  return {
36074
- path: path44,
36240
+ path: path45,
36075
36241
  usedPct: Number.isFinite(usedPct) ? usedPct : null
36076
36242
  };
36077
36243
  } catch {
36078
- return { path: path44, usedPct: null };
36244
+ return { path: path45, usedPct: null };
36079
36245
  }
36080
36246
  };
36081
36247
  parseMeminfoBytes = (value) => {
@@ -36139,8 +36305,8 @@ var init_serverHealth = __esm({
36139
36305
  };
36140
36306
  }
36141
36307
  };
36142
- runDiagnosticCommand = (command, args37) => {
36143
- const output = (0, import_node_child_process9.execFileSync)(command, args37, {
36308
+ runDiagnosticCommand = (command, args38) => {
36309
+ const output = (0, import_node_child_process9.execFileSync)(command, args38, {
36144
36310
  encoding: "utf8",
36145
36311
  timeout: 5e3,
36146
36312
  maxBuffer: 1024 * 1024,
@@ -36187,11 +36353,11 @@ var init_serverHealth = __esm({
36187
36353
  snapshot.memory.totalBytes - snapshot.memory.availableBytes
36188
36354
  );
36189
36355
  return [
36190
- `\u2022 vCPU: <b>${escapeHtml5(formatPctValue(Math.min(100, snapshot.loadPerCpu1 * 100)))}</b>`,
36191
- `\u2022 RAM: <b>${escapeHtml5(formatPctValue(snapshot.memoryUsedPct))}</b> (${escapeHtml5(
36356
+ `\u2022 vCPU: <b>${escapeHtml6(formatPctValue(Math.min(100, snapshot.loadPerCpu1 * 100)))}</b>`,
36357
+ `\u2022 RAM: <b>${escapeHtml6(formatPctValue(snapshot.memoryUsedPct))}</b> (${escapeHtml6(
36192
36358
  `${formatGiB(usedMem)} / ${formatGiB(snapshot.memory.totalBytes)}`
36193
36359
  )})`,
36194
- `\u2022 Storage: <b>${escapeHtml5(
36360
+ `\u2022 Storage: <b>${escapeHtml6(
36195
36361
  snapshot.disk.usedPct == null ? "n/a" : formatPctValue(snapshot.disk.usedPct)
36196
36362
  )}</b>`
36197
36363
  ];
@@ -36235,22 +36401,22 @@ var init_serverHealth = __esm({
36235
36401
  return [
36236
36402
  title,
36237
36403
  "",
36238
- `Host: <b>${escapeHtml5(snapshot.hostname)}</b>`,
36239
- `Time: <b>${escapeHtml5(new Date(snapshot.timestamp).toISOString())}</b>`,
36240
- `Uptime: <b>${escapeHtml5(formatDuration2(snapshot.uptimeSec))}</b>`,
36404
+ `Host: <b>${escapeHtml6(snapshot.hostname)}</b>`,
36405
+ `Time: <b>${escapeHtml6(new Date(snapshot.timestamp).toISOString())}</b>`,
36406
+ `Uptime: <b>${escapeHtml6(formatDuration2(snapshot.uptimeSec))}</b>`,
36241
36407
  "",
36242
36408
  "Summary:",
36243
36409
  ...buildHumanSummaryLines(snapshot),
36244
36410
  "",
36245
36411
  "Issues:",
36246
- ...issues.map((issue) => `\u2022 ${escapeHtml5(issue.summary)}`),
36412
+ ...issues.map((issue) => `\u2022 ${escapeHtml6(issue.summary)}`),
36247
36413
  "",
36248
36414
  "Pressure:",
36249
36415
  `\u2022 Load avg: <b>${snapshot.load1.toFixed(2)} / ${snapshot.load5.toFixed(2)} / ${snapshot.load15.toFixed(2)}</b>`,
36250
36416
  `\u2022 Load per core: <b>${formatLoadPerCore(
36251
36417
  snapshot.loadPerCpu1
36252
36418
  )}</b> (1m), <b>${formatLoadPerCore(snapshot.loadPerCpu5)}</b> (5m)`,
36253
- prevState.lastAlertAt ? `\u2022 Previous alert: <b>${escapeHtml5(new Date(prevState.lastAlertAt).toISOString())}</b>` : "\u2022 Previous alert: <b>none</b>"
36419
+ prevState.lastAlertAt ? `\u2022 Previous alert: <b>${escapeHtml6(new Date(prevState.lastAlertAt).toISOString())}</b>` : "\u2022 Previous alert: <b>none</b>"
36254
36420
  ].join("\n");
36255
36421
  };
36256
36422
  buildRecoveryMessage = ({
@@ -36259,9 +36425,9 @@ var init_serverHealth = __esm({
36259
36425
  }) => [
36260
36426
  "\u2705 <b>TradeJS server health recovered</b>",
36261
36427
  "",
36262
- `Host: <b>${escapeHtml5(snapshot.hostname)}</b>`,
36263
- `Time: <b>${escapeHtml5(new Date(snapshot.timestamp).toISOString())}</b>`,
36264
- `Uptime: <b>${escapeHtml5(formatDuration2(snapshot.uptimeSec))}</b>`,
36428
+ `Host: <b>${escapeHtml6(snapshot.hostname)}</b>`,
36429
+ `Time: <b>${escapeHtml6(new Date(snapshot.timestamp).toISOString())}</b>`,
36430
+ `Uptime: <b>${escapeHtml6(formatDuration2(snapshot.uptimeSec))}</b>`,
36265
36431
  "",
36266
36432
  "Summary:",
36267
36433
  ...buildHumanSummaryLines(snapshot),
@@ -36271,7 +36437,7 @@ var init_serverHealth = __esm({
36271
36437
  `\u2022 Load per core: <b>${formatLoadPerCore(
36272
36438
  snapshot.loadPerCpu1
36273
36439
  )}</b> (1m), <b>${formatLoadPerCore(snapshot.loadPerCpu5)}</b> (5m)`,
36274
- prevState.lastAlertAt ? `\u2022 Alert started: <b>${escapeHtml5(new Date(prevState.lastAlertAt).toISOString())}</b>` : "\u2022 Alert started: <b>unknown</b>"
36440
+ prevState.lastAlertAt ? `\u2022 Alert started: <b>${escapeHtml6(new Date(prevState.lastAlertAt).toISOString())}</b>` : "\u2022 Alert started: <b>unknown</b>"
36275
36441
  ].join("\n");
36276
36442
  buildServerHealthDiagnostics = ({
36277
36443
  snapshot,
@@ -36390,57 +36556,57 @@ var init_serverHealth = __esm({
36390
36556
  diskRecoverPct: diskRecoverPct != null && diskRecoverPct > 0 ? diskRecoverPct : DEFAULT_THRESHOLDS.diskRecoverPct
36391
36557
  };
36392
36558
  };
36393
- import_args32.default.option(["u", "user"], "Use user config", "root");
36394
- import_args32.default.option(["P", "printOnly"], "Print report instead of Telegram", false);
36395
- import_args32.default.option(
36559
+ import_args33.default.option(["u", "user"], "Use user config", "root");
36560
+ import_args33.default.option(["P", "printOnly"], "Print report instead of Telegram", false);
36561
+ import_args33.default.option(
36396
36562
  ["d", "diskPath"],
36397
36563
  "Filesystem path to inspect for disk pressure",
36398
36564
  "/"
36399
36565
  );
36400
- import_args32.default.option(
36566
+ import_args33.default.option(
36401
36567
  ["c", "cooldownSec"],
36402
36568
  "Minimum seconds between repeated unhealthy reminders",
36403
36569
  900
36404
36570
  );
36405
- import_args32.default.option(
36571
+ import_args33.default.option(
36406
36572
  ["l", "loadPerCpuWarn"],
36407
36573
  "Alert when 1m load per CPU reaches this value",
36408
36574
  String(DEFAULT_THRESHOLDS.loadPerCpuWarn)
36409
36575
  );
36410
- import_args32.default.option(
36576
+ import_args33.default.option(
36411
36577
  ["L", "loadPerCpuRecover"],
36412
36578
  "Recovery threshold for 1m load per CPU",
36413
36579
  String(DEFAULT_THRESHOLDS.loadPerCpuRecover)
36414
36580
  );
36415
- import_args32.default.option(
36581
+ import_args33.default.option(
36416
36582
  ["m", "memoryWarnPct"],
36417
36583
  "Alert when memory used percent reaches this value",
36418
36584
  String(DEFAULT_THRESHOLDS.memoryWarnPct)
36419
36585
  );
36420
- import_args32.default.option(
36586
+ import_args33.default.option(
36421
36587
  ["M", "memoryRecoverPct"],
36422
36588
  "Recovery threshold for memory used percent",
36423
36589
  String(DEFAULT_THRESHOLDS.memoryRecoverPct)
36424
36590
  );
36425
- import_args32.default.option(
36591
+ import_args33.default.option(
36426
36592
  ["D", "diskWarnPct"],
36427
36593
  "Alert when disk used percent reaches this value",
36428
36594
  String(DEFAULT_THRESHOLDS.diskWarnPct)
36429
36595
  );
36430
- import_args32.default.option(
36596
+ import_args33.default.option(
36431
36597
  ["R", "diskRecoverPct"],
36432
36598
  "Recovery threshold for disk used percent",
36433
36599
  String(DEFAULT_THRESHOLDS.diskRecoverPct)
36434
36600
  );
36435
- main42 = async () => {
36436
- const flags34 = import_args32.default.parse(process.argv);
36437
- const thresholds = resolveServerHealthThresholds(flags34);
36438
- const diskPath = String(flags34.diskPath || "/");
36601
+ main43 = async () => {
36602
+ const flags35 = import_args33.default.parse(process.argv);
36603
+ const thresholds = resolveServerHealthThresholds(flags35);
36604
+ const diskPath = String(flags35.diskPath || "/");
36439
36605
  const snapshot = collectServerHealthSnapshot(diskPath);
36440
- const stateKey = getStateKey(String(flags34.user), snapshot.hostname);
36606
+ const stateKey = getStateKey(String(flags35.user), snapshot.hostname);
36441
36607
  const prevState = await (0, import_redis19.getData)(stateKey, DEFAULT_STATE) ?? DEFAULT_STATE;
36442
36608
  const evaluation = evaluateServerHealth(snapshot, thresholds);
36443
- const cooldownMs = Math.max(60, Number(flags34.cooldownSec)) * 1e3;
36609
+ const cooldownMs = Math.max(60, Number(flags35.cooldownSec)) * 1e3;
36444
36610
  const now2 = snapshot.timestamp;
36445
36611
  if (!evaluation.isHealthy) {
36446
36612
  const reminder = prevState.status === "alerting" && typeof prevState.lastAlertAt === "number" && now2 - prevState.lastAlertAt < cooldownMs ? false : prevState.status === "alerting";
@@ -36458,7 +36624,7 @@ var init_serverHealth = __esm({
36458
36624
  prevState,
36459
36625
  reminder
36460
36626
  });
36461
- if (flags34.printOnly) {
36627
+ if (flags35.printOnly) {
36462
36628
  console.log(message);
36463
36629
  console.log("");
36464
36630
  console.log(
@@ -36468,7 +36634,7 @@ var init_serverHealth = __esm({
36468
36634
  })
36469
36635
  );
36470
36636
  } else {
36471
- await sendTelegramReport(message, { userName: flags34.user });
36637
+ await sendTelegramReport(message, { userName: flags35.user });
36472
36638
  }
36473
36639
  }
36474
36640
  return;
@@ -36483,10 +36649,10 @@ var init_serverHealth = __esm({
36483
36649
  await (0, import_redis19.setData)(stateKey, nextState, { expire: 0 });
36484
36650
  if (recovered) {
36485
36651
  const message = buildRecoveryMessage({ snapshot, prevState });
36486
- if (flags34.printOnly) {
36652
+ if (flags35.printOnly) {
36487
36653
  console.log(message);
36488
36654
  } else {
36489
- await sendTelegramReport(message, { userName: flags34.user });
36655
+ await sendTelegramReport(message, { userName: flags35.user });
36490
36656
  }
36491
36657
  }
36492
36658
  };
@@ -37533,11 +37699,11 @@ var init_reportingJson = __esm({
37533
37699
  });
37534
37700
 
37535
37701
  // src/lib/runtimeParity/reportingTerminal.ts
37536
- var import_chalk50, import_time12, DETAIL_LIMIT, buildRuntimeParityTerminalReport, writeRuntimeParityTerminalReport, printRuntimeDuplicateDetails, printClassifiedBacktestOnlyDetails, printClassifiedRuntimeOnlyDetails;
37702
+ var import_chalk51, import_time12, DETAIL_LIMIT, buildRuntimeParityTerminalReport, writeRuntimeParityTerminalReport, printRuntimeDuplicateDetails, printClassifiedBacktestOnlyDetails, printClassifiedRuntimeOnlyDetails;
37537
37703
  var init_reportingTerminal = __esm({
37538
37704
  "src/lib/runtimeParity/reportingTerminal.ts"() {
37539
37705
  "use strict";
37540
- import_chalk50 = __toESM(require("chalk"));
37706
+ import_chalk51 = __toESM(require("chalk"));
37541
37707
  import_time12 = require("@tradejs/core/time");
37542
37708
  init_classification();
37543
37709
  init_reportingShared();
@@ -37546,7 +37712,7 @@ var init_reportingTerminal = __esm({
37546
37712
  const mismatchRows = buildMismatchSummaryRows(context);
37547
37713
  const strategyIssueRows = buildStrategyIssueRows(context.strategyRows);
37548
37714
  const lines = [
37549
- import_chalk50.default.cyan("TradeJS runtime parity"),
37715
+ import_chalk51.default.cyan("TradeJS runtime parity"),
37550
37716
  `Window: ${(0, import_time12.formatUnix)(context.window.start)} -> ${(0, import_time12.formatUnix)(context.window.end)} (${context.window.source})`,
37551
37717
  `Connector: ${context.connectorName}`,
37552
37718
  `Replay env: ${context.replayEnv}${context.runtimeGatesEnabled ? " (runtime AI/ML gates enabled)" : " (core/backtest gates only)"}`,
@@ -37575,7 +37741,7 @@ var init_reportingTerminal = __esm({
37575
37741
  lines.push(`Runtime evaluations: ${context.runtimeSignalEvaluationsCount}`);
37576
37742
  }
37577
37743
  if (mismatchRows.length) {
37578
- lines.push("", import_chalk50.default.yellow("Signal mismatches"));
37744
+ lines.push("", import_chalk51.default.yellow("Signal mismatches"));
37579
37745
  for (const item of mismatchRows.slice(0, context.detailLimit)) {
37580
37746
  lines.push(`- ${item.line}`);
37581
37747
  }
@@ -37585,14 +37751,14 @@ var init_reportingTerminal = __esm({
37585
37751
  }
37586
37752
  lines.push("");
37587
37753
  if (strategyIssueRows.length) {
37588
- lines.push(import_chalk50.default.cyan("Strategy issues"), ...strategyIssueRows);
37754
+ lines.push(import_chalk51.default.cyan("Strategy issues"), ...strategyIssueRows);
37589
37755
  } else if (context.strategyRows.length) {
37590
37756
  lines.push(
37591
37757
  `Strategies: clean ${context.strategyRows.length}/${context.strategyRows.length}`
37592
37758
  );
37593
37759
  }
37594
37760
  if (context.runtimeGateWarningCounts.size && !context.runtimeGatesRequested) {
37595
- lines.push("", import_chalk50.default.yellow("Warnings"));
37761
+ lines.push("", import_chalk51.default.yellow("Warnings"));
37596
37762
  for (const [strategy, count] of [
37597
37763
  ...context.runtimeGateWarningCounts.entries()
37598
37764
  ].sort(([left], [right]) => left.localeCompare(right))) {
@@ -37602,7 +37768,7 @@ var init_reportingTerminal = __esm({
37602
37768
  }
37603
37769
  }
37604
37770
  if (context.replayErrors.length) {
37605
- lines.push("", import_chalk50.default.red("Replay errors"));
37771
+ lines.push("", import_chalk51.default.red("Replay errors"));
37606
37772
  for (const error of context.replayErrors.slice(0, context.detailLimit)) {
37607
37773
  lines.push(`- ${error.strategy} ${error.symbol}: ${error.message}`);
37608
37774
  }
@@ -37620,7 +37786,7 @@ var init_reportingTerminal = __esm({
37620
37786
  printRuntimeDuplicateDetails = (groups) => {
37621
37787
  if (!groups.length) return;
37622
37788
  console.log("");
37623
- console.log(import_chalk50.default.yellow("Runtime duplicates"));
37789
+ console.log(import_chalk51.default.yellow("Runtime duplicates"));
37624
37790
  for (const group of groups.slice(0, DETAIL_LIMIT)) {
37625
37791
  const ids = group.entries.map((entry) => entry.orderId ?? entry.id);
37626
37792
  console.log(
@@ -37634,7 +37800,7 @@ var init_reportingTerminal = __esm({
37634
37800
  printClassifiedBacktestOnlyDetails = (classifiedEntries) => {
37635
37801
  if (!classifiedEntries.length) return;
37636
37802
  console.log("");
37637
- console.log(import_chalk50.default.yellow("Backtest only"));
37803
+ console.log(import_chalk51.default.yellow("Backtest only"));
37638
37804
  for (const item of classifiedEntries.slice(0, DETAIL_LIMIT)) {
37639
37805
  const evidenceSuffix = item.signal ? ` signalId=${item.signal.signalId} signalDrift=${formatMinutes2(item.signalTimestampDiffMs ?? null)}` : item.evaluation ? ` evaluationId=${item.evaluation.evaluationId} evaluationDrift=${formatMinutes2(item.evaluationTimestampDiffMs ?? null)}` : "";
37640
37806
  const price = item.entry.price == null ? "n/a" : item.entry.price.toFixed(6);
@@ -37649,7 +37815,7 @@ var init_reportingTerminal = __esm({
37649
37815
  printClassifiedRuntimeOnlyDetails = (classifiedEntries) => {
37650
37816
  if (!classifiedEntries.length) return;
37651
37817
  console.log("");
37652
- console.log(import_chalk50.default.yellow("Runtime only"));
37818
+ console.log(import_chalk51.default.yellow("Runtime only"));
37653
37819
  for (const item of classifiedEntries.slice(0, DETAIL_LIMIT)) {
37654
37820
  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}` : "";
37655
37821
  const price = item.entry.price == null ? "n/a" : item.entry.price.toFixed(6);
@@ -37665,7 +37831,7 @@ var init_reportingTerminal = __esm({
37665
37831
  });
37666
37832
 
37667
37833
  // src/lib/runtimeParity/reportingTelegram.ts
37668
- var TELEGRAM_DETAIL_LIMIT, SUMMARY_TIMEZONE, SUMMARY_TIMEZONE_LABEL, escapeHtml6, formatMskDateTime2, buildRuntimeParityMessage, buildRuntimeParityNoTargetsMessage;
37834
+ var TELEGRAM_DETAIL_LIMIT, SUMMARY_TIMEZONE, SUMMARY_TIMEZONE_LABEL, escapeHtml7, formatMskDateTime3, buildRuntimeParityMessage, buildRuntimeParityNoTargetsMessage;
37669
37835
  var init_reportingTelegram = __esm({
37670
37836
  "src/lib/runtimeParity/reportingTelegram.ts"() {
37671
37837
  "use strict";
@@ -37674,8 +37840,8 @@ var init_reportingTelegram = __esm({
37674
37840
  TELEGRAM_DETAIL_LIMIT = 5;
37675
37841
  SUMMARY_TIMEZONE = "Europe/Moscow";
37676
37842
  SUMMARY_TIMEZONE_LABEL = "MSK";
37677
- escapeHtml6 = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
37678
- formatMskDateTime2 = (timestamp) => new Intl.DateTimeFormat("ru-RU", {
37843
+ escapeHtml7 = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
37844
+ formatMskDateTime3 = (timestamp) => new Intl.DateTimeFormat("ru-RU", {
37679
37845
  timeZone: SUMMARY_TIMEZONE,
37680
37846
  year: "numeric",
37681
37847
  month: "2-digit",
@@ -37694,11 +37860,11 @@ var init_reportingTelegram = __esm({
37694
37860
  lines.push("");
37695
37861
  lines.push("\u{1F552} <b>Window</b>");
37696
37862
  lines.push(
37697
- `<b>${escapeHtml6(formatMskDateTime2(context.window.start))} - ${escapeHtml6(formatMskDateTime2(context.window.end))} ${SUMMARY_TIMEZONE_LABEL}</b>`
37863
+ `<b>${escapeHtml7(formatMskDateTime3(context.window.start))} - ${escapeHtml7(formatMskDateTime3(context.window.end))} ${SUMMARY_TIMEZONE_LABEL}</b>`
37698
37864
  );
37699
37865
  lines.push("");
37700
- lines.push(`\u{1F50C} Connector: <b>${escapeHtml6(context.connectorName)}</b>`);
37701
- lines.push(`\u{1F9EC} Replay env: <b>${escapeHtml6(context.replayEnv)}</b>`);
37866
+ lines.push(`\u{1F50C} Connector: <b>${escapeHtml7(context.connectorName)}</b>`);
37867
+ lines.push(`\u{1F9EC} Replay env: <b>${escapeHtml7(context.replayEnv)}</b>`);
37702
37868
  lines.push(
37703
37869
  `\u{1F3AF} Tolerance: <b>${context.toleranceBars} bar(s) / ${(context.toleranceMs / 6e4).toFixed(0)}m</b>`
37704
37870
  );
@@ -37708,28 +37874,28 @@ var init_reportingTelegram = __esm({
37708
37874
  `\u2022 Targets: <b>${context.replayTargetsCount}</b> / compared <b>${context.comparedTargetsCount}</b> / errors <b>${context.replayErrors.length}</b>`
37709
37875
  );
37710
37876
  lines.push(
37711
- `\u2022 Sources: <b>${escapeHtml6(formatSourceCountsSummary(context.sourceCounts))}</b>`
37877
+ `\u2022 Sources: <b>${escapeHtml7(formatSourceCountsSummary(context.sourceCounts))}</b>`
37712
37878
  );
37713
37879
  lines.push("");
37714
37880
  lines.push("\u{1F4C8} <b>Entries</b>");
37715
37881
  lines.push(
37716
- `\u2022 Runtime: <b>${escapeHtml6(formatRuntimeEntriesSummary(context))}</b>`
37882
+ `\u2022 Runtime: <b>${escapeHtml7(formatRuntimeEntriesSummary(context))}</b>`
37717
37883
  );
37718
37884
  lines.push(`\u2022 Backtest: <b>${context.backtestEntriesCount}</b>`);
37719
37885
  lines.push(
37720
37886
  `\u2022 Runtime only: <b>${context.runtimeOnlyCount}</b> / Backtest only: <b>${context.backtestOnlyCount}</b>`
37721
37887
  );
37722
37888
  lines.push(
37723
- `\u2022 Matched deltas: price avg/max=<b>${escapeHtml6(formatPercent5(context.matchedSummary.avgPriceDeltaPct))} / ${escapeHtml6(formatPercent5(context.matchedSummary.maxPriceDeltaPct))}</b>, time avg/max=<b>${escapeHtml6(formatMinutes2(context.matchedSummary.avgTimestampDiffMs))} / ${escapeHtml6(formatMinutes2(context.matchedSummary.maxTimestampDiffMs))}</b>`
37889
+ `\u2022 Matched deltas: price avg/max=<b>${escapeHtml7(formatPercent5(context.matchedSummary.avgPriceDeltaPct))} / ${escapeHtml7(formatPercent5(context.matchedSummary.maxPriceDeltaPct))}</b>, time avg/max=<b>${escapeHtml7(formatMinutes2(context.matchedSummary.avgTimestampDiffMs))} / ${escapeHtml7(formatMinutes2(context.matchedSummary.maxTimestampDiffMs))}</b>`
37724
37890
  );
37725
37891
  if (context.classifiedRuntimeOnly.length) {
37726
37892
  lines.push(
37727
- `\u2022 Runtime-only classes: <code>${escapeHtml6(summarizeRuntimeOnlyClassifications(context.classifiedRuntimeOnly))}</code>`
37893
+ `\u2022 Runtime-only classes: <code>${escapeHtml7(summarizeRuntimeOnlyClassifications(context.classifiedRuntimeOnly))}</code>`
37728
37894
  );
37729
37895
  }
37730
37896
  if (context.classifiedBacktestOnly.length) {
37731
37897
  lines.push(
37732
- `\u2022 Backtest-only classes: <code>${escapeHtml6(summarizeBacktestOnlyClassifications(context.classifiedBacktestOnly))}</code>`
37898
+ `\u2022 Backtest-only classes: <code>${escapeHtml7(summarizeBacktestOnlyClassifications(context.classifiedBacktestOnly))}</code>`
37733
37899
  );
37734
37900
  }
37735
37901
  if (context.runtimeSignalEvaluationsCount) {
@@ -37742,7 +37908,7 @@ var init_reportingTelegram = __esm({
37742
37908
  lines.push("");
37743
37909
  lines.push("\u{1F50E} <b>Mismatches</b>");
37744
37910
  for (const item of mismatchRows.slice(0, TELEGRAM_DETAIL_LIMIT)) {
37745
- lines.push(`\u2022 <code>${escapeHtml6(item.line)}</code>`);
37911
+ lines.push(`\u2022 <code>${escapeHtml7(item.line)}</code>`);
37746
37912
  }
37747
37913
  if (mismatchRows.length > TELEGRAM_DETAIL_LIMIT) {
37748
37914
  lines.push(
@@ -37755,7 +37921,7 @@ var init_reportingTelegram = __esm({
37755
37921
  lines.push("");
37756
37922
  lines.push("\u{1F4CA} <b>Strategy issues</b>");
37757
37923
  for (const line of strategyIssueRows) {
37758
- lines.push(`\u2022 ${escapeHtml6(line.slice(2))}`);
37924
+ lines.push(`\u2022 ${escapeHtml7(line.slice(2))}`);
37759
37925
  }
37760
37926
  } else if (context.strategyRows.length) {
37761
37927
  lines.push("");
@@ -37770,7 +37936,7 @@ var init_reportingTelegram = __esm({
37770
37936
  ...runtimeGateWarningCounts.entries()
37771
37937
  ].sort(([left], [right]) => left.localeCompare(right))) {
37772
37938
  lines.push(
37773
- `\u2022 <b>${escapeHtml6(strategy)}</b>: AI/ML runtime gates configured on <b>${count}</b> target(s); BACKTEST replay covers core execution only.`
37939
+ `\u2022 <b>${escapeHtml7(strategy)}</b>: AI/ML runtime gates configured on <b>${count}</b> target(s); BACKTEST replay covers core execution only.`
37774
37940
  );
37775
37941
  }
37776
37942
  }
@@ -37779,7 +37945,7 @@ var init_reportingTelegram = __esm({
37779
37945
  lines.push("\u274C <b>Replay errors</b>");
37780
37946
  for (const error of context.replayErrors.slice(0, TELEGRAM_DETAIL_LIMIT)) {
37781
37947
  lines.push(
37782
- `\u2022 <b>${escapeHtml6(error.strategy)}</b> ${escapeHtml6(error.symbol)}: <code>${escapeHtml6(error.message)}</code>`
37948
+ `\u2022 <b>${escapeHtml7(error.strategy)}</b> ${escapeHtml7(error.symbol)}: <code>${escapeHtml7(error.message)}</code>`
37783
37949
  );
37784
37950
  }
37785
37951
  if (context.replayErrors.length > TELEGRAM_DETAIL_LIMIT) {
@@ -37799,12 +37965,12 @@ var init_reportingTelegram = __esm({
37799
37965
  "\u{1F9EA} <b>TradeJS runtime parity</b>",
37800
37966
  "",
37801
37967
  "\u{1F552} <b>Window</b>",
37802
- `<b>${escapeHtml6(formatMskDateTime2(window.start))} - ${escapeHtml6(formatMskDateTime2(window.end))} ${SUMMARY_TIMEZONE_LABEL}</b>`,
37968
+ `<b>${escapeHtml7(formatMskDateTime3(window.start))} - ${escapeHtml7(formatMskDateTime3(window.end))} ${SUMMARY_TIMEZONE_LABEL}</b>`,
37803
37969
  "",
37804
- `\u{1F50C} Connector: <b>${escapeHtml6(connectorName)}</b>`,
37805
- `\u{1F9EC} Replay env: <b>${escapeHtml6(replayEnv)}</b>`,
37970
+ `\u{1F50C} Connector: <b>${escapeHtml7(connectorName)}</b>`,
37971
+ `\u{1F9EC} Replay env: <b>${escapeHtml7(replayEnv)}</b>`,
37806
37972
  "",
37807
- `\u26A0\uFE0F No replay targets found for user <b>${escapeHtml6(userName3)}</b>.`
37973
+ `\u26A0\uFE0F No replay targets found for user <b>${escapeHtml7(userName3)}</b>.`
37808
37974
  ].join("\n");
37809
37975
  }
37810
37976
  });
@@ -37824,17 +37990,17 @@ var init_reporting = __esm({
37824
37990
  var runtimeParity_exports = {};
37825
37991
  __export(runtimeParity_exports, {
37826
37992
  buildRuntimeParityMessage: () => buildRuntimeParityMessage,
37827
- main: () => main43,
37993
+ main: () => main44,
37828
37994
  runtimeParity: () => runtimeParity
37829
37995
  });
37830
- var import_config11, import_node_crypto18, import_args33, import_chalk51, import_constants19, import_time13, import_logger7, import_redis20, import_cli12, import_backtest7, import_connectors15, flags30, interval3, projectRoot15, DEFAULT_LOOKBACK_DAYS, DETAIL_LIMIT2, DEFAULT_REPLAY_ENV, resolveParityConnectorName, createConnector, buildReplayAiAnalyses, formatReplayEnvSummary, buildReplayConfig, warmReplayHistory, runtimeParity, main43;
37996
+ var import_config11, import_node_crypto18, import_args34, import_chalk52, import_constants19, import_time13, import_logger7, import_redis20, import_cli12, import_backtest7, import_connectors15, flags31, interval3, projectRoot16, DEFAULT_LOOKBACK_DAYS, DETAIL_LIMIT2, DEFAULT_REPLAY_ENV, resolveParityConnectorName, createConnector, buildReplayAiAnalyses, formatReplayEnvSummary, buildReplayConfig, warmReplayHistory, runtimeParity, main44;
37831
37997
  var init_runtimeParity2 = __esm({
37832
37998
  "src/scripts/runtimeParity.ts"() {
37833
37999
  "use strict";
37834
38000
  import_config11 = require("dotenv/config");
37835
38001
  import_node_crypto18 = require("crypto");
37836
- import_args33 = __toESM(require("args"));
37837
- import_chalk51 = __toESM(require("chalk"));
38002
+ import_args34 = __toESM(require("args"));
38003
+ import_chalk52 = __toESM(require("chalk"));
37838
38004
  import_constants19 = require("@tradejs/core/constants");
37839
38005
  import_time13 = require("@tradejs/core/time");
37840
38006
  import_logger7 = require("@tradejs/infra/logger");
@@ -37857,45 +38023,45 @@ var init_runtimeParity2 = __esm({
37857
38023
  init_reporting();
37858
38024
  init_reporting();
37859
38025
  init_runtimeModeConfig();
37860
- import_args33.default.option(["u", "user"], "Use user config", "root");
37861
- import_args33.default.option(
38026
+ import_args34.default.option(["u", "user"], "Use user config", "root");
38027
+ import_args34.default.option(
37862
38028
  ["o", "connector"],
37863
38029
  "Connector provider or name for parity replay (e.g. bybit, binance, coinbase, custom)",
37864
38030
  "bybit"
37865
38031
  );
37866
- import_args33.default.option(["d", "days"], "Replay window in days", 3);
37867
- import_args33.default.option(
38032
+ import_args34.default.option(["d", "days"], "Replay window in days", 3);
38033
+ import_args34.default.option(
37868
38034
  ["b", "startTime"],
37869
38035
  "Explicit replay start timestamp (ms or seconds)"
37870
38036
  );
37871
- import_args33.default.option(["e", "endTime"], "Explicit replay end timestamp (ms or seconds)");
37872
- import_args33.default.option(["s", "strategy"], "Only compare one strategy");
37873
- import_args33.default.option(
38037
+ import_args34.default.option(["e", "endTime"], "Explicit replay end timestamp (ms or seconds)");
38038
+ import_args34.default.option(["s", "strategy"], "Only compare one strategy");
38039
+ import_args34.default.option(
37874
38040
  ["t", "tickers"],
37875
38041
  "Replay comma-separated symbols for all configured strategies"
37876
38042
  );
37877
- import_args33.default.option(
38043
+ import_args34.default.option(
37878
38044
  ["C", "cacheOnly"],
37879
38045
  "Do not refresh market history before replay",
37880
38046
  false
37881
38047
  );
37882
- import_args33.default.option(
38048
+ import_args34.default.option(
37883
38049
  ["a", "toleranceBars"],
37884
38050
  "Allowed entry timestamp drift in bars when matching runtime vs backtest",
37885
38051
  1
37886
38052
  );
37887
- import_args33.default.option(
38053
+ import_args34.default.option(
37888
38054
  "fullUniverse",
37889
38055
  "Replay every configured strategy across the full connector universe. By default parity replays only runtime-traded and strategy-results symbols unless --tickers is provided.",
37890
38056
  false
37891
38057
  );
37892
- import_args33.default.option(
38058
+ import_args34.default.option(
37893
38059
  "runtimeGates",
37894
38060
  "Force runtime AI/ML gates for all replay targets. Runtime-gated configs are replayed with gates by default.",
37895
38061
  false
37896
38062
  );
37897
- import_args33.default.option(["N", "notify"], "Send parity summary to Telegram", false);
37898
- import_args33.default.option(["D", "details"], "Print unmatched entry details (capped)", false);
38063
+ import_args34.default.option(["N", "notify"], "Send parity summary to Telegram", false);
38064
+ import_args34.default.option(["D", "details"], "Print unmatched entry details (capped)", false);
37899
38065
  process.argv = normalizeCliArgv(process.argv, {
37900
38066
  "-C": "--cacheOnly",
37901
38067
  "-D": "--details",
@@ -37904,14 +38070,14 @@ var init_runtimeParity2 = __esm({
37904
38070
  "-S": "--startTime",
37905
38071
  "-T": "--toleranceBars"
37906
38072
  });
37907
- flags30 = import_args33.default.parse(process.argv);
38073
+ flags31 = import_args34.default.parse(process.argv);
37908
38074
  interval3 = "15";
37909
- projectRoot15 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
38075
+ projectRoot16 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
37910
38076
  DEFAULT_LOOKBACK_DAYS = 3;
37911
38077
  DETAIL_LIMIT2 = 10;
37912
- DEFAULT_REPLAY_ENV = flags30.runtimeGates ? "PARITY" : "BACKTEST";
38078
+ DEFAULT_REPLAY_ENV = flags31.runtimeGates ? "PARITY" : "BACKTEST";
37913
38079
  resolveParityConnectorName = async (value) => {
37914
- const connectorName = await (0, import_connectors15.resolveConnectorName)(value, projectRoot15);
38080
+ const connectorName = await (0, import_connectors15.resolveConnectorName)(value, projectRoot16);
37915
38081
  if (connectorName) {
37916
38082
  return connectorName;
37917
38083
  }
@@ -37928,7 +38094,7 @@ var init_runtimeParity2 = __esm({
37928
38094
  }) => {
37929
38095
  const connectorFactory = await (0, import_connectors15.getConnectorCreatorByName)(
37930
38096
  connectorName,
37931
- projectRoot15
38097
+ projectRoot16
37932
38098
  );
37933
38099
  if (!connectorFactory) {
37934
38100
  throw new Error(`Connector "${connectorName}" is not registered`);
@@ -38020,7 +38186,7 @@ var init_runtimeParity2 = __esm({
38020
38186
  strategyConfig,
38021
38187
  env: resolveReplayStrategyEnv({
38022
38188
  strategyConfig,
38023
- forceRuntimeGates: Boolean(flags30.runtimeGates)
38189
+ forceRuntimeGates: Boolean(flags31.runtimeGates)
38024
38190
  }),
38025
38191
  interval: interval3,
38026
38192
  makeOrders: true,
@@ -38039,7 +38205,7 @@ var init_runtimeParity2 = __esm({
38039
38205
  const symbols = [...new Set(targets.map((target) => target.symbol))];
38040
38206
  const warmStartedAt = Date.now();
38041
38207
  console.log(
38042
- import_chalk51.default.gray(
38208
+ import_chalk52.default.gray(
38043
38209
  `Warm history: ${symbols.length} symbol(s) on ${connectorName}, preload ${(0, import_time13.formatUnix)(preloadStart)} -> ${(0, import_time13.formatUnix)(preloadEnd)}`
38044
38210
  )
38045
38211
  );
@@ -38047,7 +38213,7 @@ var init_runtimeParity2 = __esm({
38047
38213
  connectorName,
38048
38214
  marketConnector: connector,
38049
38215
  userName: userName3,
38050
- projectRoot: projectRoot15,
38216
+ projectRoot: projectRoot16,
38051
38217
  shouldUseDedicatedReferences: true,
38052
38218
  warn: (message) => import_logger7.logger.warn(message)
38053
38219
  });
@@ -38059,39 +38225,39 @@ var init_runtimeParity2 = __esm({
38059
38225
  symbols,
38060
38226
  preloadStart,
38061
38227
  preloadEnd,
38062
- log: (message) => console.log(import_chalk51.default.gray(message))
38228
+ log: (message) => console.log(import_chalk52.default.gray(message))
38063
38229
  });
38064
38230
  console.log(
38065
- import_chalk51.default.gray(`Warm history: done in ${formatDuration(warmStartedAt)}`)
38231
+ import_chalk52.default.gray(`Warm history: done in ${formatDuration(warmStartedAt)}`)
38066
38232
  );
38067
38233
  };
38068
38234
  runtimeParity = async () => {
38069
38235
  const window = resolveTimeWindow({
38070
- days: flags30.days ?? DEFAULT_LOOKBACK_DAYS,
38071
- startTime: flags30.startTime,
38072
- endTime: flags30.endTime,
38236
+ days: flags31.days ?? DEFAULT_LOOKBACK_DAYS,
38237
+ startTime: flags31.startTime,
38238
+ endTime: flags31.endTime,
38073
38239
  defaultStartMs: Date.now() - DEFAULT_LOOKBACK_DAYS * 24 * 60 * 60 * 1e3,
38074
38240
  defaultEndMs: Date.now()
38075
38241
  });
38076
38242
  const toleranceBars = Math.max(
38077
38243
  0,
38078
- Number.parseInt(String(flags30.toleranceBars ?? 1), 10) || 0
38244
+ Number.parseInt(String(flags31.toleranceBars ?? 1), 10) || 0
38079
38245
  );
38080
38246
  const toleranceMs = toleranceBars * 15 * 60 * 1e3;
38081
- const connectorName = await resolveParityConnectorName(flags30.connector);
38082
- const requestedSymbols = parseSymbolsFromCLI2(String(flags30.tickers || ""));
38247
+ const connectorName = await resolveParityConnectorName(flags31.connector);
38248
+ const requestedSymbols = parseSymbolsFromCLI2(String(flags31.tickers || ""));
38083
38249
  const requestedSymbolSet = requestedSymbols.length ? new Set(requestedSymbols) : null;
38084
38250
  let replayErrors = [];
38085
38251
  try {
38086
38252
  const parityConnector = await createConnector({
38087
- userName: flags30.user,
38253
+ userName: flags31.user,
38088
38254
  connectorName
38089
38255
  });
38090
38256
  const { runtimeTrades, runtimeSignals, runtimeSignalEvaluations } = await loadRuntimeParityEvidence(
38091
38257
  {
38092
- userName: flags30.user,
38258
+ userName: flags31.user,
38093
38259
  window,
38094
- strategy: flags30.strategy,
38260
+ strategy: flags31.strategy,
38095
38261
  symbols: requestedSymbolSet
38096
38262
  },
38097
38263
  {
@@ -38106,29 +38272,29 @@ var init_runtimeParity2 = __esm({
38106
38272
  runtimeSignalEvaluations
38107
38273
  });
38108
38274
  const replayTargets = await buildReplayTargets({
38109
- userName: flags30.user,
38275
+ userName: flags31.user,
38110
38276
  runtimeTrades,
38111
38277
  connectorSymbols,
38112
- strategyFilter: String(flags30.strategy || "").trim() || void 0,
38278
+ strategyFilter: String(flags31.strategy || "").trim() || void 0,
38113
38279
  explicitSymbols: requestedSymbols,
38114
- includeConnectorUniverse: Boolean(flags30.fullUniverse)
38280
+ includeConnectorUniverse: Boolean(flags31.fullUniverse)
38115
38281
  });
38116
38282
  if (!replayTargets.length) {
38117
38283
  console.log(
38118
- import_chalk51.default.yellow(
38119
- `No replay targets found for ${flags30.user} in ${(0, import_time13.formatUnix)(window.start)} -> ${(0, import_time13.formatUnix)(window.end)}.`
38284
+ import_chalk52.default.yellow(
38285
+ `No replay targets found for ${flags31.user} in ${(0, import_time13.formatUnix)(window.start)} -> ${(0, import_time13.formatUnix)(window.end)}.`
38120
38286
  )
38121
38287
  );
38122
- if (flags30.notify) {
38288
+ if (flags31.notify) {
38123
38289
  await sendTelegramReport(
38124
38290
  buildRuntimeParityNoTargetsMessage({
38125
38291
  window,
38126
38292
  connectorName,
38127
38293
  replayEnv: DEFAULT_REPLAY_ENV,
38128
- runtimeGatesEnabled: Boolean(flags30.runtimeGates),
38129
- userName: String(flags30.user)
38294
+ runtimeGatesEnabled: Boolean(flags31.runtimeGates),
38295
+ userName: String(flags31.user)
38130
38296
  }),
38131
- { userName: flags30.user }
38297
+ { userName: flags31.user }
38132
38298
  );
38133
38299
  }
38134
38300
  return;
@@ -38143,14 +38309,14 @@ var init_runtimeParity2 = __esm({
38143
38309
  replayTargets.map((target) => target.symbol)
38144
38310
  ).size;
38145
38311
  console.log(
38146
- import_chalk51.default.gray(
38147
- `Replay queue: ${replayTargets.length} target(s), ${replaySymbolsCount} symbol(s), mode=${flags30.fullUniverse ? "full-universe" : requestedSymbols.length ? "explicit-tickers" : "runtime+results"}`
38312
+ import_chalk52.default.gray(
38313
+ `Replay queue: ${replayTargets.length} target(s), ${replaySymbolsCount} symbol(s), mode=${flags31.fullUniverse ? "full-universe" : requestedSymbols.length ? "explicit-tickers" : "runtime+results"}`
38148
38314
  )
38149
38315
  );
38150
38316
  const replayConfigs = /* @__PURE__ */ new Map();
38151
38317
  for (const target of replayTargets) {
38152
38318
  const replayConfig = await buildReplayConfig({
38153
- userName: flags30.user,
38319
+ userName: flags31.user,
38154
38320
  strategy: target.strategy,
38155
38321
  symbol: target.symbol,
38156
38322
  replayInputsIndex,
@@ -38167,22 +38333,22 @@ var init_runtimeParity2 = __esm({
38167
38333
  );
38168
38334
  await prepareMarketContextForRun({
38169
38335
  mode: "parity",
38170
- userName: flags30.user,
38171
- projectRoot: projectRoot15,
38336
+ userName: flags31.user,
38337
+ projectRoot: projectRoot16,
38172
38338
  symbols: replayTargets.map((target) => target.symbol),
38173
38339
  interval: interval3,
38174
38340
  startMs: window.start,
38175
38341
  endMs: window.end,
38176
38342
  preloadStartMs: preloadStart,
38177
- cacheOnly: Boolean(flags30.cacheOnly),
38343
+ cacheOnly: Boolean(flags31.cacheOnly),
38178
38344
  aiEnabled: hasParityAiTargets,
38179
38345
  mlEnabled: hasParityMlTargets,
38180
38346
  strategyNames: replayTargets.map((target) => target.strategy),
38181
- log: (message) => console.log(import_chalk51.default.gray(message))
38347
+ log: (message) => console.log(import_chalk52.default.gray(message))
38182
38348
  });
38183
- if (!flags30.cacheOnly) {
38349
+ if (!flags31.cacheOnly) {
38184
38350
  await warmReplayHistory({
38185
- userName: flags30.user,
38351
+ userName: flags31.user,
38186
38352
  connectorName,
38187
38353
  targets: replayTargets,
38188
38354
  preloadStart,
@@ -38209,7 +38375,7 @@ var init_runtimeParity2 = __esm({
38209
38375
  );
38210
38376
  }
38211
38377
  const result = await (0, import_backtest7.testing)({
38212
- userName: flags30.user,
38378
+ userName: flags31.user,
38213
38379
  symbol: target.symbol,
38214
38380
  options: {
38215
38381
  start: window.start,
@@ -38238,15 +38404,15 @@ var init_runtimeParity2 = __esm({
38238
38404
  });
38239
38405
  } finally {
38240
38406
  (0, import_backtest7.releaseTestingSymbolCache)({
38241
- cwd: projectRoot15,
38242
- userName: flags30.user,
38407
+ cwd: projectRoot16,
38408
+ userName: flags31.user,
38243
38409
  connectorName,
38244
38410
  symbol: target.symbol
38245
38411
  });
38246
38412
  }
38247
38413
  if (progressPosition === 1 || progressPosition === replayTargets.length || progressPosition % 25 === 0) {
38248
38414
  console.log(
38249
- import_chalk51.default.gray(
38415
+ import_chalk52.default.gray(
38250
38416
  `Replay progress: ${progressPosition}/${replayTargets.length}, ok=${successfulTargetKeys.size}, errors=${replayErrors.length}, current=${target.strategy} ${target.symbol}, elapsed=${formatDuration(replayStartedAt)}`
38251
38417
  )
38252
38418
  );
@@ -38277,8 +38443,8 @@ var init_runtimeParity2 = __esm({
38277
38443
  window,
38278
38444
  connectorName,
38279
38445
  replayEnv: replayEnvSummary,
38280
- runtimeGatesEnabled: Boolean(flags30.runtimeGates) || replayEnvSummary.includes("PARITY"),
38281
- runtimeGatesRequested: Boolean(flags30.runtimeGates),
38446
+ runtimeGatesEnabled: Boolean(flags31.runtimeGates) || replayEnvSummary.includes("PARITY"),
38447
+ runtimeGatesRequested: Boolean(flags31.runtimeGates),
38282
38448
  toleranceBars,
38283
38449
  toleranceMs,
38284
38450
  replayTargetsCount: replayTargets.length,
@@ -38301,12 +38467,12 @@ var init_runtimeParity2 = __esm({
38301
38467
  detailLimit: DETAIL_LIMIT2
38302
38468
  })
38303
38469
  );
38304
- if (flags30.details) {
38470
+ if (flags31.details) {
38305
38471
  printRuntimeDuplicateDetails(runtimeDedupe.duplicateGroups);
38306
38472
  printClassifiedRuntimeOnlyDetails(classifiedRuntimeOnly);
38307
38473
  printClassifiedBacktestOnlyDetails(classifiedBacktestOnly);
38308
38474
  }
38309
- if (flags30.notify) {
38475
+ if (flags31.notify) {
38310
38476
  const mismatchAttachment = buildRuntimeParityMismatchAttachment({
38311
38477
  window,
38312
38478
  connectorName,
@@ -38335,7 +38501,7 @@ var init_runtimeParity2 = __esm({
38335
38501
  window,
38336
38502
  connectorName,
38337
38503
  replayEnv: replayEnvSummary,
38338
- runtimeGatesEnabled: Boolean(flags30.runtimeGates) || replayEnvSummary.includes("PARITY"),
38504
+ runtimeGatesEnabled: Boolean(flags31.runtimeGates) || replayEnvSummary.includes("PARITY"),
38339
38505
  toleranceBars,
38340
38506
  toleranceMs,
38341
38507
  replayTargetsCount: replayTargets.length,
@@ -38357,16 +38523,16 @@ var init_runtimeParity2 = __esm({
38357
38523
  runtimeGateWarningCounts
38358
38524
  }),
38359
38525
  {
38360
- userName: flags30.user,
38526
+ userName: flags31.user,
38361
38527
  attachments: mismatchAttachment ? [mismatchAttachment] : void 0
38362
38528
  }
38363
38529
  );
38364
38530
  }
38365
38531
  } finally {
38366
- (0, import_backtest7.resetTestingKlineCache)(projectRoot15);
38532
+ (0, import_backtest7.resetTestingKlineCache)(projectRoot16);
38367
38533
  }
38368
38534
  };
38369
- main43 = runtimeParity;
38535
+ main44 = runtimeParity;
38370
38536
  }
38371
38537
  });
38372
38538
 
@@ -38380,11 +38546,11 @@ var init_runtimeStrategies = __esm({
38380
38546
  });
38381
38547
 
38382
38548
  // src/lib/signals/skipStats.ts
38383
- var import_chalk52, import_logger8, createStrategySkipStats, recordStrategyReason, logStrategySkipStats;
38549
+ var import_chalk53, import_logger8, createStrategySkipStats, recordStrategyReason, logStrategySkipStats;
38384
38550
  var init_skipStats = __esm({
38385
38551
  "src/lib/signals/skipStats.ts"() {
38386
38552
  "use strict";
38387
- import_chalk52 = __toESM(require("chalk"));
38553
+ import_chalk53 = __toESM(require("chalk"));
38388
38554
  import_logger8 = require("@tradejs/infra/logger");
38389
38555
  init_runtimeSignalsStorage();
38390
38556
  createStrategySkipStats = (runtimeStrategies) => new Map(
@@ -38410,7 +38576,7 @@ var init_skipStats = __esm({
38410
38576
  );
38411
38577
  };
38412
38578
  logStrategySkipStats = (runtimeStrategies, strategyStats) => {
38413
- import_logger8.logger.info(import_chalk52.default.yellow("skip stats:"));
38579
+ import_logger8.logger.info(import_chalk53.default.yellow("skip stats:"));
38414
38580
  for (const { strategyName } of runtimeStrategies) {
38415
38581
  const stats = strategyStats.get(strategyName);
38416
38582
  if (!stats) {
@@ -39425,12 +39591,12 @@ var init_configuredScopes = __esm({
39425
39591
  });
39426
39592
 
39427
39593
  // src/lib/signals/runner.ts
39428
- var import_progress12, import_chalk53, import_connectors17, import_cli13, import_async5, import_strategies14, import_constants20, import_time14, import_logger11, import_runtimeDeploymentEvents, import_runtimeHeartbeats, import_runtimeStrategies8, SLOW_SIGNALS_WARNING_MS, formatDuration3, resolvePositiveInteger2, resolveNonNegativeInteger, createSignalsRunner;
39594
+ var import_progress12, import_chalk54, import_connectors17, import_cli13, import_async5, import_strategies14, import_constants20, import_time14, import_logger11, import_runtimeDeploymentEvents, import_runtimeHeartbeats, import_runtimeStrategies8, SLOW_SIGNALS_WARNING_MS, formatDuration3, resolvePositiveInteger2, resolveNonNegativeInteger, createSignalsRunner;
39429
39595
  var init_runner = __esm({
39430
39596
  "src/lib/signals/runner.ts"() {
39431
39597
  "use strict";
39432
39598
  import_progress12 = __toESM(require("progress"));
39433
- import_chalk53 = __toESM(require("chalk"));
39599
+ import_chalk54 = __toESM(require("chalk"));
39434
39600
  import_connectors17 = require("@tradejs/node/connectors");
39435
39601
  import_cli13 = require("@tradejs/node/cli");
39436
39602
  import_async5 = require("@tradejs/core/async");
@@ -39476,10 +39642,10 @@ var init_runner = __esm({
39476
39642
  };
39477
39643
  createSignalsRunner = (config2) => {
39478
39644
  const interval4 = config2.interval;
39479
- const projectRoot17 = config2.projectRoot?.trim() || String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
39645
+ const projectRoot18 = config2.projectRoot?.trim() || String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
39480
39646
  const compositionSnapshotRecorder = process.env.TRADEJS_PROJECT_SHA && process.env.TRADEJS_PROJECT_IMAGE_DIGEST && config2.deploymentId ? createRuntimeEvidenceCompositionSnapshotRecorder({
39481
39647
  persist: (compositionId) => captureRuntimeEvidenceCompositionSnapshot({
39482
- projectRoot: projectRoot17,
39648
+ projectRoot: projectRoot18,
39483
39649
  userName: config2.userName,
39484
39650
  deploymentId: config2.deploymentId,
39485
39651
  expectedCompositionId: compositionId
@@ -39512,7 +39678,7 @@ var init_runner = __esm({
39512
39678
  const timeOperation3 = (label, operation) => timeOperation(
39513
39679
  label,
39514
39680
  operation,
39515
- (message) => import_logger11.logger.info(import_chalk53.default.gray(message))
39681
+ (message) => import_logger11.logger.info(import_chalk54.default.gray(message))
39516
39682
  );
39517
39683
  const formatSlowSignalsWarning = (params) => [
39518
39684
  "<b>Slow yarn signals run</b>",
@@ -39522,7 +39688,7 @@ var init_runner = __esm({
39522
39688
  `Found signals: <b>${params.found}</b>`
39523
39689
  ].join("\n");
39524
39690
  const resolveSignalsConnectorName = async (value) => {
39525
- const connectorName = await (0, import_connectors17.resolveConnectorName)(value, projectRoot17);
39691
+ const connectorName = await (0, import_connectors17.resolveConnectorName)(value, projectRoot18);
39526
39692
  if (!connectorName) {
39527
39693
  throw new Error(
39528
39694
  `Unknown runtime connector: ${String(value || "").trim() || String(value)}`
@@ -39533,7 +39699,7 @@ var init_runner = __esm({
39533
39699
  const createSignalsSession2 = async (lifecycle, scope = {}) => {
39534
39700
  const deployment = config2.deploymentId ? await (0, import_runtimeStrategies8.getRuntimeDeployment)({
39535
39701
  userName: config2.userName,
39536
- projectRoot: projectRoot17,
39702
+ projectRoot: projectRoot18,
39537
39703
  deploymentId: config2.deploymentId
39538
39704
  }) : null;
39539
39705
  if (config2.deploymentId && !deployment) {
@@ -39552,7 +39718,7 @@ var init_runner = __esm({
39552
39718
  const requestedAccountId = deployment?.accountId ?? scope.accountId ?? config2.accountId;
39553
39719
  const connectorFactory = await (0, import_connectors17.getConnectorCreatorByName)(
39554
39720
  connectorName,
39555
- projectRoot17
39721
+ projectRoot18
39556
39722
  );
39557
39723
  if (!connectorFactory) {
39558
39724
  throw new Error(`Connector "${connectorName}" is not registered`);
@@ -39567,7 +39733,7 @@ var init_runner = __esm({
39567
39733
  connectorName,
39568
39734
  marketConnector,
39569
39735
  userName: config2.userName,
39570
- projectRoot: projectRoot17,
39736
+ projectRoot: projectRoot18,
39571
39737
  shouldUseDedicatedReferences: universe === "crypto" && connectorName.toLowerCase() === import_connectors17.DEFAULT_CONNECTOR_NAME.toLowerCase(),
39572
39738
  warn: (message) => import_logger11.logger.warn(message)
39573
39739
  });
@@ -39629,7 +39795,7 @@ var init_runner = __esm({
39629
39795
  const selectedTickers = selection?.tickers ? [.../* @__PURE__ */ new Set([...selection.tickers, ...selectedActiveSymbols])] : void 0;
39630
39796
  if (selectedActiveSymbols.length) {
39631
39797
  import_logger11.logger.info(
39632
- import_chalk53.default.gray(
39798
+ import_chalk54.default.gray(
39633
39799
  `runtime scope retained active symbols: ${selectedActiveSymbols.join(", ")}`
39634
39800
  )
39635
39801
  );
@@ -39660,10 +39826,10 @@ var init_runner = __esm({
39660
39826
  instruments.map((instrument) => [instrument.symbol, instrument])
39661
39827
  );
39662
39828
  if (config2.showTickersList) {
39663
- console.log(import_chalk53.default.gray(JSON.stringify(tickers.sort(), null, 2)));
39829
+ console.log(import_chalk54.default.gray(JSON.stringify(tickers.sort(), null, 2)));
39664
39830
  return;
39665
39831
  }
39666
- const projectConfig = await (0, import_cli13.loadTradejsConfig)(projectRoot17);
39832
+ const projectConfig = await (0, import_cli13.loadTradejsConfig)(projectRoot18);
39667
39833
  projectHooks = projectConfig.hooks;
39668
39834
  const currentTimestamp = (0, import_time14.getTimestamp)();
39669
39835
  const preloadStart = (0, import_time14.getTimestamp)(import_constants20.SIGNALS_CLI_PRELOAD_DAYS);
@@ -39681,7 +39847,7 @@ var init_runner = __esm({
39681
39847
  );
39682
39848
  await session.klineFeed.flush();
39683
39849
  import_logger11.logger.info(
39684
- import_chalk53.default.gray(
39850
+ import_chalk54.default.gray(
39685
39851
  `websocket candles: ready=${expectedSymbols.length - missingSymbols.length}/${expectedSymbols.length} missing=${missingSymbols.length}`
39686
39852
  )
39687
39853
  );
@@ -39692,7 +39858,7 @@ var init_runner = __esm({
39692
39858
  symbols: missingSymbols,
39693
39859
  preloadDays: import_constants20.SIGNALS_CLI_PRELOAD_DAYS,
39694
39860
  universe,
39695
- log: (message) => import_logger11.logger.info(import_chalk53.default.gray(message))
39861
+ log: (message) => import_logger11.logger.info(import_chalk54.default.gray(message))
39696
39862
  });
39697
39863
  await updateBtcReferenceHistory({
39698
39864
  marketConnector,
@@ -39700,7 +39866,7 @@ var init_runner = __esm({
39700
39866
  interval: interval5,
39701
39867
  preloadDays: import_constants20.SIGNALS_CLI_PRELOAD_DAYS,
39702
39868
  universe,
39703
- log: (message) => import_logger11.logger.info(import_chalk53.default.gray(message))
39869
+ log: (message) => import_logger11.logger.info(import_chalk54.default.gray(message))
39704
39870
  });
39705
39871
  } else if (!config2.cacheOnly) {
39706
39872
  await updateMarketHistoryWithBtcReferences({
@@ -39711,13 +39877,13 @@ var init_runner = __esm({
39711
39877
  symbols: tickers,
39712
39878
  preloadDays: import_constants20.SIGNALS_CLI_PRELOAD_DAYS,
39713
39879
  universe,
39714
- log: (message) => import_logger11.logger.info(import_chalk53.default.gray(message))
39880
+ log: (message) => import_logger11.logger.info(import_chalk54.default.gray(message))
39715
39881
  });
39716
39882
  }
39717
39883
  await prepareMarketContextForRun({
39718
39884
  mode: "signals",
39719
39885
  userName: config2.userName,
39720
- projectRoot: projectRoot17,
39886
+ projectRoot: projectRoot18,
39721
39887
  symbols: tickers,
39722
39888
  universe,
39723
39889
  interval: interval5,
@@ -39725,7 +39891,7 @@ var init_runner = __esm({
39725
39891
  endMs: currentTimestamp,
39726
39892
  preloadStartMs: preloadStart,
39727
39893
  cacheOnly: config2.cacheOnly,
39728
- log: (message) => import_logger11.logger.info(import_chalk53.default.gray(message))
39894
+ log: (message) => import_logger11.logger.info(import_chalk54.default.gray(message))
39729
39895
  });
39730
39896
  if (config2.updateOnly) {
39731
39897
  return;
@@ -39783,7 +39949,7 @@ var init_runner = __esm({
39783
39949
  );
39784
39950
  const configuredRuntimeStrategies = await (0, import_runtimeStrategies7.loadResolvedRuntimeStrategies)({
39785
39951
  userName: config2.userName,
39786
- projectRoot: projectRoot17,
39952
+ projectRoot: projectRoot18,
39787
39953
  deploymentId: deployment?.id ?? "",
39788
39954
  universe,
39789
39955
  accountId,
@@ -39829,7 +39995,7 @@ var init_runner = __esm({
39829
39995
  )
39830
39996
  );
39831
39997
  import_logger11.logger.info(
39832
- import_chalk53.default.yellow(
39998
+ import_chalk54.default.yellow(
39833
39999
  `loaded strategies (user=${config2.userName}): ${runtimeStrategies.map(formatConfiguredStrategyIdentity).join(", ")}`
39834
40000
  )
39835
40001
  );
@@ -39865,9 +40031,9 @@ var init_runner = __esm({
39865
40031
  width: 30
39866
40032
  }
39867
40033
  );
39868
- import_logger11.logger.info(import_chalk53.default.yellow(`tickers: ${tickers.length}`));
40034
+ import_logger11.logger.info(import_chalk54.default.yellow(`tickers: ${tickers.length}`));
39869
40035
  const signalsParallel = resolvePositiveInteger2(config2.parallel, 4);
39870
- import_logger11.logger.info(import_chalk53.default.yellow(`signal workers: ${signalsParallel}`));
40036
+ import_logger11.logger.info(import_chalk54.default.yellow(`signal workers: ${signalsParallel}`));
39871
40037
  const evaluateTicker = createSignalsTickerEvaluator({
39872
40038
  userName: config2.userName,
39873
40039
  makeOrders: config2.makeOrders,
@@ -39907,8 +40073,8 @@ var init_runner = __esm({
39907
40073
  signals3.push(...strategySignals);
39908
40074
  }
39909
40075
  bar.tick(1, {
39910
- found: import_chalk53.default.cyan(signals3.length),
39911
- symbol: import_chalk53.default.gray(symbol)
40076
+ found: import_chalk54.default.cyan(signals3.length),
40077
+ symbol: import_chalk54.default.gray(symbol)
39912
40078
  });
39913
40079
  });
39914
40080
  });
@@ -40012,7 +40178,7 @@ var init_runner = __esm({
40012
40178
  }
40013
40179
  }
40014
40180
  import_logger11.logger.info(
40015
- import_chalk53.default.yellow(
40181
+ import_chalk54.default.yellow(
40016
40182
  `signals ${status} in ${formatDuration3(durationMs)} (found=${signals3.length})`
40017
40183
  )
40018
40184
  );
@@ -40024,7 +40190,7 @@ var init_runner = __esm({
40024
40190
  const loadConfiguredSignalsScopes = async (deployment) => {
40025
40191
  const configuredStrategies = await (0, import_runtimeStrategies7.loadResolvedRuntimeStrategies)({
40026
40192
  userName: config2.userName,
40027
- projectRoot: projectRoot17,
40193
+ projectRoot: projectRoot18,
40028
40194
  deploymentId: deployment.id
40029
40195
  });
40030
40196
  const connectorName = await resolveSignalsConnectorName(
@@ -40050,7 +40216,7 @@ var init_runner = __esm({
40050
40216
  }
40051
40217
  const configuredDeployment = await (0, import_runtimeStrategies8.getRuntimeDeployment)({
40052
40218
  userName: config2.userName,
40053
- projectRoot: projectRoot17,
40219
+ projectRoot: projectRoot18,
40054
40220
  deploymentId: config2.deploymentId
40055
40221
  });
40056
40222
  if (!configuredDeployment) {
@@ -40084,7 +40250,7 @@ var init_runner = __esm({
40084
40250
  const deploymentId = config2.deploymentId;
40085
40251
  const initialDeployment = await (0, import_runtimeStrategies8.getRuntimeDeployment)({
40086
40252
  userName: config2.userName,
40087
- projectRoot: projectRoot17,
40253
+ projectRoot: projectRoot18,
40088
40254
  deploymentId
40089
40255
  });
40090
40256
  if (!initialDeployment) {
@@ -40109,7 +40275,7 @@ var init_runner = __esm({
40109
40275
  runCycle: async () => {
40110
40276
  const currentDeployment = await (0, import_runtimeStrategies8.getRuntimeDeployment)({
40111
40277
  userName: config2.userName,
40112
- projectRoot: projectRoot17,
40278
+ projectRoot: projectRoot18,
40113
40279
  deploymentId
40114
40280
  });
40115
40281
  if (!currentDeployment) {
@@ -40232,113 +40398,113 @@ var init_runner = __esm({
40232
40398
  var signals_exports = {};
40233
40399
  __export(signals_exports, {
40234
40400
  createSignalsSession: () => createSignalsSession,
40235
- main: () => main44,
40401
+ main: () => main45,
40236
40402
  signals: () => signals,
40237
40403
  signalsConfiguredScopesOnce: () => signalsConfiguredScopesOnce,
40238
40404
  signalsDaemon: () => signalsDaemon
40239
40405
  });
40240
- var import_config12, import_args34, flags31, config, runner, createSignalsSession, signals, signalsConfiguredScopesOnce, signalsDaemon, main44;
40406
+ var import_config12, import_args35, flags32, config, runner, createSignalsSession, signals, signalsConfiguredScopesOnce, signalsDaemon, main45;
40241
40407
  var init_signals = __esm({
40242
40408
  "src/scripts/signals.ts"() {
40243
40409
  "use strict";
40244
40410
  import_config12 = require("dotenv/config");
40245
- import_args34 = __toESM(require("args"));
40411
+ import_args35 = __toESM(require("args"));
40246
40412
  init_runner();
40247
- import_args34.default.option(["t", "tickers"], "Selected tickers");
40248
- import_args34.default.option(["e", "exclude"], "Exclude tickers from tests");
40249
- import_args34.default.option(["l", "tickersLimit"], "Tickers limit");
40250
- import_args34.default.option(["f", "timeframe"], "Timeframe", 15);
40251
- import_args34.default.option(["m", "makeOrders"], "Make orders");
40252
- import_args34.default.option(["N", "notify"], "Send message in Telegram", false);
40253
- import_args34.default.option(["S", "skipScreenshots"], "Skip screenshot generation", false);
40254
- import_args34.default.option(["u", "updateOnly"], "Only update tickers history", false);
40255
- import_args34.default.option(["C", "cacheOnly"], "Do not update tickers history", false);
40256
- import_args34.default.option(["L", "showTickersList"], "Just show only ticker list", false);
40257
- import_args34.default.option(
40413
+ import_args35.default.option(["t", "tickers"], "Selected tickers");
40414
+ import_args35.default.option(["e", "exclude"], "Exclude tickers from tests");
40415
+ import_args35.default.option(["l", "tickersLimit"], "Tickers limit");
40416
+ import_args35.default.option(["f", "timeframe"], "Timeframe", 15);
40417
+ import_args35.default.option(["m", "makeOrders"], "Make orders");
40418
+ import_args35.default.option(["N", "notify"], "Send message in Telegram", false);
40419
+ import_args35.default.option(["S", "skipScreenshots"], "Skip screenshot generation", false);
40420
+ import_args35.default.option(["u", "updateOnly"], "Only update tickers history", false);
40421
+ import_args35.default.option(["C", "cacheOnly"], "Do not update tickers history", false);
40422
+ import_args35.default.option(["L", "showTickersList"], "Just show only ticker list", false);
40423
+ import_args35.default.option(
40258
40424
  ["p", "parallel"],
40259
40425
  "Signal evaluation worker count",
40260
40426
  Number(process.env.SIGNALS_PARALLEL || 4)
40261
40427
  );
40262
- import_args34.default.option(
40428
+ import_args35.default.option(
40263
40429
  ["R", "showSkipStats"],
40264
40430
  "Show aggregated skip stats by strategy",
40265
40431
  false
40266
40432
  );
40267
- import_args34.default.option(["c", "chunk"], "Split by chunks, ex. 1/3");
40268
- import_args34.default.option(["U", "user"], "Use user confg", "root");
40269
- import_args34.default.option(["w", "watch"], "Keep signals running on candle boundaries", false);
40270
- import_args34.default.option(
40433
+ import_args35.default.option(["c", "chunk"], "Split by chunks, ex. 1/3");
40434
+ import_args35.default.option(["U", "user"], "Use user confg", "root");
40435
+ import_args35.default.option(["w", "watch"], "Keep signals running on candle boundaries", false);
40436
+ import_args35.default.option(
40271
40437
  ["d", "settleDelayMs"],
40272
40438
  "Delay after candle close before a daemon cycle",
40273
40439
  Number(process.env.SIGNALS_DAEMON_SETTLE_DELAY_MS || 5e3)
40274
40440
  );
40275
- import_args34.default.option(
40441
+ import_args35.default.option(
40276
40442
  ["o", "connector"],
40277
40443
  "Connector provider or name for signals (e.g. bybit, binance, coinbase, custom)",
40278
40444
  "bybit"
40279
40445
  );
40280
- import_args34.default.option(["V", "universe"], "Market universe (crypto or tradfi)", "crypto");
40281
- import_args34.default.option(["A", "account"], "Trading account id");
40282
- import_args34.default.option(["D", "deployment"], "Runtime deployment id");
40283
- flags31 = import_args34.default.parse(process.argv);
40446
+ import_args35.default.option(["V", "universe"], "Market universe (crypto or tradfi)", "crypto");
40447
+ import_args35.default.option(["A", "account"], "Trading account id");
40448
+ import_args35.default.option(["D", "deployment"], "Runtime deployment id");
40449
+ flags32 = import_args35.default.parse(process.argv);
40284
40450
  config = {
40285
40451
  projectRoot: String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd(),
40286
- userName: String(flags31.user || "root"),
40287
- interval: String(flags31.timeframe ?? 15),
40288
- connectorName: String(flags31.connector || "bybit"),
40289
- universe: flags31.universe,
40290
- accountId: flags31.account ? String(flags31.account) : void 0,
40291
- deploymentId: flags31.deployment ? String(flags31.deployment) : void 0,
40292
- tickers: flags31.tickers,
40293
- exclude: flags31.exclude,
40294
- tickersLimit: flags31.tickersLimit,
40295
- chunk: flags31.chunk,
40296
- makeOrders: Boolean(flags31.makeOrders),
40297
- notify: Boolean(flags31.notify),
40298
- skipScreenshots: Boolean(flags31.skipScreenshots),
40299
- updateOnly: Boolean(flags31.updateOnly),
40300
- cacheOnly: Boolean(flags31.cacheOnly),
40301
- showTickersList: Boolean(flags31.showTickersList),
40302
- showSkipStats: Boolean(flags31.showSkipStats),
40303
- parallel: flags31.parallel,
40304
- watch: Boolean(flags31.watch),
40305
- settleDelayMs: flags31.settleDelayMs
40452
+ userName: String(flags32.user || "root"),
40453
+ interval: String(flags32.timeframe ?? 15),
40454
+ connectorName: String(flags32.connector || "bybit"),
40455
+ universe: flags32.universe,
40456
+ accountId: flags32.account ? String(flags32.account) : void 0,
40457
+ deploymentId: flags32.deployment ? String(flags32.deployment) : void 0,
40458
+ tickers: flags32.tickers,
40459
+ exclude: flags32.exclude,
40460
+ tickersLimit: flags32.tickersLimit,
40461
+ chunk: flags32.chunk,
40462
+ makeOrders: Boolean(flags32.makeOrders),
40463
+ notify: Boolean(flags32.notify),
40464
+ skipScreenshots: Boolean(flags32.skipScreenshots),
40465
+ updateOnly: Boolean(flags32.updateOnly),
40466
+ cacheOnly: Boolean(flags32.cacheOnly),
40467
+ showTickersList: Boolean(flags32.showTickersList),
40468
+ showSkipStats: Boolean(flags32.showSkipStats),
40469
+ parallel: flags32.parallel,
40470
+ watch: Boolean(flags32.watch),
40471
+ settleDelayMs: flags32.settleDelayMs
40306
40472
  };
40307
40473
  runner = createSignalsRunner(config);
40308
40474
  createSignalsSession = runner.createSession;
40309
40475
  signals = runner.runCycle;
40310
40476
  signalsConfiguredScopesOnce = runner.runConfiguredScopesOnce;
40311
40477
  signalsDaemon = runner.runDaemon;
40312
- main44 = () => config.watch ? signalsDaemon() : signalsConfiguredScopesOnce();
40478
+ main45 = () => config.watch ? signalsDaemon() : signalsConfiguredScopesOnce();
40313
40479
  }
40314
40480
  });
40315
40481
 
40316
40482
  // src/scripts/signalsDaemon.ts
40317
40483
  var signalsDaemon_exports = {};
40318
40484
  __export(signalsDaemon_exports, {
40319
- main: () => main45
40485
+ main: () => main46
40320
40486
  });
40321
- var main45;
40487
+ var main46;
40322
40488
  var init_signalsDaemon = __esm({
40323
40489
  "src/scripts/signalsDaemon.ts"() {
40324
40490
  "use strict";
40325
40491
  init_signals();
40326
- main45 = signalsDaemon;
40492
+ main46 = signalsDaemon;
40327
40493
  }
40328
40494
  });
40329
40495
 
40330
40496
  // src/scripts/signalsSummary.ts
40331
40497
  var signalsSummary_exports = {};
40332
40498
  __export(signalsSummary_exports, {
40333
- main: () => main46,
40499
+ main: () => main47,
40334
40500
  signalsSummary: () => signalsSummary
40335
40501
  });
40336
- var import_config13, import_args35, import_logger12, import_connectors18, import_runtimeStrategies10, flags32, projectRoot16, SUMMARY_TIMEZONE2, SUMMARY_TIMEZONE_LABEL2, escapeHtml7, 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;
40502
+ var import_config13, import_args36, import_logger12, import_connectors18, import_runtimeStrategies10, flags33, projectRoot17, SUMMARY_TIMEZONE2, SUMMARY_TIMEZONE_LABEL2, escapeHtml8, formatMskDateTime4, formatSigned3, formatPnlMoneyText, formatWinRateText, resolveSummaryTitle, normalizeStatus, shouldAttachDebugReport, getSummaryDateParts, formatSummaryIsoDayKey, unescapeHtml, stripTelegramHtml, buildSignalsSummaryAttachment, appendReportAttachmentSummary, resolveSummaryConnectorName, groupRuntimeTradesByConnectorScope, syncRuntimeTradeScopes, createRuntimeSignalStats, mergeRuntimeSignalStats, buildSummaryPrelude, resolveTradeStatusEmoji, isTimestampInWindow, isRuntimeTradeClosedInWindow, buildSummaryMessages, signalsSummary, main47;
40337
40503
  var init_signalsSummary = __esm({
40338
40504
  "src/scripts/signalsSummary.ts"() {
40339
40505
  "use strict";
40340
40506
  import_config13 = require("dotenv/config");
40341
- import_args35 = __toESM(require("args"));
40507
+ import_args36 = __toESM(require("args"));
40342
40508
  import_logger12 = require("@tradejs/infra/logger");
40343
40509
  import_connectors18 = require("@tradejs/node/connectors");
40344
40510
  init_runtimeRedis();
@@ -40348,25 +40514,25 @@ var init_signalsSummary = __esm({
40348
40514
  init_runtimeSignalsStorage();
40349
40515
  init_runtimeDebugEvidence();
40350
40516
  import_runtimeStrategies10 = require("@tradejs/node/runtimeStrategies");
40351
- import_args35.default.option(["u", "user"], "Use user config", "root");
40352
- import_args35.default.option(
40517
+ import_args36.default.option(["u", "user"], "Use user config", "root");
40518
+ import_args36.default.option(
40353
40519
  "connector",
40354
40520
  "Connector provider or name for summary (e.g. bybit, binance, coinbase, custom)",
40355
40521
  "bybit"
40356
40522
  );
40357
- import_args35.default.option(["H", "hours"], "Summary window in hours", 24);
40358
- import_args35.default.option(["P", "printOnly"], "Print summary instead of Telegram", false);
40359
- import_args35.default.option(
40523
+ import_args36.default.option(["H", "hours"], "Summary window in hours", 24);
40524
+ import_args36.default.option(["P", "printOnly"], "Print summary instead of Telegram", false);
40525
+ import_args36.default.option(
40360
40526
  "debugAttachment",
40361
40527
  "Attach runtime Redis debug JSON for replay diagnostics",
40362
40528
  true
40363
40529
  );
40364
- flags32 = import_args35.default.parse(process.argv);
40365
- projectRoot16 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
40530
+ flags33 = import_args36.default.parse(process.argv);
40531
+ projectRoot17 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
40366
40532
  SUMMARY_TIMEZONE2 = "Europe/Moscow";
40367
40533
  SUMMARY_TIMEZONE_LABEL2 = "MSK";
40368
- escapeHtml7 = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
40369
- formatMskDateTime3 = (timestamp) => new Intl.DateTimeFormat("ru-RU", {
40534
+ escapeHtml8 = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
40535
+ formatMskDateTime4 = (timestamp) => new Intl.DateTimeFormat("ru-RU", {
40370
40536
  timeZone: SUMMARY_TIMEZONE2,
40371
40537
  year: "numeric",
40372
40538
  month: "2-digit",
@@ -40435,13 +40601,13 @@ var init_signalsSummary = __esm({
40435
40601
  message,
40436
40602
  "",
40437
40603
  "\u{1F4CE} <b>Signal report file</b>",
40438
- `File: <code>${escapeHtml7(signalsFilename)}</code>`
40604
+ `File: <code>${escapeHtml8(signalsFilename)}</code>`
40439
40605
  ];
40440
40606
  if (filename) {
40441
40607
  lines.push(
40442
40608
  "",
40443
40609
  "\u{1F4CE} <b>Replay debug file</b>",
40444
- `File: <code>${escapeHtml7(filename)}</code>`,
40610
+ `File: <code>${escapeHtml8(filename)}</code>`,
40445
40611
  `Inside: trades=<b>${tradesCount ?? 0}</b>, signals=<b>${signalsCount ?? 0}</b>, evaluations=<b>${evaluationsCount ?? 0}</b>`,
40446
40612
  "Redis refs: <code>trade</code>, <code>tradeBucket</code>, <code>activeTrade</code>, <code>signal</code>, <code>evaluation</code>"
40447
40613
  );
@@ -40449,7 +40615,7 @@ var init_signalsSummary = __esm({
40449
40615
  return lines.join("\n");
40450
40616
  };
40451
40617
  resolveSummaryConnectorName = async (value) => {
40452
- const connectorName = await (0, import_connectors18.resolveConnectorName)(value, projectRoot16);
40618
+ const connectorName = await (0, import_connectors18.resolveConnectorName)(value, projectRoot17);
40453
40619
  if (connectorName) {
40454
40620
  return connectorName;
40455
40621
  }
@@ -40514,7 +40680,7 @@ var init_signalsSummary = __esm({
40514
40680
  );
40515
40681
  const connectorFactory = await (0, import_connectors18.getConnectorCreatorByName)(
40516
40682
  connectorName,
40517
- projectRoot16
40683
+ projectRoot17
40518
40684
  );
40519
40685
  if (!connectorFactory) {
40520
40686
  throw new Error(`Connector "${connectorName}" is not registered`);
@@ -40591,16 +40757,16 @@ var init_signalsSummary = __esm({
40591
40757
  }) => {
40592
40758
  const windowPnlLabel = hours === 24 ? "24h Realized PnL" : `${hours}h Realized PnL`;
40593
40759
  return [
40594
- `\u{1F4CB} <b>${escapeHtml7(resolveSummaryTitle(hours))}</b>`,
40760
+ `\u{1F4CB} <b>${escapeHtml8(resolveSummaryTitle(hours))}</b>`,
40595
40761
  "",
40596
40762
  "\u{1F552} <b>Window</b>",
40597
- `<b>${escapeHtml7(formatMskDateTime3(startTime))} - ${escapeHtml7(formatMskDateTime3(endTime))} ${SUMMARY_TIMEZONE_LABEL2}</b>`,
40763
+ `<b>${escapeHtml8(formatMskDateTime4(startTime))} - ${escapeHtml8(formatMskDateTime4(endTime))} ${SUMMARY_TIMEZONE_LABEL2}</b>`,
40598
40764
  "",
40599
40765
  `\u23F1 Range: <b>${hours}h</b>`,
40600
- `\u{1F4B0} <b>${windowPnlLabel}:</b> <b>${escapeHtml7(realizedWindowPnlText)}</b>`,
40601
- `\u{1F3C6} <b>WinRate:</b> <b>${escapeHtml7(winRateText)}</b>`,
40766
+ `\u{1F4B0} <b>${windowPnlLabel}:</b> <b>${escapeHtml8(realizedWindowPnlText)}</b>`,
40767
+ `\u{1F3C6} <b>WinRate:</b> <b>${escapeHtml8(winRateText)}</b>`,
40602
40768
  `\u2197\uFE0F <b>LONG:</b> <b>${longCount}</b>, \u2198\uFE0F <b>SHORT:</b> <b>${shortCount}</b>`,
40603
- `\u{1F4CD} <b>Open positions:</b> <b>${openCount}</b>, Unrealized PnL: <b>${escapeHtml7(openPnlText)}</b>`
40769
+ `\u{1F4CD} <b>Open positions:</b> <b>${openCount}</b>, Unrealized PnL: <b>${escapeHtml8(openPnlText)}</b>`
40604
40770
  ];
40605
40771
  };
40606
40772
  resolveTradeStatusEmoji = (status, pnl) => {
@@ -40781,12 +40947,12 @@ var init_signalsSummary = __esm({
40781
40947
  }
40782
40948
  );
40783
40949
  for (const [source, reasons] of sortedReasonGroups) {
40784
- signalLines.push(`<b>${escapeHtml7(source)}</b>:`);
40950
+ signalLines.push(`<b>${escapeHtml8(source)}</b>:`);
40785
40951
  const sortedReasons = [...reasons.entries()].sort(
40786
40952
  (left, right) => right[1] - left[1] || left[0].localeCompare(right[0])
40787
40953
  );
40788
40954
  for (const [reason, count] of sortedReasons) {
40789
- signalLines.push(`${escapeHtml7(reason)}: <b>${count}</b>`);
40955
+ signalLines.push(`${escapeHtml8(reason)}: <b>${count}</b>`);
40790
40956
  }
40791
40957
  }
40792
40958
  };
@@ -40796,8 +40962,8 @@ var init_signalsSummary = __esm({
40796
40962
  const evaluation = evaluationStatsByStrategy.get(strategyName);
40797
40963
  signalLines.push("");
40798
40964
  signalLines.push(
40799
- evaluation?.evaluated ? `<b>${escapeHtml7(strategyName)}</b>
40800
- signals=<b>0</b>` : `<b>${escapeHtml7(strategyName)}</b>
40965
+ evaluation?.evaluated ? `<b>${escapeHtml8(strategyName)}</b>
40966
+ signals=<b>0</b>` : `<b>${escapeHtml8(strategyName)}</b>
40801
40967
  none`
40802
40968
  );
40803
40969
  appendEvaluationDetails(strategyName);
@@ -40808,7 +40974,7 @@ none`
40808
40974
  return count > 0 ? `${status}=<b>${count}</b>` : null;
40809
40975
  }).filter(Boolean);
40810
40976
  signalLines.push("");
40811
- signalLines.push(`<b>${escapeHtml7(strategyName)}</b>`);
40977
+ signalLines.push(`<b>${escapeHtml8(strategyName)}</b>`);
40812
40978
  signalLines.push(parts.join(", "));
40813
40979
  appendEvaluationDetails(strategyName);
40814
40980
  }
@@ -40821,17 +40987,17 @@ none`
40821
40987
  if (!stats) continue;
40822
40988
  tradeLines.push("");
40823
40989
  tradeLines.push(
40824
- `<b>${escapeHtml7(strategyName)}</b> (<b>${stats.closed}</b>)`
40990
+ `<b>${escapeHtml8(strategyName)}</b> (<b>${stats.closed}</b>)`
40825
40991
  );
40826
40992
  tradeLines.push(
40827
- `Closed PnL: <b>${escapeHtml7(formatPnlMoneyText(stats.closedPnl, stats.closedPnlKnown))}</b> (<b>${stats.closed}</b>)`
40993
+ `Closed PnL: <b>${escapeHtml8(formatPnlMoneyText(stats.closedPnl, stats.closedPnlKnown))}</b> (<b>${stats.closed}</b>)`
40828
40994
  );
40829
40995
  const sortedTrades = stats.trades.filter((trade) => trade.status === "closed").sort(
40830
40996
  (left, right) => left.entryTimestamp - right.entryTimestamp || left.symbol.localeCompare(right.symbol) || left.orderId.localeCompare(right.orderId)
40831
40997
  );
40832
40998
  for (const trade of sortedTrades) {
40833
40999
  tradeLines.push(
40834
- `- ${escapeHtml7(trade.symbol)}: PnL <b>${escapeHtml7(trade.pnlText)}</b> ${resolveTradeStatusEmoji(trade.status, trade.pnl)}`
41000
+ `- ${escapeHtml8(trade.symbol)}: PnL <b>${escapeHtml8(trade.pnlText)}</b> ${resolveTradeStatusEmoji(trade.status, trade.pnl)}`
40835
41001
  );
40836
41002
  }
40837
41003
  }
@@ -40845,17 +41011,17 @@ none`
40845
41011
  if (!stats) continue;
40846
41012
  tradeLines.push("");
40847
41013
  tradeLines.push(
40848
- `<b>${escapeHtml7(strategyName)}</b> (<b>${stats.active}</b>)`
41014
+ `<b>${escapeHtml8(strategyName)}</b> (<b>${stats.active}</b>)`
40849
41015
  );
40850
41016
  tradeLines.push(
40851
- `Unrealized PnL: <b>${escapeHtml7(formatPnlMoneyText(stats.activePnl, stats.activePnlKnown))}</b> (<b>${stats.active}</b>)`
41017
+ `Unrealized PnL: <b>${escapeHtml8(formatPnlMoneyText(stats.activePnl, stats.activePnlKnown))}</b> (<b>${stats.active}</b>)`
40852
41018
  );
40853
41019
  const sortedTrades = stats.trades.filter((trade) => trade.status === "active").sort(
40854
41020
  (left, right) => left.entryTimestamp - right.entryTimestamp || left.symbol.localeCompare(right.symbol) || left.orderId.localeCompare(right.orderId)
40855
41021
  );
40856
41022
  for (const trade of sortedTrades) {
40857
41023
  tradeLines.push(
40858
- `- ${escapeHtml7(trade.symbol)}: PnL <b>${escapeHtml7(trade.pnlText)}</b> ${resolveTradeStatusEmoji(trade.status, trade.pnl)}`
41024
+ `- ${escapeHtml8(trade.symbol)}: PnL <b>${escapeHtml8(trade.pnlText)}</b> ${resolveTradeStatusEmoji(trade.status, trade.pnl)}`
40859
41025
  );
40860
41026
  }
40861
41027
  }
@@ -40867,12 +41033,12 @@ none`
40867
41033
  signalsSummary = async () => {
40868
41034
  const hours = Math.max(
40869
41035
  1,
40870
- Number.parseInt(String(flags32.hours ?? 24), 10) || 24
41036
+ Number.parseInt(String(flags33.hours ?? 24), 10) || 24
40871
41037
  );
40872
41038
  const endTime = Date.now();
40873
41039
  const startTime = endTime - hours * 60 * 60 * 1e3;
40874
41040
  const fallbackConnectorName = await resolveSummaryConnectorName(
40875
- flags32.connector
41041
+ flags33.connector
40876
41042
  );
40877
41043
  const [
40878
41044
  configuredStrategyNames,
@@ -40881,25 +41047,25 @@ none`
40881
41047
  trades,
40882
41048
  runtimeDeployments
40883
41049
  ] = await Promise.all([
40884
- (0, import_runtimeStrategyConfigs.loadRuntimeStrategyNames)(flags32.user),
40885
- loadRuntimeSignals(flags32.user, { startTime, endTime }),
40886
- loadRuntimeSignalEvaluationStatsBuckets(flags32.user),
40887
- loadRuntimeTrades(flags32.user),
40888
- (0, import_runtimeStrategies10.listRuntimeDeployments)({ userName: flags32.user, projectRoot: projectRoot16 })
41050
+ (0, import_runtimeStrategyConfigs.loadRuntimeStrategyNames)(flags33.user),
41051
+ loadRuntimeSignals(flags33.user, { startTime, endTime }),
41052
+ loadRuntimeSignalEvaluationStatsBuckets(flags33.user),
41053
+ loadRuntimeTrades(flags33.user),
41054
+ (0, import_runtimeStrategies10.listRuntimeDeployments)({ userName: flags33.user, projectRoot: projectRoot17 })
40889
41055
  ]);
40890
41056
  const {
40891
41057
  trades: syncedTrades,
40892
41058
  connectorNames,
40893
41059
  scopesCount
40894
41060
  } = await syncRuntimeTradeScopes({
40895
- userName: flags32.user,
41061
+ userName: flags33.user,
40896
41062
  startTime,
40897
41063
  endTime,
40898
41064
  fallbackConnectorName,
40899
41065
  trades,
40900
41066
  deployments: runtimeDeployments
40901
41067
  });
40902
- const activeTradeOrderIds = await loadRuntimeActiveTradeOrderIds(flags32.user);
41068
+ const activeTradeOrderIds = await loadRuntimeActiveTradeOrderIds(flags33.user);
40903
41069
  const windowSignals = signals2.filter(
40904
41070
  (signal) => signal.timestamp >= startTime && signal.timestamp < endTime
40905
41071
  );
@@ -40947,10 +41113,10 @@ none`
40947
41113
  windowClosedTrades.length,
40948
41114
  connectorNames.join(",") || fallbackConnectorName,
40949
41115
  scopesCount,
40950
- flags32.user
41116
+ flags33.user
40951
41117
  );
40952
- const debugAttachment = shouldAttachDebugReport(flags32.debugAttachment) ? await buildRuntimeDebugReportAttachment({
40953
- userName: flags32.user,
41118
+ const debugAttachment = shouldAttachDebugReport(flags33.debugAttachment) ? await buildRuntimeDebugReportAttachment({
41119
+ userName: flags33.user,
40954
41120
  startTime,
40955
41121
  endTime,
40956
41122
  signals: debugSignals,
@@ -40958,7 +41124,7 @@ none`
40958
41124
  trades: windowTrades
40959
41125
  }) : null;
40960
41126
  const signalsAttachment = buildSignalsSummaryAttachment({
40961
- userName: flags32.user,
41127
+ userName: flags33.user,
40962
41128
  endTime,
40963
41129
  content: signalsMessage
40964
41130
  });
@@ -40974,7 +41140,7 @@ none`
40974
41140
  signalsAttachment,
40975
41141
  ...debugAttachment ? [debugAttachment] : []
40976
41142
  ];
40977
- if (flags32.printOnly) {
41143
+ if (flags33.printOnly) {
40978
41144
  console.log(tradesMessageWithAttachmentSummary);
40979
41145
  console.log("");
40980
41146
  console.log(`Signals attachment: ${signalsAttachment.filename}`);
@@ -40987,20 +41153,20 @@ none`
40987
41153
  return;
40988
41154
  }
40989
41155
  await sendTelegramReport(tradesMessageWithAttachmentSummary, {
40990
- userName: flags32.user,
41156
+ userName: flags33.user,
40991
41157
  attachments
40992
41158
  });
40993
41159
  };
40994
- main46 = signalsSummary;
41160
+ main47 = signalsSummary;
40995
41161
  }
40996
41162
  });
40997
41163
 
40998
41164
  // src/scripts/test-ml.ts
40999
41165
  var test_ml_exports = {};
41000
41166
  __export(test_ml_exports, {
41001
- main: () => main47
41167
+ main: () => main48
41002
41168
  });
41003
- var import_config14, import_constants21, import_ml3, import_registry5, now, INTERVAL_MIN, CANDLES, makeSeries, makeCandles, buildTrendline, main47;
41169
+ var import_config14, import_constants21, import_ml3, import_registry5, now, INTERVAL_MIN, CANDLES, makeSeries, makeCandles, buildTrendline, main48;
41004
41170
  var init_test_ml = __esm({
41005
41171
  "src/scripts/test-ml.ts"() {
41006
41172
  "use strict";
@@ -41050,7 +41216,7 @@ var init_test_ml = __esm({
41050
41216
  { timestamp: entryTs - 2 * INTERVAL_MIN * 6e4, value: price * 0.995 }
41051
41217
  ]
41052
41218
  });
41053
- main47 = async () => {
41219
+ main48 = async () => {
41054
41220
  const defaultConfig = await (0, import_registry5.getStrategyDefaults)("TrendLine", process.cwd());
41055
41221
  if (!defaultConfig) {
41056
41222
  throw new Error(
@@ -41143,9 +41309,9 @@ var init_test_ml = __esm({
41143
41309
  // src/scripts/test.ts
41144
41310
  var test_exports = {};
41145
41311
  __export(test_exports, {
41146
- main: () => main48
41312
+ main: () => main49
41147
41313
  });
41148
- var import_config15, import_connectors19, getPositions, main48;
41314
+ var import_config15, import_connectors19, getPositions, main49;
41149
41315
  var init_test = __esm({
41150
41316
  "src/scripts/test.ts"() {
41151
41317
  "use strict";
@@ -41155,7 +41321,7 @@ var init_test = __esm({
41155
41321
  const res = await connector.getPositions();
41156
41322
  console.log("res", res);
41157
41323
  };
41158
- main48 = async () => {
41324
+ main49 = async () => {
41159
41325
  const byBitConnector = await import_connectors19.connectors.ByBit({
41160
41326
  userName: "root"
41161
41327
  });
@@ -41167,25 +41333,25 @@ var init_test = __esm({
41167
41333
  // src/scripts/user-add.ts
41168
41334
  var user_add_exports = {};
41169
41335
  __export(user_add_exports, {
41170
- main: () => main49
41336
+ main: () => main50
41171
41337
  });
41172
- var import_args36, import_chalk54, import_bcryptjs, import_redis22, flags33, main49;
41338
+ var import_args37, import_chalk55, import_bcryptjs, import_redis22, flags34, main50;
41173
41339
  var init_user_add = __esm({
41174
41340
  "src/scripts/user-add.ts"() {
41175
41341
  "use strict";
41176
- import_args36 = __toESM(require("args"));
41177
- import_chalk54 = __toESM(require("chalk"));
41342
+ import_args37 = __toESM(require("args"));
41343
+ import_chalk55 = __toESM(require("chalk"));
41178
41344
  import_bcryptjs = __toESM(require("bcryptjs"));
41179
41345
  import_redis22 = require("@tradejs/infra/redis");
41180
- import_args36.default.example("yarn user-add -u myname -p 123456", "Create or update user");
41181
- import_args36.default.option(["u", "user"], "Username", "");
41182
- import_args36.default.option(["p", "password"], "Password (plain text)", "");
41183
- flags33 = import_args36.default.parse(process.argv);
41184
- main49 = async () => {
41185
- const userName3 = String(flags33.user || "").trim();
41186
- const password = String(flags33.password || "");
41346
+ import_args37.default.example("yarn user-add -u myname -p 123456", "Create or update user");
41347
+ import_args37.default.option(["u", "user"], "Username", "");
41348
+ import_args37.default.option(["p", "password"], "Password (plain text)", "");
41349
+ flags34 = import_args37.default.parse(process.argv);
41350
+ main50 = async () => {
41351
+ const userName3 = String(flags34.user || "").trim();
41352
+ const password = String(flags34.password || "");
41187
41353
  if (!userName3 || !password) {
41188
- console.error(import_chalk54.default.red("Missing -U <user> or -P <password>"));
41354
+ console.error(import_chalk55.default.red("Missing -U <user> or -P <password>"));
41189
41355
  process.exit(1);
41190
41356
  }
41191
41357
  const passwordHash = await import_bcryptjs.default.hash(password, 10);
@@ -41199,7 +41365,7 @@ var init_user_add = __esm({
41199
41365
  await (0, import_redis22.setData)(import_redis22.redisKeys.user(userName3), next, {
41200
41366
  expire: 0
41201
41367
  });
41202
- console.log(import_chalk54.default.green(`User ${userName3} updated`));
41368
+ console.log(import_chalk55.default.green(`User ${userName3} updated`));
41203
41369
  process.exit(0);
41204
41370
  };
41205
41371
  }
@@ -41209,7 +41375,7 @@ var init_user_add = __esm({
41209
41375
  var cli_exports = {};
41210
41376
  __export(cli_exports, {
41211
41377
  cleanupCliResources: () => cleanupCliResources,
41212
- main: () => main50,
41378
+ main: () => main51,
41213
41379
  printUsage: () => printUsage3,
41214
41380
  runLoadedModule: () => runLoadedModule
41215
41381
  });
@@ -41253,6 +41419,7 @@ var scriptLoaders = {
41253
41419
  results: () => Promise.resolve().then(() => (init_results(), results_exports)),
41254
41420
  "replay-runtime-evidence": () => Promise.resolve().then(() => (init_replayRuntimeEvidence(), replayRuntimeEvidence_exports)),
41255
41421
  "runtime-feedback-replay": () => Promise.resolve().then(() => (init_runtimeFeedbackReplay2(), runtimeFeedbackReplay_exports)),
41422
+ "runtime-feedback-notify": () => Promise.resolve().then(() => (init_runtimeFeedbackNotify(), runtimeFeedbackNotify_exports)),
41256
41423
  "runtime-feedback-sync": () => Promise.resolve().then(() => (init_runtimeFeedbackSync2(), runtimeFeedbackSync_exports)),
41257
41424
  "runtime-evidence": () => Promise.resolve().then(() => (init_runtimeEvidence(), runtimeEvidence_exports)),
41258
41425
  "runtime-evidence-sync": () => Promise.resolve().then(() => (init_runtimeEvidenceSync2(), runtimeEvidenceSync_exports)),
@@ -41285,14 +41452,14 @@ var runLoadedModule = async (loaded) => {
41285
41452
  var cleanupCliResources = async () => {
41286
41453
  await Promise.allSettled([(0, import_redis23.closeRedisConnection)(), (0, import_client9.closeTimescalePool)()]);
41287
41454
  };
41288
- var main50 = async () => {
41289
- const [, scriptPath, command = "", ...args37] = process.argv;
41455
+ var main51 = async () => {
41456
+ const [, scriptPath, command = "", ...args38] = process.argv;
41290
41457
  const loader = scriptLoaders[command];
41291
41458
  if (!loader) {
41292
41459
  printUsage3();
41293
41460
  process.exit(command ? 1 : 0);
41294
41461
  }
41295
- const nextArgs = [...args37];
41462
+ const nextArgs = [...args38];
41296
41463
  if (command === "spread:ingest") {
41297
41464
  nextArgs.push("--provider", "binance_coinbase_spread");
41298
41465
  }
@@ -41316,7 +41483,7 @@ var main50 = async () => {
41316
41483
  }
41317
41484
  };
41318
41485
  if (require.main === module) {
41319
- main50().catch((error) => {
41486
+ main51().catch((error) => {
41320
41487
  console.error(error);
41321
41488
  process.exit(1);
41322
41489
  });