From b9869d1e97a31a739f47d6006bd4594e9aa611a2 Mon Sep 17 00:00:00 2001
From: Tianyi Cui <53024+tianyicui@users.noreply.github.com>
Date: Sat, 22 Aug 2026 01:47:43 +0800
Subject: [PATCH 1/2] test(ci): stabilize cross-platform gate baselines
---
...worker-pack-lowering-and-preview.i18n.yaml | 4 ++--
...-20-webworker-pack-lowering-and-preview.md | 1 +
...-webworker-pack-lowering-and-preview.zh.md | 1 +
.../2026-08-06-web-skill-tool-row.i18n.yaml | 4 ++--
.../feature/2026-08-06-web-skill-tool-row.md | 2 +-
.../2026-08-06-web-skill-tool-row.zh.md | 2 +-
...8-18-in-job-partitioned-coverage.i18n.yaml | 4 ++--
.../2026-08-18-in-job-partitioned-coverage.md | 2 +-
...26-08-18-in-job-partitioned-coverage.zh.md | 2 +-
apps/web/tests/skill-tool-row.e2e.ts | 1 +
.../snapshots/skill-tool-row/ui.expected.md | 2 +-
.../tests/conversation-ui.client.spec.tsx | 21 +++++++++++++------
.../tests/compile/transform-corpus-check.ts | 2 +-
13 files changed, 30 insertions(+), 18 deletions(-)
diff --git a/.agents/notes/implemented/architecture/2026-08-20-webworker-pack-lowering-and-preview.i18n.yaml b/.agents/notes/implemented/architecture/2026-08-20-webworker-pack-lowering-and-preview.i18n.yaml
index b2687ac5fd..fe1745817d 100644
--- a/.agents/notes/implemented/architecture/2026-08-20-webworker-pack-lowering-and-preview.i18n.yaml
+++ b/.agents/notes/implemented/architecture/2026-08-20-webworker-pack-lowering-and-preview.i18n.yaml
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-08-20-webworker-pack-lowering-and-preview.md
-2026-08-20-webworker-pack-lowering-and-preview.md: d4a3d0b2125421e761eb1616a7605b58d0d77da3
-2026-08-20-webworker-pack-lowering-and-preview.zh.md: 24ff21957c31783d1b375c6589bc6114b3be1972
+2026-08-20-webworker-pack-lowering-and-preview.md: 37c7730c5da664560156a8e4bd9ba594c78369ee
+2026-08-20-webworker-pack-lowering-and-preview.zh.md: 833dc13d36c367faf6c25e8c4a307890f54d3176
diff --git a/.agents/notes/implemented/architecture/2026-08-20-webworker-pack-lowering-and-preview.md b/.agents/notes/implemented/architecture/2026-08-20-webworker-pack-lowering-and-preview.md
index d4a3d0b212..37c7730c5d 100644
--- a/.agents/notes/implemented/architecture/2026-08-20-webworker-pack-lowering-and-preview.md
+++ b/.agents/notes/implemented/architecture/2026-08-20-webworker-pack-lowering-and-preview.md
@@ -30,5 +30,6 @@ Both packages live in `packages/experimental/` as `@deepseek-ai/dsh-experimental
- `lib/worker.js` contains no parser (423.5 kB → 246.3 kB at the time of the cut, before the shell process layer landed).
- `diff dist/index.html dist/preview.html` is exactly one script tag; `packages/experimental/webworker-packer/tests/image-loadable.spec.ts` pins both halves of the loader contract, and `apps/web/tests/preview-boot.e2e.ts` pins preview usability (boot to an interactive page) in the web browser lane, replacing the retired `apps/web/scripts/preview/` probe scripts.
+- The transform corpus imports every built bundle through Node before comparing its lowered exports. Its pinned exemptions name the actual non-importable bundle and fail when one becomes importable: after Win32 process primitives became the Koffi type owner, `win32-process` carries the duplicate-type exemption and `sandbox-windows-acl` does not.
- The served `` anchor exists because relative asset URLs would resolve under the request directory on SPA-fallback paths; remove it only together with the relative build base.
- The image ships as a deterministically gzip-compressed tar (`vfs-image.tar.gz`; MTIME 0, OS byte 0xff): static hosts do not compress binary content types (type allowlists, CDN size caps), so the compression rides the artifact, and the worker inflates the fetch body through the browser's native `DecompressionStream` while it downloads.
diff --git a/.agents/notes/implemented/architecture/2026-08-20-webworker-pack-lowering-and-preview.zh.md b/.agents/notes/implemented/architecture/2026-08-20-webworker-pack-lowering-and-preview.zh.md
index 24ff21957c..833dc13d36 100644
--- a/.agents/notes/implemented/architecture/2026-08-20-webworker-pack-lowering-and-preview.zh.md
+++ b/.agents/notes/implemented/architecture/2026-08-20-webworker-pack-lowering-and-preview.zh.md
@@ -30,5 +30,6 @@
- `lib/worker.js` 不含解析器(当刀落时为 423.5 kB → 246.3 kB,早于 shell 进程层落地)。
- `diff dist/index.html dist/preview.html` 恰为一个 script 标签;`packages/experimental/webworker-packer/tests/image-loadable.spec.ts` 钉住装载器契约的两半,`apps/web/tests/preview-boot.e2e.ts` 在 web 浏览器车道钉住 preview 可用性(boot 到可交互页面),替代已撤编的 `apps/web/scripts/preview/` 探针脚本。
+- 转换 corpus 会先通过 Node 导入每个已构建 bundle,再比较 lowered export。固定豁免会点名真正不可导入的 bundle,并在其恢复可导入时失败:Win32 process primitive 成为 Koffi 类型 owner 后,由 `win32-process` 承担重复类型豁免,`sandbox-windows-acl` 不再承担该豁免。
- served 的 `` 锚存在的原因是:相对资产 URL 在 SPA fallback 深路径下会解析进请求目录;只有与相对构建 base 一起才可移除它。
- 镜像以确定性 gzip 压缩的 tar 交付(`vfs-image.tar.gz`;MTIME 0、OS 字节 0xff):静态托管不压缩二进制 content-type(类型白名单、CDN 尺寸帽),压缩必须随制品走;worker 用浏览器原生 `DecompressionStream` 在下载的同时解压 fetch body。
diff --git a/.agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.i18n.yaml b/.agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.i18n.yaml
index 55ce6ceeb9..9ff850b475 100644
--- a/.agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.i18n.yaml
+++ b/.agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.i18n.yaml
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.md
-2026-08-06-web-skill-tool-row.md: 04e8ffcd6e506142b569e60458af144233810bbd
-2026-08-06-web-skill-tool-row.zh.md: c68ddea1d44e3b071deafc9450f6a2d09023cd80
+2026-08-06-web-skill-tool-row.md: c07b0b724293e74d5e7649326110cf8d7237dd0d
+2026-08-06-web-skill-tool-row.zh.md: 915e1209768af0ee30dc923afd3be7a3e17e09c7
diff --git a/.agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.md b/.agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.md
index 04e8ffcd6e..c07b0b7242 100644
--- a/.agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.md
+++ b/.agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.md
@@ -14,7 +14,7 @@ The Web transcript renders `skill` calls through the generic fallback row, so a
The collapsed row uses a 14-pixel document-and-sparkle glyph and the Bash row's neutral hierarchy: tertiary glyph, secondary `Skill` title, caption separator, and tertiary skill name. Running, failed, and interrupted calls retain the transcript's shimmer, error dot and first-line summary, and warning dot semantics. A settled call expands through the whole summary row into a 260-pixel bounded `Instructions` card containing the exact durable result text; the existing trajectory `Inspect` handoff remains available below the card.
-The row derives every visible value from a paired call/result slice in the current runtime window. It reads the skill name from the recorded `name` argument and the instructions from durable result content, and never joins the current skill catalog for descriptions or provider metadata. If pagination leaves the call outside the window, the result has no tool identity and remains on the generic fallback rather than extending the history wire contract. The existing ACP `skill-load` recording is seeded through the real Web persistence and composition path for a keyless interaction and accessibility snapshot.
+The row derives every visible value from a paired call/result slice in the current runtime window. It reads the skill name from the recorded `name` argument and the instructions from durable result content, and never joins the current skill catalog for descriptions or provider metadata. If pagination leaves the call outside the window, the result has no tool identity and remains on the generic fallback rather than extending the history wire contract. The existing ACP `skill-load` recording is seeded through the real Web persistence and composition path for a keyless interaction and accessibility snapshot. The snapshot removes a calendar date only when it immediately precedes the normalized clock and `Ran for` footer; the clock remains, while local and UTC hosts no longer disagree at a same-day boundary.
## Alternatives considered
diff --git a/.agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.zh.md b/.agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.zh.md
index c68ddea1d4..915e120976 100644
--- a/.agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.zh.md
+++ b/.agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.zh.md
@@ -14,7 +14,7 @@ Web transcript(文本记录)通过通用后备行渲染 `skill` 调用,使
收起的行使用 14 像素的文档与闪光组合图标,并沿用 Bash 行的中性色层级:图标采用三级色,`Skill` 标题采用二级色,分隔符采用 caption 色,skill 名称采用三级色。运行、失败和中断调用分别沿用 transcript 的扫光、错误状态点加首行摘要,以及警告状态点语义。已结算调用可以通过整个摘要行展开一个高度上限为 260 像素的 `Instructions` 卡片,其中原样呈现持久化结果文本;用于跳转至 trajectory 的现有 `Inspect` 入口仍保留在卡片下方。
-该行的所有可见值均派生自当前 runtime 窗口中已配对的调用/结果片段。skill 名称来自已记录的 `name` 参数,指令来自持久化的结果内容;该行绝不关联当前 skill 目录来读取描述或提供方元数据。如果分页将调用留在窗口外,结果便没有工具身份,并继续使用通用后备路径,而不是扩展 history 协议约定。现有的 ACP(Agent Client Protocol)`skill-load` 记录经由真实的 Web 持久化与组合路径写入,用于无需密钥的交互和无障碍快照。
+该行的所有可见值均派生自当前 runtime 窗口中已配对的调用/结果片段。skill 名称来自已记录的 `name` 参数,指令来自持久化的结果内容;该行绝不关联当前 skill 目录来读取描述或提供方元数据。如果分页将调用留在窗口外,结果便没有工具身份,并继续使用通用后备路径,而不是扩展 history 协议约定。现有的 ACP(Agent Client Protocol)`skill-load` 记录经由真实的 Web 持久化与组合路径写入,用于无需密钥的交互和无障碍快照。快照只会在日历日期紧邻规范化时钟与 `Ran for` 页脚时移除该日期;时钟仍保留,而本地时区与 UTC 宿主不会再在同日边界产生分歧。
## 考虑过的替代方案
diff --git a/.agents/notes/implemented/process/2026-08-18-in-job-partitioned-coverage.i18n.yaml b/.agents/notes/implemented/process/2026-08-18-in-job-partitioned-coverage.i18n.yaml
index d517367d9d..b48f880c61 100644
--- a/.agents/notes/implemented/process/2026-08-18-in-job-partitioned-coverage.i18n.yaml
+++ b/.agents/notes/implemented/process/2026-08-18-in-job-partitioned-coverage.i18n.yaml
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-08-18-in-job-partitioned-coverage.md
-2026-08-18-in-job-partitioned-coverage.md: f86c2dffb6d3d30fdccfa445c57043c5217e439b
-2026-08-18-in-job-partitioned-coverage.zh.md: 62bb77511dd2c28b31e470288ff5c906dd346aeb
+2026-08-18-in-job-partitioned-coverage.md: 532c145f5b66bd6574f9ee167c12c739fd4d7fa9
+2026-08-18-in-job-partitioned-coverage.zh.md: dc8a089a7c089338b775e49fdfe67f134f077704
diff --git a/.agents/notes/implemented/process/2026-08-18-in-job-partitioned-coverage.md b/.agents/notes/implemented/process/2026-08-18-in-job-partitioned-coverage.md
index f86c2dffb6..532c145f5b 100644
--- a/.agents/notes/implemented/process/2026-08-18-in-job-partitioned-coverage.md
+++ b/.agents/notes/implemented/process/2026-08-18-in-job-partitioned-coverage.md
@@ -28,7 +28,7 @@ A normal failed test still emits a blob through `--coverage.reportOnFailure`, al
## Verification
-`scripts/coverage-partitions.spec.ts` pins argument construction, package-script separator removal, one-worker partitions, the single merged threshold command, failed-test merging, failure diagnostics before complete-blob validation, waiting for sibling partitions after a spawn failure, and link-safe cleanup. `scripts/run-gates.spec.ts` pins opt-in selection, invalid-count rejection, the complete Windows inventory with its blocking split, and unbuffered streamed output.
+`scripts/coverage-partitions.spec.ts` pins argument construction, package-script separator removal, one-worker partitions, the single merged threshold command, failed-test merging, failure diagnostics before complete-blob validation, waiting for sibling partitions after a spawn failure, and link-safe cleanup. `scripts/run-gates.spec.ts` pins opt-in selection, invalid-count rejection, the complete Windows inventory with its blocking split, and unbuffered streamed output. React fake-timer cases that can move between partitions advance timers inside `act()`; geometry-dependent portal tests stub their element rectangles so a different shard schedule cannot turn deferred updates or jsdom coordinates into coverage-only failures.
Completed native Windows comparisons measured two partitions near 405 seconds and sixteen partitions at 112.66–122.01 seconds, but the sixteen-way schedule could put more than twenty active execution units beside build and exempt coverage on a 16-core runner. Eight partitions keep separate-process isolation while accepting a longer feedback path for a materially lower peak. Two Linux samples measured the conservative two-partition configuration at 276.68 and 282.27 seconds; that configuration was stable but halved the ordinary path's four instrumented workers. Four partitions restore that fan-out, for six total coverage execution units on the 16-core hosted runner and at most 36 across the failover VM's six runner instances. These values come from completed runs or fixed capacity bounds; an unfinished run crossing an arbitrary elapsed-time mark is not evidence for increasing concurrency.
diff --git a/.agents/notes/implemented/process/2026-08-18-in-job-partitioned-coverage.zh.md b/.agents/notes/implemented/process/2026-08-18-in-job-partitioned-coverage.zh.md
index 62bb77511d..dc8a089a7c 100644
--- a/.agents/notes/implemented/process/2026-08-18-in-job-partitioned-coverage.zh.md
+++ b/.agents/notes/implemented/process/2026-08-18-in-job-partitioned-coverage.zh.md
@@ -28,7 +28,7 @@ Status: implemented
## 验证
-`scripts/coverage-partitions.spec.ts` 固定了参数构造、包脚本分隔符移除、单 worker 分区、唯一一次合并阈值命令、失败测试合并、完整 blob 校验前的失败诊断、spawn 失败后等待兄弟分区,以及链接安全清理。`scripts/run-gates.spec.ts` 固定了显式启用、非法数量拒绝、完整 Windows 清单及其阻断性划分,以及不缓冲的流式输出。
+`scripts/coverage-partitions.spec.ts` 固定了参数构造、包脚本分隔符移除、单 worker 分区、唯一一次合并阈值命令、失败测试合并、完整 blob 校验前的失败诊断、spawn 失败后等待兄弟分区,以及链接安全清理。`scripts/run-gates.spec.ts` 固定了显式启用、非法数量拒绝、完整 Windows 清单及其阻断性划分,以及不缓冲的流式输出。可能在分区间移动的 React fake-timer 用例会在 `act()` 内推进计时器;依赖几何位置的 portal 测试会固定元素矩形,使不同分片调度不会把延迟更新或 jsdom 坐标变成只在覆盖率运行中出现的失败。
已完成的原生 Windows 对比中,双分区耗时约 405 秒,16 分区耗时 112.66–122.01 秒,但 16 路调度与构建、豁免覆盖率并行时,会在 16 核运行器上形成超过 20 个活动执行单元。8 个分区继续保留独立进程隔离,同时接受更长的反馈路径,以显著降低峰值。两个 Linux 样本中,保守的双分区配置耗时 276.68 秒和 282.27 秒;该配置运行稳定,却把普通路径原有的 4 个插桩 worker 减半。4 个分区恢复这份并发,使 16 核托管 runner 上的覆盖率执行单元总数为 6,故障切换虚拟机的 6 个 runner 实例最多合计 36 个执行单元。这些数值来自完整运行或固定容量上限;运行尚未结束时跨过任意耗时刻度,不构成增加并发的证据。
diff --git a/apps/web/tests/skill-tool-row.e2e.ts b/apps/web/tests/skill-tool-row.e2e.ts
index 5c23f99935..06a2d2456b 100644
--- a/apps/web/tests/skill-tool-row.e2e.ts
+++ b/apps/web/tests/skill-tool-row.e2e.ts
@@ -68,6 +68,7 @@ describe.skipIf(MODE === 'record')('web e2e: dedicated Skill tool row', () => {
const snapshot = (await captureStableAria(page, '[class*="centerCol"]', scaffold.workspaceCwd))
.replace(/\b\d{1,2}\/\d{1,2}(?= \{\{clock\}\})/g, '{{date}}')
+ .replace(/\{\{date\}\} (?=\{\{clock\}\} Ran for)/g, '')
.split(SEED_ID).join('{{seededId}}')
await compareOrRefreshGolden(UI_EXPECTED, snapshot, MODE)
expect(tripwire.pageErrors).toEqual([])
diff --git a/apps/web/tests/snapshots/skill-tool-row/ui.expected.md b/apps/web/tests/snapshots/skill-tool-row/ui.expected.md
index 574fce7fae..36b5ebfeec 100644
--- a/apps/web/tests/snapshots/skill-tool-row/ui.expected.md
+++ b/apps/web/tests/snapshots/skill-tool-row/ui.expected.md
@@ -40,7 +40,7 @@
- img
- button "Branch into a new conversation":
- img
-- text: {{date}} {{clock}} Ran for {{duration}} TTFT {{duration}} {{throughput}} tok/s
+- text: {{clock}} Ran for {{duration}} TTFT {{duration}} {{throughput}} tok/s
- textbox "Message the agent"
- button "Commands":
- img
diff --git a/packages/client/ui-subagent/tests/conversation-ui.client.spec.tsx b/packages/client/ui-subagent/tests/conversation-ui.client.spec.tsx
index 3bccfc9c6a..7c4ff55250 100644
--- a/packages/client/ui-subagent/tests/conversation-ui.client.spec.tsx
+++ b/packages/client/ui-subagent/tests/conversation-ui.client.spec.tsx
@@ -228,33 +228,42 @@ describe('SubagentHeaderLineage', () => {
it('opens only on hover and preserves the portaled-menu crossing grace', async () => {
vi.useFakeTimers()
+ const advance = async (duration: number): Promise => {
+ await act(async () => { await vi.advanceTimersByTimeAsync(duration) })
+ }
const view = render()
const trigger = screen.getByRole('button', { name: /2 个子代理/ })
+ const triggerRect = vi.spyOn(trigger, 'getBoundingClientRect')
+ .mockReturnValue({ bottom: 40, left: 50 } as DOMRect)
fireEvent.click(trigger)
expect(screen.queryByRole('tree')).toBeNull()
fireEvent.mouseEnter(trigger.parentElement!)
- await vi.advanceTimersByTimeAsync(149)
+ await advance(149)
expect(screen.queryByRole('tree')).toBeNull()
- await vi.advanceTimersByTimeAsync(1)
+ await advance(1)
const tree = screen.getByRole('tree')
+ expect(tree.style.top).toBe('45px')
+ triggerRect.mockReturnValue({ bottom: 60, left: 70 } as DOMRect)
fireEvent.resize(window)
+ expect(tree.style.top).toBe('65px')
+ expect(tree.style.left).toBe('70px')
fireEvent.mouseLeave(trigger.parentElement!)
fireEvent.mouseEnter(tree)
- await vi.advanceTimersByTimeAsync(120)
+ await advance(120)
expect(screen.getByRole('tree')).toBeTruthy()
fireEvent.mouseLeave(tree)
- await vi.advanceTimersByTimeAsync(119)
+ await advance(119)
expect(screen.getByRole('tree')).toBeTruthy()
- await vi.advanceTimersByTimeAsync(1)
+ await advance(1)
expect(screen.queryByRole('tree')).toBeNull()
hoverCatalog(trigger)
fireEvent.mouseLeave(trigger.parentElement!)
view.unmount()
- await vi.advanceTimersByTimeAsync(120)
+ await advance(120)
})
it('cancels a pending hover when the trigger becomes hidden', async () => {
diff --git a/packages/experimental/webworker-runtime/tests/compile/transform-corpus-check.ts b/packages/experimental/webworker-runtime/tests/compile/transform-corpus-check.ts
index 8064764f58..a28bcec37a 100644
--- a/packages/experimental/webworker-runtime/tests/compile/transform-corpus-check.ts
+++ b/packages/experimental/webworker-runtime/tests/compile/transform-corpus-check.ts
@@ -64,7 +64,7 @@ const repositoryRoot = fileURLToPath(new URL('../../../../../', import.meta.url)
const BASELINE_EXEMPT: ReadonlyMap = new Map([
['packages/client/ui-primitives/lib/index.js', 'imports .css, which bare Node cannot load'],
['packages/client/web/lib/index.js', 'imports .css, which bare Node cannot load'],
- ['packages/sandbox/sandbox-windows-acl/lib/index.js', 'koffi type-name collision on a second load'],
+ ['packages/subprocess/win32-process/lib/index.js', 'koffi type-name collision on a second load'],
['packages/test-support/client-runtime/lib/index.js', "needs vitest's internal state"],
])
From 1d6f84ff42cbc7b326f537a2f3928e76daff7b0c Mon Sep 17 00:00:00 2001
From: Tianyi Cui <53024+tianyicui@users.noreply.github.com>
Date: Sat, 22 Aug 2026 02:31:11 +0800
Subject: [PATCH 2/2] test(ci): apply review feedback
---
.../2026-08-20-webworker-pack-lowering-and-preview.i18n.yaml | 2 +-
.../2026-08-20-webworker-pack-lowering-and-preview.zh.md | 2 +-
.../feature/2026-08-06-web-skill-tool-row.i18n.yaml | 4 ++--
.../implemented/feature/2026-08-06-web-skill-tool-row.md | 2 +-
.../implemented/feature/2026-08-06-web-skill-tool-row.zh.md | 2 +-
.../client/ui-subagent/tests/conversation-ui.client.spec.tsx | 1 +
6 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/.agents/notes/implemented/architecture/2026-08-20-webworker-pack-lowering-and-preview.i18n.yaml b/.agents/notes/implemented/architecture/2026-08-20-webworker-pack-lowering-and-preview.i18n.yaml
index fe1745817d..b93c9676cb 100644
--- a/.agents/notes/implemented/architecture/2026-08-20-webworker-pack-lowering-and-preview.i18n.yaml
+++ b/.agents/notes/implemented/architecture/2026-08-20-webworker-pack-lowering-and-preview.i18n.yaml
@@ -3,4 +3,4 @@
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-08-20-webworker-pack-lowering-and-preview.md
2026-08-20-webworker-pack-lowering-and-preview.md: 37c7730c5da664560156a8e4bd9ba594c78369ee
-2026-08-20-webworker-pack-lowering-and-preview.zh.md: 833dc13d36c367faf6c25e8c4a307890f54d3176
+2026-08-20-webworker-pack-lowering-and-preview.zh.md: 09d9356ee8744ba2406bd765a6ca6a060f93853a
diff --git a/.agents/notes/implemented/architecture/2026-08-20-webworker-pack-lowering-and-preview.zh.md b/.agents/notes/implemented/architecture/2026-08-20-webworker-pack-lowering-and-preview.zh.md
index 833dc13d36..09d9356ee8 100644
--- a/.agents/notes/implemented/architecture/2026-08-20-webworker-pack-lowering-and-preview.zh.md
+++ b/.agents/notes/implemented/architecture/2026-08-20-webworker-pack-lowering-and-preview.zh.md
@@ -30,6 +30,6 @@
- `lib/worker.js` 不含解析器(当刀落时为 423.5 kB → 246.3 kB,早于 shell 进程层落地)。
- `diff dist/index.html dist/preview.html` 恰为一个 script 标签;`packages/experimental/webworker-packer/tests/image-loadable.spec.ts` 钉住装载器契约的两半,`apps/web/tests/preview-boot.e2e.ts` 在 web 浏览器车道钉住 preview 可用性(boot 到可交互页面),替代已撤编的 `apps/web/scripts/preview/` 探针脚本。
-- 转换 corpus 会先通过 Node 导入每个已构建 bundle,再比较 lowered export。固定豁免会点名真正不可导入的 bundle,并在其恢复可导入时失败:Win32 process primitive 成为 Koffi 类型 owner 后,由 `win32-process` 承担重复类型豁免,`sandbox-windows-acl` 不再承担该豁免。
+- 转换 corpus 会先通过 Node 导入每个已构建 bundle,再比较 lowered export。固定豁免会点名真正不可导入的 bundle,并在其恢复可导入时失败:`win32-process` 是 Koffi 类型 owner 并承担重复类型豁免;`sandbox-windows-acl` 可正常导入,不承担该豁免。
- served 的 `` 锚存在的原因是:相对资产 URL 在 SPA fallback 深路径下会解析进请求目录;只有与相对构建 base 一起才可移除它。
- 镜像以确定性 gzip 压缩的 tar 交付(`vfs-image.tar.gz`;MTIME 0、OS 字节 0xff):静态托管不压缩二进制 content-type(类型白名单、CDN 尺寸帽),压缩必须随制品走;worker 用浏览器原生 `DecompressionStream` 在下载的同时解压 fetch body。
diff --git a/.agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.i18n.yaml b/.agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.i18n.yaml
index 9ff850b475..e340548145 100644
--- a/.agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.i18n.yaml
+++ b/.agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.i18n.yaml
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.md
-2026-08-06-web-skill-tool-row.md: c07b0b724293e74d5e7649326110cf8d7237dd0d
-2026-08-06-web-skill-tool-row.zh.md: 915e1209768af0ee30dc923afd3be7a3e17e09c7
+2026-08-06-web-skill-tool-row.md: a78afd5d375d2cecd806ade663b4a5b7511ae279
+2026-08-06-web-skill-tool-row.zh.md: 469f9510ea5f31ceb8fb177432b090d91c8a5df8
diff --git a/.agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.md b/.agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.md
index c07b0b7242..a78afd5d37 100644
--- a/.agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.md
+++ b/.agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.md
@@ -14,7 +14,7 @@ The Web transcript renders `skill` calls through the generic fallback row, so a
The collapsed row uses a 14-pixel document-and-sparkle glyph and the Bash row's neutral hierarchy: tertiary glyph, secondary `Skill` title, caption separator, and tertiary skill name. Running, failed, and interrupted calls retain the transcript's shimmer, error dot and first-line summary, and warning dot semantics. A settled call expands through the whole summary row into a 260-pixel bounded `Instructions` card containing the exact durable result text; the existing trajectory `Inspect` handoff remains available below the card.
-The row derives every visible value from a paired call/result slice in the current runtime window. It reads the skill name from the recorded `name` argument and the instructions from durable result content, and never joins the current skill catalog for descriptions or provider metadata. If pagination leaves the call outside the window, the result has no tool identity and remains on the generic fallback rather than extending the history wire contract. The existing ACP `skill-load` recording is seeded through the real Web persistence and composition path for a keyless interaction and accessibility snapshot. The snapshot removes a calendar date only when it immediately precedes the normalized clock and `Ran for` footer; the clock remains, while local and UTC hosts no longer disagree at a same-day boundary.
+The row derives every visible value from a paired call/result slice in the current runtime window. It reads the skill name from the recorded `name` argument and the instructions from durable result content, and never joins the current skill catalog for descriptions or provider metadata. If pagination leaves the call outside the window, the result has no tool identity and remains on the generic fallback rather than extending the history wire contract. The existing ACP `skill-load` recording is seeded through the real Web persistence and composition path for a keyless interaction and accessibility snapshot. The snapshot removes a calendar date only when it immediately precedes the normalized clock and `Ran for` footer; the clock remains, so hosts in different timezones produce the same snapshot at a same-day boundary.
## Alternatives considered
diff --git a/.agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.zh.md b/.agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.zh.md
index 915e120976..469f9510ea 100644
--- a/.agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.zh.md
+++ b/.agents/notes/implemented/feature/2026-08-06-web-skill-tool-row.zh.md
@@ -14,7 +14,7 @@ Web transcript(文本记录)通过通用后备行渲染 `skill` 调用,使
收起的行使用 14 像素的文档与闪光组合图标,并沿用 Bash 行的中性色层级:图标采用三级色,`Skill` 标题采用二级色,分隔符采用 caption 色,skill 名称采用三级色。运行、失败和中断调用分别沿用 transcript 的扫光、错误状态点加首行摘要,以及警告状态点语义。已结算调用可以通过整个摘要行展开一个高度上限为 260 像素的 `Instructions` 卡片,其中原样呈现持久化结果文本;用于跳转至 trajectory 的现有 `Inspect` 入口仍保留在卡片下方。
-该行的所有可见值均派生自当前 runtime 窗口中已配对的调用/结果片段。skill 名称来自已记录的 `name` 参数,指令来自持久化的结果内容;该行绝不关联当前 skill 目录来读取描述或提供方元数据。如果分页将调用留在窗口外,结果便没有工具身份,并继续使用通用后备路径,而不是扩展 history 协议约定。现有的 ACP(Agent Client Protocol)`skill-load` 记录经由真实的 Web 持久化与组合路径写入,用于无需密钥的交互和无障碍快照。快照只会在日历日期紧邻规范化时钟与 `Ran for` 页脚时移除该日期;时钟仍保留,而本地时区与 UTC 宿主不会再在同日边界产生分歧。
+该行的所有可见值均派生自当前 runtime 窗口中已配对的调用/结果片段。skill 名称来自已记录的 `name` 参数,指令来自持久化的结果内容;该行绝不关联当前 skill 目录来读取描述或提供方元数据。如果分页将调用留在窗口外,结果便没有工具身份,并继续使用通用后备路径,而不是扩展 history 协议约定。现有的 ACP(Agent Client Protocol)`skill-load` 记录经由真实的 Web 持久化与组合路径写入,用于无需密钥的交互和无障碍快照。快照只会在日历日期紧邻规范化时钟与 `Ran for` 页脚时移除该日期;时钟仍保留,使不同时区的宿主在同日边界产出相同快照。
## 考虑过的替代方案
diff --git a/packages/client/ui-subagent/tests/conversation-ui.client.spec.tsx b/packages/client/ui-subagent/tests/conversation-ui.client.spec.tsx
index 7c4ff55250..d4001659bb 100644
--- a/packages/client/ui-subagent/tests/conversation-ui.client.spec.tsx
+++ b/packages/client/ui-subagent/tests/conversation-ui.client.spec.tsx
@@ -245,6 +245,7 @@ describe('SubagentHeaderLineage', () => {
await advance(1)
const tree = screen.getByRole('tree')
expect(tree.style.top).toBe('45px')
+ expect(tree.style.left).toBe('50px')
triggerRect.mockReturnValue({ bottom: 60, left: 70 } as DOMRect)
fireEvent.resize(window)
expect(tree.style.top).toBe('65px')