Run inert captured-script analysis in owned children with per-script and aggregate deadlines, bounded source/result transfer and explicit per-script coverage. Preserve completed facts and exact cleanup authority across cancellation, mixed descriptor/process failures and cross-consumer retry. Share aggregate source admission across page and Electron capture, expose CLI/MCP resource controls and retain selected parameters in Evidence. Verified with controlled CDP public workflows, real owned Node failure controls and the reporter-matching ReactDOM UMD artifact; real Chrome/Electron and Windows/Bun remain unqualified.
123 lines
3.6 KiB
TypeScript
123 lines
3.6 KiB
TypeScript
import { z } from "zod";
|
|
|
|
import { webBundleAnalysisSchema } from "./webBundleAnalysis.js";
|
|
|
|
const observationsSchema = z.strictObject({
|
|
edges: webBundleAnalysisSchema.shape.observations.shape.chunks.shape.edges,
|
|
routes: webBundleAnalysisSchema.shape.observations.shape.routes,
|
|
endpoints: webBundleAnalysisSchema.shape.observations.shape.endpoints,
|
|
webmcp_declarations:
|
|
webBundleAnalysisSchema.shape.observations.shape.webmcp_declarations,
|
|
});
|
|
|
|
/** Serializable result for one captured script, suitable for worker transport. */
|
|
export const webBundleScriptAnalysisSchema = z
|
|
.discriminatedUnion("status", [
|
|
z.strictObject({
|
|
status: z.literal("analyzed"),
|
|
script_key: z.string(),
|
|
parse_status: z.enum(["parsed", "recovered", "failed"]),
|
|
visited_ast_nodes: z.number().int().min(0),
|
|
widened_return_references: z.boolean(),
|
|
observations: observationsSchema,
|
|
inferences: webBundleAnalysisSchema.shape.inferences,
|
|
}),
|
|
z.strictObject({
|
|
status: z.literal("unavailable"),
|
|
script_key: z.string(),
|
|
reason: z.enum([
|
|
"worker_failure",
|
|
"deadline",
|
|
"resource_constraint",
|
|
"cancelled",
|
|
"not_started",
|
|
]),
|
|
detail: z.string().optional(),
|
|
}),
|
|
])
|
|
.superRefine((result, context) => {
|
|
if (result.status !== "analyzed") return;
|
|
|
|
const checkScriptKey = (
|
|
scriptKey: string,
|
|
path: (string | number)[],
|
|
): void => {
|
|
if (scriptKey !== result.script_key)
|
|
context.addIssue({
|
|
code: "custom",
|
|
path,
|
|
message: "Per-script analysis evidence must name its owning script",
|
|
});
|
|
};
|
|
|
|
result.observations.edges.forEach((edge, index) => {
|
|
checkScriptKey(edge.from_script_key, [
|
|
"observations",
|
|
"edges",
|
|
index,
|
|
"from_script_key",
|
|
]);
|
|
checkScriptKey(edge.location.script_key, [
|
|
"observations",
|
|
"edges",
|
|
index,
|
|
"location",
|
|
"script_key",
|
|
]);
|
|
});
|
|
for (const collection of ["routes", "endpoints"] as const)
|
|
result.observations[collection].forEach((finding, index) =>
|
|
checkScriptKey(finding.location.script_key, [
|
|
"observations",
|
|
collection,
|
|
index,
|
|
"location",
|
|
"script_key",
|
|
]),
|
|
);
|
|
result.observations.webmcp_declarations.forEach((declaration, index) =>
|
|
checkScriptKey(declaration.location.script_key, [
|
|
"observations",
|
|
"webmcp_declarations",
|
|
index,
|
|
"location",
|
|
"script_key",
|
|
]),
|
|
);
|
|
result.inferences.forEach((inference, inferenceIndex) =>
|
|
inference.basis.forEach((basis, basisIndex) =>
|
|
checkScriptKey(basis.script_key, [
|
|
"inferences",
|
|
inferenceIndex,
|
|
"basis",
|
|
basisIndex,
|
|
"script_key",
|
|
]),
|
|
),
|
|
);
|
|
|
|
if (result.parse_status === "failed") {
|
|
const hasFindings =
|
|
result.observations.edges.length > 0 ||
|
|
result.observations.routes.length > 0 ||
|
|
result.observations.endpoints.length > 0 ||
|
|
result.observations.webmcp_declarations.length > 0 ||
|
|
result.inferences.length > 0;
|
|
if (
|
|
result.visited_ast_nodes !== 0 ||
|
|
result.widened_return_references ||
|
|
hasFindings
|
|
)
|
|
context.addIssue({
|
|
code: "custom",
|
|
path: ["parse_status"],
|
|
message:
|
|
"A failed script parse cannot carry visited nodes or derived findings",
|
|
});
|
|
}
|
|
});
|
|
|
|
export type WebBundleScriptAnalysis = z.infer<
|
|
typeof webBundleScriptAnalysisSchema
|
|
>;
|