@tomflow/proflow-execution-browser-extension 0.1.49 → 0.1.50

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/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # @tomflow/proflow-execution-browser-extension
2
+
3
+ ## 0.1.50
4
+
5
+ ### Patch Changes
6
+
7
+ - Preserve Observer recovery demand while a recovery pass is already in flight by coalescing reconnect, retry, and recovery requests into one trailing pass, without introducing concurrent recovery or stale retry replay.
@@ -53,7 +53,7 @@ export declare const behaviorAdapter: {
53
53
  ok: true;
54
54
  status: "SUCCEEDED";
55
55
  moduleRef: "execution-browser-extension";
56
- moduleVersion: "0.1.49";
56
+ moduleVersion: "0.1.50";
57
57
  data: {
58
58
  loadDir: string;
59
59
  };
@@ -66,7 +66,7 @@ export declare const behaviorAdapter: {
66
66
  readonly ok: true;
67
67
  readonly status: "SUCCEEDED";
68
68
  readonly moduleRef: "execution-browser-extension";
69
- readonly moduleVersion: "0.1.49";
69
+ readonly moduleVersion: "0.1.50";
70
70
  };
71
71
  observedEffects: never[];
72
72
  }>;
@@ -76,7 +76,7 @@ export declare const behaviorAdapter: {
76
76
  ok: true;
77
77
  status: "SUCCEEDED";
78
78
  moduleRef: "execution-browser-extension";
79
- moduleVersion: "0.1.49";
79
+ moduleVersion: "0.1.50";
80
80
  data: {
81
81
  setupStatus: "ACTION_REQUIRED" | "READY";
82
82
  runtimeStatus: "NOT_APPLICABLE";
@@ -101,7 +101,7 @@ export declare const behaviorAdapter: {
101
101
  result: {
102
102
  contract: "deployment.result.v1";
103
103
  moduleRef: "execution-browser-extension";
104
- moduleVersion: "0.1.49";
104
+ moduleVersion: "0.1.50";
105
105
  ok: false;
106
106
  status: "ACTION_REQUIRED";
107
107
  data: {
@@ -133,14 +133,14 @@ export declare const behaviorAdapter: {
133
133
  readonly ok: true;
134
134
  readonly status: "SUCCEEDED";
135
135
  readonly moduleRef: "execution-browser-extension";
136
- readonly moduleVersion: "0.1.49";
136
+ readonly moduleVersion: "0.1.50";
137
137
  };
138
138
  observedEffects: string[];
139
139
  } | {
140
140
  result: {
141
141
  contract: "deployment.result.v1";
142
142
  moduleRef: "execution-browser-extension";
143
- moduleVersion: "0.1.49";
143
+ moduleVersion: "0.1.50";
144
144
  ok: false;
145
145
  status: "FAILED";
146
146
  error: {
@@ -173,7 +173,7 @@ export declare const behaviorAdapter: {
173
173
  ok: true;
174
174
  status: "SUCCEEDED";
175
175
  moduleRef: "execution-browser-extension";
176
- moduleVersion: "0.1.49";
176
+ moduleVersion: "0.1.50";
177
177
  data: {
178
178
  docs: string;
179
179
  };
@@ -186,11 +186,11 @@ export declare const behaviorAdapter: {
186
186
  readonly ok: true;
187
187
  readonly status: "SUCCEEDED";
188
188
  readonly moduleRef: "execution-browser-extension";
189
- readonly moduleVersion: "0.1.49";
189
+ readonly moduleVersion: "0.1.50";
190
190
  } | {
191
191
  contract: "deployment.result.v1";
192
192
  moduleRef: "execution-browser-extension";
193
- moduleVersion: "0.1.49";
193
+ moduleVersion: "0.1.50";
194
194
  ok: false;
195
195
  status: "FAILED";
196
196
  error: {
@@ -207,7 +207,7 @@ export declare const behaviorAdapter: {
207
207
  readonly ok: true;
208
208
  readonly status: "SUCCEEDED";
209
209
  readonly moduleRef: "execution-browser-extension";
210
- readonly moduleVersion: "0.1.49";
210
+ readonly moduleVersion: "0.1.50";
211
211
  };
212
212
  observedEffects: never[];
213
213
  }>;
@@ -3,7 +3,7 @@ export declare const descriptor: {
3
3
  readonly contractVersion: "1.0.0";
4
4
  readonly moduleRef: "execution-browser-extension";
5
5
  readonly packageName: "@tomflow/proflow-execution-browser-extension";
6
- readonly moduleVersion: "0.1.49";
6
+ readonly moduleVersion: "0.1.50";
7
7
  readonly kind: "browser-extension";
8
8
  readonly templateVersion: "1.0.0";
9
9
  readonly platformCompatibility: ">=1.0.0 <2.0.0";
@@ -3,7 +3,7 @@ export const descriptor = {
3
3
  contractVersion: "1.0.0",
4
4
  moduleRef: "execution-browser-extension",
5
5
  packageName: "@tomflow/proflow-execution-browser-extension",
6
- moduleVersion: "0.1.49",
6
+ moduleVersion: "0.1.50",
7
7
  kind: "browser-extension",
8
8
  templateVersion: "1.0.0",
9
9
  platformCompatibility: ">=1.0.0 <2.0.0",
@@ -14435,6 +14435,16 @@ async function emitStructuredLog(entry) {
14435
14435
  body: JSON.stringify({ timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...entry })
14436
14436
  }).catch(() => void 0);
14437
14437
  }
14438
+ function emitObserverRecoveryDiagnostic(status, attemptNo, operationRef) {
14439
+ void emitStructuredLog({
14440
+ level: "INFO",
14441
+ component: "browser-observer-recovery",
14442
+ operation: "observer.recovery",
14443
+ status,
14444
+ attemptNo,
14445
+ operationRef
14446
+ }).catch(() => void 0);
14447
+ }
14438
14448
  async function invokeObserverApplication(operation, input) {
14439
14449
  const config2 = await taskApplicationConfig();
14440
14450
  if (!config2) throw new Error("OBSERVER_APPLICATION_NOT_CONFIGURED");
@@ -14535,9 +14545,23 @@ var collaborationCarrier = createCollaborationCarrierApplication({
14535
14545
  },
14536
14546
  agent: {
14537
14547
  async listPendingMessages(limit) {
14538
- return await invokeObserverApplication("collaboration.listPending", {
14539
- limit
14540
- });
14548
+ const recoveryTriggerRef = `bridge-session:${bridgeSessionEpoch}`;
14549
+ emitObserverRecoveryDiagnostic(
14550
+ "COLLABORATION_LIST_PENDING_BEGIN",
14551
+ observerRecoveryAttemptNo,
14552
+ recoveryTriggerRef
14553
+ );
14554
+ try {
14555
+ return await invokeObserverApplication("collaboration.listPending", {
14556
+ limit
14557
+ });
14558
+ } finally {
14559
+ emitObserverRecoveryDiagnostic(
14560
+ "COLLABORATION_LIST_PENDING_SETTLED",
14561
+ observerRecoveryAttemptNo,
14562
+ recoveryTriggerRef
14563
+ );
14564
+ }
14541
14565
  },
14542
14566
  async getPendingMessage(messageRef) {
14543
14567
  return await invokeObserverApplication("collaboration.getPending", {
@@ -14612,18 +14636,46 @@ async function persistSystemObserverState(result) {
14612
14636
  });
14613
14637
  }
14614
14638
  var observerRecoveryInFlight = null;
14639
+ var observerRecoveryTrailingRequested = false;
14615
14640
  var observerRecoveryRetryCount = 0;
14641
+ var observerRecoveryAttemptNo = 0;
14616
14642
  var nextRecoverySuppressions = [];
14617
14643
  function suppressNextObserverRecovery(denials) {
14618
14644
  nextRecoverySuppressions = denials;
14619
14645
  }
14620
14646
  function runObserverRecovery() {
14621
- if (observerRecoveryInFlight) return observerRecoveryInFlight;
14647
+ const recoveryTriggerRef = `bridge-session:${bridgeSessionEpoch}`;
14648
+ if (observerRecoveryInFlight) {
14649
+ observerRecoveryTrailingRequested = true;
14650
+ emitObserverRecoveryDiagnostic(
14651
+ "REUSED_IN_FLIGHT",
14652
+ observerRecoveryAttemptNo,
14653
+ recoveryTriggerRef
14654
+ );
14655
+ return observerRecoveryInFlight;
14656
+ }
14657
+ observerRecoveryAttemptNo += 1;
14658
+ const recoveryAttemptNo = observerRecoveryAttemptNo;
14659
+ emitObserverRecoveryDiagnostic(
14660
+ "STARTED",
14661
+ recoveryAttemptNo,
14662
+ recoveryTriggerRef
14663
+ );
14622
14664
  const suppressedContinuations = nextRecoverySuppressions;
14623
14665
  nextRecoverySuppressions = [];
14624
14666
  observerRecoveryInFlight = (async () => {
14625
14667
  let recoveryNeedsRetry = false;
14668
+ emitObserverRecoveryDiagnostic(
14669
+ "COLLABORATION_RECOVERY_BEGIN",
14670
+ recoveryAttemptNo,
14671
+ recoveryTriggerRef
14672
+ );
14626
14673
  await collaborationCarrier.recoverPending(50).catch(() => void 0);
14674
+ emitObserverRecoveryDiagnostic(
14675
+ "COLLABORATION_RECOVERY_SETTLED",
14676
+ recoveryAttemptNo,
14677
+ recoveryTriggerRef
14678
+ );
14627
14679
  const signalBatch = await invokeObserverApplication(
14628
14680
  "execution.listSignals",
14629
14681
  { limit: 50 }
@@ -14699,7 +14751,11 @@ function runObserverRecovery() {
14699
14751
  }
14700
14752
  if (recoveryNeedsRetry && observerRecoveryRetryCount < 6) {
14701
14753
  observerRecoveryRetryCount += 1;
14702
- setTimeout(() => void runObserverRecovery(), 2e3);
14754
+ const retryScheduledFromAttemptNo = recoveryAttemptNo;
14755
+ setTimeout(() => {
14756
+ if (observerRecoveryAttemptNo !== retryScheduledFromAttemptNo) return;
14757
+ void runObserverRecovery();
14758
+ }, 2e3);
14703
14759
  } else if (!recoveryNeedsRetry) {
14704
14760
  observerRecoveryRetryCount = 0;
14705
14761
  }
@@ -14715,10 +14771,18 @@ function runObserverRecovery() {
14715
14771
  }
14716
14772
  })().finally(() => {
14717
14773
  observerRecoveryInFlight = null;
14774
+ if (!observerRecoveryTrailingRequested) return;
14775
+ observerRecoveryTrailingRequested = false;
14776
+ void runObserverRecovery();
14718
14777
  });
14719
14778
  return observerRecoveryInFlight;
14720
14779
  }
14721
14780
  var observerRecoveryRearm = createObserverRecoveryRearm(() => {
14781
+ emitObserverRecoveryDiagnostic(
14782
+ "REARM_CALLBACK_ENTERED",
14783
+ bridgeSessionEpoch,
14784
+ `bridge-session:${bridgeSessionEpoch}`
14785
+ );
14722
14786
  void runObserverRecovery();
14723
14787
  });
14724
14788
  function observationFor(tabId) {
@@ -15322,6 +15386,11 @@ async function runBridgeLoop() {
15322
15386
  });
15323
15387
  if (!hello.ok) throw new Error("BRIDGE_HELLO_REJECTED");
15324
15388
  bridgeSessionEpoch += 1;
15389
+ emitObserverRecoveryDiagnostic(
15390
+ "BRIDGE_EPOCH_ACCEPTED",
15391
+ bridgeSessionEpoch,
15392
+ `bridge-session:${bridgeSessionEpoch}`
15393
+ );
15325
15394
  observerRecoveryRearm.bridgeSessionEstablished(bridgeSessionEpoch);
15326
15395
  await publishCarrierAttentions();
15327
15396
  let lastHeartbeatAt = Date.now();
@@ -473,6 +473,21 @@ async function emitStructuredLog(entry: BrowserStructuredLogEntry) {
473
473
  }).catch(() => undefined);
474
474
  }
475
475
 
476
+ function emitObserverRecoveryDiagnostic(
477
+ status: string,
478
+ attemptNo: number,
479
+ operationRef: string,
480
+ ): void {
481
+ void emitStructuredLog({
482
+ level: "INFO",
483
+ component: "browser-observer-recovery",
484
+ operation: "observer.recovery",
485
+ status,
486
+ attemptNo,
487
+ operationRef,
488
+ }).catch(() => undefined);
489
+ }
490
+
476
491
  async function invokeObserverApplication(
477
492
  operation: string,
478
493
  input: Record<string, unknown>,
@@ -599,15 +614,29 @@ const collaborationCarrier = createCollaborationCarrierApplication({
599
614
  },
600
615
  agent: {
601
616
  async listPendingMessages(limit) {
602
- return (await invokeObserverApplication("collaboration.listPending", {
603
- limit,
604
- })) as Awaited<
605
- ReturnType<
606
- Parameters<
607
- typeof createCollaborationCarrierApplication
608
- >[0]["agent"]["listPendingMessages"]
609
- >
610
- >;
617
+ const recoveryTriggerRef = `bridge-session:${bridgeSessionEpoch}`;
618
+ emitObserverRecoveryDiagnostic(
619
+ "COLLABORATION_LIST_PENDING_BEGIN",
620
+ observerRecoveryAttemptNo,
621
+ recoveryTriggerRef,
622
+ );
623
+ try {
624
+ return (await invokeObserverApplication("collaboration.listPending", {
625
+ limit,
626
+ })) as Awaited<
627
+ ReturnType<
628
+ Parameters<
629
+ typeof createCollaborationCarrierApplication
630
+ >[0]["agent"]["listPendingMessages"]
631
+ >
632
+ >;
633
+ } finally {
634
+ emitObserverRecoveryDiagnostic(
635
+ "COLLABORATION_LIST_PENDING_SETTLED",
636
+ observerRecoveryAttemptNo,
637
+ recoveryTriggerRef,
638
+ );
639
+ }
611
640
  },
612
641
  async getPendingMessage(messageRef) {
613
642
  return (await invokeObserverApplication("collaboration.getPending", {
@@ -721,7 +750,9 @@ async function persistSystemObserverState(
721
750
  }
722
751
 
723
752
  let observerRecoveryInFlight: Promise<void> | null = null;
753
+ let observerRecoveryTrailingRequested = false;
724
754
  let observerRecoveryRetryCount = 0;
755
+ let observerRecoveryAttemptNo = 0;
725
756
  let nextRecoverySuppressions: readonly CarrierContinuationDenial[] = [];
726
757
  function suppressNextObserverRecovery(
727
758
  denials: readonly CarrierContinuationDenial[],
@@ -729,12 +760,38 @@ function suppressNextObserverRecovery(
729
760
  nextRecoverySuppressions = denials;
730
761
  }
731
762
  function runObserverRecovery() {
732
- if (observerRecoveryInFlight) return observerRecoveryInFlight;
763
+ const recoveryTriggerRef = `bridge-session:${bridgeSessionEpoch}`;
764
+ if (observerRecoveryInFlight) {
765
+ observerRecoveryTrailingRequested = true;
766
+ emitObserverRecoveryDiagnostic(
767
+ "REUSED_IN_FLIGHT",
768
+ observerRecoveryAttemptNo,
769
+ recoveryTriggerRef,
770
+ );
771
+ return observerRecoveryInFlight;
772
+ }
773
+ observerRecoveryAttemptNo += 1;
774
+ const recoveryAttemptNo = observerRecoveryAttemptNo;
775
+ emitObserverRecoveryDiagnostic(
776
+ "STARTED",
777
+ recoveryAttemptNo,
778
+ recoveryTriggerRef,
779
+ );
733
780
  const suppressedContinuations = nextRecoverySuppressions;
734
781
  nextRecoverySuppressions = [];
735
782
  observerRecoveryInFlight = (async () => {
736
783
  let recoveryNeedsRetry = false;
784
+ emitObserverRecoveryDiagnostic(
785
+ "COLLABORATION_RECOVERY_BEGIN",
786
+ recoveryAttemptNo,
787
+ recoveryTriggerRef,
788
+ );
737
789
  await collaborationCarrier.recoverPending(50).catch(() => undefined);
790
+ emitObserverRecoveryDiagnostic(
791
+ "COLLABORATION_RECOVERY_SETTLED",
792
+ recoveryAttemptNo,
793
+ recoveryTriggerRef,
794
+ );
738
795
  const signalBatch = await invokeObserverApplication(
739
796
  "execution.listSignals",
740
797
  { limit: 50 },
@@ -846,7 +903,11 @@ function runObserverRecovery() {
846
903
  // remains the no-blind-replay authority for APPLIED/NOT_APPLIED/UNKNOWN.
847
904
  if (recoveryNeedsRetry && observerRecoveryRetryCount < 6) {
848
905
  observerRecoveryRetryCount += 1;
849
- setTimeout(() => void runObserverRecovery(), 2_000);
906
+ const retryScheduledFromAttemptNo = recoveryAttemptNo;
907
+ setTimeout(() => {
908
+ if (observerRecoveryAttemptNo !== retryScheduledFromAttemptNo) return;
909
+ void runObserverRecovery();
910
+ }, 2_000);
850
911
  } else if (!recoveryNeedsRetry) {
851
912
  observerRecoveryRetryCount = 0;
852
913
  }
@@ -864,11 +925,19 @@ function runObserverRecovery() {
864
925
  }
865
926
  })().finally(() => {
866
927
  observerRecoveryInFlight = null;
928
+ if (!observerRecoveryTrailingRequested) return;
929
+ observerRecoveryTrailingRequested = false;
930
+ void runObserverRecovery();
867
931
  });
868
932
  return observerRecoveryInFlight;
869
933
  }
870
934
 
871
935
  const observerRecoveryRearm = createObserverRecoveryRearm(() => {
936
+ emitObserverRecoveryDiagnostic(
937
+ "REARM_CALLBACK_ENTERED",
938
+ bridgeSessionEpoch,
939
+ `bridge-session:${bridgeSessionEpoch}`,
940
+ );
872
941
  void runObserverRecovery();
873
942
  });
874
943
 
@@ -1650,6 +1719,11 @@ async function runBridgeLoop() {
1650
1719
  });
1651
1720
  if (!hello.ok) throw new Error("BRIDGE_HELLO_REJECTED");
1652
1721
  bridgeSessionEpoch += 1;
1722
+ emitObserverRecoveryDiagnostic(
1723
+ "BRIDGE_EPOCH_ACCEPTED",
1724
+ bridgeSessionEpoch,
1725
+ `bridge-session:${bridgeSessionEpoch}`,
1726
+ );
1653
1727
  observerRecoveryRearm.bridgeSessionEstablished(bridgeSessionEpoch);
1654
1728
  await publishCarrierAttentions();
1655
1729
  // Hello only establishes a session. The first inner-loop action must be
package/manifest.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "ProFlow Execution Browser",
4
- "version": "0.1.49",
4
+ "version": "0.1.50",
5
5
  "permissions": [
6
6
  "tabs",
7
7
  "storage"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomflow/proflow-execution-browser-extension",
3
- "version": "0.1.49",
3
+ "version": "0.1.50",
4
4
  "description": "Execution-owned MV3 Browser executor, evidence provider and browser application surface.",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -27,8 +27,8 @@
27
27
  "SETUP.md"
28
28
  ],
29
29
  "dependencies": {
30
- "@tomflow/proflow-module-contract": "^0.1.13",
31
- "@tomflow/proflow-execution-contracts": "^0.1.10"
30
+ "@tomflow/proflow-execution-contracts": "^0.1.10",
31
+ "@tomflow/proflow-module-contract": "^0.1.13"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@tomflow/proflow-deployment-conformance": "^0.1.13",
@@ -3,7 +3,7 @@
3
3
  "contractVersion": "1.0.0",
4
4
  "moduleRef": "execution-browser-extension",
5
5
  "packageName": "@tomflow/proflow-execution-browser-extension",
6
- "moduleVersion": "0.1.49",
6
+ "moduleVersion": "0.1.50",
7
7
  "kind": "browser-extension",
8
8
  "templateVersion": "1.0.0",
9
9
  "platformCompatibility": ">=1.0.0 <2.0.0",