mirror of
https://github.com/morluto/rea
synced 2026-10-27 06:33:32 -04:00
fix(mcp): retain complete application results across response limits
Retain complete authenticated application Evidence when the repeated MCP representation exceeds the default receive frame or Node string limit. Return a typed transport constraint, keep useful followup queries available, and stream full canonical bundles to atomic destinations. Verify complete Notion and Obsidian workflows on Linux and native Windows, full CLI/Evidence parity, and real large Chrome screenshot recovery. Preserve complete success contracts and caller-selected evidence paths. Refs #1065, #1053.
This commit is contained in:
@@ -8,6 +8,18 @@ import type {
|
||||
JavaScriptApplicationAnalysisResult,
|
||||
} from "../../domain/javascript/javascriptApplicationAnalysis.js";
|
||||
import { JAVASCRIPT_APPLICATION_PROVIDER } from "../InvestigationProviders.js";
|
||||
import { freezeJsonSnapshot } from "../../domain/immutableJson.js";
|
||||
import { rememberOwnedApplicationGraphEvidence } from "./JavaScriptApplicationEvidenceGraph.js";
|
||||
|
||||
/** Transfer an already validated, application-owned result into immutable analysis Evidence. */
|
||||
export const createOwnedJavaScriptApplicationEvidence = (
|
||||
input: AnalyzeJavaScriptApplicationInput,
|
||||
result: JavaScriptApplicationAnalysisResult,
|
||||
): Evidence =>
|
||||
rememberOwnedApplicationGraphEvidence(
|
||||
createJavaScriptApplicationEvidence(input, freezeJsonSnapshot(result)),
|
||||
result,
|
||||
);
|
||||
|
||||
/** Create Evidence for one deterministic local JavaScript application graph. */
|
||||
export const createJavaScriptApplicationEvidence = (
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { JAVASCRIPT_APPLICATION_EVIDENCE_EXAMPLE } from "../../contracts/javascript/javascriptRuntimeReconciliationExample.js";
|
||||
import { parseEvidence } from "../../domain/evidence.js";
|
||||
import {
|
||||
analyzeJavaScriptApplicationInputSchema,
|
||||
javascriptApplicationAnalysisResultSchema,
|
||||
} from "../../domain/javascript/javascriptApplicationAnalysis.js";
|
||||
import {
|
||||
createJavaScriptApplicationEvidence,
|
||||
createOwnedJavaScriptApplicationEvidence,
|
||||
} from "./JavaScriptApplicationEvidence.js";
|
||||
import {
|
||||
parseApplicationGraphEvidence,
|
||||
rememberOwnedApplicationGraphEvidence,
|
||||
} from "./JavaScriptApplicationEvidenceGraph.js";
|
||||
|
||||
describe("owned application graph Evidence", () => {
|
||||
it("reuses the exact authenticated graph and preserves ordinary wire identity", () => {
|
||||
const result = javascriptApplicationAnalysisResultSchema.parse(
|
||||
JAVASCRIPT_APPLICATION_EVIDENCE_EXAMPLE.normalized_result,
|
||||
);
|
||||
const input = analyzeJavaScriptApplicationInputSchema.parse({
|
||||
input_path: result.input_path,
|
||||
...JAVASCRIPT_APPLICATION_EVIDENCE_EXAMPLE.parameters,
|
||||
});
|
||||
const ordinary = createJavaScriptApplicationEvidence(input, result);
|
||||
const owned = createOwnedJavaScriptApplicationEvidence(input, result);
|
||||
expect(owned.evidence_id).toBe(ordinary.evidence_id);
|
||||
expect(JSON.stringify(owned)).toBe(JSON.stringify(ordinary));
|
||||
const parsed = parseApplicationGraphEvidence(owned);
|
||||
expect(parsed.evidence).toBe(owned);
|
||||
expect(parsed.graph).toBe(result.graph);
|
||||
expect(parsed.semanticGraph).toBe(result.semantic_graph);
|
||||
expect(Object.isFrozen(parsed.graph.nodes)).toBe(true);
|
||||
expect(parseApplicationGraphEvidence(owned)).toBe(parsed);
|
||||
const wire: unknown = JSON.parse(JSON.stringify(owned));
|
||||
expect(parseApplicationGraphEvidence(wire)).toEqual(parsed);
|
||||
expect(parseApplicationGraphEvidence(wire).graph).not.toBe(parsed.graph);
|
||||
expect(() =>
|
||||
rememberOwnedApplicationGraphEvidence(ordinary, result),
|
||||
).toThrow("exact validated immutable result");
|
||||
const tampered = { ...owned, normalized_result: {} };
|
||||
expect(() => parseEvidence(Object.freeze(tampered))).toThrow();
|
||||
expect(() => parseApplicationGraphEvidence(tampered)).toThrow();
|
||||
});
|
||||
});
|
||||
@@ -3,7 +3,11 @@ import {
|
||||
JAVASCRIPT_RUNTIME_RECONCILIATION_PROVIDER,
|
||||
MANAGED_WORKFLOW_PROVIDER,
|
||||
} from "../InvestigationProviders.js";
|
||||
import { parseEvidence, type Evidence } from "../../domain/evidence.js";
|
||||
import {
|
||||
isImmutableEvidence,
|
||||
parseEvidence,
|
||||
type Evidence,
|
||||
} from "../../domain/evidence.js";
|
||||
import {
|
||||
analyzeJavaScriptApplicationInputSchema,
|
||||
javascriptApplicationAnalysisResultSchema,
|
||||
@@ -26,11 +30,39 @@ export interface ApplicationGraphEvidenceSource {
|
||||
readonly semanticGraph: JavaScriptSemanticGraph | null;
|
||||
}
|
||||
|
||||
const ownedApplicationSources = new WeakMap<
|
||||
Evidence,
|
||||
ApplicationGraphEvidenceSource
|
||||
>();
|
||||
|
||||
/** Retain the producer-validated meaning of its exact immutable result snapshot. */
|
||||
export const rememberOwnedApplicationGraphEvidence = (
|
||||
evidence: Evidence,
|
||||
result: JavaScriptApplicationAnalysisResult,
|
||||
): Evidence => {
|
||||
if (
|
||||
!isImmutableEvidence(evidence) ||
|
||||
evidence.normalized_result !== result ||
|
||||
evidence.operation !== "analyze_javascript_application" ||
|
||||
!providerMatches(evidence, JAVASCRIPT_APPLICATION_PROVIDER)
|
||||
)
|
||||
throw new TypeError(
|
||||
"Owned application Evidence must bind its exact validated immutable result",
|
||||
);
|
||||
ownedApplicationSources.set(
|
||||
evidence,
|
||||
Object.freeze(staticApplicationSourceForResult(evidence, result)),
|
||||
);
|
||||
return evidence;
|
||||
};
|
||||
|
||||
/** Parse and authenticate one REA-produced JavaScript Application Graph Evidence. */
|
||||
export const parseApplicationGraphEvidence = (
|
||||
input: unknown,
|
||||
): ApplicationGraphEvidenceSource => {
|
||||
const evidence = parseEvidence(input);
|
||||
const owned = ownedApplicationSources.get(evidence);
|
||||
if (owned !== undefined) return owned;
|
||||
if (
|
||||
evidence.operation === "analyze_javascript_application" &&
|
||||
evidence.predicate_type === "rea.javascript-application-analysis" &&
|
||||
@@ -56,6 +88,16 @@ export const parseApplicationGraphEvidence = (
|
||||
|
||||
const staticApplicationSource = (
|
||||
evidence: Evidence,
|
||||
): ApplicationGraphEvidenceSource => {
|
||||
const result = javascriptApplicationAnalysisResultSchema.parse(
|
||||
evidence.normalized_result,
|
||||
);
|
||||
return staticApplicationSourceForResult(evidence, result);
|
||||
};
|
||||
|
||||
const staticApplicationSourceForResult = (
|
||||
evidence: Evidence,
|
||||
result: JavaScriptApplicationAnalysisResult,
|
||||
): ApplicationGraphEvidenceSource => {
|
||||
if (
|
||||
evidence.authority !== "shipped-artifact" ||
|
||||
@@ -64,9 +106,6 @@ const staticApplicationSource = (
|
||||
throw new TypeError(
|
||||
"JavaScript application Evidence authority or confidence is invalid",
|
||||
);
|
||||
const result = javascriptApplicationAnalysisResultSchema.parse(
|
||||
evidence.normalized_result,
|
||||
);
|
||||
if (evidence.predicate_type !== "rea.javascript-application-analysis")
|
||||
throw new TypeError(
|
||||
"JavaScript application Evidence predicate does not match its result shape",
|
||||
|
||||
@@ -16,7 +16,7 @@ import { projectInputIssues } from "../../domain/inputIssueProjection.js";
|
||||
import { err, ok, type Result } from "../../domain/result.js";
|
||||
import { ProviderAdapterError } from "../../domain/providerAdapterError.js";
|
||||
import type { ExecutionOptions } from "../AnalysisProvider.js";
|
||||
import { createJavaScriptApplicationEvidence } from "./JavaScriptApplicationEvidence.js";
|
||||
import { createOwnedJavaScriptApplicationEvidence } from "./JavaScriptApplicationEvidence.js";
|
||||
import { reconstructJavaScriptArtifact } from "./JavaScriptArtifactReconstruction.js";
|
||||
import { JAVASCRIPT_APPLICATION_PROVIDER } from "../InvestigationProviders.js";
|
||||
|
||||
@@ -77,7 +77,7 @@ export const analyzeJavaScriptApplicationValidated = async (
|
||||
total: 1,
|
||||
message: "Creating and hashing application analysis Evidence",
|
||||
});
|
||||
const evidence = createJavaScriptApplicationEvidence(input, result);
|
||||
const evidence = createOwnedJavaScriptApplicationEvidence(input, result);
|
||||
await options.progress?.report({
|
||||
phase: "analyze_javascript_application",
|
||||
completed: 1,
|
||||
|
||||
Reference in New Issue
Block a user