feat(web-shell): add footnote previews and per-turn sources - #11480
feat(web-shell): add footnote previews and per-turn sources#11480callmeYe wants to merge 18 commits into
Conversation
E2E verification reportVerified head:
Remote CI on this final optical-alignment head passed Ubuntu tests, lint/static checks, no-AK integration, Web Shell E2E Smoke, visual capture, real-daemon E2E, desktop checks, and all install/lockfile gates. The separate automated code review is still running. The final browser runs verify source-only activation through The development run also verifies the complete host demo: a fixed DataWorks knowledge locator reaches the host Markdown link renderer, the DOM exposes a controlled Commands from npx vitest run --config vitest.config.ts client/components/messages/FootnoteCard.test.tsx client/components/messages/AssistantMessage.test.tsx client/components/messages/Markdown.test.ts client/components/messages/EnhancedMarkdownTable.test.tsx
PLAYWRIGHT_PORT=5187 npx playwright test client/e2e/web-shell.footnotes.spec.ts --config playwright.config.ts --project chromium --grep 'footnote source previews|source locator demo' --workers=1
FOOTNOTE_BUILT=1 PLAYWRIGHT_PORT=5188 npx playwright test client/e2e/web-shell.footnotes.spec.ts --config playwright.config.ts --project chromium --grep 'footnote source previews|source locator demo' --workers=1中文测试报告最终验证提交为 浏览器验收覆盖 开发态 Demo 还验证了完整知识库 locator 会交给宿主 Markdown 链接渲染器;点击卡片标题后,宿主用受控的 |
|
Thanks for the PR — this one arrives with a bilingual design doc and a real test suite behind it, which makes the gate easy to run. Template ✓ — every required section is present, including the reviewer test plan and the OS matrix. One small gap: the template asks a PR that adds a design document to link both language versions from the body, and Problem: this is a presentation change rather than a bug fix, so there is no reproduction to ask for. The premise holds against the code — Direction: aligned. It stays inside Size: no core paths are touched, so the core-module gate does not apply here. For context, the 1391 changed lines break down as 486 production logic, 754 test, 88 docs, 62 lockfile, 1 SVG asset — the test code outweighs the feature, which is the right way round, and it sits below both the 500- and 1000-line thresholds. Approach: the shape looks right. Annotating grouped
Nothing in the diff looks unrelated to the stated goal. The Risk: no elevated risk signals — none of the changed files match the high-risk paths from the revert-history analysis. The real exposure is breadth rather than any single path: this switches on for every shared interactive Markdown surface at once, so an unintended visual change somewhere else is the failure mode to watch. Moving on to code review. 🔍 中文说明感谢贡献!这个 PR 自带中英双语设计文档和一套实打实的测试,门禁跑起来很顺畅。 模板 ✓ —— 必填章节齐全,包括审阅者验证计划和操作系统矩阵。一个小缺口:模板要求新增设计文档的 PR 在正文里给出两个语言版本的链接,而 问题: 这是展示层改动而不是 bug 修复,所以不需要复现。前提在代码里成立—— 方向: 对齐。改动限定在 规模: 未触及核心路径,因此核心模块门禁不适用。供参考:1391 行改动拆分为 486 行生产逻辑、754 行测试、88 行文档、62 行锁文件、1 个 SVG 资源——测试代码多于功能代码,比例是对的,且低于 500 行和 1000 行两个阈值。 方案: 整体形态是对的。在 AST 上给聚合后的
diff 里没有与目标无关的改动。 风险: 无升级风险信号——改动文件都没有命中回滚历史分析得出的高风险路径。真正的暴露面是广度而非某个单点:它一次性对所有共用的交互式 Markdown 界面生效,所以要盯的失败模式是别处出现了非预期的视觉变化。 进入代码审查 🔍 — Qwen Code · qwen3.8-max-2026-09-02 Reviewed at |
Code reviewI went in expecting to push back on scope and mostly found careful work instead. No defects in the feature code. The things I checked that could plausibly have been wrong, and weren't:
Four things to fix or consider — the first one blocks, the rest do not: 1. Blocking: This is the same miss as the lockfile one, one step further along: adding 2. 3. The two lockfiles now disagree. 4. Carried over from the gate, so I won't repeat the argument: the card is a large state machine for one affordance, and the tree walk that locates the footnotes section runs before the early return, so footnote-free documents pay a full traversal per parse. Both are judgement calls for a maintainer, not defects. My own independent take before reading the code was: group adjacent refs into a count pill, namespace anchors with sequenceDiagram
participant P6 as Reader
participant P1 as Markdown renderer
participant P2 as rehypeFootnoteCards
participant P3 as FootnoteSup
participant P4 as FootnoteCard popover
participant P5 as MarkdownLink backref
P1->>P2: parse footnote markdown into hast
P2->>P2: collect definitions and namespaced anchors
P2->>P2: merge adjacent refs into one sup
P2-->>P1: sup carries footnoteCards data
P1->>P3: render sup component
P3->>P4: notes present, render trigger pill with count
P3-->>P1: no notes, render plain sup
P6->>P4: hover, focus or tap
P4-->>P6: one source per page with prev and next
P6->>P5: click footer return link
P5->>P5: resolve namespaced id via getRootNode
P5-->>P6: scroll and focus the owning message entry
Test evidenceThis is an unattended CI run, so I did not build or execute anything from this PR — the evidence below is the PR's own CI, read off the API for the reviewed commit. The first commit was red and the author fixed part of it before this review landed. At The same dependency addition then tripped the next generated-artifact gate: Final CI results for
One row per check name (latest run); skipped checks omitted; failures sort first. / 每个检查名一行(取最新一次运行),省略 skipped,失败项排在最前。 Not verified, and I want to be explicit about it: no CI job runs the browser suite on Windows or macOS. Sandboxed verification would settle part of this: 中文说明代码审查我本来准备好要在范围上提出异议,结果发现大部分工作做得很细致。功能代码本身没有缺陷。以下是我重点核查、原本可能出问题但没出问题的地方:
四处需要修改或考虑——第一处是阻塞项,其余不是: 1. 阻塞项:新增依赖后没有重新生成 2. 3. 两个锁文件现在不一致。 4. 门禁阶段已提过的两点,不再重复论证:卡片对单个交互来说是个庞大的状态机;定位脚注区块的整树遍历发生在提前返回之前,因此没有脚注的文档每次解析都要付一次完整遍历。两者都是 maintainer 的判断取舍,不是缺陷。 在读代码之前我自己的方案是:把相邻引用聚合成一个带数量的胶囊、用 (时序图见上方英文版,内容一致:hast 标注 → 组件分派 → 弹层交互 → 跨 ShadowRoot 的命名空间回链路由。) 测试证据这是无人值守的 CI 运行,因此我没有构建或执行本 PR 的任何代码——下面的证据全部来自本 PR 自己的 CI,通过 API 读取所审提交的结果。 第一个提交是红的,作者在本次审查发布前修复了其中一部分。 在 同一次依赖新增接着绊倒了下一个生成物门禁: 明确说明未验证的部分:CI 里没有任何任务在 Windows 或 macOS 上运行浏览器套件。 沙箱验证能坐实其中一部分: — Qwen Code · qwen3.8-max-2026-09-02 Reviewed at |
🖼️ web-shell visual previewRendered against a mock daemon (no real backend): the PR base vs this PR head Screenshots · before / afterℹ️ No screenshot changed against the PR base — but this PR edits 15 render-shaping files:
Either the change has no visual effect (logic, plumbing, a state the scenarios never reach), or no scenario renders this UI — in which case the preview cannot see it, and an empty result is a coverage gap rather than a clean bill of health. To make it visible, add a scenario to Full-resolution recordings (.webm) are attached to the workflow run. — Qwen Code · web-shell visuals |
|
Confidence: 2/5 — on the code alone I would be at 4; the score is low because a required gate is red from this PR's own dependency change, so it cannot merge as-is. One generated file needs regenerating and this is a different review. Stepping back: this is the kind of PR that is easy to wave through and easy to reject, and I tried to do neither. What convinced me the feature work is real rather than plausible-looking is the test suite. Nine unit cases and ten browser scenarios that pin behaviour I would otherwise have had to take on faith — that grouping stops at punctuation, cell and inline-code boundaries; that an unresolved reference stays literal until its definition streams in; that a selected source survives the document growing and falls back cleanly when it is removed; that two messages reusing the same footnote ids keep isolated return targets. Those are precisely the cases a careless implementation gets wrong, and they are the cases someone wrote down before shipping. The unsafe-URL test feeds it The duplicate-id question is the one I spent the most time on, because the AST rewrite really does map four nodes onto one namespaced id. It is safe only because I also want to record the concern I raised in the gate and then had answered for me. I flagged that this switches on for every shared interactive Markdown surface at once, so an unintended visual change somewhere else was the failure mode to watch. What blocks it is one file, and it is mechanical. It is the same miss as the first commit's, one step further along the generated-artifact chain: Where I still have a reservation is scope, and I want to state it plainly rather than bury it under the blocker. My own answer to this problem was a count pill over the existing shared The second half of that reservation is the one I could not resolve, and it is a product question rather than a code question: I found nothing in Two small things I would fix while the branch is open, neither worth a round trip on its own: use the existing Verdict: request changes, for the stale 中文说明Confidence: 2/5 —— 单看代码我会给到 4 分;分数低是因为一个必需门禁因本 PR 自己的依赖改动而变红,所以现状无法合并。只要重新生成一个生成文件,这就是一次完全不同的审查。 退一步看整体:这种 PR 既容易被随手放过,也容易被一口否掉,我两边都尽量没做。 让我相信功能部分是真实工作、而不是"看起来像样"的,是测试套件。九个单测用例加十个浏览器场景,钉住了那些我本来只能选择相信的行为——聚合会在标点、单元格和行内代码边界处停止;未定义的引用在定义流入前保持字面文本;选中的来源在文档增长时保留、被移除时干净回退;两条复用相同脚注 id 的消息各自保有隔离的回链目标。这些恰恰是草率实现会做错的地方,也是有人在提交前就写下来的地方。不安全 URL 的测试喂进 我在重复 id 这个问题上花的时间最多,因为 AST 改写确实把四个节点映射到了同一个命名空间 id。它之所以安全,仅仅是因为 我还想记录一个我在门禁里提出、随后被事实回答了的顾虑。我当时指出这个改动一次性对所有共用的交互式 Markdown 界面生效,所以要盯的失败模式是别处出现非预期的视觉变化。 阻塞它的只有一个文件,而且是机械性的。 这和第一个提交的疏漏是同一个,只是沿生成物链条又往前走了一步: 我仍有保留意见的地方是范围,我想直说而不是把它埋在阻塞项下面。我自己对这个问题的答案是:在现有共享 保留意见的另一半是我没能解决的,它是产品问题而不是代码问题:我在 两件我建议趁分支还开着就修掉的小事,单独看都不值得来回一轮:用现有的 结论:要求修改,只为过期的 — Qwen Code · qwen3.8-max-2026-09-02 Reviewed at |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
One mechanical blocker, and nothing else — the feature work itself is clean and well tested. Full notes are in my review comment above.
Lint & Static is red because packages/vscode-ide-companion/NOTICES.txt is stale (27 missing lines). Adding @types/hast changes the dependency tree, and that file is generated from it:
npm run generate:notices --workspace=qwen-code-vscode-ide-companion
then commit the result. I checked this against main rather than assuming it: Lint & Static is green at 3733c8eb, the same base this PR sits on, and the adjacent settings.schema.json drift check in the same job passed — so it is this diff, not pre-existing rot.
It is the same miss as the first commit's, one step further along the chain: c3338de1 regenerated both lockfiles but not the notices. Worth treating as one rule — when a dependency changes, everything derived from the tree moves.
Two optional, non-blocking items while you are in there: use the existing cssUrlValue helper from client/utils/cssUrlVar.ts for the mask URL instead of hand-building url("…") twice in FootnoteCard.tsx; and consider ^3.0.4 for @types/hast so npm dedupes to a single copy and both lockfiles describe the same tree.
The scope question in my comment (the card is a 218-line state machine for one affordance) is a genuine question for a maintainer, not a reason for this review.
中文说明
只有一个机械性阻塞项,别无其他——功能部分本身干净且测试充分。完整意见见上方的审查评论。
Lint & Static 变红是因为 packages/vscode-ide-companion/NOTICES.txt 过期(缺 27 行)。新增 @types/hast 改变了依赖树,而该文件正是由依赖树生成的:
npm run generate:notices --workspace=qwen-code-vscode-ide-companion
然后提交结果。我没有想当然,而是对照了 main:Lint & Static 在本 PR 所基于的同一个提交 3733c8eb 上是绿的,同一任务里紧邻的 settings.schema.json 漂移检查也通过了——所以是这个 diff 造成的,不是主干已有的腐化。
这和第一个提交的疏漏是同一个,只是沿链条又往前一步:c3338de1 重新生成了两个锁文件,但没有重新生成 notices。建议当成一条规则来处理——依赖一变,所有由依赖树派生的东西都要动。
顺手有两个可选、不阻塞的项:用 client/utils/cssUrlVar.ts 里现成的 cssUrlValue 辅助函数生成遮罩 URL,而不是在 FootnoteCard.tsx 里手工拼接两遍 url("…");@types/hast 考虑写 ^3.0.4,这样 npm 会去重成一份,两个锁文件也能描述同一棵树。
评论里那个范围问题(卡片为一个交互用了 218 行状态机)是给 maintainer 的真实提问,不是本次要求修改的原因。
— Qwen Code · qwen3.8-max-2026-09-02
|
Qwen Code review timed out. Qwen review timed out after 21600 seconds (of the 360-minute budget). This run already used the maximum 360 minute timeout. See workflow logs. |
Dismissed as stale after 58c8de6 regenerated NOTICES.txt for @types/hast and passed repeat generation, lockfile checks, build, typecheck, 230 focused tests, and source/production browser E2E. The review identified no other blocker.
|
Qwen Code review did not complete successfully. The review pipeline failed before a review could be posted. A transient error is retried automatically; if you are seeing this, retry with |
|
E2E verification for commit
Verified behaviors: numeric/named/Chinese IDs, plain and multiline notes, whitespace grouping and ID deduplication, literal percent IDs staying distinct, full transformed definition Markdown, safe public payloads, separate inline/Assistant callback lists, independent/default/invalid/throwing icon callbacks, SVG resource loading and centering, scrollable complete descriptions, hover-only action footer, pinned pagination, keyboard/touch, streaming, message isolation, host link handoff, preserved navigation targets, Markdown copy and static document footnotes. Reproduction from npx vitest run client/components/messages/FootnoteCard.test.tsx client/components/messages/AssistantMessage.test.tsx client/components/messages/Markdown.test.ts client/components/messages/EnhancedMarkdownTable.test.tsx
PLAYWRIGHT_PORT=5187 npx playwright test client/e2e/web-shell.footnotes.spec.ts --config playwright.config.ts --project chromium --grep 'footnote source previews|source locator demo' --workers=1For the production run, build first, start The demo uses deterministic locator fixtures and a mocked host panel. Live BFF knowledge retrieval and OpenCode's production URL builder are outside this verification. 中文说明本次提交
已验证:数字/命名/中文 ID,纯文本和多行脚注,空白聚合与 ID 去重,字面百分号 ID 不混淆,transform 后完整原文,公开数据不含内部节点,两个函数的完整列表及独立性,空值/无效/异常回退,SVG 加载与居中,长说明滚动,Hover 操作栏,分页保持打开,键盘/触屏,流式更新,消息隔离,宿主链接接管,未转换引用目标,Markdown 复制和静态脚注导出。 复现命令见上方。生产运行需先构建并在 5188 启动 Demo 为确定性 locator fixture 和模拟宿主面板,不包含真实 BFF 检索或 OpenCode 生产 URL 拼接的验证。 |
|
Follow-up fix The demo now supplies a dedicated SVG with normalized padding, geometry and stroke weight. Public icon sizing and host callback behavior are unchanged. A new browser regression measures actual painted bounds and visual centroids from the DOM Copy SVG and the citation's resolved mask URL. Verification: painted width/height differences are now 0.027/0.137 CSS px; bounding-box/visual-center differences are below 0.3px. The updated host demo E2E passed (1/1); both message-hover and direct button-hover screenshots were inspected. An isolated negative control serving the old SVG failed the same measurement check. Web Shell build/typecheck, root bundle, focused lint and formatting passed. This asset is a development-demo resource; production rendering code is unchanged. 中文说明补充修复 Demo 现使用单独校正留白、几何尺寸和线宽的 SVG。公共图标尺寸与宿主回调行为不变。新增浏览器回归会从实际 DOM 复制 SVG 和引用 mask URL 测量实绘边界及视觉重心。 验证:实绘宽/高差已降为 0.027/0.137 CSS px,边界中心和视觉重心差均小于 0.3px;宿主 Demo E2E 1/1 通过,并人工查看了消息 Hover 与直接按钮 Hover 截图。独立负对照替换回旧 SVG 后,同一检查明确失败。Web Shell 构建/类型检查、根目录 bundle、定向 lint 和格式检查通过。该资源只用于开发 Demo,生产渲染代码未变。 |
|
Current-page content slot verification for
Source unchanged during final browser acceptance. Earlier interrupted browser runs were caused by root build temporarily rebuilding SDK output. An exit-animation locator race was corrected by awaiting close before another interaction. The independent consumer initially inlined SVGs; its ignored build config was corrected to emit resource URLs, preserving Web Shell's existing SVG-data-URL policy. Public API: 中文说明提交
最终浏览器验收期间源码保持不变。早期中断来自全仓构建重建 SDK 产物;退出动画导致的定位器冲突通过等待关闭后再切换交互修正。独立宿主构建首次内联 SVG,随后仅修正其忽略目录内的构建配置以输出资源 URL,没有放宽 Web Shell 的 SVG data URL 策略。 公开接口为 |
|
E2E report for
Verified behavior: source totals are independent from footnotes; a previously registered source counts in both explicitly associated turns; deleting associated sources updates the open list and count without borrowing unrelated sources; asynchronous inventories update without an extra click. An attachment-only daemon shows the first turn's attachment and later reused/new attachments with the environment panel closed. Source rows use the existing preview; body footnote grouping, pagination persistence, custom DOM content lifecycle, host links, icon geometry, keyboard/touch, streaming and isolated message previews remain covered. The demo deliberately has 3 footnotes / 4 current-turn sources / 5 session sources. Screenshots were manually checked for footer icon alignment and list layout. Browser fixtures control daemon events and source inventories; this does not claim a live BFF/knowledge-retrieval integration test or new Core source-use tracking. Two clean source-review passes completed after the async hydration and attachment-loading fixes. No Core/daemon protocol or dependency changes are included. Latest-main merge-tree check is clean. 中文验收:开发版 18/18、生产应用 14/14(4 项源码专用场景明确跳过)、独立编译宿主 3/3,定向单元/DOM 测试 324 项通过;完整构建、全仓及集成类型检查、打包和格式/lint 检查通过。生产资源已核对 HTTP 与磁盘内容一致,宿主实际消费编译后的 transcript 导出。 已验证本轮来源与脚注数量独立、旧来源跨轮复用、删除后实时更新、异步加载无需点击、环境面板关闭时附件来源仍显示与刷新,以及现有来源预览、正文分页/宿主内容插槽/键盘触屏/流式与跨消息隔离。Demo 为 3 个脚注、4 个本轮来源、5 个会话来源,截图已检查图标对齐。浏览器使用可控 daemon 与来源数据,不将结果描述为真实 BFF/知识检索端到端验证,也未新增 Core 来源使用追踪协议。修复后完成两轮无新发现审查,与最新 main 的合并检查无冲突。 |
|
Post-merge validation for The first CI attempt stopped at the lint-gate freshness guard because main had updated its filename rules. Main was merged normally in
Main now sends a same-origin image CSP in development. The thumbnail fixture was moved to a same-origin intercepted test asset so both successful loading and failed-image fallback are tested under that policy. No product/CSP policy was weakened. An old Vite optimizer process was restarted after the dependency installation. The final app and compiled-consumer HTTP assets were checked against disk; test artifacts and screenshots from both pre-merge and post-merge runs are preserved locally. 中文:已正常合并 main,解决首次 CI 的 lint 规则过旧阻塞,无合并冲突。合并后的全仓构建、类型检查、打包和 335 项定向测试通过,开发 E2E 18/18、生产应用 14/14(4 项明确跳过)、独立编译宿主 3/3 再次通过。上游新增同源图片 CSP 后,仅将测试样图调整为同源资源,没有降低产品安全策略;依赖同步后已重启旧 Vite 优化器。当前提交为上述精确 SHA,新一轮 GitHub CI/评审独立跟进。 |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Partially reviewed — gaps disclosed.
1 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:
- R1-19
@types/hastversion range in packages/web-shell/package.json (anchor package-lock.json:31124) — already reported (issue comment 5602755982, non-blocking item 3)
Not explored to full depth (tool budget reached): chunk 17: none of these e2e specs were executed (they need a vite dev server plus Playwright browsers); every claim above is from reading the spec against the component, …; "agent reverse-audit (round 2)": did not execute the shadow test under a live Playwright dev server, so the timeout is argued from the accessible-name and menu-item evidence rather than observe…; chunk 13: tracing how core's llmContent for record_source is mapped by the ACP bridge into the daemon transcript block ( content text vs rawOutput ) — the first fin…; "agent reverse-audit (round 1)": the doc's number: number = "Footnote number in first-reference order" — I could not confirm the footnote <li> order the numbering is read from ( rehype-foot…; "agent reverse-audit (round 1)": the doc's "Stable component identities preserve open cards through streaming updates" — I did not trace React reconciliation of the sup / section components a…, and 6 more.
Not reviewed: reverse audit — stopped before round 3 by the review time budget.
中文说明
仅完成部分审查,审查缺口已披露。
本轮确认的 1 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。
未探索到全部深度(达到工具调用预算):chunk 17:none of these e2e specs were executed (they need a vite dev server plus Playwright browsers); every claim above is from reading the spec against the component, …;"agent reverse-audit (round 2)":did not execute the shadow test under a live Playwright dev server, so the timeout is argued from the accessible-name and menu-item evidence rather than observe…;chunk 13:tracing how core's llmContent for record_source is mapped by the ACP bridge into the daemon transcript block ( content text vs rawOutput ) — the first fin…;"agent reverse-audit (round 1)":the doc's number: number = "Footnote number in first-reference order" — I could not confirm the footnote <li> order the numbering is read from ( rehype-foot…;"agent reverse-audit (round 1)":the doc's "Stable component identities preserve open cards through streaming updates" — I did not trace React reconciliation of the sup / section components a…,另有 6 条。
未审查:反向审计——评审时间预算不足,未能开始第 3 轮。
— qwen3.8-max via Qwen Code /review (v0.23.3)
|
Verification for
Observed before/after: activating a source previously left focus on BODY and the next Tab reached New task; it now returns to the source trigger, including in a shadow portal. A host that explicitly focuses its preview keeps that focus. Hover-only closing and clicking an external textbox retain their existing focus behavior. A focus-neutral trigger click now remains open after pointer leave and resets after dismissal. Scroll width changed from334/client328 to340/client340. Nested notes retain both definitions and all forward paths, while flat notes still aggregate and paginate. The ordinary nested-link external opener was also reproduced with the exact merge-base Markdown component and was deliberately left unchanged. The Shadow DOM selector Critical was disproved by the actual accessible-name tree and an unchanged passing test. Readonly source content remains accessible via Tab and PageDown; no unrelated keyboard redesign was added. Regression tests for ordinary/shadow activation focus and nested definitions were observed failing before their corresponding corrections, then passing. Two clean scoped source audits completed after the shadow-focus correction. Worktree is clean and pushes are normal (no force push). |
Scoped review dispositionsThe user explicitly requires that this follow-up fix only defects introduced by this PR or necessary compatibility consequences, and forbids opportunistic fixes to pre-existing behavior. The production patch is confined to two files; accompanying tests and bilingual documentation cover those changes. Main was synchronized to incorporate its current lint gate; the PR tests also provide a GET-only model-list fixture for the new upstream request, without changing the global harness or production code. Fix confirmed PR regressionsR1-33, R1-3, R1-35, R1-4. Source activation focus (including shadow portals), focus-neutral click persistence, source-list overflow, and nested-definition forward paths. Targeted tests were red before the fixes and browser probes verify the repaired behavior. Not reproduced as reportedR1-34, R1-38. The unchanged Shadow DOM scenario passes; the composed accessible name selects the session row. The readonly source list is reachable with Tab and scrolls with PageDown; changing ArrowDown behavior is not necessary for this fix. Exclude pre-existing behaviorR1-2. The same outer desktop opener fires with the exact merge-base Markdown component. Per the user instruction, ordinary link opening is not modified. Retain the accepted contract; defer API or contract refinementsR1-1, R1-6, R1-8, R1-18, R1-57, R1-60, R1-66. The turn footer is independent of the environment-panel layout; host source identity and link resolution remain explicit. New global opt-outs, sentinel/relative-URL heuristics, shared Core protocols, API shape changes and summary semantics are outside this regression patch. Extra public-type documentation can be addressed separately; the existing bilingual design documents the identity requirements. Defer performance changesR1-5, R1-54, R1-55, R1-67. These are cache/identity/allocation or unused extraction-work improvements, not a demonstrated new correctness failure in this run. No cache refactor or document-mode architecture change is included. Defer presentation/accessibility refinementsR1-7, R1-56, R1-61, R1-62, R1-64, R1-65, R1-37. These propose additional readonly-row, hover, tooltip, label or announcement behavior. They are non-blocking refinements and require their own validation; this patch retains the accepted UI apart from the reproduced new defects. Retain for further investigation, without claiming fixedR1-70, R1-71, R1-68. Advanced-table clone IDs, advanced-mode/custom-component remounting and custom demo reparenting need separate focused investigation. They were not promoted to Critical or treated as verified fixes, and no broad table/render/host-lifecycle changes are included. Defer additional test coverageR1-13, R1-15, R1-58, R1-14, R1-16, R1-42, R1-43, R1-39, R1-47, R1-23, R1-24, R1-52, R1-50, R1-51, R1-9, R1-53. These request additional cases or stronger witnesses, rather than identifying broken production guards in the current patch. Only regression coverage necessary for the confirmed fixes is added; no claim is made that existing tests detect every proposed mutation. Defer fixture, documentation and cleanup changesR1-12, R1-11, R1-36, R1-41, R1-44, R1-45, R1-22, R1-25, R1-10, R1-20, R1-21. These concern optional simplification, test/demo typing, example wording, runner documentation, unused labels/helpers or dependency resolution cleanup. The local production runner explicitly supplies FOOTNOTE_BUILT, and dependency ranges are validated by frozen-install CI. No dependency deduplication, broad fixture cleanup or unrelated code removal is included. Closing non-blocking threads records these explicit dispositions; it does not claim deferred work has been implemented. The blocking focus fix has now been pushed and verified at |
Superseded by c68a32e: R1-33 fixed and verified in ordinary/shadow portals; R1-34 disproved by exact-head browser/ARIA evidence. Other findings have explicit non-blocking scoped dispositions (issuecomment-5658612838); no unresolved threads or live human objections remain. This removes the stale blocker, not a fresh approval; CI and required reviews remain in force.
What this PR does
Web Shell renders resolved Markdown footnotes as grouped, paginated previews. Numeric, named and Chinese IDs, linked sources and multiline plain-text notes share the same behavior. Hosts can choose an SVG/image URL for each inline group and mount framework-neutral DOM or SolidJS content for the current page while Qwen retains navigation, hover, keyboard handling and pagination. Original definitions remain intact when copying Markdown or exporting a static document. Definitions containing nested footnote references stay in the standard list so their navigation remains intact.
The Assistant action footer independently shows the current turn's Sources-panel entries, including attachment fallbacks, instead of counting footnotes. A source reused in another turn counts in both turns. Hover opens the turn's source list, and selecting an item uses the existing source preview. Hosts can choose a separate footer icon and explicitly associate registered sources with user turns. Source and attachment data update without opening the environment panel or interacting with the report.
Why it's needed
Reports combine web pages, files, attachments, knowledge records and explanatory notes. Inline footnotes identify what a passage cites; the Sources panel also contains material associated with a turn that has no footnote. These two controls need independent data while retaining the same host customization and existing source-opening behavior.
Reviewer Test Plan
How to verify
[^a][^b], separate[^c], repeated IDs, Chinese/numeric IDs and multiline plain notes. Expect one group per adjacent run, one page per definition, complete original definitions and no URL-based merging.Evidence (Before & After)
Before: the footer summarized footnotes and could omit source-panel entries that had no footnote. After: the demo retains three inline footnotes while its footer shows four turn sources from the five-item session inventory. Browser regressions also verify that asynchronously loaded sources appear without clicking the report and that attachment-only sources refresh with the environment panel closed. A separate E2E report records the completed development and production checks.
Tested on
Environment (optional)
Local Web Shell development server, built production app and a separately compiled host consuming the published transcript entry point, with controlled mock-daemon events and source inventories.
Risk & Scope
Linked Issues
Builds on the Session Sources capability from #11262.
中文说明
本 PR 的改动
Web Shell 将可解析的 Markdown 脚注展示为可聚合、可翻页的预览。数字、命名、中文 ID、有链接的来源及多行纯文本说明使用相同行为。宿主可为各组正文脚注选择 SVG/图片 URL,并以框架无关接口挂载原生 DOM 或 SolidJS 当前页内容,Qwen 保留导航、Hover、键盘操作和分页。复制 Markdown 或导出静态文档时保留原始脚注定义。包含嵌套脚注引用的定义保留普通文末列表,确保导航完整。
Assistant 操作栏独立展示本轮来源面板条目(包含附件兜底),不再统计脚注。旧来源在其他轮次再次使用时,两轮都计入。Hover 展示本轮来源列表,点击条目沿用现有来源预览。宿主可独立定制操作栏图标,并将已登记来源明确关联到用户轮次。来源与附件数据更新不依赖打开环境面板或操作报告。
为什么需要
报告混合网页、文件、附件、知识库记录及说明性脚注。正文脚注表达段落引用,来源面板还包含本轮关联、但没有脚注的材料。两个入口需要独立的数据,同时保留一致的宿主定制能力和已有来源打开行为。
审阅者测试计划
如何验证
[^a][^b]、独立的[^c]、重复 ID、中文/数字 ID 及多行纯文本说明。应按连续引用分组,每个 definition 一页,保留完整原文,不按 URL 合并。证据(修改前后)
修改前:操作栏汇总脚注,可能遗漏没有脚注的来源面板条目。修改后:Demo 保留三个正文脚注,操作栏从五个会话来源中展示四个本轮来源。浏览器回归同时验证异步来源加载后无需点击报告即可显示,以及环境面板关闭时附件来源继续刷新。独立 E2E 报告记录已完成的开发和生产验收。
测试平台
环境(可选)
本地 Web Shell 开发服务器、生产构建应用及单独编译的 transcript 导出入口消费宿主,使用受控 mock daemon 事件和来源数据。
风险与范围
关联事项
基于 #11262 的 Session Sources 能力。