From 778e0866c36f036b66ee0ccb63a741fa4c6ddc13 Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Thu, 3 Sep 2026 19:00:16 +0800 Subject: [PATCH] test(session): cover the migration read faults and the versioned export name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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.jsonl` name. The module graph records the `session-log-export` → `session` peer edge. --- apps/web/tests/navigation-panes.e2e.ts | 2 +- docs/module-graph.i18n.yaml | 4 ++-- docs/module-graph.md | 3 ++- docs/module-graph.zh.md | 3 ++- .../session-persistence-jsonl/tests/jsonl.spec.ts | 12 ++++++++++++ 5 files changed, 19 insertions(+), 5 deletions(-) diff --git a/apps/web/tests/navigation-panes.e2e.ts b/apps/web/tests/navigation-panes.e2e.ts index 5e00ec337c..504b7df9c5 100644 --- a/apps/web/tests/navigation-panes.e2e.ts +++ b/apps/web/tests/navigation-panes.e2e.ts @@ -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 diff --git a/docs/module-graph.i18n.yaml b/docs/module-graph.i18n.yaml index 6541140b9e..ab00bfde96 100644 --- a/docs/module-graph.i18n.yaml +++ b/docs/module-graph.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 docs/module-graph.md -module-graph.md: f09a036f508b0c2c5f608a67aee6d8213bda5823 -module-graph.zh.md: aba07411c0c2dc0d98d1bfba4f2d3981c50279bc +module-graph.md: 2855f362435b0082ed6e154b139127b7f472b2cb +module-graph.zh.md: f8b2a8c4219e8c95714716b9e4ce914f2d53d01b diff --git a/docs/module-graph.md b/docs/module-graph.md index f09a036f50..2855f36243 100644 --- a/docs/module-graph.md +++ b/docs/module-graph.md @@ -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) | diff --git a/docs/module-graph.zh.md b/docs/module-graph.zh.md index aba07411c0..f8b2a8c421 100644 --- a/docs/module-graph.zh.md +++ b/docs/module-graph.zh.md @@ -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) | diff --git a/packages/session/session-persistence-jsonl/tests/jsonl.spec.ts b/packages/session/session-persistence-jsonl/tests/jsonl.spec.ts index 72f08589e6..cde11955c5 100644 --- a/packages/session/session-persistence-jsonl/tests/jsonl.spec.ts +++ b/packages/session/session-persistence-jsonl/tests/jsonl.spec.ts @@ -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)