From 38bbb656da2659088e30a1ca3e4434b2f65bab32 Mon Sep 17 00:00:00 2001 From: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com> Date: Thu, 8 Oct 2026 14:09:28 +0000 Subject: [PATCH] fix(evidence): require a complete record before the single-record hint A malformed bundle that merely has an evidence_id field was described as one Evidence record. Use the single-record message only when the input matches the Evidence record schema; otherwise report the bundle schema failure. Co-Authored-By: Claude Opus 5.5 --- src/domain/evidenceBundle.ts | 12 +++--------- .../filesystem/evidenceBundleFiles.test.ts | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/domain/evidenceBundle.ts b/src/domain/evidenceBundle.ts index 1184ed86f..807781b66 100644 --- a/src/domain/evidenceBundle.ts +++ b/src/domain/evidenceBundle.ts @@ -190,15 +190,9 @@ export const describeEvidenceBundleFailure = ( input: unknown, cause: unknown, ): string => { - if ( - typeof input === "object" && - input !== null && - !Array.isArray(input) && - "evidence_id" in input && - typeof input.evidence_id === "string" && - !("records" in input) - ) - return `Expected an Evidence bundle with records and manifest arrays, but this JSON is one Evidence record (${input.evidence_id}). Export a session bundle with the MCP export_evidence_bundle tool and supply that file.`; + const record = evidenceRecordSchema.safeParse(input); + if (record.success) + return `Expected an Evidence bundle with records and manifest arrays, but this JSON is one Evidence record (${record.data.evidence_id}). Export a session bundle with the MCP export_evidence_bundle tool and supply that file.`; return cause instanceof z.ZodError ? `Evidence bundle does not match the bundle schema ${describeValidationFailure(cause)}. Supply an unmodified bundle written by export_evidence_bundle or rea evidence-export.` : `Evidence bundle validation failed: ${describeValidationFailure(cause)}. Recreate or re-export the bundle, then try again.`; diff --git a/tests/boundary/filesystem/evidenceBundleFiles.test.ts b/tests/boundary/filesystem/evidenceBundleFiles.test.ts index ce61a550d..1a048449a 100644 --- a/tests/boundary/filesystem/evidenceBundleFiles.test.ts +++ b/tests/boundary/filesystem/evidenceBundleFiles.test.ts @@ -160,6 +160,21 @@ describe("evidence bundle filesystem adapter", () => { }, }); + const partial = join(directory, "partial.json"); + await writeFile(partial, JSON.stringify({ evidence_id: "typo" })); + const rejected = await readEvidenceBundle(partial); + expect(rejected).toMatchObject({ + ok: false, + error: { + userMessage: expect.stringContaining( + "does not match the bundle schema", + ), + }, + }); + expect(rejected).not.toMatchObject({ + error: { userMessage: expect.stringContaining("one Evidence record") }, + }); + const mismatched = join(directory, "mismatched.json"); await writeFile(mismatched, JSON.stringify({ ...bundle(), records: {} })); expect(await readEvidenceBundle(mismatched)).toMatchObject({