Skip to content

[Bug]: Frequent cmd.exe / conhost flashes on Windows from provider probe & VCS process kill paths #2537

Description

@samvdst

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/server

Steps to reproduce

  1. Install T3 Code v0.0.22 on Windows 11.
  2. Open a project with at least one provider (Claude/Cursor/Codex/OpenCode) configured, and a git repo.
  3. Leave the app running and watch the screen.

Expected behavior

No transient cmd.exe / conhost windows appear during normal idle / agent activity.

Actual behavior

Roughly every 5 minutes, a burst of console windows briefly flashes. With Process Monitor I captured 43 short-lived cmd.exe processes in a ~1 second window, all of the form:

C:\WINDOWS\system32\cmd.exe /d /s /c "taskkill /pid <N> /T /F"

In the same window: 114 git.exe → conhost.exe and 9 gh.exe → conhost.exe events from interleaved checkpoint / SCM activity.

Root cause

All flashes route through Effect's NodeChildProcessSpawner.killProcessGroup on Windows, which uses child_process.exec("taskkill /pid <pid> /T /F") — and exec always wraps in %ComSpec% /d /s /c … (no windowsHide). Anything that calls child.kill() on a handle from Effect's spawner produces the flash.

Three v0.0.22 changes added new code paths that hit this on a regular cadence; v0.0.21 didn't:

1. OpenCode probe was rewritten with shell:true + dual SIGTERM/SIGKILL kill (commit 3582288, "Stop OpenCode refresh from leaking serve processes").

apps/server/src/provider/opencodeRuntime.ts:

  • Spawn now sets shell: process.platform === "win32" on opencode serve (was direct in v0.0.21) → cmd.exe wrapper flash on every 5-minute refresh.
  • New terminateChild finalizer unconditionally fires SIGTERM via child.kill({ killSignal, forceKillAfter: "1s" }), sleeps 1s, then SIGKILL — both routed through killProcessGroup on Windows, both flash. Total: 3 cmd.exe events per OpenCode probe, where v0.0.21 had 0.

2. VcsProcess adds an explicit child.kill() finalizer on every git invocation (commit 6d7fe2e, "Introduce pluggable VCS driver foundation").

apps/server/src/vcs/VcsProcess.ts:155:

const child = yield* spawner.spawn(...);
yield* Effect.addFinalizer(() => child.kill().pipe(Effect.ignore));

Effect.addFinalizer(child.kill()) runs on every git scope close, even when git already exited cleanly. child.kill() always tries killProcessGroup first → cmd.exe + taskkill flash per git command. Active consumers via VcsDriverRegistry.make → GitVcsDriver.makeVcsDriverShape():

  • apps/server/src/checkpointing/Layers/CheckpointStore.ts:40-42 — every checkpoint capture (5–10 git commands per agent turn).
  • apps/server/src/sourceControl/SourceControlProviderRegistry.ts:159-171, apps/server/src/sourceControl/BitbucketApi.ts:435, apps/server/src/git/GitWorkflowService.ts (ensureGit, detectGitRepositoryForStatus).
  • apps/server/src/vcs/VcsProvisioningService.ts:46.

The v0.0.21 equivalent (apps/server/src/git/Layers/GitCore.ts) only added an addFinalizer for the trace2 monitor — never an explicit child.kill(). The spawner's internal acquireRelease already no-ops on clean exit, so the new explicit finalizer is redundant on the success path and is what fires the flash on every git command.

3. SSH + Tailscale integrations shell-wrap on Windows (commit 3772fa1, "feat: Hosted Frontend, Tailscale Integration & SSH Lancher").

packages/tailscale/src/tailscale.ts:134,213, packages/ssh/src/command.ts:177, packages/ssh/src/tunnel.ts:982 all spawn with shell: process.platform === "win32" and rely on the same kill path on scope close.

Why the 5-minute burst

makeManagedServerProvider (apps/server/src/provider/makeManagedServerProvider.ts:133-138) has each provider run Effect.forever(sleep(5min) >> refreshSnapshot()).pipe(Effect.forkScoped). All four providers' loops start together at boot and fire roughly synchronously every 5 minutes. ProviderSessionReaper (apps/server/src/provider/Layers/ProviderSessionReaper.ts:12,115) sweeps idle sessions on the same 5-minute cadence, each reaped OpenCode session adding 2 more cmd.exe events. The Multi-Provider per-instance refactor (commit 08e6d4c) means probe count scales with configured instance count.

