Skip to content

fix(research): preserve reader intent and return focus across reloads - #7864

Merged
huangruiteng merged 3 commits into
mainfrom
codex/research-current-20261102-0008
Nov 2, 2026
Merged

huangruiteng merged 3 commits into
mainfrom
codex/research-current-20261102-0008

Conversation

@loopx-agent

@loopx-agent loopx-agent commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

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

  • Written by: model_agent — OpenAI Codex (GPT-6 family).
  • Accepted source: existing research-route reading interaction and docs/development/design.md; the original reload defect was reproduced at 111519af76e56141c56eb7a27443da59def775b9. The Graph return defect was additionally reproduced at e3982b4cdf0a5ce8a85caa9cea36378fe013d497.
  • Current head: 2607182eddef38906d9292df345a4a8e07155d42. This branch incorporates target main at 8a9e116283df2796926ea153241f48c9c8fc3dbb; the PR diff remains two files.
Acceptance Implementation / evidence
Reload retains the complete recorded question Expansion derives from the persisted selection, replacing parallel React state
Escape or the back control returns to the exact caption/node Existing data-research-return lookup and persisted local key; Graph passes the activated node key explicitly
Collapse, direct finding and legacy links retain intent Packaged positive and negative browser controls
Goal selection remains isolated Existing Goal guard retained; other Goal loads 134/134 records with no stale selection, and browser Back restores the question

Scope 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.

Check Result Scope / limit
Dashboard TypeScript/Vite and packaged Chat build passed Current head, source-bound build; existing large-chunk warnings retained
Focused Ego browser semantics passed Chinese/English × 1200/768/390 widths: timeline and Graph question reload, keyboard Escape, exact return identity and a nonfocused programmatic click followed by reload/back
Boundary controls passed Chinese/English × 1200/390: explicit collapse and finding reload, old finding/node URLs, negative and unknown-cost text, cross-Goal navigation and browser Back; readable question text ≥16 px, no document overflow in tested reading views
Readback passed 86 synthetic history records; public Graph fixture 134/134; zero writes and unchanged hashes across four fixture sources
Configured static checks passed CONTRIBUTING's explicit Ruff paths; mypy's 17 configured files; changed-scenario syntax; committed/staged/unstaged diff checks
Session regression passed test:conversation-returns
Quick premerge components passed Four direct checks, three selected catalog checks and the changed-file public-boundary check
Exact quality / aggregate premerge nonpassing Exact scope f80fb06024d5ffec5f67d162fbf1c8f70d3a307aa733aba1e330d1b55fbf1dd4, receipt cqr_f80fb06024d5ffec5f67; required gaps and failed broad diagnostic below remain blocking
Full repository pytest incomplete / failed; current head unqualified Corrected-environment run at prior head e3982b4 stopped 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 claimed
Broad ruff check diagnostic failed 118 findings outside this two-file diff. The narrower repository-declared Ruff command passed. The broad failure has no full immutable base/head attribution and is not waived
Complete browser / analysis-state harness not run Existing durable scenario was extended and syntax checked. The focused Ego checks passed; the entire multi-engine runner and its analysis-state matrix were not executed
Complete exact-head CI and installed App not qualified CI remains required before merge. Installed App, live providers and scientific outcome acceptance were not tested

Test-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 .py download 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.

Current view Desktop 1200 × 844 Narrow 390 × 844
Populated initial view Current populated timeline, desktop Current populated timeline, narrow
Complete question after reload Current complete question after reload, desktop Current complete question after reload, narrow

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.

Width Before (e3982b4) Current
1200 Before Graph return after reload, desktop Current Graph return after reload, desktop
390 Before Graph return after reload, narrow Current Graph return after reload, narrow
Earlier source-base comparison for question persistence (111519a → e3982b4)
View Before: reload loses the question After: reading intent survives
Desktop, 1200 × 844 Before: research question disappears on reload After: research question remains on reload
Narrow, 390 × 844 Before narrow: finding-only view after reload After narrow: full recorded question remains

Default populated history and English recorded-question reading at 390:

Populated research history at 390 English question reading at 390

Boundaries

  • No runtime routing, provider, permission, shared schema or authority changes; the new URL fields and Graph return prefix are local UI selection state.
  • No benchmark jobs, model calls, live research mutations or installed-package changes.
  • Public-boundary scan is clean for both changed files. Description and captures exclude private paths, operating state, raw traces and credentials.
  • Paired RFC changes are not needed; the bilingual diff check passed. Every branch commit has a DCO sign-off.
  • The executable repository scenario is the reproducible preview; the isolated local server was temporary.

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 loopx-agent left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@loopx-agent loopx-agent changed the title fix(research): preserve question reading intent across reloads fix(research): preserve reader intent and return focus across reloads Nov 2, 2026
@huangruiteng
huangruiteng merged commit 263a43c into main Nov 2, 2026
31 of 43 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants