@tomflow/proflow-execution-browser-extension 0.1.48 → 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.48";
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.48";
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.48";
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.48";
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.48";
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.48";
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.48";
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.48";
189
+ readonly moduleVersion: "0.1.50";
190
190
  } | {
191
191
  contract: "deployment.result.v1";
192
192
  moduleRef: "execution-browser-extension";
193
- moduleVersion: "0.1.48";
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.48";
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.48";
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.48",
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",
@@ -13843,6 +13843,29 @@ function createCollaborationCarrierApplication(options) {
13843
13843
  return Object.freeze({ deliverMessage, recoverPending });
13844
13844
  }
13845
13845
 
13846
+ // packages/execution-browser-extension/src/observer-recovery-rearm.ts
13847
+ function createObserverRecoveryRearm(recover) {
13848
+ let startupReady = false;
13849
+ let latestBridgeSessionEpoch = 0;
13850
+ const startupReadyAfterDenialRestore = () => {
13851
+ startupReady = true;
13852
+ recover();
13853
+ };
13854
+ const bridgeSessionEstablished = (epoch) => {
13855
+ if (!Number.isInteger(epoch) || epoch <= 0)
13856
+ throw new TypeError("bridge session epoch must be a positive integer");
13857
+ if (epoch <= latestBridgeSessionEpoch) return false;
13858
+ latestBridgeSessionEpoch = epoch;
13859
+ if (!startupReady) return false;
13860
+ recover();
13861
+ return true;
13862
+ };
13863
+ return Object.freeze({
13864
+ startupReady: startupReadyAfterDenialRestore,
13865
+ bridgeSessionEstablished
13866
+ });
13867
+ }
13868
+
13846
13869
  // packages/execution-browser-extension/src/recovery-trigger.ts
13847
13870
  async function boundedRecoveryObservation(observe, timeoutMs) {
13848
13871
  if (!Number.isFinite(timeoutMs) || timeoutMs <= 0)
@@ -14412,6 +14435,16 @@ async function emitStructuredLog(entry) {
14412
14435
  body: JSON.stringify({ timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...entry })
14413
14436
  }).catch(() => void 0);
14414
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
+ }
14415
14448
  async function invokeObserverApplication(operation, input) {
14416
14449
  const config2 = await taskApplicationConfig();
14417
14450
  if (!config2) throw new Error("OBSERVER_APPLICATION_NOT_CONFIGURED");
@@ -14512,9 +14545,23 @@ var collaborationCarrier = createCollaborationCarrierApplication({
14512
14545
  },
14513
14546
  agent: {
14514
14547
  async listPendingMessages(limit) {
14515
- return await invokeObserverApplication("collaboration.listPending", {
14516
- limit
14517
- });
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
+ }
14518
14565
  },
14519
14566
  async getPendingMessage(messageRef) {
14520
14567
  return await invokeObserverApplication("collaboration.getPending", {
@@ -14589,18 +14636,46 @@ async function persistSystemObserverState(result) {
14589
14636
  });
14590
14637
  }
14591
14638
  var observerRecoveryInFlight = null;
14639
+ var observerRecoveryTrailingRequested = false;
14592
14640
  var observerRecoveryRetryCount = 0;
14641
+ var observerRecoveryAttemptNo = 0;
14593
14642
  var nextRecoverySuppressions = [];
14594
14643
  function suppressNextObserverRecovery(denials) {
14595
14644
  nextRecoverySuppressions = denials;
14596
14645
  }
14597
14646
  function runObserverRecovery() {
14598
- 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
+ );
14599
14664
  const suppressedContinuations = nextRecoverySuppressions;
14600
14665
  nextRecoverySuppressions = [];
14601
14666
  observerRecoveryInFlight = (async () => {
14602
14667
  let recoveryNeedsRetry = false;
14668
+ emitObserverRecoveryDiagnostic(
14669
+ "COLLABORATION_RECOVERY_BEGIN",
14670
+ recoveryAttemptNo,
14671
+ recoveryTriggerRef
14672
+ );
14603
14673
  await collaborationCarrier.recoverPending(50).catch(() => void 0);
14674
+ emitObserverRecoveryDiagnostic(
14675
+ "COLLABORATION_RECOVERY_SETTLED",
14676
+ recoveryAttemptNo,
14677
+ recoveryTriggerRef
14678
+ );
14604
14679
  const signalBatch = await invokeObserverApplication(
14605
14680
  "execution.listSignals",
14606
14681
  { limit: 50 }
@@ -14676,7 +14751,11 @@ function runObserverRecovery() {
14676
14751
  }
14677
14752
  if (recoveryNeedsRetry && observerRecoveryRetryCount < 6) {
14678
14753
  observerRecoveryRetryCount += 1;
14679
- setTimeout(() => void runObserverRecovery(), 2e3);
14754
+ const retryScheduledFromAttemptNo = recoveryAttemptNo;
14755
+ setTimeout(() => {
14756
+ if (observerRecoveryAttemptNo !== retryScheduledFromAttemptNo) return;
14757
+ void runObserverRecovery();
14758
+ }, 2e3);
14680
14759
  } else if (!recoveryNeedsRetry) {
14681
14760
  observerRecoveryRetryCount = 0;
14682
14761
  }
@@ -14692,9 +14771,20 @@ function runObserverRecovery() {
14692
14771
  }
14693
14772
  })().finally(() => {
14694
14773
  observerRecoveryInFlight = null;
14774
+ if (!observerRecoveryTrailingRequested) return;
14775
+ observerRecoveryTrailingRequested = false;
14776
+ void runObserverRecovery();
14695
14777
  });
14696
14778
  return observerRecoveryInFlight;
14697
14779
  }
14780
+ var observerRecoveryRearm = createObserverRecoveryRearm(() => {
14781
+ emitObserverRecoveryDiagnostic(
14782
+ "REARM_CALLBACK_ENTERED",
14783
+ bridgeSessionEpoch,
14784
+ `bridge-session:${bridgeSessionEpoch}`
14785
+ );
14786
+ void runObserverRecovery();
14787
+ });
14698
14788
  function observationFor(tabId) {
14699
14789
  const observed = sessions.get(tabId);
14700
14790
  if (!observed) throw new Error("CONTENT_SESSION_NOT_READY");
@@ -15274,6 +15364,7 @@ async function bridgeFetch(config2, path, init = {}) {
15274
15364
  });
15275
15365
  }
15276
15366
  var bridgeLoopStarted = false;
15367
+ var bridgeSessionEpoch = 0;
15277
15368
  async function runBridgeLoop() {
15278
15369
  if (bridgeLoopStarted) return;
15279
15370
  bridgeLoopStarted = true;
@@ -15294,6 +15385,13 @@ async function runBridgeLoop() {
15294
15385
  })
15295
15386
  });
