Repository navigation
fix(research): preserve reader intent and return focus across reloads - #7864
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
…t-20261102-0008 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.
Reviewer: model_agent · gpt-6.1-sol · OpenAI · runtime_reported · effort=max
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
未发现阻塞性问题。当前审查绑定 7864@e3982b4cdf0a5ce8a85caa9cea36378fe013d497,不继承其他 head 的批准。
动机 / Motivation
在研究页阅读已记录问题的人,需要刷新后继续阅读,并能用键盘回到原路线入口。 从路线打开完整问题后,基线刷新会只剩结论,Escape 也会丢掉原路线标题的位置;当前保存阅读意图和返回入口。 当前 head 刷新后保留完整已记录问题及原结论,Escape 回到同一路线标题;主动折叠和结论直达链接继续保持紧凑阅读。 本结论覆盖现有研究阅读交互;installed App、远端来源组合、完整科学分析及整个仓库资格仍分别验收。
改动思路 / Approach
自动固定 finding 无法表达用户是否仍在读完整问题;将不可推导的阅读意图与 return key 放回现有 Selection,避免第二套 UI 状态漂移。 当前 PR 的边界是原研究页的 URL 恢复与键盘返回,以及原 route-reading 场景的 reload 回归断言。 只保存两个不可从 finding 推出的意图值,比再建全局 store、后端配置或恢复服务更小;保留既有 Node/Finding 链接默认。
实际路径是:Goal workspace Research → GoalResearchWorkbench → GoalResearchHistory → URL selection → 原 Explore history HTTP reader → route/question/finding reader。 只更新浏览器 history 与焦点;没有分析、配置或任务写入。两个真实只读 backend 均回读 mutation_attempts=0、source_unchanged=true。 已读取并判断 repository experience 的任务/恢复视角;当前结论来自本 head 的实际反例与消费路径,不把 recall 或历史意见当验收。
具体改动 / Changes
2 文件 +33/-16:UI production +25/-16;既有 regression scenario +8/-0。 规范依据为 docs/development/design.md,固定 revision 111519a。该文本在实现 diff 前已读取,以下 criterion_id 是对既有段落要求的映射,并未追加整个父 roadmap 的验收。
-
research-reading-intent — implemented:从路线打开完整问题与直接打开 finding 是不同阅读意图,完整原文应可直接阅读。 对应 apps/presentation/dashboard/src/features/personal-workspace/goal-research-history.tsx:21,由当前正/负路径验证。
-
research-reload-history — implemented:reload、Back/Forward 保持选择;Goal 切换保留 Research,返回恢复原选择。 对应 apps/presentation/dashboard/src/features/personal-workspace/goal-research-history.tsx:308,由当前正/负路径验证。
-
research-route-keyboard-return — implemented:路线标题一次进入完整问题,键盘返回同一入口,窄屏正文保持可读。 对应 apps/presentation/dashboard/src/features/personal-workspace/goal-research-history.tsx:279,由当前正/负路径验证。
关键代码讲解
-
selectedFromUrl:恢复 question/returnKey,保留 finding-only 与 node-only 旧链接的区别。
-
select:在现有 URL selection 中写入明确阅读意图和返回键,并保留 history 导航。
-
focusReturn layout effect:优先原 opener,再用保存的 route key 查找重新挂载的同一控件;CSS.escape 保留。
Ego 在显式绑定的 packaged Chat 构建和真实隔离 SQLite/HTTP 上,1200×844 与 390×844 验证完整问题 reload、原 finding 固定及精确路线返回。 验证主动折叠 reload、主动选择 finding reload、legacy finding URL、Back 恢复完整问题、缺失 finding、跨 Goal 仍在 Research 且不继承旧 reader,再 Back 恢复原问题。
对主干的风险 / Risks
把所有 finding URL 都强制展开会破坏原紧凑阅读;本 head 仅在明确 question intent 或无 finding 的旧 node URL 时展开,折叠和 finding 导航都清除该意图。 Dashboard TypeScript/Vite 和 packaged Chat build PASS;conversation-returns PASS;场景 syntax PASS;标准 premerge 4 direct + 5 selected 命令通过,聚合因 quality_stale_receipt FAIL。
PASS:显式区分 base/head 构建后,在真实 SQLite/HTTP、相同 86 条合成历史和 134 条公开 Graph 历史上复现 before/after。基线 reload 后完整问题消失,返回 key 也丢失;head 在 1200 和 390 宽度都保留完整记录与精确返回。原 harness 新断言已审阅并做 syntax 检查,整套 harness 和全部分析状态矩阵没有执行。初次 browser listener 的资产版本不符已排除,后续结论均核过实际加载的构建;英文按 canonical 记录字段逐字比较,未把 fixture 生产前的长输入当作已记录全文。两个 backend 的 mutation_attempts=0、source_unchanged=true。
语义与 CI 对齐
本轮未查询、轮询或等待 CI,远端 CI 的未知原因保持未知。配置范围的质量资格实测为 quality_stale_receipt,standard premerge 聚合仍 FAIL;已通过的 direct/selected 命令与该政策 hold 分别记录,未改写旧 receipt、豁免合并门或声称 ready。实际合并仍须当前精确 head 的独立资格。
我的整体评价 / Verdict
实际整页中,研究图与状态在默认视图居前;选中后完整问题与一条结论组成阅读区,负结果和未知成本可见,来源及全景按需展开,390 宽度正文仍可读。 未验证 installed native App、远端同名 Goal 的来源切换、所有分析状态矩阵和完整 browser harness;英文断言以实际记录字段为准,保留其原有字面省略号。
long_horizon:improved,依据上述恢复/重载与后续读取路径;没有推断模型采用、科学效益或完整成本净益。user_experience:improved。复用既有 owner、边界可独立回退,code_volume 为 necessary、change_proportionality 为 proportionate;无新增 feature-off 承诺或 actor 权限。两个字段属于本地阅读 intent,旧 URL 的默认兼容保留。 当前证据支持 APPROVE,质量/安装/合并限制继续保留。
English verdict: APPROVE — 7864@e3982b4cdf0a5ce8a85caa9cea36378fe013d497; recorded-question intent and exact route focus survive reload; explicit finding/collapse, legacy links and Goal history remain correct on the real isolated reader. The configured quality gate remains held; no merge qualification is claimed.
Problem And Result
A research question opened from the timeline or Graph must remain the same reading view after reload. Previously, automatic finding pinning replaced the complete question with finding-only reading; returning then lost the original caption or Graph-node keyboard position. This change preserves reading intent and a stable return address in the existing Goal-scoped URL selection.
Explicit collapse and direct finding selection remain compact. Legacy finding links stay compact; node-only links open the complete recorded question. Graph activation supplies its return address independently of native button-focus behavior.
Author Declaration
docs/development/design.md; the original reload defect was reproduced at111519af76e56141c56eb7a27443da59def775b9. The Graph return defect was additionally reproduced ate3982b4cdf0a5ce8a85caa9cea36378fe013d497.2607182eddef38906d9292df345a4a8e07155d42. This branch incorporates targetmainat8a9e116283df2796926ea153241f48c9c8fc3dbb; the PR diff remains two files.data-research-returnlookup and persisted local key; Graph passes the activated node key explicitlyScope And Continuation
The complete, independently reversible author proposal changes the existing reader and its regression scenario. It introduces no new graph, analysis, configuration, persisted authority or provider owner. Broader workbench acceptance, installed native App qualification and complete repository validation remain open. This PR is ready for review; merge and installation remain held.
Validation
The current source was built with its own Python environment and served through a real disposable SQLite/HTTP history owner. The served Chat asset was
index-3exALtVR.js. Inputs are synthetic and public archived fixtures, not live experiments. There were no model calls, mutation attempts or source-hash changes.test:conversation-returnsf80fb06024d5ffec5f67d162fbf1c8f70d3a307aa733aba1e330d1b55fbf1dd4, receiptcqr_f80fb06024d5ffec5f67; required gaps and failed broad diagnostic below remain blockinge3982b4stopped after 7,388 passed, 6 failed and 439 skipped out of 32,814 selected. It was interrupted after the Graph defect required a new candidate. An earlier inherited-provider-contaminated run also failed and is preserved separately. No full-suite pass or baseline waiver is claimedruff checkdiagnosticTest-harness recovery: two initial trailing snapshot calls used unsupported options after their semantic assertions had completed. Those failed attempts were preserved. The API calls were corrected and both focused scripts reran successfully; they are separate from the unrun complete browser harness. Ambient provider configuration was removed only from the isolated Python test child after a two-case control and four explicit-provider contract arms; production configuration was not changed.
An advisory frontstage build at the earlier head also failed on a
.pydownload being resolved as a page directory. Immutable checker-subpath controls reproduce that classification at the original base and earlier head, with JSON-asset/page controls passing. This limited diagnosis does not qualify the complete exporter or waive its failure; no unrelated site code is included here.Current Visual Evidence
All screenshots below are actual packaged UI captures inspected at the current head, except the explicitly labeled Graph-before captures from
e3982b4. Data is synthetic/public; no operating state or generated media is committed. The full question remains above the recorded finding, and negative/unknown outcome text stays readable. The populated history retains multiple routes and mixed recorded statuses. The Graph remains an explicitly scrollable canvas at 390; reading views fit the document width. These captures do not qualify model-analysis states or the installed App.Graph return after reload: before closes onto the canvas; after resolves the activated node. DOM assertions verify the exact focused element, including click activation that does not focus the opener. Screenshots show the surrounding composition; they are not a substitute for those assertions.
e3982b4)Earlier source-base comparison for question persistence (111519a → e3982b4)
Default populated history and English recorded-question reading at 390:
Boundaries