Files
rea/src/domain/javascript/javascriptSemanticQuerySchemas.ts
T
Lewis WangandClaude Fable 5.1 b912ec184c fix(javascript): accept retained empty endpoint seeds (#6462)
Application analysis preserves the complete literal request endpoint,
including the empty string, and the event seed already accepts a
retained empty name. The endpoint seed still required a non-empty
value, so trace-javascript-semantics refused to select a retained ""
endpoint with invalid_request.

The endpoint seed now accepts any string and keeps exact matching.
Boundary-field seeds keep their minimum because boundary nodes are only
produced from method names.

Found while fixing #6458; the event half of that report landed in
cf5e4f6fa.

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-03 10:10:33 +08:00

119 lines
3.6 KiB
TypeScript

import { z } from "zod";
import {
JAVASCRIPT_SEMANTIC_NODE_KINDS,
JAVASCRIPT_SEMANTIC_RELATIONS,
javaScriptSemanticNodeSchema,
javaScriptSemanticRelationSchema,
javaScriptSemanticEvidenceContextSchema,
javaScriptSemanticUnknownSchema,
} from "./javascriptSemanticGraphSchemas.js";
import { digestSchema, prefixedDigestSchema } from "../digests.js";
const semanticNodeIdSchema = prefixedDigestSchema("jsrg_node");
const literalValueSchema = z.union([
z.string(),
z.number(),
z.boolean(),
z.null(),
]);
const literalSeedSchema = z.strictObject({
kind: z.literal("literal"),
value: literalValueSchema,
});
/** Authenticated starting points accepted by semantic tracing. */
export const javaScriptSemanticQuerySeedSchema = z.discriminatedUnion("kind", [
z.strictObject({
kind: z.literal("semantic-node"),
node_id: semanticNodeIdSchema,
}),
z.strictObject({
kind: z.literal("application-node"),
node_id: prefixedDigestSchema("jag_node"),
}),
literalSeedSchema,
z.strictObject({
kind: z.literal("function"),
fingerprint_sha256: digestSchema,
}),
z.strictObject({
kind: z.literal("property"),
name: z.string(),
}),
// Analysis preserves the complete literal endpoint, including the empty
// string, so the seed matches any retained value exactly, as event does.
z.strictObject({
kind: z.literal("endpoint"),
value: z.string(),
}),
z.strictObject({
kind: z.literal("event"),
name: z.string(),
}),
z.strictObject({
kind: z.literal("boundary-field"),
field: z.string().min(1),
}),
]);
/** Parsed pure-domain query over one authenticated companion graph. */
export const javaScriptSemanticQueryInputSchema = z.strictObject({
seed: javaScriptSemanticQuerySeedSchema,
direction: z.enum([
"backward-provenance",
"forward-influence",
"callers",
"ownership",
]),
allowed_relations: z
.array(z.enum(JAVASCRIPT_SEMANTIC_RELATIONS))
.min(1)
.optional(),
include_ambiguous_dynamic_edges: z.boolean().default(false),
expected: z
.strictObject({
role: z.enum(["source", "sink"]),
classes: z.array(z.enum(JAVASCRIPT_SEMANTIC_NODE_KINDS)).min(1),
})
.nullable()
.default(null),
});
/** Deterministic semantic trace result. */
export const javaScriptSemanticQueryResultSchema = z.strictObject({
query_id: prefixedDigestSchema("jsrq"),
source_graph_id: prefixedDigestSchema("jsrg"),
seed: javaScriptSemanticQuerySeedSchema,
direction: javaScriptSemanticQueryInputSchema.shape.direction,
status: z.enum(["found", "no-match", "ambiguous", "partial", "unsupported"]),
seed_node_ids: z.array(semanticNodeIdSchema),
evidence_contexts: z.array(javaScriptSemanticEvidenceContextSchema),
nodes: z.array(javaScriptSemanticNodeSchema),
relations: z.array(javaScriptSemanticRelationSchema),
unknowns: z.array(javaScriptSemanticUnknownSchema),
expected_match_node_ids: z.array(semanticNodeIdSchema),
summary: z.strictObject({
total_seed_matches: z.int().min(0),
traversed_nodes: z.int().min(0),
traversed_relations: z.int().min(0),
traversed_functions: z.int().min(0),
traversed_modules: z.int().min(0),
relevant_unknowns: z.int().min(0),
}),
coverage: z.strictObject({
status: z.enum(["complete", "partial", "unavailable"]),
}),
limitations: z.array(z.string().min(1)),
});
/** Validated semantic query input. */
export type JavaScriptSemanticQueryInput = z.infer<
typeof javaScriptSemanticQueryInputSchema
>;
/** Validated semantic query result. */
export type JavaScriptSemanticQueryResult = z.infer<
typeof javaScriptSemanticQueryResultSchema
>;