15296
15387
  if (!hello.ok) throw new Error("BRIDGE_HELLO_REJECTED");
15388
+ bridgeSessionEpoch += 1;
15389
+ emitObserverRecoveryDiagnostic(
15390
+ "BRIDGE_EPOCH_ACCEPTED",
15391
+ bridgeSessionEpoch,
15392
+ `bridge-session:${bridgeSessionEpoch}`
15393
+ );
15394
+ observerRecoveryRearm.bridgeSessionEstablished(bridgeSessionEpoch);
15297
15395
  await publishCarrierAttentions();
15298
15396
  let lastHeartbeatAt = Date.now();
15299
15397
  let lastExtensionKeepaliveAt = Date.now();
@@ -15627,7 +15725,7 @@ async function startBackgroundRuntime() {
15627
15725
  void runProvisioningBridgeLoop();
15628
15726
  const suppressedContinuations = await rebuildCarrierAttentionsFromTabs();
15629
15727
  suppressNextObserverRecovery(suppressedContinuations);
15630
- void runObserverRecovery();
15728
+ observerRecoveryRearm.startupReady();
15631
15729
  }
15632
15730
  chrome.action.onClicked.addListener(() => {
15633
15731
  void openTaskPage();
@@ -15639,7 +15737,7 @@ chrome.runtime.onInstalled.addListener(() => {
15639
15737
  void runBridgeLoop();
15640
15738
  const suppressedContinuations = await rebuildCarrierAttentionsFromTabs();
15641
15739
  suppressNextObserverRecovery(suppressedContinuations);
15642
- void runObserverRecovery();
15740
+ observerRecoveryRearm.startupReady();
15643
15741
  });
15644
15742
  });
15645
15743
  chrome.runtime.onStartup.addListener(() => {
@@ -15650,7 +15748,7 @@ chrome.runtime.onStartup.addListener(() => {
15650
15748
  void runBridgeLoop();
15651
15749
  const suppressedContinuations = await rebuildCarrierAttentionsFromTabs();
15652
15750
  suppressNextObserverRecovery(suppressedContinuations);
15653
- void runObserverRecovery();
15751
+ observerRecoveryRearm.startupReady();
15654
15752
  });
15655
15753
  });
