You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
During the real packaged macOS Desktop qualification on 2026-09-30, the native window disappeared while the Desktop main process, Control Plane, Workbench, Chat Host and the owned Build123d provider were still alive.
A later system sample attributed 77 GB of memory to the Desktop main process and showed 42.2 GB of swap in use. A simple RSS sample taken after the window disappeared was much smaller, so the allocator and ownership of that footprint are not yet established. The run also used repeated macOS Accessibility tree inspection; that instrumentation must be isolated from ordinary product use before assigning root cause.
SIGTERM did not terminate the invisible host within 30 seconds. The main process required SIGKILL, and the owned Build123d container was then stopped explicitly. Swap subsequently fell to about 7.5 GB and system-disk availability returned from 36 GiB to about 70 GiB.
This blocks further unattended native qualification.
Confirmed lifecycle mismatch
Deno Desktop 2.9.6 removes the native window before dispatching its JavaScript close event. That event is not cancelable. The current Desktop code instead calls preventDefault(), assumes the window remains visible during resource draining, and offers a retry path that cannot work once the native window is gone.
A local correction now treats close as a one-way notification, performs one bounded cleanup, and exits the invisible host with success or failure. It is not yet packaged or qualified.
Required evidence
Add an external native-test guard that samples process-tree RSS, physical footprint and system swap at a short interval.
Stop the test automatically on abnormal growth. The next run should warn around 4 GB and terminate around 6 GB, or sooner on a steep growth rate or material swap increase.
Compare a short manual journey with a journey using Accessibility inspection to distinguish a product leak from test-instrumentation pressure.
Record memory samples around viewer open/close, Canvas navigation and window close.
Prove that native close drains or terminates the Desktop process, helpers and owned provider within the declared bound; unrelated containers remain untouched.
Update the qualification record with exact observed metrics and keep the result unverified until this passes.
Scope
This issue concerns Desktop host stability and qualification safety. It does not change engineering authority, project truth, MCP operation identity or provider contracts.
Static diagnosis found a concrete unbounded refresh loop in Desktop Chat:
every snapshot parse creates a fresh conversations array;
the polling effect depended on that array;
every completed snapshot therefore restarted the effect and immediately called the binding again, bypassing the intended 250/1000 ms delay;
refresh calls were not serialized.
Local correction now schedules the next poll only after the previous refresh settles, uses the current active/idle state only to select the delay, and shares one in-flight refresh across timer and command callers. Two targeted polling tests and the UI type check pass.
A native memory guard was also added locally. It samples exact process-tree RSS, periodic macOS physical footprint and system swap growth, logs JSONL evidence, and stops only the named PID after declared warning/stop bounds. Three parser/tree tests pass; a smoke test terminated only a disposable sleep target at the configured limit.
The Deno 2.9.6 close-event mismatch is corrected locally as well: close is treated as a one-way notification, bounded cleanup runs once, then the invisible host exits 0 or 1. Seven shutdown tests, targeted lint/format and deno check main.ts pass.
No native app was relaunched for these checks. The causal contribution of the polling loop to the earlier 42.2 GB swap observation remains to be measured under the guard.
Guarded native qualification completed on 2026-09-30 with the locally finalized macOS/arm64 bundle. This remains local, ad-hoc signed work; it is not merged or published.
The first guard implementation was tightened before the app run:
the guard now launches and retains the exact root ChildProcess instead of attaching to a numeric PID;
descendants are pinned by PID plus start time, included in the bound, and verified gone after TERM/KILL escalation;
logging failures cannot bypass a required stop;
ps, footprint, sysctl, and kill subprocesses are time-bounded;
the system swap metric is named and treated as a system-wide net safety bound, not target attribution.
Targeted validation: 3 parser/tree tests, deno check, deno lint, deno fmt --check, an owned-root smoke test, and a resistant parent/child smoke test. The latter required SIGKILL and left neither process alive.
Two guarded native cycles used warning/stop bounds of 4/6 GiB and a 2 GiB system-wide net swap-growth bound:
172.5 s: maximum process-tree RSS 803.1 MiB; maximum macOS tree footprint 248.2 MiB; maximum system-wide net swap growth 0 MiB.
579.3 s: maximum process-tree RSS 837.0 MiB; maximum macOS tree footprint 318.1 MiB; maximum system-wide net swap growth 1,073.8 MiB.
No guard warning or stop threshold fired. The swap increase in cycle 2 is system-wide and cannot be attributed to Casys; the app's own tree metrics stayed bounded.
Both window closes exited the owned Desktop root with code 0. No packaged Desktop, control-plane, Workbench, Chat Host, or Node process remained. The exact owned Build123d container ended stopped (ExitCode 143, OOMKilled false), and the shutdown report recorded stopped: ["build123d"], unresolved: [].
The native reopen restored the persisted standalone conversation, Build123d with 4 tools, the open session whiteboard, and 3 saved results. The persisted layout still contains 3 viewer nodes and the note for the 10 × 10 × 20 mm part. STEP/STL/GLB/source downloads and digests remained unchanged.
This run gives strong evidence that the fixed unbounded snapshot polling loop caused or amplified the earlier runaway behavior: with serialized delayed polling, the same persisted native journey stayed below 1 GiB tree RSS for nearly ten minutes. It does not establish that polling was the only contributor. Large in-flight MCP App resource reads still lack cancellation and remain a follow-up risk.
Activity
superWorldSavior commentedon Sep 30, 2026
Static diagnosis found a concrete unbounded refresh loop in Desktop Chat:
conversationsarray;Local correction now schedules the next poll only after the previous refresh settles, uses the current active/idle state only to select the delay, and shares one in-flight refresh across timer and command callers. Two targeted polling tests and the UI type check pass.
A native memory guard was also added locally. It samples exact process-tree RSS, periodic macOS physical footprint and system swap growth, logs JSONL evidence, and stops only the named PID after declared warning/stop bounds. Three parser/tree tests pass; a smoke test terminated only a disposable
sleeptarget at the configured limit.The Deno 2.9.6 close-event mismatch is corrected locally as well: close is treated as a one-way notification, bounded cleanup runs once, then the invisible host exits 0 or 1. Seven shutdown tests, targeted lint/format and
deno check main.tspass.No native app was relaunched for these checks. The causal contribution of the polling loop to the earlier 42.2 GB swap observation remains to be measured under the guard.
superWorldSavior commentedon Sep 30, 2026
Guarded native qualification completed on 2026-09-30 with the locally finalized macOS/arm64 bundle. This remains local, ad-hoc signed work; it is not merged or published.
The first guard implementation was tightened before the app run:
Targeted validation: 3 parser/tree tests, deno check, deno lint, deno fmt --check, an owned-root smoke test, and a resistant parent/child smoke test. The latter required SIGKILL and left neither process alive.
Two guarded native cycles used warning/stop bounds of 4/6 GiB and a 2 GiB system-wide net swap-growth bound:
No guard warning or stop threshold fired. The swap increase in cycle 2 is system-wide and cannot be attributed to Casys; the app's own tree metrics stayed bounded.
Both window closes exited the owned Desktop root with code 0. No packaged Desktop, control-plane, Workbench, Chat Host, or Node process remained. The exact owned Build123d container ended stopped (ExitCode 143, OOMKilled false), and the shutdown report recorded stopped: ["build123d"], unresolved: [].
The native reopen restored the persisted standalone conversation, Build123d with 4 tools, the open session whiteboard, and 3 saved results. The persisted layout still contains 3 viewer nodes and the note for the 10 × 10 × 20 mm part. STEP/STL/GLB/source downloads and digests remained unchanged.
This run gives strong evidence that the fixed unbounded snapshot polling loop caused or amplified the earlier runaway behavior: with serialized delayed polling, the same persisted native journey stayed below 1 GiB tree RSS for nearly ten minutes. It does not establish that polling was the only contributor. Large in-flight MCP App resource reads still lack cancellation and remain a follow-up risk.