[GH-ISSUE #7290] [Bug] DOL Evidence cannot be bundled or saved in an analysis snapshot #4329

Closed
opened 2026-10-31 00:48:57 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @coygeek on GitHub (Oct 26, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/7290

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Evidence, artifacts, or reconstruction

Observed behavior

After a supported GameCube DOL target produces one authenticated Evidence record, the production MCP handlers for get_evidence_bundle in summary and complete modes, export_evidence_bundle, and close_binary with snapshot_path fail with a Zod format-discriminator error. The accepted manifest formats exclude gamecube-dol, although the Evidence subject schema accepts it with architecture powerpc. The empty session bundle succeeds before the observation. These runtime observations use a selected fixture provider with a concrete analysis profile, not a real Ghidra engine.

Reproduction

Use Node.js 24.22.1 and the checkout's locked dependencies. Run the following block from the repository root. It generates a 288-byte DOL containing a 256-byte header and eight ordinary PowerPC blr instructions: one aligned 32-byte text section at file offset 256 and load address 0x80003100, with its entry at that address and no data or BSS. The script uses the source loader, production target admission, provider registry, binary session, MCP server, and MCP client; only provider readiness and observation results are fixtures. All generated files and server configuration belong to a disposable directory. This exact block's JavaScript was executed successfully once; a separate longer probe also reproduced the failure and passed raw-binary export/snapshot controls.

node --input-type=module <<'JS'
import assert from 'node:assert/strict';
import { mkdtemp, mkdir, writeFile, stat } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { pathToFileURL } from 'node:url';
const root = process.cwd();
const work = process.env.PROBE_OUTPUT ?? await mkdtemp(join(tmpdir(), 'dol-bundle-'));
await mkdir(join(work, 'home'), { recursive: true });
const env = { HOME: join(work, 'home'), XDG_CONFIG_HOME: join(work, 'home', 'config'), PATH: process.env.PATH };
const { importVerifierSource } = await import(pathToFileURL(join(root, 'scripts/lib/verifier-source-loader.mjs')));
const source = (path) => importVerifierSource(pathToFileURL(join(root, 'src', path)));
const { BinarySession } = await source('application/binary/BinarySession.ts');
const { SessionProviderRouter } = await source('application/binary/SessionProviderRouter.ts');
const { AnalysisProviderRegistry } = await source('application/binary/AnalysisProviderRegistry.ts');
const { createAnalysisExecution } = await source('application/AnalysisProvider.ts');
const { createAnalysisProfile } = await source('domain/analysisProfile.ts');
const { parseEvidence } = await source('domain/evidence.ts');
const { createServer } = await source('server/createServer.ts');
const { silentLogger } = await source('logger.ts');
const { ok } = await source('domain/result.ts');
const { Client, InMemoryTransport } = await import(pathToFileURL(join(root, 'node_modules/@modelcontextprotocol/client/dist/index.mjs')));
const bytes = Buffer.alloc(288);
for (const [offset, value] of [[0, 256], [0x48, 0x80003100], [0x90, 32], [0xe0, 0x80003100]]) bytes.writeUInt32BE(value, offset);
for (let offset = 256; offset < 288; offset += 4) bytes.writeUInt32BE(0x4e800020, offset);
const path = join(work, 'game.dol');
await writeFile(path, bytes);
const identity = { id: 'fixture', name: 'Fixture provider', version: '1' };
const provider = {
  identity: () => identity,
  capabilities: () => [{ provider: identity, operation: 'address_name', available: true, reason: null, cachePolicy: 'snapshot', limitations: [], effects: { mutatesArtifact: false, launchesProcess: false, mayShowUi: false, mayAccessNetwork: false, mayWriteFilesystem: false, changesPermissions: false, requiresRoot: false } }],
  inspectAvailability: () => ({ status: 'available', code: null, reason: null, diagnostics: {} }),
  inspectTargetSupport: () => ({ status: 'supported', code: null, reason: null, diagnostics: {} }),
  resolveAnalysisProfile: async () => ok({ profile: createAnalysisProfile(identity, { fixture: true }) }),
  createClient: () => ({ execute: async (operation) => ok(createAnalysisExecution(operation === 'health' ? null : 'entry', identity)), close: async () => ok(null) }),
};
const session = new BinarySession(SessionProviderRouter.selectable(new AnalysisProviderRegistry([provider]), []));
const server = createServer({ kind: 'session', session }, { logger: silentLogger, environment: env });
const client = new Client({ name: 'dol-bundle-review', version: '1' });
const [left, right] = InMemoryTransport.createLinkedPair();
await server.connect(right);
await client.connect(left);
const call = async (name, args = {}) => {
  const result = await client.callTool({ name, arguments: args });
  console.log(name, result.isError ? 'ERROR' : 'OK');
  if (result.isError) {
    const text = result.content.find((part) => part.type === 'text').text;
    const first = JSON.parse(text)[0];
    console.log(JSON.stringify({ code: first.code, discriminator: first.discriminator, note: first.note, acceptsDol: first.options.includes('gamecube-dol') }));
  }
  return result;
};
try {
  assert(!(await call('open_binary', { path, format: 'gamecube-dol' })).isError);
  assert(!(await call('get_evidence_bundle', { detail: 'complete' })).isError);
  const result = await call('address_name', { address: '0x80003100' });
  assert(!result.isError);
  const evidence = parseEvidence(result.structuredContent);
  assert.equal(evidence.subject.format, 'gamecube-dol');
  assert.equal(evidence.analysis_profile.provider.id, 'fixture');
  console.log('Authenticated DOL Evidence with concrete provider profile');
  for (const detail of ['summary', 'complete']) assert((await call('get_evidence_bundle', { detail })).isError);
  const bundle = join(work, 'bundle.json'), snapshot = join(work, 'snapshot.json');
  assert((await call('export_evidence_bundle', { path: bundle })).isError);
  assert((await call('close_binary', { snapshot_path: snapshot })).isError);
  for (const output of [bundle, snapshot]) assert(!(await stat(output).then(() => true, () => false)));
  assert.equal((await call('binary_session')).structuredContent.result.open, true);
  assert(!(await call('close_binary')).isError);
} finally {
  await client.close();
  await server.close();
}
JS

Expected behavior

DOL observations that authenticate under the Evidence schema should be representable in the canonical bundle, discoverable through summary mode, and exportable to disk. A DOL session with a concrete provider profile should support the advertised snapshot-save path. docs/ghidra-dol.md documents explicit DOL admission through open_binary and the stock POSIX Ghidra lane; docs/mcp-contracts.md documents canonical bundle delivery, retained-record summary discovery, and export for complete Evidence.

Impact and scope

The reproduced failure starts after the first DOL-subject record is retained. Both bundle detail modes, export, and snapshot save fail in the tested selected-provider session. The save failure creates no output and leaves binary_session.result.open true; closing without a snapshot succeeds. A raw-binary/6502 session with the same fixture provider exports and saves a snapshot successfully. This is a bounded failure of DOL Evidence persistence, with no observed corruption, silent record loss, or failure of the analysis operation itself. Individual successful MCP replies can still be retained separately; that does not provide the bundle round-trip or cached-session replay. No equivalent workaround for those two operations was established. Real Ghidra execution and other CLI analysis variants were not run in this reproduction; their shared bundle-construction path is source-derived scope.

REA version

6.8.0, source revision 0d1a454e25db825567782e461da21530bad4b158.

Runtime and platform

Node.js 24.22.1; macOS 27.0.1 arm64; linked in-memory MCP transports. No Ghidra process starts in the executed reproduction.

Target and artifact context

Synthetic MEM1 GameCube/Wii DOL; format gamecube-dol, architecture powerpc; authenticated Evidence record and canonical Evidence bundle; provider-profile-bound analysis snapshot.

Interface

MCP

Earliest failure stage

Artifact or evidence registration

Relevant output or evidence

open_binary OK
get_evidence_bundle OK
address_name OK
Authenticated DOL Evidence with concrete provider profile
get_evidence_bundle ERROR
{"code":"invalid_union","discriminator":"format","note":"No matching discriminator","acceptsDol":false}
get_evidence_bundle ERROR
{"code":"invalid_union","discriminator":"format","note":"No matching discriminator","acceptsDol":false}
export_evidence_bundle ERROR
{"code":"invalid_union","discriminator":"format","note":"No matching discriminator","acceptsDol":false}
close_binary ERROR
{"code":"invalid_union","discriminator":"format","note":"No matching discriminator","acceptsDol":false}
binary_session OK
close_binary OK
  • Expected source: src/domain/evidence.ts:84 admits the DOL subject branch; src/domain/analysisSnapshot.ts:97 admits DOL execution subjects and targets; the DOL and MCP guides cited above establish supported admission and persistence behavior.
  • Failure source: src/domain/evidenceBundle.ts:23 selects only the first two Evidence subject branches for the manifest union, and createEvidenceBundle at line 106 parses each non-null subject through that union; the executed public MCP handlers in src/server/registerSessionRecordTools.ts:54 and :87 request the bundle before exporting or summarizing it.
  • Evidence provenance: observed MCP integration failures and positive controls using an explicitly selected fixture provider; real-provider reachability and additional consumers are static source reasoning, not engine execution evidence.
  • Local verification: reproduced.
  • Reproduction completeness: complete.

The complete executed reproduction is the fixture-provider MCP case above; it does not establish real-engine execution. The supported real-provider path is explicit open_binary with format: "gamecube-dol" and provider_id: "ghidra" on POSIX, with a ready official installation, no existing-project mode, and no conflicting language override. BinaryTargetResolver validates the header and derives powerpc; GhidraProvider.inspectTargetSupport admits that executable architecture on POSIX, while ghidraProcessorUnsupportedReason explicitly exempts DOL from ELF-only PowerPC checks. resolveGhidraAnalysisProfile selects stock PowerPC:BE:32:default and commits the DOL section facts. GhidraProviderClient prepares the DOL import and returns a successful address_name execution without replacing its subject; BinarySessionExecution.bindExecutionTarget supplies the selected DOL subject, and the session/server records it. No subsequent bundle guard exempts that admitted format. Windows Ghidra, Hopper, IDA, conflicting language settings, and existing-project imports are outside this path.

Snapshot export has additional guards: an active concrete provider profile, no invalidated analysis state, and an executable session. The executed fixture is a selected registry candidate with a matching profile, rather than an auxiliary-only provider, and passes those guards. BinarySessionRecords.exportAnalysisSnapshot then calls the ledger's bundle exporter before writing the file. The independently executed direct snapshot call throws at createEvidenceBundle, matching the MCP snapshot failure. Snapshot import also uses the same bundle schema; importing a DOL-containing snapshot successfully was not executed.

Typed outcome or recovery expected

Return the normal canonical bundle or summary, export receipt, and snapshot-save receipt for the admitted DOL record. Preserve the current safe behavior that a failed save does not close the live session. A raw schema exception does not identify a usable recovery path for an intact supported observation.

Analysis or suspected cause

The source subject union contains detected-format, raw-binary, and DOL branches, but the artifact-manifest union is constructed from only the detected-format and raw-binary branches. That discrepancy is sufficient to explain the format-discriminator failure for each non-null DOL subject, independent of the producing engine. Summary filters cannot bypass it because the handler constructs the full immutable bundle before applying the summary selection. CLI delivery with --evidence_output also calls the same constructor; no one-shot DOL CLI export was executed, so this report does not claim a measured failure for every CLI command or delivery variant.

Additional context

An auxiliary-only fixture with no active deep-provider profile can fail snapshot export earlier with a profile-related integrity error; that signal alone does not establish this snapshot-schema failure. The supplied reproduction selects a profile-bearing candidate to reach the failing bundle projection. Related but different reports are #7082/#7081, which concern a conflicting DOL language override, and #6240, which introduced DOL analysis. The known-good raw-binary control establishes that the fixture profile and snapshot mechanism work for an admitted manifest format. NOT_ENOUGH_INFO: the first affected release and last known-good DOL persistence revision have not been established.

Restoration check

With the same generated DOL and profile-bound MCP sequence, the first retained observation must remain authenticated and retain its original subject identity; summary and complete bundle reads must succeed, export must write a canonical bundle with that DOL artifact and record, and snapshot save must write the snapshot and close the session. Re-import that bundle in a fresh session and reopen the same DOL with the saved snapshot to verify record preservation and replay binding. Keep the empty-session and raw-binary export/snapshot controls passing. Preserve rejection of unsupported DOL architectures and malformed headers; success must not be obtained by removing the subject, discarding records, or bypassing authentication.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: A valid supported target's recorded Evidence cannot pass the shared bundle projection, blocking the reproduced discovery, export, and snapshot-save operations; the bounded DOL scope, successful analysis replies, surviving live session, and passing raw-binary control do not establish severe harm or a product-wide core analysis failure.
  • Workaround status: none
  • Workaround basis: Keeping individual successful replies preserves those observations, but no supported setting or alternate persistence path was established that produces the canonical DOL bundle and equivalent saved-session replay; closing without a snapshot does not preserve that result.

References

Originally created by @coygeek on GitHub (Oct 26, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/7290 ## Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ## Area Evidence, artifacts, or reconstruction ## Observed behavior After a supported GameCube DOL target produces one authenticated Evidence record, the production MCP handlers for `get_evidence_bundle` in summary and complete modes, `export_evidence_bundle`, and `close_binary` with `snapshot_path` fail with a Zod format-discriminator error. The accepted manifest formats exclude `gamecube-dol`, although the Evidence subject schema accepts it with architecture `powerpc`. The empty session bundle succeeds before the observation. These runtime observations use a selected fixture provider with a concrete analysis profile, not a real Ghidra engine. ## Reproduction Use Node.js 24.22.1 and the checkout's locked dependencies. Run the following block from the repository root. It generates a 288-byte DOL containing a 256-byte header and eight ordinary PowerPC `blr` instructions: one aligned 32-byte text section at file offset 256 and load address `0x80003100`, with its entry at that address and no data or BSS. The script uses the source loader, production target admission, provider registry, binary session, MCP server, and MCP client; only provider readiness and observation results are fixtures. All generated files and server configuration belong to a disposable directory. This exact block's JavaScript was executed successfully once; a separate longer probe also reproduced the failure and passed raw-binary export/snapshot controls. ```sh node --input-type=module <<'JS' import assert from 'node:assert/strict'; import { mkdtemp, mkdir, writeFile, stat } from 'node:fs/promises'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { pathToFileURL } from 'node:url'; const root = process.cwd(); const work = process.env.PROBE_OUTPUT ?? await mkdtemp(join(tmpdir(), 'dol-bundle-')); await mkdir(join(work, 'home'), { recursive: true }); const env = { HOME: join(work, 'home'), XDG_CONFIG_HOME: join(work, 'home', 'config'), PATH: process.env.PATH }; const { importVerifierSource } = await import(pathToFileURL(join(root, 'scripts/lib/verifier-source-loader.mjs'))); const source = (path) => importVerifierSource(pathToFileURL(join(root, 'src', path))); const { BinarySession } = await source('application/binary/BinarySession.ts'); const { SessionProviderRouter } = await source('application/binary/SessionProviderRouter.ts'); const { AnalysisProviderRegistry } = await source('application/binary/AnalysisProviderRegistry.ts'); const { createAnalysisExecution } = await source('application/AnalysisProvider.ts'); const { createAnalysisProfile } = await source('domain/analysisProfile.ts'); const { parseEvidence } = await source('domain/evidence.ts'); const { createServer } = await source('server/createServer.ts'); const { silentLogger } = await source('logger.ts'); const { ok } = await source('domain/result.ts'); const { Client, InMemoryTransport } = await import(pathToFileURL(join(root, 'node_modules/@modelcontextprotocol/client/dist/index.mjs'))); const bytes = Buffer.alloc(288); for (const [offset, value] of [[0, 256], [0x48, 0x80003100], [0x90, 32], [0xe0, 0x80003100]]) bytes.writeUInt32BE(value, offset); for (let offset = 256; offset < 288; offset += 4) bytes.writeUInt32BE(0x4e800020, offset); const path = join(work, 'game.dol'); await writeFile(path, bytes); const identity = { id: 'fixture', name: 'Fixture provider', version: '1' }; const provider = { identity: () => identity, capabilities: () => [{ provider: identity, operation: 'address_name', available: true, reason: null, cachePolicy: 'snapshot', limitations: [], effects: { mutatesArtifact: false, launchesProcess: false, mayShowUi: false, mayAccessNetwork: false, mayWriteFilesystem: false, changesPermissions: false, requiresRoot: false } }], inspectAvailability: () => ({ status: 'available', code: null, reason: null, diagnostics: {} }), inspectTargetSupport: () => ({ status: 'supported', code: null, reason: null, diagnostics: {} }), resolveAnalysisProfile: async () => ok({ profile: createAnalysisProfile(identity, { fixture: true }) }), createClient: () => ({ execute: async (operation) => ok(createAnalysisExecution(operation === 'health' ? null : 'entry', identity)), close: async () => ok(null) }), }; const session = new BinarySession(SessionProviderRouter.selectable(new AnalysisProviderRegistry([provider]), [])); const server = createServer({ kind: 'session', session }, { logger: silentLogger, environment: env }); const client = new Client({ name: 'dol-bundle-review', version: '1' }); const [left, right] = InMemoryTransport.createLinkedPair(); await server.connect(right); await client.connect(left); const call = async (name, args = {}) => { const result = await client.callTool({ name, arguments: args }); console.log(name, result.isError ? 'ERROR' : 'OK'); if (result.isError) { const text = result.content.find((part) => part.type === 'text').text; const first = JSON.parse(text)[0]; console.log(JSON.stringify({ code: first.code, discriminator: first.discriminator, note: first.note, acceptsDol: first.options.includes('gamecube-dol') })); } return result; }; try { assert(!(await call('open_binary', { path, format: 'gamecube-dol' })).isError); assert(!(await call('get_evidence_bundle', { detail: 'complete' })).isError); const result = await call('address_name', { address: '0x80003100' }); assert(!result.isError); const evidence = parseEvidence(result.structuredContent); assert.equal(evidence.subject.format, 'gamecube-dol'); assert.equal(evidence.analysis_profile.provider.id, 'fixture'); console.log('Authenticated DOL Evidence with concrete provider profile'); for (const detail of ['summary', 'complete']) assert((await call('get_evidence_bundle', { detail })).isError); const bundle = join(work, 'bundle.json'), snapshot = join(work, 'snapshot.json'); assert((await call('export_evidence_bundle', { path: bundle })).isError); assert((await call('close_binary', { snapshot_path: snapshot })).isError); for (const output of [bundle, snapshot]) assert(!(await stat(output).then(() => true, () => false))); assert.equal((await call('binary_session')).structuredContent.result.open, true); assert(!(await call('close_binary')).isError); } finally { await client.close(); await server.close(); } JS ``` ## Expected behavior DOL observations that authenticate under the Evidence schema should be representable in the canonical bundle, discoverable through summary mode, and exportable to disk. A DOL session with a concrete provider profile should support the advertised snapshot-save path. `docs/ghidra-dol.md` documents explicit DOL admission through `open_binary` and the stock POSIX Ghidra lane; `docs/mcp-contracts.md` documents canonical bundle delivery, retained-record summary discovery, and export for complete Evidence. ## Impact and scope The reproduced failure starts after the first DOL-subject record is retained. Both bundle detail modes, export, and snapshot save fail in the tested selected-provider session. The save failure creates no output and leaves `binary_session.result.open` true; closing without a snapshot succeeds. A raw-binary/6502 session with the same fixture provider exports and saves a snapshot successfully. This is a bounded failure of DOL Evidence persistence, with no observed corruption, silent record loss, or failure of the analysis operation itself. Individual successful MCP replies can still be retained separately; that does not provide the bundle round-trip or cached-session replay. No equivalent workaround for those two operations was established. Real Ghidra execution and other CLI analysis variants were not run in this reproduction; their shared bundle-construction path is source-derived scope. ## REA version 6.8.0, source revision `0d1a454e25db825567782e461da21530bad4b158`. ## Runtime and platform Node.js 24.22.1; macOS 27.0.1 arm64; linked in-memory MCP transports. No Ghidra process starts in the executed reproduction. ## Target and artifact context Synthetic MEM1 GameCube/Wii DOL; format `gamecube-dol`, architecture `powerpc`; authenticated Evidence record and canonical Evidence bundle; provider-profile-bound analysis snapshot. ## Interface MCP ## Earliest failure stage Artifact or evidence registration ## Relevant output or evidence ```text open_binary OK get_evidence_bundle OK address_name OK Authenticated DOL Evidence with concrete provider profile get_evidence_bundle ERROR {"code":"invalid_union","discriminator":"format","note":"No matching discriminator","acceptsDol":false} get_evidence_bundle ERROR {"code":"invalid_union","discriminator":"format","note":"No matching discriminator","acceptsDol":false} export_evidence_bundle ERROR {"code":"invalid_union","discriminator":"format","note":"No matching discriminator","acceptsDol":false} close_binary ERROR {"code":"invalid_union","discriminator":"format","note":"No matching discriminator","acceptsDol":false} binary_session OK close_binary OK ``` - Expected source: `src/domain/evidence.ts:84` admits the DOL subject branch; `src/domain/analysisSnapshot.ts:97` admits DOL execution subjects and targets; the DOL and MCP guides cited above establish supported admission and persistence behavior. - Failure source: `src/domain/evidenceBundle.ts:23` selects only the first two Evidence subject branches for the manifest union, and `createEvidenceBundle` at line 106 parses each non-null subject through that union; the executed public MCP handlers in `src/server/registerSessionRecordTools.ts:54` and `:87` request the bundle before exporting or summarizing it. - Evidence provenance: observed MCP integration failures and positive controls using an explicitly selected fixture provider; real-provider reachability and additional consumers are static source reasoning, not engine execution evidence. - Local verification: reproduced. - Reproduction completeness: complete. The complete executed reproduction is the fixture-provider MCP case above; it does not establish real-engine execution. The supported real-provider path is explicit `open_binary` with `format: "gamecube-dol"` and `provider_id: "ghidra"` on POSIX, with a ready official installation, no existing-project mode, and no conflicting language override. `BinaryTargetResolver` validates the header and derives `powerpc`; `GhidraProvider.inspectTargetSupport` admits that executable architecture on POSIX, while `ghidraProcessorUnsupportedReason` explicitly exempts DOL from ELF-only PowerPC checks. `resolveGhidraAnalysisProfile` selects stock `PowerPC:BE:32:default` and commits the DOL section facts. `GhidraProviderClient` prepares the DOL import and returns a successful `address_name` execution without replacing its subject; `BinarySessionExecution.bindExecutionTarget` supplies the selected DOL subject, and the session/server records it. No subsequent bundle guard exempts that admitted format. Windows Ghidra, Hopper, IDA, conflicting language settings, and existing-project imports are outside this path. Snapshot export has additional guards: an active concrete provider profile, no invalidated analysis state, and an executable session. The executed fixture is a selected registry candidate with a matching profile, rather than an auxiliary-only provider, and passes those guards. `BinarySessionRecords.exportAnalysisSnapshot` then calls the ledger's bundle exporter before writing the file. The independently executed direct snapshot call throws at `createEvidenceBundle`, matching the MCP snapshot failure. Snapshot import also uses the same bundle schema; importing a DOL-containing snapshot successfully was not executed. ## Typed outcome or recovery expected Return the normal canonical bundle or summary, export receipt, and snapshot-save receipt for the admitted DOL record. Preserve the current safe behavior that a failed save does not close the live session. A raw schema exception does not identify a usable recovery path for an intact supported observation. ## Analysis or suspected cause The source subject union contains detected-format, raw-binary, and DOL branches, but the artifact-manifest union is constructed from only the detected-format and raw-binary branches. That discrepancy is sufficient to explain the format-discriminator failure for each non-null DOL subject, independent of the producing engine. Summary filters cannot bypass it because the handler constructs the full immutable bundle before applying the summary selection. CLI delivery with `--evidence_output` also calls the same constructor; no one-shot DOL CLI export was executed, so this report does not claim a measured failure for every CLI command or delivery variant. ## Additional context An auxiliary-only fixture with no active deep-provider profile can fail snapshot export earlier with a profile-related integrity error; that signal alone does not establish this snapshot-schema failure. The supplied reproduction selects a profile-bearing candidate to reach the failing bundle projection. Related but different reports are #7082/#7081, which concern a conflicting DOL language override, and #6240, which introduced DOL analysis. The known-good raw-binary control establishes that the fixture profile and snapshot mechanism work for an admitted manifest format. NOT_ENOUGH_INFO: the first affected release and last known-good DOL persistence revision have not been established. ## Restoration check With the same generated DOL and profile-bound MCP sequence, the first retained observation must remain authenticated and retain its original subject identity; summary and complete bundle reads must succeed, export must write a canonical bundle with that DOL artifact and record, and snapshot save must write the snapshot and close the session. Re-import that bundle in a fresh session and reopen the same DOL with the saved snapshot to verify record preservation and replay binding. Keep the empty-session and raw-binary export/snapshot controls passing. Preserve rejection of unsupported DOL architectures and malformed headers; success must not be obtained by removing the subject, discarding records, or bypassing authentication. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: A valid supported target's recorded Evidence cannot pass the shared bundle projection, blocking the reproduced discovery, export, and snapshot-save operations; the bounded DOL scope, successful analysis replies, surviving live session, and passing raw-binary control do not establish severe harm or a product-wide core analysis failure. - Workaround status: none - Workaround basis: Keeping individual successful replies preserves those observations, but no supported setting or alternate persistence path was established that produces the canonical DOL bundle and equivalent saved-session replay; closing without a snapshot does not preserve that result. ## References - [DOL support PR #6240](https://github.com/morluto/rea/pull/6240) introduced the supported analysis path; this report concerns persistence after an authenticated DOL observation. - [Closed DOL override issue #7082](https://github.com/morluto/rea/issues/7082) and [fix PR #7081](https://github.com/morluto/rea/pull/7081) concern admission with a conflicting language override. This reproduction supplies no override and reaches successful observation before failing. - [Open export-manifest feature #6337](https://github.com/morluto/rea/issues/6337) requests an optional file inventory and verification format; this report concerns the existing canonical Evidence artifact manifest rejecting an admitted subject format. - [Closed historical-bundle issue #4436](https://github.com/morluto/rea/issues/4436) concerns earlier-version Evidence identities. This reproduction uses freshly authenticated current-version Evidence and fails during bundle construction. - [Closed native-dispatch snapshot issue #5529](https://github.com/morluto/rea/issues/5529) concerns a missing concrete provider profile. This reproduction selects a matching concrete profile and reaches the different bundle-schema failure. - Source at the tested revision: [artifact manifest projection](https://github.com/morluto/rea/blob/0d1a454e25db825567782e461da21530bad4b158/src/domain/evidenceBundle.ts#L23-L33), [DOL Evidence subject](https://github.com/morluto/rea/blob/0d1a454e25db825567782e461da21530bad4b158/src/domain/evidence.ts#L84-L100).
Author
Owner

@coygeek commented on GitHub (Oct 31, 2026):

I checked this against latest main, and the issue appears resolved. The original problem was that after I recorded an authenticated GameCube DOL observation, get_evidence_bundle in both summary and complete modes, export_evidence_bundle, and close_binary with snapshot_path all failed with a Zod invalid_union error on the format discriminator, because the bundle artifact manifest only accepted the detected-format and raw-binary subject branches and rejected gamecube-dol, even though the Evidence subject schema itself accepted a DOL subject with architecture powerpc. The fix in commit 50822e1ef, merged via PR #7481 (merge commit 54756ff24) into main, changes src/domain/evidenceBundle.ts so the artifact manifest is built with withEvidenceSubjectDeclaration from src/domain/evidenceSubject.ts, which includes all three subject branches, including gamecube-dol with architecture powerpc. The same shared helper is now used by src/domain/evidence.ts and src/domain/analysisSnapshot.ts, so Evidence, bundles, and snapshots no longer disagree about this admitted format. PR #7481 also adds regression coverage for exactly the reported flow: a DOL session test that saves with close_binary and snapshot_path, verifies the saved gamecube-dol/powerpc target and artifact manifest, reopens from the snapshot, and replays the read without re-running the provider, plus vocabulary tests that require the DOL format to pass through Evidence creation, immutable bundle creation, snapshot target parsing, and target summary. That covers the bundle reads, export, and snapshot-save path that were failing. Closing as resolved.

<!-- gh-comment-id:6537221415 --> @coygeek commented on GitHub (Oct 31, 2026): I checked this against latest main, and the issue appears resolved. The original problem was that after I recorded an authenticated GameCube DOL observation, `get_evidence_bundle` in both summary and complete modes, `export_evidence_bundle`, and `close_binary` with `snapshot_path` all failed with a Zod `invalid_union` error on the `format` discriminator, because the bundle artifact manifest only accepted the detected-format and raw-binary subject branches and rejected `gamecube-dol`, even though the Evidence subject schema itself accepted a DOL subject with architecture `powerpc`. The fix in commit [`50822e1ef`](https://github.com/morluto/rea/commit/50822e1eff99136c5e5f7b1b1d3351c898937983), merged via [PR #7481](https://github.com/morluto/rea/pull/7481) (merge commit [`54756ff24`](https://github.com/morluto/rea/commit/54756ff24e1f4c2e47554f61ea5efe57bab27b64)) into `main`, changes `src/domain/evidenceBundle.ts` so the artifact manifest is built with `withEvidenceSubjectDeclaration` from `src/domain/evidenceSubject.ts`, which includes all three subject branches, including `gamecube-dol` with architecture `powerpc`. The same shared helper is now used by `src/domain/evidence.ts` and `src/domain/analysisSnapshot.ts`, so Evidence, bundles, and snapshots no longer disagree about this admitted format. [PR #7481](https://github.com/morluto/rea/pull/7481) also adds regression coverage for exactly the reported flow: a DOL session test that saves with `close_binary` and `snapshot_path`, verifies the saved `gamecube-dol`/`powerpc` target and artifact manifest, reopens from the snapshot, and replays the read without re-running the provider, plus vocabulary tests that require the DOL format to pass through Evidence creation, immutable bundle creation, snapshot target parsing, and target summary. That covers the bundle reads, export, and snapshot-save path that were failing. Closing as resolved.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#4329
No description provided.