Skip to content

Add a native Windows launcher and local service tooling - #21

Open
LeZergan wants to merge 4 commits into
devnoname120:mainfrom
LeZergan:pr/windows-launcher
Open

LeZergan wants to merge 4 commits into
devnoname120:mainfrom
LeZergan:pr/windows-launcher

Conversation

@LeZergan

Copy link
Copy Markdown

Summary

Split out of #20, as requested. This PR has only the Windows launcher and local service tooling. Every file is a new script, plus one installer-test fix, so it can be reviewed and merged on its own. Based on current main (v2.3.29).

Changes

Native launcher

  • Launch Codexify.cmd opens a WPF launcher (scripts/windows-launcher.ps1, windows-launcher-core.ps1, windows-launcher.xaml). The launcher starts the installed service, its saved OpenAI tunnel(s) and the browser companion, then shows live status.
  • scripts/install-windows-launcher.ps1 copies the launcher into %USERPROFILE%\.codexify\launcher and adds desktop and Start menu shortcuts. No admin rights are needed. It runs on Windows PowerShell 5.1 and WPF.
  • The launcher always reuses the existing installation and config. It never provisions tunnels or connectors.
  • See docs/WINDOWS_LAUNCHER.md. The README links it from the install section.

Console start

  • START CODEXIFY.cmd and windows-start-local(-core).ps1 start the installed service in a console. They don't create or change scheduled tasks.

Autowork status

  • windows-autowork-status.ps1, windows-autowork-state-files.ps1 and windows-autowork-team-status.mjs give a read-only snapshot of the service. It covers server and browser readiness, supervisor count, free disk, active goals, last tool activity and retry errors.

Guarded local updates

  • windows-build-agent-update.ps1, windows-activate-agent-update.ps1, windows-install-local-update.ps1 and windows-install-browser-patch.ps1 build and install a local update without interrupting running agent work. windows-agent-update-guards.ps1 checks for that work before anything is replaced.
  • windows-browser-graceful-update.ps1 and windows-stage-browser-patch-on-exit.ps1 defer a browser update until Chrome exits cleanly. They never terminate a live Chrome profile.
  • Supporting helpers: windows-browser-only-native-backup.ps1, windows-live-renderer-priority.ps1, windows-apply-navigation-stall-patch.ps1, windows-update-file-server.cjs.

Installer test

  • scripts/test-windows-installer.ps1 now runs under Windows PowerShell 5.1. $IsWindows is undefined there under StrictMode, and 5.1 wraps captured output at the host width.

Testing

  • scripts/test-windows-launcher.ps1 and scripts/test-windows-start-local.ps1 pass on Windows 11 with Windows PowerShell 5.1.
  • scripts/test-windows-autowork-state-files.ps1 passes.
  • The update-tooling tests (test-windows-agent-update-guards.ps1, test-windows-browser-graceful-update.ps1, test-windows-stage-browser-patch-on-exit.ps1) need PowerShell 7 (#Requires -Version 7.0). They were not run for this PR.

🤖 Generated with Claude Code

Adds a WPF launcher (Launch Codexify.cmd) that starts the installed service,
saved tunnels and the browser companion with live status, a console start
script, autowork status helpers, and guarded local update tooling that never
interrupts running agent work. Every script has a Windows PowerShell test.
Also makes the installer test run under Windows PowerShell 5.1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@devnoname120 devnoname120 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 818a084, including the launcher/service entry points, process ownership checks, update/rollback paths and their split dependencies. Requesting changes for the inline findings.

The launcher is useful, but the bundled maintenance scripts are not ready to merge with it: two update paths accept a pool with an active action as idle, the console start path ignores the configured port, and the staged-agent helpers depend on a private, dated receipt directory with no initialization path in this branch.

Validation: parsed the added PowerShell scripts with PowerShell 7.7 (zero syntax errors); evaluated the actual Browser-Idle function definitions with a two-page health fixture containing one accepted action. Both windows-install-local-update.ps1 and windows-install-browser-patch.ps1 returned true, while Test-AgentUpdateBrowserIdle correctly returned false. This was an isolated function probe, not a Windows deployment or WPF UI run. The Windows/macOS service CI jobs passed. The check job's needless_bool diagnostic is in unchanged agent_automation/store.rs, so I am not attributing that failure to this PR.

Recommendation: keep this open until the update guards and standalone behavior are corrected and covered. The launcher portion is much closer to mergeable than the deployment helpers.

$liveness=Invoke-RestMethod ($descriptor.endpoint.TrimEnd('/')+'/v1/liveness') -TimeoutSec 5 -Headers @{Authorization=('Bearer '+$descriptor.token)}
return [bool]$liveness.available
}
return $health.status -in @('idle','authentication_required') -and -not $health.activeActionId

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Use the pool-aware idle guard before stopping the browser

With #22/#24's pool, an idle free page produces status="idle", activeActionId=null and activeActionIds=["accepted-action"] while another page still owns a Send. This predicate returns true for that real health shape, and the deployment path proceeds to browser stop, interrupting the active action. I reproduced this by evaluating this function with that health fixture; windows-install-local-update.ps1 has the same problem, and windows-browser-graceful-update.ps1 also checks only the singular field. The shared Test-AgentUpdateBrowserIdle helper already rejects this shape, but these paths do not use it. Apply the complete ownership/capacity check consistently before any shutdown, including the final recheck, and add coverage at the updater entry points.

