fix(ios-simulator): release disabled Host and settle WDA fallback - #2494
fix(ios-simulator): release disabled Host and settle WDA fallback#2494horizon554 wants to merge 5 commits into
Conversation
Signed-off-by: JiangJiahao <jiangjiahao@xd.com>
Signed-off-by: JiangJiahao <jiangjiahao@xd.com>
Signed-off-by: JiangJiahao <jiangjiahao@xd.com>
|
| Filename | Overview |
|---|---|
| apps/desktop/src/main/mcp-integrations/ios-simulator.ts | 新增 scoped/global deactivation 和 Host 释放流程,但 scoped 清理仍使用进程级 closing 标志,导致跨项目访问中断。 |
| apps/desktop/src/main/cindy-brain/index.ts | 在 capability provider 停用或卸载后触发全局或项目级 Simulator 清理,并保留失败重试所需资源。 |
| apps/desktop/src/main/maker-host/agent-shell-policy-server.ts | 新增带 token 的 loopback policy server,使 shell shim 能按实时项目与 Host 状态决定放行。 |
| apps/desktop/src/main/maker-host/agent-shell-guards.ts | 将静态 Simulator 命令拦截改为 fail-closed 的动态 policy 查询。 |
| packages/ios-simulator-runtime/src/native-sidecar/process-manager.ts | 将 Native Sidecar preflight 失败收敛为稳定失败状态,以便 WDA 接管兼容路径。 |
| apps/desktop/src/renderer/features/right-sidebar/plugins/ios-simulator/IOSSimulatorTabBody.tsx | 仅在 Native 实际 probe 时展示检测状态,并根据稳定 route status 选择输入适配器。 |
Sequence Diagram
sequenceDiagram
participant A as 项目 A 设置
participant D as deactivateIOSSimulatorHost
participant H as 共享 Host
participant B as 项目 B
A->>D: "projectWorkingDirs=[A]"
D->>D: "defaultIOSSimulatorRuntimeClosing=true"
D->>H: 清理 A 的 binding
B->>D: 查询状态或初始化 Host
D-->>B: Host is shutting down
Note over H,B: B 的 binding 仍保留,但访问被进程级标志阻断
D->>D: "清理完成后 closing=false"
Prompt To Fix All With AI
### Issue 1
apps/desktop/src/main/mcp-integrations/ios-simulator.ts:6754
**项目清理关闭全局 Host**
当项目 A 执行异步 capability 清理时,这里无条件设置进程级 `defaultIOSSimulatorRuntimeClosing`;项目 B 即使仍显式启用该能力且 binding 被保留,其 Host 初始化和插件状态查询也会收到 “The iOS Simulator host is shutting down.”,导致工具调用、状态查询和 Viewer 输入被无关项目的清理中断。
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Reviews (3): Last reviewed commit: "fix(ios-simulator): make Codex shell gua..." | Re-trigger Greptile
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 79f744651d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // Close the actor queues before ownership reconciliation. This is the | ||
| // point at which the shell guard's protection becomes stricter, so no | ||
| // new boot/mutation can race the final sweep. | ||
| await Promise.all([actor.cancelAllLifecycleStarts(), actor.cancelAllMutations()]); |
There was a problem hiding this comment.
Block new actor starts before draining the Host
When a create_instance or attach_device call has already passed assertHostActive() but is still awaiting resolveWorktreeRoot, it has not registered an actor lifecycle start, so this snapshot drain misses it. The operation can then register immediately after the final hasPendingOperations() check; deactivation may conclude that the Host is releasable, dispose it without ownership cleanup, and release the registry lease and shell guard while the new binding/device remains. Add an admission latch that is checked when actor work is registered, or revalidate and drain atomically before releasing the Host.
Useful? React with 👍 / 👎.
| getPluginRegistry, | ||
| onProjectPolicyChanged: async ({ workingDir, id, effectiveEnabled }) => { | ||
| if (id === 'ios-simulator' && !effectiveEnabled) { | ||
| await deactivateIOSSimulatorForBuiltinToolProject(workingDir); |
There was a problem hiding this comment.
Canonicalize project paths before deactivating bindings
When a local session uses a symlinked working directory, project settings are keyed by that symlink path, but simulator bindings store realpath(workDir). Passing the settings path here therefore cannot match instance.worktreeRoot in deactivate(), because normalizeWorkingDirForProjectSettings does not resolve imported/user-managed symlinks; disabling iOS Simulator for that project returns successfully while its binding, Host lease, and shell guard remain active. Resolve both sides to the same canonical identity, or select bindings from the affected sessions rather than comparing these differently normalized paths.
AGENTS.md reference: AGENTS.md:L115-L116
Useful? React with 👍 / 👎.
|
@horizon554 👋 这个 PR 还有 3 条 review conversation 没 resolve(apps/desktop/src/main/mcp-integrations/ios-simulator.ts / apps/desktop/src/main/maker-ipc/register.ts),auto-review 因此暂时跳过、没法继续审查 / 合并。 如果你已经按评论改完或回应了,请到对应 thread 上点 Resolve conversation;全部 resolve 后,下一轮 auto-review 会自动重新审查这个 PR。 |
Signed-off-by: JiangJiahao <jiangjiahao@xd.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3d3bb9e2f3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } | ||
|
|
||
| const pendingCreateEvidenceArmed = pendingCreateEvidence?.isArmed() === true; | ||
| if (!scoped && (actor.listAll().length > 0 || pendingCreateEvidenceArmed)) { |
There was a problem hiding this comment.
Reconcile pending-create evidence during default disable
When the user-default Settings handler disables iOS Simulator, it always passes shouldReleaseProject, which makes this deactivation scoped even when there are no explicitly enabled projects. If an interrupted create has left pendingCreateEvidence armed without a persisted binding, this branch skips reconcilePersistedOwnership(), selects no session to clean, and returns hostCanBeReleased: false without throwing; because the capability is now disabled, no later tool call triggers reconciliation, so the Host lease and shell guard can remain indefinitely and external Simulator/simctl use stays blocked. The default-disable path needs to reconcile this evidence or otherwise arrange a retry before reporting successful cleanup.
Useful? React with 👍 / 👎.
维护者确认本 PR 涉及 iOS Simulator 功能改动(Host 释放与 WDA fallback 修复),触发产品确认门。 确认方式:请维护者直接在 PR 上 Approve;如需修改请 Request Changes,作者改完后重新 Approve 即放行。 讨论 issue:#2530 |
Signed-off-by: JiangJiahao <jiangjiahao@xd.com>
| return Promise.resolve({ hostReleased: true, cleanedInstanceCount: 0 }); | ||
| } | ||
|
|
||
| defaultIOSSimulatorRuntimeClosing = true; |
There was a problem hiding this comment.
当项目 A 执行异步 capability 清理时,这里无条件设置进程级 defaultIOSSimulatorRuntimeClosing;项目 B 即使仍显式启用该能力且 binding 被保留,其 Host 初始化和插件状态查询也会收到 “The iOS Simulator host is shutting down.”,导致工具调用、状态查询和 Viewer 输入被无关项目的清理中断。
Context Used: 使用和PR描述相同的语言进行评论 (source)
Knowledge Base Used: Embedded iOS Simulator Integration
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/main/mcp-integrations/ios-simulator.ts
Line: 6754
Comment:
**项目清理关闭全局 Host**
当项目 A 执行异步 capability 清理时,这里无条件设置进程级 `defaultIOSSimulatorRuntimeClosing`;项目 B 即使仍显式启用该能力且 binding 被保留,其 Host 初始化和插件状态查询也会收到 “The iOS Simulator host is shutting down.”,导致工具调用、状态查询和 Viewer 输入被无关项目的清理中断。
**Context Used:** 使用和PR描述相同的语言进行评论 ([source](https://app.greptile.com/review/custom-context?memory=instruction-0))
**Knowledge Base Used:** [Embedded iOS Simulator Integration](https://app.greptile.com/xindong/-/custom-context/knowledge-base/makecindy/cindy/-/docs/ios-simulator.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f870303558
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (id === 'ios-simulator' && enabled === false) { | ||
| const registry = getPluginRegistry(); | ||
| await deactivateIOSSimulatorForBuiltinToolDefault({ | ||
| // A project-level explicit enable outranks the user default. Keep its | ||
| // active bindings while retiring projects that now resolve disabled. | ||
| shouldReleaseProject: (workingDir) => !registry.isEnabled(id, workingDir), | ||
| }); |
There was a problem hiding this comment.
Prevent stale disable cleanup after re-enabling
When a second PLUGINS_SET_ENABLED invocation re-enables ios-simulator while this awaited deactivation is still running, the new preference is persisted concurrently but does not cancel or supersede the older cleanup. If the disable pass has already selected a matching session, it continues shutting down or deleting that session's simulator and may dispose the Host after the enable call succeeds, leaving the currently enabled capability without its active simulator state. Serialize these writes with teardown or revalidate a preference generation before cleaning each selected session and releasing the Host.
Useful? React with 👍 / 👎.
这次改了什么
摘要
修复 iOS Simulator capability 关闭后 Host 仍长期占用 ownership / shell guard,以及 Native Sidecar 不可用时界面和输入没有稳定降级的问题。
关闭最后一个 capability provider、卸载最后一个 provider,或在「设置 → 内置工具」按用户/项目范围关闭 iOS Simulator 时,Host 会按 scope 清理 Cindy-owned 资源;清理成功后释放 singleton、writer lease 与 shell guard,之后 Agent 可以再次启动外部 Simulator.app /
simctl,重新启用能力时 Host 仍可懒初始化。Codex 的
open/xcrunPATH shim 现在通过当前 Desktop profile 的鉴权 loopback 通道实时复用项目开关与 Host 状态。能力关闭且清理完成后,同一个 Codex 任务无需重建任务或重启 Desktop 即可使用外部 Simulator;重新启用后,同一个 shim 会恢复拒绝外部 Simulator 操作。Native Sidecar 在二进制、完整性或沙箱 preflight 阶段失败时,现在会把 admission 收敛为
failed,而不是一直遗留AWAITING_PROBE。WDA 保持运行并成为稳定兼容路径;右侧栏只在 Native 确实处于 probe 时显示「检测中」,并且 WDA 模式的点击/滑动不再先发送一个必然失败的 Native touch。变更类型
feat新功能fix缺陷修复refactor/perf重构或性能优化docs/test/chore文档、测试或工程维护范围
UI 变化
docs/design-rules/DESIGN.md§11 Voice & Content(进行中状态只用于真实进行中的操作)与 §10 Light / Dark 双模式交付门槛。本次只修正既有状态文案的显示条件,不新增样式、颜色、布局或文案 key;沿用现有主题 token,因此 Light / Dark 实现均未改变。怎么验证的
自动验证
手工验证
未执行的验证
风险
风险分类
影响与回滚
open/xcrunPATH shim、Native Sidecar admission、WDA fallback 与右侧栏 route status / input routing。allow才会转发;通道缺失、超时、鉴权失败、异常响应或 Desktop 正在退出时继续拒绝。提交前检查
git commit -s,见 DCO)