mirror of
https://github.com/morluto/rea.git
synced 2026-11-12 09:52:27 +00:00
147 lines
5.8 KiB
TypeScript
147 lines
5.8 KiB
TypeScript
import { readArtifactInspectionSources } from "../domain/artifactInspection.js";
|
|
import type { AnalysisError } from "../domain/analysisErrorBase.js";
|
|
import { tryParseEvidence, type Evidence } from "../domain/evidence.js";
|
|
import { jsonValueByteLength } from "../domain/jsonValueByteLength.js";
|
|
import { err, ok, type Result } from "../domain/result.js";
|
|
|
|
/** Resolve the embedded publication closure without reinterpreting it in delivery adapters. */
|
|
export const analysisEvidenceSources = (
|
|
complete: Evidence,
|
|
): Result<Evidence[], AnalysisError> => {
|
|
const embedded =
|
|
complete.operation === "inspect_artifact"
|
|
? readArtifactInspectionSources(complete.normalized_result)
|
|
: ok([]);
|
|
if (!embedded.ok)
|
|
return err(embedded.error.retainPartialObservation(complete));
|
|
return ok([...embedded.value, complete]);
|
|
};
|
|
|
|
/** Matches the diagnostics allowance retained for other finalized one-shot work. */
|
|
const SOURCE_CLOSURE_INLINE_BYTES = 64 * 1024;
|
|
/** Identities beyond this stay counted; direct links remain on the observation. */
|
|
const SOURCE_CLOSURE_LISTED_OMISSIONS = 64;
|
|
const SOURCE_CLOSURE_RECOVERY =
|
|
"No bundle was written and this invocation retains nothing after exit. Keep any records shown here, or run the operation again after following remediation; that is a new observation and may differ.";
|
|
|
|
/** What a failed one-shot delivery holds for one record its observation cites. */
|
|
export type SourceClosureOmission = {
|
|
readonly evidence_id: string;
|
|
/**
|
|
* `not_captured`: this invocation holds no such record, so none can be shown.
|
|
* `not_inlined`: captured, but not part of this bounded failure response.
|
|
*/
|
|
readonly reason: "not_captured" | "not_inlined";
|
|
};
|
|
|
|
/** Bounded failure handoff for a completed observation whose bundle never committed. */
|
|
export type UndeliveredSourceClosure = {
|
|
readonly publication: "not_published";
|
|
/** The embedded source list was read and every cited record is in `records` or the observation. */
|
|
readonly complete: boolean;
|
|
/** The embedded producer source list could not be read, so closure remains unknown. */
|
|
readonly collection_failure?: string;
|
|
readonly records: Evidence[];
|
|
readonly omitted_count: number;
|
|
readonly omitted: SourceClosureOmission[];
|
|
readonly recovery: string;
|
|
};
|
|
|
|
/** The closure state is unknown because examining it failed. */
|
|
export type UnavailableSourceClosure = {
|
|
readonly publication: "not_published";
|
|
readonly complete: false;
|
|
readonly collection_failure: string;
|
|
readonly recovery: string;
|
|
};
|
|
|
|
const collectSourceClosure = (
|
|
observation: Evidence,
|
|
captured: readonly Evidence[],
|
|
options: { readonly inlineRecords: boolean },
|
|
): UndeliveredSourceClosure | undefined => {
|
|
const inspection = analysisEvidenceSources(observation);
|
|
const embedded = new Map(
|
|
(inspection.ok ? inspection.value : []).map((record) => [
|
|
record.evidence_id,
|
|
record,
|
|
]),
|
|
);
|
|
const held = new Map(captured.map((record) => [record.evidence_id, record]));
|
|
// Set iteration reaches entries added while it runs, which makes this a
|
|
// deduplicating breadth-first queue: directly cited records spend the
|
|
// allowance first, and each link costs one lookup however often it repeats.
|
|
const closure = new Set([observation.evidence_id]);
|
|
for (const evidenceId of observation.evidence_links) closure.add(evidenceId);
|
|
for (const evidenceId of held.keys()) closure.add(evidenceId);
|
|
const records: Evidence[] = [];
|
|
const omitted: SourceClosureOmission[] = [];
|
|
let omittedCount = 0;
|
|
let inlineBytes = options.inlineRecords ? SOURCE_CLOSURE_INLINE_BYTES : 0;
|
|
const omit = (
|
|
evidenceId: string,
|
|
reason: SourceClosureOmission["reason"],
|
|
) => {
|
|
omittedCount += 1;
|
|
if (omitted.length < SOURCE_CLOSURE_LISTED_OMISSIONS)
|
|
omitted.push({ evidence_id: evidenceId, reason });
|
|
};
|
|
for (const evidenceId of closure) {
|
|
if (evidenceId === observation.evidence_id) continue;
|
|
const inObservation = embedded.get(evidenceId);
|
|
const record = inObservation ?? held.get(evidenceId);
|
|
if (record === undefined) {
|
|
omit(evidenceId, "not_captured");
|
|
continue;
|
|
}
|
|
for (const link of record.evidence_links) closure.add(link);
|
|
if (inObservation !== undefined) continue;
|
|
const bytes = jsonValueByteLength(record, inlineBytes);
|
|
if (bytes > inlineBytes) {
|
|
omit(evidenceId, "not_inlined");
|
|
continue;
|
|
}
|
|
records.push(record);
|
|
inlineBytes -= bytes;
|
|
}
|
|
if (closure.size === 1 && inspection.ok) return undefined;
|
|
return {
|
|
publication: "not_published",
|
|
complete: inspection.ok && omittedCount === 0,
|
|
...(inspection.ok ? {} : { collection_failure: inspection.error.name }),
|
|
records,
|
|
omitted_count: omittedCount,
|
|
omitted,
|
|
recovery: SOURCE_CLOSURE_RECOVERY,
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Describe the source closure of a completed observation after delivery failed
|
|
* before commit. Only already captured records are reported, so an unresolved
|
|
* link stays an explicit omission and its own ancestors remain unknown.
|
|
*
|
|
* This annotates a failure that must reach the caller, so it never throws. If
|
|
* examining the closure fails, the state is reported as unknown, naming only
|
|
* the bounded error type rather than a message that could quote analyzed data.
|
|
*/
|
|
export const undeliveredSourceClosure = (
|
|
partialObservation: unknown,
|
|
captured: readonly Evidence[],
|
|
options: { readonly inlineRecords: boolean },
|
|
): UndeliveredSourceClosure | UnavailableSourceClosure | undefined => {
|
|
try {
|
|
const observation = tryParseEvidence(partialObservation);
|
|
return observation === undefined
|
|
? undefined
|
|
: collectSourceClosure(observation, captured, options);
|
|
} catch (cause: unknown) {
|
|
return {
|
|
publication: "not_published",
|
|
complete: false,
|
|
collection_failure: cause instanceof Error ? cause.name : "unknown",
|
|
recovery: SOURCE_CLOSURE_RECOVERY,
|
|
};
|
|
}
|
|
};
|