15656
15754
  void startBackgroundRuntime();
@@ -0,0 +1,4 @@
1
+ export declare function createObserverRecoveryRearm(recover: () => void): Readonly<{
2
+ startupReady: () => void;
3
+ bridgeSessionEstablished: (epoch: number) => boolean;
4
+ }>;
@@ -0,0 +1,23 @@
1
+ export function createObserverRecoveryRearm(recover) {
2
+ let startupReady = false;
3
+ let latestBridgeSessionEpoch = 0;
4
+ const startupReadyAfterDenialRestore = () => {
5
+ startupReady = true;
6
+ recover();
7
+ };
8
+ const bridgeSessionEstablished = (epoch) => {
9
+ if (!Number.isInteger(epoch) || epoch <= 0)
10
+ throw new TypeError("bridge session epoch must be a positive integer");
11
+ if (epoch <= latestBridgeSessionEpoch)
12
+ return false;
13
+ latestBridgeSessionEpoch = epoch;
14
+ if (!startupReady)
15
+ return false;
16
+ recover();
17
+ return true;
18
+ };
19
+ return Object.freeze({
20
+ startupReady: startupReadyAfterDenialRestore,
21
+ bridgeSessionEstablished,
22
+ });
23
+ }
@@ -18,6 +18,7 @@ import {
18
18
  resolveRoutineCarrierPermission,
19
19
  } from "../src/carrier-permission-lifecycle.js";
20
20
  import { createCollaborationCarrierApplication } from "../src/collaboration-carrier.js";
21
+ import { createObserverRecoveryRearm } from "../src/observer-recovery-rearm.js";
21
22
  import {
22
23
  boundedRecoveryObservation,
23
24
  shouldTriggerObserverRecovery,
@@ -472,6 +473,21 @@ async function emitStructuredLog(entry: BrowserStructuredLogEntry) {
472
473
  }).catch(() => undefined);
473
474
  }
474
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
+
475
491
  async function invokeObserverApplication(
476
492
  operation: string,
477
493
  input: Record<string, unknown>,
@@ -598,15 +614,29 @@ const collaborationCarrier = createCollaborationCarrierApplication({
598
614
  },
599
615
  agent: {
600
616
  async listPendingMessages(limit) {
601
- return (await invokeObserverApplication("collaboration.listPending", {
602
- limit,
603
- })) as Awaited<
604
- ReturnType<
605
- Parameters<
606
- typeof createCollaborationCarrierApplication
607
- >[0]["agent"]["listPendingMessages"]
608
- >
609
- >;
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
+ }
610
640
  },
611
641
  async getPendingMessage(messageRef) {
612
642
  return (await invokeObserverApplication("collaboration.getPending", {
@@ -720,7 +750,9 @@ async function persistSystemObserverState(
720
750
  }
721
751
 
722
752
  let observerRecoveryInFlight: Promise<void> | null = null;
753
+ let observerRecoveryTrailingRequested = false;
723
754
  let observerRecoveryRetryCount = 0;
755
+ let observerRecoveryAttemptNo = 0;
724
756
  let nextRecoverySuppressions: readonly CarrierContinuationDenial[] = [];
725
757
  function suppressNextObserverRecovery(
726
758
  denials: readonly CarrierContinuationDenial[],
@@ -728,12 +760,38 @@ function suppressNextObserverRecovery(
728
760
  nextRecoverySuppressions = denials;
729
761
  }
730
762
  function runObserverRecovery() {
731
- 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
+ );
732
780
  const suppressedContinuations = nextRecoverySuppressions;
733
781
  nextRecoverySuppressions = [];
734
782
  observerRecoveryInFlight = (async () => {
735
783
  let recoveryNeedsRetry = false;
784
+ emitObserverRecoveryDiagnostic(
785
+ "COLLABORATION_RECOVERY_BEGIN",
786
+ recoveryAttemptNo,
787
+ recoveryTriggerRef,
788
+ );
736
789
  await collaborationCarrier.recoverPending(50).catch(() => undefined);
790
+ emitObserverRecoveryDiagnostic(
791
+ "COLLABORATION_RECOVERY_SETTLED",
792
+ recoveryAttemptNo,
793
+ recoveryTriggerRef,
794
+ );
737
795
  const signalBatch = await invokeObserverApplication(
738
796
  "execution.listSignals",
739
797
  { limit: 50 },
@@ -845,7 +903,11 @@ function runObserverRecovery() {
845
903
  // remains the no-blind-replay authority for APPLIED/NOT_APPLIED/UNKNOWN.
846
904
  if (recoveryNeedsRetry && observerRecoveryRetryCount < 6) {
847
905
  observerRecoveryRetryCount += 1;
848
- setTimeout(() => void runObserverRecovery(), 2_000);
906
+ const retryScheduledFromAttemptNo = recoveryAttemptNo;
907
+ setTimeout(() => {
908
+ if (observerRecoveryAttemptNo !== retryScheduledFromAttemptNo) return;
909
+ void runObserverRecovery();
910
+ }, 2_000);
849
911
  } else if (!recoveryNeedsRetry) {
850
912
  observerRecoveryRetryCount = 0;
851
913
  }
@@ -863,10 +925,22 @@ function runObserverRecovery() {
863
925
  }
864
926
  })().finally(() => {
865
927
  observerRecoveryInFlight = null;
928
+ if (!observerRecoveryTrailingRequested) return;
929
+ observerRecoveryTrailingRequested = false;
930
+ void runObserverRecovery();
866
931
  });
867
932
  return observerRecoveryInFlight;
868
933
  }
869
934
 
935
+ const observerRecoveryRearm = createObserverRecoveryRearm(() => {
936
+ emitObserverRecoveryDiagnostic(
937
+ "REARM_CALLBACK_ENTERED",
938
+ bridgeSessionEpoch,
939
+ `bridge-session:${bridgeSessionEpoch}`,
940
+ );
941
+ void runObserverRecovery();
942
+ });
943
+
870
944
  function observationFor(tabId: number): ContentObservation {
871
945
  const observed = sessions.get(tabId);
872
946
  if (!observed) throw new Error("CONTENT_SESSION_NOT_READY");
@@ -1623,6 +1697,7 @@ async function bridgeFetch(
1623
1697
  }
1624
1698
 
1625
1699
  let bridgeLoopStarted = false;
1700
+ let bridgeSessionEpoch = 0;
1626
1701
  async function runBridgeLoop() {
1627
1702
  if (bridgeLoopStarted) return;
1628
1703
  bridgeLoopStarted = true;
@@ -1643,6 +1718,13 @@ async function runBridgeLoop() {
1643
1718
  }),
1644
1719
  });
1645
1720
  if (!hello.ok) throw new Error("BRIDGE_HELLO_REJECTED");
1721
+ bridgeSessionEpoch += 1;
1722
+ emitObserverRecoveryDiagnostic(
1723
+ "BRIDGE_EPOCH_ACCEPTED",
1724
+ bridgeSessionEpoch,
1725
+ `bridge-session:${bridgeSessionEpoch}`,
1726
+ );
1727
+ observerRecoveryRearm.bridgeSessionEstablished(bridgeSessionEpoch);
1646
1728
  await publishCarrierAttentions();
1647
1729
  // Hello only establishes a session. The first inner-loop action must be
1648
1730
  // a real command poll so Runtime readiness cannot be granted by hello alone.
@@ -2046,7 +2128,7 @@ async function startBackgroundRuntime(): Promise<void> {
2046
2128
  void runProvisioningBridgeLoop();
2047
2129
  const suppressedContinuations = await rebuildCarrierAttentionsFromTabs();
2048
2130
  suppressNextObserverRecovery(suppressedContinuations);
2049
- void runObserverRecovery();
2131
+ observerRecoveryRearm.startupReady();
2050
2132
  }
2051
2133
 
2052
2134
  chrome.action.onClicked.addListener(() => {
@@ -2059,7 +2141,7 @@ chrome.runtime.onInstalled.addListener(() => {
2059
2141
  void runBridgeLoop();
2060
2142
  const suppressedContinuations = await rebuildCarrierAttentionsFromTabs();
2061
2143
  suppressNextObserverRecovery(suppressedContinuations);
2062
- void runObserverRecovery();
2144
+ observerRecoveryRearm.startupReady();
2063
2145
  });
2064
2146
  });
2065
2147
  chrome.runtime.onStartup.addListener(() => {
@@ -2070,7 +2152,7 @@ chrome.runtime.onStartup.addListener(() => {
2070
2152
  void runBridgeLoop();
2071
2153
  const suppressedContinuations = await rebuildCarrierAttentionsFromTabs();
2072
2154
  suppressNextObserverRecovery(suppressedContinuations);
2073
- void runObserverRecovery();
2155
+ observerRecoveryRearm.startupReady();
2074
2156
  });
2075
2157
  });
2076
2158
  void startBackgroundRuntime();
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.48",
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.48",
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": {
@@ -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.48",
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",