test(web): separate session snapshots from goldens

This commit is contained in:
Tianyi Cui
2026-08-24 21:36:31 +08:00
parent 33faf7f35f
commit 6189e4a374
259 changed files with 233 additions and 129 deletions
@@ -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-07-30-command-row-copy-contract.md
2026-07-30-command-row-copy-contract.md: f6d5199389b3907780c501894e2861e6add85e77
2026-07-30-command-row-copy-contract.zh.md: 86f0c044e841a6a0148b1f785582868bba5bb3d0
2026-07-30-command-row-copy-contract.md: d410adf62dbbc4445936c70309d5902bc184b16f
2026-07-30-command-row-copy-contract.zh.md: 0f680f9beb8b335dd6311cadc6c7e022809fb8f2
@@ -32,4 +32,4 @@ The log is unchanged: `command/run` keeps the structured `name`/`args` split, so
## Consequences
Every command row gets shorter, and the rule scales: a new command's author writes its outcome without knowing which surface renders it, and no surface has to de-duplicate. The cost is that the dispatched arguments leave the collapsed row — while a command is still executing the row shows only its name and `执行中…` — and that the no-caption rule is a convention the reviewer enforces, not a gate. The `/permission` texts are pinned by the permission package's command tests, and the assembled row copy by the [seeded-history](../../../../apps/web/tests/snapshots/seeded-history/command-row.expected.md) web golden, which reaches a real settled command row keylessly because `/permission` runs entirely on the host.
Every command row gets shorter, and the rule scales: a new command's author writes its outcome without knowing which surface renders it, and no surface has to de-duplicate. The cost is that the dispatched arguments leave the collapsed row — while a command is still executing the row shows only its name and `执行中…` — and that the no-caption rule is a convention the reviewer enforces, not a gate. The `/permission` texts are pinned by the permission package's command tests, and the assembled row copy by the [seeded-history](../../../../snapshots/web/seeded-history/command-row.expected.md) web golden, which reaches a real settled command row keylessly because `/permission` runs entirely on the host.
@@ -32,4 +32,4 @@ Web 命令条目由一对落库的[命令生命周期事件](../../proposed/arch
## 后果
每一条命令条目都变短了,而且这条规则可扩展:新命令的作者写结果时无需知道由哪个界面渲染,任何界面也都不必再去重。代价是分派参数离开了折叠行——命令仍在执行时,行上只有名字和 `执行中…`——以及「不加题头」这条规则是靠评审执行的约定,而非门禁。`/permission` 的文案由 permission 包的命令测试钉住,装配后的行文案由 [seeded-history](../../../../apps/web/tests/snapshots/seeded-history/command-row.expected.md) web 预期输出钉住:由于 `/permission` 完全在 host 上执行,该预期输出无需密钥即可覆盖一条真实的已落定命令条目。
每一条命令条目都变短了,而且这条规则可扩展:新命令的作者写结果时无需知道由哪个界面渲染,任何界面也都不必再去重。代价是分派参数离开了折叠行——命令仍在执行时,行上只有名字和 `执行中…`——以及「不加题头」这条规则是靠评审执行的约定,而非门禁。`/permission` 的文案由 permission 包的命令测试钉住,装配后的行文案由 [seeded-history](../../../../snapshots/web/seeded-history/command-row.expected.md) web 预期输出钉住:由于 `/permission` 完全在 host 上执行,该预期输出无需密钥即可覆盖一条真实的已落定命令条目。
@@ -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-08-bounded-session-persistence-write-batching.md
2026-08-08-bounded-session-persistence-write-batching.md: 6d77ef90276dcf143bb63019f801379b702b43b2
2026-08-08-bounded-session-persistence-write-batching.zh.md: e773f20ade706e97a5f84d4a4cc15cc9d3b2d836
2026-08-08-bounded-session-persistence-write-batching.md: fc22a10537ebb9009ab1ae1ec21ca625c9025651
2026-08-08-bounded-session-persistence-write-batching.zh.md: c2763e157fcfc2e004b14116694054c604fbfb9c
@@ -12,7 +12,7 @@ Dropping chunk events or replacing them with assembled messages would reduce log
### Quantified baseline
Repository fixtures make the logical volume concrete. Decoding the current packed rows in [`goal-multi-turn-actions`](../../../../apps/web/tests/snapshots/goal-multi-turn-actions/session.jsonl) yields 2,098 events: 2,017 chunks (96.1%). Their unpacked JSONL lines occupy 332,647 of 379,225 event bytes (87.7%), while chunk packing reduces the committed file to 89,176 bytes and 182 storage rows, including 23 packed chunk rows. [`permission-policy-context`](../../../../apps/web/tests/snapshots/permission-policy-context/session.jsonl) yields 813 events: 746 chunks (91.8%) and 118,935 of 184,821 unpacked event bytes (64.4%); its packed file is 84,917 bytes and 123 storage rows, including 14 packed rows. These are tracked deterministic fixtures, not a production workload distribution, but they demonstrate why deleting chunks would reduce logical volume and why the existing packed-row layout already removes much of their JSON envelope cost.
Repository fixtures make the logical volume concrete. Decoding the current packed rows in [`goal-multi-turn-actions`](../../../../snapshots/web/goal-multi-turn-actions/session.jsonl) yields 2,098 events: 2,017 chunks (96.1%). Their unpacked JSONL lines occupy 332,647 of 379,225 event bytes (87.7%), while chunk packing reduces the committed file to 89,176 bytes and 182 storage rows, including 23 packed chunk rows. [`permission-policy-context`](../../../../snapshots/web/permission-policy-context/session.jsonl) yields 813 events: 746 chunks (91.8%) and 118,935 of 184,821 unpacked event bytes (64.4%); its packed file is 84,917 bytes and 123 storage rows, including 14 packed rows. These are tracked deterministic fixtures, not a production workload distribution, but they demonstrate why deleting chunks would reduce logical volume and why the existing packed-row layout already removes much of their JSON envelope cost.
SQLite stores one row per logical event, so those same logical logs would retain 2,098 and 813 event rows respectively; batching does not change those counts. JSONL writes one Zstandard frame and fsync per durable append batch, while SQLite performs one transaction and one session-revision increment per batch. Runtime files do not record former append boundaries, so fixture row counts cannot honestly be presented as fsync or transaction counts.
@@ -12,7 +12,7 @@ Status: implemented
### 量化基线
仓库 fixture(测试前置数据)让逻辑数据量有了具体依据。对当前 [`goal-multi-turn-actions`](../../../../apps/web/tests/snapshots/goal-multi-turn-actions/session.jsonl) 中的打包行进行解码,可得到 2,098 个事件,其中 2,017 个是分片(96.1%)。这些分片解包后的 JSONL 行共 332,647 字节,占全部事件 379,225 字节的 87.7%;分片打包则把仓库中的已提交文件缩小到 89,176 字节和 182 个存储行,其中包括 23 个打包分片行。[`permission-policy-context`](../../../../apps/web/tests/snapshots/permission-policy-context/session.jsonl) 可得到 813 个事件,其中 746 个是分片(91.8%);这些分片解包后的 JSONL 行共 118,935 字节,占全部事件 184,821 字节的 64.4%。其打包文件为 84,917 字节,共 123 个存储行,其中包括 14 个打包行。这些是纳入版本控制的确定性 fixture,不代表生产工作负载分布;但它们说明了删除分片为何会降低逻辑数据量,也说明现有打包行布局已经消除了大量 JSON 包装开销。
仓库 fixture(测试前置数据)让逻辑数据量有了具体依据。对当前 [`goal-multi-turn-actions`](../../../../snapshots/web/goal-multi-turn-actions/session.jsonl) 中的打包行进行解码,可得到 2,098 个事件,其中 2,017 个是分片(96.1%)。这些分片解包后的 JSONL 行共 332,647 字节,占全部事件 379,225 字节的 87.7%;分片打包则把仓库中的已提交文件缩小到 89,176 字节和 182 个存储行,其中包括 23 个打包分片行。[`permission-policy-context`](../../../../snapshots/web/permission-policy-context/session.jsonl) 可得到 813 个事件,其中 746 个是分片(91.8%);这些分片解包后的 JSONL 行共 118,935 字节,占全部事件 184,821 字节的 64.4%。其打包文件为 84,917 字节,共 123 个存储行,其中包括 14 个打包行。这些是纳入版本控制的确定性 fixture,不代表生产工作负载分布;但它们说明了删除分片为何会降低逻辑数据量,也说明现有打包行布局已经消除了大量 JSON 包装开销。
SQLite 每个逻辑事件存储一行,因此同样的逻辑日志会分别保留 2,098 和 813 个事件行;批处理不会改变这些数量。JSONL 每个持久化追加批次会写入一个 Zstandard 帧并执行一次 fsync,SQLite 每个批次会执行一次事务并递增一次会话修订版本。运行时文件不记录原有追加边界,因此不能把 fixture 的存储行数当作 fsync 或事务次数。
@@ -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-07-30-web-search-card.md
2026-07-30-web-search-card.md: 930a705fc227d7961e9cb1a51b0b04774a62c6a4
2026-07-30-web-search-card.zh.md: 7771097423bda24c7fe254d5747205c1f06a5474
2026-07-30-web-search-card.md: 7b16c401a4cac45a218ba0b42743b38171f99d9e
2026-07-30-web-search-card.zh.md: 4fd653ef519d3ba1cb5e6e3e9c9275b3cc8127bb
@@ -56,7 +56,7 @@ Three sites consume the derivation, mirroring the terminal card's placement exac
`packages/client/ui-primitives/tests/search-block.client.spec.tsx` pins the component at per-file 100%: both kinds, the folded pre-cap total in the summary, the empty arm, per-file collapse/re-expand without touching neighbours, a file header counting as one capped row alongside its matches, the tail slice restoring its owning file header when the cut falls mid-file, the head/tail cap and its expand control across both shapes and the no-tail and default-cap edges, and the copy control writing the whole structured result on the accepted and refused clipboard paths.
`packages/client/ui-tool/tests/search-card.client.spec.tsx` pins the wiring at every render site: `searchCardModel`'s derivation for both kinds, the truncation signal, the replacement title, the recovery text surfaced only when capped, each null arm (running, no views, generic, terminal, unknown card, an uncompiled `kind`, and a known kind with a missing/malformed shape); the chat row's expand-gated matches and paths bodies through `GenericToolCard` (with the recovery footer) against the non-search args-JSON body; `SearchRow`'s resident card for both kinds, its recovery footer, its fallback body for both an errored search and a settled cardless result, its agreement with the summary row's run state, the replacement-title precedence, and the keyed registration under both `grep` and `glob` with one component; and the details panel's Output section for both kinds (with the recovery footer) against the non-search flattened form. `packages/client/ui-tool/src/*` sits on the coverage exclude list, so this file is written against no gate pressure. `packages/client/connection/src/client/fixture.ts` gains a `grep` turn emitting `kind: 'matches'` (three files, twelve rows over the row cap, `truncated` with a spill-recovery footer, so it exercises the head/tail cap and the recovery footer in the assembled snapshot) and a `glob` turn emitting `kind: 'paths'`, both driving the built-boot snapshot and the live `?fixture` server. `apps/web/tests/search-card.snapshot.ts` is the assembled-output check the repo contract asks for: it boots the real built `client.js` bundles through the keyless fixture transport, opens the fixture session, and pins the grep card's assembled shape — kind, truncation summary, the head/tail slice, and its expand control — under `apps/web/tests/snapshots/search-card/`, so a broken SearchRow registration or a dropped card fails a golden the built-boot smoke (boot-only by contract) cannot.
`packages/client/ui-tool/tests/search-card.client.spec.tsx` pins the wiring at every render site: `searchCardModel`'s derivation for both kinds, the truncation signal, the replacement title, the recovery text surfaced only when capped, each null arm (running, no views, generic, terminal, unknown card, an uncompiled `kind`, and a known kind with a missing/malformed shape); the chat row's expand-gated matches and paths bodies through `GenericToolCard` (with the recovery footer) against the non-search args-JSON body; `SearchRow`'s resident card for both kinds, its recovery footer, its fallback body for both an errored search and a settled cardless result, its agreement with the summary row's run state, the replacement-title precedence, and the keyed registration under both `grep` and `glob` with one component; and the details panel's Output section for both kinds (with the recovery footer) against the non-search flattened form. `packages/client/ui-tool/src/*` sits on the coverage exclude list, so this file is written against no gate pressure. `packages/client/connection/src/client/fixture.ts` gains a `grep` turn emitting `kind: 'matches'` (three files, twelve rows over the row cap, `truncated` with a spill-recovery footer, so it exercises the head/tail cap and the recovery footer in the assembled snapshot) and a `glob` turn emitting `kind: 'paths'`, both driving the built-boot snapshot and the live `?fixture` server. `apps/web/tests/search-card.snapshot.ts` is the assembled-output check the repo contract asks for: it boots the real built `client.js` bundles through the keyless fixture transport, opens the fixture session, and pins the grep card's assembled shape — kind, truncation summary, the head/tail slice, and its expand control — under `apps/web/tests/goldens/search-card/`, so a broken SearchRow registration or a dropped card fails a golden the built-boot smoke (boot-only by contract) cannot.
## Related
@@ -56,7 +56,7 @@ Status: implemented
`packages/client/ui-primitives/tests/search-block.client.spec.tsx` 以 per-file 100% 覆盖固定组件:两种 kind、折入摘要的截断前总数、空结果分支、逐文件折叠/再展开且不影响邻居、一个文件头与匹配行一样,在高度上限中单独计为一行、切口落在文件中间时尾部切片恢复其所属文件头、跨两种形态的头/尾上限及其展开控件(含无尾与默认上限的边界),以及复制控件在接受与拒绝的剪贴板路径上写入整个结构化结果。
`packages/client/ui-tool/tests/search-card.client.spec.tsx` 固定每个渲染点的接线:`searchCardModel` 对两种 kind 的推导、截断信号、替换标题、仅在截断时暴露的恢复文本,以及每个 null 分支(运行中、无视图、generic、terminal、未知卡片、本版本无法编译的 `kind`、以及一个形态缺失/错误的已知 kind);通过 `GenericToolCard` 的展开门控 matches 与 paths body(含恢复脚注),对照非搜索的 args-JSON body`SearchRow` 对两种 kind 的常驻卡片、它的恢复脚注、它对出错搜索与已结算无卡片结果两者的 fallback body、它与摘要行运行状态的一致、替换标题优先级,以及一个组件在 `grep``glob` 两个键下的 keyed 注册;以及 details panel 的 Output 段对两种 kind(含恢复脚注),对照非搜索的压平形态。`packages/client/ui-tool/src/*` 在覆盖排除清单上,因此该文件不受 gate 压力。`packages/client/connection/src/client/fixture.ts` 新增一个发出 `kind: 'matches'``grep` turn(三个文件、十二行超过行内上限、`truncated` 且带溢出恢复脚注,因此在组装快照里同时演练头/尾上限与恢复脚注)与一个发出 `kind: 'paths'``glob` turn,两者都驱动 built-boot snapshot 与实时 `?fixture` 服务。`apps/web/tests/search-card.snapshot.ts` 是仓库约定要求的组装输出检查:它通过 keyless fixture 传输启动真实构建的 `client.js` bundle,打开 fixture 会话,并把 grep 卡片的组装形态——kind、截断摘要、头/尾切片及其展开控件——固定在 `apps/web/tests/snapshots/search-card/` 下,因此一个损坏的 SearchRow 注册或被丢弃的卡片会让一个 golden 失败,而 built-boot smoke(按约定只测启动)无法捕获它。
`packages/client/ui-tool/tests/search-card.client.spec.tsx` 固定每个渲染点的接线:`searchCardModel` 对两种 kind 的推导、截断信号、替换标题、仅在截断时暴露的恢复文本,以及每个 null 分支(运行中、无视图、generic、terminal、未知卡片、本版本无法编译的 `kind`、以及一个形态缺失/错误的已知 kind);通过 `GenericToolCard` 的展开门控 matches 与 paths body(含恢复脚注),对照非搜索的 args-JSON body`SearchRow` 对两种 kind 的常驻卡片、它的恢复脚注、它对出错搜索与已结算无卡片结果两者的 fallback body、它与摘要行运行状态的一致、替换标题优先级,以及一个组件在 `grep``glob` 两个键下的 keyed 注册;以及 details panel 的 Output 段对两种 kind(含恢复脚注),对照非搜索的压平形态。`packages/client/ui-tool/src/*` 在覆盖排除清单上,因此该文件不受 gate 压力。`packages/client/connection/src/client/fixture.ts` 新增一个发出 `kind: 'matches'``grep` turn(三个文件、十二行超过行内上限、`truncated` 且带溢出恢复脚注,因此在组装快照里同时演练头/尾上限与恢复脚注)与一个发出 `kind: 'paths'``glob` turn,两者都驱动 built-boot snapshot 与实时 `?fixture` 服务。`apps/web/tests/search-card.snapshot.ts` 是仓库约定要求的组装输出检查:它通过 keyless fixture 传输启动真实构建的 `client.js` bundle,打开 fixture 会话,并把 grep 卡片的组装形态——kind、截断摘要、头/尾切片及其展开控件——固定在 `apps/web/tests/goldens/search-card/` 下,因此一个损坏的 SearchRow 注册或被丢弃的卡片会让一个 golden 失败,而 built-boot smoke(按约定只测启动)无法捕获它。
## Related
@@ -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/testing/2026-07-30-web-browser-snapshot-ci-gate.md
2026-07-30-web-browser-snapshot-ci-gate.md: abb197f2a8e3488e2ae1edc7c2e77cbdcf919556
2026-07-30-web-browser-snapshot-ci-gate.zh.md: 0239ae6062d2828b8b92683d4b0e7103205756fc
2026-07-30-web-browser-snapshot-ci-gate.md: e94141070ba283434f49108899f743fab6073ebc
2026-07-30-web-browser-snapshot-ci-gate.zh.md: 9976034bb0ff8ba0435be41fe9e6bd406267fadb
@@ -6,7 +6,7 @@ English | [中文](2026-07-30-web-browser-snapshot-ci-gate.zh.md)
## Problem
The [keyless web browser e2e lane](2026-07-24-web-gui-browser-e2e-lane.md) runs only under the local `pnpm run test:web` command, and PR CI does not compare `apps/web/tests/snapshots/**/*.expected.md`. A PR that changes user-visible web output can therefore remain green when its expected outputs are not refreshed; when any later branch explicitly runs `DSH_SNAPSHOT=refresh`, it backfills the earlier change and produces a diff unrelated to that branch. Ordinary local runs already default to read-only replay, so the gap is mandatory enforcement at the PR level, not a ban on writes in refresh mode.
The [keyless web browser e2e lane](2026-07-24-web-gui-browser-e2e-lane.md) runs only under the local `pnpm run test:web` command, and PR CI does not compare Web expectations under `snapshots/web/` or `apps/web/tests/goldens/`. A PR that changes user-visible web output can therefore remain green when its expected outputs are not refreshed; when any later branch explicitly runs `DSH_SNAPSHOT=refresh`, it backfills the earlier change and produces a diff unrelated to that branch. Ordinary local runs already default to read-only replay, so the gap is mandatory enforcement at the PR level, not a ban on writes in refresh mode.
## Decision
@@ -6,7 +6,7 @@ Status: implemented
## 问题
[无密钥 Web 浏览器 e2e 车道](2026-07-24-web-gui-browser-e2e-lane.zh.md)只由本地 `pnpm run test:web` 运行,PR CI 不比较 `apps/web/tests/snapshots/**/*.expected.md`。因此,改变用户可见 Web 输出的 PR 可以在漏刷预期输出时保持绿色;后来任意分支显式运行 `DSH_SNAPSHOT=refresh`,都会替前序变更补账并产生与本分支无关的 diff。普通本地运行已经默认使用只读 replay,缺口是 PR 级的强制执行,而不是禁止 refresh 写入。
[无密钥 Web 浏览器 e2e 车道](2026-07-24-web-gui-browser-e2e-lane.zh.md)只由本地 `pnpm run test:web` 运行,PR CI 不比较 `snapshots/web/``apps/web/tests/goldens/` 下的 Web 预期输出。因此,改变用户可见 Web 输出的 PR 可以在漏刷预期输出时保持绿色;后来任意分支显式运行 `DSH_SNAPSHOT=refresh`,都会替前序变更补账并产生与本分支无关的 diff。普通本地运行已经默认使用只读 replay,缺口是 PR 级的强制执行,而不是禁止 refresh 写入。
## 决策
+1 -1
View File
@@ -13,7 +13,7 @@ import {
} from './scaffold.ts'
import { ZH_BROWSER_LOCALE, connectFreshWorkspaceZh, saveFailureShot } from './support.ts'
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/access-confirmation', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('./goldens/access-confirmation', import.meta.url))
const UI_EXPECTED = join(SNAPSHOT_DIR, 'ui.expected.md')
const MODE = webSnapshotMode()
+1 -1
View File
@@ -22,7 +22,7 @@ import {
} from './scaffold.ts'
import { ZH_BROWSER_LOCALE, connectFreshWorkspaceZh, saveFailureShot } from './support.ts'
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/agent-preset-authoring', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('./goldens/agent-preset-authoring', import.meta.url))
const SECTION_EXPECTED = join(SNAPSHOT_DIR, 'section.expected.md')
const COPY_DIALOG_EXPECTED = join(SNAPSHOT_DIR, 'copy-dialog.expected.md')
const CREATED_EXPECTED = join(SNAPSHOT_DIR, 'created.expected.md')
+1 -1
View File
@@ -24,7 +24,7 @@ import {
} from './scaffold.ts'
import { connectFreshWorkspace, newEnglishPage, saveFailureShot } from './support.ts'
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/agent-preset-selection', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('./goldens/agent-preset-selection', import.meta.url))
const HERO_EXPECTED = join(SNAPSHOT_DIR, 'hero.expected.md')
const MENU_EXPECTED = join(SNAPSHOT_DIR, 'menu.expected.md')
const HEADER_EXPECTED = join(SNAPSHOT_DIR, 'header.expected.md')
+1 -1
View File
@@ -16,7 +16,7 @@ import {
} from './scaffold.ts'
import { connectFreshWorkspace, newEnglishPage, saveFailureShot } from './support.ts'
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/approval-composer', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('../../../snapshots/web/approval-composer', import.meta.url))
const FIXTURE = join(SNAPSHOT_DIR, 'session.jsonl')
// The golden covers the stable waiting panel; direct assertions cover its answer.
const UI_EXPECTED = join(SNAPSHOT_DIR, 'ui.expected.md')
+2 -2
View File
@@ -16,8 +16,8 @@ import {
} from './scaffold.ts'
import { newEnglishPage, saveFailureShot } from './support.ts'
const FIXTURE = fileURLToPath(new URL('./snapshots/fresh-round-trip/session.jsonl', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/background-job-list', import.meta.url))
const FIXTURE = fileURLToPath(new URL('../../../snapshots/web/fresh-round-trip/session.jsonl', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('../../../snapshots/web/background-job-list', import.meta.url))
const RUNNING_EXPECTED = join(SNAPSHOT_DIR, 'running.expected.md')
const SETTLED_EXPECTED = join(SNAPSHOT_DIR, 'settled.expected.md')
const MODE = webSnapshotMode()
+1 -1
View File
@@ -14,7 +14,7 @@ import {
import { newEnglishPage, saveFailureShot } from './support.ts'
const FIXTURE = fileURLToPath(new URL('../../../snapshots/acp/cancel-tool-calls/session.jsonl', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/bash-abort-row', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('../../../snapshots/web/bash-abort-row', import.meta.url))
const UI_EXPECTED = join(SNAPSHOT_DIR, 'ui.expected.md')
const MODE = webSnapshotMode()
const SEED_ID = 'bash-abort-row-web-e2e'
+2 -2
View File
@@ -13,8 +13,8 @@ import {
} from './scaffold.ts'
import { connectFreshWorkspace, newEnglishPage, saveFailureShot } from './support.ts'
const FIXTURE = fileURLToPath(new URL('./snapshots/code-mode-round/session.jsonl', import.meta.url))
const UI_EXPECTED = fileURLToPath(new URL('./snapshots/code-mode-round/ui.expected.md', import.meta.url))
const FIXTURE = fileURLToPath(new URL('../../../snapshots/web/code-mode-round/session.jsonl', import.meta.url))
const UI_EXPECTED = fileURLToPath(new URL('../../../snapshots/web/code-mode-round/ui.expected.md', import.meta.url))
const MODE = webSnapshotMode()
// Elicits the successful and failed sub-rows this scenario asserts.
+1 -1
View File
@@ -12,7 +12,7 @@ import {
} from './scaffold.ts'
import { newEnglishPage, saveFailureShot } from './support.ts'
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/cold-blank-session', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('./goldens/cold-blank-session', import.meta.url))
const SIDEBAR_EXPECTED = join(SNAPSHOT_DIR, 'sidebar.expected.md')
const MODE = webSnapshotMode()
const SESSION_ID = 'cold-blank-session-web-e2e'
+1 -1
View File
@@ -12,7 +12,7 @@ import {
} from './scaffold.ts'
import { connectFreshWorkspace, newEnglishPage, saveFailureShot } from './support.ts'
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/composer-draft-scroll', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('./goldens/composer-draft-scroll', import.meta.url))
/** Scroll geometry is absent from ARIA snapshots, so this scenario records it directly. */
const GEOMETRY_EXPECTED = join(SNAPSHOT_DIR, 'geometry.expected.md')
const MODE = webSnapshotMode()
+1 -1
View File
@@ -13,7 +13,7 @@ import {
} from './scaffold.ts'
import { newEnglishPage, saveFailureShot } from './support.ts'
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/composer-tab-geometry', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('./goldens/composer-tab-geometry', import.meta.url))
/** Records platform-neutral distances between the two tabs' card rectangles. */
const GEOMETRY_EXPECTED = join(SNAPSHOT_DIR, 'geometry.expected.md')
const MODE = webSnapshotMode()
@@ -31,7 +31,7 @@ import {
} from './scaffold.ts'
import { newEnglishPage, saveFailureShot } from './support.ts'
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/conversation-column-overflow', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('./goldens/conversation-column-overflow', import.meta.url))
/**
* Committed golden of the one-axis relation at every stop. It records
* relations and booleans, never absolute coordinates: the column width follows
+2 -2
View File
@@ -20,8 +20,8 @@ import {
} from './scaffold.ts'
import { connectFreshWorkspace, newEnglishPage, saveFailureShot } from './support.ts'
const FIXTURE = fileURLToPath(new URL('./snapshots/cordis-tool-round/session.jsonl', import.meta.url))
const UI_EXPECTED = fileURLToPath(new URL('./snapshots/cordis-tool-round/ui.expected.md', import.meta.url))
const FIXTURE = fileURLToPath(new URL('../../../snapshots/web/cordis-tool-round/session.jsonl', import.meta.url))
const UI_EXPECTED = fileURLToPath(new URL('../../../snapshots/web/cordis-tool-round/ui.expected.md', import.meta.url))
const MODE = webSnapshotMode()
const CORDIS_TOOLS = ['cordis_inspect_self', 'cordis_define', 'cordis_run', 'cordis_stop'] as const
const PACKAGE_CODE = 'return { name: "snapshot-noop", apply(ctx) {} }'
+2 -2
View File
@@ -18,8 +18,8 @@ import { ZH_BROWSER_LOCALE, connectFreshWorkspaceZh, saveFailureShot } from './s
/** Starts the shipped default on this scenario's declared reasoning model. */
const OVERLAY = fileURLToPath(new URL('./declared-reasoning.overlay.yml', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/declared-reasoning', import.meta.url))
const UI_EXPECTED = fileURLToPath(new URL('./snapshots/declared-reasoning/ui.expected.md', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('./goldens/declared-reasoning', import.meta.url))
const UI_EXPECTED = fileURLToPath(new URL('./goldens/declared-reasoning/ui.expected.md', import.meta.url))
const MODE = webSnapshotMode()
describe.skipIf(MODE === 'record')('web e2e: declared reasoning efforts reach the composer', () => {
@@ -14,10 +14,10 @@ import {
} from './scaffold.ts'
import { connectFreshWorkspace, newEnglishPage, saveFailureShot } from './support.ts'
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/details-session-lifecycle', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('../../../snapshots/web/details-session-lifecycle', import.meta.url))
const HANDLES_EXPECTED = join(SNAPSHOT_DIR, 'handles.expected.md')
const FIXTURE = fileURLToPath(new URL('./snapshots/lifecycle-chrome/session.jsonl', import.meta.url))
const SEED_FIXTURE = fileURLToPath(new URL('./snapshots/seeded-history/seed.jsonl', import.meta.url))
const FIXTURE = fileURLToPath(new URL('../../../snapshots/web/lifecycle-chrome/session.jsonl', import.meta.url))
const SEED_FIXTURE = fileURLToPath(new URL('../../../snapshots/web/seeded-history/seed.jsonl', import.meta.url))
const PROMPT = 'Reply with the single word LIGHTHOUSE and stop.'
const MODE = webSnapshotMode()
+1 -1
View File
@@ -20,7 +20,7 @@ import {
} from './scaffold.ts'
import { connectFreshWorkspace, newEnglishPage, saveFailureShot } from './support.ts'
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/feedback-command', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('../../../snapshots/web/feedback-command', import.meta.url))
const FIXTURE = join(SNAPSHOT_DIR, 'session.jsonl')
const ACK_EXPECTED = join(SNAPSHOT_DIR, 'ack.expected.md')
const MODE = webSnapshotMode()
+1 -1
View File
@@ -22,7 +22,7 @@ import { saveFailureShot } from './support.ts'
const MODE = webSnapshotMode()
const OVERLAY = fileURLToPath(new URL('../../../examples/web-github-review/cordis.yml', import.meta.url))
const EXPECTED = fileURLToPath(new URL('./snapshots/github-ready-review/conversation.expected.md', import.meta.url))
const EXPECTED = fileURLToPath(new URL('./goldens/github-ready-review/conversation.expected.md', import.meta.url))
const PROVIDER = 'github-webhook-review-test'
const MODEL = 'reply'
const SECRET = 'github-webhook-review-secret'
+1 -1
View File
@@ -14,7 +14,7 @@ import {
} from './scaffold.ts'
import { newEnglishPage, saveFailureShot } from './support.ts'
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/goal-bar', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('./goldens/goal-bar', import.meta.url))
const ACTIVE_EXPECTED = join(SNAPSHOT_DIR, 'active.expected.md')
const OVERLAY = fileURLToPath(new URL('./goal-bar.overlay.yml', import.meta.url))
const MODE = webSnapshotMode()
@@ -14,9 +14,9 @@ import {
} from './scaffold.ts'
import { connectFreshWorkspace, newEnglishPage, saveFailureShot } from './support.ts'
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/goal-command-presentation', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('./goldens/goal-command-presentation', import.meta.url))
const UI_EXPECTED = fileURLToPath(new URL(
'./snapshots/goal-command-presentation/ui.expected.md', import.meta.url,
'./goldens/goal-command-presentation/ui.expected.md', import.meta.url,
))
const MODE = webSnapshotMode()
@@ -16,7 +16,7 @@ import {
} from './scaffold.ts'
import { connectFreshWorkspace, newEnglishPage, saveFailureShot } from './support.ts'
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/goal-multi-turn-actions', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('../../../snapshots/web/goal-multi-turn-actions', import.meta.url))
const FIXTURE = join(SNAPSHOT_DIR, 'session.jsonl')
const OVERRIDE = join(SNAPSHOT_DIR, 'replay.override.json')
const UI_EXPECTED = join(SNAPSHOT_DIR, 'ui.expected.md')
+1 -1
View File
@@ -8,7 +8,7 @@ import { act, fireEvent, screen, waitFor, within } from '@testing-library/react'
import { describe, expect, it } from 'vitest'
import { installAssembledBootEnv, mountAssembledApp, REFRESHING_GOLDEN } from './assembled-boot.ts'
const EXPECTED = join(process.cwd(), 'apps/web/tests/snapshots/home-path-tilde/workspace-hover.expected.txt')
const EXPECTED = join(process.cwd(), 'apps/web/tests/goldens/home-path-tilde/workspace-hover.expected.txt')
installAssembledBootEnv()
+1 -1
View File
@@ -23,7 +23,7 @@ import {
} from './scaffold.ts'
import { connectFreshWorkspace, newEnglishPage, saveFailureShot } from './support.ts'
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/lifecycle-chrome', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('../../../snapshots/web/lifecycle-chrome', import.meta.url))
const FIXTURE = join(SNAPSHOT_DIR, 'session.jsonl')
const REPLAY_OVERRIDE = join(SNAPSHOT_DIR, 'replay.override.json')
const HERO_EXPECTED = join(SNAPSHOT_DIR, 'hero.expected.md')
+1 -1
View File
@@ -28,7 +28,7 @@ import {
} from './scaffold.ts'
import { connectFreshWorkspace, newEnglishPage, saveFailureShot } from './support.ts'
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/live-interactions', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('../../../snapshots/web/live-interactions', import.meta.url))
const FIXTURE = join(SNAPSHOT_DIR, 'session.jsonl')
// One golden pins the empty mid-turn loading state, one pins the sendable draft
// state, and the other four capture what remains after cancel, after a
+2 -2
View File
@@ -17,8 +17,8 @@ import {
} from './scaffold.ts'
import { newEnglishPage, saveFailureShot } from './support.ts'
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/markdown-cjk-strong', import.meta.url))
const UI_EXPECTED = fileURLToPath(new URL('./snapshots/markdown-cjk-strong/ui.expected.md', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('./goldens/markdown-cjk-strong', import.meta.url))
const UI_EXPECTED = fileURLToPath(new URL('./goldens/markdown-cjk-strong/ui.expected.md', import.meta.url))
const MODE = webSnapshotMode()
const SEED_ID = 'markdown-cjk-strong-web-e2e'
const DONE = 'CJK_STRONG_DONE'
+2 -2
View File
@@ -26,8 +26,8 @@ import {
} from './scaffold.ts'
import { newEnglishPage, saveFailureShot } from './support.ts'
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/markdown-images', import.meta.url))
const UI_EXPECTED = fileURLToPath(new URL('./snapshots/markdown-images/ui.expected.md', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('./goldens/markdown-images', import.meta.url))
const UI_EXPECTED = fileURLToPath(new URL('./goldens/markdown-images/ui.expected.md', import.meta.url))
const MODE = webSnapshotMode()
const SEED_ID = 'markdown-images-web-e2e'
const REMOTE_ALT = 'Remote test image'
@@ -17,8 +17,8 @@ import {
} from './scaffold.ts'
import { newEnglishPage, saveFailureShot } from './support.ts'
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/markdown-inline-code-links', import.meta.url))
const UI_EXPECTED = fileURLToPath(new URL('./snapshots/markdown-inline-code-links/ui.expected.md', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('./goldens/markdown-inline-code-links', import.meta.url))
const UI_EXPECTED = fileURLToPath(new URL('./goldens/markdown-inline-code-links/ui.expected.md', import.meta.url))
const MODE = webSnapshotMode()
const SEED_ID = 'markdown-inline-code-links-web-e2e'
const DONE = 'INLINE_CODE_LINK_DONE'
+2 -2
View File
@@ -40,9 +40,9 @@ import {
} from './scaffold.ts'
import { newEnglishPage, saveFailureShot } from './support.ts'
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/markdown-wide-table', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('./goldens/markdown-wide-table', import.meta.url))
const GEOMETRY_EXPECTED = fileURLToPath(
new URL('./snapshots/markdown-wide-table/geometry.expected.md', import.meta.url),
new URL('./goldens/markdown-wide-table/geometry.expected.md', import.meta.url),
)
const MODE = webSnapshotMode()
const SEED_ID = 'markdown-wide-table-web-e2e'
+2 -2
View File
@@ -17,8 +17,8 @@ import {
} from './scaffold.ts'
import { newEnglishPage, saveFailureShot } from './support.ts'
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/math-rendering', import.meta.url))
const UI_EXPECTED = fileURLToPath(new URL('./snapshots/math-rendering/ui.expected.md', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('./goldens/math-rendering', import.meta.url))
const UI_EXPECTED = fileURLToPath(new URL('./goldens/math-rendering/ui.expected.md', import.meta.url))
const MODE = webSnapshotMode()
const SEED_ID = 'math-rendering-web-e2e'
const DONE = 'MATH_RENDERING_DONE'
+1 -1
View File
@@ -15,7 +15,7 @@ import { fireEvent, screen, waitFor, within } from '@testing-library/react'
import { describe, expect, it } from 'vitest'
import { hasClass, installAssembledBootEnv, mountAssembledApp, REFRESHING_GOLDEN } from './assembled-boot.ts'
const EXPECTED = join(process.cwd(), 'apps/web/tests/snapshots/max-tokens-notice/history-turn.expected.txt')
const EXPECTED = join(process.cwd(), 'apps/web/tests/goldens/max-tokens-notice/history-turn.expected.txt')
installAssembledBootEnv()
+2 -2
View File
@@ -15,10 +15,10 @@ import {
} from './scaffold.ts'
import { newEnglishPage, saveFailureShot } from './support.ts'
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/message-actions', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('../../../snapshots/web/message-actions', import.meta.url))
// Borrowed read-only: this scenario needs any settled user+assistant pair, not
// a new recording (workspace-management / sidebar-scrollbar pattern).
const SEED = fileURLToPath(new URL('./snapshots/seeded-history/seed.jsonl', import.meta.url))
const SEED = fileURLToPath(new URL('../../../snapshots/web/seeded-history/seed.jsonl', import.meta.url))
const UI_EXPECTED = join(SNAPSHOT_DIR, 'ui.expected.md')
const FORK_EXPECTED = join(SNAPSHOT_DIR, 'fork.expected.md')
const MODE = webSnapshotMode()
@@ -33,7 +33,7 @@ import {
} from './scaffold.ts'
import { newEnglishPage, saveFailureShot } from './support.ts'
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/message-feedback-layout', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('../../../snapshots/web/message-feedback-layout', import.meta.url))
/**
* Committed golden of the popover relations at every stop. Booleans and counts
* only, never absolute coordinates.
@@ -41,7 +41,7 @@ const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/message-feedback-layout'
const GEOMETRY_EXPECTED = join(SNAPSHOT_DIR, 'geometry.expected.md')
const MODE = webSnapshotMode()
/** Borrowed read-only: this scenario needs any settled assistant message to rate. */
const SEED = fileURLToPath(new URL('./snapshots/seeded-history/seed.jsonl', import.meta.url))
const SEED = fileURLToPath(new URL('../../../snapshots/web/seeded-history/seed.jsonl', import.meta.url))
const SEED_ID = 'message-feedback-layout-e2e'
/** Viewport widths from full-screen desktop down to a narrow window. */
const WIDTHS = [1680, 1280, 1024, 900, 700, 600]
@@ -10,7 +10,7 @@ import {
type WebScaffold,
} from './scaffold.ts'
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/message-feedback-protocol', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('../../../snapshots/web/message-feedback-protocol', import.meta.url))
const SESSION_FIXTURE = join(SNAPSHOT_DIR, 'session.jsonl')
const PROTOCOL_EXPECTED = join(SNAPSHOT_DIR, 'protocol.expected.json')
const SESSION_ID = 'message-feedback-protocol'
+1 -1
View File
@@ -15,7 +15,7 @@ import { newEnglishPage, saveFailureShot } from './support.ts'
// Borrowed read-only: this scenario needs any settled assistant message to
// address, not a new recording (message-actions / sidebar-scrollbar pattern).
const SEED = fileURLToPath(new URL('./snapshots/seeded-history/seed.jsonl', import.meta.url))
const SEED = fileURLToPath(new URL('../../../snapshots/web/seeded-history/seed.jsonl', import.meta.url))
const MODE = webSnapshotMode()
const SEED_ID = 'message-feedback-web-e2e'
const NOTE = 'Read both files before answering.'

Some files were not shown because too many files have changed in this diff Show More