@tradejs/cli 3.1.11 → 3.1.12-beta.218

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.
@@ -523,17 +523,21 @@ var loadDeploymentReplayStrategies = async ({
523
523
  const strategies = deployment.enabled ? runtimeStrategies.filter((strategy) => strategy.enabled).map(
524
524
  ({
525
525
  strategyName,
526
- version,
526
+ strategyRevision,
527
+ deploymentCompositionId,
527
528
  strategyPackage,
528
529
  strategyPackageVersion,
530
+ strategyDependencyVersions,
529
531
  runtimePackageVersion,
530
532
  sourceStrategyConfig,
531
533
  selection
532
534
  }) => ({
533
535
  strategyName,
534
- version,
536
+ strategyRevision,
537
+ deploymentCompositionId,
535
538
  strategyPackage,
536
539
  strategyPackageVersion,
540
+ strategyDependencyVersions,
537
541
  runtimePackageVersion,
538
542
  strategyConfig: sourceStrategyConfig,
539
543
  ...selection ? { selection } : {}
@@ -29,6 +29,9 @@ module.exports = __toCommonJS(runtimeEvidenceDeployment_exports);
29
29
  var import_runtimeStrategies = require("@tradejs/node/runtimeStrategies");
30
30
  var isRecord = (value) => value != null && typeof value === "object" && !Array.isArray(value);
31
31
  var isNonEmptyString = (value) => typeof value === "string" && value.trim().length > 0;
32
+ var isPackageVersionMap = (value) => isRecord(value) && Object.keys(value).length > 0 && Object.entries(value).every(
33
+ ([name, version]) => name.startsWith("@tradejs/") && isNonEmptyString(version)
34
+ );
32
35
  var INTERVALS = /* @__PURE__ */ new Set([
33
36
  "1",
34
37
  "3",
@@ -47,13 +50,13 @@ var INTERVALS = /* @__PURE__ */ new Set([
47
50
  var UNIVERSES = /* @__PURE__ */ new Set(["crypto", "tradfi"]);
48
51
  var isRuntimeStrategySelection = (value) => value === void 0 || isRecord(value) && Object.keys(value).length === 1 && Object.keys(value).every((key) => key === "tickers") && Array.isArray(value.tickers) && value.tickers.length > 0 && value.tickers.every((ticker) => isNonEmptyString(ticker));
49
52
  var parseRuntimeEvidenceDeploymentSnapshot = (value) => {
50
- if (!isRecord(value) || value.schemaVersion !== 1 || !isNonEmptyString(value.id) || !isNonEmptyString(value.label) || !isNonEmptyString(value.connectorName) || !isNonEmptyString(value.provider) || !isNonEmptyString(value.accountId) || typeof value.enabled !== "boolean" || !Array.isArray(value.strategies)) {
53
+ if (!isRecord(value) || value.schemaVersion !== 2 || !isNonEmptyString(value.id) || !isNonEmptyString(value.deploymentCompositionId) || !/^dc1:[a-f0-9]{16}$/.test(value.deploymentCompositionId) || !isNonEmptyString(value.label) || !isNonEmptyString(value.connectorName) || !isNonEmptyString(value.provider) || !isNonEmptyString(value.accountId) || typeof value.enabled !== "boolean" || !Array.isArray(value.strategies)) {
51
54
  throw new Error(
52
55
  "Runtime evidence deployment snapshot is missing or invalid"
53
56
  );
54
57
  }
55
58
  const strategies = value.strategies.map((candidate) => {
56
- if (!isRecord(candidate) || !isNonEmptyString(candidate.strategyName) || !Number.isSafeInteger(candidate.version) || Number(candidate.version) <= 0 || typeof candidate.enabled !== "boolean" || !["active", "entries_paused"].includes(String(candidate.controlState)) || !INTERVALS.has(String(candidate.interval)) || !UNIVERSES.has(String(candidate.universe)) || !isNonEmptyString(candidate.strategyPackage) || !isNonEmptyString(candidate.strategyPackageVersion) || !isNonEmptyString(candidate.runtimePackageVersion) || !isRecord(candidate.strategyConfig) || !isRuntimeStrategySelection(candidate.selection)) {
59
+ if (!isRecord(candidate) || !isNonEmptyString(candidate.strategyName) || !isNonEmptyString(candidate.strategyRevision) || !/^sr1:[a-f0-9]{16}$/.test(candidate.strategyRevision) || typeof candidate.enabled !== "boolean" || !["active", "entries_paused"].includes(String(candidate.controlState)) || !INTERVALS.has(String(candidate.interval)) || !UNIVERSES.has(String(candidate.universe)) || !isNonEmptyString(candidate.strategyPackage) || !isNonEmptyString(candidate.strategyPackageVersion) || !isPackageVersionMap(candidate.strategyDependencyVersions) || !isNonEmptyString(candidate.runtimePackageVersion) || !isRecord(candidate.strategyConfig) || !isRuntimeStrategySelection(candidate.selection)) {
57
60
  throw new Error(
58
61
  "Runtime evidence deployment strategy snapshot is invalid"
59
62
  );
@@ -87,15 +90,16 @@ var parseRuntimeEvidenceDeploymentSnapshot = (value) => {
87
90
  var activeRuntimeEvidenceStrategies = (deployment) => deployment.enabled ? deployment.strategies.filter((strategy) => strategy.enabled) : [];
88
91
  var runtimeDeploymentFromEvidence = (deployment) => ({
89
92
  id: deployment.id,
93
+ deploymentCompositionId: deployment.deploymentCompositionId,
90
94
  label: deployment.label,
91
95
  connectorName: deployment.connectorName,
92
96
  provider: deployment.provider,
93
97
  accountId: deployment.accountId,
94
98
  enabled: deployment.enabled,
95
99
  strategies: deployment.strategies.map(
96
- ({ strategyName, version, enabled, controlState, selection }) => ({
100
+ ({ strategyName, strategyRevision, enabled, controlState, selection }) => ({
97
101
  strategyName,
98
- version,
102
+ strategyRevision,
99
103
  enabled,
100
104
  controlState,
101
105
  ...selection ? { selection } : {}
@@ -117,8 +121,9 @@ var resolveRuntimeEvidenceDeploymentSnapshot = async ({
117
121
  throw new Error(`Runtime deployment not found: ${deploymentId}`);
118
122
  }
119
123
  return {
120
- schemaVersion: 1,
124
+ schemaVersion: 2,
121
125
  id: deployment.id,
126
+ deploymentCompositionId: deployment.deploymentCompositionId,
122
127
  label: deployment.label,
123
128
  connectorName: deployment.connectorName,
124
129
  provider: deployment.provider,
@@ -127,7 +132,7 @@ var resolveRuntimeEvidenceDeploymentSnapshot = async ({
127
132
  strategies: strategies.map(
128
133
  ({
129
134
  strategyName,
130
- version,
135
+ strategyRevision,
131
136
  enabled,
132
137
  controlState,
133
138
  interval,
@@ -135,12 +140,13 @@ var resolveRuntimeEvidenceDeploymentSnapshot = async ({
135
140
  accountId,
136
141
  strategyPackage,
137
142
  strategyPackageVersion,
143
+ strategyDependencyVersions,
138
144
  runtimePackageVersion,
139
- sourceStrategyConfig,
145
+ strategyConfig,
140
146
  selection
141
147
  }) => ({
142
148
  strategyName,
143
- version,
149
+ strategyRevision,
144
150
  enabled,
145
151
  controlState,
146
152
  interval,
@@ -148,8 +154,9 @@ var resolveRuntimeEvidenceDeploymentSnapshot = async ({
148
154
  ...accountId ? { accountId } : {},
149
155
  strategyPackage,
150
156
  strategyPackageVersion,
157
+ strategyDependencyVersions,
151
158
  runtimePackageVersion,
152
- strategyConfig: sourceStrategyConfig,
159
+ strategyConfig,
153
160
  ...selection ? { selection } : {}
154
161
  })
155
162
  ),
@@ -277,21 +277,38 @@ async function buildRuntimeLineage({
277
277
  projectRoot,
278
278
  strategyName,
279
279
  compositionId,
280
- version,
280
+ strategyRevision,
281
+ deploymentCompositionId,
281
282
  strategyPackageVersion,
283
+ strategyDependencyVersions,
282
284
  runtimePackageVersion,
283
285
  config,
284
286
  runContext,
285
287
  env = process.env
286
288
  }) {
287
- if (version != null) {
288
- if (!Number.isSafeInteger(version) || version <= 0) {
289
- throw new Error(`Invalid runtime strategy version: ${version}`);
289
+ if (strategyRevision != null) {
290
+ if (!/^sr1:[a-f0-9]{16}$/.test(strategyRevision)) {
291
+ throw new Error(`Invalid strategy revision: ${strategyRevision}`);
292
+ }
293
+ if (typeof deploymentCompositionId !== "string" || !/^dc1:[a-f0-9]{16}$/.test(deploymentCompositionId)) {
294
+ throw new Error(
295
+ `Invalid deployment composition id: ${String(deploymentCompositionId)}`
296
+ );
297
+ }
298
+ if (typeof strategyPackageVersion !== "string" || !strategyPackageVersion.trim() || typeof runtimePackageVersion !== "string" || !runtimePackageVersion.trim()) {
299
+ throw new Error("Invalid revision package versions");
300
+ }
301
+ if (!strategyDependencyVersions || Object.keys(strategyDependencyVersions).length === 0 || Object.entries(strategyDependencyVersions).some(
302
+ ([name, version]) => !name.startsWith("@tradejs/") || typeof version !== "string" || !version.trim()
303
+ )) {
304
+ throw new Error("Invalid strategy dependency versions");
290
305
  }
291
306
  return {
292
- schemaVersion: 2,
293
- version,
307
+ schemaVersion: 3,
308
+ strategyRevision,
309
+ deploymentCompositionId,
294
310
  strategyPackageVersion,
311
+ strategyDependencyVersions,
295
312
  runtimePackageVersion,
296
313
  maxLossValue: resolveRuntimeMaxLossValue(config)
297
314
  };
@@ -331,11 +348,15 @@ async function buildRuntimeLineage({
331
348
  maxLossValue: resolveRuntimeMaxLossValue(config)
332
349
  };
333
350
  }
334
- var runtimeLineageKey = (lineage) => lineage.schemaVersion === 2 ? [
335
- "v2",
336
- lineage.version,
337
- lineage.strategyPackageVersion ?? "strategy:unknown",
338
- lineage.runtimePackageVersion ?? "runtime:unknown"
351
+ var runtimeLineageKey = (lineage) => lineage.schemaVersion === 3 ? [
352
+ "v3",
353
+ lineage.deploymentCompositionId,
354
+ lineage.strategyRevision,
355
+ lineage.strategyPackageVersion,
356
+ `deps:${fingerprintRuntimeValue(
357
+ lineage.strategyDependencyVersions
358
+ ).slice(0, 16)}`,
359
+ lineage.runtimePackageVersion
339
360
  ].join(":") : [
340
361
  lineage.schemaVersion,
341
362
  lineage.compositionId ?? "unbound-composition",
@@ -51,11 +51,27 @@ var import_promises = __toESM(require("fs/promises"));
51
51
  var import_node_path = __toESM(require("path"));
52
52
 
53
53
  // src/lib/runtimeLineage.ts
54
- var runtimeLineageKey = (lineage) => lineage.schemaVersion === 2 ? [
55
- "v2",
56
- lineage.version,
57
- lineage.strategyPackageVersion ?? "strategy:unknown",
58
- lineage.runtimePackageVersion ?? "runtime:unknown"
54
+ var normalizeForStableJson = (value) => {
55
+ if (Array.isArray(value)) {
56
+ return value.map(normalizeForStableJson);
57
+ }
58
+ if (value && typeof value === "object") {
59
+ return Object.fromEntries(
60
+ Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => [key, normalizeForStableJson(entry)])
61
+ );
62
+ }
63
+ return value;
64
+ };
65
+ var fingerprintRuntimeValue = (value) => (0, import_node_crypto2.createHash)("sha256").update(JSON.stringify(normalizeForStableJson(value))).digest("hex").slice(0, 16);
66
+ var runtimeLineageKey = (lineage) => lineage.schemaVersion === 3 ? [
67
+ "v3",
68
+ lineage.deploymentCompositionId,
69
+ lineage.strategyRevision,
70
+ lineage.strategyPackageVersion,
71
+ `deps:${fingerprintRuntimeValue(
72
+ lineage.strategyDependencyVersions
73
+ ).slice(0, 16)}`,
74
+ lineage.runtimePackageVersion
59
75
  ].join(":") : [
60
76
  lineage.schemaVersion,
61
77
  lineage.compositionId ?? "unbound-composition",
@@ -71,6 +87,19 @@ var asRecord = (value) => value && typeof value === "object" && !Array.isArray(v
71
87
  var asArray = (value) => Array.isArray(value) ? value : [];
72
88
  var finiteNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
73
89
  var finiteString = (value) => typeof value === "string" && value.trim() ? value.trim() : null;
90
+ var packageVersionMap = (value) => {
91
+ const record = asRecord(value);
92
+ if (!record || Object.keys(record).length === 0) return null;
93
+ const entries = Object.entries(record);
94
+ if (entries.some(
95
+ ([name, version]) => !name.startsWith("@tradejs/") || finiteString(version) == null
96
+ )) {
97
+ return null;
98
+ }
99
+ return Object.fromEntries(
100
+ entries.map(([name, version]) => [name, String(version).trim()]).sort(([left], [right]) => left.localeCompare(right))
101
+ );
102
+ };
74
103
  var round = (value, decimals = 6) => Number(value.toFixed(decimals));
75
104
  var unwrapRows = (value, key) => asArray(value).map((item) => asRecord(asRecord(item)?.[key]) ?? asRecord(item)).filter((item) => item != null);
76
105
  var runtimePayload = (artifact) => {
@@ -103,12 +132,18 @@ var buildRuntimeLineageSummary = (rows) => {
103
132
  const lineages = lineageRows.map((row) => asRecord(row.runtimeLineage)).filter((lineage) => lineage != null);
104
133
  const identities = /* @__PURE__ */ new Map();
105
134
  for (const lineage of lineages) {
106
- const identity2 = lineage.schemaVersion === 2 ? {
107
- schemaVersion: 2,
108
- version: finiteNumber(lineage.version),
135
+ const identity2 = lineage.schemaVersion === 3 ? {
136
+ schemaVersion: 3,
137
+ strategyRevision: finiteString(lineage.strategyRevision),
138
+ deploymentCompositionId: finiteString(
139
+ lineage.deploymentCompositionId
140
+ ),
109
141
  strategyPackageVersion: finiteString(
110
142
  lineage.strategyPackageVersion
111
143
  ),
144
+ strategyDependencyVersions: packageVersionMap(
145
+ lineage.strategyDependencyVersions
146
+ ),
112
147
  runtimePackageVersion: finiteString(lineage.runtimePackageVersion),
113
148
  maxLossValue: finiteNumber(lineage.maxLossValue)
114
149
  } : {
@@ -125,7 +160,7 @@ var buildRuntimeLineageSummary = (rows) => {
125
160
  }
126
161
  const identity = identities.size === 1 ? [...identities.values()][0] : null;
127
162
  const schemaVersion = finiteNumber(identity?.schemaVersion);
128
- const identityComplete = lineages.length > 0 && identity != null && (schemaVersion === 2 && finiteNumber(identity.version) != null && finiteString(identity.strategyPackageVersion) != null && finiteString(identity.runtimePackageVersion) != null || schemaVersion === 1 && identity.compositionId != null && identity.gitSha != null && identity.gitDirty === false && identity.gateFingerprint != null && identity.configFingerprint != null && identity.contextFingerprint != null) && identity.maxLossValue != null;
163
+ const identityComplete = lineages.length > 0 && identity != null && (schemaVersion === 3 && finiteString(identity.strategyRevision) != null && finiteString(identity.deploymentCompositionId) != null && finiteString(identity.strategyPackageVersion) != null && packageVersionMap(identity.strategyDependencyVersions) != null && finiteString(identity.runtimePackageVersion) != null || schemaVersion === 1 && identity.compositionId != null && identity.gitSha != null && identity.gitDirty === false && identity.gateFingerprint != null && identity.configFingerprint != null && identity.contextFingerprint != null) && identity.maxLossValue != null;
129
164
  const coverageComplete = lineageRows.length > 0 && lineages.length === lineageRows.length;
130
165
  const complete = identityComplete && coverageComplete;
131
166
  const lineageKey = identityComplete ? runtimeLineageKey(identity) : null;
@@ -138,8 +173,12 @@ var buildRuntimeLineageSummary = (rows) => {
138
173
  rowsWithLineage: lineages.length,
139
174
  schemaVersion,
140
175
  lineageKey,
141
- version: finiteNumber(identity?.version),
176
+ strategyRevision: finiteString(identity?.strategyRevision),
177
+ deploymentCompositionId: finiteString(identity?.deploymentCompositionId),
142
178
  strategyPackageVersion: finiteString(identity?.strategyPackageVersion),
179
+ strategyDependencyVersions: packageVersionMap(
180
+ identity?.strategyDependencyVersions
181
+ ),
143
182
  runtimePackageVersion: finiteString(identity?.runtimePackageVersion),
144
183
  compositionId: finiteString(identity?.compositionId),
145
184
  gitSha: finiteString(identity?.gitSha),
@@ -64,7 +64,7 @@ var toRuntimeSignalBucketRef = (signal) => ({
64
64
  strategy: signal.strategy,
65
65
  timestamp: signal.timestamp,
66
66
  ...signal.runtimeConfigId && signal.runtimeConfigId !== "config" ? { runtimeConfigId: signal.runtimeConfigId } : {},
67
- ...signal.runtimeVersion ? { runtimeVersion: signal.runtimeVersion } : {}
67
+ ...signal.strategyRevision ? { strategyRevision: signal.strategyRevision } : {}
68
68
  });
69
69
  var shouldStoreRuntimeSignalDiagnostics = (signal) => signal.orderStatus === "completed" || signal.orderStatus === "failed";
70
70
  var toStoredRuntimeSignal = (signal) => {
@@ -279,6 +279,8 @@ var planStrategyEvidenceRetention = ({
279
279
  // src/lib/strategyRelease.ts
280
280
  var SHA256_RE = /^[a-f0-9]{64}$/;
281
281
  var LINEAGE_FINGERPRINT_RE = /^[a-f0-9]{16}$/;
282
+ var STRATEGY_REVISION_RE = /^sr1:[a-f0-9]{16}$/;
283
+ var DEPLOYMENT_COMPOSITION_ID_RE = /^dc1:[a-f0-9]{16}$/;
282
284
  var REQUIRED_LONG_WINDOWS = [1095, 1460, 1825];
283
285
  var REQUIRED_STABLE_TERMINAL_WINDOWS = [365, 180, 90];
284
286
  var MIN_RECENT_DIRECTION_REPAIR_TRADES = 20;
@@ -301,7 +303,7 @@ var verifyFullPeriodChartArtifact = async (input) => {
301
303
  }
302
304
  };
303
305
  var hasExactRuntimeTarget = (target, strategyName) => Boolean(
304
- target?.userName.trim() && target.deploymentId.trim() && target.accountId.trim() && target.strategyName.trim() === strategyName.trim() && Number.isSafeInteger(target.version) && target.version > 0
306
+ target?.userName.trim() && target.deploymentId.trim() && target.accountId.trim() && target.strategyName.trim() === strategyName.trim() && STRATEGY_REVISION_RE.test(target.strategyRevision) && DEPLOYMENT_COMPOSITION_ID_RE.test(target.deploymentCompositionId)
305
307
  );
306
308
  var deriveStrategyReleaseResearchDecision = async (input) => {
307
309
  const blockers = [];
@@ -402,7 +404,7 @@ var deriveStrategyReleaseResearchDecision = async (input) => {
402
404
  maxLossValue: 1,
403
405
  requiresRuntimeBinding: true,
404
406
  blockers: [],
405
- summary: "The portable micro-forward handoff is ready. Commit its deployment, account binding, complete config, and explicit strategy version in TradeJS-Project."
407
+ summary: "The portable micro-forward handoff is ready. Commit its deployment, account binding, and complete config in TradeJS-Project; runtime revisions are computed from the installed packages and parsed config."
406
408
  };
407
409
  }
408
410
  return {
@@ -526,17 +526,21 @@ var loadDeploymentReplayStrategies = async ({
526
526
  const strategies = deployment.enabled ? runtimeStrategies.filter((strategy) => strategy.enabled).map(
527
527
  ({
528
528
  strategyName,
529
- version,
529
+ strategyRevision,
530
+ deploymentCompositionId,
530
531
  strategyPackage,
531
532
  strategyPackageVersion,
533
+ strategyDependencyVersions,
532
534
  runtimePackageVersion,
533
535
  sourceStrategyConfig,
534
536
  selection
535
537
  }) => ({
536
538
  strategyName,
537
- version,
539
+ strategyRevision,
540
+ deploymentCompositionId,
538
541
  strategyPackage,
539
542
  strategyPackageVersion,
543
+ strategyDependencyVersions,
540
544
  runtimePackageVersion,
541
545
  strategyConfig: sourceStrategyConfig,
542
546
  ...selection ? { selection } : {}
@@ -4586,21 +4590,38 @@ async function buildRuntimeLineage({
4586
4590
  projectRoot,
4587
4591
  strategyName,
4588
4592
  compositionId,
4589
- version,
4593
+ strategyRevision,
4594
+ deploymentCompositionId,
4590
4595
  strategyPackageVersion,
4596
+ strategyDependencyVersions,
4591
4597
  runtimePackageVersion,
4592
4598
  config,
4593
4599
  runContext,
4594
4600
  env = process.env
4595
4601
  }) {
4596
- if (version != null) {
4597
- if (!Number.isSafeInteger(version) || version <= 0) {
4598
- throw new Error(`Invalid runtime strategy version: ${version}`);
4602
+ if (strategyRevision != null) {
4603
+ if (!/^sr1:[a-f0-9]{16}$/.test(strategyRevision)) {
4604
+ throw new Error(`Invalid strategy revision: ${strategyRevision}`);
4605
+ }
4606
+ if (typeof deploymentCompositionId !== "string" || !/^dc1:[a-f0-9]{16}$/.test(deploymentCompositionId)) {
4607
+ throw new Error(
4608
+ `Invalid deployment composition id: ${String(deploymentCompositionId)}`
4609
+ );
4610
+ }
4611
+ if (typeof strategyPackageVersion !== "string" || !strategyPackageVersion.trim() || typeof runtimePackageVersion !== "string" || !runtimePackageVersion.trim()) {
4612
+ throw new Error("Invalid revision package versions");
4613
+ }
4614
+ if (!strategyDependencyVersions || Object.keys(strategyDependencyVersions).length === 0 || Object.entries(strategyDependencyVersions).some(
4615
+ ([name, version]) => !name.startsWith("@tradejs/") || typeof version !== "string" || !version.trim()
4616
+ )) {
4617
+ throw new Error("Invalid strategy dependency versions");
4599
4618
  }
4600
4619
  return {
4601
- schemaVersion: 2,
4602
- version,
4620
+ schemaVersion: 3,
4621
+ strategyRevision,
4622
+ deploymentCompositionId,
4603
4623
  strategyPackageVersion,
4624
+ strategyDependencyVersions,
4604
4625
  runtimePackageVersion,
4605
4626
  maxLossValue: resolveRuntimeMaxLossValue(config)
4606
4627
  };
@@ -4640,11 +4661,15 @@ async function buildRuntimeLineage({
4640
4661
  maxLossValue: resolveRuntimeMaxLossValue(config)
4641
4662
  };
4642
4663
  }
4643
- var runtimeLineageKey = (lineage) => lineage.schemaVersion === 2 ? [
4644
- "v2",
4645
- lineage.version,
4646
- lineage.strategyPackageVersion ?? "strategy:unknown",
4647
- lineage.runtimePackageVersion ?? "runtime:unknown"
4664
+ var runtimeLineageKey = (lineage) => lineage.schemaVersion === 3 ? [
4665
+ "v3",
4666
+ lineage.deploymentCompositionId,
4667
+ lineage.strategyRevision,
4668
+ lineage.strategyPackageVersion,
4669
+ `deps:${fingerprintRuntimeValue(
4670
+ lineage.strategyDependencyVersions
4671
+ ).slice(0, 16)}`,
4672
+ lineage.runtimePackageVersion
4648
4673
  ].join(":") : [
4649
4674
  lineage.schemaVersion,
4650
4675
  lineage.compositionId ?? "unbound-composition",
@@ -4661,6 +4686,9 @@ var runtimeLineagesComparable = (left, right) => runtimeLineagesMatch(left, righ
4661
4686
  var import_runtimeStrategies2 = require("@tradejs/node/runtimeStrategies");
4662
4687
  var isRecord = (value) => value != null && typeof value === "object" && !Array.isArray(value);
4663
4688
  var isNonEmptyString = (value) => typeof value === "string" && value.trim().length > 0;
4689
+ var isPackageVersionMap = (value) => isRecord(value) && Object.keys(value).length > 0 && Object.entries(value).every(
4690
+ ([name, version]) => name.startsWith("@tradejs/") && isNonEmptyString(version)
4691
+ );
4664
4692
  var INTERVALS = /* @__PURE__ */ new Set([
4665
4693
  "1",
4666
4694
  "3",
@@ -4679,13 +4707,13 @@ var INTERVALS = /* @__PURE__ */ new Set([
4679
4707
  var UNIVERSES = /* @__PURE__ */ new Set(["crypto", "tradfi"]);
4680
4708
  var isRuntimeStrategySelection = (value) => value === void 0 || isRecord(value) && Object.keys(value).length === 1 && Object.keys(value).every((key) => key === "tickers") && Array.isArray(value.tickers) && value.tickers.length > 0 && value.tickers.every((ticker) => isNonEmptyString(ticker));
4681
4709
  var parseRuntimeEvidenceDeploymentSnapshot = (value) => {
4682
- if (!isRecord(value) || value.schemaVersion !== 1 || !isNonEmptyString(value.id) || !isNonEmptyString(value.label) || !isNonEmptyString(value.connectorName) || !isNonEmptyString(value.provider) || !isNonEmptyString(value.accountId) || typeof value.enabled !== "boolean" || !Array.isArray(value.strategies)) {
4710
+ if (!isRecord(value) || value.schemaVersion !== 2 || !isNonEmptyString(value.id) || !isNonEmptyString(value.deploymentCompositionId) || !/^dc1:[a-f0-9]{16}$/.test(value.deploymentCompositionId) || !isNonEmptyString(value.label) || !isNonEmptyString(value.connectorName) || !isNonEmptyString(value.provider) || !isNonEmptyString(value.accountId) || typeof value.enabled !== "boolean" || !Array.isArray(value.strategies)) {
4683
4711
  throw new Error(
4684
4712
  "Runtime evidence deployment snapshot is missing or invalid"
4685
4713
  );
4686
4714
  }
4687
4715
  const strategies = value.strategies.map((candidate) => {
4688
- if (!isRecord(candidate) || !isNonEmptyString(candidate.strategyName) || !Number.isSafeInteger(candidate.version) || Number(candidate.version) <= 0 || typeof candidate.enabled !== "boolean" || !["active", "entries_paused"].includes(String(candidate.controlState)) || !INTERVALS.has(String(candidate.interval)) || !UNIVERSES.has(String(candidate.universe)) || !isNonEmptyString(candidate.strategyPackage) || !isNonEmptyString(candidate.strategyPackageVersion) || !isNonEmptyString(candidate.runtimePackageVersion) || !isRecord(candidate.strategyConfig) || !isRuntimeStrategySelection(candidate.selection)) {
4716
+ if (!isRecord(candidate) || !isNonEmptyString(candidate.strategyName) || !isNonEmptyString(candidate.strategyRevision) || !/^sr1:[a-f0-9]{16}$/.test(candidate.strategyRevision) || typeof candidate.enabled !== "boolean" || !["active", "entries_paused"].includes(String(candidate.controlState)) || !INTERVALS.has(String(candidate.interval)) || !UNIVERSES.has(String(candidate.universe)) || !isNonEmptyString(candidate.strategyPackage) || !isNonEmptyString(candidate.strategyPackageVersion) || !isPackageVersionMap(candidate.strategyDependencyVersions) || !isNonEmptyString(candidate.runtimePackageVersion) || !isRecord(candidate.strategyConfig) || !isRuntimeStrategySelection(candidate.selection)) {
4689
4717
  throw new Error(
4690
4718
  "Runtime evidence deployment strategy snapshot is invalid"
4691
4719
  );
@@ -4719,15 +4747,16 @@ var parseRuntimeEvidenceDeploymentSnapshot = (value) => {
4719
4747
  var activeRuntimeEvidenceStrategies = (deployment) => deployment.enabled ? deployment.strategies.filter((strategy) => strategy.enabled) : [];
4720
4748
  var runtimeDeploymentFromEvidence = (deployment) => ({
4721
4749
  id: deployment.id,
4750
+ deploymentCompositionId: deployment.deploymentCompositionId,
4722
4751
  label: deployment.label,
4723
4752
  connectorName: deployment.connectorName,
4724
4753
  provider: deployment.provider,
4725
4754
  accountId: deployment.accountId,
4726
4755
  enabled: deployment.enabled,
4727
4756
  strategies: deployment.strategies.map(
4728
- ({ strategyName, version, enabled, controlState, selection }) => ({
4757
+ ({ strategyName, strategyRevision, enabled, controlState, selection }) => ({
4729
4758
  strategyName,
4730
- version,
4759
+ strategyRevision,
4731
4760
  enabled,
4732
4761
  controlState,
4733
4762
  ...selection ? { selection } : {}
@@ -4807,7 +4836,7 @@ var buildRuntimeEvidenceLineageScopes = ({
4807
4836
  deploymentId,
4808
4837
  accountId,
4809
4838
  runtimeConfigId,
4810
- runtimeVersion,
4839
+ strategyRevision,
4811
4840
  timestamp,
4812
4841
  lineage
4813
4842
  }) => {
@@ -4822,7 +4851,7 @@ var buildRuntimeEvidenceLineageScopes = ({
4822
4851
  ...deploymentId ? { deploymentId } : {},
4823
4852
  ...accountId ? { accountId } : {},
4824
4853
  ...runtimeConfigId ? { runtimeConfigId } : {},
4825
- ...runtimeVersion ? { runtimeVersion } : {},
4854
+ ...strategyRevision ? { strategyRevision } : {},
4826
4855
  lineage,
4827
4856
  firstTimestamp: existing ? Math.min(existing.firstTimestamp, timestamp) : timestamp,
4828
4857
  lastTimestamp: existing ? Math.max(existing.lastTimestamp, timestamp) : timestamp
@@ -4835,7 +4864,7 @@ var buildRuntimeEvidenceLineageScopes = ({
4835
4864
  deploymentId: signal.deploymentId,
4836
4865
  accountId: signal.accountId,
4837
4866
  runtimeConfigId: signal.runtimeConfigId,
4838
- runtimeVersion: signal.runtimeVersion,
4867
+ strategyRevision: signal.strategyRevision,
4839
4868
  timestamp: signal.timestamp,
4840
4869
  lineage: signal.runtimeLineage
4841
4870
  });
@@ -4847,7 +4876,7 @@ var buildRuntimeEvidenceLineageScopes = ({
4847
4876
  deploymentId: evaluation.deploymentId,
4848
4877
  accountId: evaluation.accountId,
4849
4878
  runtimeConfigId: evaluation.runtimeConfigId,
4850
- runtimeVersion: evaluation.runtimeVersion,
4879
+ strategyRevision: evaluation.strategyRevision,
4851
4880
  timestamp: evaluation.timestamp,
4852
4881
  lineage: evaluation.runtimeLineage
4853
4882
  });
@@ -5491,9 +5520,11 @@ var loadRuntimeStrategies = async (runtimeStrategies) => {
5491
5520
  runtimeStrategies.map(async (runtimeStrategy) => {
5492
5521
  const {
5493
5522
  strategyName,
5494
- version,
5523
+ strategyRevision,
5524
+ deploymentCompositionId,
5495
5525
  strategyPackage,
5496
5526
  strategyPackageVersion,
5527
+ strategyDependencyVersions,
5497
5528
  runtimePackageVersion,
5498
5529
  strategyConfig,
5499
5530
  selection
@@ -5509,7 +5540,7 @@ var loadRuntimeStrategies = async (runtimeStrategies) => {
5509
5540
  strategyName,
5510
5541
  projectRoot: replayProjectRoot
5511
5542
  });
5512
- if (installed.strategyPackage !== strategyPackage || installed.strategyPackageVersion !== strategyPackageVersion || installed.runtimePackageVersion !== runtimePackageVersion) {
5543
+ if (installed.strategyPackage !== strategyPackage || installed.strategyPackageVersion !== strategyPackageVersion || JSON.stringify(installed.strategyDependencyVersions) !== JSON.stringify(strategyDependencyVersions) || installed.runtimePackageVersion !== runtimePackageVersion) {
5513
5544
  throw new Error(
5514
5545
  `Runtime evidence package mismatch for ${strategyName}: expected=${strategyPackage}@${strategyPackageVersion}/@tradejs/node@${runtimePackageVersion}, installed=${installed.strategyPackage ?? "missing"}@${installed.strategyPackageVersion ?? "missing"}/@tradejs/node@${installed.runtimePackageVersion ?? "missing"}`
5515
5546
  );
@@ -5520,9 +5551,11 @@ var loadRuntimeStrategies = async (runtimeStrategies) => {
5520
5551
  );
5521
5552
  return {
5522
5553
  strategyName,
5523
- version,
5554
+ strategyRevision,
5555
+ deploymentCompositionId,
5524
5556
  strategyPackage,
5525
5557
  strategyPackageVersion,
5558
+ strategyDependencyVersions,
5526
5559
  runtimePackageVersion,
5527
5560
  strategyCreator,
5528
5561
  strategyConfig,
@@ -5726,8 +5759,10 @@ var runHistoricalSignalsReplay = async ({
5726
5759
  loadedStrategies.filter((strategy) => strategyIncludesSymbol(strategy, symbol)).map(
5727
5760
  async ({
5728
5761
  strategyName,
5729
- version,
5762
+ strategyRevision,
5763
+ deploymentCompositionId,
5730
5764
  strategyPackageVersion,
5765
+ strategyDependencyVersions,
5731
5766
  runtimePackageVersion,
5732
5767
  strategyCreator,
5733
5768
  strategyConfig,
@@ -5736,11 +5771,13 @@ var runHistoricalSignalsReplay = async ({
5736
5771
  const runtimeLineage = await buildRuntimeLineage({
5737
5772
  projectRoot: replayProjectRoot,
5738
5773
  strategyName,
5739
- version,
5774
+ strategyRevision,
5775
+ deploymentCompositionId,
5740
5776
  strategyPackageVersion,
5777
+ strategyDependencyVersions,
5741
5778
  runtimePackageVersion,
5742
5779
  config: {
5743
- configId: `v${version}`,
5780
+ configId: strategyRevision,
5744
5781
  strategyConfig,
5745
5782
  symbolResultConfig: strategyResults?.[symbol]?.config ?? null
5746
5783
  },
@@ -5764,7 +5801,8 @@ var runHistoricalSignalsReplay = async ({
5764
5801
  run: await strategyCreator({
5765
5802
  userName: replayUserName,
5766
5803
  connectorName,
5767
- runtimeConfigId: `v${version}`,
5804
+ runtimeConfigId: strategyRevision,
5805
+ strategyRevision,
5768
5806
  runtimeLineage,
5769
5807
  universe: preparedRun.universe,
5770
5808
  accountId: preparedRun.accountId,
@@ -8810,15 +8848,15 @@ var renderLineageRows = (runtimeComparison) => {
8810
8848
  contexts: /* @__PURE__ */ new Set()
8811
8849
  };
8812
8850
  existing.scopes += 1;
8813
- if (record.lineage.schemaVersion === 2) {
8814
- existing.gitShas.add("release-versioned");
8851
+ if (record.lineage.schemaVersion === 3) {
8852
+ existing.gitShas.add(record.lineage.deploymentCompositionId);
8815
8853
  existing.dirty.add("n/a");
8816
- existing.gates.add("release-versioned");
8817
- existing.configs.add(`v${record.lineage.version}`);
8854
+ existing.gates.add("package-owned");
8855
+ existing.configs.add(record.lineage.strategyRevision);
8818
8856
  existing.contexts.add(
8819
8857
  [
8820
- record.lineage.strategyPackageVersion ?? "strategy:unknown",
8821
- record.lineage.runtimePackageVersion ?? "runtime:unknown"
8858
+ record.lineage.strategyPackageVersion,
8859
+ record.lineage.runtimePackageVersion
8822
8860
  ].join("/")
8823
8861
  );
8824
8862
  } else {
@@ -9126,17 +9164,20 @@ var replayBacktest = async () => {
9126
9164
  ).map(
9127
9165
  ({
9128
9166
  strategyName,
9129
- version,
9167
+ strategyRevision,
9130
9168
  strategyPackage,
9131
9169
  strategyPackageVersion,
9170
+ strategyDependencyVersions,
9132
9171
  runtimePackageVersion,
9133
9172
  strategyConfig,
9134
9173
  selection
9135
9174
  }) => ({
9136
9175
  strategyName,
9137
- version,
9176
+ strategyRevision,
9177
+ deploymentCompositionId: evidenceMetadata.deployment.deploymentCompositionId,
9138
9178
  strategyPackage,
9139
9179
  strategyPackageVersion,
9180
+ strategyDependencyVersions,
9140
9181
  runtimePackageVersion,
9141
9182
  strategyConfig,
9142
9183
  ...selection ? { selection } : {}