@tradejs/cli 3.1.29-beta.289 → 3.1.29-beta.290

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
@@ -16039,7 +16039,13 @@ var init_runtimeEvidenceSource = __esm({
16039
16039
  userName: artifact.userName,
16040
16040
  startTime: artifact.startTime,
16041
16041
  endTime: artifact.endTime,
16042
- deployment: artifact.deployment
16042
+ deployment: artifact.deployment,
16043
+ decisionTraceTargets: unwrapRows(
16044
+ artifact.runtime.trades,
16045
+ "trade"
16046
+ ).flatMap(
16047
+ ({ strategy, symbol, signalTimestamp }) => typeof signalTimestamp === "number" && Number.isFinite(signalTimestamp) && artifact.startTime != null && artifact.endTime != null && signalTimestamp >= artifact.startTime && signalTimestamp < artifact.endTime ? [{ strategy, symbol, signalTimestamp }] : []
16048
+ )
16043
16049
  };
16044
16050
  };
16045
16051
  buildRuntimeEvidenceLineageScopes = ({
@@ -16649,6 +16655,79 @@ var init_hooks = __esm({
16649
16655
  }
16650
16656
  });
16651
16657
 
16658
+ // src/lib/replay/historicalSignalsReplayDecisionTrace.ts
16659
+ var replayDecisionTraceKey, describeOutcome, createReplayDecisionTrace;
16660
+ var init_historicalSignalsReplayDecisionTrace = __esm({
16661
+ "src/lib/replay/historicalSignalsReplayDecisionTrace.ts"() {
16662
+ "use strict";
16663
+ replayDecisionTraceKey = ({
16664
+ strategy,
16665
+ symbol,
16666
+ signalTimestamp
16667
+ }) => JSON.stringify([strategy, symbol, signalTimestamp]);
16668
+ describeOutcome = (result) => {
16669
+ if (typeof result === "string") {
16670
+ return {
16671
+ stage: result.startsWith("BACKTEST_ENTRY_DELAY_") ? "entry_delay" : /(?:NO_PATTERN|POSITION_EXISTS)$/.test(result) ? "core" : "evaluation",
16672
+ reason: result
16673
+ };
16674
+ }
16675
+ if (!result) return { stage: "evaluation", reason: "NO_SIGNAL" };
16676
+ const reason = result.orderSkipReason || result.orderFailureReason || result.orderStatus || "SIGNAL";
16677
+ const patternContext = result.additionalIndicators?.tradingPatternsContext;
16678
+ return {
16679
+ stage: result.riskDecision?.status === "rejected" || /^ENTRY_(?:RR_BELOW|RISK_EXCEEDS)/.test(reason) ? "risk" : /^(?:AI_|ML_|HOOK_BEFORE_ENTRY_GATE|RESEARCH_ENTRY_POLICY)/.test(
16680
+ reason
16681
+ ) ? "gate" : result.orderStatus ? "execution" : "evaluation",
16682
+ reason,
16683
+ direction: result.direction,
16684
+ orderStatus: result.orderStatus,
16685
+ ...typeof patternContext?.selectedPattern === "string" ? { pattern: patternContext.selectedPattern } : {},
16686
+ ...typeof patternContext?.sourceCode === "string" ? { patternCode: patternContext.sourceCode } : {}
16687
+ };
16688
+ };
16689
+ createReplayDecisionTrace = (targets = []) => {
16690
+ const traces = /* @__PURE__ */ new Map();
16691
+ const symbols = new Set(targets.map(({ symbol }) => symbol));
16692
+ for (const target of targets) {
16693
+ traces.set(replayDecisionTraceKey(target), {
16694
+ ...target,
16695
+ decision: {
16696
+ stage: "not_evaluated",
16697
+ reason: "REPLAY_CANDLE_NOT_EVALUATED"
16698
+ }
16699
+ });
16700
+ }
16701
+ const record = (strategy, symbol, candle, result, notEvaluatedReason) => {
16702
+ if (!symbols.has(symbol)) return;
16703
+ const { timestamp, open, high, low, close, volume } = candle;
16704
+ const trace = traces.get(
16705
+ replayDecisionTraceKey({ strategy, symbol, signalTimestamp: timestamp })
16706
+ );
16707
+ if (result && typeof result !== "string" && result.timestamp !== timestamp) {
16708
+ const original = traces.get(
16709
+ replayDecisionTraceKey({
16710
+ strategy,
16711
+ symbol,
16712
+ signalTimestamp: result.timestamp
16713
+ })
16714
+ );
16715
+ if (original)
16716
+ original.followUp = {
16717
+ ...describeOutcome(result),
16718
+ candleTimestamp: timestamp
16719
+ };
16720
+ notEvaluatedReason = "REPLAY_PROCESSED_DELAYED_ENTRY";
16721
+ }
16722
+ if (!trace) return;
16723
+ trace.candle = { timestamp, open, high, low, close, volume };
16724
+ trace.decision = notEvaluatedReason ? { stage: "not_evaluated", reason: notEvaluatedReason } : describeOutcome(result);
16725
+ };
16726
+ return { record, values: () => [...traces.values()] };
16727
+ };
16728
+ }
16729
+ });
16730
+
16652
16731
  // src/lib/replay/historicalSignalsReplaySkipEvidence.ts
16653
16732
  var import_data3, replayScopeKey, appendReplaySignalEvaluationRun, createHistoricalReplaySkipEvidence;
16654
16733
  var init_historicalSignalsReplaySkipEvidence = __esm({
@@ -16739,6 +16818,7 @@ var init_historicalSignalsReplayExecution = __esm({
16739
16818
  "src/lib/replay/historicalSignalsReplayExecution.ts"() {
16740
16819
  "use strict";
16741
16820
  init_historicalSignalsReplayPreparation();
16821
+ init_historicalSignalsReplayDecisionTrace();
16742
16822
  init_historicalSignalsReplaySkipEvidence();
16743
16823
  advanceCycleMarket = async (plan, connector, timestamp) => {
16744
16824
  const cycleSymbols = plan.symbolRuntimes.filter(
@@ -16771,6 +16851,7 @@ var init_historicalSignalsReplayExecution = __esm({
16771
16851
  context.plan.runtimeLineages,
16772
16852
  context.collectSkipEvidence
16773
16853
  );
16854
+ const decisionTrace = createReplayDecisionTrace(context.decisionTraceTargets);
16774
16855
  const reportProgress = (timestamp) => {
16775
16856
  if (adapters.progress.enabled === false) return;
16776
16857
  adapters.progress.tick({
@@ -16799,6 +16880,20 @@ var init_historicalSignalsReplayExecution = __esm({
16799
16880
  status: "completed",
16800
16881
  durationMs: adapters.clock.now() - cycleStartedAt
16801
16882
  });
16883
+ if (context.decisionTraceTargets?.length) {
16884
+ for (const symbolRuntime of cycleSymbols) {
16885
+ const candle = symbolRuntime.replayData[symbolRuntime.currentIndex];
16886
+ for (const strategy of symbolRuntime.strategies) {
16887
+ decisionTrace.record(
16888
+ strategy.strategyName,
16889
+ symbolRuntime.symbol,
16890
+ candle,
16891
+ void 0,
16892
+ "REPLAY_CYCLE_ABORTED"
16893
+ );
16894
+ }
16895
+ }
16896
+ }
16802
16897
  advanceAbortedCycle(cycleSymbols, timestamp);
16803
16898
  reportProgress(timestamp);
16804
16899
  continue;
@@ -16809,6 +16904,17 @@ var init_historicalSignalsReplayExecution = __esm({
16809
16904
  const btcCandle = symbolRuntime.btcReplayData[symbolRuntime.currentIndex];
16810
16905
  const ethCandle = symbolRuntime.ethReplayData[symbolRuntime.currentIndex];
16811
16906
  if (!candle || !btcCandle || candle.timestamp + (symbolRuntime.timestampOffsetMs ?? 0) !== timestamp || btcCandle.timestamp !== candle.timestamp) {
16907
+ if (candle && context.decisionTraceTargets?.length) {
16908
+ for (const strategy of symbolRuntime.strategies) {
16909
+ decisionTrace.record(
16910
+ strategy.strategyName,
16911
+ symbolRuntime.symbol,
16912
+ candle,
16913
+ void 0,
16914
+ "REPLAY_CANDLE_OR_REFERENCE_NOT_ALIGNED"
16915
+ );
16916
+ }
16917
+ }
16812
16918
  continue;
16813
16919
  }
16814
16920
  for (const strategyRuntime of symbolRuntime.strategies) {
@@ -16817,6 +16923,12 @@ var init_historicalSignalsReplayExecution = __esm({
16817
16923
  btcCandle,
16818
16924
  ethCandle?.timestamp === candle.timestamp ? ethCandle : void 0
16819
16925
  );
16926
+ decisionTrace.record(
16927
+ strategyRuntime.strategyName,
16928
+ symbolRuntime.symbol,
16929
+ candle,
16930
+ result
16931
+ );
16820
16932
  skipEvidence.record({
16821
16933
  strategyName: strategyRuntime.strategyName,
16822
16934
  symbol: symbolRuntime.symbol,
@@ -16848,7 +16960,8 @@ var init_historicalSignalsReplayExecution = __esm({
16848
16960
  return {
16849
16961
  signals: signals2,
16850
16962
  abortedCycles,
16851
- replayLineageScopes: skipEvidence.values()
16963
+ replayLineageScopes: skipEvidence.values(),
16964
+ replayDecisionTraces: decisionTrace.values()
16852
16965
  };
16853
16966
  };
16854
16967
  }
@@ -16905,7 +17018,8 @@ var init_historicalSignalsReplayResults = __esm({
16905
17018
  cycleCount: context.cycleCount,
16906
17019
  abortedCycles: context.abortedCycles,
16907
17020
  runtimeLineages: context.runtimeLineages,
16908
- replayLineageScopes: context.replayLineageScopes
17021
+ replayLineageScopes: context.replayLineageScopes,
17022
+ ...context.replayDecisionTraces?.length ? { replayDecisionTraces: context.replayDecisionTraces } : {}
16909
17023
  });
16910
17024
  compactHistoricalReplayResultForPortfolio = (result) => ({
16911
17025
  ...result,
@@ -16951,7 +17065,10 @@ var init_historicalSignalsReplayResults = __esm({
16951
17065
  cycleCount: parts.reduce((sum3, part) => sum3 + part.cycleCount, 0),
16952
17066
  abortedCycles: parts.reduce((sum3, part) => sum3 + part.abortedCycles, 0),
16953
17067
  runtimeLineages: parts.flatMap((part) => part.runtimeLineages),
16954
- replayLineageScopes: parts.flatMap((part) => part.replayLineageScopes)
17068
+ replayLineageScopes: parts.flatMap((part) => part.replayLineageScopes),
17069
+ replayDecisionTraces: parts.flatMap(
17070
+ (part) => part.replayDecisionTraces ?? []
17071
+ )
16955
17072
  };
16956
17073
  };
16957
17074
  }
@@ -17127,7 +17244,8 @@ var init_historicalSignalsReplay = __esm({
17127
17244
  references,
17128
17245
  showProgress = true,
17129
17246
  collectSkipEvidence = true,
17130
- collectSignals = true
17247
+ collectSignals = true,
17248
+ decisionTraceTargets
17131
17249
  }) => {
17132
17250
  const memory = createReplayMemoryProfile();
17133
17251
  memory?.("prepare:start");
@@ -17214,6 +17332,7 @@ var init_historicalSignalsReplay = __esm({
17214
17332
  connector: replayConnector,
17215
17333
  collectSkipEvidence,
17216
17334
  collectSignals,
17335
+ decisionTraceTargets,
17217
17336
  hooks: projectHooks,
17218
17337
  hookContext
17219
17338
  },
@@ -17250,7 +17369,8 @@ var init_historicalSignalsReplay = __esm({
17250
17369
  cycleCount: plan.orderedTimestamps.length,
17251
17370
  abortedCycles: execution.abortedCycles,
17252
17371
  runtimeLineages: plan.runtimeLineages,
17253
- replayLineageScopes: execution.replayLineageScopes
17372
+ replayLineageScopes: execution.replayLineageScopes,
17373
+ replayDecisionTraces: execution.replayDecisionTraces
17254
17374
  });
17255
17375
  memory?.("result:collected");
17256
17376
  return result;
@@ -17487,6 +17607,7 @@ var init_runtimeParity = __esm({
17487
17607
  direction: trade.direction,
17488
17608
  qty: toFiniteNumberOrNull2(trade.qty),
17489
17609
  timestamp: trade.entryTimestamp,
17610
+ ...Number.isFinite(trade.signalTimestamp) ? { signalTimestamp: trade.signalTimestamp } : {},
17490
17611
  price: toFiniteNumberOrNull2(trade.entryPrice),
17491
17612
  orderId: trade.orderId,
17492
17613
  signalId: typeof trade.signalId === "string" ? trade.signalId : void 0,
@@ -18407,6 +18528,7 @@ var init_runtimeParityDetails = __esm({
18407
18528
  "use strict";
18408
18529
  import_trade2 = require("@tradejs/core/trade");
18409
18530
  init_runtimeParity();
18531
+ init_historicalSignalsReplayDecisionTrace();
18410
18532
  DEFAULT_REPLAY_PARITY_DETAILS_LIMIT = 500;
18411
18533
  DEFAULT_REPLAY_PARITY_ARTIFACT_LIMIT = 100;
18412
18534
  buildStrategyNameByOrderLinkKey = (strategyNames) => new Map(
@@ -18481,6 +18603,7 @@ var init_runtimeParityDetails = __esm({
18481
18603
  direction: entry.direction,
18482
18604
  qty: entry.qty ?? null,
18483
18605
  timestamp: entry.timestamp,
18606
+ ...entry.signalTimestamp != null ? { signalTimestamp: entry.signalTimestamp } : {},
18484
18607
  price: entry.price,
18485
18608
  exitType: entry.exitType ?? null,
18486
18609
  exitTimestamp: entry.exitTimestamp ?? null,
@@ -18554,7 +18677,8 @@ var init_runtimeParityDetails = __esm({
18554
18677
  evaluations,
18555
18678
  toleranceMs,
18556
18679
  timestampOffsetMs,
18557
- entryTimestampOffsetMs = 0
18680
+ entryTimestampOffsetMs = 0,
18681
+ matchDirection = false
18558
18682
  }) => {
18559
18683
  const entryStrategy2 = getEntryStrategy(entry);
18560
18684
  if (!entryStrategy2) {
@@ -18564,7 +18688,7 @@ var init_runtimeParityDetails = __esm({
18564
18688
  let bestDiff = Number.POSITIVE_INFINITY;
18565
18689
  const entryTimestamp = entry.timestamp + entryTimestampOffsetMs;
18566
18690
  for (const evaluation of evaluations) {
18567
- if (evaluation.strategy !== entryStrategy2 || evaluation.symbol !== entry.symbol) {
18691
+ if (evaluation.strategy !== entryStrategy2 || evaluation.symbol !== entry.symbol || matchDirection && evaluation.direction != null && evaluation.direction !== entry.direction) {
18568
18692
  continue;
18569
18693
  }
18570
18694
  const diff = Math.abs(
@@ -18910,6 +19034,7 @@ var init_runtimeParityDetails = __esm({
18910
19034
  replaySignals = [],
18911
19035
  replaySignalEvaluations = [],
18912
19036
  replayLineageScopes = [],
19037
+ replayDecisionTraces = [],
18913
19038
  runtimeLineageScopes = [],
18914
19039
  toleranceMs,
18915
19040
  backtestTimestampOffsetMs,
@@ -18918,48 +19043,66 @@ var init_runtimeParityDetails = __esm({
18918
19043
  const nearestByEntry = new Map(
18919
19044
  nearestCandidates.map((candidate) => [candidate.entry, candidate])
18920
19045
  );
19046
+ const traceByCandle = new Map(
19047
+ replayDecisionTraces.map((trace) => [replayDecisionTraceKey(trace), trace])
19048
+ );
18921
19049
  const artifactLimit = Math.min(limit, resolveReplayParityArtifactLimit());
18922
19050
  let runtimeOnlyArtifactsIncluded = 0;
18923
19051
  let backtestOnlyArtifactsIncluded = 0;
18924
19052
  const runtimeOnlyDiagnostics = runtimeOnly.map((entry, index) => {
18925
- const entryOffsetMs = resolveTradeParityTimestampOffset(
18926
- getEntryStrategy(entry) ?? "",
18927
- backtestTimestampOffsetMs
18928
- );
19053
+ const isRuntimeTrade = entry.source === "runtime";
19054
+ const decisionEntry = isRuntimeTrade ? entry.signalTimestamp == null ? null : { ...entry, timestamp: entry.signalTimestamp } : entry;
19055
+ const decisionClock = {
19056
+ toleranceMs: isRuntimeTrade ? 0 : toleranceMs,
19057
+ timestampOffsetMs: isRuntimeTrade ? 0 : resolveTradeParityTimestampOffset(
19058
+ getEntryStrategy(entry) ?? "",
19059
+ backtestTimestampOffsetMs
19060
+ )
19061
+ };
18929
19062
  const includeArtifacts = index < artifactLimit;
18930
19063
  const nearestCandidate = nearestByEntry.get(entry);
18931
- const nearestReplaySignal = findNearestSignal({
18932
- entry,
19064
+ const nearestReplaySignal = decisionEntry && findNearestSignal({
19065
+ entry: decisionEntry,
18933
19066
  signals: replaySignals,
18934
- toleranceMs,
18935
- timestampOffsetMs: entryOffsetMs
19067
+ ...decisionClock
18936
19068
  });
18937
- const nearestReplayEvaluation = findNearestEvaluation({
18938
- entry,
19069
+ const nearestReplayEvaluation = decisionEntry && findNearestEvaluation({
19070
+ entry: decisionEntry,
18939
19071
  evaluations: replaySignalEvaluations,
18940
- toleranceMs,
18941
- timestampOffsetMs: entryOffsetMs
19072
+ matchDirection: isRuntimeTrade,
19073
+ ...decisionClock
18942
19074
  });
18943
- const nearestReplayEvaluationOutcome = findNearestReplayEvaluationOutcome({
18944
- entry,
19075
+ const nearestReplayEvaluationOutcome = decisionEntry && findNearestReplayEvaluationOutcome({
19076
+ entry: decisionEntry,
18945
19077
  lineageScopes: replayLineageScopes,
18946
- toleranceMs,
18947
- timestampOffsetMs: entryOffsetMs
19078
+ ...decisionClock
18948
19079
  });
19080
+ const strategy = getEntryStrategy(entry);
19081
+ const replayDecisionTrace = isRuntimeTrade && strategy && decisionEntry ? traceByCandle.get(
19082
+ replayDecisionTraceKey({
19083
+ strategy,
19084
+ symbol: entry.symbol,
19085
+ signalTimestamp: decisionEntry.timestamp
19086
+ })
19087
+ ) : void 0;
19088
+ const unavailableReason = !isRuntimeTrade ? "no_replay_signal_or_backtest_candidate" : !decisionEntry ? "replay_signal_timestamp_unavailable" : replayDecisionTrace?.decision.stage === "not_evaluated" ? replayDecisionTrace.decision.reason : "replay_evaluation_unavailable";
18949
19089
  const classification = nearestReplaySignal ? classifySignalDiagnostic(nearestReplaySignal.signal) : nearestReplayEvaluation ? classifyEvaluationDiagnostic(nearestReplayEvaluation.evaluation) : nearestReplayEvaluationOutcome ? {
18950
- classification: "core_skipped",
19090
+ classification: nearestReplayEvaluationOutcome.reason.startsWith(
19091
+ "BACKTEST_ENTRY_DELAY_"
19092
+ ) ? "entry_delayed" : "core_skipped",
18951
19093
  reason: nearestReplayEvaluationOutcome.reason
18952
- } : nearestCandidate?.nearest ? {
19094
+ } : !isRuntimeTrade && nearestCandidate?.nearest ? {
18953
19095
  classification: "timing_or_price_drift",
18954
19096
  reason: nearestCandidate.reason
18955
19097
  } : {
18956
19098
  classification: "no_replay_candidate",
18957
- reason: "no_replay_signal_or_backtest_candidate"
19099
+ reason: unavailableReason
18958
19100
  };
18959
19101
  return {
18960
19102
  entry,
18961
19103
  ...classification,
18962
19104
  ...nearestCandidate ? { nearestCandidate } : {},
19105
+ ...replayDecisionTrace ? { replayDecisionTrace } : {},
18963
19106
  ...nearestReplaySignal ? {
18964
19107
  replaySignal: toSignalDiagnostic({
18965
19108
  signal: nearestReplaySignal.signal,
@@ -19085,6 +19228,7 @@ var init_runtimeParityDetails = __esm({
19085
19228
  replaySignals,
19086
19229
  replaySignalEvaluations,
19087
19230
  replayLineageScopes,
19231
+ replayDecisionTraces,
19088
19232
  runtimeLineageScopes
19089
19233
  }) => {
19090
19234
  const runtimeDetails = runtimeEntries.map(toRuntimeParityDetail);
@@ -19145,6 +19289,7 @@ var init_runtimeParityDetails = __esm({
19145
19289
  replaySignals,
19146
19290
  replaySignalEvaluations,
19147
19291
  replayLineageScopes,
19292
+ replayDecisionTraces,
19148
19293
  runtimeLineageScopes,
19149
19294
  toleranceMs,
19150
19295
  backtestTimestampOffsetMs,
@@ -20209,6 +20354,7 @@ var init_runtimeComparison = __esm({
20209
20354
  replaySignals,
20210
20355
  replayLineages,
20211
20356
  replayLineageScopes,
20357
+ replayDecisionTraces,
20212
20358
  runtimeEvidencePath
20213
20359
  }) => {
20214
20360
  const { connector, connectorName, window } = getRuntimeCompareContext();
@@ -20360,7 +20506,8 @@ var init_runtimeComparison = __esm({
20360
20506
  replaySignals,
20361
20507
  replaySignalEvaluations,
20362
20508
  runtimeLineageScopes: comparable.runtimeLineageScopes,
20363
- replayLineageScopes
20509
+ replayLineageScopes,
20510
+ replayDecisionTraces
20364
20511
  });
20365
20512
  const parityRows = summarizeTradeParityByStrategy({
20366
20513
  runtimeEntries: runtimeDedupe.entries,
@@ -21338,6 +21485,7 @@ var init_replayRunner = __esm({
21338
21485
  replaySignals: replayResult.signals,
21339
21486
  replayLineages: replayResult.runtimeLineages,
21340
21487
  replayLineageScopes: replayResult.replayLineageScopes,
21488
+ replayDecisionTraces: replayResult.replayDecisionTraces,
21341
21489
  runtimeEvidencePath: replayRuntimeEvidencePath
21342
21490
  });
21343
21491
  const finishedAt = /* @__PURE__ */ new Date();
@@ -21687,7 +21835,8 @@ var init_replayRunner = __esm({
21687
21835
  references: historicalReplayReferences,
21688
21836
  showProgress: !replayFlags.portfolioReport,
21689
21837
  collectSkipEvidence: !replayFlags.portfolioReport,
21690
- collectSignals: !replayFlags.portfolioReport
21838
+ collectSignals: !replayFlags.portfolioReport,
21839
+ decisionTraceTargets: replayFlags.portfolioReport ? void 0 : evidenceMetadata?.decisionTraceTargets
21691
21840
  });
21692
21841
  return replayFlags.portfolioReport ? compactHistoricalReplayResultForPortfolio(result) : result;
21693
21842
  };
@@ -36439,13 +36588,14 @@ var init_runtimeFeedbackArtifacts = __esm({
36439
36588
  });
36440
36589
 
36441
36590
  // src/lib/runtimeFeedbackReplay.ts
36442
- var import_node_child_process9, import_promises35, import_node_path32, REQUIRED_ENV, FORBIDDEN_SECRET_ENV, unsafeRedisHosts, safeSegment, assertRuntimeFeedbackReplaySafety, buildRuntimeFeedbackReplayCommands, runLoggedCommand, runRuntimeFeedbackReplay;
36591
+ var import_node_child_process9, import_promises35, import_node_path32, import_mcp2, REQUIRED_ENV, FORBIDDEN_SECRET_ENV, unsafeRedisHosts, safeSegment, assertRuntimeFeedbackReplaySafety, buildRuntimeFeedbackReplayCommands, runLoggedCommand, runRuntimeFeedbackReplay;
36443
36592
  var init_runtimeFeedbackReplay = __esm({
36444
36593
  "src/lib/runtimeFeedbackReplay.ts"() {
36445
36594
  "use strict";
36446
36595
  import_node_child_process9 = require("child_process");
36447
36596
  import_promises35 = __toESM(require("fs/promises"));
36448
36597
  import_node_path32 = __toESM(require("path"));
36598
+ import_mcp2 = require("@tradejs/node/mcp");
36449
36599
  init_runtimeEvidenceDeployment();
36450
36600
  init_runtimeEvidenceArtifacts();
36451
36601
  init_runtimeEvidenceProducer();
@@ -36579,44 +36729,58 @@ var init_runtimeFeedbackReplay = __esm({
36579
36729
  env,
36580
36730
  logHandle
36581
36731
  }) => {
36582
- await logHandle.write(`
36583
- $ ${[executable, ...command].join(" ")}
36584
- `);
36585
- await new Promise((resolve, reject) => {
36586
- let pendingLogWrite = Promise.resolve();
36587
- const appendLog = (chunk) => {
36588
- pendingLogWrite = pendingLogWrite.then(async () => {
36589
- await logHandle.write(chunk);
36590
- });
36591
- };
36592
- const child = (0, import_node_child_process9.spawn)(executable, command, {
36593
- cwd,
36594
- env,
36595
- stdio: ["ignore", "pipe", "pipe"]
36596
- });
36597
- child.stdout.on("data", (chunk) => {
36598
- process.stdout.write(chunk);
36599
- appendLog(chunk);
36600
- });
36601
- child.stderr.on("data", (chunk) => {
36602
- process.stderr.write(chunk);
36603
- appendLog(chunk);
36604
- });
36732
+ await logHandle.writeFile(
36733
+ "\n" + (0, import_mcp2.formatMcpArtifactLogLine)(`$ ${[executable, ...command].join(" ")}`)
36734
+ );
36735
+ const child = (0, import_node_child_process9.spawn)(executable, command, {
36736
+ cwd,
36737
+ env,
36738
+ stdio: ["ignore", "pipe", "pipe"]
36739
+ });
36740
+ const exit = new Promise((resolve, reject) => {
36605
36741
  child.once("error", reject);
36606
36742
  child.once("close", (code, signal) => {
36607
- void pendingLogWrite.then(() => {
36608
- if (code === 0) {
36609
- resolve();
36610
- return;
36611
- }
36743
+ if (code === 0) resolve();
36744
+ else {
36612
36745
  reject(
36613
36746
  new Error(
36614
36747
  `Runtime feedback command failed: exit=${String(code)} signal=${String(signal)}`
36615
36748
  )
36616
36749
  );
36617
- }, reject);
36750
+ }
36618
36751
  });
36619
36752
  });
36753
+ let pendingLogWrite = Promise.resolve();
36754
+ const copyLog = async (input, output) => {
36755
+ const writeLine2 = async (line) => {
36756
+ const formatted = (0, import_mcp2.formatMcpArtifactLogLine)(line);
36757
+ pendingLogWrite = pendingLogWrite.then(
36758
+ () => logHandle.writeFile(formatted)
36759
+ );
36760
+ await pendingLogWrite;
36761
+ output.write(formatted);
36762
+ };
36763
+ let pendingLine = "";
36764
+ try {
36765
+ for await (const chunk of input.setEncoding("utf8")) {
36766
+ const lines = (pendingLine + chunk).split("\n");
36767
+ pendingLine = lines.pop() ?? "";
36768
+ for (const line of lines) await writeLine2(line);
36769
+ }
36770
+ if (pendingLine) await writeLine2(pendingLine);
36771
+ } catch (error) {
36772
+ child.kill();
36773
+ throw error;
36774
+ }
36775
+ };
36776
+ const results2 = await Promise.allSettled([
36777
+ copyLog(child.stdout, process.stdout),
36778
+ copyLog(child.stderr, process.stderr),
36779
+ exit
36780
+ ]);
36781
+ for (const result of results2) {
36782
+ if (result.status === "rejected") throw result.reason;
36783
+ }
36620
36784
  };
36621
36785
  runRuntimeFeedbackReplay = async ({
36622
36786
  runtimeEvidencePath,
@@ -36761,10 +36925,11 @@ var init_runtimeFeedbackReplay2 = __esm({
36761
36925
  });
36762
36926
 
36763
36927
  // src/lib/runtimeFeedbackNotification.ts
36764
- var isRecord, asRecord6, asArray3, finiteNumber5, requiredTimestamp, escapeHtml5, formatMskDateTime2, formatConnectorName, sumRows, buildRuntimeFeedbackTelegramMessage, notifyRuntimeFeedbackBundle;
36928
+ var import_userSettings7, isRecord, asRecord6, asArray3, finiteNumber5, requiredTimestamp, escapeHtml5, formatMskDateTime2, formatConnectorName, sumRows, buildRuntimeFeedbackTelegramMessage, notifyRuntimeFeedbackBundle;
36765
36929
  var init_runtimeFeedbackNotification = __esm({
36766
36930
  "src/lib/runtimeFeedbackNotification.ts"() {
36767
36931
  "use strict";
36932
+ import_userSettings7 = require("@tradejs/infra/userSettings");
36768
36933
  init_runtimeFeedbackArtifacts();
36769
36934
  init_telegramReports();
36770
36935
  isRecord = (value) => value != null && typeof value === "object" && !Array.isArray(value);
@@ -36877,11 +37042,14 @@ var init_runtimeFeedbackNotification = __esm({
36877
37042
  }) => {
36878
37043
  const verified = await (0, runtimeFeedbackArtifacts_exports.verifyRuntimeFeedbackReplayBundle)(bundleDir);
36879
37044
  const message = buildRuntimeFeedbackTelegramMessage(verified.replayEvidence);
36880
- await send(message, { userName: verified.manifest.userName });
37045
+ const settings = await (0, import_userSettings7.getUserSettings)(verified.manifest.userName);
37046
+ const sent = settings.NOTIFY_RUNTIME_DEBUG !== false;
37047
+ if (sent) await send(message, { userName: verified.manifest.userName });
36881
37048
  return {
36882
37049
  artifactId: verified.manifest.artifactId,
36883
37050
  userName: verified.manifest.userName,
36884
- message
37051
+ message,
37052
+ sent
36885
37053
  };
36886
37054
  };
36887
37055
  }
@@ -36919,7 +37087,9 @@ var init_runtimeFeedbackNotify = __esm({
36919
37087
  }
36920
37088
  const result = await notifyRuntimeFeedbackBundle({ bundleDir });
36921
37089
  console.log(
36922
- import_chalk45.default.green(`Runtime feedback notification sent: ${result.artifactId}`)
37090
+ import_chalk45.default.green(
37091
+ `Runtime feedback notification ${result.sent ? "sent" : "disabled"}: ${result.artifactId}`
37092
+ )
36923
37093
  );
36924
37094
  };
36925
37095
  main39 = runtimeFeedbackNotify;
@@ -45302,11 +45472,12 @@ __export(signalsSummary_exports, {
45302
45472
  main: () => main51,
45303
45473
  signalsSummary: () => signalsSummary
45304
45474
  });
45305
- var import_config13, import_args38, import_logger12, import_connectors19, import_runtimeStrategies9, flags34, 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, main51;
45475
+ var import_config13, import_userSettings8, import_args38, import_logger12, import_connectors19, import_runtimeStrategies9, flags34, 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, main51;
45306
45476
  var init_signalsSummary = __esm({
45307
45477
  "src/scripts/signalsSummary.ts"() {
45308
45478
  "use strict";
45309
45479
  import_config13 = require("dotenv/config");
45480
+ import_userSettings8 = require("@tradejs/infra/userSettings");
45310
45481
  import_args38 = __toESM(require("args"));
45311
45482
  import_logger12 = require("@tradejs/infra/logger");
45312
45483
  import_connectors19 = require("@tradejs/node/connectors");
@@ -45840,6 +46011,7 @@ none`
45840
46011
  };
45841
46012
  };
45842
46013
  signalsSummary = async () => {
46014
+ const includeDebug = flags34.printOnly || (await (0, import_userSettings8.getUserSettings)(flags34.user)).NOTIFY_RUNTIME_DEBUG !== false;
45843
46015
  const hours = Math.max(
45844
46016
  1,
45845
46017
  Number.parseInt(String(flags34.hours ?? 24), 10) || 24
@@ -45960,18 +46132,15 @@ none`
45960
46132
  content: signalsMessage,
45961
46133
  deploymentId: scope.deploymentId
45962
46134
  });
45963
- const tradesMessageWithAttachmentSummary = appendReportAttachmentSummary({
46135
+ const tradesMessageWithAttachmentSummary = includeDebug ? appendReportAttachmentSummary({
45964
46136
  message: tradesMessage,
45965
46137
  signalsFilename: signalsAttachment.filename,
45966
46138
  filename: debugAttachment?.filename,
45967
46139
  tradesCount: debugAttachment ? scopeTrades.length : void 0,
45968
46140
  signalsCount: debugAttachment ? debugAttachment.summary?.signals ?? debugSignals.length : void 0,
45969
46141
  evaluationsCount: debugAttachment ? debugAttachment.summary?.evaluations ?? 0 : void 0
45970
- });
45971
- const attachments = [
45972
- signalsAttachment,
45973
- ...debugAttachment ? [debugAttachment] : []
45974
- ];
46142
+ }) : tradesMessage;
46143
+ const attachments = includeDebug ? [signalsAttachment, ...debugAttachment ? [debugAttachment] : []] : [];
45975
46144
  if (flags34.printOnly) {
45976
46145
  console.log(tradesMessageWithAttachmentSummary);
45977
46146
  console.log("");
@@ -25,6 +25,7 @@ __export(runtimeFeedbackNotification_exports, {
25
25
  notifyRuntimeFeedbackBundle: () => notifyRuntimeFeedbackBundle
26
26
  });
27
27
  module.exports = __toCommonJS(runtimeFeedbackNotification_exports);
28
+ var import_userSettings = require("@tradejs/infra/userSettings");
28
29
 
29
30
  // src/lib/runtimeFeedbackArtifacts.ts
30
31
  var runtimeFeedbackArtifacts_exports = {};
@@ -210,11 +211,14 @@ var notifyRuntimeFeedbackBundle = async ({
210
211
  }) => {
211
212
  const verified = await (0, runtimeFeedbackArtifacts_exports.verifyRuntimeFeedbackReplayBundle)(bundleDir);
212
213
  const message = buildRuntimeFeedbackTelegramMessage(verified.replayEvidence);
213
- await send(message, { userName: verified.manifest.userName });
214
+ const settings = await (0, import_userSettings.getUserSettings)(verified.manifest.userName);
215
+ const sent = settings.NOTIFY_RUNTIME_DEBUG !== false;
216
+ if (sent) await send(message, { userName: verified.manifest.userName });
214
217
  return {
215
218
  artifactId: verified.manifest.artifactId,
216
219
  userName: verified.manifest.userName,
217
- message
220
+ message,
221
+ sent
218
222
  };
219
223
  };
220
224
  // Annotate the CommonJS export names for ESM import in node: