Ending a conversation does not erase work already started in the browser. Closing the whole app to stop one task can affect other projects. I treated disconnecting, stopping work and shutting down normally as operations on different lifetimes.

Disconnect cleans up conversation-side resources

McpClient.disconnect rejects pending replies, closes stdio input and reading and kills the intermediary process. It is not the host's task cancellation command, nor does it close the browser app.

A finally block cleaning up the connection cannot establish that all browser work stopped. A task intended to end needs its finish or stop result checked first. Code should make the ordering meaningful rather than treating object cleanup and workflow cleanup as interchangeable.

Stop targets a specific current execution

Task stop checks the task ID, profile and project before using the existing taskControl cancellation command. An unrelated ID does not stop the current task as a substitute. Programs and notebooks have their own interruption routes.

That scope is smaller than force-closing a window. It distinguishes the work to stop from work to retain. Cancellation cannot undo a remote save already processed by a service, however. Subsequent inspection and cleanup must follow the outcome actually left behind. A UI event recording a cancellation request and an executor reporting that it has actually stopped are different evidence; inspect the latter rather than infer it from the former.

Stop must remain reachable while input is pending

The pipe server limits concurrent ordinary mutations but classifies stop so it is not blocked behind the waiting mutation. Otherwise an input waiting too long could also prevent the user from asking it to stop.

The integration test holds a request pending and checks that a stop request can release it. Its controlled executor cooperates with that stop. This cannot establish immediate termination of every arbitrary Python script. Reachability of cancellation and each executor's actual interruption behavior require different evidence.

Application close considers other projects too

Normal close checks current context and busy state and asks whether other projects are active. A quiet visible screen does not establish an idle background. Ongoing work can cause shutdown refusal.

When closing is allowed, the handler captures drafts, awaits browser-state persistence and schedules window closure. Its closing reply means shutdown was requested. It cannot establish that every state will restore successfully at the next launch. Saving before close and verifying restoration after restart are separate stages.

Separate retained state from a new judgment after reconnecting

The host can retain existing execution state without a conversation connection. New AI judgment still requires the external conversation to reconnect. A program continuing a decided procedure is not the same as an always-present model evaluating a new error.

After reconnection, read the current task and program first and inherit any uncertain outcome. Creating a new connection does not authorize resending the initial request. Distinguishing finished, running and unresolved work is the practical consequence of separate lifetimes.

Explain effects rather than relying on verb names

Disconnect, stop and close all sound like endings, but their scopes differ. Status wording should explain which resource ended and which outcome remains. An instruction to reconnect must not be used interchangeably with a claim that work was cancelled.

This article compares the current client, handler and pipe test. I did not close a user's running app or interrupt a live notebook for review. Separating transport, work and application lifetimes also gives other work tools a concrete basis for avoiding unnecessary whole-app shutdown and misleading completion reports.