Files
deepseek-harness/apps/web/tests
_Kerman cdb4cc3c68 feat(session-projection-cache): store one projection_cache.json per session
Replace the single global session_projcache domain with a per-session
cache file inside the session's own persistence directory, resolved
through sessionPersistence.locate(meta) — the persistence backend owns
the session-directory layout, the cache service keeps every checkpoint
and cold-read responsibility.

- cachedSnapshot(meta) becomes async (one file read per session);
  coldSnapshot takes the session header so it can locate the file, with
  the stored log header remaining the identity witness.
- Backends without a per-session directory (sqlite) disable the durable
  cache: writes no-op and cold reads fall to the full-log rung. An
  obsolete global cache is never read — derived data refolds on first
  cold read (no migration).
- writeAtomic is exported from dsh-storage-json as the shared atomic
  whole-file replace primitive; api-proxy listing and subagent cold
  reads await the now-async cachedSnapshot.
- READMEs and a new Agent Note document the per-session medium.
2026-08-19 21:03:20 +08:00
..
2026-08-12 20:26:47 +08:00
2026-08-13 01:19:52 -07:00
2026-08-18 19:31:12 +08:00
2026-08-12 20:26:47 +08:00

apps/web browser e2e

English | 中文

These tests boot the real web composition in-process and drive it with a real Chromium over real HTTP. The lane's mechanics — modes, fixtures, goldens, and the deliberate composition divergences from dsh web — are documented in scaffold.ts and the browser e2e Agent Note.

These are Host-face tests

They type-check in the root tsconfig.host.json, not in the Client aggregate, because they read Host services directly: ctx.apiProxy, the Host SessionStore, ctx.sessionProjectionCache. Driving a browser at runtime does not make a file part of the Client program — the two faces merge cordis Context under the same keys with different services, so one program cannot see both. Moving these files into the Client aggregate makes every Host-service access fail to compile.

Do not import @deepseek-ai/dsh-client-* here

Importing a Client package — a value or a type — pulls its whole TypeScript project, and every project it references, into the Host build graph. That has bitten this lane once already: four Client consumer packages reference api/remotes' Client face, which cannot compile until Host tsdown has generated @deepseek-ai/dsh-goal/remote, so the Host build phase ended up waiting on an artifact it produces itself.

When a scenario needs a Client-owned constant or pure function, mirror it here instead, next to the commented-out import that names the source module. A drift then surfaces as a missed selector or a stale mirrored value — a loud failure, never a silent pass. scaffold.ts follows this rule for the welcome-notice namespace, acknowledgement field, version, and asserted Chinese copy.

Two kinds of Client import stand. assembled-boot.ts drives the shell itself, so it imports AppWebEntry from @deepseek-ai/dsh-client-web and the boot-manifest type from @deepseek-ai/dsh-client-modules/client: booting the real shell is what that harness is for, and both packages are already in the Host graph. Separately, the chat scenarios import conversationContextKey from @deepseek-ai/dsh-client-runtime/client because client/runtime is reachable through the unsplit directory-picker packages and pulls nothing further in. That reachability is incidental, not a guarantee — if it ever leaves the graph, mirror the helper like the rest.

Nothing mechanically enforces this rule; keep it in review.