Repository navigation
fix(workspace): preserve focus moved after closing task details - #7807
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
Reviewer: actor_kind=model_agent; model=gpt-6.1-sol; provider=OpenAI; runtime_reported; reasoning_effort=max
执行归属来自最近的宿主记录,bounded read 未验证当前执行活性;这不认证模型权重,也不赋予结论额外权限。
动机 / Motivation
使用工作台查看任务详情、关闭后继续操作其他控件的用户会遇到这个问题。 关闭详情后立刻把焦点移到“交付与依据”,旧版下一帧会把它抢回工作地图节点,随后的回车可能打开错误对象。 修复后保留用户已经移到外部控件的焦点;普通关闭时仍返回原入口,详情读取失败与重试路径也保留。
本 PR 只修复详情关闭时的焦点竞态并校正该测试的安装包来源,不增加界面、配置、权限或发布资格。 整版发布仍需在最终固定源码上完成完整回归、原模型组合、原生 Goal 和实际渠道读回。
改动思路 / Approach
焦点由详情组件根据当前真实 DOM 判断,测试来源复用既有 Python 启动器;无需维护第二份状态或复制包选择规则。 当前 PR 交付一个可逆的关闭交互修复及其真实浏览器反例,保留所有现有关闭回退、原始要求读取和恢复断言。
最有力的反对意见是:原失败也许只是测试按回车前的等待不充分,修复测试即可。但独立反例在关闭与显式聚焦发生于同一事件时,确实观察到旧回调重新聚焦地图节点。这是实际用户可以触发的焦点争抢,单纯等待、增大超时或删除回焦会分别掩盖问题或损失键盘导航。此处只在已有新焦点时停止旧回调,保留原返回目标和备用入口。
具体改动 / Changes
关键代码讲解
closeDrawer,第 281 行:仍先调用原关闭动作,再在原 animation frame 中处理返回;新增判断读取当前activeElement,如果它已在关闭侧栏之外且不是 body,立即返回。其余原入口与备用目标逻辑不变,不写 Goal、任务或授权状态。requestAuthority,第 12 行:复用testPythonCommand的隔离启动及来源断言。先导入、核对实际包,再执行原合成 File authority/HTTP 服务;安装包验收不再有因 cwd 导入源码的旁路。goalWorkMapScenario的关闭用例,第 207 行:真实点击关闭并立即聚焦证据 summary,等待原一帧后用独立activeElement判断验证。地图的全文、来源丢失、重试、截断与窄屏检查保留,未改变截止和 oracle。
判断依据为 docs/development/design.md#accessibility,spec_revision: 70f643153ea773b7bc1ef71bdb06095b0744bd6d,以及同版本的异步详情/关闭焦点约定。
FOCUS-1:implemented。语义 HTML 和键盘焦点可用;普通 pointer/Escape/Enter/More/close 返回入口在原版及精确 head 的真实浏览器场景均通过,新增显式焦点反例在旧版失败、新版通过。FOCUS-2:implemented。保留窄屏键盘与全文访问;390px 和桌面已打包界面均通过原要求读取、不可用来源与恢复检查,并逐张检查实际画面。
两份文件共 +16/-4,其中生产代码仅增加三行。新 helper、协议、状态词表或兼容版本均未增加。查询 base/head 的 returnFocusRef、focus 回调及包选择器,最近 owner 均为现有 ContextDrawer 和 scripts/test-python.mjs;没有把其他独立详情组件的焦点策略一并重构。
对主干的风险 / Risks
最强回归是新判断误阻止普通关闭后的回焦。既有 Task inspector 用例覆盖 pointer、Escape、Enter、More、长要求、失败/错版本读取与重试,以及实际 File authority/Chat HTTP 编辑、冲突草稿和丢失响应恢复;原版和此 head 的对应场景通过,原有断言均未放松。新的竞态断言使用原 DOM 真实关闭回调,不由 mock 直接给出焦点结果。
PASS:精确 head 的源码与新装 Python 3.11 wheel 各三个完整相关场景;规范 bundle、wheel/sdist 与 strict Twine 6.2;标准 Goal premerge 四项直接及五项选择检查;公开边界、差异和双语检查。未查询、轮询或等待 PR CI。旧版全量浏览器运行失败及后来的局部通过均保留,不据局部通过声明整版合格。旧版反例的控制器清理曾遇缓存目录竞争,随后仅清理其自有运行时和命名空间;不把该记录当作成功产品执行。
我的整体评价 / Verdict
problem_context: justified_increment;long_horizon preserved,user_experience improved。没有增加设置、确认或重复准备步骤,用户选择新控件后可继续原工作;原详情与恢复路径保留。实际检查了混合任务状态的桌面工作地图、完整要求侧栏和 390px 全屏详情;原有层级和文字未变,完整要求与不可用说明均可读。焦点改善由 DOM 断言证明,截图本身不证明焦点。 本 PR 不改响应式布局;390px 展开态为附加检查。 未把合成工作区状态当成线上排序、新鲜度或原生 App WebView/live provider 的证据;这些不属于本次变更的验证声明。
焦点由详情组件根据当前真实 DOM 判断,测试来源复用既有 Python 启动器;无需维护第二份状态或复制包选择规则。 当前 PR 交付一个可逆的关闭交互修复及其真实浏览器反例,保留所有现有关闭回退、原始要求读取和恢复断言。 体量与实际风险相称,无持久格式或独立消费者迁移。整版发布验收仍独立,当前 head 可在既有维护者授权及即时 readiness 通过后合并。
English verdict: APPROVE — Head 9610afb fixes the independently reproduced focus race and preserves the inspected return/recovery paths; whole-release qualification remains separate.
Closing Task details schedules a focus restore for the next animation frame. If the user moves focus to another control first, that callback steals it back. In the work map this can send a subsequent Enter key to the old node instead of opening evidence.
This patch preserves focus already moved outside the closing drawer, while keeping the existing return target and fallback. The existing map scenario now reproduces that exact race. Its HTTP authority fixture also reuses
testPythonCommand, so installed-package tests cannot silently import the checkout.Validation at
9610afb0e2568ded1b9bf5f292717ceb5e39d77d:70f643153ea773b7bc1ef71bdb06095b0744bd6d: the old callback selects the map node. The same assertion passes on this head.goal-work-map,task-inspector-returnandworkspace-view-recoveryscenarios pass both in the source environment and against a freshly installed Python 3.11 wheel with packaged UI. Original full-request, unavailable-source/retry, ordinary close/return and desktop/narrow assertions remain.cqr_d50f4205df89b1243d33passes. Public-boundary scan and diff checks are clean.The baseline assertion is an expected negative, not a successful product run. Its temporary cleanup initially raced a compiler-cache flush; owned runtime and namespace cleanup was completed and the original failure retained. No timeout, retry, oracle, or acceptance budget was relaxed. These focused results do not qualify the entire release or claim native App WebView/live-provider coverage.
Visual evidence
Synthetic public fixtures, no live operating data. The primary question is whether closing details lets the user continue at their chosen control. Existing page hierarchy/copy are unchanged. Focus is verified by the DOM assertion; the screenshots show the affected populated desktop view and narrow request readback.
Before: development UI/source backend at the immutable base, with the new failing regression harness only.
After: packaged UI and freshly installed backend at the exact reviewed head.
Narrow-screen full-request readback on that same installed head: