fix(analysis): retain source evidence through directory exports (#7250)

Retain authenticated provider source records independently of snapshot replay eligibility and return them explicitly to plain application callers, including late cancellation. CLI/MCP commit source records before delivering links; function dossiers share the canonical Evidence constructor. Keep directory replies compact and preserve successful retry verification.

Real Ghidra CLI/MCP investigations verify 652-function ls, historical report provenance, cross-session resume, unchanged source/project content and complete offline Evidence. Final full 14,338-function libcrypto comparison matches all metadata/pseudocode facts and independent fresh-import observations: 14,194 written, 143 external, one recorded deadline; 494.03 s, 445.63 CPU s, 1.584 GiB sampled family peak under 2-CPU/8-GiB guards, with no OOM or cleanup failure.

144 focused tests and static/docs/site checks pass; latest-main integration passes 289 cases plus typecheck/lint and actual CLI snapshot source retrieval. Final CI source/static/build/docs/quality/package checks pass. Four ADB shard failures also occur in main CI 40349559391; cancelled coverage remains unverified and author declarations stay unchecked under the user's explicit bypass authorization. No human-review attestation is made.
This commit is contained in:
gensokyo-dev authored and GitHub committed 2026-10-26 23:56:03 +08:00
1 parent 13fba271e6
commit 5508b2affd
15 files changed
+887 -66

No files matched your search

+9 -5
View File
@@ -1254,6 +1254,15 @@ export class BinarySession
)
this.#active.nativeSourceAdmitted = true;
this.#observeRuntimeAvailability(name, execution);
// Source facts belong to the observation, even when this query cannot be
// replayed (for example a Ghidra procedure read without a document selector).
if (execution.ok && execution.value.sourceEvidence !== undefined) {
const sourcesRecorded = recordEvidenceSources(
(source) => this.recordEvidence(source),
execution.value.sourceEvidence,
);
if (!sourcesRecorded.ok) return sourcesRecorded;
}
if (
execution.ok &&
cacheable &&
@@ -1276,11 +1285,6 @@ export class BinarySession
},
"observed",
);
const sourcesRecorded = recordEvidenceSources(
(source) => this.recordEvidence(source),
execution.value.sourceEvidence ?? [],
);
if (!sourcesRecorded.ok) return sourcesRecorded;
const recorded = this.recordEvidence(evidence);
if (!recorded.ok) return recorded;
const retained = { ...execution.value, evidenceId: evidence.evidence_id };