rea-agents 2.1.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +84 -18
- package/dist/application/AndroidApplicationService.js +17 -0
- package/dist/application/AppleApplicationService.js +17 -0
- package/dist/application/ApplicationWorkflowEvidenceResolver.js +162 -0
- package/dist/application/BinarySession.js +9 -2
- package/dist/application/BinarySessionStatus.js +39 -1
- package/dist/application/CapabilityInventory.js +15 -0
- package/dist/application/ClientRegistrationStatus.js +11 -4
- package/dist/application/CommandShimReplay.js +6 -3
- package/dist/application/CompositeProvider.js +5 -2
- package/dist/application/DirectAnalysis.js +1 -20
- package/dist/application/DirectAnalysisStatus.js +83 -0
- package/dist/application/Doctor.js +34 -25
- package/dist/application/DoctorDiagnostics.js +1 -4
- package/dist/application/DoctorProjection.js +43 -0
- package/dist/application/DoctorScope.js +102 -0
- package/dist/application/EvidenceReferenceResolver.js +26 -0
- package/dist/application/InventoryProjectionEvidence.js +41 -0
- package/dist/application/InvestigationProviders.js +12 -0
- package/dist/application/JavaScriptApplicationEvidence.js +1 -1
- package/dist/application/JavaScriptApplicationEvidenceGraph.js +10 -1
- package/dist/application/JavaScriptApplicationService.js +3 -2
- package/dist/application/JavaScriptApplicationWorkflowEvidence.js +26 -0
- package/dist/application/JavaScriptApplicationWorkflowService.js +49 -1
- package/dist/application/JavaScriptArtifactReconstruction.js +7 -0
- package/dist/application/JavaScriptModuleRelationships.js +25 -1
- package/dist/application/JavaScriptReturnShapeProjection.js +111 -0
- package/dist/application/JavaScriptSemanticGraphBuilder.js +294 -0
- package/dist/application/JavaScriptSemanticGraphConstruction.js +144 -0
- package/dist/application/JavaScriptSemanticGraphEvidence.js +86 -0
- package/dist/application/JavaScriptSemanticGraphFlowProjection.js +72 -0
- package/dist/application/JavaScriptSemanticGraphProjection.js +33 -0
- package/dist/application/JavaScriptSemanticTraceService.js +45 -0
- package/dist/application/LoopbackReplay.js +277 -133
- package/dist/application/LoopbackReplayRecorder.js +101 -0
- package/dist/application/PermissionAuthority.js +7 -3
- package/dist/application/ProcessCaptureJournal.js +95 -0
- package/dist/application/ProcessCaptureLifecycle.js +24 -13
- package/dist/application/ProcessCheckpoints.js +30 -4
- package/dist/application/ProcessCli.js +26 -4
- package/dist/application/ProcessHarness.js +20 -50
- package/dist/application/ProcessNormalization.js +3 -2
- package/dist/application/ProcessPairedExperiment.js +72 -0
- package/dist/application/ProcessReactiveCoordinator.js +218 -0
- package/dist/application/ProcessReactiveEffects.js +133 -0
- package/dist/application/ProcessReactiveObservations.js +20 -0
- package/dist/application/ProcessSampling.js +2 -0
- package/dist/application/SessionProviderRouter.js +7 -6
- package/dist/application/Setup.js +14 -13
- package/dist/application/SetupClientConfiguration.js +10 -6
- package/dist/application/SetupPlan.js +4 -3
- package/dist/application/SetupRegistrationEnvironment.js +12 -0
- package/dist/application/SetupSkill.js +44 -40
- package/dist/application/TerminalRenderer.js +3 -1
- package/dist/application/Uninstall.js +7 -1
- package/dist/application/Upgrade.js +16 -1
- package/dist/browser/CdpEndpoint.js +37 -4
- package/dist/catalogIdentity.js +16 -7
- package/dist/cli/coreAnalysisCommands.js +34 -2
- package/dist/cli/javascriptApplicationAnalysis.js +19 -0
- package/dist/cli/setupCommands.js +84 -30
- package/dist/cli/utilityCommands.js +10 -2
- package/dist/cliApplicationCommands.js +79 -16
- package/dist/cliCommandNames.js +3 -0
- package/dist/cliElectronCommands.js +23 -33
- package/dist/cliObservationOptions.js +1 -1
- package/dist/cliOutput.js +56 -0
- package/dist/cliProcessCommands.js +32 -1
- package/dist/cliSetup.js +55 -29
- package/dist/contracts/applicationToolContracts.js +54 -7
- package/dist/contracts/applicationWorkflowInputContracts.js +119 -0
- package/dist/contracts/electronToolContracts.js +73 -4
- package/dist/contracts/javascriptApplicationWorkflowExamples.js +32 -9
- package/dist/contracts/managedToolContracts.js +7 -2
- package/dist/contracts/processCaptureExample.js +1 -0
- package/dist/contracts/replayMachineExample.js +37 -0
- package/dist/contracts/sessionStatusContract.js +26 -0
- package/dist/contracts/toolContractExamples.js +2 -0
- package/dist/contracts/toolContractTypes.js +12 -1
- package/dist/contracts/toolContracts.js +8 -11
- package/dist/contracts/toolEffects.js +3 -0
- package/dist/contracts/toolOutputSchemaGroups.js +53 -9
- package/dist/contracts/toolOutputSchemaPrimitives.js +73 -32
- package/dist/doctorRuntime.js +41 -0
- package/dist/domain/analysisErrorPresentation.js +5 -3
- package/dist/domain/analysisErrorProjection.js +7 -1
- package/dist/domain/androidApplication.js +206 -0
- package/dist/domain/appleApplication.js +221 -0
- package/dist/domain/boundedCartesianProjection.js +15 -0
- package/dist/domain/changedBehavior.js +5 -4
- package/dist/domain/completionLedgerGeneration.js +190 -0
- package/dist/domain/errors.js +4 -2
- package/dist/domain/evidenceCompletionLedger.js +113 -0
- package/dist/domain/hopperStartupFailure.js +9 -0
- package/dist/domain/javascriptApplicationAnalysis.js +44 -2
- package/dist/domain/javascriptExportShapeComparison.js +145 -0
- package/dist/domain/javascriptExportShapeComparisonIdentity.js +11 -0
- package/dist/domain/javascriptExportShapeComparisonSchemas.js +277 -0
- package/dist/domain/javascriptExportShapeSelection.js +132 -0
- package/dist/domain/javascriptExportShapeVariants.js +272 -0
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +2 -2
- package/dist/domain/javascriptSemanticAnalysis.js +17 -36
- package/dist/domain/javascriptSemanticCallResolution.js +129 -0
- package/dist/domain/javascriptSemanticCalls.js +269 -0
- package/dist/domain/javascriptSemanticGraph.js +356 -0
- package/dist/domain/javascriptSemanticGraphSchemas.js +329 -0
- package/dist/domain/javascriptSemanticGraphSerialization.js +23 -0
- package/dist/domain/javascriptSemanticIr.js +14 -1
- package/dist/domain/javascriptSemanticPrimitives.js +36 -0
- package/dist/domain/javascriptSemanticProjection.js +36 -4
- package/dist/domain/javascriptSemanticProvenance.js +29 -0
- package/dist/domain/javascriptSemanticQuery.js +294 -0
- package/dist/domain/javascriptSemanticQueryAssessment.js +74 -0
- package/dist/domain/javascriptSemanticQueryIdentity.js +86 -0
- package/dist/domain/javascriptSemanticQueryRelations.js +15 -0
- package/dist/domain/javascriptSemanticQuerySchemas.js +188 -0
- package/dist/domain/javascriptSemanticReturns.js +187 -0
- package/dist/domain/javascriptSemanticState.js +32 -0
- package/dist/domain/javascriptSemanticTraceSchemas.js +14 -0
- package/dist/domain/javascriptSemanticValues.js +54 -70
- package/dist/domain/processCapture.js +36 -0
- package/dist/domain/processCaptureValidation.js +101 -12
- package/dist/domain/processComparison.js +96 -24
- package/dist/domain/processObservation.js +153 -0
- package/dist/domain/processPairedExperiment.js +128 -0
- package/dist/domain/processReactiveCheckpointDataflow.js +32 -0
- package/dist/domain/processReactiveMatching.js +210 -0
- package/dist/domain/processReactiveRuntime.js +109 -0
- package/dist/domain/processReactiveScenario.js +361 -0
- package/dist/domain/processReactiveScenarioPreflight.js +120 -0
- package/dist/domain/processReactiveTransition.js +159 -0
- package/dist/domain/processScenario.js +12 -0
- package/dist/domain/processTraceComparison.js +43 -0
- package/dist/domain/processTraceDimensionProjection.js +50 -0
- package/dist/domain/processTraceEvaluation.js +312 -0
- package/dist/domain/processTraceSpecification.js +373 -0
- package/dist/domain/reconstructionVerification.js +5 -4
- package/dist/domain/replayMachine.js +332 -0
- package/dist/domain/replayMachineRun.js +216 -0
- package/dist/domain/replayMachineRuntime.js +294 -0
- package/dist/domain/runtimeIdentification.js +210 -0
- package/dist/domain/staticRuntimeCorrelation.js +4 -2
- package/dist/evaluation/CodexAgentEval.js +156 -0
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraClient.js +13 -2
- package/dist/ghidra/GhidraDiagnostics.js +1 -0
- package/dist/ghidra/GhidraLauncher.js +7 -3
- package/dist/ghidra/GhidraProvider.js +8 -1
- package/dist/hopper/BridgeLauncher.js +56 -14
- package/dist/hopper/HopperClient.js +23 -10
- package/dist/hopper/HopperDiagnostics.js +14 -0
- package/dist/hopper/HopperProcessDiagnostic.js +14 -0
- package/dist/hopper/HopperProvider.js +8 -1
- package/dist/hopper/LinuxPrivateDisplayDiagnostic.js +72 -0
- package/dist/hopper/LinuxPrivateDisplayProbe.js +217 -0
- package/dist/identity.js +2 -1
- package/dist/main/transport.js +2 -0
- package/dist/mcpDoctor.js +310 -0
- package/dist/process/ProcessOwnership.js +200 -53
- package/dist/process/ProviderRunLineage.js +21 -0
- package/dist/server/createServer.js +8 -2
- package/dist/server/javascriptApplicationResult.js +106 -0
- package/dist/server/registerApplicationTools/characterization.js +3 -3
- package/dist/server/registerApplicationTools/compareExportShapes.js +37 -0
- package/dist/server/registerApplicationTools/compareVersions.js +12 -6
- package/dist/server/registerApplicationTools/controlledReplay.js +2 -2
- package/dist/server/registerApplicationTools/coverage.js +3 -3
- package/dist/server/registerApplicationTools/helpers.js +37 -25
- package/dist/server/registerApplicationTools/traceFeature.js +9 -5
- package/dist/server/registerApplicationTools/traceSemantics.js +30 -0
- package/dist/server/registerApplicationTools.js +4 -0
- package/dist/server/registerElectronTools.js +19 -5
- package/dist/server/registerEvidenceResources.js +7 -1
- package/dist/server/registerJavaScriptApplicationGraphResource.js +69 -0
- package/dist/server/registerManagedTools.js +18 -1
- package/dist/server/registerProcessComparisonTool.js +17 -7
- package/dist/server/registerReplayMachineTool.js +20 -0
- package/dist/server/registerSessionStatusTool.js +95 -25
- package/dist/server/registerSessionTools.js +12 -7
- package/dist/server/sessionAvailabilityPolicy.js +2 -1
- package/dist/server/toolResult.js +10 -4
- package/dist/serverIdentity.js +19 -0
- package/package.json +62 -29
- package/scripts/hopper-demo-x11.py +459 -61
- package/scripts/prepack.mjs +55 -0
- package/scripts/prepare.mjs +28 -0
- package/scripts/rea.mjs +26 -5
- package/skills/reverse-engineer-anything/SKILL.md +69 -228
- package/skills/reverse-engineer-anything/references/controlled-replay.md +12 -0
- package/skills/reverse-engineer-anything/references/evidence-workflows.md +33 -0
- package/skills/reverse-engineer-anything/references/javascript-applications.md +35 -0
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +36 -0
- package/skills/reverse-engineer-anything/references/runtime-observation.md +24 -0
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import canonicalize from "canonicalize";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { compareCodePoints } from "./javascriptApplicationGraph.js";
|
|
5
|
+
import { JAVASCRIPT_SEMANTIC_RELATION_FAMILIES, JAVASCRIPT_SEMANTIC_RELATION_FAMILY, javaScriptSemanticFingerprintInputSchema, javaScriptSemanticFingerprintSchema, javaScriptSemanticGraphInputSchema, javaScriptSemanticGraphRecordSchema, javaScriptSemanticNodeInputSchema, javaScriptSemanticNodeSchema, javaScriptSemanticRelationInputSchema, javaScriptSemanticRelationSchema, javaScriptSemanticUnknownInputSchema, javaScriptSemanticUnknownSchema, } from "./javascriptSemanticGraphSchemas.js";
|
|
6
|
+
const canonicalJson = (value) => {
|
|
7
|
+
const encoded = canonicalize(value);
|
|
8
|
+
if (encoded === undefined)
|
|
9
|
+
throw new TypeError("JavaScript semantic graph could not canonicalize data");
|
|
10
|
+
return encoded;
|
|
11
|
+
};
|
|
12
|
+
const digestCanonical = (value) => createHash("sha256").update(canonicalJson(value)).digest("hex");
|
|
13
|
+
const uniqueSorted = (values) => [...new Set(values)].sort(compareCodePoints);
|
|
14
|
+
const normalizeEvidence = (evidence) => ({
|
|
15
|
+
...evidence,
|
|
16
|
+
coverage: {
|
|
17
|
+
...evidence.coverage,
|
|
18
|
+
limits: [...evidence.coverage.limits].sort((left, right) => compareCodePoints(canonicalJson(left), canonicalJson(right))),
|
|
19
|
+
},
|
|
20
|
+
limitations: uniqueSorted(evidence.limitations),
|
|
21
|
+
evidence_ids: uniqueSorted(evidence.evidence_ids),
|
|
22
|
+
});
|
|
23
|
+
const nodeId = (node) => `jsrg_node_${digestCanonical({ kind: node.kind, identity: node.identity })}`;
|
|
24
|
+
/** Normalize one semantic entity and derive its artifact-version identifier. */
|
|
25
|
+
export const createJavaScriptSemanticGraphNode = (input) => {
|
|
26
|
+
const parsed = javaScriptSemanticNodeInputSchema.parse(input);
|
|
27
|
+
const semantic = {
|
|
28
|
+
...parsed,
|
|
29
|
+
application_node_ids: uniqueSorted(parsed.application_node_ids),
|
|
30
|
+
evidence: normalizeEvidence(parsed.evidence),
|
|
31
|
+
identifier_strategy: {
|
|
32
|
+
strategy: "semantic-content-sha256",
|
|
33
|
+
stability: "artifact-version",
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
return javaScriptSemanticNodeSchema.parse({
|
|
37
|
+
...semantic,
|
|
38
|
+
node_id: nodeId(semantic),
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
/** Normalize one semantic relationship and derive its exact identifier. */
|
|
42
|
+
export const createJavaScriptSemanticGraphRelation = (input) => {
|
|
43
|
+
const parsed = javaScriptSemanticRelationInputSchema.parse(input);
|
|
44
|
+
const semantic = {
|
|
45
|
+
...parsed,
|
|
46
|
+
evidence: normalizeEvidence(parsed.evidence),
|
|
47
|
+
identifier_strategy: {
|
|
48
|
+
strategy: "semantic-content-sha256",
|
|
49
|
+
stability: "relationship-exact",
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
return javaScriptSemanticRelationSchema.parse({
|
|
53
|
+
...semantic,
|
|
54
|
+
relation_id: `jsrg_relation_${digestCanonical(semantic)}`,
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
/** Normalize one unresolved semantic frontier and derive its identifier. */
|
|
58
|
+
export const createJavaScriptSemanticGraphUnknown = (input) => {
|
|
59
|
+
const parsed = javaScriptSemanticUnknownInputSchema.parse(input);
|
|
60
|
+
const semantic = {
|
|
61
|
+
...parsed,
|
|
62
|
+
relation_kinds: uniqueSorted(parsed.relation_kinds),
|
|
63
|
+
candidate_node_ids: uniqueSorted(parsed.candidate_node_ids),
|
|
64
|
+
evidence: normalizeEvidence(parsed.evidence),
|
|
65
|
+
};
|
|
66
|
+
return javaScriptSemanticUnknownSchema.parse({
|
|
67
|
+
...semantic,
|
|
68
|
+
unknown_id: `jsrg_unknown_${digestCanonical(semantic)}`,
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
/** Normalize one function fingerprint and derive its component commitment. */
|
|
72
|
+
export const createJavaScriptSemanticFingerprint = (input) => {
|
|
73
|
+
const parsed = javaScriptSemanticFingerprintInputSchema.parse(input);
|
|
74
|
+
const semantic = {
|
|
75
|
+
...parsed,
|
|
76
|
+
components: {
|
|
77
|
+
...parsed.components,
|
|
78
|
+
effects: uniqueSorted(parsed.components.effects),
|
|
79
|
+
},
|
|
80
|
+
limitations: uniqueSorted(parsed.limitations),
|
|
81
|
+
evidence: normalizeEvidence(parsed.evidence),
|
|
82
|
+
};
|
|
83
|
+
const fingerprintSha256 = digestCanonical(semantic.components);
|
|
84
|
+
return javaScriptSemanticFingerprintSchema.parse({
|
|
85
|
+
...semantic,
|
|
86
|
+
fingerprint_sha256: fingerprintSha256,
|
|
87
|
+
fingerprint_id: `jsrg_fingerprint_${digestCanonical({
|
|
88
|
+
function_node_id: semantic.function_node_id,
|
|
89
|
+
algorithm: semantic.algorithm,
|
|
90
|
+
fingerprint_sha256: fingerprintSha256,
|
|
91
|
+
})}`,
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
const sortedUniqueIssue = (values, path, label, context) => {
|
|
95
|
+
for (let index = 1; index < values.length; index += 1) {
|
|
96
|
+
if (compareCodePoints(values[index - 1] ?? "", values[index] ?? "") < 0)
|
|
97
|
+
continue;
|
|
98
|
+
context.addIssue({
|
|
99
|
+
code: "custom",
|
|
100
|
+
path: [...path, index],
|
|
101
|
+
message: `${label} must be sorted and unique`,
|
|
102
|
+
});
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
const checkCoverage = (graph, context) => {
|
|
107
|
+
const families = graph.coverage.families.map(({ family }) => family);
|
|
108
|
+
if (canonicalJson(families) !==
|
|
109
|
+
canonicalJson(JAVASCRIPT_SEMANTIC_RELATION_FAMILIES))
|
|
110
|
+
context.addIssue({
|
|
111
|
+
code: "custom",
|
|
112
|
+
path: ["coverage", "families"],
|
|
113
|
+
message: "Coverage must name every semantic relation family once in canonical order",
|
|
114
|
+
});
|
|
115
|
+
if (graph.coverage.status === "complete" &&
|
|
116
|
+
(graph.coverage.truncated ||
|
|
117
|
+
graph.coverage.omitted_nodes !== 0 ||
|
|
118
|
+
graph.coverage.omitted_relations !== 0 ||
|
|
119
|
+
graph.coverage.families.some(({ status }) => status !== "complete")))
|
|
120
|
+
context.addIssue({
|
|
121
|
+
code: "custom",
|
|
122
|
+
path: ["coverage"],
|
|
123
|
+
message: "Complete graph coverage cannot omit or truncate semantic facts",
|
|
124
|
+
});
|
|
125
|
+
if (graph.coverage.truncated && graph.coverage.limits.length === 0)
|
|
126
|
+
context.addIssue({
|
|
127
|
+
code: "custom",
|
|
128
|
+
path: ["coverage", "limits"],
|
|
129
|
+
message: "Truncated graph coverage must identify an effective limit",
|
|
130
|
+
});
|
|
131
|
+
const relationsByFamily = new Map(JAVASCRIPT_SEMANTIC_RELATION_FAMILIES.map((family) => [family, 0]));
|
|
132
|
+
for (const relation of graph.relations) {
|
|
133
|
+
const family = JAVASCRIPT_SEMANTIC_RELATION_FAMILY[relation.relation];
|
|
134
|
+
relationsByFamily.set(family, (relationsByFamily.get(family) ?? 0) + 1);
|
|
135
|
+
}
|
|
136
|
+
const unknownsById = new Map(graph.unknowns.map((unknown) => [unknown.unknown_id, unknown]));
|
|
137
|
+
for (const [index, family] of graph.coverage.families.entries()) {
|
|
138
|
+
if (family.retained_relations !== relationsByFamily.get(family.family))
|
|
139
|
+
context.addIssue({
|
|
140
|
+
code: "custom",
|
|
141
|
+
path: ["coverage", "families", index, "retained_relations"],
|
|
142
|
+
message: "Family retained relation count does not match graph content",
|
|
143
|
+
});
|
|
144
|
+
if (family.unknown_ids.some((identifier) => unknownsById.get(identifier)?.family !== family.family))
|
|
145
|
+
context.addIssue({
|
|
146
|
+
code: "custom",
|
|
147
|
+
path: ["coverage", "families", index, "unknown_ids"],
|
|
148
|
+
message: "Family coverage references an unknown from another family",
|
|
149
|
+
});
|
|
150
|
+
if (family.status === "complete" &&
|
|
151
|
+
(family.omitted_relations !== 0 || family.unknown_ids.length > 0))
|
|
152
|
+
context.addIssue({
|
|
153
|
+
code: "custom",
|
|
154
|
+
path: ["coverage", "families", index],
|
|
155
|
+
message: "Complete family coverage cannot omit or retain unknown facts",
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
const checkCanonicalOrder = (graph, context) => {
|
|
160
|
+
sortedUniqueIssue(graph.root_node_ids, ["root_node_ids"], "Root nodes", context);
|
|
161
|
+
sortedUniqueIssue(graph.nodes.map(({ node_id }) => node_id), ["nodes"], "Nodes", context);
|
|
162
|
+
sortedUniqueIssue(graph.relations.map(({ relation_id }) => relation_id), ["relations"], "Relations", context);
|
|
163
|
+
sortedUniqueIssue(graph.fingerprints.map(({ fingerprint_id }) => fingerprint_id), ["fingerprints"], "Fingerprints", context);
|
|
164
|
+
sortedUniqueIssue(graph.unknowns.map(({ unknown_id }) => unknown_id), ["unknowns"], "Unknown frontiers", context);
|
|
165
|
+
sortedUniqueIssue(graph.limitations, ["limitations"], "Limitations", context);
|
|
166
|
+
};
|
|
167
|
+
const checkNodes = (graph, nodes, context) => {
|
|
168
|
+
for (const [index, node] of graph.nodes.entries()) {
|
|
169
|
+
if (node.node_id !== nodeId(node))
|
|
170
|
+
context.addIssue({
|
|
171
|
+
code: "custom",
|
|
172
|
+
path: ["nodes", index, "node_id"],
|
|
173
|
+
message: "Node identifier is stale",
|
|
174
|
+
});
|
|
175
|
+
if (node.function_node_id !== null &&
|
|
176
|
+
nodes.get(node.function_node_id)?.kind !== "function")
|
|
177
|
+
context.addIssue({
|
|
178
|
+
code: "custom",
|
|
179
|
+
path: ["nodes", index, "function_node_id"],
|
|
180
|
+
message: "Function owner must name a function node",
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
const checkRoots = (graph, nodes, context) => {
|
|
185
|
+
for (const root of graph.root_node_ids)
|
|
186
|
+
if (!nodes.has(root))
|
|
187
|
+
context.addIssue({
|
|
188
|
+
code: "custom",
|
|
189
|
+
path: ["root_node_ids"],
|
|
190
|
+
message: "Root identifier must name a semantic node",
|
|
191
|
+
});
|
|
192
|
+
};
|
|
193
|
+
const checkRelations = (graph, nodes, context) => {
|
|
194
|
+
for (const [index, relation] of graph.relations.entries()) {
|
|
195
|
+
const { relation_id: identifier, ...semantic } = relation;
|
|
196
|
+
if (identifier !== "jsrg_relation_" + digestCanonical(semantic))
|
|
197
|
+
context.addIssue({
|
|
198
|
+
code: "custom",
|
|
199
|
+
path: ["relations", index, "relation_id"],
|
|
200
|
+
message: "Relation identifier is stale",
|
|
201
|
+
});
|
|
202
|
+
if (!nodes.has(relation.source_node_id) ||
|
|
203
|
+
!nodes.has(relation.target_node_id))
|
|
204
|
+
context.addIssue({
|
|
205
|
+
code: "custom",
|
|
206
|
+
path: ["relations", index],
|
|
207
|
+
message: "Relation endpoints must name semantic nodes",
|
|
208
|
+
});
|
|
209
|
+
if (relation.source_node_id === relation.target_node_id)
|
|
210
|
+
context.addIssue({
|
|
211
|
+
code: "custom",
|
|
212
|
+
path: ["relations", index],
|
|
213
|
+
message: "Semantic relations cannot be self-referential",
|
|
214
|
+
});
|
|
215
|
+
if (relation.resolution === "candidate" &&
|
|
216
|
+
relation.evidence.state === "observed")
|
|
217
|
+
context.addIssue({
|
|
218
|
+
code: "custom",
|
|
219
|
+
path: ["relations", index, "evidence", "state"],
|
|
220
|
+
message: "Candidate relations cannot claim observed resolution",
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
const checkUnknowns = (graph, nodes, context) => {
|
|
225
|
+
for (const [index, unknown] of graph.unknowns.entries()) {
|
|
226
|
+
const { unknown_id: identifier, ...semantic } = unknown;
|
|
227
|
+
if (identifier !== "jsrg_unknown_" + digestCanonical(semantic))
|
|
228
|
+
context.addIssue({
|
|
229
|
+
code: "custom",
|
|
230
|
+
path: ["unknowns", index, "unknown_id"],
|
|
231
|
+
message: "Unknown frontier identifier is stale",
|
|
232
|
+
});
|
|
233
|
+
if (unknown.node_id !== null && !nodes.has(unknown.node_id))
|
|
234
|
+
context.addIssue({
|
|
235
|
+
code: "custom",
|
|
236
|
+
path: ["unknowns", index, "node_id"],
|
|
237
|
+
message: "Unknown frontier node is absent",
|
|
238
|
+
});
|
|
239
|
+
if (unknown.candidate_node_ids.some((nodeId) => !nodes.has(nodeId)))
|
|
240
|
+
context.addIssue({
|
|
241
|
+
code: "custom",
|
|
242
|
+
path: ["unknowns", index, "candidate_node_ids"],
|
|
243
|
+
message: "Unknown frontier candidate node is absent",
|
|
244
|
+
});
|
|
245
|
+
if (unknown.relation_kinds.some((kind) => JAVASCRIPT_SEMANTIC_RELATION_FAMILY[kind] !== unknown.family))
|
|
246
|
+
context.addIssue({
|
|
247
|
+
code: "custom",
|
|
248
|
+
path: ["unknowns", index, "relation_kinds"],
|
|
249
|
+
message: "Unknown relation kinds must belong to their declared family",
|
|
250
|
+
});
|
|
251
|
+
if (!["unknown", "unavailable"].includes(unknown.evidence.state))
|
|
252
|
+
context.addIssue({
|
|
253
|
+
code: "custom",
|
|
254
|
+
path: ["unknowns", index, "evidence", "state"],
|
|
255
|
+
message: "Unknown frontiers require unknown or unavailable evidence",
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
const checkUnknownReferences = (graph, context) => {
|
|
260
|
+
const unknownIds = new Set(graph.unknowns.map(({ unknown_id }) => unknown_id));
|
|
261
|
+
for (const [index, family] of graph.coverage.families.entries())
|
|
262
|
+
if (family.unknown_ids.some((identifier) => !unknownIds.has(identifier)))
|
|
263
|
+
context.addIssue({
|
|
264
|
+
code: "custom",
|
|
265
|
+
path: ["coverage", "families", index, "unknown_ids"],
|
|
266
|
+
message: "Family coverage references an absent unknown frontier",
|
|
267
|
+
});
|
|
268
|
+
};
|
|
269
|
+
const checkFingerprints = (graph, nodes, context) => {
|
|
270
|
+
for (const [index, fingerprint] of graph.fingerprints.entries()) {
|
|
271
|
+
if (nodes.get(fingerprint.function_node_id)?.kind !== "function")
|
|
272
|
+
context.addIssue({
|
|
273
|
+
code: "custom",
|
|
274
|
+
path: ["fingerprints", index, "function_node_id"],
|
|
275
|
+
message: "Fingerprint must name a function node",
|
|
276
|
+
});
|
|
277
|
+
if (fingerprint.fingerprint_sha256 !== digestCanonical(fingerprint.components))
|
|
278
|
+
context.addIssue({
|
|
279
|
+
code: "custom",
|
|
280
|
+
path: ["fingerprints", index, "fingerprint_sha256"],
|
|
281
|
+
message: "Fingerprint component commitment is stale",
|
|
282
|
+
});
|
|
283
|
+
const expectedIdentifier = "jsrg_fingerprint_" +
|
|
284
|
+
digestCanonical({
|
|
285
|
+
function_node_id: fingerprint.function_node_id,
|
|
286
|
+
algorithm: fingerprint.algorithm,
|
|
287
|
+
fingerprint_sha256: fingerprint.fingerprint_sha256,
|
|
288
|
+
});
|
|
289
|
+
if (fingerprint.fingerprint_id !== expectedIdentifier)
|
|
290
|
+
context.addIssue({
|
|
291
|
+
code: "custom",
|
|
292
|
+
path: ["fingerprints", index, "fingerprint_id"],
|
|
293
|
+
message: "Fingerprint identifier is stale",
|
|
294
|
+
});
|
|
295
|
+
if (fingerprint.status !== "complete" &&
|
|
296
|
+
fingerprint.limitations.length === 0)
|
|
297
|
+
context.addIssue({
|
|
298
|
+
code: "custom",
|
|
299
|
+
path: ["fingerprints", index, "limitations"],
|
|
300
|
+
message: "Incomplete fingerprints require a limitation",
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
const checkGraph = (graph, context) => {
|
|
305
|
+
checkCanonicalOrder(graph, context);
|
|
306
|
+
const nodes = new Map(graph.nodes.map((node) => [node.node_id, node]));
|
|
307
|
+
checkNodes(graph, nodes, context);
|
|
308
|
+
checkRoots(graph, nodes, context);
|
|
309
|
+
checkRelations(graph, nodes, context);
|
|
310
|
+
checkUnknowns(graph, nodes, context);
|
|
311
|
+
checkUnknownReferences(graph, context);
|
|
312
|
+
checkFingerprints(graph, nodes, context);
|
|
313
|
+
checkCoverage(graph, context);
|
|
314
|
+
if (graph.coverage.status !== "complete" && graph.limitations.length === 0)
|
|
315
|
+
context.addIssue({
|
|
316
|
+
code: "custom",
|
|
317
|
+
path: ["limitations"],
|
|
318
|
+
message: "Non-complete graph coverage requires a limitation",
|
|
319
|
+
});
|
|
320
|
+
const { graph_id: identifier, ...semantic } = graph;
|
|
321
|
+
if (identifier !== "jsrg_" + digestCanonical(semantic))
|
|
322
|
+
context.addIssue({
|
|
323
|
+
code: "custom",
|
|
324
|
+
path: ["graph_id"],
|
|
325
|
+
message: "Graph identifier is stale",
|
|
326
|
+
});
|
|
327
|
+
};
|
|
328
|
+
/** Strict semantic graph schema with verified canonical commitments. */
|
|
329
|
+
export const javaScriptSemanticGraphSchema = javaScriptSemanticGraphRecordSchema.superRefine(checkGraph);
|
|
330
|
+
/** Normalize a complete companion graph and derive its graph ID. */
|
|
331
|
+
export const createJavaScriptSemanticGraph = (input) => {
|
|
332
|
+
const parsed = javaScriptSemanticGraphInputSchema.parse(input);
|
|
333
|
+
const semantic = {
|
|
334
|
+
...parsed,
|
|
335
|
+
root_node_ids: uniqueSorted(parsed.root_node_ids),
|
|
336
|
+
nodes: [...parsed.nodes].sort((left, right) => compareCodePoints(left.node_id, right.node_id)),
|
|
337
|
+
relations: [...parsed.relations].sort((left, right) => compareCodePoints(left.relation_id, right.relation_id)),
|
|
338
|
+
fingerprints: [...parsed.fingerprints].sort((left, right) => compareCodePoints(left.fingerprint_id, right.fingerprint_id)),
|
|
339
|
+
unknowns: [...parsed.unknowns].sort((left, right) => compareCodePoints(left.unknown_id, right.unknown_id)),
|
|
340
|
+
coverage: {
|
|
341
|
+
...parsed.coverage,
|
|
342
|
+
limits: [...parsed.coverage.limits].sort((left, right) => compareCodePoints(canonicalJson(left), canonicalJson(right))),
|
|
343
|
+
families: [...parsed.coverage.families]
|
|
344
|
+
.map((family) => ({
|
|
345
|
+
...family,
|
|
346
|
+
unknown_ids: uniqueSorted(family.unknown_ids),
|
|
347
|
+
}))
|
|
348
|
+
.sort((left, right) => compareCodePoints(left.family, right.family)),
|
|
349
|
+
},
|
|
350
|
+
limitations: uniqueSorted(parsed.limitations),
|
|
351
|
+
};
|
|
352
|
+
return javaScriptSemanticGraphSchema.parse({
|
|
353
|
+
...semantic,
|
|
354
|
+
graph_id: `jsrg_${digestCanonical(semantic)}`,
|
|
355
|
+
});
|
|
356
|
+
};
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { applicationGraphEvidenceSchema } from "./javascriptApplicationEvidenceSchemas.js";
|
|
3
|
+
import { isJsonWithinLimits } from "./jsonLimits.js";
|
|
4
|
+
import { jsonValueSchema } from "./jsonValue.js";
|
|
5
|
+
const digestSchema = z.string().regex(/^[a-f0-9]{64}$/u);
|
|
6
|
+
const boundedTextSchema = z.string().min(1).max(4_096);
|
|
7
|
+
const semanticNodeIdSchema = z.string().regex(/^jsrg_node_[a-f0-9]{64}$/u);
|
|
8
|
+
const semanticRelationIdSchema = z
|
|
9
|
+
.string()
|
|
10
|
+
.regex(/^jsrg_relation_[a-f0-9]{64}$/u);
|
|
11
|
+
const semanticUnknownIdSchema = z
|
|
12
|
+
.string()
|
|
13
|
+
.regex(/^jsrg_unknown_[a-f0-9]{64}$/u);
|
|
14
|
+
/** Semantic entity kinds admitted by JavaScript Semantic Relation Graph v1. */
|
|
15
|
+
export const JAVASCRIPT_SEMANTIC_NODE_KINDS = [
|
|
16
|
+
"module",
|
|
17
|
+
"function",
|
|
18
|
+
"parameter",
|
|
19
|
+
"binding",
|
|
20
|
+
"expression",
|
|
21
|
+
"literal",
|
|
22
|
+
"property-slot",
|
|
23
|
+
"call-site",
|
|
24
|
+
"return-site",
|
|
25
|
+
"closure-capture",
|
|
26
|
+
"promise",
|
|
27
|
+
"task",
|
|
28
|
+
"event",
|
|
29
|
+
"listener",
|
|
30
|
+
"timer",
|
|
31
|
+
"child-process",
|
|
32
|
+
"stdio",
|
|
33
|
+
"signal",
|
|
34
|
+
"config-source",
|
|
35
|
+
"request",
|
|
36
|
+
"response",
|
|
37
|
+
"boundary",
|
|
38
|
+
"resource",
|
|
39
|
+
"unknown-frontier",
|
|
40
|
+
];
|
|
41
|
+
/** Required semantic-analysis coverage families. */
|
|
42
|
+
export const JAVASCRIPT_SEMANTIC_RELATION_FAMILIES = [
|
|
43
|
+
"boundary",
|
|
44
|
+
"call-flow",
|
|
45
|
+
"child-process",
|
|
46
|
+
"closure",
|
|
47
|
+
"configuration",
|
|
48
|
+
"data-flow",
|
|
49
|
+
"event",
|
|
50
|
+
"object-flow",
|
|
51
|
+
"promise-ownership",
|
|
52
|
+
"request",
|
|
53
|
+
"resource-lifecycle",
|
|
54
|
+
"timer",
|
|
55
|
+
];
|
|
56
|
+
/** Directed semantic relations admitted by graph v1. */
|
|
57
|
+
export const JAVASCRIPT_SEMANTIC_RELATIONS = [
|
|
58
|
+
"acquires",
|
|
59
|
+
"aggregates",
|
|
60
|
+
"aliases",
|
|
61
|
+
"argument-to-parameter",
|
|
62
|
+
"awaits",
|
|
63
|
+
"calls",
|
|
64
|
+
"cancels-timer",
|
|
65
|
+
"captures",
|
|
66
|
+
"chains",
|
|
67
|
+
"coerces",
|
|
68
|
+
"connects-stdio",
|
|
69
|
+
"consumed-by",
|
|
70
|
+
"constructs-request",
|
|
71
|
+
"creates-promise",
|
|
72
|
+
"defaults",
|
|
73
|
+
"defines",
|
|
74
|
+
"destructures",
|
|
75
|
+
"detaches-task",
|
|
76
|
+
"dispatches-candidate",
|
|
77
|
+
"forwards-signal",
|
|
78
|
+
"listens-error",
|
|
79
|
+
"listens-exit",
|
|
80
|
+
"owns",
|
|
81
|
+
"overrides",
|
|
82
|
+
"parses",
|
|
83
|
+
"reads",
|
|
84
|
+
"reads-argv",
|
|
85
|
+
"reads-config",
|
|
86
|
+
"reads-environment",
|
|
87
|
+
"reads-property",
|
|
88
|
+
"registers-listener",
|
|
89
|
+
"releases",
|
|
90
|
+
"removes-listener",
|
|
91
|
+
"returns-task",
|
|
92
|
+
"returns-to-call",
|
|
93
|
+
"schedules-timer",
|
|
94
|
+
"spawns",
|
|
95
|
+
"spreads",
|
|
96
|
+
"supplies-argv",
|
|
97
|
+
"supplies-env",
|
|
98
|
+
"supplies-request-field",
|
|
99
|
+
"validates",
|
|
100
|
+
"writes",
|
|
101
|
+
"writes-property",
|
|
102
|
+
];
|
|
103
|
+
/** Map each semantic relation to its coverage family. */
|
|
104
|
+
export const JAVASCRIPT_SEMANTIC_RELATION_FAMILY = {
|
|
105
|
+
acquires: "resource-lifecycle",
|
|
106
|
+
aggregates: "promise-ownership",
|
|
107
|
+
aliases: "data-flow",
|
|
108
|
+
"argument-to-parameter": "call-flow",
|
|
109
|
+
awaits: "promise-ownership",
|
|
110
|
+
calls: "call-flow",
|
|
111
|
+
"cancels-timer": "timer",
|
|
112
|
+
captures: "closure",
|
|
113
|
+
chains: "promise-ownership",
|
|
114
|
+
coerces: "boundary",
|
|
115
|
+
"connects-stdio": "child-process",
|
|
116
|
+
"consumed-by": "request",
|
|
117
|
+
"constructs-request": "request",
|
|
118
|
+
"creates-promise": "promise-ownership",
|
|
119
|
+
defaults: "configuration",
|
|
120
|
+
defines: "data-flow",
|
|
121
|
+
destructures: "object-flow",
|
|
122
|
+
"detaches-task": "promise-ownership",
|
|
123
|
+
"dispatches-candidate": "event",
|
|
124
|
+
"forwards-signal": "child-process",
|
|
125
|
+
"listens-error": "child-process",
|
|
126
|
+
"listens-exit": "child-process",
|
|
127
|
+
owns: "promise-ownership",
|
|
128
|
+
overrides: "configuration",
|
|
129
|
+
parses: "boundary",
|
|
130
|
+
reads: "data-flow",
|
|
131
|
+
"reads-argv": "configuration",
|
|
132
|
+
"reads-config": "configuration",
|
|
133
|
+
"reads-environment": "configuration",
|
|
134
|
+
"reads-property": "object-flow",
|
|
135
|
+
"registers-listener": "event",
|
|
136
|
+
releases: "resource-lifecycle",
|
|
137
|
+
"removes-listener": "event",
|
|
138
|
+
"returns-task": "promise-ownership",
|
|
139
|
+
"returns-to-call": "call-flow",
|
|
140
|
+
"schedules-timer": "timer",
|
|
141
|
+
spawns: "child-process",
|
|
142
|
+
spreads: "object-flow",
|
|
143
|
+
"supplies-argv": "child-process",
|
|
144
|
+
"supplies-env": "child-process",
|
|
145
|
+
"supplies-request-field": "request",
|
|
146
|
+
validates: "boundary",
|
|
147
|
+
writes: "data-flow",
|
|
148
|
+
"writes-property": "object-flow",
|
|
149
|
+
};
|
|
150
|
+
const relativePathSchema = z
|
|
151
|
+
.string()
|
|
152
|
+
.min(1)
|
|
153
|
+
.max(4_096)
|
|
154
|
+
.refine((path) => !path.startsWith("/") &&
|
|
155
|
+
!path.includes("\\") &&
|
|
156
|
+
path.split("/").every((part) => !["", ".", ".."].includes(part)), "Expected a normalized relative POSIX path without traversal");
|
|
157
|
+
const sourcePointSchema = z.strictObject({
|
|
158
|
+
line: z.number().int().min(1),
|
|
159
|
+
column: z.number().int().min(0),
|
|
160
|
+
});
|
|
161
|
+
const sourceRangeSchema = z
|
|
162
|
+
.strictObject({ start: sourcePointSchema, end: sourcePointSchema })
|
|
163
|
+
.superRefine((range, context) => {
|
|
164
|
+
if (range.end.line < range.start.line ||
|
|
165
|
+
(range.end.line === range.start.line &&
|
|
166
|
+
range.end.column < range.start.column))
|
|
167
|
+
context.addIssue({
|
|
168
|
+
code: "custom",
|
|
169
|
+
path: ["end"],
|
|
170
|
+
message: "Source range end must not precede its start",
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
const semanticPropertiesSchema = z
|
|
174
|
+
.record(z.string().min(1).max(128), jsonValueSchema)
|
|
175
|
+
.superRefine((properties, context) => {
|
|
176
|
+
if (Object.keys(properties).length > 64)
|
|
177
|
+
context.addIssue({
|
|
178
|
+
code: "custom",
|
|
179
|
+
message: "Semantic properties exceed 64 keys",
|
|
180
|
+
});
|
|
181
|
+
if (!isJsonWithinLimits(properties, {
|
|
182
|
+
maxDepth: 6,
|
|
183
|
+
maxNodes: 512,
|
|
184
|
+
maxStringLength: 4_096,
|
|
185
|
+
}))
|
|
186
|
+
context.addIssue({
|
|
187
|
+
code: "custom",
|
|
188
|
+
message: "Semantic properties exceed structural limits",
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
const semanticNodeIdentitySchema = z.strictObject({
|
|
192
|
+
artifact_sha256: digestSchema,
|
|
193
|
+
module_path: relativePathSchema,
|
|
194
|
+
source_range: sourceRangeSchema.nullable(),
|
|
195
|
+
role_key: z.string().min(1).max(1_024),
|
|
196
|
+
});
|
|
197
|
+
/** One semantic entity before its canonical identifier is derived. */
|
|
198
|
+
export const javaScriptSemanticNodeInputSchema = z.strictObject({
|
|
199
|
+
kind: z.enum(JAVASCRIPT_SEMANTIC_NODE_KINDS),
|
|
200
|
+
identity: semanticNodeIdentitySchema,
|
|
201
|
+
function_node_id: semanticNodeIdSchema.nullable(),
|
|
202
|
+
application_node_ids: z
|
|
203
|
+
.array(z.string().regex(/^jag_node_[a-f0-9]{64}$/u))
|
|
204
|
+
.max(64),
|
|
205
|
+
label: z.string().min(1).max(1_024).nullable(),
|
|
206
|
+
properties: semanticPropertiesSchema,
|
|
207
|
+
evidence: applicationGraphEvidenceSchema,
|
|
208
|
+
});
|
|
209
|
+
/** One exact, artifact-version semantic entity. */
|
|
210
|
+
export const javaScriptSemanticNodeSchema = javaScriptSemanticNodeInputSchema.extend({
|
|
211
|
+
node_id: semanticNodeIdSchema,
|
|
212
|
+
identifier_strategy: z.strictObject({
|
|
213
|
+
strategy: z.literal("semantic-content-sha256"),
|
|
214
|
+
stability: z.literal("artifact-version"),
|
|
215
|
+
}),
|
|
216
|
+
});
|
|
217
|
+
/** One directed semantic relationship before its ID is derived. */
|
|
218
|
+
export const javaScriptSemanticRelationInputSchema = z.strictObject({
|
|
219
|
+
source_node_id: semanticNodeIdSchema,
|
|
220
|
+
target_node_id: semanticNodeIdSchema,
|
|
221
|
+
relation: z.enum(JAVASCRIPT_SEMANTIC_RELATIONS),
|
|
222
|
+
resolution: z.enum(["resolved", "candidate"]),
|
|
223
|
+
properties: semanticPropertiesSchema,
|
|
224
|
+
evidence: applicationGraphEvidenceSchema,
|
|
225
|
+
});
|
|
226
|
+
/** One canonical directed semantic relationship. */
|
|
227
|
+
export const javaScriptSemanticRelationSchema = javaScriptSemanticRelationInputSchema.extend({
|
|
228
|
+
relation_id: semanticRelationIdSchema,
|
|
229
|
+
identifier_strategy: z.strictObject({
|
|
230
|
+
strategy: z.literal("semantic-content-sha256"),
|
|
231
|
+
stability: z.literal("relationship-exact"),
|
|
232
|
+
}),
|
|
233
|
+
});
|
|
234
|
+
/** Reasons semantic analysis can leave an explicit frontier. */
|
|
235
|
+
export const JAVASCRIPT_SEMANTIC_UNKNOWN_REASONS = [
|
|
236
|
+
"ambiguous-target",
|
|
237
|
+
"bound-reached",
|
|
238
|
+
"dynamic-call",
|
|
239
|
+
"dynamic-property",
|
|
240
|
+
"eval-or-generated-code",
|
|
241
|
+
"incomplete-module",
|
|
242
|
+
"missing-source",
|
|
243
|
+
"unsupported-syntax",
|
|
244
|
+
];
|
|
245
|
+
/** One unresolved semantic frontier before its ID is derived. */
|
|
246
|
+
export const javaScriptSemanticUnknownInputSchema = z.strictObject({
|
|
247
|
+
node_id: semanticNodeIdSchema.nullable(),
|
|
248
|
+
family: z.enum(JAVASCRIPT_SEMANTIC_RELATION_FAMILIES),
|
|
249
|
+
relation_kinds: z.array(z.enum(JAVASCRIPT_SEMANTIC_RELATIONS)).min(1).max(45),
|
|
250
|
+
reason: z.enum(JAVASCRIPT_SEMANTIC_UNKNOWN_REASONS),
|
|
251
|
+
detail: boundedTextSchema,
|
|
252
|
+
candidate_node_ids: z.array(semanticNodeIdSchema).max(1_000),
|
|
253
|
+
evidence: applicationGraphEvidenceSchema,
|
|
254
|
+
});
|
|
255
|
+
/** One canonical unresolved semantic frontier. */
|
|
256
|
+
export const javaScriptSemanticUnknownSchema = javaScriptSemanticUnknownInputSchema.extend({
|
|
257
|
+
unknown_id: semanticUnknownIdSchema,
|
|
258
|
+
});
|
|
259
|
+
const fingerprintComponentsSchema = z.strictObject({
|
|
260
|
+
parameter_arity: z.number().int().min(0).max(10_000),
|
|
261
|
+
normalized_ast_sha256: digestSchema,
|
|
262
|
+
control_flow_sha256: digestSchema,
|
|
263
|
+
relation_shape_sha256: digestSchema,
|
|
264
|
+
literal_set_sha256: digestSchema,
|
|
265
|
+
effects: z
|
|
266
|
+
.array(z.enum([
|
|
267
|
+
"async",
|
|
268
|
+
"child-process",
|
|
269
|
+
"event",
|
|
270
|
+
"network",
|
|
271
|
+
"promise",
|
|
272
|
+
"resource",
|
|
273
|
+
"timer",
|
|
274
|
+
]))
|
|
275
|
+
.max(7),
|
|
276
|
+
});
|
|
277
|
+
/** One bounded rename-resistant function fingerprint. */
|
|
278
|
+
export const javaScriptSemanticFingerprintInputSchema = z.strictObject({
|
|
279
|
+
function_node_id: semanticNodeIdSchema,
|
|
280
|
+
algorithm: z.literal("rea.javascript-semantic-function/v1"),
|
|
281
|
+
status: z.enum(["complete", "partial", "unavailable"]),
|
|
282
|
+
components: fingerprintComponentsSchema,
|
|
283
|
+
limitations: z.array(boundedTextSchema).max(100),
|
|
284
|
+
evidence: applicationGraphEvidenceSchema,
|
|
285
|
+
});
|
|
286
|
+
/** One canonical function fingerprint record. */
|
|
287
|
+
export const javaScriptSemanticFingerprintSchema = javaScriptSemanticFingerprintInputSchema.extend({
|
|
288
|
+
fingerprint_id: z.string().regex(/^jsrg_fingerprint_[a-f0-9]{64}$/u),
|
|
289
|
+
fingerprint_sha256: digestSchema,
|
|
290
|
+
});
|
|
291
|
+
const familyCoverageSchema = z.strictObject({
|
|
292
|
+
family: z.enum(JAVASCRIPT_SEMANTIC_RELATION_FAMILIES),
|
|
293
|
+
status: z.enum(["complete", "partial", "unknown", "unsupported"]),
|
|
294
|
+
retained_relations: z.number().int().min(0),
|
|
295
|
+
omitted_relations: z.number().int().min(0).nullable(),
|
|
296
|
+
unknown_ids: z.array(semanticUnknownIdSchema).max(100_000),
|
|
297
|
+
});
|
|
298
|
+
const graphCoverageSchema = z.strictObject({
|
|
299
|
+
status: z.enum(["complete", "partial", "unknown", "unavailable"]),
|
|
300
|
+
truncated: z.boolean(),
|
|
301
|
+
omitted_nodes: z.number().int().min(0).nullable(),
|
|
302
|
+
omitted_relations: z.number().int().min(0).nullable(),
|
|
303
|
+
limits: z
|
|
304
|
+
.array(z.strictObject({
|
|
305
|
+
name: z.string().min(1).max(128),
|
|
306
|
+
value: z.number().int().min(0),
|
|
307
|
+
unit: z.enum(["items", "bytes", "milliseconds", "depth", "other"]),
|
|
308
|
+
}))
|
|
309
|
+
.max(32),
|
|
310
|
+
families: z.array(familyCoverageSchema).length(12),
|
|
311
|
+
});
|
|
312
|
+
/** Graph content before its top-level commitment is derived. */
|
|
313
|
+
export const javaScriptSemanticGraphInputSchema = z.strictObject({
|
|
314
|
+
schema: z.literal("JavaScriptSemanticRelationGraph"),
|
|
315
|
+
schema_version: z.literal(1),
|
|
316
|
+
root_artifact_sha256: digestSchema,
|
|
317
|
+
application_graph_id: z.string().regex(/^jag_[a-f0-9]{64}$/u),
|
|
318
|
+
root_node_ids: z.array(semanticNodeIdSchema).min(1).max(10_000),
|
|
319
|
+
nodes: z.array(javaScriptSemanticNodeSchema).min(1).max(100_000),
|
|
320
|
+
relations: z.array(javaScriptSemanticRelationSchema).max(200_000),
|
|
321
|
+
fingerprints: z.array(javaScriptSemanticFingerprintSchema).max(20_000),
|
|
322
|
+
unknowns: z.array(javaScriptSemanticUnknownSchema).max(100_000),
|
|
323
|
+
coverage: graphCoverageSchema,
|
|
324
|
+
limitations: z.array(boundedTextSchema).max(1_000),
|
|
325
|
+
});
|
|
326
|
+
/** Stored JavaScript Semantic Relation Graph v1. */
|
|
327
|
+
export const javaScriptSemanticGraphRecordSchema = javaScriptSemanticGraphInputSchema.extend({
|
|
328
|
+
graph_id: z.string().regex(/^jsrg_[a-f0-9]{64}$/u),
|
|
329
|
+
});
|