test(session): cover the migration read faults and the versioned export name

The JSONL backend rethrows storage errno failures and abort signals from the
source read of a pending migration unwrapped; a test now drives both through
the stat seam so the classification stays covered. The navigation-panes Web
e2e derives the exported archive entry from `SESSION_FORMAT_VERSION`, which
`session-log-export` uses for its `session.v<N>.jsonl` name. The module graph
records the `session-log-export` → `session` peer edge.
This commit is contained in:
Tianyi Cui committed 2026-09-03 19:00:16 +08:00
1 parent 3c3ad02b30
commit 778e0866c3
5 files changed
+19 -5

No files matched your search

+1 -1
View File
@@ -28,7 +28,7 @@ const SEARCH_EXPECTED = join(SNAPSHOT_DIR, 'search-results.expected.md')
const TERMINAL_EXPECTED = join(SNAPSHOT_DIR, 'terminal-card.expected.md')
const MODE = webSnapshotMode()
const SEED_ID = 'navigation-panes-web-e2e'
const EXPORTED_LOG_FILE = 'session.jsonl'
const EXPORTED_LOG_FILE = `session.v${SESSION_FORMAT_VERSION}.jsonl`
// Turn 1 leads with a distinctive word: the session-title fallback takes the
// first words of the first message, so the sidebar-search scenario has a
+2 -2
View File
@@ -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 docs/module-graph.md
module-graph.md: f09a036f508b0c2c5f608a67aee6d8213bda5823
module-graph.zh.md: aba07411c0c2dc0d98d1bfba4f2d3981c50279bc
module-graph.md: 2855f362435b0082ed6e154b139127b7f472b2cb
module-graph.zh.md: f8b2a8c4219e8c95714716b9e4ce914f2d53d01b
+2 -1
View File
@@ -456,6 +456,7 @@ flowchart TD
pkg_fs --> pkg_llm
pkg_fs --> pkg_sandbox
pkg_spill_local --> pkg_spill
pkg_session_log_export --> pkg_session
pkg_session_log_export --> pkg_session_persistence
pkg_message_feedback --> pkg_brand
pkg_message_feedback --> pkg_llm
@@ -1277,7 +1278,7 @@ flowchart TD
| [`agent`](../packages/core/agent) | `core` | [`invariants`](../packages/runtime-diagnostics/invariants), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`system-prompt`](../packages/core/system-prompt), [`typert-protocol`](../packages/typert/protocol) |
| [`fs`](../packages/fs/fs) | `fs` | [`brand`](../packages/util/brand), [`invariants`](../packages/runtime-diagnostics/invariants), [`llm`](../packages/llm/llm), [`sandbox`](../packages/sandbox/sandbox) |
| [`spill-local`](../packages/spill/spill-local) | `spill` | [`spill`](../packages/spill/spill) |
| [`session-log-export`](../packages/session-query/session-log-export) | `session-query` | [`session-persistence`](../packages/session/session-persistence) |
| [`session-log-export`](../packages/session-query/session-log-export) | `session-query` | [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence) |
| [`message-feedback`](../packages/feedback/message-feedback) | `feedback` | [`brand`](../packages/util/brand), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`storage-domain`](../packages/storage/storage-domain), [`typert-protocol`](../packages/typert/protocol) |
| [`sandbox-local`](../packages/sandbox/sandbox-local) | `sandbox` | [`llm`](../packages/llm/llm), [`sandbox`](../packages/sandbox/sandbox), [`session`](../packages/core/session) |
| [`session-persistence-jsonl`](../packages/session/session-persistence-jsonl) | `session` | [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence) |
+2 -1
View File
@@ -458,6 +458,7 @@ flowchart TD
pkg_fs --> pkg_llm
pkg_fs --> pkg_sandbox
pkg_spill_local --> pkg_spill
pkg_session_log_export --> pkg_session
pkg_session_log_export --> pkg_session_persistence
pkg_message_feedback --> pkg_brand
pkg_message_feedback --> pkg_llm
@@ -1279,7 +1280,7 @@ flowchart TD
| [`agent`](../packages/core/agent) | `core` | [`invariants`](../packages/runtime-diagnostics/invariants), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`system-prompt`](../packages/core/system-prompt), [`typert-protocol`](../packages/typert/protocol) |
| [`fs`](../packages/fs/fs) | `fs` | [`brand`](../packages/util/brand), [`invariants`](../packages/runtime-diagnostics/invariants), [`llm`](../packages/llm/llm), [`sandbox`](../packages/sandbox/sandbox) |
| [`spill-local`](../packages/spill/spill-local) | `spill` | [`spill`](../packages/spill/spill) |
| [`session-log-export`](../packages/session-query/session-log-export) | `session-query` | [`session-persistence`](../packages/session/session-persistence) |
| [`session-log-export`](../packages/session-query/session-log-export) | `session-query` | [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence) |
| [`message-feedback`](../packages/feedback/message-feedback) | `feedback` | [`brand`](../packages/util/brand), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`storage-domain`](../packages/storage/storage-domain), [`typert-protocol`](../packages/typert/protocol) |
| [`sandbox-local`](../packages/sandbox/sandbox-local) | `sandbox` | [`llm`](../packages/llm/llm), [`sandbox`](../packages/sandbox/sandbox), [`session`](../packages/core/session) |
| [`session-persistence-jsonl`](../packages/session/session-persistence-jsonl) | `session` | [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence) |
@@ -661,6 +661,18 @@ describe('JsonlSessionPersistence: immutable format generations', () => {
.rejects.toThrow(/released v0 physical header lacks required member "type"/)
})
it('surfaces source-read storage faults and aborts unwrapped during migration', async () => {
const header = meta('source-read-fault', '/work')
const sourcePath = historicalLogPath(root, header.cwd, header.id)
await mkdir(dirname(sourcePath), { recursive: true })
await writeFile(sourcePath, `${JSON.stringify(releasedV0Header(header))}\n`)
statFailure.path = sourcePath
statFailure.error = Object.assign(new Error('EACCES: denied'), { code: 'EACCES' })
await expect(ctx.sessionPersistence.open(header.id, 'read')).rejects.toMatchObject({ code: 'EACCES' })
statFailure.error = new DOMException('source read aborted', 'AbortError')
await expect(ctx.sessionPersistence.open(header.id, 'read')).rejects.toMatchObject({ name: 'AbortError' })
})
it('selects the highest opposite-encoding generation for its refusal', async () => {
const header = meta('opposite-generations', '/work')
const dir = sessionDir(root, header.cwd, header.id)