@tradejs/cli 3.1.28-beta.254 → 3.1.28-beta.256

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
@@ -1871,7 +1871,7 @@ var init_aiTrainOptions = __esm({
1871
1871
  });
1872
1872
 
1873
1873
  // src/lib/aiPocketSearch/commandOptions.ts
1874
- var normalizeInt, normalizePositiveInt, normalizeNonNegativeNumber, normalizeRatio, normalizeUnitRatio, normalizeFeatureProfile, normalizeFeaturePolicy, normalizeCoverageMode, normalizeCadenceMode, normalizeObjective, hasCliOption2, resolveAiPocketSearchCommandOptions;
1874
+ var normalizeInt, normalizePositiveInt, normalizeNonNegativeNumber, normalizeRatio, normalizeUnitRatio, normalizeFeatureProfile, normalizeFeaturePolicy, normalizeExcludeFeaturePattern, normalizeCoverageMode, normalizeCadenceMode, normalizeObjective, hasCliOption2, resolveAiPocketSearchCommandOptions;
1875
1875
  var init_commandOptions = __esm({
1876
1876
  "src/lib/aiPocketSearch/commandOptions.ts"() {
1877
1877
  "use strict";
@@ -1916,6 +1916,17 @@ var init_commandOptions = __esm({
1916
1916
  }
1917
1917
  return normalized;
1918
1918
  };
1919
+ normalizeExcludeFeaturePattern = (value) => {
1920
+ const pattern = String(value ?? "");
1921
+ if (!pattern) {
1922
+ return void 0;
1923
+ }
1924
+ try {
1925
+ return new RegExp(pattern);
1926
+ } catch {
1927
+ throw new Error("Invalid --excludeFeaturePattern regular expression.");
1928
+ }
1929
+ };
1919
1930
  normalizeCoverageMode = (value) => {
1920
1931
  const normalized = String(value || "auto").trim().toLowerCase();
1921
1932
  if (!["auto", "full"].includes(normalized)) {
@@ -2093,6 +2104,9 @@ var init_commandOptions = __esm({
2093
2104
  includeGateContext: Boolean(flags34.includeGateContext),
2094
2105
  featureProfile: normalizeFeatureProfile(flags34.featureProfile),
2095
2106
  featurePolicy: normalizeFeaturePolicy(flags34.featurePolicy),
2107
+ excludeFeaturePattern: normalizeExcludeFeaturePattern(
2108
+ flags34.excludeFeaturePattern
2109
+ ),
2096
2110
  coverageMode: normalizeCoverageMode(flags34.coverageMode),
2097
2111
  cadenceMode: normalizeCadenceMode(flags34.cadenceMode),
2098
2112
  jsonOutput: Boolean(flags34.json),
@@ -2683,10 +2697,22 @@ var init_features = __esm({
2683
2697
  includeGateContext = false,
2684
2698
  featureProfile = "all",
2685
2699
  featurePolicy = "all",
2700
+ excludeFeaturePattern,
2686
2701
  onFeatureExcluded
2687
2702
  }) => {
2688
2703
  const features = {};
2689
2704
  const featureCoverage = resolveAiPocketFeatureCoverage(payload);
2705
+ const exclusion = excludeFeaturePattern ? new RegExp(
2706
+ excludeFeaturePattern.source,
2707
+ excludeFeaturePattern.flags.replace(/[gy]/g, "")
2708
+ ) : void 0;
2709
+ const isOperatorExcluded = (path44) => {
2710
+ if (!exclusion?.test(path44)) {
2711
+ return false;
2712
+ }
2713
+ onFeatureExcluded?.({ path: path44, classification: "operator-excluded" });
2714
+ return true;
2715
+ };
2690
2716
  const signal = payload.signal ?? {};
2691
2717
  const source = {
2692
2718
  signal: {
@@ -2705,6 +2731,9 @@ var init_features = __esm({
2705
2731
  segments: [],
2706
2732
  maxDepth: 8,
2707
2733
  shouldSkipPath: (segments) => {
2734
+ if (isOperatorExcluded(segments.join("."))) {
2735
+ return true;
2736
+ }
2708
2737
  const coverageFamily = classifyAiPocketCoverageFeaturePath(segments);
2709
2738
  if (featurePolicy === "causal-stationary" && coverageFamily != null && !isAiPocketCoverageFeatureUsable({
2710
2739
  payload,
@@ -2748,6 +2777,11 @@ var init_features = __esm({
2748
2777
  }
2749
2778
  addSignalRiskDistanceFeatures({ features, signal });
2750
2779
  addDirectionalDerivedFeatures(features);
2780
+ for (const key of Object.keys(features)) {
2781
+ if (isOperatorExcluded(key)) {
2782
+ delete features[key];
2783
+ }
2784
+ }
2751
2785
  return { features, featureCoverage };
2752
2786
  };
2753
2787
  }
@@ -4101,6 +4135,7 @@ var init_markdownReport = __esm({
4101
4135
  ["include_gate_context", run.includeGateContext ? "on" : "off"],
4102
4136
  ["feature_profile", run.featureProfile ?? "all"],
4103
4137
  ["feature_policy", run.featurePolicy ?? "all"],
4138
+ ...run.excludeFeaturePattern ? [["exclude_feature_pattern", run.excludeFeaturePattern]] : [],
4104
4139
  ["coverage_mode", run.coverageMode ?? "full"],
4105
4140
  ["cadence_mode", run.cadenceMode ?? "fixed"],
4106
4141
  ["low_cadence", pocketSearch.stats.cadence.lowCadence ? "yes" : "no"],
@@ -4832,6 +4867,12 @@ var init_presenter = __esm({
4832
4867
  ],
4833
4868
  ["feature_profile", import_chalk4.default.magenta(featureProfile)],
4834
4869
  ["feature_policy", import_chalk4.default.magenta(featurePolicy)],
4870
+ ...run.excludeFeaturePattern ? [
4871
+ [
4872
+ "exclude_feature_pattern",
4873
+ import_chalk4.default.magenta(run.excludeFeaturePattern)
4874
+ ]
4875
+ ] : [],
4835
4876
  ["coverage_mode", import_chalk4.default.magenta(coverageMode)],
4836
4877
  [
4837
4878
  "allow_risk_regression",
@@ -5391,6 +5432,7 @@ var init_dataset = __esm({
5391
5432
  includeGateContext: options.includeGateContext,
5392
5433
  featureProfile: options.featureProfile,
5393
5434
  featurePolicy: options.featurePolicy,
5435
+ excludeFeaturePattern: options.excludeFeaturePattern,
5394
5436
  onFeatureExcluded: ({ path: featurePath, classification }) => {
5395
5437
  const paths = excludedFeaturePaths.get(classification) ?? /* @__PURE__ */ new Set();
5396
5438
  paths.add(featurePath);
@@ -6035,6 +6077,7 @@ var init_command = __esm({
6035
6077
  includeGateContext,
6036
6078
  featureProfile,
6037
6079
  featurePolicy,
6080
+ excludeFeaturePattern,
6038
6081
  coverageMode,
6039
6082
  cadenceMode,
6040
6083
  jsonOutput,
@@ -6111,6 +6154,7 @@ var init_command = __esm({
6111
6154
  includeGateContext,
6112
6155
  featureProfile,
6113
6156
  featurePolicy,
6157
+ ...excludeFeaturePattern ? { excludeFeaturePattern: excludeFeaturePattern.source } : {},
6114
6158
  coverageMode,
6115
6159
  cadenceMode,
6116
6160
  coverageSearches: coverageSearches.map(
@@ -6363,6 +6407,11 @@ var init_aiPocketSearch2 = __esm({
6363
6407
  "Feature policy: causal-stationary or all",
6364
6408
  "causal-stationary"
6365
6409
  );
6410
+ import_args3.default.option(
6411
+ ["x", "excludeFeaturePattern"],
6412
+ "Case-sensitive regular expression excluding feature paths before predicate ranking",
6413
+ ""
6414
+ );
6366
6415
  import_args3.default.option(
6367
6416
  ["Q", "coverageMode"],
6368
6417
  "Coverage-aware search mode: auto or full",
@@ -14936,7 +14985,8 @@ var init_runtimeEvidenceDeployment = __esm({
14936
14985
  };
14937
14986
  resolveRuntimeEvidenceTickerUniverse = ({
14938
14987
  deployment,
14939
- lineageScopes
14988
+ lineageScopes,
14989
+ fallbackTickers
14940
14990
  }) => {
14941
14991
  const declaredTickers = deployment.tickers?.filter(isNonEmptyString) ?? [];
14942
14992
  if (declaredTickers.length > 0) {
@@ -14976,6 +15026,15 @@ var init_runtimeEvidenceDeployment = __esm({
14976
15026
  tickers.add(scope.symbol.trim());
14977
15027
  }
14978
15028
  if (tickers.size === 0) {
15029
+ const verifiedFallbackTickers = fallbackTickers?.filter(isNonEmptyString) ?? [];
15030
+ if (verifiedFallbackTickers.length > 0) {
15031
+ return {
15032
+ ...deployment,
15033
+ tickers: [
15034
+ ...new Set(verifiedFallbackTickers.map((ticker) => ticker.trim()))
15035
+ ].sort()
15036
+ };
15037
+ }
14979
15038
  throw new Error(
14980
15039
  "Runtime evidence has no immutable ticker universe for the embedded deployment composition"
14981
15040
  );
@@ -32660,7 +32719,7 @@ var init_runtimeEvidenceCompositions = __esm({
32660
32719
  for (const snapshot of compositionSnapshots) {
32661
32720
  if (snapshot.deployment.id !== currentDeployment.id) continue;
32662
32721
  register({
32663
- deployment: { ...snapshot.deployment, tickers: void 0 },
32722
+ deployment: snapshot.deployment,
32664
32723
  producer: snapshot.producer
32665
32724
  });
32666
32725
  }
@@ -32674,7 +32733,11 @@ var init_runtimeEvidenceCompositions = __esm({
32674
32733
  if (bundle.artifact.producer == null) continue;
32675
32734
  register({
32676
32735
  deployment: { ...deployment, tickers: void 0 },
32677
- producer: parseRuntimeEvidenceProducer(bundle.artifact.producer)
32736
+ producer: parseRuntimeEvidenceProducer(bundle.artifact.producer),
32737
+ // A historical composition may reappear through a position that closes
32738
+ // in this window even without current-window lineage scopes. Its latest
32739
+ // checksum-verified universe is only a fallback; fresh scopes win.
32740
+ ...deployment.tickers?.length ? { fallbackTickers: [...deployment.tickers] } : {}
32678
32741
  });
32679
32742
  }
32680
32743
  const historicalCurrent = snapshots.get(
@@ -32743,7 +32806,7 @@ var init_runtimeEvidenceCompositions = __esm({
32743
32806
  `Runtime evidence has no verified deployment snapshot for composition(s): ${missing.sort().join(", ")}`
32744
32807
  );
32745
32808
  }
32746
- return [...observed].filter((compositionId) => snapshots.has(compositionId)).map((compositionId) => snapshots.get(compositionId)).map(({ deployment, producer }) => {
32809
+ return [...observed].filter((compositionId) => snapshots.has(compositionId)).map((compositionId) => snapshots.get(compositionId)).map(({ deployment, producer, fallbackTickers }) => {
32747
32810
  const trades = evidence.trades.filter(
32748
32811
  (row) => belongsToSnapshot(row, deployment)
32749
32812
  );
@@ -32765,6 +32828,7 @@ var init_runtimeEvidenceCompositions = __esm({
32765
32828
  return {
32766
32829
  deployment,
32767
32830
  producer,
32831
+ ...fallbackTickers ? { fallbackTickers } : {},
32768
32832
  trades,
32769
32833
  signals: signals2,
32770
32834
  evaluations,
@@ -32941,7 +33005,8 @@ var init_runtimeEvidence = __esm({
32941
33005
  });
32942
33006
  const deployment = resolveRuntimeEvidenceTickerUniverse({
32943
33007
  deployment: composition.deployment,
32944
- lineageScopes: composition.lineageScopes
33008
+ lineageScopes: composition.lineageScopes,
33009
+ fallbackTickers: composition.fallbackTickers
32945
33010
  });
32946
33011
  return {
32947
33012
  artifact: {
@@ -39965,13 +40030,16 @@ var init_runner = __esm({
39965
40030
  const connectorName = await resolveSignalsConnectorName(
39966
40031
  deployment.connectorName
39967
40032
  );
39968
- return new Map(
39969
- buildConfiguredSignalsScopes({
39970
- connectorName,
39971
- deployment,
39972
- strategies: configuredStrategies
39973
- }).map(({ key, scope }) => [key, scope])
39974
- );
40033
+ return {
40034
+ strategies: configuredStrategies,
40035
+ scopes: new Map(
40036
+ buildConfiguredSignalsScopes({
40037
+ connectorName,
40038
+ deployment,
40039
+ strategies: configuredStrategies
40040
+ }).map(({ key, scope }) => [key, scope])
40041
+ )
40042
+ };
39975
40043
  };
39976
40044
  const signalsConfiguredScopesOnce2 = async () => {
39977
40045
  if (config2.updateOnly || config2.showTickersList) {
@@ -39988,7 +40056,7 @@ var init_runner = __esm({
39988
40056
  if (!configuredDeployment) {
39989
40057
  throw new Error(`Runtime deployment not found: ${config2.deploymentId}`);
39990
40058
  }
39991
- const scopes = await loadConfiguredSignalsScopes(configuredDeployment);
40059
+ const { scopes } = await loadConfiguredSignalsScopes(configuredDeployment);
39992
40060
  if (!scopes.size) return signals2();
39993
40061
  for (const scope of scopes.values()) {
39994
40062
  const session = await createSignalsSession2(
@@ -40047,10 +40115,15 @@ var init_runner = __esm({
40047
40115
  if (!currentDeployment) {
40048
40116
  throw new Error(`Runtime deployment not found: ${deploymentId}`);
40049
40117
  }
40118
+ compositionSnapshotRecorder?.observe(
40119
+ currentDeployment.deploymentCompositionId
40120
+ );
40121
+ const { scopes, strategies } = await loadConfiguredSignalsScopes(currentDeployment);
40050
40122
  try {
40051
40123
  await (0, import_runtimeDeploymentEvents.observeRuntimeDeploymentComposition)({
40052
40124
  userName: config2.userName,
40053
- deployment: currentDeployment
40125
+ deployment: currentDeployment,
40126
+ strategies
40054
40127
  });
40055
40128
  } catch (error) {
40056
40129
  import_logger11.logger.warn(
@@ -40059,10 +40132,6 @@ var init_runner = __esm({
40059
40132
  error instanceof Error ? error.message : String(error)
40060
40133
  );
40061
40134
  }
40062
- compositionSnapshotRecorder?.observe(
40063
- currentDeployment.deploymentCompositionId
40064
- );
40065
- const scopes = await loadConfiguredSignalsScopes(currentDeployment);
40066
40135
  for (const [key, staleSession] of sessions) {
40067
40136
  if (scopes.has(key)) continue;
40068
40137
  await staleSession.klineFeed?.close();
@@ -608,10 +608,22 @@ var collectAiPocketFeatureSnapshot = ({
608
608
  includeGateContext = false,
609
609
  featureProfile = "all",
610
610
  featurePolicy = "all",
611
+ excludeFeaturePattern,
611
612
  onFeatureExcluded
612
613
  }) => {
613
614
  const features = {};
614
615
  const featureCoverage = resolveAiPocketFeatureCoverage(payload);
616
+ const exclusion = excludeFeaturePattern ? new RegExp(
617
+ excludeFeaturePattern.source,
618
+ excludeFeaturePattern.flags.replace(/[gy]/g, "")
619
+ ) : void 0;
620
+ const isOperatorExcluded = (path) => {
621
+ if (!exclusion?.test(path)) {
622
+ return false;
623
+ }
624
+ onFeatureExcluded?.({ path, classification: "operator-excluded" });
625
+ return true;
626
+ };
615
627
  const signal = payload.signal ?? {};
616
628
  const source = {
617
629
  signal: {
@@ -630,6 +642,9 @@ var collectAiPocketFeatureSnapshot = ({
630
642
  segments: [],
631
643
  maxDepth: 8,
632
644
  shouldSkipPath: (segments) => {
645
+ if (isOperatorExcluded(segments.join("."))) {
646
+ return true;
647
+ }
633
648
  const coverageFamily = classifyAiPocketCoverageFeaturePath(segments);
634
649
  if (featurePolicy === "causal-stationary" && coverageFamily != null && !isAiPocketCoverageFeatureUsable({
635
650
  payload,
@@ -673,6 +688,11 @@ var collectAiPocketFeatureSnapshot = ({
673
688
  }
674
689
  addSignalRiskDistanceFeatures({ features, signal });
675
690
  addDirectionalDerivedFeatures(features);
691
+ for (const key of Object.keys(features)) {
692
+ if (isOperatorExcluded(key)) {
693
+ delete features[key];
694
+ }
695
+ }
676
696
  return { features, featureCoverage };
677
697
  };
678
698
  var collectAiPocketFeatures = (options) => collectAiPocketFeatureSnapshot(options).features;
@@ -1998,6 +2018,7 @@ var buildAiPocketMarkdownReport = ({
1998
2018
  ["include_gate_context", run.includeGateContext ? "on" : "off"],
1999
2019
  ["feature_profile", run.featureProfile ?? "all"],
2000
2020
  ["feature_policy", run.featurePolicy ?? "all"],
2021
+ ...run.excludeFeaturePattern ? [["exclude_feature_pattern", run.excludeFeaturePattern]] : [],
2001
2022
  ["coverage_mode", run.coverageMode ?? "full"],
2002
2023
  ["cadence_mode", run.cadenceMode ?? "fixed"],
2003
2024
  ["low_cadence", pocketSearch.stats.cadence.lowCadence ? "yes" : "no"],
@@ -424,7 +424,7 @@ var loadRuntimeEvidenceCompositionSnapshots = async ({
424
424
  for (const snapshot of compositionSnapshots) {
425
425
  if (snapshot.deployment.id !== currentDeployment.id) continue;
426
426
  register({
427
- deployment: { ...snapshot.deployment, tickers: void 0 },
427
+ deployment: snapshot.deployment,
428
428
  producer: snapshot.producer
429
429
  });
430
430
  }
@@ -438,7 +438,11 @@ var loadRuntimeEvidenceCompositionSnapshots = async ({
438
438
  if (bundle.artifact.producer == null) continue;
439
439
  register({
440
440
  deployment: { ...deployment, tickers: void 0 },
441
- producer: parseRuntimeEvidenceProducer(bundle.artifact.producer)
441
+ producer: parseRuntimeEvidenceProducer(bundle.artifact.producer),
442
+ // A historical composition may reappear through a position that closes
443
+ // in this window even without current-window lineage scopes. Its latest
444
+ // checksum-verified universe is only a fallback; fresh scopes win.
445
+ ...deployment.tickers?.length ? { fallbackTickers: [...deployment.tickers] } : {}
442
446
  });
443
447
  }
444
448
  const historicalCurrent = snapshots.get(
@@ -507,7 +511,7 @@ var splitRuntimeEvidenceByComposition = ({
507
511
  `Runtime evidence has no verified deployment snapshot for composition(s): ${missing.sort().join(", ")}`
508
512
  );
509
513
  }
510
- return [...observed].filter((compositionId) => snapshots.has(compositionId)).map((compositionId) => snapshots.get(compositionId)).map(({ deployment, producer }) => {
514
+ return [...observed].filter((compositionId) => snapshots.has(compositionId)).map((compositionId) => snapshots.get(compositionId)).map(({ deployment, producer, fallbackTickers }) => {
511
515
  const trades = evidence.trades.filter(
512
516
  (row) => belongsToSnapshot(row, deployment)
513
517
  );
@@ -529,6 +533,7 @@ var splitRuntimeEvidenceByComposition = ({
529
533
  return {
530
534
  deployment,
531
535
  producer,
536
+ ...fallbackTickers ? { fallbackTickers } : {},
532
537
  trades,
533
538
  signals,
534
539
  evaluations,
@@ -192,7 +192,8 @@ var assertCurrentRuntimeEvidenceArtifact = (artifact) => {
192
192
  };
193
193
  var resolveRuntimeEvidenceTickerUniverse = ({
194
194
  deployment,
195
- lineageScopes
195
+ lineageScopes,
196
+ fallbackTickers
196
197
  }) => {
197
198
  const declaredTickers = deployment.tickers?.filter(isNonEmptyString) ?? [];
198
199
  if (declaredTickers.length > 0) {
@@ -232,6 +233,15 @@ var resolveRuntimeEvidenceTickerUniverse = ({
232
233
  tickers.add(scope.symbol.trim());
233
234
  }
234
235
  if (tickers.size === 0) {
236
+ const verifiedFallbackTickers = fallbackTickers?.filter(isNonEmptyString) ?? [];
237
+ if (verifiedFallbackTickers.length > 0) {
238
+ return {
239
+ ...deployment,
240
+ tickers: [
241
+ ...new Set(verifiedFallbackTickers.map((ticker) => ticker.trim()))
242
+ ].sort()
243
+ };
244
+ }
235
245
  throw new Error(
236
246
  "Runtime evidence has no immutable ticker universe for the embedded deployment composition"
237
247
  );
@@ -319,6 +319,17 @@ var normalizeFeaturePolicy = (value) => {
319
319
  }
320
320
  return normalized;
321
321
  };
322
+ var normalizeExcludeFeaturePattern = (value) => {
323
+ const pattern = String(value ?? "");
324
+ if (!pattern) {
325
+ return void 0;
326
+ }
327
+ try {
328
+ return new RegExp(pattern);
329
+ } catch {
330
+ throw new Error("Invalid --excludeFeaturePattern regular expression.");
331
+ }
332
+ };
322
333
  var normalizeCoverageMode = (value) => {
323
334
  const normalized = String(value || "auto").trim().toLowerCase();
324
335
  if (!["auto", "full"].includes(normalized)) {
@@ -496,6 +507,9 @@ var resolveAiPocketSearchCommandOptions = ({
496
507
  includeGateContext: Boolean(flags2.includeGateContext),
497
508
  featureProfile: normalizeFeatureProfile(flags2.featureProfile),
498
509
  featurePolicy: normalizeFeaturePolicy(flags2.featurePolicy),
510
+ excludeFeaturePattern: normalizeExcludeFeaturePattern(
511
+ flags2.excludeFeaturePattern
512
+ ),
499
513
  coverageMode: normalizeCoverageMode(flags2.coverageMode),
500
514
  cadenceMode: normalizeCadenceMode(flags2.cadenceMode),
501
515
  jsonOutput: Boolean(flags2.json),
@@ -1087,10 +1101,22 @@ var collectAiPocketFeatureSnapshot = ({
1087
1101
  includeGateContext = false,
1088
1102
  featureProfile = "all",
1089
1103
  featurePolicy = "all",
1104
+ excludeFeaturePattern,
1090
1105
  onFeatureExcluded
1091
1106
  }) => {
1092
1107
  const features = {};
1093
1108
  const featureCoverage = resolveAiPocketFeatureCoverage(payload);
1109
+ const exclusion = excludeFeaturePattern ? new RegExp(
1110
+ excludeFeaturePattern.source,
1111
+ excludeFeaturePattern.flags.replace(/[gy]/g, "")
1112
+ ) : void 0;
1113
+ const isOperatorExcluded = (path3) => {
1114
+ if (!exclusion?.test(path3)) {
1115
+ return false;
1116
+ }
1117
+ onFeatureExcluded?.({ path: path3, classification: "operator-excluded" });
1118
+ return true;
1119
+ };
1094
1120
  const signal = payload.signal ?? {};
1095
1121
  const source = {
1096
1122
  signal: {
@@ -1109,6 +1135,9 @@ var collectAiPocketFeatureSnapshot = ({
1109
1135
  segments: [],
1110
1136
  maxDepth: 8,
1111
1137
  shouldSkipPath: (segments) => {
1138
+ if (isOperatorExcluded(segments.join("."))) {
1139
+ return true;
1140
+ }
1112
1141
  const coverageFamily = classifyAiPocketCoverageFeaturePath(segments);
1113
1142
  if (featurePolicy === "causal-stationary" && coverageFamily != null && !isAiPocketCoverageFeatureUsable({
1114
1143
  payload,
@@ -1152,6 +1181,11 @@ var collectAiPocketFeatureSnapshot = ({
1152
1181
  }
1153
1182
  addSignalRiskDistanceFeatures({ features, signal });
1154
1183
  addDirectionalDerivedFeatures(features);
1184
+ for (const key of Object.keys(features)) {
1185
+ if (isOperatorExcluded(key)) {
1186
+ delete features[key];
1187
+ }
1188
+ }
1155
1189
  return { features, featureCoverage };
1156
1190
  };
1157
1191
 
@@ -2475,6 +2509,7 @@ var buildAiPocketMarkdownReport = ({
2475
2509
  ["include_gate_context", run.includeGateContext ? "on" : "off"],
2476
2510
  ["feature_profile", run.featureProfile ?? "all"],
2477
2511
  ["feature_policy", run.featurePolicy ?? "all"],
2512
+ ...run.excludeFeaturePattern ? [["exclude_feature_pattern", run.excludeFeaturePattern]] : [],
2478
2513
  ["coverage_mode", run.coverageMode ?? "full"],
2479
2514
  ["cadence_mode", run.cadenceMode ?? "fixed"],
2480
2515
  ["low_cadence", pocketSearch.stats.cadence.lowCadence ? "yes" : "no"],
@@ -3182,6 +3217,12 @@ var presentAiPocketSearchResult = ({
3182
3217
  ],
3183
3218
  ["feature_profile", import_chalk.default.magenta(featureProfile)],
3184
3219
  ["feature_policy", import_chalk.default.magenta(featurePolicy)],
3220
+ ...run.excludeFeaturePattern ? [
3221
+ [
3222
+ "exclude_feature_pattern",
3223
+ import_chalk.default.magenta(run.excludeFeaturePattern)
3224
+ ]
3225
+ ] : [],
3185
3226
  ["coverage_mode", import_chalk.default.magenta(coverageMode)],
3186
3227
  [
3187
3228
  "allow_risk_regression",
@@ -3729,6 +3770,7 @@ var evaluateAiPocketSearchDataset = async ({
3729
3770
  includeGateContext: options.includeGateContext,
3730
3771
  featureProfile: options.featureProfile,
3731
3772
  featurePolicy: options.featurePolicy,
3773
+ excludeFeaturePattern: options.excludeFeaturePattern,
3732
3774
  onFeatureExcluded: ({ path: featurePath, classification }) => {
3733
3775
  const paths = excludedFeaturePaths.get(classification) ?? /* @__PURE__ */ new Set();
3734
3776
  paths.add(featurePath);
@@ -4302,6 +4344,7 @@ var runAiPocketSearchCommand = async ({
4302
4344
  includeGateContext,
4303
4345
  featureProfile,
4304
4346
  featurePolicy,
4347
+ excludeFeaturePattern,
4305
4348
  coverageMode,
4306
4349
  cadenceMode,
4307
4350
  jsonOutput,
@@ -4378,6 +4421,7 @@ var runAiPocketSearchCommand = async ({
4378
4421
  includeGateContext,
4379
4422
  featureProfile,
4380
4423
  featurePolicy,
4424
+ ...excludeFeaturePattern ? { excludeFeaturePattern: excludeFeaturePattern.source } : {},
4381
4425
  coverageMode,
4382
4426
  cadenceMode,
4383
4427
  coverageSearches: coverageSearches.map(
@@ -4617,6 +4661,11 @@ import_args.default.option(
4617
4661
  "Feature policy: causal-stationary or all",
4618
4662
  "causal-stationary"
4619
4663
  );
4664
+ import_args.default.option(
4665
+ ["x", "excludeFeaturePattern"],
4666
+ "Case-sensitive regular expression excluding feature paths before predicate ranking",
4667
+ ""
4668
+ );
4620
4669
  import_args.default.option(
4621
4670
  ["Q", "coverageMode"],
4622
4671
  "Coverage-aware search mode: auto or full",
@@ -4610,7 +4610,8 @@ var assertCurrentRuntimeEvidenceArtifact = (artifact) => {
4610
4610
  };
4611
4611
  var resolveRuntimeEvidenceTickerUniverse = ({
4612
4612
  deployment,
4613
- lineageScopes
4613
+ lineageScopes,
4614
+ fallbackTickers
4614
4615
  }) => {
4615
4616
  const declaredTickers = deployment.tickers?.filter(isNonEmptyString) ?? [];
4616
4617
  if (declaredTickers.length > 0) {
@@ -4650,6 +4651,15 @@ var resolveRuntimeEvidenceTickerUniverse = ({
4650
4651
  tickers.add(scope.symbol.trim());
4651
4652
  }
4652
4653
  if (tickers.size === 0) {
4654
+ const verifiedFallbackTickers = fallbackTickers?.filter(isNonEmptyString) ?? [];
4655
+ if (verifiedFallbackTickers.length > 0) {
4656
+ return {
4657
+ ...deployment,
4658
+ tickers: [
4659
+ ...new Set(verifiedFallbackTickers.map((ticker) => ticker.trim()))
4660
+ ].sort()
4661
+ };
4662
+ }
4653
4663
  throw new Error(
4654
4664
  "Runtime evidence has no immutable ticker universe for the embedded deployment composition"
4655
4665
  );
@@ -4613,7 +4613,8 @@ var assertCurrentRuntimeEvidenceArtifact = (artifact) => {
4613
4613
  };
4614
4614
  var resolveRuntimeEvidenceTickerUniverse = ({
4615
4615
  deployment,
4616
- lineageScopes
4616
+ lineageScopes,
4617
+ fallbackTickers
4617
4618
  }) => {
4618
4619
  const declaredTickers = deployment.tickers?.filter(isNonEmptyString) ?? [];
4619
4620
  if (declaredTickers.length > 0) {
@@ -4653,6 +4654,15 @@ var resolveRuntimeEvidenceTickerUniverse = ({
4653
4654
  tickers.add(scope.symbol.trim());
4654
4655
  }
4655
4656
  if (tickers.size === 0) {
4657
+ const verifiedFallbackTickers = fallbackTickers?.filter(isNonEmptyString) ?? [];
4658
+ if (verifiedFallbackTickers.length > 0) {
4659
+ return {
4660
+ ...deployment,
4661
+ tickers: [
4662
+ ...new Set(verifiedFallbackTickers.map((ticker) => ticker.trim()))
4663
+ ].sort()
4664
+ };
4665
+ }
4656
4666
  throw new Error(
4657
4667
  "Runtime evidence has no immutable ticker universe for the embedded deployment composition"
4658
4668
  );
@@ -552,7 +552,8 @@ var assertCurrentRuntimeEvidenceArtifact = (artifact) => {
552
552
  };
553
553
  var resolveRuntimeEvidenceTickerUniverse = ({
554
554
  deployment,
555
- lineageScopes
555
+ lineageScopes,
556
+ fallbackTickers
556
557
  }) => {
557
558
  const declaredTickers = deployment.tickers?.filter(isNonEmptyString) ?? [];
558
559
  if (declaredTickers.length > 0) {
@@ -592,6 +593,15 @@ var resolveRuntimeEvidenceTickerUniverse = ({
592
593
  tickers.add(scope.symbol.trim());
593
594
  }
594
595
  if (tickers.size === 0) {
596
+ const verifiedFallbackTickers = fallbackTickers?.filter(isNonEmptyString) ?? [];
597
+ if (verifiedFallbackTickers.length > 0) {
598
+ return {
599
+ ...deployment,
600
+ tickers: [
601
+ ...new Set(verifiedFallbackTickers.map((ticker) => ticker.trim()))
602
+ ].sort()
603
+ };
604
+ }
595
605
  throw new Error(
596
606
  "Runtime evidence has no immutable ticker universe for the embedded deployment composition"
597
607
  );
@@ -1035,7 +1045,7 @@ var loadRuntimeEvidenceCompositionSnapshots = async ({
1035
1045
  for (const snapshot of compositionSnapshots) {
1036
1046
  if (snapshot.deployment.id !== currentDeployment.id) continue;
1037
1047
  register({
1038
- deployment: { ...snapshot.deployment, tickers: void 0 },
1048
+ deployment: snapshot.deployment,
1039
1049
  producer: snapshot.producer
1040
1050
  });
1041
1051
  }
@@ -1049,7 +1059,11 @@ var loadRuntimeEvidenceCompositionSnapshots = async ({
1049
1059
  if (bundle.artifact.producer == null) continue;
1050
1060
  register({
1051
1061
  deployment: { ...deployment, tickers: void 0 },
1052
- producer: parseRuntimeEvidenceProducer(bundle.artifact.producer)
1062
+ producer: parseRuntimeEvidenceProducer(bundle.artifact.producer),
1063
+ // A historical composition may reappear through a position that closes
1064
+ // in this window even without current-window lineage scopes. Its latest
1065
+ // checksum-verified universe is only a fallback; fresh scopes win.
1066
+ ...deployment.tickers?.length ? { fallbackTickers: [...deployment.tickers] } : {}
1053
1067
  });
1054
1068
  }
1055
1069
  const historicalCurrent = snapshots.get(
@@ -1118,7 +1132,7 @@ var splitRuntimeEvidenceByComposition = ({
1118
1132
  `Runtime evidence has no verified deployment snapshot for composition(s): ${missing.sort().join(", ")}`
1119
1133
  );
1120
1134
  }
1121
- return [...observed].filter((compositionId) => snapshots.has(compositionId)).map((compositionId) => snapshots.get(compositionId)).map(({ deployment, producer }) => {
1135
+ return [...observed].filter((compositionId) => snapshots.has(compositionId)).map((compositionId) => snapshots.get(compositionId)).map(({ deployment, producer, fallbackTickers }) => {
1122
1136
  const trades = evidence.trades.filter(
1123
1137
  (row) => belongsToSnapshot(row, deployment)
1124
1138
  );
@@ -1140,6 +1154,7 @@ var splitRuntimeEvidenceByComposition = ({
1140
1154
  return {
1141
1155
  deployment,
1142
1156
  producer,
1157
+ ...fallbackTickers ? { fallbackTickers } : {},
1143
1158
  trades,
1144
1159
  signals,
1145
1160
  evaluations,
@@ -1318,7 +1333,8 @@ var runtimeEvidence = async () => {
1318
1333
  });
1319
1334
  const deployment = resolveRuntimeEvidenceTickerUniverse({
1320
1335
  deployment: composition.deployment,
1321
- lineageScopes: composition.lineageScopes
1336
+ lineageScopes: composition.lineageScopes,
1337
+ fallbackTickers: composition.fallbackTickers
1322
1338
  });
1323
1339
  return {
1324
1340
  artifact: {
@@ -5932,13 +5932,16 @@ var createSignalsRunner = (config2) => {
5932
5932
  const connectorName = await resolveSignalsConnectorName(
5933
5933
  deployment.connectorName
5934
5934
  );
5935
- return new Map(
5936
- buildConfiguredSignalsScopes({
5937
- connectorName,
5938
- deployment,
5939
- strategies: configuredStrategies
5940
- }).map(({ key, scope }) => [key, scope])
5941
- );
5935
+ return {
5936
+ strategies: configuredStrategies,
5937
+ scopes: new Map(
5938
+ buildConfiguredSignalsScopes({
5939
+ connectorName,
5940
+ deployment,
5941
+ strategies: configuredStrategies
5942
+ }).map(({ key, scope }) => [key, scope])
5943
+ )
5944
+ };
5942
5945
  };
5943
5946
  const signalsConfiguredScopesOnce2 = async () => {
5944
5947
  if (config2.updateOnly || config2.showTickersList) {
@@ -5955,7 +5958,7 @@ var createSignalsRunner = (config2) => {
5955
5958
  if (!configuredDeployment) {
5956
5959
  throw new Error(`Runtime deployment not found: ${config2.deploymentId}`);
5957
5960
  }
5958
- const scopes = await loadConfiguredSignalsScopes(configuredDeployment);
5961
+ const { scopes } = await loadConfiguredSignalsScopes(configuredDeployment);
5959
5962
  if (!scopes.size) return signals2();
5960
5963
  for (const scope of scopes.values()) {
5961
5964
  const session = await createSignalsSession2(
@@ -6014,10 +6017,15 @@ var createSignalsRunner = (config2) => {
6014
6017
  if (!currentDeployment) {
6015
6018
  throw new Error(`Runtime deployment not found: ${deploymentId}`);
6016
6019
  }
6020
+ compositionSnapshotRecorder?.observe(
6021
+ currentDeployment.deploymentCompositionId
6022
+ );
6023
+ const { scopes, strategies } = await loadConfiguredSignalsScopes(currentDeployment);
6017
6024
  try {
6018
6025
  await (0, import_runtimeDeploymentEvents.observeRuntimeDeploymentComposition)({
6019
6026
  userName: config2.userName,
6020
- deployment: currentDeployment
6027
+ deployment: currentDeployment,
6028
+ strategies
6021
6029
  });
6022
6030
  } catch (error) {
6023
6031
  import_logger4.logger.warn(
@@ -6026,10 +6034,6 @@ var createSignalsRunner = (config2) => {
6026
6034
  error instanceof Error ? error.message : String(error)
6027
6035
  );
6028
6036
  }
6029
- compositionSnapshotRecorder?.observe(
6030
- currentDeployment.deploymentCompositionId
6031
- );
6032
- const scopes = await loadConfiguredSignalsScopes(currentDeployment);
6033
6037
  for (const [key, staleSession] of sessions) {
6034
6038
  if (scopes.has(key)) continue;
6035
6039
  await staleSession.klineFeed?.close();
@@ -5930,13 +5930,16 @@ var createSignalsRunner = (config2) => {
5930
5930
  const connectorName = await resolveSignalsConnectorName(
5931
5931
  deployment.connectorName
5932
5932
  );
5933
- return new Map(
5934
- buildConfiguredSignalsScopes({
5935
- connectorName,
5936
- deployment,
5937
- strategies: configuredStrategies
5938
- }).map(({ key, scope }) => [key, scope])
5939
- );
5933
+ return {
5934
+ strategies: configuredStrategies,
5935
+ scopes: new Map(
5936
+ buildConfiguredSignalsScopes({
5937
+ connectorName,
5938
+ deployment,
5939
+ strategies: configuredStrategies
5940
+ }).map(({ key, scope }) => [key, scope])
5941
+ )
5942
+ };
5940
5943
  };
5941
5944
  const signalsConfiguredScopesOnce2 = async () => {
5942
5945
  if (config2.updateOnly || config2.showTickersList) {
@@ -5953,7 +5956,7 @@ var createSignalsRunner = (config2) => {
5953
5956
  if (!configuredDeployment) {
5954
5957
  throw new Error(`Runtime deployment not found: ${config2.deploymentId}`);
5955
5958
  }
5956
- const scopes = await loadConfiguredSignalsScopes(configuredDeployment);
5959
+ const { scopes } = await loadConfiguredSignalsScopes(configuredDeployment);
5957
5960
  if (!scopes.size) return signals2();
5958
5961
  for (const scope of scopes.values()) {
5959
5962
  const session = await createSignalsSession2(
@@ -6012,10 +6015,15 @@ var createSignalsRunner = (config2) => {
6012
6015
  if (!currentDeployment) {
6013
6016
  throw new Error(`Runtime deployment not found: ${deploymentId}`);
6014
6017
  }
6018
+ compositionSnapshotRecorder?.observe(
6019
+ currentDeployment.deploymentCompositionId
6020
+ );
6021
+ const { scopes, strategies } = await loadConfiguredSignalsScopes(currentDeployment);
6015
6022
  try {
6016
6023
  await (0, import_runtimeDeploymentEvents.observeRuntimeDeploymentComposition)({
6017
6024
  userName: config2.userName,
6018
- deployment: currentDeployment
6025
+ deployment: currentDeployment,
6026
+ strategies
6019
6027
  });
6020
6028
  } catch (error) {
6021
6029
  import_logger4.logger.warn(
@@ -6024,10 +6032,6 @@ var createSignalsRunner = (config2) => {
6024
6032
  error instanceof Error ? error.message : String(error)
6025
6033
  );
6026
6034
  }
6027
- compositionSnapshotRecorder?.observe(
6028
- currentDeployment.deploymentCompositionId
6029
- );
6030
- const scopes = await loadConfiguredSignalsScopes(currentDeployment);
6031
6035
  for (const [key, staleSession] of sessions) {
6032
6036
  if (scopes.has(key)) continue;
6033
6037
  await staleSession.klineFeed?.close();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tradejs/cli",
3
- "version": "3.1.28-beta.254",
3
+ "version": "3.1.28-beta.256",
4
4
  "description": "Official CLI for the TradeJS TypeScript framework: infra setup, backtests, signals, bots, and ML workflows.",
5
5
  "keywords": [
6
6
  "tradejs",
@@ -36,13 +36,13 @@
36
36
  "tradejs": "dist/cli.js"
37
37
  },
38
38
  "dependencies": {
39
- "@tradejs/connectors": "^3.1.28-beta.254",
40
- "@tradejs/core": "^3.1.28-beta.254",
41
- "@tradejs/indicators": "^3.1.28-beta.254",
42
- "@tradejs/infra": "^3.1.28-beta.254",
43
- "@tradejs/node": "^3.1.28-beta.254",
39
+ "@tradejs/connectors": "^3.1.28-beta.256",
40
+ "@tradejs/core": "^3.1.28-beta.256",
41
+ "@tradejs/indicators": "^3.1.28-beta.256",
42
+ "@tradejs/infra": "^3.1.28-beta.256",
43
+ "@tradejs/node": "^3.1.28-beta.256",
44
44
  "@tradejs/strategy-kit": "3.0.5",
45
- "@tradejs/types": "^3.1.28-beta.254",
45
+ "@tradejs/types": "^3.1.28-beta.256",
46
46
  "args": "^5.0.3",
47
47
  "bcryptjs": "^2.4.3",
48
48
  "chalk": "4.1.2",