feat(core): extend Zod schemas and aliases for 8 new node/edge types

Update EdgeTypeSchema with 8 new edge types (deploys, serves, migrates,
documents, provisions, routes, defines_schema, triggers).

Update GraphNodeSchema with 8 new node types (config, document, service,
table, endpoint, pipeline, schema, resource).

Add NODE_TYPE_ALIASES for non-code types (container->service, doc->document,
workflow->pipeline, etc.) and EDGE_TYPE_ALIASES (describes->documents,
creates->provisions, exposes->serves, etc.).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Lum1104
2026-03-28 18:30:17 +08:00
co-authored by Claude Opus 4.6
parent b1f763adac
commit 1f554146c0
2 changed files with 107 additions and 2 deletions
@@ -662,3 +662,61 @@ describe("permissive validation", () => {
expect(result.errors).toContain('edges[0]: target "non-existent-node" does not exist in nodes — removed');
});
});
describe("Extended node/edge types", () => {
it("validates nodes with new types: config, document, service, table, endpoint, pipeline, schema, resource", () => {
const newTypes = ["config", "document", "service", "table", "endpoint", "pipeline", "schema", "resource"];
for (const type of newTypes) {
const graph = structuredClone(validGraph);
(graph.nodes[0] as any).type = type;
const result = validateGraph(graph);
expect(result.success).toBe(true);
expect(result.data!.nodes[0].type).toBe(type);
}
});
it("validates edges with new types: deploys, serves, migrates, documents, provisions, routes, defines_schema, triggers", () => {
const newTypes = ["deploys", "serves", "migrates", "documents", "provisions", "routes", "defines_schema", "triggers"];
for (const type of newTypes) {
const graph = structuredClone(validGraph);
(graph.edges[0] as any).type = type;
const result = validateGraph(graph);
expect(result.success).toBe(true);
expect(result.data!.edges[0].type).toBe(type);
}
});
it("auto-fixes new node type aliases: container->service, doc->document, workflow->pipeline, etc.", () => {
const aliases: Record<string, string> = {
container: "service",
doc: "document",
workflow: "pipeline",
route: "endpoint",
setting: "config",
infra: "resource",
migration: "table",
};
for (const [alias, canonical] of Object.entries(aliases)) {
const graph = structuredClone(validGraph);
(graph.nodes[0] as any).type = alias;
const result = validateGraph(graph);
expect(result.success).toBe(true);
expect(result.data!.nodes[0].type).toBe(canonical);
}
});
it("auto-fixes new edge type aliases: describes->documents, creates->provisions, exposes->serves", () => {
const aliases: Record<string, string> = {
describes: "documents",
creates: "provisions",
exposes: "serves",
};
for (const [alias, canonical] of Object.entries(aliases)) {
const graph = structuredClone(validGraph);
(graph.edges[0] as any).type = alias;
const result = validateGraph(graph);
expect(result.success).toBe(true);
expect(result.data!.edges[0].type).toBe(canonical);
}
});
});
@@ -1,12 +1,14 @@
import { z } from "zod";
// Edge types (18 values across 5 categories)
// Edge types (26 values across 6 categories)
export const EdgeTypeSchema = z.enum([
"imports", "exports", "contains", "inherits", "implements", // Structural
"calls", "subscribes", "publishes", "middleware", // Behavioral
"reads_from", "writes_to", "transforms", "validates", // Data flow
"depends_on", "tested_by", "configures", // Dependencies
"related", "similar_to", // Semantic
"deploys", "serves", "migrates", "documents", // Infrastructure
"provisions", "routes", "defines_schema", "triggers", // Infrastructure
]);
// Aliases that LLMs commonly generate instead of canonical node types
@@ -19,6 +21,35 @@ export const NODE_TYPE_ALIASES: Record<string, string> = {
mod: "module",
pkg: "module",
package: "module",
// Non-code aliases
container: "service",
deployment: "service",
pod: "service",
doc: "document",
readme: "document",
docs: "document",
workflow: "pipeline",
job: "pipeline",
ci: "pipeline",
action: "pipeline",
route: "endpoint",
api: "endpoint",
query: "endpoint",
mutation: "endpoint",
setting: "config",
env: "config",
configuration: "config",
infra: "resource",
infrastructure: "resource",
terraform: "resource",
migration: "table",
database: "table",
db: "table",
view: "table",
proto: "schema",
protobuf: "schema",
definition: "schema",
typedef: "schema",
};
// Aliases that LLMs commonly generate instead of canonical edge types
@@ -36,6 +67,18 @@ export const EDGE_TYPE_ALIASES: Record<string, string> = {
contain: "contains",
publish: "publishes",
subscribe: "subscribes",
// Non-code aliases
describes: "documents",
documented_by: "documents",
creates: "provisions",
exposes: "serves",
listens: "serves",
deploys_to: "deploys",
migrates_to: "migrates",
routes_to: "routes",
triggers_on: "triggers",
fires: "triggers",
defines: "defines_schema",
};
// Aliases for complexity values LLMs commonly generate
@@ -266,7 +309,11 @@ export function autoFixGraph(data: Record<string, unknown>): {
export const GraphNodeSchema = z.object({
id: z.string(),
type: z.enum(["file", "function", "class", "module", "concept"]),
type: z.enum([
"file", "function", "class", "module", "concept",
"config", "document", "service", "table", "endpoint",
"pipeline", "schema", "resource",
]),
name: z.string(),
filePath: z.string().optional(),
lineRange: z.tuple([z.number(), z.number()]).optional(),