deepline 0.1.268 → 0.1.269

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.
@@ -155,7 +155,7 @@ export const SDK_RELEASE = {
155
155
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
156
156
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
157
157
  // Operators use the checkout-local deepline-admin binary instead.
158
- version: '0.1.268',
158
+ version: '0.1.269',
159
159
  contracts: {
160
160
  api: {
161
161
  name: 'sdk-http-api',
@@ -1023,6 +1023,57 @@ function terminalFinishedAt(
1023
1023
  return base.finishedAt ?? occurredAt;
1024
1024
  }
1025
1025
 
1026
+ function isStepLifecycleEvent(event: PlayRunLedgerEvent): boolean {
1027
+ return (
1028
+ event.type === 'step.started' ||
1029
+ event.type === 'step.progress' ||
1030
+ event.type === 'step.completed' ||
1031
+ event.type === 'step.failed' ||
1032
+ event.type === 'step.skipped'
1033
+ );
1034
+ }
1035
+
1036
+ /**
1037
+ * A terminal status patch can arrive twice: first without a step start, then
1038
+ * with the original start timestamp after the runner recovers its progress
1039
+ * buffer. A completed node whose start equals its completion is synthetic, so
1040
+ * this is the only late lifecycle refinement that is safe to admit. It cannot
1041
+ * create a node, change a terminal status, alter completion, or revive active
1042
+ * work. Preserve the Run Snapshot's own timestamps while making the node's
1043
+ * duration truthful.
1044
+ */
1045
+ function refineTerminalSyntheticStepStart(
1046
+ snapshot: PlayRunLedgerSnapshot,
1047
+ event: Extract<PlayRunLedgerEvent, { type: 'step.progress' }>,
1048
+ ): PlayRunLedgerSnapshot | null {
1049
+ const current = snapshot.stepsById[event.stepId];
1050
+ const startedAt = event.progress.startedAt;
1051
+ if (
1052
+ current?.status !== 'completed' ||
1053
+ event.status !== 'completed' ||
1054
+ typeof startedAt !== 'number' ||
1055
+ current.startedAt == null ||
1056
+ current.completedAt == null ||
1057
+ current.startedAt !== current.completedAt ||
1058
+ startedAt >= current.startedAt
1059
+ ) {
1060
+ return null;
1061
+ }
1062
+ return {
1063
+ ...snapshot,
1064
+ stepsById: {
1065
+ ...snapshot.stepsById,
1066
+ [event.stepId]: {
1067
+ ...current,
1068
+ startedAt,
1069
+ progress: current.progress
1070
+ ? { ...current.progress, startedAt }
1071
+ : { startedAt },
1072
+ },
1073
+ },
1074
+ };
1075
+ }
1076
+
1026
1077
  export function reducePlayRunLedgerEvent(
1027
1078
  snapshot: PlayRunLedgerSnapshot,
1028
1079
  event: PlayRunLedgerEvent,
@@ -1030,6 +1081,18 @@ export function reducePlayRunLedgerEvent(
1030
1081
  if (event.runId !== snapshot.runId) {
1031
1082
  return snapshot;
1032
1083
  }
1084
+ // A terminal Run Snapshot is immutable with respect to step lifecycle.
1085
+ // Detached runners can race their best-effort progress transport against the
1086
+ // terminal outbox, and gateway processes can restart or split that traffic.
1087
+ // The Play Run Ledger is the durable projection authority, so late
1088
+ // `step.*` facts must be a true no-op here rather than relying on a gateway
1089
+ // process to remember terminal state.
1090
+ if (isTerminalPlayRunLedgerStatus(snapshot.status)) {
1091
+ if (event.type === 'step.progress') {
1092
+ return refineTerminalSyntheticStepStart(snapshot, event) ?? snapshot;
1093
+ }
1094
+ if (isStepLifecycleEvent(event)) return snapshot;
1095
+ }
1033
1096
  // The scheduler's outbox can replay an older wait transition after its run
1034
1097
  // reached a terminal state. That transition is no longer meaningful and
1035
1098
  // must be byte-for-byte inert: even advancing `updatedAt` would re-publish
package/dist/cli/index.js CHANGED
@@ -718,7 +718,7 @@ var SDK_RELEASE = {
718
718
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
719
719
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
720
720
  // Operators use the checkout-local deepline-admin binary instead.
721
- version: "0.1.268",
721
+ version: "0.1.269",
722
722
  contracts: {
723
723
  api: {
724
724
  name: "sdk-http-api",
@@ -703,7 +703,7 @@ var SDK_RELEASE = {
703
703
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
704
704
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
705
705
  // Operators use the checkout-local deepline-admin binary instead.
706
- version: "0.1.268",
706
+ version: "0.1.269",
707
707
  contracts: {
708
708
  api: {
709
709
  name: "sdk-http-api",
package/dist/index.js CHANGED
@@ -437,7 +437,7 @@ var SDK_RELEASE = {
437
437
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
438
438
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
439
439
  // Operators use the checkout-local deepline-admin binary instead.
440
- version: "0.1.268",
440
+ version: "0.1.269",
441
441
  contracts: {
442
442
  api: {
443
443
  name: "sdk-http-api",
package/dist/index.mjs CHANGED
@@ -367,7 +367,7 @@ var SDK_RELEASE = {
367
367
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
368
368
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
369
369
  // Operators use the checkout-local deepline-admin binary instead.
370
- version: "0.1.268",
370
+ version: "0.1.269",
371
371
  contracts: {
372
372
  api: {
373
373
  name: "sdk-http-api",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.268",
3
+ "version": "0.1.269",
4
4
  "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
5
  "license": "MIT",
6
6
  "repository": {