mirror of
https://github.com/morluto/rea
synced 2026-10-27 14:42:18 -04:00
refactor(javascript): group domain semantics and contracts (#907)
This commit is contained in:
@@ -0,0 +1,255 @@
|
||||
import { canonicalDigest } from "../comparisonSemantics.js";
|
||||
import { compareCodePoints, uniqueSorted } from "../canonicalOrdering.js";
|
||||
import type { Evidence } from "../evidence.js";
|
||||
import {
|
||||
createJavaScriptApplicationGraph,
|
||||
type ApplicationEdge,
|
||||
type ApplicationNode,
|
||||
type JavaScriptApplicationGraph,
|
||||
} from "./javascriptApplicationGraph.js";
|
||||
import {
|
||||
applicationFeatureTraceResultSchema,
|
||||
type ApplicationFeatureTraceResult,
|
||||
type TraceApplicationFeatureInput,
|
||||
} from "./javascriptFeatureTraceSchemas.js";
|
||||
import {
|
||||
findApplicationFeatureSeeds,
|
||||
type ApplicationFeatureSeedMatch,
|
||||
} from "./javascriptFeatureSeed.js";
|
||||
import {
|
||||
traverseApplicationFeature,
|
||||
type ApplicationFeatureTraversal,
|
||||
} from "./javascriptFeatureTraversal.js";
|
||||
import { buildJavaScriptNativeHandoffs } from "./javascriptNativeHandoff.js";
|
||||
|
||||
/** Pure, authenticated inputs projected by the application service. */
|
||||
export interface ApplicationFeatureTraceProjectionInput {
|
||||
readonly sourceEvidenceId: string;
|
||||
readonly graph: JavaScriptApplicationGraph;
|
||||
readonly nativeEvidence: readonly Evidence[];
|
||||
readonly seed: TraceApplicationFeatureInput["seed"];
|
||||
readonly direction: TraceApplicationFeatureInput["direction"];
|
||||
}
|
||||
|
||||
/** Trace a literal feature through its complete reachable, authority-preserving JAG. */
|
||||
export const traceApplicationFeature = (
|
||||
input: ApplicationFeatureTraceProjectionInput,
|
||||
): ApplicationFeatureTraceResult => {
|
||||
const allSeedMatches = findApplicationFeatureSeeds(
|
||||
input.graph.nodes,
|
||||
input.seed,
|
||||
);
|
||||
const seedMatches = allSeedMatches;
|
||||
if (seedMatches.length === 0) return noMatchResult(input);
|
||||
const traversal = traverseApplicationFeature(
|
||||
input.graph,
|
||||
seedMatches.map(({ node_id: id }) => id),
|
||||
input.direction,
|
||||
);
|
||||
const graph = traceGraph(input, seedMatches, traversal);
|
||||
const paths = terminalPaths(traversal, seedMatches);
|
||||
const nativeHandoffs = buildJavaScriptNativeHandoffs(
|
||||
traversal.nodes,
|
||||
traversal.edges,
|
||||
input.nativeEvidence,
|
||||
);
|
||||
const evidenceLinks = uniqueSorted([
|
||||
input.sourceEvidenceId,
|
||||
...nativeHandoffs.flatMap(({ evidence_ids: ids }) => ids),
|
||||
]);
|
||||
const semantic = {
|
||||
source_evidence_id: input.sourceEvidenceId,
|
||||
source_graph_id: input.graph.graph_id,
|
||||
seed: input.seed,
|
||||
direction: input.direction,
|
||||
seed_matches: seedMatches,
|
||||
graph,
|
||||
paths,
|
||||
native_handoffs: nativeHandoffs,
|
||||
summary: {
|
||||
matched_seeds: seedMatches.length,
|
||||
traced_nodes: traversal.nodes.length,
|
||||
traced_edges: traversal.edges.length,
|
||||
terminal_paths: paths.length,
|
||||
native_handoffs: nativeHandoffs.length,
|
||||
...factSummary(traversal.nodes, traversal.edges),
|
||||
},
|
||||
coverage: {
|
||||
status: traceCoverageStatus(input.graph),
|
||||
source_graph_status: input.graph.coverage.status,
|
||||
total_seed_matches: allSeedMatches.length,
|
||||
},
|
||||
evidence_links: evidenceLinks,
|
||||
limitations: traceLimitations(input.graph),
|
||||
};
|
||||
return applicationFeatureTraceResultSchema.parse({
|
||||
...semantic,
|
||||
trace_id: `jatr_${canonicalDigest(semantic, "Feature trace")}`,
|
||||
});
|
||||
};
|
||||
|
||||
const noMatchResult = (
|
||||
input: ApplicationFeatureTraceProjectionInput,
|
||||
): ApplicationFeatureTraceResult => {
|
||||
const semantic = {
|
||||
source_evidence_id: input.sourceEvidenceId,
|
||||
source_graph_id: input.graph.graph_id,
|
||||
seed: input.seed,
|
||||
direction: input.direction,
|
||||
seed_matches: [],
|
||||
graph: null,
|
||||
paths: [],
|
||||
native_handoffs: [],
|
||||
summary: {
|
||||
matched_seeds: 0,
|
||||
traced_nodes: 0,
|
||||
traced_edges: 0,
|
||||
terminal_paths: 0,
|
||||
native_handoffs: 0,
|
||||
observed_facts: 0,
|
||||
inferred_facts: 0,
|
||||
unknown_facts: 0,
|
||||
unavailable_facts: 0,
|
||||
},
|
||||
coverage: {
|
||||
status: "no-match" as const,
|
||||
source_graph_status: input.graph.coverage.status,
|
||||
total_seed_matches: 0,
|
||||
},
|
||||
evidence_links: [input.sourceEvidenceId],
|
||||
limitations: uniqueSorted([
|
||||
"No graph entity matched the literal seed; this is not evidence that the feature is absent.",
|
||||
...sourceCoverageLimitations(input.graph),
|
||||
]),
|
||||
};
|
||||
return applicationFeatureTraceResultSchema.parse({
|
||||
...semantic,
|
||||
trace_id: `jatr_${canonicalDigest(semantic, "Feature trace")}`,
|
||||
});
|
||||
};
|
||||
|
||||
const traceGraph = (
|
||||
input: ApplicationFeatureTraceProjectionInput,
|
||||
seedMatches: readonly ApplicationFeatureSeedMatch[],
|
||||
traversal: ApplicationFeatureTraversal,
|
||||
): JavaScriptApplicationGraph => {
|
||||
return createJavaScriptApplicationGraph({
|
||||
schema: "JavaScriptApplicationGraph",
|
||||
root_node_ids: uniqueSorted(seedMatches.map(({ node_id: id }) => id)),
|
||||
nodes: traversal.nodes,
|
||||
edges: traversal.edges,
|
||||
coverage: traceGraphCoverage(input.graph),
|
||||
limitations: uniqueSorted([
|
||||
...input.graph.limitations,
|
||||
"Trace edges retain their source authority; graph connectivity does not prove runtime execution or reachability.",
|
||||
]),
|
||||
});
|
||||
};
|
||||
|
||||
const traceGraphCoverage = (
|
||||
source: JavaScriptApplicationGraph,
|
||||
): JavaScriptApplicationGraph["coverage"] => {
|
||||
return source.coverage.status === "complete"
|
||||
? { status: "complete", truncated: false, omitted_count: 0, limits: [] }
|
||||
: source.coverage;
|
||||
};
|
||||
|
||||
const terminalPaths = (
|
||||
traversal: ApplicationFeatureTraversal,
|
||||
seeds: readonly ApplicationFeatureSeedMatch[],
|
||||
): ApplicationFeatureTraceResult["paths"] => {
|
||||
const seedIds = new Set(seeds.map(({ node_id: id }) => id));
|
||||
const edgeById = new Map(traversal.edges.map((edge) => [edge.edge_id, edge]));
|
||||
return traversal.nodes
|
||||
.filter(
|
||||
(node) =>
|
||||
isTerminal(node) &&
|
||||
(!seedIds.has(node.node_id) || traversal.nodes.length === 1),
|
||||
)
|
||||
.map((node) => pathTo(node, traversal.predecessors, edgeById))
|
||||
.filter((path): path is NonNullable<typeof path> => path !== null)
|
||||
.sort((left, right) => compareCodePoints(left.path_id, right.path_id));
|
||||
};
|
||||
|
||||
const pathTo = (
|
||||
node: ApplicationNode,
|
||||
predecessors: ApplicationFeatureTraversal["predecessors"],
|
||||
edgeById: ReadonlyMap<string, ApplicationEdge>,
|
||||
): ApplicationFeatureTraceResult["paths"][number] | null => {
|
||||
const nodeIds = [node.node_id];
|
||||
const edgeIds: string[] = [];
|
||||
let current = node.node_id;
|
||||
while (predecessors.has(current)) {
|
||||
const predecessor = predecessors.get(current);
|
||||
if (predecessor === undefined) break;
|
||||
nodeIds.push(predecessor.previousNodeId);
|
||||
edgeIds.push(predecessor.edgeId);
|
||||
current = predecessor.previousNodeId;
|
||||
}
|
||||
nodeIds.reverse();
|
||||
edgeIds.reverse();
|
||||
const edges = edgeIds
|
||||
.map((edgeId) => edgeById.get(edgeId))
|
||||
.filter((edge): edge is ApplicationEdge => edge !== undefined);
|
||||
if (edges.length !== edgeIds.length) return null;
|
||||
const semantic = {
|
||||
start_node_id: nodeIds[0] ?? node.node_id,
|
||||
end_node_id: node.node_id,
|
||||
end_kind: node.kind,
|
||||
node_ids: nodeIds,
|
||||
edge_ids: edgeIds,
|
||||
authorities: uniqueSorted(edges.map(({ evidence }) => evidence.authority)),
|
||||
contains_inference: edges.some(
|
||||
({ evidence }) => evidence.state === "inferred",
|
||||
),
|
||||
};
|
||||
return {
|
||||
...semantic,
|
||||
path_id: `jatp_${canonicalDigest(semantic, "Feature trace")}`,
|
||||
};
|
||||
};
|
||||
|
||||
const isTerminal = (node: ApplicationNode): boolean =>
|
||||
["endpoint", "storage", "native-addon", "native-export", "unknown"].includes(
|
||||
node.kind,
|
||||
);
|
||||
|
||||
const factSummary = (
|
||||
nodes: readonly ApplicationNode[],
|
||||
edges: readonly ApplicationEdge[],
|
||||
) => {
|
||||
const states = [
|
||||
...nodes.flatMap(({ observations }) =>
|
||||
observations.map(({ evidence }) => evidence.state),
|
||||
),
|
||||
...edges.map(({ evidence }) => evidence.state),
|
||||
];
|
||||
return {
|
||||
observed_facts: states.filter((state) => state === "observed").length,
|
||||
inferred_facts: states.filter((state) => state === "inferred").length,
|
||||
unknown_facts: states.filter((state) => state === "unknown").length,
|
||||
unavailable_facts: states.filter((state) => state === "unavailable").length,
|
||||
};
|
||||
};
|
||||
|
||||
const traceCoverageStatus = (
|
||||
graph: JavaScriptApplicationGraph,
|
||||
): ApplicationFeatureTraceResult["coverage"]["status"] =>
|
||||
graph.coverage.status === "complete" ? "complete-within-source" : "partial";
|
||||
|
||||
const traceLimitations = (graph: JavaScriptApplicationGraph): string[] =>
|
||||
uniqueSorted([
|
||||
"A trace reports graph relationships, not proof that code executed or that a feature is reachable in every state.",
|
||||
"Static, native, passive-runtime, inferred, and unknown facts retain their original authority in the returned graph.",
|
||||
"Native handoffs never open a binary or invoke a provider automatically; snapshot reuse remains provider/profile/target exact.",
|
||||
...sourceCoverageLimitations(graph),
|
||||
]);
|
||||
|
||||
const sourceCoverageLimitations = (
|
||||
graph: JavaScriptApplicationGraph,
|
||||
): string[] =>
|
||||
graph.coverage.status === "complete"
|
||||
? []
|
||||
: [
|
||||
"The source application graph is incomplete; unmatched seeds and frontiers remain unknown.",
|
||||
];
|
||||
Reference in New Issue
Block a user