Repository navigation
fix(desktop): restore guarded Chat adoption and responsive startup - #7737
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; GPT-6.1 Sol; OpenAI; self_reported (host observation unavailable)
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
未发现阻塞本次修复交付的 finding。审查对象为 7737@3cc24fe473e115bb5bae18c0229903afb89fee52;这是作者账户发布的审查结论,不冒称另一位独立审查者,也不是 GitHub 的正式自我批准。
动机 / Motivation
桌面用户打开 LoopX,并进入已绑定的原管家会话时会遇到这个问题。旧服务采用失败或后台检查持锁时,窗口会长时间等待、原会话入口可能超时;修复后启动探针避开慢元数据,只读发现避开修改锁,服务采用仍等待原任务安全结束。已验证打包工作区能打开、只读发现能在后台锁占用期间返回,以及原管理器忙碌时不会被终止。本 PR 不执行账户切换、业务回复或失败任务重放,也不以探针就绪证明模型可用。
生产原服务与已安装 App 的最终采用仍需独立读回;本审查不把隔离打包验收说成生产恢复完成。 这属于 justified_increment:先交付可以打包和验证的机制修复,再独立安装并读回原服务。用户已经明确授权修复,普通打开路径不应再要求复制配置、重输已知信息或增加确认轮次。
改动思路 / Approach
三个机制分别修复同一打开路径上的服务采用、HTTP 就绪和只读发现阻塞;均留在已有责任层,没有第二套队列、授权状态或恢复调度器。本次边界是可打包交付的启动与原会话发现修复,生产安装后的原服务身份和原消息回传由后续采用验收负责。
最强的不发布理由是:增加一个 CLI 选择器和 HTTP 协议,看起来比延长超时复杂,而且移除读锁可能被误解成取消授权。检查实际责任层后,这两个疑问不构成阻塞。新选择器复用已有原管理器和接受任务保护;HTTP 只投影已加载身份;只读发现仍实时核验 Core grant,并在返回前重读同一原子配置。发送仍使用原有执行时保护锁。延长超时既不能建立管理器所有权,也不能消除后台锁,直接杀进程则违反原任务保护。
| 触发 | 旧路径 | 当前路径及停止条件 |
|---|---|---|
| 服务版本不匹配 | 桌面 Python 模板未必识别私有包装 | Core 核验正在运行的原管理器;忙碌/未知则等待 |
| 打开工作区 | 每次读取完整能力信息 | 身份专用探针;旧端点 404 才回退 |
| 打开原会话 | 等待后台修改锁 | 实时身份及授权发现,配置变化则拒绝 |
此表是基于 3cc24fe473e115bb5bae18c0229903afb89fee52 源码的示意,不是执行证据。没有新增规范状态、消息消费者或另一套恢复队列。
具体改动 / Changes
依据 apps/desktop/loopx-control-plane/README.md; docs/development/frontend-delivery.md,规范版本 428f71177db4c0acb87d16ecad2abe555d952e2d,逐项核对:runtime-identity-before-workspace、original-request-continuity、task-first-unavailable-recovery 均为 implemented。判据来自改动前的身份配对、原请求连续性和现有恢复流程,不使用本 PR 新增 README 文案反证自己正确。
关键代码讲解
replace_managed_loopx_chat从实际加载的管理器取得原存储路由,在 ingress fence 内检查全部非终态任务,再重核 PID、端口和路由。只向固定 PID 发 SIGTERM;停止后才请求同一管理器启动,返回仍为readiness_verified:false。队列没有 active 指针也不能被当成空闲。terminate_verified_listener把 macOS Chat 采用交给所选 Core 的 typed receipt。退出码、schema、service 和 status 必须一致;旧 Core、丢失或异常结果均不允许退回直接 kill。原生自己的私有子进程仍由原生命周期负责。probe_on_port优先查询廉价就绪端点,500 ms 期限和冻结身份比较不变。404 才回退旧能力接口。Python 启动器中显式能力配置仍使用完整接口,不能拿 HTTP 就绪代替模型配置可用。local_session_snapshot读取原绑定、实时身份和 Core grant,构建既有会话投影后完整重读配置;选择或撤权变化会拒绝。这里只取消读发现对后台修改锁的等待,没有缓存授权、恢复线程或提交任务。
变更共 20 文件、666 增加/73 删除,包含 colocated 测试、README 和两张有当前文档消费者的合成截图。Chat handler 增长八行,原 module ceiling 失败原样保留;依现有预算决策规则把上限从 2026 调至 2034,余量为零。保留原组合入口比为八行新建转发层更简单,没有删除语义或放宽延迟门限。
对主干的风险 / Risks
最严重风险是把空默认存储当成原工作为空,或在管理器 PID 已变时停止错误进程。原 route/PID 重核、接受任务 fence 和 busy/unknown 分支均已覆盖。真实 disposable launchd 验收中,排队原输入保持逐字节不变且不发信号,原拥有者完成后同一管理器才重启,HTTP 独立读回;该 fixture 不连接 Lark 或启动第二实际消费者。另一个风险是只读授权竞态,最终配置重读以及选择/撤权反例均通过;执行时 fence 未变。
PASS:完整对应代码体 218 Python、86 binding、189 Rust;最终 exact head 的四个关键反例全部通过。旧 probe 在能力读取阻塞时失败,旧 snapshot 在后台锁仍占用时超时,新实现分别通过相同 oracle。重基线及最后改字/媒体没有改变 Python/Rust 测试体,已逐文件核验。既有 3 个平台 skip 和 12 个 ignored 不作为 Windows 或跨平台完成证据。
PASS:最终 standard 的 6 个 direct、10 个 catalog、8 个 risk-profile 和文本边界检查均通过,保持原 120 秒/检查。原始结果为 manual_review_required,原因仅为两张 PNG 不在文本扫描范围;本审查检查了像素、合成来源和 PNG chunks,未发现私人消息、身份、路径、token 或真实运行上下文,且无文本/EXIF metadata。没有把机器结果改写成自动合格。两张截图有 README 直接消费者,其他运行证据未进入提交。
真实打包隔离验收观察到 native ready 为 1.808 秒、交互工作区读回上界 3.594 秒;这是一次样本,不能推广成百分比性能收益。当前 exact-source 原生候选构建及 deep codesign 检查也通过;这仍不等于已安装生产 App 采用完成。最重要的剩余验证是安装后原服务身份与原会话实际可用,而不是追加模型调用或重放历史失败任务。
语义与 CI 对齐
复用既有 accepted-work、身份、grant 词汇;新增 readiness/activation receipt 的名字和权限范围一致。没有扩大 Goal 策略、调度或业务义务。模块 ceiling 属于有证据的回归预算调整,不是硬执行期限或冻结 promotion 指标;原失败保留。本轮按当前 validation contract 使用本地检查,未抓取、轮询或等待 GitHub CI,变化质量 receipt 当前为 disabled。
我的整体评价 / Verdict
long_horizon improved:既有输入、原接收者和后续重试 owner 保留,忙碌不会被重启绕过。user_experience improved:现有授权的打开任务保持零额外确认轮次,等待原因与恢复入口更清楚。实际检查了完整启动恢复页:单一等待状态居中,忙碌与未知状态文案各自明确,诊断仍由原恢复面板承接;窄屏文字完整可读,无新增卡片或视觉层级。截图仅使用合成原生状态,不证明生产服务或业务完成;原生空注册表工作区另有真实打包读回。
结构判断 retain/proportionate:三个机制的责任和默认范围吻合同一打开路径,兼容分支仅保留独立升级服务的 404 回退,当前不需新增持久状态或抽象层。本次边界是可打包交付的启动与原会话发现修复,生产安装后的原服务身份和原消息回传由后续采用验收负责。 本结论不关闭原业务任务、不证明订阅切换,也不清除其他历史失败。主机审查身份观察不可用,保留 self_reported 来源缺口;merge readiness 和生产采用仍分别核验。
English verdict: APPROVE for this exact head; production adoption remains a separate verification step.
Goal and delivered behavior
LoopX can remain on its boot screen when a managed Chat service belongs to a previous runtime. The desktop previously relied on a Python launch-template match, while the real service could use a private bootstrap; full capability discovery also ran on each readiness probe. Opening the original steward conversation could wait behind a long background mutation lock and exceed the UI request deadline.
This change restores the default desktop journey: adopt the installed Chat runtime through Core's existing original-manager guard, use an identity-only readiness probe, and discover the original conversation without waiting for mutation locks. Pending work and unknown state remain visible and retry automatically.
apps/desktop/loopx-control-plane/README.md(runtime pairing, external-service lifecycle and original-conversation boundaries),docs/development/frontend-delivery.md,docs/development/design.mdat 428f711.main/ 428f711. This is a scoped repair; subscription switching, report business completion and protected external actions remain separate.runtime_activation.py, native supervisor; queued/running/unknown cases never signal; idle original-manager restart acceptance/api/chat/readiness; 500 ms native deadline unchanged; blocked-capability counterfactuallocal_session_snapshotandapp_steward_target; final canonical reread rejects changed selection/revocation; sending retains effect-time fencesScope and implementation
update activate --service chat --port PORTperforms no installation. It delegates to the loaded original manager's explicit store route and the existing accepted-work fence. On macOS the native supervisor consumes its typed receipt. An older Core, malformed/lost result, busy work or unknown ownership never enables a raw-kill fallback or another consumer./api/chat/readiness, containing the loaded artifact's frozen identity and HTTP state only. A 404 retains the legacy capabilities fallback; explicit capability/configuration requests still use the full endpoint.Validation at 3cc24fe
manual_review_requiredfor the two PNGs. Their pixels, source fixture and PNG metadata were inspected separately; no private message, identity, path, token or live operating context appears. Exact-head review still decides those holds. Change-quality receipts are disabled by current Goal policy.node --check, Rust formatting, Ruff and diff hygiene passed. Remote CI was not polled under the managed validation contract.Visual evidence
Primary question: why am I waiting, and will the existing request continue? The existing single recovery surface stays in place; no extra card, color or control is added. Busy, unknown and retry states remain distinct, and diagnostics remain under Recovery & updates. Desktop 1120×850 and narrow 390×844 inspected; no horizontal overflow.
These images are synthetic native-state presentation only at 3cc24fe, using the actual boot HTML/CSS/JS. They are consumed by the desktop README; they do not prove service readiness or request completion. The before view uses 428f711. The packaged backend and original-service checks are separate evidence.
Boundaries
No account switch, business reply, failed-Turn replay, receiver wake, grant expansion, data deletion or second original-message consumer. Existing pending/failed/partial requests retain their original owners. RFC and capability semantics are unchanged; these helpers belong to the existing startup/recovery journey. DCO sign-off included; no temporary evidence pack or private operating data is committed.