mirror of
https://github.com/morluto/rea.git
synced 2026-10-29 19:05:45 +00:00
* fix(hopper): report unavailable procedure body coverage * refactor!: simplify runtime tools and remove replay engines Keep direct inspection, capture, and comparison tools. Bind handlers to named contracts and let agents compose experiments with commands and local fixture servers. BREAKING CHANGE: Remove controlled replay, Node characterization, finite replay-machine, managed runtime planning, and redundant string-tracing tools. Retire process replay, shims, reactive scenarios, custom checkpoints, and active browser replay and origin-scope inputs.
268 lines
8.2 KiB
TypeScript
268 lines
8.2 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import { INVESTIGATION_EXAMPLES } from "../contracts/investigationExamples.js";
|
|
import { createEvidence, type Evidence } from "./evidence.js";
|
|
import type { JsonValue } from "./jsonValue.js";
|
|
import {
|
|
correlateStaticAndRuntime,
|
|
staticRuntimeCorrelationInputSchema,
|
|
staticRuntimeCorrelationResultSchema,
|
|
} from "./staticRuntimeCorrelation.js";
|
|
|
|
const staticComparison =
|
|
INVESTIGATION_EXAMPLES.find_changed_behavior.comparisons[0];
|
|
if (staticComparison === undefined)
|
|
throw new Error("Missing static comparison fixture");
|
|
|
|
const capture = (digit: string): Evidence =>
|
|
createEvidence(
|
|
undefined,
|
|
{ id: "fixture", name: "Fixture", version: "1" },
|
|
{
|
|
predicateType: "rea.process-capture",
|
|
operation: "capture_process_scenario",
|
|
parameters: {},
|
|
result: { digit },
|
|
authority: "controlled-replay",
|
|
environment: {
|
|
id: `fixture-${digit}`,
|
|
platform: "test",
|
|
architecture: "test",
|
|
isolation: "process",
|
|
},
|
|
},
|
|
);
|
|
|
|
const leftCapture = capture("1");
|
|
const rightCapture = capture("2");
|
|
|
|
const processComparison = (
|
|
terminal: "unchanged" | "changed" | "unknown" | "truncated",
|
|
): Evidence => {
|
|
const result = {
|
|
status: terminal,
|
|
terminal,
|
|
interaction: terminal === "truncated" ? "truncated" : "unchanged",
|
|
exit: terminal === "truncated" ? "truncated" : "unchanged",
|
|
filesystem: terminal === "truncated" ? "truncated" : "unchanged",
|
|
process: terminal === "truncated" ? "truncated" : "unchanged",
|
|
first_divergence:
|
|
terminal === "changed"
|
|
? {
|
|
status: "found",
|
|
dimension: "terminal",
|
|
index: 0,
|
|
left_at_ms: 0,
|
|
right_at_ms: 0,
|
|
left: "left",
|
|
right: "right",
|
|
}
|
|
: terminal === "truncated" || terminal === "unknown"
|
|
? { status: "unknown", reason: "Incomplete fixture." }
|
|
: { status: "none" },
|
|
limitations: terminal === "unknown" ? ["Terminal unavailable."] : [],
|
|
} satisfies JsonValue;
|
|
return createEvidence(
|
|
undefined,
|
|
{
|
|
id: "rea-process",
|
|
name: "REA deterministic process harness",
|
|
version: "3",
|
|
},
|
|
{
|
|
predicateType: "rea.process-comparison",
|
|
operation: "compare_process_captures",
|
|
parameters: {
|
|
left_evidence_id: leftCapture.evidence_id,
|
|
right_evidence_id: rightCapture.evidence_id,
|
|
},
|
|
result,
|
|
confidence: "derived",
|
|
authority: "analyst-inference",
|
|
evidenceLinks: [leftCapture.evidence_id, rightCapture.evidence_id],
|
|
},
|
|
);
|
|
};
|
|
|
|
const mapping = (
|
|
runtime: Evidence,
|
|
expected: "cochanged" | "static_only" | "runtime_only" | "both_unchanged",
|
|
dimension: string = "terminal",
|
|
) => ({
|
|
static_comparisons: [staticComparison],
|
|
runtime_comparisons: [runtime],
|
|
mappings: [
|
|
{
|
|
static: {
|
|
comparison_evidence_id: staticComparison.evidence_id,
|
|
selector: {
|
|
kind: "function" as const,
|
|
dimension: "pseudocode" as const,
|
|
},
|
|
},
|
|
runtime: {
|
|
comparison_evidence_id: runtime.evidence_id,
|
|
dimension,
|
|
},
|
|
side_alignment: "left_to_left" as const,
|
|
hypothesis: {
|
|
statement: "The static edit is associated with terminal behavior.",
|
|
expected_pattern: expected,
|
|
},
|
|
},
|
|
],
|
|
});
|
|
|
|
describe("static/runtime correlation", () => {
|
|
it("accepts real runtime dimensions and rejects removed protocol dimensions", () => {
|
|
const runtime = processComparison("unchanged");
|
|
expect(
|
|
correlateStaticAndRuntime(mapping(runtime, "static_only", "interaction")),
|
|
).toMatchObject({ status: "correlated" });
|
|
for (const dimension of ["protocol", "shim"] as const)
|
|
expect(
|
|
staticRuntimeCorrelationInputSchema.safeParse(
|
|
mapping(runtime, "static_only", dimension),
|
|
).success,
|
|
).toBe(false);
|
|
});
|
|
|
|
it("keeps consistent cochange as a hypothesis with complete citations", () => {
|
|
const runtime = processComparison("changed");
|
|
const result = correlateStaticAndRuntime(mapping(runtime, "cochanged"));
|
|
expect(staticRuntimeCorrelationResultSchema.parse(result)).toMatchObject({
|
|
status: "correlated",
|
|
summary: { hypotheses: 1, contradictions: 0, unresolved: 0 },
|
|
correlations: {
|
|
items: [
|
|
{
|
|
observed_pattern: "cochanged",
|
|
classification: "hypothesis",
|
|
side_alignment: "left_to_left",
|
|
},
|
|
],
|
|
},
|
|
});
|
|
expect(result.correlations.items[0]?.evidence_links).toEqual(
|
|
expect.arrayContaining([
|
|
staticComparison.evidence_id,
|
|
runtime.evidence_id,
|
|
leftCapture.evidence_id,
|
|
rightCapture.evidence_id,
|
|
]),
|
|
);
|
|
expect(result.limitations.join(" ")).toMatch(
|
|
/does not establish causality/u,
|
|
);
|
|
});
|
|
|
|
it("classifies an explicit expectation mismatch as contradiction", () => {
|
|
const result = correlateStaticAndRuntime(
|
|
mapping(processComparison("unchanged"), "cochanged"),
|
|
);
|
|
expect(result).toMatchObject({
|
|
status: "contradicted",
|
|
summary: { hypotheses: 0, contradictions: 1, unresolved: 0 },
|
|
correlations: {
|
|
items: [
|
|
{ observed_pattern: "static_only", classification: "contradiction" },
|
|
],
|
|
},
|
|
});
|
|
});
|
|
|
|
it("lets unknown and truncation dominate rather than imply equivalence", () => {
|
|
const unknown = correlateStaticAndRuntime(
|
|
mapping(processComparison("unknown"), "cochanged"),
|
|
);
|
|
const truncated = correlateStaticAndRuntime(
|
|
mapping(processComparison("truncated"), "cochanged"),
|
|
);
|
|
expect(unknown).toMatchObject({
|
|
status: "unknown",
|
|
correlations: { items: [{ classification: "unresolved_branch" }] },
|
|
});
|
|
expect(truncated).toMatchObject({
|
|
status: "truncated",
|
|
correlations: { items: [{ observed_pattern: "truncated" }] },
|
|
});
|
|
});
|
|
|
|
it("returns all correlations order-stably and rejects duplicates and absent selectors", () => {
|
|
const runtime = processComparison("changed");
|
|
const base = mapping(runtime, "cochanged");
|
|
const second = {
|
|
...base.mappings[0],
|
|
runtime: { ...base.mappings[0]!.runtime, dimension: "exit" as const },
|
|
hypothesis: {
|
|
statement: "The edit is associated with exit behavior.",
|
|
expected_pattern: "static_only" as const,
|
|
},
|
|
};
|
|
const forward = correlateStaticAndRuntime({
|
|
...base,
|
|
mappings: [base.mappings[0], second],
|
|
});
|
|
const reversed = correlateStaticAndRuntime({
|
|
...base,
|
|
mappings: [second, base.mappings[0]],
|
|
});
|
|
expect(reversed).toEqual(forward);
|
|
expect(forward.correlations.items).toHaveLength(2);
|
|
expect(() =>
|
|
correlateStaticAndRuntime({
|
|
...base,
|
|
mappings: [base.mappings[0], base.mappings[0]],
|
|
}),
|
|
).toThrow(/duplicate mappings/u);
|
|
expect(() =>
|
|
correlateStaticAndRuntime({
|
|
...base,
|
|
mappings: [
|
|
{
|
|
...base.mappings[0],
|
|
static: {
|
|
...base.mappings[0]!.static,
|
|
selector: { kind: "function", dimension: "assembly" },
|
|
},
|
|
},
|
|
],
|
|
}),
|
|
).not.toThrow();
|
|
expect(() =>
|
|
correlateStaticAndRuntime({
|
|
...base,
|
|
mappings: [
|
|
{
|
|
...base.mappings[0],
|
|
static: {
|
|
comparison_evidence_id: runtime.evidence_id,
|
|
selector: { kind: "function", dimension: "pseudocode" },
|
|
},
|
|
},
|
|
],
|
|
}),
|
|
).toThrow(/absent static comparison/u);
|
|
});
|
|
|
|
it("rejects comparison citations that disagree with source parameters", () => {
|
|
const runtime = processComparison("changed");
|
|
const forged = createEvidence(undefined, runtime.provider, {
|
|
predicateType: runtime.predicate_type,
|
|
operation: runtime.operation,
|
|
parameters: {
|
|
left_evidence_id: leftCapture.evidence_id,
|
|
right_evidence_id: staticComparison.evidence_id,
|
|
},
|
|
result: runtime.normalized_result,
|
|
confidence: runtime.confidence,
|
|
authority: runtime.authority,
|
|
evidenceLinks: runtime.evidence_links,
|
|
});
|
|
const input = mapping(forged, "cochanged");
|
|
expect(() => correlateStaticAndRuntime(input)).toThrow(
|
|
/closure disagrees with its source parameters/u,
|
|
);
|
|
});
|
|
});
|