@tradejs/cli 2.0.20 → 2.0.21

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
@@ -24654,7 +24654,7 @@ var init_runtimeEvidenceArtifacts = __esm({
24654
24654
  });
24655
24655
 
24656
24656
  // src/lib/runtimeLineage.ts
24657
- var import_node_child_process6, import_node_crypto11, import_promises22, import_node_path16, import_types8, import_strategies11, RUNTIME_CONTEXT_ENV_KEYS, RUNTIME_CONTEXT_DATA_MODEL, normalizeForStableJson2, normalizeRuntimeLogicConfig, resolveRuntimeMaxLossValue, fingerprintRuntimeValue, gitLineageCache, gateFingerprintCache, binanceBreadthFingerprintCache, snapshotFingerprintCache, resolveGitLineage, readOptionalFile, resolveBinanceBreadthFingerprint, resolveSnapshotFingerprint, resolveRuntimeGateFingerprint, buildRuntimeLineage, runtimeLineageKey, runtimeLineagesMatch;
24657
+ var import_node_child_process6, import_node_crypto11, import_promises22, import_node_path16, import_types8, import_strategies11, import_strategyReleaseEvidence2, RUNTIME_CONTEXT_ENV_KEYS, RUNTIME_CONTEXT_DATA_MODEL, normalizeForStableJson2, resolveRuntimeMaxLossValue, fingerprintRuntimeValue, gitLineageCache, gateFingerprintCache, binanceBreadthFingerprintCache, snapshotFingerprintCache, resolveGitLineage, readOptionalFile, resolveBinanceBreadthFingerprint, resolveSnapshotFingerprint, resolveRuntimeGateFingerprint, buildRuntimeLineage, runtimeLineageKey, runtimeLineagesMatch;
24658
24658
  var init_runtimeLineage = __esm({
24659
24659
  "src/lib/runtimeLineage.ts"() {
24660
24660
  "use strict";
@@ -24664,6 +24664,7 @@ var init_runtimeLineage = __esm({
24664
24664
  import_node_path16 = __toESM(require("path"));
24665
24665
  import_types8 = require("@tradejs/types");
24666
24666
  import_strategies11 = require("@tradejs/node/strategies");
24667
+ import_strategyReleaseEvidence2 = require("@tradejs/infra/strategyReleaseEvidence");
24667
24668
  init_strategyGateFingerprint();
24668
24669
  RUNTIME_CONTEXT_ENV_KEYS = [
24669
24670
  "AI_MODE",
@@ -24714,17 +24715,6 @@ var init_runtimeLineage = __esm({
24714
24715
  }
24715
24716
  return value;
24716
24717
  };
24717
- normalizeRuntimeLogicConfig = (value) => {
24718
- if (Array.isArray(value)) {
24719
- return value.map(normalizeRuntimeLogicConfig);
24720
- }
24721
- if (value && typeof value === "object") {
24722
- return Object.fromEntries(
24723
- Object.entries(value).filter(([key]) => key !== "MAX_LOSS_VALUE").sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => [key, normalizeRuntimeLogicConfig(entry)])
24724
- );
24725
- }
24726
- return value;
24727
- };
24728
24718
  resolveRuntimeMaxLossValue = (config2) => {
24729
24719
  if (!config2 || typeof config2 !== "object" || Array.isArray(config2)) {
24730
24720
  return null;
@@ -24888,9 +24878,7 @@ var init_runtimeLineage = __esm({
24888
24878
  })).gateFingerprint,
24889
24879
  // Position risk is tracked separately so changing trade size does not
24890
24880
  // masquerade as a change to the core + gate decision logic.
24891
- configFingerprint: fingerprintRuntimeValue(
24892
- normalizeRuntimeLogicConfig(config2)
24893
- ),
24881
+ configFingerprint: (0, import_strategyReleaseEvidence2.strategyLogicConfigFingerprint)(config2),
24894
24882
  contextFingerprint: fingerprintRuntimeValue(context),
24895
24883
  maxLossValue: resolveRuntimeMaxLossValue(config2)
24896
24884
  };
@@ -25880,7 +25868,7 @@ function assert2(condition, message) {
25880
25868
  async function collectReleaseEvidenceReferences(references) {
25881
25869
  return Promise.all(
25882
25870
  references.map(async (reference) => {
25883
- const actualSha256 = await (0, import_strategyReleaseEvidence2.strategyEvidenceFileSha256)(reference.path);
25871
+ const actualSha256 = await (0, import_strategyReleaseEvidence3.strategyEvidenceFileSha256)(reference.path);
25884
25872
  assert2(
25885
25873
  actualSha256 === reference.sha256,
25886
25874
  `evidence ${reference.artifactId} checksum mismatch`
@@ -26018,7 +26006,7 @@ async function collectReleaseEvidenceReferences(references) {
26018
26006
  })
26019
26007
  );
26020
26008
  }
26021
- var import_node_crypto12, import_promises25, import_node_path20, import_types9, import_strategyReleaseEvidence2, SHA256_RE2, LINEAGE_FINGERPRINT_RE, DAY_MS12, REQUIRED_LONG_WINDOWS, REQUIRED_STABLE_TERMINAL_WINDOWS, MIN_RECENT_DIRECTION_REPAIR_TRADES, safeSegment3, compactTimestamp2, verifyFullPeriodChartArtifact, hasExactRuntimeTarget, deriveStrategyReleaseResearchDecision, canonicalStrategyReleaseJson, strategyReleaseSha256, assertFingerprint, assertLineageFingerprint, releaseReasons, deriveReleaseGates, verifyEvidenceComposition, createStrategyReleaseManifest, createStrategyReleaseEnvelope, verifyStrategyReleaseEnvelope, verifyStrategyEvidenceMarkerEnvelope, releaseMarkers, writeJsonAtomic2, publishStrategyRelease, buildStrategyLiveDiagnosis, buildStrategyLiveDiagnosisFromScorecard, realizedDrawdown, lowerBoundExitTimestamp, percentile2, buildStrategyMonitoringProfile, publishStrategyLiveDiagnosis, planStrategyEvidenceRetention, finiteString3, finiteNumber6, uniqueStrings, incompleteEvidenceLineage, extractEvidenceLineage, verifyCompletedCoreResearchBundle;
26009
+ var import_node_crypto12, import_promises25, import_node_path20, import_types9, import_strategyReleaseEvidence3, SHA256_RE2, LINEAGE_FINGERPRINT_RE, DAY_MS12, REQUIRED_LONG_WINDOWS, REQUIRED_STABLE_TERMINAL_WINDOWS, MIN_RECENT_DIRECTION_REPAIR_TRADES, safeSegment3, compactTimestamp2, verifyFullPeriodChartArtifact, hasExactRuntimeTarget, deriveStrategyReleaseResearchDecision, canonicalStrategyReleaseJson, strategyReleaseSha256, assertFingerprint, assertLineageFingerprint, releaseReasons, deriveReleaseGates, verifyEvidenceComposition, createStrategyReleaseManifest, createStrategyReleaseEnvelope, verifyStrategyReleaseEnvelope, verifyStrategyEvidenceMarkerEnvelope, releaseMarkers, writeJsonAtomic2, publishStrategyRelease, buildStrategyLiveDiagnosis, buildStrategyLiveDiagnosisFromScorecard, realizedDrawdown, lowerBoundExitTimestamp, percentile2, buildStrategyMonitoringProfile, publishStrategyLiveDiagnosis, planStrategyEvidenceRetention, finiteString3, finiteNumber6, uniqueStrings, incompleteEvidenceLineage, extractEvidenceLineage, verifyCompletedCoreResearchBundle;
26022
26010
  var init_strategyRelease = __esm({
26023
26011
  "src/lib/strategyRelease.ts"() {
26024
26012
  "use strict";
@@ -26026,21 +26014,21 @@ var init_strategyRelease = __esm({
26026
26014
  import_promises25 = __toESM(require("fs/promises"));
26027
26015
  import_node_path20 = __toESM(require("path"));
26028
26016
  import_types9 = require("@tradejs/types");
26029
- import_strategyReleaseEvidence2 = require("@tradejs/infra/strategyReleaseEvidence");
26017
+ import_strategyReleaseEvidence3 = require("@tradejs/infra/strategyReleaseEvidence");
26030
26018
  SHA256_RE2 = /^[a-f0-9]{64}$/;
26031
26019
  LINEAGE_FINGERPRINT_RE = /^[a-f0-9]{16}$/;
26032
26020
  DAY_MS12 = 864e5;
26033
26021
  REQUIRED_LONG_WINDOWS = [1095, 1460, 1825];
26034
26022
  REQUIRED_STABLE_TERMINAL_WINDOWS = [365, 180, 90];
26035
26023
  MIN_RECENT_DIRECTION_REPAIR_TRADES = 20;
26036
- safeSegment3 = import_strategyReleaseEvidence2.safeStrategyEvidenceSegment;
26037
- compactTimestamp2 = import_strategyReleaseEvidence2.compactStrategyEvidenceTimestamp;
26024
+ safeSegment3 = import_strategyReleaseEvidence3.safeStrategyEvidenceSegment;
26025
+ compactTimestamp2 = import_strategyReleaseEvidence3.compactStrategyEvidenceTimestamp;
26038
26026
  verifyFullPeriodChartArtifact = async (input) => {
26039
26027
  const artifact = input.chartArtifact;
26040
26028
  if (!artifact?.path || !SHA256_RE2.test(artifact.sha256)) return false;
26041
26029
  try {
26042
26030
  const artifactPath = import_node_path20.default.resolve(artifact.path);
26043
- if (await (0, import_strategyReleaseEvidence2.strategyEvidenceFileSha256)(artifactPath) !== artifact.sha256) {
26031
+ if (await (0, import_strategyReleaseEvidence3.strategyEvidenceFileSha256)(artifactPath) !== artifact.sha256) {
26044
26032
  return false;
26045
26033
  }
26046
26034
  const report = JSON.parse(await import_promises25.default.readFile(artifactPath, "utf8"));
@@ -26088,6 +26076,7 @@ var init_strategyRelease = __esm({
26088
26076
  repairAllowed: false,
26089
26077
  targetDirection: input.recentFailure?.direction ?? null,
26090
26078
  maxLossValue: null,
26079
+ requiresRuntimeBinding: false,
26091
26080
  blockers,
26092
26081
  summary: "The final composition does not have complete positive ALL/LONG/SHORT evidence on the frozen 3y/4y/max-window matrix."
26093
26082
  };
@@ -26102,6 +26091,7 @@ var init_strategyRelease = __esm({
26102
26091
  repairAllowed: true,
26103
26092
  targetDirection: input.recentFailure.direction,
26104
26093
  maxLossValue: null,
26094
+ requiresRuntimeBinding: false,
26105
26095
  blockers: [],
26106
26096
  summary: "Spend the single terminal-direction repair round on the preregistered causal mechanism, then rebuild the full evidence matrix."
26107
26097
  };
@@ -26120,6 +26110,7 @@ var init_strategyRelease = __esm({
26120
26110
  repairAllowed: false,
26121
26111
  targetDirection: input.recentFailure?.direction ?? null,
26122
26112
  maxLossValue: null,
26113
+ requiresRuntimeBinding: false,
26123
26114
  blockers,
26124
26115
  summary: "Complete the frozen candidate implementation and full-period chart before any micro-forward execution."
26125
26116
  };
@@ -26131,6 +26122,9 @@ var init_strategyRelease = __esm({
26131
26122
  repairAllowed: false,
26132
26123
  targetDirection: input.recentFailure?.direction ?? null,
26133
26124
  maxLossValue: 1,
26125
+ requiresRuntimeBinding: !hasExactRuntimeTarget(
26126
+ input.forwardTest.runtimeTarget
26127
+ ),
26134
26128
  blockers: ["FORWARD_NOT_AUTHORIZED"],
26135
26129
  summary: "The candidate is ready for a separately authorized micro-forward test at MAX_LOSS_VALUE=1."
26136
26130
  };
@@ -26138,12 +26132,13 @@ var init_strategyRelease = __esm({
26138
26132
  if (!hasExactRuntimeTarget(input.forwardTest.runtimeTarget)) {
26139
26133
  return {
26140
26134
  strategy: input.strategy,
26141
- action: "FORWARD_BLOCKED",
26135
+ action: "MICRO_FORWARD_READY",
26142
26136
  repairAllowed: false,
26143
26137
  targetDirection: input.recentFailure?.direction ?? null,
26144
26138
  maxLossValue: 1,
26145
- blockers: ["RUNTIME_TARGET_UNRESOLVED"],
26146
- summary: "Forward testing is authorized, but an exact runtime deployment/account target must be resolved first."
26139
+ requiresRuntimeBinding: true,
26140
+ blockers: [],
26141
+ summary: "The portable micro-forward handoff is ready. Bind it on the runtime server to that server's deployment/account ids and verify canonical composition fingerprints there."
26147
26142
  };
26148
26143
  }
26149
26144
  return {
@@ -26152,12 +26147,13 @@ var init_strategyRelease = __esm({
26152
26147
  repairAllowed: false,
26153
26148
  targetDirection: input.recentFailure?.direction ?? null,
26154
26149
  maxLossValue: 1,
26150
+ requiresRuntimeBinding: false,
26155
26151
  blockers: [],
26156
26152
  summary: "Start the exact frozen composition as a micro-forward test at MAX_LOSS_VALUE=1; do not retune an underpowered or exposed recent tail."
26157
26153
  };
26158
26154
  };
26159
- canonicalStrategyReleaseJson = (value) => (0, import_strategyReleaseEvidence2.canonicalStrategyEvidenceJson)(value);
26160
- strategyReleaseSha256 = (value) => (0, import_strategyReleaseEvidence2.strategyEvidenceSha256)(value);
26155
+ canonicalStrategyReleaseJson = (value) => (0, import_strategyReleaseEvidence3.canonicalStrategyEvidenceJson)(value);
26156
+ strategyReleaseSha256 = (value) => (0, import_strategyReleaseEvidence3.strategyEvidenceSha256)(value);
26161
26157
  assertFingerprint = (value, label) => assert2(SHA256_RE2.test(value), `${label} must be a lowercase SHA-256`);
26162
26158
  assertLineageFingerprint = (value, label) => assert2(
26163
26159
  LINEAGE_FINGERPRINT_RE.test(value),
@@ -26567,7 +26563,7 @@ var init_strategyRelease = __esm({
26567
26563
  };
26568
26564
  verifyStrategyEvidenceMarkerEnvelope = async (valueOrPath) => {
26569
26565
  const value = typeof valueOrPath === "string" ? JSON.parse(await import_promises25.default.readFile(valueOrPath, "utf8")) : valueOrPath;
26570
- return (0, import_strategyReleaseEvidence2.verifyStrategyEvidenceMarkerEnvelope)(value);
26566
+ return (0, import_strategyReleaseEvidence3.verifyStrategyEvidenceMarkerEnvelope)(value);
26571
26567
  };
26572
26568
  releaseMarkers = (manifest) => {
26573
26569
  const common = {
@@ -26642,7 +26638,7 @@ var init_strategyRelease = __esm({
26642
26638
  manifest
26643
26639
  }) => {
26644
26640
  const envelope = createStrategyReleaseEnvelope(manifest);
26645
- const markerEnvelope = (0, import_strategyReleaseEvidence2.createStrategyEvidenceMarkerEnvelope)({
26641
+ const markerEnvelope = (0, import_strategyReleaseEvidence3.createStrategyEvidenceMarkerEnvelope)({
26646
26642
  strategy: manifest.strategy,
26647
26643
  createdAt: manifest.createdAt,
26648
26644
  markers: releaseMarkers(manifest),
@@ -26917,7 +26913,7 @@ var init_strategyRelease = __esm({
26917
26913
  severity: diagnosis.verdict === "EXPECTED_DRAWDOWN" ? "info" : "warning"
26918
26914
  }
26919
26915
  ];
26920
- const markerEnvelope = (0, import_strategyReleaseEvidence2.createStrategyEvidenceMarkerEnvelope)({
26916
+ const markerEnvelope = (0, import_strategyReleaseEvidence3.createStrategyEvidenceMarkerEnvelope)({
26921
26917
  strategy: diagnosis.strategy,
26922
26918
  createdAt: diagnosis.createdAt,
26923
26919
  markers,
@@ -27167,7 +27163,7 @@ var init_strategyRelease = __esm({
27167
27163
  typeof expectedSha256 === "string" && SHA256_RE2.test(expectedSha256),
27168
27164
  `core bundle artifact ${relativePath} has an invalid checksum`
27169
27165
  );
27170
- const actualSha256 = await (0, import_strategyReleaseEvidence2.strategyEvidenceFileSha256)(
27166
+ const actualSha256 = await (0, import_strategyReleaseEvidence3.strategyEvidenceFileSha256)(
27171
27167
  import_node_path20.default.join(researchDir, relativePath)
27172
27168
  );
27173
27169
  assert2(
@@ -43,6 +43,7 @@ var import_promises2 = __toESM(require("fs/promises"));
43
43
  var import_node_path2 = __toESM(require("path"));
44
44
  var import_types = require("@tradejs/types");
45
45
  var import_strategies = require("@tradejs/node/strategies");
46
+ var import_strategyReleaseEvidence = require("@tradejs/infra/strategyReleaseEvidence");
46
47
 
47
48
  // src/lib/strategyGateFingerprint.ts
48
49
  var import_node_crypto = require("crypto");
@@ -137,17 +138,6 @@ var normalizeForStableJson = (value) => {
137
138
  }
138
139
  return value;
139
140
  };
140
- var normalizeRuntimeLogicConfig = (value) => {
141
- if (Array.isArray(value)) {
142
- return value.map(normalizeRuntimeLogicConfig);
143
- }
144
- if (value && typeof value === "object") {
145
- return Object.fromEntries(
146
- Object.entries(value).filter(([key]) => key !== "MAX_LOSS_VALUE").sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => [key, normalizeRuntimeLogicConfig(entry)])
147
- );
148
- }
149
- return value;
150
- };
151
141
  var resolveRuntimeMaxLossValue = (config) => {
152
142
  if (!config || typeof config !== "object" || Array.isArray(config)) {
153
143
  return null;
@@ -311,9 +301,7 @@ var buildRuntimeLineage = async ({
311
301
  })).gateFingerprint,
312
302
  // Position risk is tracked separately so changing trade size does not
313
303
  // masquerade as a change to the core + gate decision logic.
314
- configFingerprint: fingerprintRuntimeValue(
315
- normalizeRuntimeLogicConfig(config)
316
- ),
304
+ configFingerprint: (0, import_strategyReleaseEvidence.strategyLogicConfigFingerprint)(config),
317
305
  contextFingerprint: fingerprintRuntimeValue(context),
318
306
  maxLossValue: resolveRuntimeMaxLossValue(config)
319
307
  };
@@ -113,6 +113,7 @@ var deriveStrategyReleaseResearchDecision = async (input) => {
113
113
  repairAllowed: false,
114
114
  targetDirection: input.recentFailure?.direction ?? null,
115
115
  maxLossValue: null,
116
+ requiresRuntimeBinding: false,
116
117
  blockers,
117
118
  summary: "The final composition does not have complete positive ALL/LONG/SHORT evidence on the frozen 3y/4y/max-window matrix."
118
119
  };
@@ -127,6 +128,7 @@ var deriveStrategyReleaseResearchDecision = async (input) => {
127
128
  repairAllowed: true,
128
129
  targetDirection: input.recentFailure.direction,
129
130
  maxLossValue: null,
131
+ requiresRuntimeBinding: false,
130
132
  blockers: [],
131
133
  summary: "Spend the single terminal-direction repair round on the preregistered causal mechanism, then rebuild the full evidence matrix."
132
134
  };
@@ -145,6 +147,7 @@ var deriveStrategyReleaseResearchDecision = async (input) => {
145
147
  repairAllowed: false,
146
148
  targetDirection: input.recentFailure?.direction ?? null,
147
149
  maxLossValue: null,
150
+ requiresRuntimeBinding: false,
148
151
  blockers,
149
152
  summary: "Complete the frozen candidate implementation and full-period chart before any micro-forward execution."
150
153
  };
@@ -156,6 +159,9 @@ var deriveStrategyReleaseResearchDecision = async (input) => {
156
159
  repairAllowed: false,
157
160
  targetDirection: input.recentFailure?.direction ?? null,
158
161
  maxLossValue: 1,
162
+ requiresRuntimeBinding: !hasExactRuntimeTarget(
163
+ input.forwardTest.runtimeTarget
164
+ ),
159
165
  blockers: ["FORWARD_NOT_AUTHORIZED"],
160
166
  summary: "The candidate is ready for a separately authorized micro-forward test at MAX_LOSS_VALUE=1."
161
167
  };
@@ -163,12 +169,13 @@ var deriveStrategyReleaseResearchDecision = async (input) => {
163
169
  if (!hasExactRuntimeTarget(input.forwardTest.runtimeTarget)) {
164
170
  return {
165
171
  strategy: input.strategy,
166
- action: "FORWARD_BLOCKED",
172
+ action: "MICRO_FORWARD_READY",
167
173
  repairAllowed: false,
168
174
  targetDirection: input.recentFailure?.direction ?? null,
169
175
  maxLossValue: 1,
170
- blockers: ["RUNTIME_TARGET_UNRESOLVED"],
171
- summary: "Forward testing is authorized, but an exact runtime deployment/account target must be resolved first."
176
+ requiresRuntimeBinding: true,
177
+ blockers: [],
178
+ summary: "The portable micro-forward handoff is ready. Bind it on the runtime server to that server's deployment/account ids and verify canonical composition fingerprints there."
172
179
  };
173
180
  }
174
181
  return {
@@ -177,6 +184,7 @@ var deriveStrategyReleaseResearchDecision = async (input) => {
177
184
  repairAllowed: false,
178
185
  targetDirection: input.recentFailure?.direction ?? null,
179
186
  maxLossValue: 1,
187
+ requiresRuntimeBinding: false,
180
188
  blockers: [],
181
189
  summary: "Start the exact frozen composition as a micro-forward test at MAX_LOSS_VALUE=1; do not retune an underpowered or exposed recent tail."
182
190
  };
@@ -4906,6 +4906,7 @@ var import_promises2 = __toESM(require("fs/promises"));
4906
4906
  var import_node_path2 = __toESM(require("path"));
4907
4907
  var import_types2 = require("@tradejs/types");
4908
4908
  var import_strategies3 = require("@tradejs/node/strategies");
4909
+ var import_strategyReleaseEvidence = require("@tradejs/infra/strategyReleaseEvidence");
4909
4910
 
4910
4911
  // src/lib/strategyGateFingerprint.ts
4911
4912
  var import_node_crypto = require("crypto");
@@ -5000,17 +5001,6 @@ var normalizeForStableJson = (value) => {
5000
5001
  }
5001
5002
  return value;
5002
5003
  };
5003
- var normalizeRuntimeLogicConfig = (value) => {
5004
- if (Array.isArray(value)) {
5005
- return value.map(normalizeRuntimeLogicConfig);
5006
- }
5007
- if (value && typeof value === "object") {
5008
- return Object.fromEntries(
5009
- Object.entries(value).filter(([key]) => key !== "MAX_LOSS_VALUE").sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => [key, normalizeRuntimeLogicConfig(entry)])
5010
- );
5011
- }
5012
- return value;
5013
- };
5014
5004
  var resolveRuntimeMaxLossValue = (config) => {
5015
5005
  if (!config || typeof config !== "object" || Array.isArray(config)) {
5016
5006
  return null;
@@ -5174,9 +5164,7 @@ var buildRuntimeLineage = async ({
5174
5164
  })).gateFingerprint,
5175
5165
  // Position risk is tracked separately so changing trade size does not
5176
5166
  // masquerade as a change to the core + gate decision logic.
5177
- configFingerprint: fingerprintRuntimeValue(
5178
- normalizeRuntimeLogicConfig(config)
5179
- ),
5167
+ configFingerprint: (0, import_strategyReleaseEvidence.strategyLogicConfigFingerprint)(config),
5180
5168
  contextFingerprint: fingerprintRuntimeValue(context),
5181
5169
  maxLossValue: resolveRuntimeMaxLossValue(config)
5182
5170
  };
@@ -4909,6 +4909,7 @@ var import_promises2 = __toESM(require("fs/promises"));
4909
4909
  var import_node_path2 = __toESM(require("path"));
4910
4910
  var import_types2 = require("@tradejs/types");
4911
4911
  var import_strategies3 = require("@tradejs/node/strategies");
4912
+ var import_strategyReleaseEvidence = require("@tradejs/infra/strategyReleaseEvidence");
4912
4913
 
4913
4914
  // src/lib/strategyGateFingerprint.ts
4914
4915
  var import_node_crypto = require("crypto");
@@ -5003,17 +5004,6 @@ var normalizeForStableJson = (value) => {
5003
5004
  }
5004
5005
  return value;
5005
5006
  };
5006
- var normalizeRuntimeLogicConfig = (value) => {
5007
- if (Array.isArray(value)) {
5008
- return value.map(normalizeRuntimeLogicConfig);
5009
- }
5010
- if (value && typeof value === "object") {
5011
- return Object.fromEntries(
5012
- Object.entries(value).filter(([key]) => key !== "MAX_LOSS_VALUE").sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => [key, normalizeRuntimeLogicConfig(entry)])
5013
- );
5014
- }
5015
- return value;
5016
- };
5017
5007
  var resolveRuntimeMaxLossValue = (config) => {
5018
5008
  if (!config || typeof config !== "object" || Array.isArray(config)) {
5019
5009
  return null;
@@ -5177,9 +5167,7 @@ var buildRuntimeLineage = async ({
5177
5167
  })).gateFingerprint,
5178
5168
  // Position risk is tracked separately so changing trade size does not
5179
5169
  // masquerade as a change to the core + gate decision logic.
5180
- configFingerprint: fingerprintRuntimeValue(
5181
- normalizeRuntimeLogicConfig(config)
5182
- ),
5170
+ configFingerprint: (0, import_strategyReleaseEvidence.strategyLogicConfigFingerprint)(config),
5183
5171
  contextFingerprint: fingerprintRuntimeValue(context),
5184
5172
  maxLossValue: resolveRuntimeMaxLossValue(config)
5185
5173
  };
@@ -564,6 +564,7 @@ var import_promises3 = __toESM(require("fs/promises"));
564
564
  var import_node_path3 = __toESM(require("path"));
565
565
  var import_types = require("@tradejs/types");
566
566
  var import_strategies = require("@tradejs/node/strategies");
567
+ var import_strategyReleaseEvidence = require("@tradejs/infra/strategyReleaseEvidence");
567
568
 
568
569
  // src/lib/strategyGateFingerprint.ts
569
570
  var import_node_crypto2 = require("crypto");
@@ -4003,6 +4003,7 @@ var import_promises2 = __toESM(require("fs/promises"));
4003
4003
  var import_node_path2 = __toESM(require("path"));
4004
4004
  var import_types = require("@tradejs/types");
4005
4005
  var import_strategies4 = require("@tradejs/node/strategies");
4006
+ var import_strategyReleaseEvidence = require("@tradejs/infra/strategyReleaseEvidence");
4006
4007
 
4007
4008
  // src/lib/strategyGateFingerprint.ts
4008
4009
  var import_node_crypto = require("crypto");
@@ -4097,17 +4098,6 @@ var normalizeForStableJson = (value) => {
4097
4098
  }
4098
4099
  return value;
4099
4100
  };
4100
- var normalizeRuntimeLogicConfig = (value) => {
4101
- if (Array.isArray(value)) {
4102
- return value.map(normalizeRuntimeLogicConfig);
4103
- }
4104
- if (value && typeof value === "object") {
4105
- return Object.fromEntries(
4106
- Object.entries(value).filter(([key]) => key !== "MAX_LOSS_VALUE").sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => [key, normalizeRuntimeLogicConfig(entry)])
4107
- );
4108
- }
4109
- return value;
4110
- };
4111
4101
  var resolveRuntimeMaxLossValue = (config2) => {
4112
4102
  if (!config2 || typeof config2 !== "object" || Array.isArray(config2)) {
4113
4103
  return null;
@@ -4271,9 +4261,7 @@ var buildRuntimeLineage = async ({
4271
4261
  })).gateFingerprint,
4272
4262
  // Position risk is tracked separately so changing trade size does not
4273
4263
  // masquerade as a change to the core + gate decision logic.
4274
- configFingerprint: fingerprintRuntimeValue(
4275
- normalizeRuntimeLogicConfig(config2)
4276
- ),
4264
+ configFingerprint: (0, import_strategyReleaseEvidence.strategyLogicConfigFingerprint)(config2),
4277
4265
  contextFingerprint: fingerprintRuntimeValue(context),
4278
4266
  maxLossValue: resolveRuntimeMaxLossValue(config2)
4279
4267
  };
@@ -4001,6 +4001,7 @@ var import_promises2 = __toESM(require("fs/promises"));
4001
4001
  var import_node_path2 = __toESM(require("path"));
4002
4002
  var import_types = require("@tradejs/types");
4003
4003
  var import_strategies4 = require("@tradejs/node/strategies");
4004
+ var import_strategyReleaseEvidence = require("@tradejs/infra/strategyReleaseEvidence");
4004
4005
 
4005
4006
  // src/lib/strategyGateFingerprint.ts
4006
4007
  var import_node_crypto = require("crypto");
@@ -4095,17 +4096,6 @@ var normalizeForStableJson = (value) => {
4095
4096
  }
4096
4097
  return value;
4097
4098
  };
4098
- var normalizeRuntimeLogicConfig = (value) => {
4099
- if (Array.isArray(value)) {
4100
- return value.map(normalizeRuntimeLogicConfig);
4101
- }
4102
- if (value && typeof value === "object") {
4103
- return Object.fromEntries(
4104
- Object.entries(value).filter(([key]) => key !== "MAX_LOSS_VALUE").sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => [key, normalizeRuntimeLogicConfig(entry)])
4105
- );
4106
- }
4107
- return value;
4108
- };
4109
4099
  var resolveRuntimeMaxLossValue = (config2) => {
4110
4100
  if (!config2 || typeof config2 !== "object" || Array.isArray(config2)) {
4111
4101
  return null;
@@ -4269,9 +4259,7 @@ var buildRuntimeLineage = async ({
4269
4259
  })).gateFingerprint,
4270
4260
  // Position risk is tracked separately so changing trade size does not
4271
4261
  // masquerade as a change to the core + gate decision logic.
4272
- configFingerprint: fingerprintRuntimeValue(
4273
- normalizeRuntimeLogicConfig(config2)
4274
- ),
4262
+ configFingerprint: (0, import_strategyReleaseEvidence.strategyLogicConfigFingerprint)(config2),
4275
4263
  contextFingerprint: fingerprintRuntimeValue(context),
4276
4264
  maxLossValue: resolveRuntimeMaxLossValue(config2)
4277
4265
  };
@@ -107,6 +107,7 @@ var deriveStrategyReleaseResearchDecision = async (input) => {
107
107
  repairAllowed: false,
108
108
  targetDirection: input.recentFailure?.direction ?? null,
109
109
  maxLossValue: null,
110
+ requiresRuntimeBinding: false,
110
111
  blockers,
111
112
  summary: "The final composition does not have complete positive ALL/LONG/SHORT evidence on the frozen 3y/4y/max-window matrix."
112
113
  };
@@ -121,6 +122,7 @@ var deriveStrategyReleaseResearchDecision = async (input) => {
121
122
  repairAllowed: true,
122
123
  targetDirection: input.recentFailure.direction,
123
124
  maxLossValue: null,
125
+ requiresRuntimeBinding: false,
124
126
  blockers: [],
125
127
  summary: "Spend the single terminal-direction repair round on the preregistered causal mechanism, then rebuild the full evidence matrix."
126
128
  };
@@ -139,6 +141,7 @@ var deriveStrategyReleaseResearchDecision = async (input) => {
139
141
  repairAllowed: false,
140
142
  targetDirection: input.recentFailure?.direction ?? null,
141
143
  maxLossValue: null,
144
+ requiresRuntimeBinding: false,
142
145
  blockers,
143
146
  summary: "Complete the frozen candidate implementation and full-period chart before any micro-forward execution."
144
147
  };
@@ -150,6 +153,9 @@ var deriveStrategyReleaseResearchDecision = async (input) => {
150
153
  repairAllowed: false,
151
154
  targetDirection: input.recentFailure?.direction ?? null,
152
155
  maxLossValue: 1,
156
+ requiresRuntimeBinding: !hasExactRuntimeTarget(
157
+ input.forwardTest.runtimeTarget
158
+ ),
153
159
  blockers: ["FORWARD_NOT_AUTHORIZED"],
154
160
  summary: "The candidate is ready for a separately authorized micro-forward test at MAX_LOSS_VALUE=1."
155
161
  };
@@ -157,12 +163,13 @@ var deriveStrategyReleaseResearchDecision = async (input) => {
157
163
  if (!hasExactRuntimeTarget(input.forwardTest.runtimeTarget)) {
158
164
  return {
159
165
  strategy: input.strategy,
160
- action: "FORWARD_BLOCKED",
166
+ action: "MICRO_FORWARD_READY",
161
167
  repairAllowed: false,
162
168
  targetDirection: input.recentFailure?.direction ?? null,
163
169
  maxLossValue: 1,
164
- blockers: ["RUNTIME_TARGET_UNRESOLVED"],
165
- summary: "Forward testing is authorized, but an exact runtime deployment/account target must be resolved first."
170
+ requiresRuntimeBinding: true,
171
+ blockers: [],
172
+ summary: "The portable micro-forward handoff is ready. Bind it on the runtime server to that server's deployment/account ids and verify canonical composition fingerprints there."
166
173
  };
167
174
  }
168
175
  return {
@@ -171,6 +178,7 @@ var deriveStrategyReleaseResearchDecision = async (input) => {
171
178
  repairAllowed: false,
172
179
  targetDirection: input.recentFailure?.direction ?? null,
173
180
  maxLossValue: 1,
181
+ requiresRuntimeBinding: false,
174
182
  blockers: [],
175
183
  summary: "Start the exact frozen composition as a micro-forward test at MAX_LOSS_VALUE=1; do not retune an underpowered or exposed recent tail."
176
184
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tradejs/cli",
3
- "version": "2.0.20",
3
+ "version": "2.0.21",
4
4
  "description": "Official CLI for the TradeJS TypeScript framework: infra setup, backtests, signals, bots, and ML workflows.",
5
5
  "keywords": [
6
6
  "tradejs",
@@ -29,14 +29,14 @@
29
29
  "tradejs": "dist/cli.js"
30
30
  },
31
31
  "dependencies": {
32
- "@tradejs/base": "^2.0.20",
33
- "@tradejs/connectors": "^2.0.20",
34
- "@tradejs/core": "^2.0.20",
35
- "@tradejs/indicators": "^2.0.20",
36
- "@tradejs/infra": "^2.0.20",
37
- "@tradejs/node": "^2.0.20",
38
- "@tradejs/strategies": "^2.0.20",
39
- "@tradejs/types": "^2.0.20",
32
+ "@tradejs/base": "^2.0.21",
33
+ "@tradejs/connectors": "^2.0.21",
34
+ "@tradejs/core": "^2.0.21",
35
+ "@tradejs/indicators": "^2.0.21",
36
+ "@tradejs/infra": "^2.0.21",
37
+ "@tradejs/node": "^2.0.21",
38
+ "@tradejs/strategies": "^2.0.21",
39
+ "@tradejs/types": "^2.0.21",
40
40
  "args": "^5.0.3",
41
41
  "bcryptjs": "^2.4.3",
42
42
  "chalk": "4.1.2",