Comment thread scripts/windows-start-local.ps1 Outdated
$client=[Net.Http.HttpClient]::new($handler)
$client.Timeout=[TimeSpan]::FromSeconds(2)
function Read-LocalHealth {
try {return ($client.GetStringAsync('http://127.0.0.1:3000/health').GetAwaiter().GetResult() | ConvertFrom-Json)}catch{return $null}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Read the saved server port for console startup

START CODEXIFY.cmd launches this script against the saved codexify.config.json, but readiness is always polled on port 3000. A valid installation configured with another port starts correctly and then spends 60 seconds polling the wrong endpoint before reporting failure; an unrelated listener on 3000 can also satisfy the wrong readiness check. Read the configured port (using 3000 only as its default), and use it throughout this startup path. The WPF launcher already does this through Get-LauncherSettings.

Comment thread scripts/windows-build-agent-update.ps1 Outdated
param([ValidateRange(1,8)][int]$Jobs=4)
$ErrorActionPreference='Stop'
$repo=Split-Path -Parent $PSScriptRoot
$ready=Join-Path $repo 'browser-companion/artifacts/ready-20261030'

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Remove the dependency on a pre-existing private staging receipt

This path is neither created here nor present in the PR. Start-Process redirects output into it, Save-BuildState writes into it, and the later build path unconditionally reads agent-update.json from it. A clean checkout therefore cannot run the advertised build helper, even with all build tools and an installed service available; the activation helper also requires the same unprovided receipt. Parameterize/create the staging area and provide a documented way to generate its initial receipt, or keep these one-off deployment helpers out of the standalone launcher PR.

LeZergan and others added 3 commits November 13, 2026 13:53
Opens process handles early so exit codes are not null, snapshots chat state
with robocopy to survive long paths, tolerates Chrome's background process
after a clean window close, skips the graceful close when the browser is
already stopped, and starts the existing elevated scheduled task when its
launcher cannot be upgraded without admin rights. Adds -ConfigSet to apply
validated settings before the single restart and -AllowActiveCommands to
update without waiting for every agent command to finish.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Share Test-BrowserPoolUnowned between the agent-update guards, both
  installers and the graceful browser shutdown, including its final
  recheck. A free page can report idle while another page owns a Send.
- START CODEXIFY polls the configured server port instead of 3000.
- Add entry-point coverage for the installers' idle predicates and the
  console port.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Remove windows-build-agent-update.ps1 and windows-activate-agent-update.ps1.
  They were one-off deployment helpers tied to a dated, uncommitted staging
  receipt and cannot run from a clean checkout.
- The renderer priority helper writes its status to ~/.codexify/logs.
- Updater tests use the system temp directory instead of D:/CodexifyBuild,
  and the graceful-shutdown fixture runs its stop helper with the current
  PowerShell host, so it also runs under Windows PowerShell 5.1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@LeZergan

Copy link
Copy Markdown
Author

Thanks for the review. All three findings are addressed:

[P1] Pool-aware idle guard (86ce3af)

  • New shared Test-BrowserPoolUnowned in windows-agent-update-guards.ps1. It requires no singular activeActionId, an empty activeActionIds, and availableActionSlots == actionCapacity. Test-AgentUpdateBrowserIdle now builds on it.
  • Every shutdown path now uses it:
    • Browser-Idle in windows-install-local-update.ps1 and windows-install-browser-patch.ps1
    • windows-browser-graceful-update.ps1, both the initial check and the final recheck after the stop intent
  • New scripts/test-windows-updater-pool-idle.ps1 loads each installer's actual Browser-Idle through the AST and evaluates it against your two-page fixture (one free page, one accepted action). It also covers a list-only shape and a fully idle pool. On the previous head it fails at windows-install-local-update.ps1; it now passes under Windows PowerShell 5.1.

[P2] Console port

  • START CODEXIFY reads the saved top-level port through Get-StartLocalServerPort (3000 when absent; out-of-range values are rejected) and polls that port.
  • Covered in test-windows-start-local.ps1.

[P2] Private staging receipt (bc5502e)

  • Removed windows-build-agent-update.ps1 and windows-activate-agent-update.ps1. They were one-off deployment helpers for a dated receipt and don't belong in this PR.
  • The renderer-priority helper now writes its status to ~/.codexify/logs.
  • The updater tests now use the system temp directory instead of D:/CodexifyBuild.
  • The graceful-shutdown fixture now launches its stop helper with the current PowerShell host, so it also runs under 5.1.

This also picks up d2bf7a6, a set of Windows PowerShell 5.1 fixes from a real deployment of this updater:

  • the null ExitCode without an early .Handle
  • long-path snapshots via robocopy
  • the Chrome background process after the window closes
  • the 30s settle for the stop-exit race
  • the Start-ScheduledTask fallback when the task is admin-owned
  • -ConfigSet and -AllowActiveCommands

Validation on Windows 11 / PowerShell 5.1: test-windows-updater-pool-idle, test-windows-start-local, test-windows-browser-graceful-update, test-windows-clean-stop-exit-race and test-windows-browser-only-native-backup all pass.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants