rea-agents 2.2.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.
Files changed (165) hide show
  1. package/README.md +56 -9
  2. package/dist/application/ApplicationWorkflowEvidenceResolver.js +162 -0
  3. package/dist/application/BinarySession.js +9 -2
  4. package/dist/application/BinarySessionStatus.js +39 -1
  5. package/dist/application/CapabilityInventory.js +15 -0
  6. package/dist/application/CommandShimReplay.js +6 -3
  7. package/dist/application/CompositeProvider.js +5 -2
  8. package/dist/application/DirectAnalysis.js +1 -20
  9. package/dist/application/DirectAnalysisStatus.js +83 -0
  10. package/dist/application/Doctor.js +34 -25
  11. package/dist/application/DoctorDiagnostics.js +1 -4
  12. package/dist/application/DoctorProjection.js +43 -0
  13. package/dist/application/DoctorScope.js +102 -0
  14. package/dist/application/EvidenceReferenceResolver.js +26 -0
  15. package/dist/application/JavaScriptApplicationEvidence.js +1 -1
  16. package/dist/application/JavaScriptApplicationEvidenceGraph.js +10 -1
  17. package/dist/application/JavaScriptApplicationService.js +3 -2
  18. package/dist/application/JavaScriptApplicationWorkflowEvidence.js +26 -0
  19. package/dist/application/JavaScriptApplicationWorkflowService.js +49 -1
  20. package/dist/application/JavaScriptArtifactReconstruction.js +7 -0
  21. package/dist/application/JavaScriptModuleRelationships.js +25 -1
  22. package/dist/application/JavaScriptReturnShapeProjection.js +111 -0
  23. package/dist/application/JavaScriptSemanticGraphBuilder.js +294 -0
  24. package/dist/application/JavaScriptSemanticGraphConstruction.js +144 -0
  25. package/dist/application/JavaScriptSemanticGraphEvidence.js +86 -0
  26. package/dist/application/JavaScriptSemanticGraphFlowProjection.js +72 -0
  27. package/dist/application/JavaScriptSemanticGraphProjection.js +33 -0
  28. package/dist/application/JavaScriptSemanticTraceService.js +45 -0
  29. package/dist/application/LoopbackReplay.js +277 -133
  30. package/dist/application/LoopbackReplayRecorder.js +101 -0
  31. package/dist/application/PermissionAuthority.js +7 -3
  32. package/dist/application/ProcessCaptureJournal.js +95 -0
  33. package/dist/application/ProcessCaptureLifecycle.js +24 -13
  34. package/dist/application/ProcessCheckpoints.js +30 -4
  35. package/dist/application/ProcessCli.js +26 -4
  36. package/dist/application/ProcessHarness.js +20 -50
  37. package/dist/application/ProcessNormalization.js +3 -2
  38. package/dist/application/ProcessReactiveCoordinator.js +218 -0
  39. package/dist/application/ProcessReactiveEffects.js +133 -0
  40. package/dist/application/ProcessReactiveObservations.js +20 -0
  41. package/dist/application/ProcessSampling.js +2 -0
  42. package/dist/application/SessionProviderRouter.js +7 -6
  43. package/dist/application/Setup.js +11 -10
  44. package/dist/application/SetupPlan.js +1 -1
  45. package/dist/application/SetupRegistrationEnvironment.js +12 -0
  46. package/dist/application/TerminalRenderer.js +3 -1
  47. package/dist/browser/CdpEndpoint.js +37 -4
  48. package/dist/catalogIdentity.js +16 -7
  49. package/dist/cli/coreAnalysisCommands.js +34 -2
  50. package/dist/cli/javascriptApplicationAnalysis.js +19 -0
  51. package/dist/cli/setupCommands.js +81 -32
  52. package/dist/cli/utilityCommands.js +10 -2
  53. package/dist/cliApplicationCommands.js +79 -16
  54. package/dist/cliCommandNames.js +3 -0
  55. package/dist/cliElectronCommands.js +23 -33
  56. package/dist/cliObservationOptions.js +1 -1
  57. package/dist/cliOutput.js +56 -0
  58. package/dist/cliProcessCommands.js +32 -1
  59. package/dist/cliSetup.js +30 -21
  60. package/dist/contracts/applicationToolContracts.js +54 -7
  61. package/dist/contracts/applicationWorkflowInputContracts.js +119 -0
  62. package/dist/contracts/electronToolContracts.js +53 -32
  63. package/dist/contracts/javascriptApplicationWorkflowExamples.js +32 -9
  64. package/dist/contracts/processCaptureExample.js +1 -0
  65. package/dist/contracts/replayMachineExample.js +37 -0
  66. package/dist/contracts/toolContractExamples.js +2 -0
  67. package/dist/contracts/toolContracts.js +5 -1
  68. package/dist/contracts/toolEffects.js +3 -0
  69. package/dist/contracts/toolOutputSchemaGroups.js +2 -0
  70. package/dist/contracts/toolOutputSchemaPrimitives.js +40 -0
  71. package/dist/doctorRuntime.js +41 -0
  72. package/dist/domain/analysisErrorPresentation.js +5 -3
  73. package/dist/domain/analysisErrorProjection.js +7 -1
  74. package/dist/domain/changedBehavior.js +5 -4
  75. package/dist/domain/completionLedgerGeneration.js +190 -0
  76. package/dist/domain/errors.js +4 -2
  77. package/dist/domain/evidenceCompletionLedger.js +113 -0
  78. package/dist/domain/hopperStartupFailure.js +9 -0
  79. package/dist/domain/javascriptApplicationAnalysis.js +44 -2
  80. package/dist/domain/javascriptExportShapeComparison.js +145 -0
  81. package/dist/domain/javascriptExportShapeComparisonIdentity.js +11 -0
  82. package/dist/domain/javascriptExportShapeComparisonSchemas.js +277 -0
  83. package/dist/domain/javascriptExportShapeSelection.js +132 -0
  84. package/dist/domain/javascriptExportShapeVariants.js +272 -0
  85. package/dist/domain/javascriptRuntimeReconciliationParsing.js +2 -2
  86. package/dist/domain/javascriptSemanticAnalysis.js +17 -36
  87. package/dist/domain/javascriptSemanticCallResolution.js +129 -0
  88. package/dist/domain/javascriptSemanticCalls.js +269 -0
  89. package/dist/domain/javascriptSemanticGraph.js +356 -0
  90. package/dist/domain/javascriptSemanticGraphSchemas.js +329 -0
  91. package/dist/domain/javascriptSemanticGraphSerialization.js +23 -0
  92. package/dist/domain/javascriptSemanticIr.js +14 -1
  93. package/dist/domain/javascriptSemanticPrimitives.js +36 -0
  94. package/dist/domain/javascriptSemanticProjection.js +36 -4
  95. package/dist/domain/javascriptSemanticProvenance.js +29 -0
  96. package/dist/domain/javascriptSemanticQuery.js +294 -0
  97. package/dist/domain/javascriptSemanticQueryAssessment.js +74 -0
  98. package/dist/domain/javascriptSemanticQueryIdentity.js +86 -0
  99. package/dist/domain/javascriptSemanticQueryRelations.js +15 -0
  100. package/dist/domain/javascriptSemanticQuerySchemas.js +188 -0
  101. package/dist/domain/javascriptSemanticReturns.js +187 -0
  102. package/dist/domain/javascriptSemanticState.js +32 -0
  103. package/dist/domain/javascriptSemanticTraceSchemas.js +14 -0
  104. package/dist/domain/javascriptSemanticValues.js +54 -70
  105. package/dist/domain/processCapture.js +36 -0
  106. package/dist/domain/processCaptureValidation.js +101 -12
  107. package/dist/domain/processComparison.js +78 -25
  108. package/dist/domain/processObservation.js +153 -0
  109. package/dist/domain/processReactiveCheckpointDataflow.js +32 -0
  110. package/dist/domain/processReactiveMatching.js +210 -0
  111. package/dist/domain/processReactiveRuntime.js +109 -0
  112. package/dist/domain/processReactiveScenario.js +361 -0
  113. package/dist/domain/processReactiveScenarioPreflight.js +120 -0
  114. package/dist/domain/processReactiveTransition.js +159 -0
  115. package/dist/domain/processScenario.js +12 -0
  116. package/dist/domain/processTraceComparison.js +43 -0
  117. package/dist/domain/processTraceDimensionProjection.js +50 -0
  118. package/dist/domain/processTraceEvaluation.js +312 -0
  119. package/dist/domain/processTraceSpecification.js +373 -0
  120. package/dist/domain/reconstructionVerification.js +5 -4
  121. package/dist/domain/replayMachine.js +18 -2
  122. package/dist/domain/replayMachineRun.js +216 -0
  123. package/dist/domain/replayMachineRuntime.js +88 -9
  124. package/dist/domain/staticRuntimeCorrelation.js +4 -2
  125. package/dist/evaluation/CodexAgentEval.js +24 -0
  126. package/dist/generatedPackageMetadata.js +1 -1
  127. package/dist/ghidra/GhidraClient.js +13 -2
  128. package/dist/ghidra/GhidraDiagnostics.js +1 -0
  129. package/dist/ghidra/GhidraLauncher.js +7 -3
  130. package/dist/ghidra/GhidraProvider.js +8 -1
  131. package/dist/hopper/BridgeLauncher.js +56 -14
  132. package/dist/hopper/HopperClient.js +23 -10
  133. package/dist/hopper/HopperDiagnostics.js +14 -0
  134. package/dist/hopper/HopperProcessDiagnostic.js +14 -0
  135. package/dist/hopper/HopperProvider.js +8 -1
  136. package/dist/hopper/LinuxPrivateDisplayDiagnostic.js +72 -0
  137. package/dist/hopper/LinuxPrivateDisplayProbe.js +217 -0
  138. package/dist/main/transport.js +2 -0
  139. package/dist/mcpDoctor.js +310 -0
  140. package/dist/process/ProcessOwnership.js +200 -53
  141. package/dist/process/ProviderRunLineage.js +21 -0
  142. package/dist/server/createServer.js +4 -1
  143. package/dist/server/javascriptApplicationResult.js +22 -1
  144. package/dist/server/registerApplicationTools/characterization.js +3 -3
  145. package/dist/server/registerApplicationTools/compareExportShapes.js +37 -0
  146. package/dist/server/registerApplicationTools/compareVersions.js +12 -6
  147. package/dist/server/registerApplicationTools/controlledReplay.js +2 -2
  148. package/dist/server/registerApplicationTools/coverage.js +3 -3
  149. package/dist/server/registerApplicationTools/helpers.js +37 -25
  150. package/dist/server/registerApplicationTools/traceFeature.js +9 -5
  151. package/dist/server/registerApplicationTools/traceSemantics.js +30 -0
  152. package/dist/server/registerApplicationTools.js +4 -0
  153. package/dist/server/registerEvidenceResources.js +5 -1
  154. package/dist/server/registerProcessComparisonTool.js +17 -7
  155. package/dist/server/registerReplayMachineTool.js +20 -0
  156. package/dist/server/registerSessionTools.js +12 -7
  157. package/dist/server/sessionAvailabilityPolicy.js +2 -1
  158. package/dist/serverIdentity.js +19 -0
  159. package/package.json +62 -30
  160. package/scripts/hopper-demo-x11.py +459 -61
  161. package/scripts/prepack.mjs +55 -0
  162. package/scripts/prepare.mjs +28 -0
  163. package/scripts/rea.mjs +26 -5
  164. package/skills/reverse-engineer-anything/SKILL.md +2 -2
  165. package/skills/reverse-engineer-anything/references/javascript-applications.md +10 -0
@@ -0,0 +1,145 @@
1
+ import { compareCodePoints } from "./javascriptApplicationGraph.js";
2
+ import { digestExportShapeValue } from "./javascriptExportShapeComparisonIdentity.js";
3
+ import { javaScriptExportShapeComparisonResultSchema, } from "./javascriptExportShapeComparisonSchemas.js";
4
+ import { retainJavaScriptExportShapes, selectJavaScriptExport, } from "./javascriptExportShapeSelection.js";
5
+ import { buildJavaScriptExportShapeChanges, compareJavaScriptExportShapeChanges, hasPartialJavaScriptExportPropertyCoverage, pairJavaScriptExportShapeVariants, } from "./javascriptExportShapeVariants.js";
6
+ /** Compare exact selected export return shapes without executing JavaScript. */
7
+ export const compareJavaScriptExportShapes = (input) => {
8
+ const left = selectJavaScriptExport(input.left, input.limits.max_candidate_exports);
9
+ const right = selectJavaScriptExport(input.right, input.limits.max_candidate_exports);
10
+ const leftRetained = retainJavaScriptExportShapes(left, input.limits.max_return_variants);
11
+ const rightRetained = retainJavaScriptExportShapes(right, input.limits.max_return_variants);
12
+ const pairing = pairJavaScriptExportShapeVariants(leftRetained.shapes, rightRetained.shapes);
13
+ const evidenceLinks = evidencePair(input.left.evidenceId, input.right.evidenceId);
14
+ const allChanges = buildJavaScriptExportShapeChanges({
15
+ leftSelection: left,
16
+ rightSelection: right,
17
+ pairing,
18
+ leftShapes: leftRetained.shapes,
19
+ rightShapes: rightRetained.shapes,
20
+ evidenceLinks,
21
+ }).sort(compareJavaScriptExportShapeChanges);
22
+ const changes = allChanges.slice(0, input.limits.max_changes);
23
+ const omittedChanges = allChanges.length - changes.length;
24
+ const coverage = comparisonCoverage({
25
+ input,
26
+ left,
27
+ right,
28
+ leftRetained,
29
+ rightRetained,
30
+ pairing,
31
+ allChanges,
32
+ omittedChanges,
33
+ });
34
+ const limitations = comparisonLimitations(left, right, coverage.status);
35
+ const semantic = {
36
+ schema_version: 1,
37
+ left: left.selection,
38
+ right: right.selection,
39
+ summary: summarize(allChanges),
40
+ changes,
41
+ coverage,
42
+ evidence_links: evidenceLinks,
43
+ limitations,
44
+ runtime_validation: {
45
+ recommended_tool: "run_controlled_replay",
46
+ automatically_started: false,
47
+ required_for: "runtime-semantics",
48
+ },
49
+ };
50
+ return javaScriptExportShapeComparisonResultSchema.parse({
51
+ ...semantic,
52
+ comparison_id: `jesc_${digestExportShapeValue(semantic)}`,
53
+ });
54
+ };
55
+ const comparisonCoverage = (context) => {
56
+ const leftSource = context.left.projection?.return_shape_coverage;
57
+ const rightSource = context.right.projection?.return_shape_coverage;
58
+ const omittedCandidates = context.left.selection.omitted_candidates +
59
+ context.right.selection.omitted_candidates;
60
+ const truncated = comparisonTruncated(context, omittedCandidates);
61
+ const partial = comparisonPartial(context);
62
+ return {
63
+ status: truncated
64
+ ? "truncated"
65
+ : partial
66
+ ? "partial"
67
+ : "complete-within-inputs",
68
+ left_graph_status: context.input.left.graph.coverage.status,
69
+ right_graph_status: context.input.right.graph.coverage.status,
70
+ paired_variants: context.pairing.pairs.length,
71
+ unpaired_left_variants: context.pairing.unpairedLeft.length,
72
+ unpaired_right_variants: context.pairing.unpairedRight.length,
73
+ omitted_left_variants: context.leftRetained.omitted,
74
+ omitted_right_variants: context.rightRetained.omitted,
75
+ left_source_omitted_variants: leftSource?.omitted_return_sites ?? null,
76
+ right_source_omitted_variants: rightSource?.omitted_return_sites ?? null,
77
+ left_omitted_fields: leftSource?.omitted_fields ?? 0,
78
+ right_omitted_fields: rightSource?.omitted_fields ?? 0,
79
+ left_omitted_property_coverage: leftSource?.omitted_property_coverage ?? 0,
80
+ right_omitted_property_coverage: rightSource?.omitted_property_coverage ?? 0,
81
+ omitted_candidates: omittedCandidates,
82
+ omitted_changes: context.omittedChanges,
83
+ };
84
+ };
85
+ const comparisonTruncated = (context, omittedCandidates) => context.leftRetained.omitted > 0 ||
86
+ context.rightRetained.omitted > 0 ||
87
+ omittedCandidates > 0 ||
88
+ context.omittedChanges > 0 ||
89
+ sourceProjectionTruncated(context.left) ||
90
+ sourceProjectionTruncated(context.right);
91
+ const sourceProjectionTruncated = (selection) => {
92
+ const coverage = selection.projection?.return_shape_coverage;
93
+ if (coverage === undefined)
94
+ return false;
95
+ return (coverage.status === "truncated" ||
96
+ coverage.omitted_fields > 0 ||
97
+ coverage.omitted_property_coverage > 0 ||
98
+ coverage.projection_complete === false);
99
+ };
100
+ const comparisonPartial = (context) => selectionPartial(context.left) ||
101
+ selectionPartial(context.right) ||
102
+ context.input.left.graph.coverage.status !== "complete" ||
103
+ context.input.right.graph.coverage.status !== "complete" ||
104
+ hasPartialJavaScriptExportPropertyCoverage(context.leftRetained.shapes) ||
105
+ hasPartialJavaScriptExportPropertyCoverage(context.rightRetained.shapes) ||
106
+ context.pairing.unpairedLeft.length > 0 ||
107
+ context.pairing.unpairedRight.length > 0 ||
108
+ context.allChanges.some(({ status }) => status === "unknown");
109
+ const selectionPartial = (selection) => {
110
+ const coverage = selection.projection?.return_shape_coverage;
111
+ return (selection.selection.status !== "selected" ||
112
+ !selection.observationComplete ||
113
+ coverage?.status !== "complete" ||
114
+ coverage.projection_complete !== true);
115
+ };
116
+ const comparisonLimitations = (left, right, status) => uniqueSorted([
117
+ "Return shapes are inferred from inert syntax and do not prove runtime behavior.",
118
+ "Return variants are paired only by unique exact literal discriminants, never by source order.",
119
+ "Dynamic values, incomplete object coverage, and ambiguous variants remain unknown.",
120
+ "Controlled replay is recommended separately for runtime semantics and was not started.",
121
+ ...left.limitations,
122
+ ...right.limitations,
123
+ ...(status === "truncated"
124
+ ? [
125
+ "Comparison output or source return-shape recovery reached an explicit limit.",
126
+ ]
127
+ : []),
128
+ ...(status === "partial"
129
+ ? [
130
+ "At least one selector, graph, return shape, or property boundary is incomplete.",
131
+ ]
132
+ : []),
133
+ ]);
134
+ const summarize = (changes) => ({
135
+ added: countStatus(changes, "added"),
136
+ removed: countStatus(changes, "removed"),
137
+ changed: countStatus(changes, "changed"),
138
+ unknown: countStatus(changes, "unknown"),
139
+ });
140
+ const countStatus = (changes, status) => changes.filter((change) => change.status === status).length;
141
+ const evidencePair = (left, right) => [
142
+ left,
143
+ right,
144
+ ];
145
+ const uniqueSorted = (values) => [...new Set(values)].sort(compareCodePoints);
@@ -0,0 +1,11 @@
1
+ import { createHash } from "node:crypto";
2
+ import canonicalize from "canonicalize";
3
+ /** Canonically encode one export-shape comparison value. */
4
+ export const canonicalExportShapeValue = (value) => {
5
+ const encoded = canonicalize(value);
6
+ if (encoded === undefined)
7
+ throw new TypeError("JavaScript export shape comparison could not canonicalize data");
8
+ return encoded;
9
+ };
10
+ /** Derive one deterministic SHA-256 comparison identifier component. */
11
+ export const digestExportShapeValue = (value) => createHash("sha256").update(canonicalExportShapeValue(value)).digest("hex");
@@ -0,0 +1,277 @@
1
+ import { z } from "zod";
2
+ import { evidenceSchema } from "./evidence.js";
3
+ const evidenceIdSchema = z.string().regex(/^ev_[a-f0-9]{64}$/u);
4
+ const graphIdSchema = z.string().regex(/^jag_[a-f0-9]{64}$/u);
5
+ const nodeIdSchema = z.string().regex(/^jag_node_[a-f0-9]{64}$/u);
6
+ const boundedTextSchema = z.string().min(1).max(4_096);
7
+ const selectorTextSchema = z.string().min(1).max(4_096);
8
+ const semanticPrimitiveSchema = z.union([
9
+ z.string().max(4_096),
10
+ z.number().finite(),
11
+ z.boolean(),
12
+ z.null(),
13
+ ]);
14
+ function isJsonPointer(value) {
15
+ if (value === "")
16
+ return true;
17
+ if (!value.startsWith("/"))
18
+ return false;
19
+ for (let index = 0; index < value.length; index += 1) {
20
+ if (value[index] !== "~")
21
+ continue;
22
+ const escaped = value[index + 1];
23
+ if (escaped !== "0" && escaped !== "1")
24
+ return false;
25
+ index += 1;
26
+ }
27
+ return true;
28
+ }
29
+ const jsonPointerSchema = z
30
+ .string()
31
+ .max(4_096)
32
+ .refine(isJsonPointer, "Expected an RFC 6901 JSON Pointer");
33
+ const sourcePointSchema = z.strictObject({
34
+ line: z.number().int().min(1),
35
+ column: z.number().int().min(0),
36
+ });
37
+ const sourceRangeSchema = z
38
+ .strictObject({
39
+ start: sourcePointSchema,
40
+ end: sourcePointSchema,
41
+ })
42
+ .superRefine((range, context) => {
43
+ if (range.end.line < range.start.line ||
44
+ (range.end.line === range.start.line &&
45
+ range.end.column < range.start.column))
46
+ context.addIssue({
47
+ code: "custom",
48
+ path: ["end"],
49
+ message: "Source range end must not precede its start",
50
+ });
51
+ });
52
+ const comparisonLimitsSchema = z.strictObject({
53
+ max_candidate_exports: z.number().int().min(1).max(1_000).default(100),
54
+ max_return_variants: z.number().int().min(1).max(1_000).default(128),
55
+ max_changes: z.number().int().min(1).max(10_000).default(1_000),
56
+ });
57
+ /** Two authenticated application graphs, exact export selectors, and bounds. */
58
+ export const compareJavaScriptExportShapesInputSchema = z
59
+ .strictObject({
60
+ left: evidenceSchema,
61
+ right: evidenceSchema,
62
+ left_module_path: selectorTextSchema,
63
+ left_export_name: selectorTextSchema,
64
+ right_module_path: selectorTextSchema,
65
+ right_export_name: selectorTextSchema,
66
+ limits: comparisonLimitsSchema.default({
67
+ max_candidate_exports: 100,
68
+ max_return_variants: 128,
69
+ max_changes: 1_000,
70
+ }),
71
+ unknown_registry_approved: z.literal(true).optional(),
72
+ })
73
+ .superRefine((input, context) => {
74
+ if (input.left.evidence_id === input.right.evidence_id)
75
+ context.addIssue({
76
+ code: "custom",
77
+ path: ["right"],
78
+ message: "JavaScript export shape Evidence must be distinct",
79
+ });
80
+ });
81
+ const projectedReturnFieldSchema = z
82
+ .strictObject({
83
+ path: jsonPointerSchema,
84
+ state: z.enum(["literal", "union", "unknown"]),
85
+ value: z.union([
86
+ semanticPrimitiveSchema,
87
+ z.array(semanticPrimitiveSchema).min(1).max(32),
88
+ ]),
89
+ reason: boundedTextSchema.nullable(),
90
+ })
91
+ .superRefine((field, context) => {
92
+ if (field.state === "union" && !Array.isArray(field.value))
93
+ context.addIssue({
94
+ code: "custom",
95
+ path: ["value"],
96
+ message: "Union return fields require a primitive value array",
97
+ });
98
+ if (field.state !== "union" && Array.isArray(field.value))
99
+ context.addIssue({
100
+ code: "custom",
101
+ path: ["value"],
102
+ message: "Only union return fields may contain a value array",
103
+ });
104
+ if (field.state === "unknown" && field.reason === null)
105
+ context.addIssue({
106
+ code: "custom",
107
+ path: ["reason"],
108
+ message: "Unknown return fields require a reason",
109
+ });
110
+ if (field.state !== "unknown" && field.reason !== null)
111
+ context.addIssue({
112
+ code: "custom",
113
+ path: ["reason"],
114
+ message: "Known return fields cannot carry an unknown reason",
115
+ });
116
+ });
117
+ const projectedPropertyCoverageSchema = z.strictObject({
118
+ path: jsonPointerSchema,
119
+ status: z.enum(["complete", "partial"]),
120
+ omitted: z.number().int().min(0).nullable(),
121
+ });
122
+ const projectedReturnShapeSchema = z
123
+ .strictObject({
124
+ source_range: sourceRangeSchema,
125
+ value_status: z.enum([
126
+ "literal",
127
+ "union",
128
+ "object",
129
+ "array",
130
+ "unknown",
131
+ "ambiguous",
132
+ "cycle",
133
+ "limit-reached",
134
+ ]),
135
+ fields: z.array(projectedReturnFieldSchema).max(64),
136
+ property_coverage: z.array(projectedPropertyCoverageSchema).max(64),
137
+ })
138
+ .superRefine((shape, context) => {
139
+ const fieldPaths = shape.fields.map(({ path }) => path);
140
+ if (new Set(fieldPaths).size !== fieldPaths.length)
141
+ context.addIssue({
142
+ code: "custom",
143
+ path: ["fields"],
144
+ message: "Projected return field paths must be unique",
145
+ });
146
+ const coveragePaths = shape.property_coverage.map(({ path }) => path);
147
+ if (new Set(coveragePaths).size !== coveragePaths.length)
148
+ context.addIssue({
149
+ code: "custom",
150
+ path: ["property_coverage"],
151
+ message: "Projected property coverage paths must be unique",
152
+ });
153
+ });
154
+ /** Strict graph-observation payload produced by static return-shape recovery. */
155
+ export const projectedExportReturnShapesSchema = z
156
+ .strictObject({
157
+ semantic_role: z.literal("export-return-shapes"),
158
+ module_path: selectorTextSchema,
159
+ exported_name: selectorTextSchema,
160
+ callable_id: boundedTextSchema,
161
+ callable_kind: z.enum(["function", "class", "method"]),
162
+ static_return_shapes: z.array(projectedReturnShapeSchema).max(32),
163
+ return_shape_coverage: z.strictObject({
164
+ status: z.enum(["complete", "partial", "truncated"]),
165
+ retained_return_sites: z.number().int().min(0).max(32),
166
+ omitted_return_sites: z.number().int().min(0).nullable(),
167
+ omitted_fields: z.number().int().min(0),
168
+ omitted_property_coverage: z.number().int().min(0),
169
+ projection_complete: z.boolean(),
170
+ }),
171
+ })
172
+ .superRefine((projection, context) => {
173
+ if (projection.return_shape_coverage.retained_return_sites !==
174
+ projection.static_return_shapes.length)
175
+ context.addIssue({
176
+ code: "custom",
177
+ path: ["return_shape_coverage", "retained_return_sites"],
178
+ message: "Retained return-site count must match projected shapes",
179
+ });
180
+ });
181
+ const exportCandidateSchema = z.strictObject({
182
+ node_id: nodeIdSchema,
183
+ module_path: selectorTextSchema,
184
+ export_name: selectorTextSchema,
185
+ matches_requested_module: z.boolean(),
186
+ matches_requested_export: z.boolean(),
187
+ });
188
+ const selectorResultSchema = z.strictObject({
189
+ evidence_id: evidenceIdSchema,
190
+ graph_id: graphIdSchema,
191
+ requested_module_path: selectorTextSchema,
192
+ requested_export_name: selectorTextSchema,
193
+ status: z.enum(["selected", "missing", "ambiguous", "unavailable"]),
194
+ selected_node_id: nodeIdSchema.nullable(),
195
+ candidates: z.array(exportCandidateSchema).max(1_000),
196
+ omitted_candidates: z.number().int().min(0),
197
+ });
198
+ const valueAvailabilitySchema = z.discriminatedUnion("availability", [
199
+ z.strictObject({ availability: z.literal("absent") }),
200
+ z.strictObject({
201
+ availability: z.literal("literal"),
202
+ value: semanticPrimitiveSchema,
203
+ }),
204
+ z.strictObject({
205
+ availability: z.literal("union"),
206
+ values: z.array(semanticPrimitiveSchema).min(1).max(32),
207
+ }),
208
+ z.strictObject({
209
+ availability: z.literal("unknown"),
210
+ reason: boundedTextSchema,
211
+ }),
212
+ ]);
213
+ const discriminantSchema = z.strictObject({
214
+ path: jsonPointerSchema,
215
+ value: semanticPrimitiveSchema,
216
+ });
217
+ const comparisonChangeSchema = z.strictObject({
218
+ change_id: z.string().regex(/^jesc_change_[a-f0-9]{64}$/u),
219
+ status: z.enum(["added", "removed", "changed", "unknown"]),
220
+ path: jsonPointerSchema,
221
+ discriminant: discriminantSchema.nullable(),
222
+ left: valueAvailabilitySchema,
223
+ right: valueAvailabilitySchema,
224
+ left_source_range: sourceRangeSchema.nullable(),
225
+ right_source_range: sourceRangeSchema.nullable(),
226
+ evidence_links: z.tuple([evidenceIdSchema, evidenceIdSchema]),
227
+ limitations: z.array(boundedTextSchema).max(20),
228
+ });
229
+ /** Bounded static export-return comparison with explicit unknown semantics. */
230
+ export const javaScriptExportShapeComparisonResultSchema = z.strictObject({
231
+ schema_version: z.literal(1),
232
+ comparison_id: z.string().regex(/^jesc_[a-f0-9]{64}$/u),
233
+ left: selectorResultSchema,
234
+ right: selectorResultSchema,
235
+ summary: z.strictObject({
236
+ added: z.number().int().min(0),
237
+ removed: z.number().int().min(0),
238
+ changed: z.number().int().min(0),
239
+ unknown: z.number().int().min(0),
240
+ }),
241
+ changes: z.array(comparisonChangeSchema).max(10_000),
242
+ coverage: z.strictObject({
243
+ status: z.enum(["complete-within-inputs", "partial", "truncated"]),
244
+ left_graph_status: z.enum([
245
+ "complete",
246
+ "partial",
247
+ "unknown",
248
+ "unavailable",
249
+ ]),
250
+ right_graph_status: z.enum([
251
+ "complete",
252
+ "partial",
253
+ "unknown",
254
+ "unavailable",
255
+ ]),
256
+ paired_variants: z.number().int().min(0),
257
+ unpaired_left_variants: z.number().int().min(0),
258
+ unpaired_right_variants: z.number().int().min(0),
259
+ omitted_left_variants: z.number().int().min(0),
260
+ omitted_right_variants: z.number().int().min(0),
261
+ left_source_omitted_variants: z.number().int().min(0).nullable(),
262
+ right_source_omitted_variants: z.number().int().min(0).nullable(),
263
+ left_omitted_fields: z.number().int().min(0),
264
+ right_omitted_fields: z.number().int().min(0),
265
+ left_omitted_property_coverage: z.number().int().min(0),
266
+ right_omitted_property_coverage: z.number().int().min(0),
267
+ omitted_candidates: z.number().int().min(0),
268
+ omitted_changes: z.number().int().min(0),
269
+ }),
270
+ evidence_links: z.tuple([evidenceIdSchema, evidenceIdSchema]),
271
+ limitations: z.array(boundedTextSchema).max(1_000),
272
+ runtime_validation: z.strictObject({
273
+ recommended_tool: z.literal("run_controlled_replay"),
274
+ automatically_started: z.literal(false),
275
+ required_for: z.literal("runtime-semantics"),
276
+ }),
277
+ });
@@ -0,0 +1,132 @@
1
+ import { compareCodePoints } from "./javascriptApplicationGraph.js";
2
+ import { projectedExportReturnShapesSchema, } from "./javascriptExportShapeComparisonSchemas.js";
3
+ /** Select one exact trusted export and its exact static return-shape observation. */
4
+ export const selectJavaScriptExport = (side, maxCandidates) => {
5
+ const candidates = exportCandidates(side.graph);
6
+ const exact = candidates.filter(({ modulePath, exportName }) => modulePath === side.modulePath && exportName === side.exportName);
7
+ const matchingOneSelector = candidates.filter(({ modulePath, exportName }) => modulePath === side.modulePath || exportName === side.exportName);
8
+ const diagnosticPool = exact.length > 0
9
+ ? exact
10
+ : matchingOneSelector.length > 0
11
+ ? matchingOneSelector
12
+ : candidates;
13
+ const retainedCandidates = diagnosticPool.slice(0, maxCandidates);
14
+ const base = selectorBase(side, diagnosticPool, retainedCandidates);
15
+ if (exact.length === 0)
16
+ return unresolvedSelection(base, "missing", null, [
17
+ `No exact export binding matched ${side.modulePath}:${side.exportName}.`,
18
+ ]);
19
+ if (exact.length > 1)
20
+ return unresolvedSelection(base, "ambiguous", null, [
21
+ `Multiple exact export bindings matched ${side.modulePath}:${side.exportName}; none was selected.`,
22
+ ]);
23
+ const selected = exact[0];
24
+ if (selected === undefined || !selected.trusted)
25
+ return unresolvedSelection(base, "unavailable", selected?.node.node_id ?? null, [
26
+ "The exact export binding lacks the expected static-analysis authority.",
27
+ ]);
28
+ const returnShape = returnShapeFor(selected.node, side);
29
+ if (returnShape.projection === null)
30
+ return unresolvedSelection(base, "unavailable", selected.node.node_id, [
31
+ returnShape.reason,
32
+ ]);
33
+ return {
34
+ selection: {
35
+ ...base,
36
+ status: "selected",
37
+ selected_node_id: selected.node.node_id,
38
+ },
39
+ projection: returnShape.projection,
40
+ observationComplete: returnShape.observationComplete,
41
+ limitations: [],
42
+ };
43
+ };
44
+ /** Apply the caller's explicit return-variant limit. */
45
+ export const retainJavaScriptExportShapes = (selection, maximum) => {
46
+ const shapes = selection.projection?.static_return_shapes ?? [];
47
+ const retained = shapes.slice(0, maximum);
48
+ return { shapes: retained, omitted: shapes.length - retained.length };
49
+ };
50
+ const selectorBase = (side, candidates, retained) => ({
51
+ evidence_id: side.evidenceId,
52
+ graph_id: side.graph.graph_id,
53
+ requested_module_path: side.modulePath,
54
+ requested_export_name: side.exportName,
55
+ candidates: retained.map((candidate) => ({
56
+ node_id: candidate.node.node_id,
57
+ module_path: candidate.modulePath,
58
+ export_name: candidate.exportName,
59
+ matches_requested_module: candidate.modulePath === side.modulePath,
60
+ matches_requested_export: candidate.exportName === side.exportName,
61
+ })),
62
+ omitted_candidates: candidates.length - retained.length,
63
+ });
64
+ const unresolvedSelection = (base, status, nodeId, limitations) => ({
65
+ selection: { ...base, status, selected_node_id: nodeId },
66
+ projection: null,
67
+ observationComplete: false,
68
+ limitations,
69
+ });
70
+ const exportCandidates = (graph) => {
71
+ const candidates = new Map();
72
+ for (const node of graph.nodes) {
73
+ for (const observation of node.observations) {
74
+ const properties = observation.properties;
75
+ if (properties.semantic_role !== "export-binding")
76
+ continue;
77
+ const modulePath = properties.module_path;
78
+ const exportName = properties.exported_name;
79
+ if (typeof modulePath !== "string" || typeof exportName !== "string")
80
+ continue;
81
+ const key = `${node.node_id}\0${modulePath}\0${exportName}`;
82
+ const trusted = observation.evidence.authority === "ast-static-analysis" &&
83
+ observation.evidence.state === "observed" &&
84
+ observation.evidence.extractor.operation === "recover-module-export";
85
+ const existing = candidates.get(key);
86
+ candidates.set(key, {
87
+ node,
88
+ modulePath,
89
+ exportName,
90
+ trusted: trusted || existing?.trusted === true,
91
+ });
92
+ }
93
+ }
94
+ return [...candidates.values()].sort((left, right) => compareCodePoints(candidateKey(left), candidateKey(right)));
95
+ };
96
+ const candidateKey = (candidate) => `${candidate.modulePath}\0${candidate.exportName}\0${candidate.node.node_id}`;
97
+ const returnShapeFor = (node, side) => {
98
+ const roleObservations = node.observations.filter(({ properties }) => properties.semantic_role === "export-return-shapes");
99
+ const parsed = roleObservations.map((observation) => ({
100
+ observation,
101
+ result: projectedExportReturnShapesSchema.safeParse(observation.properties),
102
+ }));
103
+ if (parsed.some(({ result }) => !result.success))
104
+ return unavailableReturnShape("The export return-shape observation is malformed.");
105
+ const matching = parsed.filter(({ result }) => result.success &&
106
+ result.data.module_path === side.modulePath &&
107
+ result.data.exported_name === side.exportName);
108
+ if (matching.length !== 1)
109
+ return unavailableReturnShape(matching.length === 0
110
+ ? "No exact static return-shape observation is available for the selected export."
111
+ : "Multiple static return-shape observations matched the selected export.");
112
+ const selected = matching[0];
113
+ if (selected === undefined || !selected.result.success)
114
+ return unavailableReturnShape("The selected return-shape observation could not be parsed.");
115
+ const { observation } = selected;
116
+ const trusted = observation.evidence.authority === "static-relationship-inference" &&
117
+ observation.evidence.state === "inferred" &&
118
+ observation.evidence.extractor.operation === "recover-export-return-shapes";
119
+ if (!trusted)
120
+ return unavailableReturnShape("The return-shape observation lacks the expected static-inference authority.");
121
+ return {
122
+ projection: selected.result.data,
123
+ observationComplete: observation.evidence.coverage.status === "complete" &&
124
+ !observation.evidence.coverage.truncated,
125
+ reason: "",
126
+ };
127
+ };
128
+ const unavailableReturnShape = (reason) => ({
129
+ projection: null,
130
+ observationComplete: false,
131
+ reason,
132
+ });