Suggested fixes (all local; no Effect changes required)

  1. apps/server/src/provider/opencodeRuntime.ts:337 — drop shell: process.platform === "win32" from the opencode serve spawn (v0.0.21 didn't have it).
  2. apps/server/src/provider/opencodeRuntime.ts:356-369 — guard terminateChild so it skips when the child has already exited, or replace killProcessGroup with a plain childProcess.kill(signal) on Windows when the process is still alive.
  3. apps/server/src/vcs/VcsProcess.ts:155 — remove the explicit Effect.addFinalizer(() => child.kill()). The spawner's internal acquireRelease already cleans up non-zero / still-running children.
  4. Broader cleanup: stop passing shell: process.platform === "win32" for binaries that aren't .cmd/.bat shims (most call sites — see processRunner.ts:155, tailscale.ts, ssh/command.ts, ssh/tunnel.ts, the Cursor/Claude/Codex provider probes), and consider upstreaming a windowsHide: true option into @effect/platform-node-shared's NodeChildProcessSpawner.spawn.

Impact

Slows me down / annoying

Version or commit

0.0.22

Environment

T3 Code Desktop v0.0.22 on Windows 11 Enterprise 26200 (10.0.26200).

Logs or stack traces

Process Monitor capture (60s window): 43× cmd.exe /d /s /c "taskkill /pid <N> /T /F", 114× git.exe → conhost.exe, 9× gh.exe → conhost.exe.

Screenshots, recordings, or supporting files

No response

Workaround

No response

Activity

  1. amrbashir commented on May 7, 2026

    @amrbashir

    This is a major productivity annoyance when using a Tiling window manager like komorebi. Windows keep shift around at weird times.

  2. Derpedyea commented on May 15, 2026

    @Derpedyea
    Contributor

    This is happening for me too.

    • VcsStatusBroadcaster.refreshRemoteStatus: ~3.8-4.9s
    • readRemoteStatus: ~3.6-4.6s
    • statusDetails/readStatusDetailsLocal: ~2-3s
    • findLatestPr fails with: Source control provider unknown failed in listChangeRequests
  3. pingu2k4 commented on Jun 20, 2026

    @pingu2k4

    This has been super frustrating for a while now.

  4. CDVolvik commented on Aug 9, 2026

    @CDVolvik
    Contributor

    The console flashes come from @effect/platform-node-shared, not from t3code, which is why the three code fixes suggested above no longer apply — opencodeRuntime and VcsProcess were both refactored since this was filed.

    Two things in NodeChildProcessSpawner cause it:

    • spawn never passes windowsHide, which Node defaults to false, so console executables like git and gh create a conhost window
    • killProcessGroup and killProcessGroupOnExit run taskkill through exec, which always wraps in %ComSpec% /d /s /c and spawns a cmd.exe per kill

    Easy to confirm:

    taskkill via exec()      -> spawnfile: C:\WINDOWS\system32\cmd.exe
    taskkill via execFile()  -> spawnfile: taskkill
    

    Both are still present in beta.105. I opened Effect-TS/effect#7154 to fix them. Once that lands this should clear with a version bump; a patches/ entry would work sooner if you want it before then.

  5. CDVolvik commented on Aug 9, 2026

    @CDVolvik
    Contributor

    Upstream fix is merged: Effect-TS/effect#7154.

    windowsHide is now a documented CommandOptions option that defaults to hiding non-detached children, and the two taskkill calls no longer route through cmd.exe. It is on main but not yet published — the newest beta is 4.0.0-beta.106, which predates the merge, so this should clear here with a version bump once the next one ships.

  6. CDVolvik commented on Aug 11, 2026

    @CDVolvik
    Contributor

    4.0.0-beta.107 shipped on 10 August with the fix in it: see the @effect/platform-node-shared changelog.

    This repo will not pick it up on its own. The catalog in pnpm-workspace.yaml pins effect and the @effect/* packages to 4.0.0-beta.103, so the flashes stay here until that moves. It is four betas rather than one, so I would not assume it is a drop-in bump.

  7. bompus commented on Sep 8, 2026

    @bompus
    Contributor

    Cross-posting from #10818, closed as a duplicate of this one — including a correction to something I asserted there without testing it.

    Correction

    In #10818 I wrote that CREATE_NO_WINDOW / windowsHide: true "suppresses this", where "this" was the console allocation. That is wrong as stated, and I had not measured it. The flag does not prevent the allocation — a conhost.exe child is created either way. It prevents the window.

    Windows 11 Pro 26200. A console-less parent is synthesised in two levels: level 1 spawns level 2 detached, so level 2 has no console to lend, and level 2 then does the real spawn with only windowsHide varying. Measurement is scoped to the exact child PID via ParentProcessId, arms order-reversed across three rounds:

    windowsHide console host allocated peak visible windows
    false conhost.exe (3/3) 1 (3/3)
    true conhost.exe (3/3) 0 (3/3)

    Two methodology notes, because both of my earlier attempts at this returned confident nonsense:

    • The console window belongs to the console client, not to its conhost child — calibration against a deliberately visible cmd.exe gives visibleWindows(cmd)=1 against visibleWindows(conhost)=0. Counting the host reads zero in every arm and looks like evidence that nothing happened.
    • Host-wide process counting is not usable on a busy machine. A control arm that spawned nothing still registered conhost +4/+3/+5, larger than the one-process effect under test.

    So @CDVolvik's diagnosis and the upstream windowsHide default look right to me, and should clear the flashing once the pnpm-workspace.yaml catalog moves off 4.0.0-beta.103.

    One thing I can no longer support: #10818 described the allocation as being handed off to WindowsTerminal.exe -Embedding. In these runs, with delegation set to automatic, the host was conhost.exe every time and I did not reproduce a Windows Terminal handoff. Treat that part of #10818 as unverified.

    What the Effect fix will not clear

    Hiding a window does not remove a spawn, so the process churn behind the flashes survives it. Measured separately: 43.7 process creations per minute while idle — no prompt, no agent running, no terminal open — 238 creations in 327 seconds, attributed by ParentProcessId to the T3 Code PID. The next-largest contributor on the same host in the same window spawned 22.

    Image Count in 327 s
    git.exe 138
    taskkill.exe 75
    gh.exe 21
    other (1 each) 4

    Of the commands that were still readable when the sampler caught them:

     21  gh pr list --head ...                     (~1 every 16 s)
      9  git config --get remote.origin.url
      5  git rev-parse --abbrev-ref --symbolic-full-name
      5  git -C <dir> rev-parse
      5  git --git-dir <dir> fetch
      4  git symbolic-ref refs/remotes/origin/HEAD
      4  git rev-list --count origin/main..HEAD
    

    gh pr list every ~16 seconds is a process start plus an authenticated GitHub API round trip, for state that does not change on that cadence. git config --get remote.origin.url nine times in 5.5 minutes reads a value that changes approximately never. And git --git-dir <dir> fetch on a timer drags git-remote-https.exe and git-credential-manager.exe behind it.

    The 75 taskkill spawns should go away with the Effect fix, since execFile replaces the cmd.exe wrapper — but that is 75 of 238.

    Caveats, so these are not read as more than they are: one 5.5-minute sample, one machine, one repository, so the rate is not established as constant across sessions or repo sizes. The host was not quiet, which inflates host-wide figures but not the per-parent attribution. 90 of the 138 git.exe rows had an empty command line by the time the 250 ms poll caught them, so the totals are exact but the subcommand mix is a sample. Anything shorter than the 250 ms poll interval is missed entirely, so every count here is a lower bound.

    Version: 0.0.41-nightly.20260908.1400. Environment: Windows 11 Pro 10.0.26200, git 2.55.0.windows.5, gh 2.97.0, project is one of ~13 worktrees of the same repository.

    Happy to re-run the spawn sampler against a build with the catalog bumped, if that is useful for separating the two defects.

  8. SkiTee3000 commented on Sep 11, 2026

    @SkiTee3000
    Contributor

    With the catalog now on @effect/platform-node-shared 4.0.0-rc.112 the cmd.exe wrapper is gone (taskkill goes through execFile), but every non-zero exit still produces two taskkill /pid <pid> /T /F runs, each with its own conhost.exe:

    1. childProcess.on("exit") calls killProcessGroupOnExit when code !== 0 (NodeChildProcessSpawner.ts ~L515). Fire-and-forget; the process is already gone, so it does nothing.
    2. The acquireRelease finalizer sees exited && code !== 0 and runs killProcessGroup again (~L484-497). This one is awaited; on my machine the server waits 0.4–4 s for it.

    An ordinary git rev-parse in a non-repository (exit 128) therefore costs two extra process trees. On Windows desktop 0.0.41-nightly.20260908.1414 with 12 projects that is about 5,000 taskkill pairs per day from the background sweeps alone, and it is part of the ~8 s pass time in #11220. Neither taskkill appears in server.trace.ndjson, so the trace does not explain where the pass time goes.

    Two smaller points: taskkill /T /F against a PID whose process has already exited is a PID-reuse hazard, and the wait is unrelated to forceKillAfter, so nothing in T3 config changes it. This is still upstream Effect (a follow-up to Effect-TS/effect#7154): skip both calls when the exit has already been observed, or keep only the finalizer.

  9. SkiTee3000 commented on Sep 18, 2026

    @SkiTee3000
    Contributor

    A cost of the taskkill path that is not a window flash: taskkill /T enumerates Win32_Process through WMI, so every call lands in the shared WmiPrvSE.exe host.

    On 0.0.43-nightly.20260917.1851, idle: 26 taskkill /pid <pid> /T /F in 20 s, all children of the server. In a 30 s sampled profile WmiPrvSE.exe was 7.4% of all busy CPU time on the machine, more than the server process itself (4.6%); taskkill was the only recurring Win32_Process client I could find. None of it appears in server.trace.ndjson.

    Machine-wide effect and measurements: #12498.

    Filed by Claude Code (Claude Fable 5.1), following the t3 triage playbook.

  10. synephi commented on Sep 20, 2026

    @synephi

    Cross-link: Nightly 0.0.43-nightly.20260920.2005 still launches OpenCode through the npm opencode.CMD shim:

    cmd.exe /d /s /c ""%APPDATA%\npm\opencode.CMD" "serve" "--hostname=127.0.0.1" "--port=<ephemeral>""
    

    That is packages/shared/src/shell.ts resolveSpawnCommand returning { shell: true, args } for .cmd/.bat. Node 24 then emits DEP0190, and with Windows Terminal as the default console host it shows up as a C:\WINDOWS\system32\cmd.exe tab (not only a flash).

    Workaround that avoids the shim: set OpenCode binaryPath to %APPDATA%\npm\node_modules\opencode-ai\bin\opencode.exe.

    Dedicated DEP0190 report against the shared helper: #12797

  11. SonyStone commented on Sep 30, 2026

    @SonyStone

    Confirmed on T3 Code Desktop 0.0.44, Windows 11 Home x64 (10.0.26200). This matches the two-taskkill cleanup mechanism described in #2537 (comment) and explains recurring "Some requests are slow" warnings for vcs.refreshStatus on this installation.

    What happened

    A local Git repository with no configured remote repeatedly produced successful vcs.refreshStatus RPCs taking about 19–23 seconds. The warning appears after 15 seconds and returns on later refreshes.

    Diagnosis

    The installed bundle contains @effect/platform-node-shared 4.0.0-rc.115. Its NodeChildProcessSpawner starts taskkill /pid /T /F twice after an observed non-zero process exit:

    1. The exit listener calls killProcessGroupOnExit without awaiting it.
    2. The acquireRelease finalizer calls and awaits killProcessGroup.

    This also happens for normal negative Git probes. For example, git config --get returns exit code 1 when the key is absent. GitVcsDriverCore explicitly permits that result, but the process-spawner cleanup still runs.

    In v0.0.44, runGitCommand is wrapped in Effect.scoped outside its own span. As a result, the inner span ends before the awaited cleanup, while the enclosing GitVcsDriver operation includes that wait:
    https://github.com/pingdotgg/t3code/blob/v0.0.44/apps/server/src/vcs/GitVcsDriverCore.ts#L943
    https://github.com/pingdotgg/t3code/blob/v0.0.44/apps/server/src/vcs/GitVcsDriverCore.ts#L2760

    Evidence

    Across 271 readConfigValue operations in the retained trace window for the affected repository:

    • Median enclosing operation: 1,560.7 ms.
    • Median inner runGitCommand: 106.6 ms.
    • Median time AFTER the inner span ends: 1,457.3 ms.
    • Median time before the inner span begins: about 0.1 ms.

    The medians are computed independently. This is predominantly post-command cleanup, not waiting to acquire the Git semaphore.

    A 19,304 ms refresh contained 26 Git operations; 18 had more than 500 ms between the inner span ending and the enclosing operation ending. Successful probes such as status and listing remote names usually had approximately 0.2–0.3 ms of that overhead.

    Isolated reproduction and control

    A standalone diagnostic process used the process-spawner implementation extracted from the installed bundle, with the original bundled Effect runtime. It ran read-only Git probes against the same repository three times per condition. It did not start a T3 server or modify the installation.

    Commands:

    • git rev-parse --is-inside-work-tree (exit 0)
    • git config --get t3diagnostic.nonexistent (exit 1)
    • git show-ref --verify --quiet refs/heads/t3-diagnostic-nonexistent (exit 1)

    The control condition changed only taskkill handling inside the diagnostic process: calls targeting its own already-exited children completed without launching taskkill. This is a diagnostic intervention, not a proposed general cleanup patch.

    Probe Original spawner, total ms Diagnostic control, total ms
    Existing repository, exit 0 100–112 101–127
    Missing config, exit 1 1,550–1,839 96–101
    Missing ref, exit 1 1,794–1,869 105–132

    In the original condition, each non-zero Git command exited after approximately 81–114 ms and caused exactly two taskkill calls. The observed taskkill callback times were approximately 1.4–1.8 seconds. Across six non-zero commands, that was 12 taskkill launches. The diagnostic control retained the same Git exit codes and removed the long delay.

    The test host was Node 24.14.0 with Git 2.41.0.windows.2. The standalone host is not the desktop Electron runtime, and its Git executable/environment has not been proven identical to the live server's. The live trace independently shows the same post-command delay pattern.

    Fix applied or workaround

    None applied to the live app. All diagnostic processes exited; application settings, installed files, repository configuration, and project contents were unchanged. Skipping cleanup broadly would require separate validation for commands that leave descendants alive.

    I initially filed #14352 before identifying this mechanism. These results connect that report to the existing discussion here.

    Filed by

    Codex (GPT-6 Astra High), through a local diagnostic session using the repository's triage guidance; not launched with npx t3 triage. Private paths, project names, credentials, and chat content are omitted.

  12. Alb11747 commented on Oct 5, 2026

    @Alb11747

    Confirmed on the current nightly: slow refreshes survive the window-hiding fix

    Confirmed again on 0.0.46-nightly.20261005.2667, Windows 11 Pro 10.0.26200. Successful vcs.refreshStatus requests take 17–26 seconds and repeatedly trigger the Some requests are slow / waiting longer than 15s warning.

    This is a follow-up to #2537 and #14352, with fresh measurements from the current installed nightly and an isolated original/control reproduction. #10818 and #14352 were closed as duplicates; #2537 remains open. The report is not claiming a new independent root cause or that the earlier window-hiding fix was absent.

    Steps to reproduce

    1. On Windows, open a local Git repository with no upstream and absent optional branch/hosting configuration keys.
    2. Let T3 refresh VCS status, or focus the window/open its Git action menu to request a refresh.
    3. Watch for the slow-request notification and inspect enclosing Git operation spans versus their runGitCommand children.

    Expected: normal negative Git probes (such as git config --get returning 1 because a key is absent) complete promptly, with no tree-kill work targeting the already-exited Git process. Cancellation cleanup for genuinely live processes still needs to work.

    Actual: the bundled process spawner invokes taskkill /pid <pid> /T /F twice after an observed nonzero exit. One call comes from the exit listener; the second is awaited by the scope finalizer. T3 permits these normal Git results, but that does not bypass cleanup in the lower-level process spawner.

    Live trace evidence

    The affected repository's retained successful refreshes include:

    Refresh duration Raw Git-command spans
    17,299 ms 35
    25,573 ms 34
    23,440 ms 32

    For the 23,440 ms refresh, nine GitVcsDriver.readConfigValue operations had these independently calculated medians:

    • Enclosing operation: 1,097.29 ms.
    • Inner runGitCommand: 114.78 ms.
    • Time before the inner command span starts: 0.06 ms.
    • Time after the inner command span ends: 971.93 ms.

    Successful probes have almost no post-command delay: statusDetailsRemote.branch took 107.87 ms overall, with a 107.57 ms inner span and 0.20 ms afterward. listRemoteNames took 130.55 ms overall, with 130.27 ms inside and 0.22 ms afterward.

    These gaps are predominantly after command execution, not Git semaphore waiting. The Effect.scoped cleanup is outside the inner runGitCommand span, so looking only at that span misses the wait. The refresh also contains branch/PR lookup work and locking, so the entire RPC duration is not attributed solely to cleanup.

    Isolated original/control reproduction

    A standalone Node diagnostic extracted the installed spawner module and used its bundled Effect runtime. It did not start a T3 server or open its database. Three rounds alternated original/control order.

    The control changed only the diagnostic module's taskkill function: when its own captured child was already observed to have exited, the callback completed without launching taskkill. This is a causal diagnostic intervention, not a validated general-purpose cleanup patch.

    Read-only Git probe Exit Original total, ms (3 runs) Diagnostic control total, ms (3 runs)
    Existing repository (rev-parse --is-inside-work-tree) 0 70.73 / 60.64 / 58.36 57.96 / 58.68 / 59.67
    Absent config key (config --get t3diagnostic.nonexistent) 1 657.42 / 668.56 / 661.56 58.02 / 56.65 / 58.79
    Absent ref (show-ref --verify --quiet refs/heads/t3-diagnostic-nonexistent) 1 662.48 / 670.95 / 667.60 57.81 / 57.50 / 59.63

    For the six original nonzero commands:

    • Git execution completed in 56.93–77.96 ms.
    • There were exactly 12 taskkill launches, two per command, all targeting the diagnostic's own already-exited children.
    • Taskkill callbacks took 553.78–611.48 ms.
    • The control preserved the same exit codes and removed the delay. All callbacks and diagnostic processes completed.

    The standalone host was Node 24.21.0, Git 2.55.0.windows.5. It is not the desktop Electron runtime. The actual application's independent traces and process-parent sampling show the same pattern.

    Bounded leak and process check

    A 240-second psutil sampler tracked T3's process tree using PID plus creation time, with a nominal 100 ms process-enumeration interval and approximately two-second resource samples. Other agents/diagnostics were active, so this is not an idle benchmark.

    • 22 observed taskkill launches had the T3 server as their direct parent. The readable launches were in pairs for the same target PID. This excludes GitHub CLI/shell subprocesses started by the diagnostic agent.
    • Process-tree population was 41 at both start and finish, with a peak of 49.
    • Server private memory: 266,006,528 → 263,725,056 bytes; handles 343 → 342; threads 15 → 15.
    • Renderer private memory: 250,089,472 → 249,827,328 bytes; handles 394 → 394; threads 24 → 24.
    • Main desktop private memory: 134,205,440 → 131,534,848 bytes; handles 1162 → 1165; threads 63 → 63.

    No accumulating process, memory, handle or thread leak was demonstrated in this short sample. This cannot rule out a longer-term leak. Short-lived Git children can escape sampling; the 22 taskkill count is a lower bound, not a complete spawn count. No process was terminated as part of the live observation.

    Why the earlier fix did not resolve this symptom

    The installed bundle already uses hidden execFile taskkill calls and contains @effect/platform-node-shared 4.0.0-rc.115. Removing the cmd.exe wrapper and hiding windows does not remove either taskkill invocation or the awaited finalizer delay. Missing Git settings remain valid negative probes but still enter that nonzero-exit cleanup path.

    Effect #7154 fixed hiding/wrapping and shipped in beta.107; the installed dependency is already past that fix. Current upstream cleanup still has both the exit listener and finalizer. Yesterday's merged #8736 changes finalizer escalation but retains the Windows taskkill path; its process-group regression test skips Windows. A dependency bump alone is therefore not a demonstrated fix for this latency.

    T3 source references: scope cleanup outside the raw command span and permitted negative config probes.

    The remaining fix needs to address Windows cleanup of already-exited leaders, while preserving cancellation and cleanup of genuine live descendants. Broadly disabling cleanup has not been validated here.

    Evidence and scope

    Only focused, redacted measurements are included. Private paths, project names, environment identifiers, credentials and chat content are omitted.

    Native Computer Use failed with Access is denied, including after a reset. The Moonlight fallback exited before readiness with code 2; its launcher reported verified cleanup. No new desktop screenshot or UI-driven refresh was obtained. The original warning screenshot and actual retained traces provide the UI symptom evidence.

    No application install, settings, repository configuration or project files were changed. The live app was not restarted. No fix or workaround was deployed.

    Filed by Codex (GPT-6.1 Sol, high reasoning), through T3 Code; local diagnostics, not npx t3 triage.

  13. Alb11747 commented on Oct 5, 2026

    @Alb11747

    I implemented a focused Windows cleanup fix in a fork, based on current upstream cf3e714b0:

    The shared @effect/platform-node-shared taskkill helper now completes immediately once Node has observed the leader's exit (exitCode or signalCode set). This covers both redundant cleanup call sites, including the awaited nonzero-exit finalizer. Running process trees retain the original taskkill path. Source and distribution are patched; no dependency versions or T3 call-site behavior changed.

    Before accepting that change, I reproduced the surviving-grandchild case against the unpatched dependency. A detached grandchild survived with both ignored and inherited stdout, while both taskkills returned exit 128/process-not-found. The patched gate preserved the exact orphan/stdout behavior with zero taskkills: ignored stdout measured 1554 ms before / 139 ms after, inherited stdout 1403 ms / 290 ms including its deliberate drain timeout. Owned fixtures were cleaned and verified gone. This guard does not solve the pre-existing detached-orphan limitation; retained Windows process/job ownership would be separate work.

    Ten Windows regression tests cover successful/nonzero/signaled exits, missing Git config/ref, explicit kill after exit, both orphan stdio modes, and actual running parent + detached-grandchild termination on interruption/timeout/kill. All 39 cleanup + VcsProcess tests passed. The combined current-upstream GitCore run had 154 passed, 1 failed, 1 skipped; the sole failure is the existing Windows-invalid :(exclude)after.ts filename fixture. Targeted lint/typecheck, LF/whitespace checks, frozen-lockfile installation, and desktop build passed.

    I also started a separate ChatGPT desktop app thread for computer-use testing of the built fork, using isolated worktree state/profile and a local no-remote dirty Git fixture. It confirmed main, modified README, +2/-0, and three completed workspace file refreshes without warnings/errors. Full diff viewing was blocked because Changes/Diff are disabled in an unsent draft, so this is not a full GUI pass. No agent prompt or source-control mutation was submitted in the fork.

    Additional computer-use opening of Git action options was reconciled with backend traces. Three explicit ws.rpc.vcs.refreshStatus requests succeeded in 2.453, 3.268, and 2.305 seconds, below the 15-second warning threshold. These isolated-repository timings are runtime evidence for this build, not a guarantee for every repository or every other source of delay.

    A bounded 240-second process/resource recording found 6 processes initially and finally, peak 10. Backend handles remained 312, threads 17, private memory changed from 199.5 MB to 201.9 MB (peak 208.1 MB). Desktop main warmed by about 6.1 MB and 55 handles during UI navigation. No accumulating process population or backend handles were observed; this short recording cannot rule out every leak. Two taskkill launches coincided with live Codex provider probes; live cleanup is intentionally preserved. Very short processes can be missed by 100 ms sampling.

    The fix is in the fork branch; the user's installed Nightly has not been replaced. No PR has been opened. Implementation and validation: GPT-6.1 Sol through the Codex harness in T3 Code, with independent Claude review and a separate ChatGPT app GUI test.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions