impel-cli 0.20.46 → 0.20.47

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/RELEASE_NOTES.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Release notes
2
2
 
3
+ ## 0.20.47 — Keep Tasks on the primary app window
4
+
5
+ - Makes the native Tasks fallback choose the earliest surviving primary host
6
+ window deterministically, so a later ChatGPT auxiliary renderer cannot win a
7
+ probe race and cover the real app with an empty grey window.
8
+ - Adds a behavioral regression that returns the auxiliary window first, lets it
9
+ finish navigation probing first, and proves the fallback and authenticated
10
+ board still attach only to the primary window.
11
+ - Skips the prerelease soak because this is an immediate stable regression
12
+ hotfix for `0.20.46`. The change updates the external Tasks preload
13
+ orchestration without changing vendor pins, generated profile contracts, or
14
+ built bundle bytes; the full release CI, pinned managed-app launch smoke, and
15
+ Windows vendor contracts remain mandatory before tagging.
16
+
3
17
  ## 0.20.46-beta.2 — Reload reconciled apps safely
4
18
 
5
19
  - Closes every running managed macOS app before rewriting its profile and
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "impel-cli",
3
- "version": "0.20.46",
3
+ "version": "0.20.47",
4
4
  "description": "Prepare isolated Claude and Codex workspaces for every accessible Impel tenant",
5
5
  "type": "module",
6
6
  "bin": {
@@ -483,6 +483,9 @@ if (
483
483
  } catch {}
484
484
  return window.isVisible?.() !== false;
485
485
  };
486
+ const fallbackHostWindow = () => BrowserWindow.getAllWindows()
487
+ .filter(isPrimaryWindow)
488
+ .sort((left, right) => left.id - right.id)[0] || null;
486
489
  const createView = (window) => {
487
490
  const state = stateFor(window);
488
491
  if (state.view && !state.view.webContents.isDestroyed()) return state;
@@ -573,8 +576,12 @@ if (
573
576
  const content = window.getContentBounds();
574
577
  state.nativeNav.setBounds({ x: content.x + 12, y: content.y + Math.max(48, content.height - 92), width: Math.min(120, Math.max(80, content.width - 24)), height: 38 });
575
578
  };
576
- const ensureNativeNav = (window) => {
577
- if (!isPrimaryWindow(window)) return;
579
+ const ensureNativeNav = () => {
580
+ // Renderer probes finish independently. Always bind the singleton
581
+ // fallback to the earliest surviving host window, not whichever visible
582
+ // auxiliary renderer happens to exhaust its probe retries first.
583
+ const window = fallbackHostWindow();
584
+ if (!window) return;
578
585
  const state = stateFor(window);
579
586
  if (state.nativeNav && !state.nativeNav.isDestroyed()) return;
580
587
  // Auxiliary vendor windows (for example Codex's hidden avatar overlay)
@@ -641,7 +648,7 @@ if (
641
648
  state.hasDomNavigation = true;
642
649
  for (const owner of BrowserWindow.getAllWindows()) removeNativeNav(owner);
643
650
  } else if (attempt < 3) setTimeout(() => inject(attempt + 1), 1000);
644
- else if (!state.hasDomNavigation && !hasDomNavigation) ensureNativeNav(window);
651
+ else if (!state.hasDomNavigation && !hasDomNavigation) ensureNativeNav();
645
652
  })
646
653
  .catch(() => record("navigation-injection-failed"));
647
654
  };