From b3a0377cd29a0601c8eb6d4abf6cc4464f4fb57a Mon Sep 17 00:00:00 2001
From: ericjypark
Date: Sun, 13 Sep 2026 16:54:37 -0500
Subject: [PATCH] feat(windows): add native app and installer pipeline
---
.github/workflows/release.yml | 9 +
.github/workflows/windows.yml | 82 +
README.md | 56 +-
windows/.gitignore | 4 +
windows/BEHAVIOR.md | 107 +
windows/CARD-PARITY.md | 45 +
windows/HISTORY.md | 135 +
windows/IslandPrototype/AlertEngine.cs | 62 +
windows/IslandPrototype/App.xaml | 58 +
windows/IslandPrototype/App.xaml.cs | 71 +
windows/IslandPrototype/AppUpdates.cs | 163 +
.../IslandPrototype/Assets/CodexIsland.ico | Bin 0 -> 40918 bytes
.../Assets/Fonts/CardDisplay-Medium.ttf | Bin 0 -> 341156 bytes
.../Assets/Fonts/CardDisplay-Regular.ttf | Bin 0 -> 340308 bytes
.../Assets/Fonts/CardDisplay-SemiBold.ttf | Bin 0 -> 341392 bytes
.../Assets/Fonts/CardText-SemiBold.ttf | Bin 0 -> 342848 bytes
.../Assets/Fonts/Inter-OFL.txt | 93 +
.../Assets/Fonts/IslandText-Medium.ttf | Bin 0 -> 342180 bytes
.../Assets/Fonts/IslandText-SemiBold.ttf | Bin 0 -> 342872 bytes
.../Assets/Fonts/IslandText-Status.ttf | Bin 0 -> 342860 bytes
.../IslandPrototype/Assets/Fonts/README.md | 31 +
.../IslandPrototype/Assets/antigravity.png | Bin 0 -> 3015 bytes
windows/IslandPrototype/Assets/claude.png | Bin 0 -> 11125 bytes
.../IslandPrototype/Assets/codexisland.png | Bin 0 -> 21238 bytes
windows/IslandPrototype/Assets/grok.png | Bin 0 -> 4901 bytes
.../IslandPrototype/Assets/mac-fixture.json | 6646 +++++++++++++++++
windows/IslandPrototype/Assets/openai.png | Bin 0 -> 12663 bytes
.../IslandPrototype/Assets/pricing-seed.json | 203 +
windows/IslandPrototype/Assets/tray-dark.ico | Bin 0 -> 4336 bytes
windows/IslandPrototype/Assets/tray-light.ico | Bin 0 -> 4357 bytes
windows/IslandPrototype/Assets/zh-Hans.json | 1 +
windows/IslandPrototype/CardTypography.cs | 90 +
windows/IslandPrototype/CliAccountActions.cs | 134 +
windows/IslandPrototype/CliCredentialWatch.cs | 26 +
windows/IslandPrototype/CliCredentials.cs | 123 +
windows/IslandPrototype/CliSessionRecovery.cs | 42 +
windows/IslandPrototype/CodexAccountReader.cs | 155 +
windows/IslandPrototype/CodexResetCredits.cs | 30 +
.../IslandPrototype/ConnectedProviderUsage.cs | 160 +
windows/IslandPrototype/CurrencyStore.cs | 83 +
windows/IslandPrototype/DataPaths.cs | 18 +
windows/IslandPrototype/DatabaseLogScanner.cs | 157 +
windows/IslandPrototype/DisplayCatalog.cs | 35 +
windows/IslandPrototype/DollarGlowLayer.cs | 40 +
windows/IslandPrototype/FooterStatus.cs | 36 +
windows/IslandPrototype/FooterStatusLayer.cs | 154 +
windows/IslandPrototype/FrameDiagnostics.cs | 51 +
windows/IslandPrototype/FullscreenGeometry.cs | 10 +
windows/IslandPrototype/GlowSweep.cs | 86 +
windows/IslandPrototype/GrokCompatibility.cs | 107 +
windows/IslandPrototype/HistoricalUsageDay.cs | 36 +
windows/IslandPrototype/HistoryCoordinator.cs | 110 +
windows/IslandPrototype/HistoryImport.cs | 145 +
windows/IslandPrototype/HistorySummary.cs | 52 +
.../IslandPrototype/IslandAccessibility.cs | 81 +
.../IslandPrototype/IslandPrototype.csproj | 24 +
windows/IslandPrototype/IslandTypography.cs | 73 +
windows/IslandPrototype/IslandVisual.Pill.cs | 78 +
.../IslandVisual.ResetCredits.cs | 133 +
windows/IslandPrototype/IslandVisual.cs | 886 +++
windows/IslandPrototype/LiveUsage.cs | 210 +
windows/IslandPrototype/LocalLogScanner.cs | 170 +
windows/IslandPrototype/Localizer.cs | 23 +
.../MainWindow.Introduction.cs | 148 +
windows/IslandPrototype/MainWindow.Motion.cs | 70 +
windows/IslandPrototype/MainWindow.xaml | 25 +
windows/IslandPrototype/MainWindow.xaml.cs | 819 ++
windows/IslandPrototype/ModelPricing.cs | 127 +
windows/IslandPrototype/Native.cs | 51 +
windows/IslandPrototype/NativeSqlite.cs | 109 +
windows/IslandPrototype/PageScrollGesture.cs | 25 +
windows/IslandPrototype/ParityData.cs | 93 +
windows/IslandPrototype/ParityTheme.cs | 106 +
windows/IslandPrototype/PillMotion.cs | 115 +
windows/IslandPrototype/PlatformActions.cs | 76 +
windows/IslandPrototype/PreferenceStore.cs | 124 +
windows/IslandPrototype/PreviewSettings.cs | 512 ++
.../ProviderCredentialParser.cs | 47 +
.../IslandPrototype/ProviderQuotaSelection.cs | 32 +
.../IslandPrototype/ProviderUsageClient.cs | 171 +
windows/IslandPrototype/QuotaHistoryStore.cs | 116 +
windows/IslandPrototype/SettingsControls.cs | 237 +
windows/IslandPrototype/TestAccess.cs | 7 +
windows/IslandPrototype/UsageCardSnapshot.cs | 111 +
windows/IslandPrototype/UsageCardStudio.cs | 237 +
windows/IslandPrototype/UsageCardVisual.cs | 161 +
windows/IslandPrototype/UsageFeed.cs | 108 +
windows/IslandPrototype/UsageHistory.cs | 30 +
windows/IslandPrototype/UsageLedger.cs | 94 +
windows/IslandPrototype/WakeScheduling.cs | 10 +
windows/IslandPrototype/WindowContext.cs | 62 +
.../IslandPrototype/WindowsCliCredential.cs | 51 +
.../IslandPrototype/WindowsUpdateBackend.cs | 104 +
windows/IslandPrototype/app.manifest | 13 +
windows/LIVE-PROVIDERS.md | 264 +
windows/PARITY.md | 226 +
windows/PERFORMANCE.md | 277 +
windows/README.md | 132 +
windows/UPDATES.md | 88 +
windows/VISUAL-REFINEMENT.md | 99 +
windows/build-installer.ps1 | 60 +
windows/publish-release.py | 94 +
windows/reference/MacHistoryReference.swift | 61 +
windows/reference/MacQuotaReference.swift | 35 +
windows/reference/PerformanceMac.swift | 92 +
windows/reference/RenderMacReference.swift | 139 +
windows/reference/history.sh | 18 +
windows/reference/measure-cards.py | 41 +
windows/reference/measure-island.py | 79 +
windows/reference/performance.sh | 40 +
windows/reference/prepare-card-fonts.py | 36 +
windows/reference/prepare-island-fonts.py | 24 +
windows/reference/quota.sh | 28 +
windows/reference/render.sh | 34 +
windows/run-parallels.sh | 6 +
windows/run.ps1 | 23 +
windows/tests/build-provider-work.ps1 | 8 +
.../tests/card-render/CardRenderTests.csproj | 13 +
windows/tests/card-render/Program.cs | 51 +
windows/tests/check-account-setup.ps1 | 48 +
windows/tests/check-alerts.ps1 | 144 +
windows/tests/check-card-preserved.ps1 | 38 +
windows/tests/check-card.ps1 | 166 +
windows/tests/check-codex-reset-ui.ps1 | 65 +
.../tests/check-connected-account-setup.ps1 | 33 +
windows/tests/check-dropdowns.ps1 | 111 +
windows/tests/check-footer-ui.ps1 | 64 +
windows/tests/check-installer-upgrade.ps1 | 142 +
windows/tests/check-interaction.ps1 | 143 +
windows/tests/check-introduction-startup.ps1 | 74 +
windows/tests/check-live-pointer.ps1 | 81 +
windows/tests/check-live-ui.ps1 | 131 +
windows/tests/check-mac-history-ui.ps1 | 147 +
windows/tests/check-motion.ps1 | 96 +
windows/tests/check-native-share.ps1 | 37 +
windows/tests/check-network-parallels.py | 40 +
windows/tests/check-network-recovery.ps1 | 44 +
windows/tests/check-parity.ps1 | 112 +
windows/tests/check-performance.ps1 | 102 +
windows/tests/check-preferences.ps1 | 79 +
windows/tests/check-quota-profile.ps1 | 48 +
windows/tests/check-render-cost.ps1 | 95 +
windows/tests/check-responsive-install.ps1 | 21 +
windows/tests/check-services.ps1 | 9 +
windows/tests/check-settings.ps1 | 122 +
windows/tests/check-startup-data-mode.ps1 | 60 +
windows/tests/check-swipe.ps1 | 79 +
windows/tests/check-tooltips.ps1 | 60 +
windows/tests/check-wake-ui.ps1 | 67 +
windows/tests/check-window-context.ps1 | 101 +
windows/tests/choose-antigravity-login.ps1 | 26 +
windows/tests/compare-island-refinement.py | 53 +
windows/tests/compare-renders.py | 51 +
windows/tests/diagnose-grok-signin.ps1 | 11 +
windows/tests/export-codex-schema.ps1 | 3 +
.../grok-compat/GrokCompatibilityCheck.csproj | 4 +
windows/tests/grok-compat/Program.cs | 13 +
windows/tests/inspect-account-login.ps1 | 23 +
windows/tests/inspect-account-processes.ps1 | 4 +
windows/tests/inspect-cli-installation.ps1 | 14 +
windows/tests/inspect-codex-protocol.ps1 | 2 +
windows/tests/inspect-codex-server.ps1 | 3 +
windows/tests/inspect-connected-clis.ps1 | 15 +
windows/tests/inspect-current-usage.ps1 | 3 +
windows/tests/inspect-live-account-values.ps1 | 12 +
.../tests/inspect-native-event-windows.ps1 | 21 +
windows/tests/inspect-settings.ps1 | 11 +
windows/tests/inspect-signin-pages.ps1 | 17 +
.../tests/live-render/FooterStatusUiTests.cs | 80 +
.../tests/live-render/LiveRenderTests.csproj | 16 +
windows/tests/live-render/Program.cs | 159 +
.../tests/live-render/QuotaHistoryUiTests.cs | 83 +
.../tests/live-render/QuotaSettingsTests.cs | 74 +
.../tests/live-render/ResetCreditUiTests.cs | 90 +
.../tests/live-render/SettingsPageTests.cs | 106 +
windows/tests/logic/AccountSetupTests.cs | 47 +
windows/tests/logic/AppUpdateTests.cs | 90 +
windows/tests/logic/CodexAccountTests.cs | 128 +
windows/tests/logic/ConnectedProviderTests.cs | 156 +
windows/tests/logic/FooterStatusTests.cs | 59 +
windows/tests/logic/HistoryTests.cs | 191 +
windows/tests/logic/LiveUsageTests.cs | 182 +
windows/tests/logic/LogicTests.csproj | 60 +
windows/tests/logic/Program.cs | 203 +
windows/tests/logic/QuotaHistoryTests.cs | 112 +
windows/tests/logic/WakeRecoveryTests.cs | 98 +
.../tests/mac-history/ImportBoundaryTests.cs | 82 +
.../tests/mac-history/MacHistoryTests.csproj | 15 +
windows/tests/mac-history/Program.cs | 192 +
windows/tests/measure-live-responsiveness.ps1 | 99 +
windows/tests/measure-pointer-reference.ps1 | 34 +
windows/tests/open-card-studio.ps1 | 43 +
windows/tests/open-mac-history-preview.ps1 | 41 +
windows/tests/open-provider-settings.ps1 | 25 +
windows/tests/prepare-grok-compat.ps1 | 9 +
.../PresentationProbe.csproj | 10 +
windows/tests/presentation-probe/Program.cs | 66 +
windows/tests/probe-graphics-effects.ps1 | 50 +
windows/tests/probe-grok-x64.ps1 | 18 +
windows/tests/probe-reset-hover.ps1 | 52 +
windows/tests/read-codex-account.ps1 | 7 +
windows/tests/render/Program.cs | 131 +
windows/tests/render/RenderTests.csproj | 15 +
windows/tests/run-card-render.ps1 | 10 +
windows/tests/run-live-render.ps1 | 18 +
windows/tests/run-logic.ps1 | 9 +
windows/tests/run-mac-history.ps1 | 20 +
windows/tests/run-presentation-probe.ps1 | 8 +
windows/tests/run-render.ps1 | 13 +
windows/tests/run-swipe-render.ps1 | 10 +
windows/tests/run-visual-render.ps1 | 15 +
windows/tests/run-window-motion.ps1 | 44 +
windows/tests/show-preview.ps1 | 81 +
windows/tests/snapshot-mac-history.py | 35 +
windows/tests/snapshot-mac-quota.swift | 26 +
windows/tests/start-connected-signin.ps1 | 14 +
windows/tests/stop-unneeded-signins.ps1 | 6 +
windows/tests/swipe-render/Program.cs | 88 +
.../swipe-render/SwipeRenderTests.csproj | 15 +
windows/tests/test_publish_release.py | 104 +
windows/tests/update-mac-history-preview.ps1 | 37 +
windows/tests/verify-provider-settings.ps1 | 61 +
.../tests/visual-render/PillMotionTests.cs | 152 +
windows/tests/visual-render/PillTests.cs | 107 +
windows/tests/visual-render/Program.cs | 54 +
.../tests/visual-render/RefinementTests.cs | 76 +
.../visual-render/VisualRenderTests.csproj | 13 +
.../tests/window-motion/IntroductionTests.cs | 171 +
windows/tests/window-motion/Program.cs | 137 +
windows/tests/window-motion/ReferenceSweep.cs | 77 +
.../window-motion/WindowMotionTests.csproj | 4 +
windows/tests/window-motion/app.manifest | 13 +
232 files changed, 24350 insertions(+), 19 deletions(-)
create mode 100644 .github/workflows/windows.yml
create mode 100644 windows/.gitignore
create mode 100644 windows/BEHAVIOR.md
create mode 100644 windows/CARD-PARITY.md
create mode 100644 windows/HISTORY.md
create mode 100644 windows/IslandPrototype/AlertEngine.cs
create mode 100644 windows/IslandPrototype/App.xaml
create mode 100644 windows/IslandPrototype/App.xaml.cs
create mode 100644 windows/IslandPrototype/AppUpdates.cs
create mode 100644 windows/IslandPrototype/Assets/CodexIsland.ico
create mode 100644 windows/IslandPrototype/Assets/Fonts/CardDisplay-Medium.ttf
create mode 100644 windows/IslandPrototype/Assets/Fonts/CardDisplay-Regular.ttf
create mode 100644 windows/IslandPrototype/Assets/Fonts/CardDisplay-SemiBold.ttf
create mode 100644 windows/IslandPrototype/Assets/Fonts/CardText-SemiBold.ttf
create mode 100644 windows/IslandPrototype/Assets/Fonts/Inter-OFL.txt
create mode 100644 windows/IslandPrototype/Assets/Fonts/IslandText-Medium.ttf
create mode 100644 windows/IslandPrototype/Assets/Fonts/IslandText-SemiBold.ttf
create mode 100644 windows/IslandPrototype/Assets/Fonts/IslandText-Status.ttf
create mode 100644 windows/IslandPrototype/Assets/Fonts/README.md
create mode 100644 windows/IslandPrototype/Assets/antigravity.png
create mode 100644 windows/IslandPrototype/Assets/claude.png
create mode 100644 windows/IslandPrototype/Assets/codexisland.png
create mode 100644 windows/IslandPrototype/Assets/grok.png
create mode 100644 windows/IslandPrototype/Assets/mac-fixture.json
create mode 100644 windows/IslandPrototype/Assets/openai.png
create mode 100644 windows/IslandPrototype/Assets/pricing-seed.json
create mode 100644 windows/IslandPrototype/Assets/tray-dark.ico
create mode 100644 windows/IslandPrototype/Assets/tray-light.ico
create mode 100644 windows/IslandPrototype/Assets/zh-Hans.json
create mode 100644 windows/IslandPrototype/CardTypography.cs
create mode 100644 windows/IslandPrototype/CliAccountActions.cs
create mode 100644 windows/IslandPrototype/CliCredentialWatch.cs
create mode 100644 windows/IslandPrototype/CliCredentials.cs
create mode 100644 windows/IslandPrototype/CliSessionRecovery.cs
create mode 100644 windows/IslandPrototype/CodexAccountReader.cs
create mode 100644 windows/IslandPrototype/CodexResetCredits.cs
create mode 100644 windows/IslandPrototype/ConnectedProviderUsage.cs
create mode 100644 windows/IslandPrototype/CurrencyStore.cs
create mode 100644 windows/IslandPrototype/DataPaths.cs
create mode 100644 windows/IslandPrototype/DatabaseLogScanner.cs
create mode 100644 windows/IslandPrototype/DisplayCatalog.cs
create mode 100644 windows/IslandPrototype/DollarGlowLayer.cs
create mode 100644 windows/IslandPrototype/FooterStatus.cs
create mode 100644 windows/IslandPrototype/FooterStatusLayer.cs
create mode 100644 windows/IslandPrototype/FrameDiagnostics.cs
create mode 100644 windows/IslandPrototype/FullscreenGeometry.cs
create mode 100644 windows/IslandPrototype/GlowSweep.cs
create mode 100644 windows/IslandPrototype/GrokCompatibility.cs
create mode 100644 windows/IslandPrototype/HistoricalUsageDay.cs
create mode 100644 windows/IslandPrototype/HistoryCoordinator.cs
create mode 100644 windows/IslandPrototype/HistoryImport.cs
create mode 100644 windows/IslandPrototype/HistorySummary.cs
create mode 100644 windows/IslandPrototype/IslandAccessibility.cs
create mode 100644 windows/IslandPrototype/IslandPrototype.csproj
create mode 100644 windows/IslandPrototype/IslandTypography.cs
create mode 100644 windows/IslandPrototype/IslandVisual.Pill.cs
create mode 100644 windows/IslandPrototype/IslandVisual.ResetCredits.cs
create mode 100644 windows/IslandPrototype/IslandVisual.cs
create mode 100644 windows/IslandPrototype/LiveUsage.cs
create mode 100644 windows/IslandPrototype/LocalLogScanner.cs
create mode 100644 windows/IslandPrototype/Localizer.cs
create mode 100644 windows/IslandPrototype/MainWindow.Introduction.cs
create mode 100644 windows/IslandPrototype/MainWindow.Motion.cs
create mode 100644 windows/IslandPrototype/MainWindow.xaml
create mode 100644 windows/IslandPrototype/MainWindow.xaml.cs
create mode 100644 windows/IslandPrototype/ModelPricing.cs
create mode 100644 windows/IslandPrototype/Native.cs
create mode 100644 windows/IslandPrototype/NativeSqlite.cs
create mode 100644 windows/IslandPrototype/PageScrollGesture.cs
create mode 100644 windows/IslandPrototype/ParityData.cs
create mode 100644 windows/IslandPrototype/ParityTheme.cs
create mode 100644 windows/IslandPrototype/PillMotion.cs
create mode 100644 windows/IslandPrototype/PlatformActions.cs
create mode 100644 windows/IslandPrototype/PreferenceStore.cs
create mode 100644 windows/IslandPrototype/PreviewSettings.cs
create mode 100644 windows/IslandPrototype/ProviderCredentialParser.cs
create mode 100644 windows/IslandPrototype/ProviderQuotaSelection.cs
create mode 100644 windows/IslandPrototype/ProviderUsageClient.cs
create mode 100644 windows/IslandPrototype/QuotaHistoryStore.cs
create mode 100644 windows/IslandPrototype/SettingsControls.cs
create mode 100644 windows/IslandPrototype/TestAccess.cs
create mode 100644 windows/IslandPrototype/UsageCardSnapshot.cs
create mode 100644 windows/IslandPrototype/UsageCardStudio.cs
create mode 100644 windows/IslandPrototype/UsageCardVisual.cs
create mode 100644 windows/IslandPrototype/UsageFeed.cs
create mode 100644 windows/IslandPrototype/UsageHistory.cs
create mode 100644 windows/IslandPrototype/UsageLedger.cs
create mode 100644 windows/IslandPrototype/WakeScheduling.cs
create mode 100644 windows/IslandPrototype/WindowContext.cs
create mode 100644 windows/IslandPrototype/WindowsCliCredential.cs
create mode 100644 windows/IslandPrototype/WindowsUpdateBackend.cs
create mode 100644 windows/IslandPrototype/app.manifest
create mode 100644 windows/LIVE-PROVIDERS.md
create mode 100644 windows/PARITY.md
create mode 100644 windows/PERFORMANCE.md
create mode 100644 windows/README.md
create mode 100644 windows/UPDATES.md
create mode 100644 windows/VISUAL-REFINEMENT.md
create mode 100644 windows/build-installer.ps1
create mode 100644 windows/publish-release.py
create mode 100644 windows/reference/MacHistoryReference.swift
create mode 100644 windows/reference/MacQuotaReference.swift
create mode 100644 windows/reference/PerformanceMac.swift
create mode 100644 windows/reference/RenderMacReference.swift
create mode 100644 windows/reference/history.sh
create mode 100644 windows/reference/measure-cards.py
create mode 100644 windows/reference/measure-island.py
create mode 100644 windows/reference/performance.sh
create mode 100644 windows/reference/prepare-card-fonts.py
create mode 100644 windows/reference/prepare-island-fonts.py
create mode 100644 windows/reference/quota.sh
create mode 100644 windows/reference/render.sh
create mode 100644 windows/run-parallels.sh
create mode 100644 windows/run.ps1
create mode 100644 windows/tests/build-provider-work.ps1
create mode 100644 windows/tests/card-render/CardRenderTests.csproj
create mode 100644 windows/tests/card-render/Program.cs
create mode 100644 windows/tests/check-account-setup.ps1
create mode 100644 windows/tests/check-alerts.ps1
create mode 100644 windows/tests/check-card-preserved.ps1
create mode 100644 windows/tests/check-card.ps1
create mode 100644 windows/tests/check-codex-reset-ui.ps1
create mode 100644 windows/tests/check-connected-account-setup.ps1
create mode 100644 windows/tests/check-dropdowns.ps1
create mode 100644 windows/tests/check-footer-ui.ps1
create mode 100644 windows/tests/check-installer-upgrade.ps1
create mode 100644 windows/tests/check-interaction.ps1
create mode 100644 windows/tests/check-introduction-startup.ps1
create mode 100644 windows/tests/check-live-pointer.ps1
create mode 100644 windows/tests/check-live-ui.ps1
create mode 100644 windows/tests/check-mac-history-ui.ps1
create mode 100644 windows/tests/check-motion.ps1
create mode 100644 windows/tests/check-native-share.ps1
create mode 100644 windows/tests/check-network-parallels.py
create mode 100644 windows/tests/check-network-recovery.ps1
create mode 100644 windows/tests/check-parity.ps1
create mode 100644 windows/tests/check-performance.ps1
create mode 100644 windows/tests/check-preferences.ps1
create mode 100644 windows/tests/check-quota-profile.ps1
create mode 100644 windows/tests/check-render-cost.ps1
create mode 100644 windows/tests/check-responsive-install.ps1
create mode 100644 windows/tests/check-services.ps1
create mode 100644 windows/tests/check-settings.ps1
create mode 100644 windows/tests/check-startup-data-mode.ps1
create mode 100644 windows/tests/check-swipe.ps1
create mode 100644 windows/tests/check-tooltips.ps1
create mode 100644 windows/tests/check-wake-ui.ps1
create mode 100644 windows/tests/check-window-context.ps1
create mode 100644 windows/tests/choose-antigravity-login.ps1
create mode 100644 windows/tests/compare-island-refinement.py
create mode 100644 windows/tests/compare-renders.py
create mode 100644 windows/tests/diagnose-grok-signin.ps1
create mode 100644 windows/tests/export-codex-schema.ps1
create mode 100644 windows/tests/grok-compat/GrokCompatibilityCheck.csproj
create mode 100644 windows/tests/grok-compat/Program.cs
create mode 100644 windows/tests/inspect-account-login.ps1
create mode 100644 windows/tests/inspect-account-processes.ps1
create mode 100644 windows/tests/inspect-cli-installation.ps1
create mode 100644 windows/tests/inspect-codex-protocol.ps1
create mode 100644 windows/tests/inspect-codex-server.ps1
create mode 100644 windows/tests/inspect-connected-clis.ps1
create mode 100644 windows/tests/inspect-current-usage.ps1
create mode 100644 windows/tests/inspect-live-account-values.ps1
create mode 100644 windows/tests/inspect-native-event-windows.ps1
create mode 100644 windows/tests/inspect-settings.ps1
create mode 100644 windows/tests/inspect-signin-pages.ps1
create mode 100644 windows/tests/live-render/FooterStatusUiTests.cs
create mode 100644 windows/tests/live-render/LiveRenderTests.csproj
create mode 100644 windows/tests/live-render/Program.cs
create mode 100644 windows/tests/live-render/QuotaHistoryUiTests.cs
create mode 100644 windows/tests/live-render/QuotaSettingsTests.cs
create mode 100644 windows/tests/live-render/ResetCreditUiTests.cs
create mode 100644 windows/tests/live-render/SettingsPageTests.cs
create mode 100644 windows/tests/logic/AccountSetupTests.cs
create mode 100644 windows/tests/logic/AppUpdateTests.cs
create mode 100644 windows/tests/logic/CodexAccountTests.cs
create mode 100644 windows/tests/logic/ConnectedProviderTests.cs
create mode 100644 windows/tests/logic/FooterStatusTests.cs
create mode 100644 windows/tests/logic/HistoryTests.cs
create mode 100644 windows/tests/logic/LiveUsageTests.cs
create mode 100644 windows/tests/logic/LogicTests.csproj
create mode 100644 windows/tests/logic/Program.cs
create mode 100644 windows/tests/logic/QuotaHistoryTests.cs
create mode 100644 windows/tests/logic/WakeRecoveryTests.cs
create mode 100644 windows/tests/mac-history/ImportBoundaryTests.cs
create mode 100644 windows/tests/mac-history/MacHistoryTests.csproj
create mode 100644 windows/tests/mac-history/Program.cs
create mode 100644 windows/tests/measure-live-responsiveness.ps1
create mode 100644 windows/tests/measure-pointer-reference.ps1
create mode 100644 windows/tests/open-card-studio.ps1
create mode 100644 windows/tests/open-mac-history-preview.ps1
create mode 100644 windows/tests/open-provider-settings.ps1
create mode 100644 windows/tests/prepare-grok-compat.ps1
create mode 100644 windows/tests/presentation-probe/PresentationProbe.csproj
create mode 100644 windows/tests/presentation-probe/Program.cs
create mode 100644 windows/tests/probe-graphics-effects.ps1
create mode 100644 windows/tests/probe-grok-x64.ps1
create mode 100644 windows/tests/probe-reset-hover.ps1
create mode 100644 windows/tests/read-codex-account.ps1
create mode 100644 windows/tests/render/Program.cs
create mode 100644 windows/tests/render/RenderTests.csproj
create mode 100644 windows/tests/run-card-render.ps1
create mode 100644 windows/tests/run-live-render.ps1
create mode 100644 windows/tests/run-logic.ps1
create mode 100644 windows/tests/run-mac-history.ps1
create mode 100644 windows/tests/run-presentation-probe.ps1
create mode 100644 windows/tests/run-render.ps1
create mode 100644 windows/tests/run-swipe-render.ps1
create mode 100644 windows/tests/run-visual-render.ps1
create mode 100644 windows/tests/run-window-motion.ps1
create mode 100644 windows/tests/show-preview.ps1
create mode 100644 windows/tests/snapshot-mac-history.py
create mode 100644 windows/tests/snapshot-mac-quota.swift
create mode 100644 windows/tests/start-connected-signin.ps1
create mode 100644 windows/tests/stop-unneeded-signins.ps1
create mode 100644 windows/tests/swipe-render/Program.cs
create mode 100644 windows/tests/swipe-render/SwipeRenderTests.csproj
create mode 100644 windows/tests/test_publish_release.py
create mode 100644 windows/tests/update-mac-history-preview.ps1
create mode 100644 windows/tests/verify-provider-settings.ps1
create mode 100644 windows/tests/visual-render/PillMotionTests.cs
create mode 100644 windows/tests/visual-render/PillTests.cs
create mode 100644 windows/tests/visual-render/Program.cs
create mode 100644 windows/tests/visual-render/RefinementTests.cs
create mode 100644 windows/tests/visual-render/VisualRenderTests.csproj
create mode 100644 windows/tests/window-motion/IntroductionTests.cs
create mode 100644 windows/tests/window-motion/Program.cs
create mode 100644 windows/tests/window-motion/ReferenceSweep.cs
create mode 100644 windows/tests/window-motion/WindowMotionTests.csproj
create mode 100644 windows/tests/window-motion/app.manifest
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 38656170..4c108c37 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -16,6 +16,15 @@ jobs:
# against the previous tag. Default shallow checkout sees only HEAD.
fetch-depth: 0
+ - name: Validate production release version
+ run: |
+ set -euo pipefail
+ VERSION=$(tr -d '\n\r' < VERSION)
+ if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ || "$GITHUB_REF_NAME" != "v$VERSION" ]]; then
+ echo "::error::Production releases require an exact vX.Y.Z tag matching VERSION. Share beta installers privately."
+ exit 1
+ fi
+
- name: Install create-dmg
run: npm install --global create-dmg
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
new file mode 100644
index 00000000..eaa85f80
--- /dev/null
+++ b/.github/workflows/windows.yml
@@ -0,0 +1,82 @@
+name: Windows installers
+
+on:
+ pull_request:
+ paths: ["windows/**", "VERSION", ".github/workflows/windows.yml"]
+ push:
+ branches: [main]
+ tags: ["v*"]
+ paths: ["windows/**", "VERSION", ".github/workflows/windows.yml"]
+ workflow_dispatch:
+
+permissions:
+ contents: read
+
+concurrency:
+ group: windows-${{ github.event.pull_request.number || github.ref }}
+ cancel-in-progress: ${{ !startsWith(github.ref, 'refs/tags/') }}
+
+jobs:
+ build:
+ name: ${{ matrix.runtime }} installer
+ runs-on: windows-2025
+ timeout-minutes: 25
+ strategy:
+ fail-fast: false
+ matrix:
+ runtime: [win-x64, win-arm64]
+ steps:
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ persist-credentials: false
+ - uses: actions/setup-dotnet@26b0ec14cb23fa6904739307f278c14f94c95bf1 # v5
+ with:
+ dotnet-version: "10.0.x"
+ - name: Verify tag and application version agree
+ if: startsWith(github.ref, 'refs/tags/')
+ shell: pwsh
+ run: |
+ $version=(Get-Content VERSION -Raw).Trim()
+ if($env:GITHUB_REF_NAME -ne ('v'+$version)){throw 'The tag must match VERSION.'}
+ - name: Run Windows logic checks
+ if: matrix.runtime == 'win-x64'
+ run: dotnet run --project windows/tests/logic/LogicTests.csproj -c Release
+ - name: Verify release publishing safeguards
+ if: matrix.runtime == 'win-x64'
+ run: python -m unittest discover -s windows/tests -p test_publish_release.py
+ - name: Build unsigned Windows preview
+ shell: pwsh
+ run: ./windows/build-installer.ps1 -Runtime '${{ matrix.runtime }}' -Unsigned -OutputDirectory '${{ runner.temp }}/windows-installer'
+ - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
+ with:
+ name: windows-${{ matrix.runtime }}
+ path: |
+ ${{ runner.temp }}/windows-installer/*-Setup.exe
+ ${{ runner.temp }}/windows-installer/*.nupkg
+ ${{ runner.temp }}/windows-installer/releases.*.json
+ ${{ runner.temp }}/windows-installer/windows-*.json
+ compression-level: 0
+ if-no-files-found: error
+ retention-days: 14
+
+ publish:
+ name: Attach Windows assets to the existing release
+ if: startsWith(github.ref, 'refs/tags/')
+ needs: build
+ runs-on: ubuntu-latest
+ timeout-minutes: 20
+ permissions:
+ contents: write
+ steps:
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ persist-credentials: false
+ - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
+ with:
+ pattern: windows-win-*
+ path: windows-assets
+ merge-multiple: true
+ - name: Publish installers and update feeds
+ env:
+ GH_TOKEN: ${{ github.token }}
+ run: python3 windows/publish-release.py windows-assets
diff --git a/README.md b/README.md
index 6d8b7e2e..d8930eff 100644
--- a/README.md
+++ b/README.md
@@ -12,21 +12,24 @@
-> Your AI usage limits, living in your notch.
+> Your AI limits. Always in view.
-CodexIsland is a native macOS overlay that turns the MacBook notch into a
-Dynamic-Island-style live activity for Claude Code and Codex usage limits. It
-sits quietly over the notch, peeks on hover with the 5-hour headline, and
-expands on click to show both providers' 5-hour and weekly windows with reset
-timing, chart controls, local-log cost estimates, and a year-at-a-glance usage
-history.
+CodexIsland keeps AI usage, reset times, and local token-cost estimates above
+your work. On macOS it lives in the MacBook notch. On Windows 11 it uses a
+floating pill with quota rings, percentages, and reset countdowns. Hover for
+a quick read; click for usage charts, cost history, and shareable usage cards.
+
+Windows builds include x64 and ARM64 installers. See
+[Windows installation and updates](windows/UPDATES.md) and the
+[Windows compatibility notes](windows/PARITY.md).
https://github.com/user-attachments/assets/195beeff-0f70-4d6b-8f3d-9f31d9c0b989
The app is free, open source, unsigned, and local-first. It reads credentials
-already written by Claude Code / Claude Desktop and Codex, then calls only the
-providers' own usage endpoints.
+already written by CLI tools such as Claude Code and Codex, and asks providers
+directly for usage. Session logs stay on your computer. Pricing, currency,
+and app-update requests are described in the platform documentation.
## What it does
@@ -113,7 +116,7 @@ providers' own usage endpoints.
## Install
-### Homebrew
+### macOS with Homebrew
```sh
brew install --cask ericjypark/tap/codexisland
@@ -123,7 +126,7 @@ The first invocation auto-taps `ericjypark/homebrew-tap`. The cask strips the
Gatekeeper quarantine attribute automatically (CodexIsland is unsigned by
Apple — Sparkle handles update verification independently).
-### Direct download
+### macOS direct download
Download the current `CodexIsland-X.Y.Z.dmg` from the
[latest release](https://github.com/ericjypark/codex-island/releases/latest),
@@ -157,6 +160,19 @@ follow.
5. Click **Open Anyway**, then re-launch the app.
+### Windows 11
+
+Choose the x64 installer for Intel or AMD PCs, or ARM64 for Snapdragon PCs.
+The Windows installers include their runtime; you do not need the .NET SDK.
+After installation, open **CodexIsland** from Start. Sign in to your CLI tools
+first, then select your providers in Settings.
+
+Download Windows installers from the
+[landing page](https://codexisland.com/#install), which lists available releases.
+The current installers are unsigned and may show an unknown publisher warning.
+Updates are downloaded in Settings and installed only when you choose
+**Restart and update**. See [Windows installation and updates](windows/UPDATES.md).
+
## First run
CodexIsland does not ask for passwords or API keys. It reads the auth state
@@ -170,12 +186,11 @@ For Codex:
For Claude:
-- Run `claude` once, or open Claude Desktop, so Claude credentials are
- populated.
-- CodexIsland checks `CLAUDE_CODE_OAUTH_TOKEN`, then
- `$CLAUDE_CONFIG_DIR/.credentials.json` (normally
- `~/.claude/.credentials.json`), then the macOS Keychain item named
- `Claude Code-credentials`.
+- Run `claude` in a terminal and sign in. Signing in to Claude Desktop alone
+ does not populate the CLI credentials.
+- On macOS, CodexIsland checks `CLAUDE_CODE_OAUTH_TOKEN`, then matching Claude
+ Code Keychain items, then `$CLAUDE_CONFIG_DIR/.credentials.json` as a fallback.
+ Windows credential discovery is documented in [LIVE-PROVIDERS.md](windows/LIVE-PROVIDERS.md).
- Credential access is strictly read-only. CodexIsland never refreshes OAuth
tokens or writes to Claude's credential store; run `claude` when an access
token expires, or `claude /login` when the endpoint requires a newly scoped
@@ -231,7 +246,7 @@ changing the app language offers to restart CodexIsland.
## Build from source
-Requires macOS 13+ and a Swift toolchain from Xcode / Command Line Tools.
+For the Mac app, requires macOS 13+ and a Swift toolchain from Xcode / Command Line Tools.
```sh
git clone https://github.com/ericjypark/codex-island
@@ -255,6 +270,9 @@ Smoke test the native app:
test harnesses. `verify.sh` builds the app, launches the binary for one second,
then kills it if it is still alive.
+For the Windows app, see the [Windows build instructions](windows/README.md)
+and [installer packaging](windows/UPDATES.md).
+
## Release
Package a DMG:
@@ -269,7 +287,7 @@ codesigning, creates `dist/CodexIsland-X.Y.Z.dmg`, signs it with Sparkle's
EdDSA key when available, generates `dist/appcast.xml`, and prints the file size
and SHA-256.
-Pushing a `v*` tag triggers `.github/workflows/release.yml` on `macos-15`,
+Pushing an exact `vX.Y.Z` tag matching `VERSION` triggers `.github/workflows/release.yml` on `macos-15`,
builds the signed DMG and appcast, generates release notes from Conventional
Commits, publishes both artifacts in a GitHub Release, and mirrors the cask to
`ericjypark/homebrew-tap` when `HOMEBREW_TAP_TOKEN` is configured.
diff --git a/windows/.gitignore b/windows/.gitignore
new file mode 100644
index 00000000..2a03b9bd
--- /dev/null
+++ b/windows/.gitignore
@@ -0,0 +1,4 @@
+**/bin/
+**/obj/
+**/__pycache__/
+artifacts/
diff --git a/windows/BEHAVIOR.md b/windows/BEHAVIOR.md
new file mode 100644
index 00000000..0d84db50
--- /dev/null
+++ b/windows/BEHAVIOR.md
@@ -0,0 +1,107 @@
+# Alert and window behavior
+
+The Windows implementation now includes the Mac alert decisions and pulse lifecycle, plus native
+full-screen suppression. This is implementation and test evidence, not acceptance as visually or
+functionally identical across every platform condition. Live Codex and Antigravity connections are
+verified; real Claude/Grok account validation remains unavailable. See [LIVE-PROVIDERS.md](LIVE-PROVIDERS.md).
+
+## Alerts
+
+`AlertEngine.cs` follows `Sources/Model/AlertEngine.swift`:
+
+- Severity follows the visible provider's primary limit, using consumed percentage even when the UI
+ displays remaining percentage. Codex falls back to its weekly limit when its five-hour reading is
+ missing; a real zero remains a valid five-hour reading. Claude keeps its five-hour primary.
+- The first completed update establishes crossing memory without a notification. High usage can tint
+ the island immediately. Missing values cannot become a real zero or a threshold crossing.
+- Restored quota values retain severity but cannot create or prune live crossing memory. Each restored
+ provider's first live response establishes its baseline silently, even if another provider already
+ refreshed. An offline restored provider does not suppress fresh alerts from another provider.
+- Warning and critical crossings are remembered separately per provider and reset boundary. Falling
+ below a threshold and recrossing it in the same cycle does not repeat the notification. A changed
+ reset boundary permits a new crossing. Missing reset boundaries preserve existing crossing memory.
+- Simultaneous crossings produce one event containing the affected providers and highest severity.
+ Disabling alerts or using invalid thresholds clears both severity and crossing memory.
+- Normal demo updates retain severity but suppress pulses, as the Mac demo does. The explicit
+ `--preview-alerts` launch flag exposes fixture-injection buttons in General settings for verification.
+ It does not connect accounts or change the demo provenance labels.
+
+An unattended pulse opens a peek, holds it for four seconds, fades the pills over 80 ms, and begins
+closing after a 100 ms wait. Hover, an expanded panel, and Always show usage retain ownership of their
+respective state. Automatic peeks do not activate the window. Expanded panels consume the crossing
+without opening a new peek. Warning and critical use the source amber/red values, including separate
+provider pill colors. Active alerts retain the event glow in Low Power mode.
+
+Hidden-to-peek uses the source opening spring (response 0.42, damping 0.82). Returning from expanded
+uses the closing spring (0.30, 0.88). Pill fades now use the standard ease-out curve. Halo color changes
+use 450 ms ease-in-out and opacity changes use 250 ms ease-in-out; cursor events no longer restart an
+in-flight halo animation toward an unchanged target.
+
+The native pointer tracker also synchronizes reset-credit hover after changing the overlay's
+click-through state. A first move directly into the badge after expansion previously failed to open
+details until a second move. The installed-app test reproduced that failure and passed after the
+correction, including movement into the panel, Escape, and reopening.
+
+## Full screen and visibility
+
+The Mac source pauses its sweep when its native window is occluded. The Windows topmost overlay also
+needs to hide when another foreground application's client area covers its target monitor. It uses
+[window event hooks](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwineventhook)
+for foreground, geometry, minimize, hide, and desktop/cloaking changes. Notifications are coalesced on
+the dispatcher. There is no periodic full-screen polling timer.
+
+The test compares screen-space client bounds against the target monitor. Normal maximized windows
+with a title bar are excluded, as are the desktop/shell, invisible or minimized windows, and this
+application's own windows. DWM cloaking and session lock/suspend state also suppress the overlay.
+While suppressed, it is hidden, click-through, nonactivating, and its glow timer stops. Automatic alerts
+update their severity without revealing the island. On restoration, Always show usage returns to peek;
+ordinary hover mode returns to its hidden rest state.
+
+The Windows event and geometry behavior is based on Microsoft's
+[event constants](https://learn.microsoft.com/en-us/windows/win32/winauto/event-constants),
+[client coordinates](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getclientrect),
+[screen conversion](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-clienttoscreen),
+and [DWM attributes](https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute).
+
+## Verification
+
+`run-logic.ps1` includes the original alert and monitor-geometry cases plus six saved/live alert
+regressions, within the current 350-check suite.
+The alert checks cover warmup, deduplication, escalation, reset changes, hidden providers, absent and
+invalid readings, rounding, demo suppression, re-enabling, and primary-limit selection. Geometry checks
+include negative monitor coordinates, another display, a spanning client, and a maximized title bar.
+
+`check-alerts.ps1` drives the running app through its Settings controls. It verifies pulse timing, focus,
+hover and expanded ownership, per-provider severity, disabling, Low Power, and full-screen suppression.
+All 19 checks passed on build `bd18c691-39e5-40aa-b103-1317526a7064`.
+The full-screen alert case schedules a fixture update three seconds later, then gives the full-screen
+window foreground focus. This tests a background update without activating the Settings button mid-test.
+`check-window-context.ps1` creates a real WinForms window, changes between ordinary, maximized, and
+borderless full-screen states, and checks both app state and pixels copied from the Windows desktop.
+Both scripts preserve preferences and return the preview to a normal launch without fixture controls.
+
+The full-screen sequence passed 17 checks on build `ec2654be-baea-4352-b43a-a709a8f5f046` in Windows 11
+ARM in Parallels at 200% scaling. The screenshot
+at the island's position contained the full-screen application's background without overlay pixels.
+The suppressed process consumed 0 ms of CPU during the five-second settled sample. This measurement
+does not establish behavior on a physical PC, battery use, or presentation frame pacing.
+
+The alert test also exposed a hover regression: timed dismissal set the same suppression flag as a
+manual dismissal while the pointer was still inside. A direct return from outside to the trigger could
+then stay hidden. `check-interaction.ps1` gained checks for re-entry and successful expansion before
+testing outside-click dismissal. Both new checks failed before the fix. Suppression now applies only
+when dismissal occurs with the pointer inside the island or its trigger. The harness now returns failure
+when a behavioral assertion fails, rather than only writing the failed assertion to JSON.
+Preference diagnostics are written after the glow predicate updates, so recorded Low Power and sweep
+states describe the same update. Redundant diagnostic writes during that path were removed.
+
+Raw results and captures are in ignored `windows/artifacts/`, with the app build identifier recorded
+in alert/context results. `check-alerts.ps1 -InputOnly` isolates hover after relaunch for investigation.
+
+## Not yet verified
+
+- Actual lock/unlock, suspend/resume, secure-desktop changes, and DWM cloaking transitions.
+- Exclusive Direct3D games, other virtual desktops, display hot-plug, and mixed-DPI physical monitors.
+- A real Windows energy-saver transition and physical presentation timing during alert motion.
+- Pixel-level equivalence of warning symbols, typography, halo kernels, and intermediate animation frames.
+- Alert delivery from live provider updates and durable usage history, which still require their services.
diff --git a/windows/CARD-PARITY.md b/windows/CARD-PARITY.md
new file mode 100644
index 00000000..29d091f8
--- /dev/null
+++ b/windows/CARD-PARITY.md
@@ -0,0 +1,45 @@
+# Share-card design corrections
+
+The Windows card now has dedicated embedded text and display fonts, rounded numeric outlines,
+explicit headline weight, and layout values measured from the existing SwiftUI card. This removes
+the previous dependence on Segoe UI and the accidental regular-weight headline. The Mac production
+card is the reference and was not edited for this work.
+
+The feed, square, and story cards use the Mac's text baselines and section heights. The square API
+amount now fits the source's 82-point line box. Legend rows are 15 points with 10-point spacing;
+the footer is 44.5 points tall; the chart header and canvas are separated by the source's measured
+24-point offset. The footer uses a drawn arrow. Long signatures retain their font size and truncate
+at the trailing edge, sharing the date row's available width.
+
+The portable faces are static Inter instances. Large numeric glyphs use the source card's measured
+advances and cap height. Convex-corner cuts round terminals without eroding strokes or changing
+counters. Cached outlines are reused across preview redraws and exports. Details, licenses, and
+reproduction instructions are in [Assets/Fonts/README.md](IslandPrototype/Assets/Fonts/README.md).
+Apple font files and glyph outlines are not embedded. Inter's glyph shapes and Windows rasterization
+still differ from SF; these changes do not establish pixel-identical typography.
+
+## Verification
+
+On Windows 11 ARM in Parallels:
+
+- `tests/run-card-render.ps1`: 30 checks passed across the six format/metric combinations and seven
+ additional cases. The embedded font faces resolve from the application resources. Full-resolution
+ dimensions and card margins hold for White/Black/Blue, sub-cent amounts, very large amounts,
+ partial pricing, unpriced usage, Korean signatures, and long signatures.
+- `tests/check-card-preserved.ps1`: all 12 installed-app interaction checks passed on build
+ `077a0186-8459-4d0c-873e-ba8a5a58da2a`. These cover opening the studio, all six PNG exports,
+ Fit/Actual size, signature length, copying the caption and image, and disabling export when no
+ providers are selected. The wrapper restores the prior preferences and live/demo mode.
+- Fixed-fixture renders are under `artifacts/card-after/`. For all six formats, the background,
+ final chart marker, and first legend-dot position agree with the Mac reference to within two
+ sRGB channel levels at the measured coordinates. Color profiles are honored before comparing
+ the Mac and Windows PNGs. These anchor checks are not a visual similarity percentage.
+
+`reference/measure-cards.py` instruments a separate copy of `WeeklyUsageCard.swift` to record actual
+SwiftUI layout frames. It writes only the Windows reference artifacts. The fixed fixture retains
+September 5-11 so typography and layout comparisons remain stable across midnight. Installed-app
+exports use the card studio's current calendar period and can therefore contain different dates.
+
+Rendered results were inspected for all six combinations and the edge cases. Exact font identity,
+all possible personal signatures, and differences in system color-management/rasterization remain
+outside the verified equivalence above.
diff --git a/windows/HISTORY.md b/windows/HISTORY.md
new file mode 100644
index 00000000..f4e01533
--- /dev/null
+++ b/windows/HISTORY.md
@@ -0,0 +1,135 @@
+# Windows local usage history
+
+Live mode now reads local session usage, retains it in a Windows-owned SQLite ledger, and supplies the
+Cost page, model breakdowns, Overview calendar, and usage-card studio. This is independent of quota
+authentication. A missing quota login does not erase recorded usage, and hiding a provider does not
+stop its history scan. The first launch opens the labeled demo; the account action in Providers switches
+to live data and remembers that choice for the desktop shortcut.
+
+## Sources and identities
+
+The readers follow the corresponding Mac source contracts. They do not copy Mac logs or credentials.
+An explicit history import can merge a Mac ledger containing usage metadata and counts.
+
+| Source | Windows paths | Accounting and identity |
+| --- | --- | --- |
+| Codex | `$CODEX_HOME/sessions`, otherwise `%USERPROFILE%/.codex/sessions`; recursive `rollout-*.jsonl` | Each `last_token_usage` delta, with cached input removed from ordinary input. Cumulative session totals are excluded. Basename, timestamp, and occurrence identify a record. |
+| Claude | Each comma-separated `$CLAUDE_CONFIG_DIR/projects`; otherwise `%USERPROFILE%/.claude/projects` and `.config/claude/projects` | Assistant usage, excluding synthetic messages. Message/request IDs deduplicate streaming updates. A later row replaces an earlier row only when all its components dominate; components from different rows are never combined. |
+| Grok | `$GROK_HOME/sessions`, otherwise `%USERPROFILE%/.grok/sessions`; recursive `updates.jsonl` | Completed prompt/model totals, excluding incomplete or partial-cost updates. Prompt/model IDs prevent repeated final updates from adding usage twice. |
+| Antigravity CLI | `%USERPROFILE%/.gemini/antigravity-cli/conversations/*.db` | Generation metadata joined to step timestamps. Stable generation usage IDs deduplicate multi-step usage and copied conversations. |
+| OpenCode | `$XDG_DATA_HOME/opencode`, otherwise `%USERPROFILE%/.local/share/opencode` | SQLite messages plus legacy `storage/message` JSON. OpenAI and Anthropic usage is attributed to Codex and Claude. Persistent fingerprints deduplicate database, legacy, and fork copies. |
+
+JSONL reads are streamed in 64 KiB chunks, with a 1 MiB record limit for Codex/Claude and 2 MiB for Grok.
+An oversized or malformed record does not prevent later complete records from being read. Unchanged
+JSONL files reuse an in-memory size/mtime parse cache. Scans skip directory junctions and symbolic links.
+Database sources open read-only snapshots. Source files and credential stores are never rewritten.
+
+Counts must be nonnegative, bounded integers, with positive total usage and a valid nonfuture timestamp.
+Missing history evidence remains unavailable. Once records establish history, an empty current day can
+correctly show zero. Unknown models retain their token counts and an explicit unpriced-usage notice.
+The Codex reader retains the Mac reader's `gpt-5.4` fallback when a log has no model context; this is an
+estimate, not proof that the session used that model.
+
+## Persistence and refresh
+
+`%LOCALAPPDATA%/CodexIslandPrototype/usage-history.sqlite3` uses Windows' native SQLite engine, WAL,
+full synchronous transactions, and parameterized statements. The ledger stores usage metadata and
+counts, not prompts, completions, or credentials. Hashed event identities and persistent aliases keep
+repeated scans idempotent. Windows timestamps use integer milliseconds. The importer detects the Mac
+schema's timestamps in seconds and converts them, retaining event identities and aliases. Identity
+hashes use UTF-8 byte lengths on both platforms.
+
+A current scan can correct an existing event, including reducing an earlier count. A late scan can add
+new records but cannot overwrite a newer correction. Empty, deleted, truncated, and temporarily
+unreadable source files do not delete retained events. Reads merge the latest committed database state
+before applying a batch, so a stale in-memory view cannot overwrite another writer's newer correction.
+
+If persistence fails, already observed and current records remain available in memory with a visible
+warning. A later successful save commits those unsaved records. Corrupt files and newer schemas are
+preserved rather than replaced. Unsaved records cannot survive process exit, and a corrupt database is
+not claimed to be recovered.
+
+All five sources scan on worker threads and publish independently. History aggregation, including
+recalculation after a price update, also runs off the UI thread. Automatic refresh uses the existing
+5/15/30-minute presets; simultaneous refreshes join one active batch. The footer and card studio can
+request a manual scan. Healthy scans clear stale local-record warnings. The current implementation
+rescans changed files in full and re-aggregates retained events; very large archives still need measured
+performance coverage.
+
+## Import and backup
+
+In live mode, **Settings > General > History backup** offers **Import** and **Back up**. Import accepts
+Mac or Windows schema-1 SQLite ledgers. It validates records, aliases, daily totals, dates, provider
+ownership, and nonoverlapping recovery intervals before committing. Existing events and corrected
+counts are preserved. Duplicate identities and aliases are skipped. A snapshot of existing Windows
+history is saved beside the ledger before an import; invalid merges roll back atomically.
+
+Backups use SQLite's snapshot API, include committed WAL content, and produce a portable database.
+A chosen export is replaced only after its new snapshot finishes. The active database cannot be used
+as its own export destination. Imports wait for an active scan and publish newly aggregated history
+before reporting completion. The actions are disabled in demo mode.
+
+Recovered daily totals retain their source date and timezone interval, including 23- and 25-hour DST
+days. Only the portion missing from observed events is added. Recovered usage has no inferred model,
+timestamp within the day, or API price. It remains explicitly unpriced in value cards and captions.
+An unpriced token is not treated as an unreadable-file error in the footer.
+
+`--data-dir` selects a separate absolute folder for preferences, history, pricing, currency cache, and
+the current-state diagnostic. Restarts preserve that selection. This supports an isolated history
+preview while Windows CLI credentials continue to belong to their own CLIs.
+
+## Prices, dates, and exports
+
+The app includes the Mac source's 33 fallback model rates and reads the same
+[public model catalog](https://ericjypark.github.io/codex-island-model-catalog/v1/models.json).
+Validated prices are cached for 24 hours with conditional requests; automatic failed attempts are
+spaced by six hours. An incomplete or malformed catalog cannot erase the previous table. Catalog
+entries override matching seed rates, while omitted models retain their fallback. The Mac's historical
+Gemini introductory-rate boundary is applied using each event's timestamp.
+
+Amounts are API-rate estimates in USD before display currency conversion. They are not subscription
+charges or actual bills. Input, output, cache creation, and cache reads have separate rates. Unpriced
+tokens stay in totals, add a `+` to partial dollar values, and are identified in card captions. The API
+value card cannot export an entirely unpriced period as a zero-dollar result.
+
+Today, month, calendar days, and rolling card periods use local calendar dates. Model breakdowns use
+rolling five-hour and seven-day windows; their token metric counts input plus output. Overview and
+cards include cache tokens. The calendar combines all four providers regardless of the two header
+selections. Cards refresh when history changes and when the local date changes, without recreating
+the signature field during background updates.
+
+## Verification and remaining work
+
+The 48 history checks in `tests/logic/HistoryTests.cs` use temporary synthetic logs and databases. They
+cover all five readers, duplicate and corrected records, missing logs, corrupt/newer ledgers, failed-save
+recovery, source immutability, malformed data, price caching, DST, partial pricing, and stale warnings.
+The complete logic suite passes 232 checks, including the seven swipe-input regressions.
+
+`tests/run-live-render.ps1` passes 50 checks through the actual WPF surface. It renders synthetic records
+through the real readers, ledger, summary, calendar, model rows, and card exporter. Exact totals persist
+after deleting the temporary source logs and reopening the history service. These are integration
+checks with controlled data, not an actual provider-account session.
+
+An additional Mac-ledger comparison passes 1,774 checks on Windows 11 ARM at 200% display scaling.
+The source snapshot is created through a read-only SQLite connection, with checksums verified after
+copying it into the guest. `reference/history.sh` compiles the actual Mac cost sources and exports the
+reference with a fixed clock, timezone, and price table. The Windows test uses the production importer,
+history coordinator, summaries, calendar, and card renderer. Every positive daily bucket, Today/Month
+total and cumulative point, model row and share, and all five card periods match the Mac result.
+Date-range punctuation uses the Windows interface's hyphen convention. Reimport, portable backup,
+restore, restart without source files, Unicode identities, overlap rejection, and scan/import ordering
+are covered. Native captures include all four cost styles, model layouts, calendar selection, and cards.
+Generated ledgers, personal totals, captures, timing samples, and reports stay in ignored artifacts.
+The running app also passed the native Save/Open dialog flow: a saved backup reimported with zero new
+events or recovered days, while the calendar retained its exact total. These controls were exercised
+in the separate interactive profile, with the original preferences preserved.
+
+Run `tests/run-mac-history.ps1 -Snapshot ` for the comparison. After it passes,
+`tests/open-mac-history-preview.ps1 -Snapshot ` builds a separate interactive app
+profile and creates a **CodexIsland Mac history** desktop shortcut. The ordinary profile remains separate.
+
+Remaining work includes real Windows session-archive validation, desktop-app and WSL discovery,
+recovery directly from Claude daily-statistics files, larger-archive performance, wake/network behavior,
+quota-history curves, reset credits, and remaining provider-account validation. Codex and Antigravity
+live quota requests are covered separately in [LIVE-PROVIDERS.md](LIVE-PROVIDERS.md). The broader motion,
+visual, device, packaging, and update requirements remain in [PARITY.md](PARITY.md).
diff --git a/windows/IslandPrototype/AlertEngine.cs b/windows/IslandPrototype/AlertEngine.cs
new file mode 100644
index 00000000..ad7b7d1a
--- /dev/null
+++ b/windows/IslandPrototype/AlertEngine.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace IslandPrototype;
+
+public enum AlertSeverity {None,Warning,Critical}
+public sealed record AlertWindow(string Provider,bool Visible,double? UsedPercent,DateTimeOffset? ResetAt,bool FromHistory=false)
+{
+ public int? Percent=>UsedPercent is double value&&double.IsFinite(value)
+ ?(int)Math.Round(Math.Clamp(value,0,100),MidpointRounding.AwayFromZero):null;
+}
+public sealed record AlertLine(string Provider,int Percent,DateTimeOffset ResetAt);
+public sealed record AlertPulse(Guid Id,AlertSeverity Severity,IReadOnlyList Lines);
+
+public sealed class AlertEngine
+{
+ private sealed record Crossing(string Provider,AlertSeverity Threshold,DateTimeOffset ResetAt);
+ private readonly HashSet crossings=new();
+ private readonly HashSet awaitingFresh=new();
+ private bool warmedUp;
+ public IReadOnlyDictionary ProviderSeverities {get;private set;}=new Dictionary();
+ public AlertSeverity Severity {get;private set;}
+ public int CrossingCount=>crossings.Count;
+
+ public AlertPulse? Update(IEnumerable windows,bool enabled,int warning,int critical,bool hasUpdated,bool isDemo)
+ {
+ var inputs=windows.ToArray();
+ var severities=new Dictionary();
+ bool valid=enabled&&warning is >=50 and <=98&&critical is >=51 and <=99&&warning=critical)severities[input.Provider]=AlertSeverity.Critical;
+ else if(percent>=warning)severities[input.Provider]=AlertSeverity.Warning;
+ }
+ ProviderSeverities=severities;
+ Severity=severities.Values.DefaultIfEmpty(AlertSeverity.None).Max();
+ if(!valid){crossings.Clear();awaitingFresh.Clear();warmedUp=false;return null;}
+ foreach(var input in inputs)if(input.FromHistory)awaitingFresh.Add(input.Provider);
+ if(!hasUpdated)return null;
+ foreach(var input in inputs)if(!input.FromHistory&&input.ResetAt is DateTimeOffset reset)
+ crossings.RemoveWhere(key=>key.Provider==input.Provider&&key.ResetAt!=reset);
+ var lines=new List();
+ AlertSeverity pulseSeverity=AlertSeverity.None;
+ foreach(var input in inputs) {
+ if(input.FromHistory)continue;
+ bool restored=awaitingFresh.Remove(input.Provider);
+ if(!input.Visible||input.ResetAt is not DateTimeOffset reset||input.Percent is not int percent)continue;
+ bool crossed=false;
+ if(percent>=warning)crossed|=crossings.Add(new(input.Provider,AlertSeverity.Warning,reset));
+ if(percent>=critical)crossed|=crossings.Add(new(input.Provider,AlertSeverity.Critical,reset));
+ if(!crossed||restored)continue;
+ var severity=percent>=critical?AlertSeverity.Critical:AlertSeverity.Warning;
+ if(severity>pulseSeverity)pulseSeverity=severity;
+ lines.Add(new(input.Provider,percent,reset));
+ }
+ bool wasWarm=warmedUp;warmedUp=true;
+ return wasWarm&&!isDemo&&lines.Count>0?new(Guid.NewGuid(),pulseSeverity,lines):null;
+ }
+
+ internal void PreparePreview(){crossings.Clear();warmedUp=true;}
+}
diff --git a/windows/IslandPrototype/App.xaml b/windows/IslandPrototype/App.xaml
new file mode 100644
index 00000000..8d211ce8
--- /dev/null
+++ b/windows/IslandPrototype/App.xaml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/windows/IslandPrototype/App.xaml.cs b/windows/IslandPrototype/App.xaml.cs
new file mode 100644
index 00000000..4effffd5
--- /dev/null
+++ b/windows/IslandPrototype/App.xaml.cs
@@ -0,0 +1,71 @@
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading;
+using System.Windows;
+using Velopack;
+using Velopack.Locators;
+
+namespace IslandPrototype;
+
+public partial class App : Application
+{
+ [STAThread]
+ private static void Main(string[] args)
+ {
+ VelopackApp.Build().SetArgs(args).SetAutoApplyOnStartup(false)
+ .OnBeforeUninstallFastCallback(_=>{
+ if(VelopackLocator.Current.RootAppDir is string root)StartupRegistration.RemoveForInstallation(root);
+ }).Run();
+ var app=new App();app.InitializeComponent();app.Run();
+ }
+
+ private Mutex? instance;
+ internal bool RestartRequested {get;set;}
+ internal bool? RestartLiveMode {get;set;}
+ internal bool RestartProviders {get;set;}
+ internal static bool PreviewAlerts {get;private set;}
+ internal static bool Live {get;private set;}
+ internal static bool IsInstalled=>VelopackLocator.Current.CurrentlyInstalledVersion!=null&&!VelopackLocator.Current.IsPortable;
+
+ protected override void OnStartup(StartupEventArgs e)
+ {
+ base.OnStartup(e);
+ try{DataPaths.Configure(e.Args);}catch(ArgumentException error){MessageBox.Show(error.Message,"CodexIsland");Shutdown();return;}
+ string profile=Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(DataPaths.Root.TrimEnd('\\','/').ToUpperInvariant())));
+ string instanceName=string.Equals(DataPaths.Root.TrimEnd('\\','/'),DataPaths.DefaultRoot,StringComparison.OrdinalIgnoreCase)?"Local\\CodexIslandWindowsPrototype":"Local\\CodexIsland-"+profile;
+ instance = new Mutex(true, instanceName, out bool first);
+ if (!first) { Shutdown(); return; }
+ if(Array.IndexOf(e.Args,"--trace-frames")>=0)FrameDiagnostics.Start();
+ Live=Array.IndexOf(e.Args,"--demo")<0&&Array.IndexOf(e.Args,"--preview-alerts")<0
+ &&(Array.IndexOf(e.Args,"--live")>=0||new PreferenceStore(PreferenceStore.DefaultPath).Value.LiveMode);
+ PreviewAlerts=!Live&&Array.IndexOf(e.Args,"--preview-alerts")>=0;
+ MainWindow = new MainWindow();
+ MainWindow.Show();
+ if(Array.IndexOf(e.Args,"--providers")>=0)Dispatcher.BeginInvoke(new Action(()=>((MainWindow)MainWindow).OpenProviderSettings()));
+ else if(Array.IndexOf(e.Args,"--settings")>=0)Dispatcher.BeginInvoke(new Action(()=>((MainWindow)MainWindow).OpenGeneralSettings()));
+ else if(Live) ((MainWindow)MainWindow).OfferIntroduction();
+ }
+
+ internal static string[] RestartArguments(bool? live=null,bool providers=false,bool settings=false)
+ {
+ var arguments=new List{(live??Live)?"--live":"--demo"};
+ if(providers)arguments.Add("--providers");else if(settings)arguments.Add("--settings");
+ if(DataPaths.IsCustom){arguments.Add("--data-dir");arguments.Add(DataPaths.Root);}
+ return arguments.ToArray();
+ }
+
+ protected override void OnExit(ExitEventArgs e)
+ {
+ FrameDiagnostics.Save();
+ instance?.Dispose();
+ if(RestartRequested && Environment.ProcessPath is string executable) {
+ var start=new System.Diagnostics.ProcessStartInfo(executable){UseShellExecute=true};
+ foreach(string argument in RestartArguments(RestartLiveMode,RestartProviders))start.ArgumentList.Add(argument);
+ System.Diagnostics.Process.Start(start);
+ }
+ base.OnExit(e);
+ }
+}
diff --git a/windows/IslandPrototype/AppUpdates.cs b/windows/IslandPrototype/AppUpdates.cs
new file mode 100644
index 00000000..0e52e6d2
--- /dev/null
+++ b/windows/IslandPrototype/AppUpdates.cs
@@ -0,0 +1,163 @@
+using System;
+using System.IO;
+using System.Text.Json;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace IslandPrototype;
+
+internal enum AppUpdatePhase { Unavailable, Idle, Checking, Current, Available, Downloading, Ready, Installing, Error }
+internal sealed class WindowsUpdateFeedUnavailableException : Exception;
+
+internal interface IAppUpdateRelease
+{
+ string Version {get;}
+}
+
+internal interface IAppUpdateBackend
+{
+ bool IsInstalled {get;}
+ string CurrentVersion {get;}
+ IAppUpdateRelease? PendingUpdate {get;}
+ Task CheckAsync(CancellationToken cancellation);
+ Task DownloadAsync(IAppUpdateRelease release,Action progress,CancellationToken cancellation);
+ void InstallAfterExit(IAppUpdateRelease release,string[] restartArguments);
+}
+
+internal sealed record AppUpdateState(AppUpdatePhase Phase,string CurrentVersion,string? AvailableVersion=null,int Progress=0,string? Error=null,DateTimeOffset? LastChecked=null)
+{
+ internal bool Busy=>Phase is AppUpdatePhase.Checking or AppUpdatePhase.Downloading or AppUpdatePhase.Installing;
+}
+
+internal sealed class AppUpdates : IDisposable
+{
+ internal static readonly TimeSpan CheckInterval=TimeSpan.FromDays(1);
+ internal static readonly TimeSpan RetryInterval=TimeSpan.FromHours(1);
+ private readonly IAppUpdateBackend backend;
+ private readonly string journalPath;
+ private readonly Func now;
+ private readonly CancellationTokenSource lifetime=new();
+ private readonly object stateLock=new();
+ private AppUpdateState state;
+ private IAppUpdateRelease? release;
+ private CheckJournal journal;
+ private int operation;
+ private bool automatic,disposed;
+ internal event Action? Changed;
+ internal event Action? UpdateAvailable;
+ internal AppUpdateState State {get {lock(stateLock)return state;}}
+ internal bool AutomaticChecks {
+ get=>automatic;
+ set {if(automatic==value)return;automatic=value;Changed?.Invoke();}
+ }
+ internal DateTimeOffset NextAutomaticCheck {
+ get {
+ if(journal.LastAttempt is not DateTimeOffset attempt)return now();
+ if(attempt>now())return now();
+ return attempt+(journal.LastChecked==attempt?CheckInterval:RetryInterval);
+ }
+ }
+
+ internal AppUpdates(IAppUpdateBackend backend,string journalPath,Func? now=null)
+ {
+ this.backend=backend;this.journalPath=journalPath;this.now=now??(()=>DateTimeOffset.UtcNow);
+ try {journal=JsonSerializer.Deserialize(File.ReadAllText(journalPath))??new();}
+ catch(Exception error) when(error is IOException or UnauthorizedAccessException or JsonException){journal=new();}
+ release=backend.PendingUpdate;
+ state=new(!backend.IsInstalled?AppUpdatePhase.Unavailable:release==null?AppUpdatePhase.Idle:AppUpdatePhase.Ready,
+ backend.CurrentVersion,release?.Version,LastChecked:journal.LastChecked);
+ }
+
+ internal async Task CheckAsync(bool manual)
+ {
+ if(disposed||!backend.IsInstalled||!manual&&(!automatic||now(){
+ lock(stateLock) {
+ if(disposed||state.Phase!=AppUpdatePhase.Downloading)return;
+ state=state with {Progress=Math.Clamp(value,0,100)};
+ }
+ Changed?.Invoke();
+ },lifetime.Token);
+ if(!disposed)Set(State with {Phase=AppUpdatePhase.Ready,Progress=100});
+ } catch(OperationCanceledException) when(lifetime.IsCancellationRequested) {
+ } catch(Exception error) {
+ if(!disposed)Set(State with {Phase=AppUpdatePhase.Available,Progress=0,Error=FailureMessage(error,true)});
+ } finally {Interlocked.Exchange(ref operation,0);if(!disposed)Changed?.Invoke();}
+ }
+
+ internal bool PrepareInstall(string[] restartArguments)
+ {
+ if(disposed||release==null||State.Phase!=AppUpdatePhase.Ready||Interlocked.CompareExchange(ref operation,1,0)!=0)return false;
+ try {
+ backend.InstallAfterExit(release,restartArguments);
+ Set(State with {Phase=AppUpdatePhase.Installing,Error=null});
+ return true;
+ } catch(Exception) {
+ Set(State with {Error="The update could not start. Try again."});
+ Interlocked.Exchange(ref operation,0);
+ return false;
+ }
+ }
+
+ private void Set(AppUpdateState next)
+ {
+ lock(stateLock){if(disposed)return;state=next;}
+ Changed?.Invoke();
+ }
+ private static string FailureMessage(Exception error,bool downloading)=>error is WindowsUpdateFeedUnavailableException
+ ?"Windows updates have not been published yet. Try again later."
+ :error is InvalidDataException
+ ?"The update could not be verified. Your current version has been kept."
+ :downloading?"The update could not be downloaded. Check your connection and try again."
+ :"Updates could not be checked. Check your connection and try again.";
+ private void SaveJournal()
+ {
+ string temporary=journalPath+"."+Guid.NewGuid().ToString("N")+".tmp";
+ try {Directory.CreateDirectory(Path.GetDirectoryName(journalPath)!);File.WriteAllText(temporary,JsonSerializer.Serialize(journal));File.Move(temporary,journalPath,true);}
+ catch(Exception error) when(error is IOException or UnauthorizedAccessException){}
+ finally {try{File.Delete(temporary);}catch(Exception error) when(error is IOException or UnauthorizedAccessException){}}
+ }
+ public void Dispose()
+ {
+ lock(stateLock){if(disposed)return;disposed=true;}
+ lifetime.Cancel();
+ }
+ private sealed record CheckJournal(DateTimeOffset? LastAttempt=null,DateTimeOffset? LastChecked=null,string? NotifiedVersion=null);
+}
diff --git a/windows/IslandPrototype/Assets/CodexIsland.ico b/windows/IslandPrototype/Assets/CodexIsland.ico
new file mode 100644
index 0000000000000000000000000000000000000000..aa965d860f0f7cb627aced276d6e9581d7843f47
GIT binary patch
literal 40918
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 gbA#x64Q%kKg#>z(@
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
T0K!@900000NkvXXu0mjfp}hGg
literal 0
HcmV?d00001
diff --git a/windows/IslandPrototype/Assets/Fonts/CardDisplay-Medium.ttf b/windows/IslandPrototype/Assets/Fonts/CardDisplay-Medium.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..2e647106815453c0e1945d04650da99b30648b30
GIT binary patch
literal 341156
zcmd?S2b2}X*7vgww5s@l7%yLa_LQbd#w
z|FJ}^TeNI7^~p&~$P6xs48L`!j$OZgX!tBL!%C34b!Y3Y-J0F9X2?rqKR-@1U~I>(
zRjNlnTa-$qrsFIFx?X?H_1!Ku`JKF)J+a+x(C~qy==!e3h^o9nG$g!f;O(RMYB+yx
zXs(-XyL0Hq&aHYAy}Oij(LTe53>;j0Yri5mAMdX{3>k&XMnA`P3v8DfHhk%&CH*y8=bDZh
zdHdLU-CE}+eH`bzf9I$%Lq-krA9)bR??m~4xGyX>MUAngKN?VDtv!xEX
z4(TUQrFp#1CVP7z$&}k`s@l+goP7}G`(I}=RrRJ)4Zki`^{)eMKsV%l4l=5N_fKS~R}p0^tPco6)AzWoMV2ES3&AQ#lj&gA|7P_GA2&j+$s+nC0V?~HT&dwxQh
z|Af`CdOd(^bN&92pK(pj-!1!sr8GTPA4&VKq26DDEVKbW68s9zQPo@;IuXplzU=Hw
zF30EicV)SZ%A)D!AZzxE;0Zm4@z
z%JR0~PLA;j?Jkb?{|Df>hrH1!>t$c?EM50srWxvjIp_a|7f@}Rr8Zw##(Rk-{jc$M
z_Cc>7?kjPEjks_83%vGJ=nw8d`nC9W3miX>ig~R6j%%{dav6UE?8ACN=CNFPVDlFw
zFLsWveqWbU#{Nw8{v+0*Ttm9
z3W{?2U-CTm<-l!18u!cQ-uNr>bM`}X%>uPVgAe0ndPD#BXrkYvclA8Vr`ys5JrP;~
zinL!GnhM^dXiQPYA5Hmk+Uu43=WWc{Z);O^J00AG{=JKCvv;A-W5l*61VcqJ2jq((
z`=3M^K)vO->}m1i`5Y6}JJcIYFb{A#dm6Y8tO6_J%!IzfWuQ-joq+eBio{3m>!>}j}8Z(WC~@P2(D`yhifpM&9JwsBo-#VbMm|GIsFx8rsC9LMl=
z=JU4cm3_ge?5X-t&VDMTpNpk$KpC$44loz*1ru~H*k&i?)k`R!=?wCr96xiMqrv*s
zoHUL(N4eCw>@Q;He*$*=;$L%R-*Vd9%r?oM|M&cVw(U1W*$rGCe()#Nu1H^*|38`j
zZ`C2Vmzw*{F*c{g{Ca|2LU+QK|2{v+c*j`RXuFU-6Pk7f@%-5SQpm5ZH)OAcb_Trf
z1|fR~=9LMI`G#8lw>XWuzKi?qAv|}!OI!8J@DXOJV0vb6@o$dhRn6IFip9(1l>I}q
zzt){mzs@v1raNM3-tHaGFRwdi{{sFpChZBd;bHhr6ysRNdTgxz7t*8tZCSp?--%!A
zUtIU!pOcUO`#E#A|C4sqqM~@N{{z1o75#VEk|=*A9nfd-bKu#dsI5!Ia<>0lnu+t}
zz~}8xMa_@Y|3Af^q5Jq*-Rp>F7(8>@lhoGZ_pyA`!ry~u(9e-R3!R2%Rb~zN0M9J%
z#GhApLl1*KU^w<|&))s-%JBKTQ*=F^O{@BNk7M