diff --git a/schema.neo4j.json b/schema.neo4j.json index 2fb9054..8cae479 100644 --- a/schema.neo4j.json +++ b/schema.neo4j.json @@ -14,7 +14,9 @@ "schema_version": "string", "language": "string", "max_level": "integer", - "k_limit": "integer" + "k_limit": "integer", + "analyzer_name": "string", + "analyzer_version": "string" } }, { diff --git a/src/build/neo4j/project.ts b/src/build/neo4j/project.ts index 7c59e54..198b04e 100644 --- a/src/build/neo4j/project.ts +++ b/src/build/neo4j/project.ts @@ -51,6 +51,12 @@ export function project(app: V2Application, _appName?: string): GraphRows { language: app.language, max_level: app.max_level, k_limit: app.k_limit ?? null, + // Same analyzer{name,version} the JSON envelope carries (emit.ts) — the two co-primary + // projections must never diverge on analyzer identity (issue #43). Namespaced as + // analyzer_name/analyzer_version (not bare name/version) to avoid colliding with the + // app-name param (project()'s _appName) and every other CanNode's bare `name`. + analyzer_name: app.analyzer.name, + analyzer_version: app.analyzer.version, })); for (const mod of Object.values(root.symbol_table)) { diff --git a/src/build/neo4j/schema.ts b/src/build/neo4j/schema.ts index 8c43efc..4584af4 100644 --- a/src/build/neo4j/schema.ts +++ b/src/build/neo4j/schema.ts @@ -56,7 +56,13 @@ export const NODE_LABELS: NodeLabel[] = [ label: "Application", mergeLabel: "Application", key: "id", - properties: { id: "string", schema_version: "string", language: "string", max_level: "integer", k_limit: "integer" }, + properties: { + id: "string", schema_version: "string", language: "string", max_level: "integer", k_limit: "integer", + // Analyzer identity — mirrors the JSON envelope's `analyzer{name,version}` (issue #43), + // namespaced (not bare name/version) to avoid colliding with the app-name param / every + // other CanNode's bare `name`. + analyzer_name: "string", analyzer_version: "string", + }, }, { label: "Module", diff --git a/test/neo4j-schema.test.ts b/test/neo4j-schema.test.ts index c22e139..0c0d813 100644 --- a/test/neo4j-schema.test.ts +++ b/test/neo4j-schema.test.ts @@ -9,6 +9,7 @@ import { describe, expect, test } from "bun:test"; import * as fs from "node:fs"; import * as os from "node:os"; import * as path from "node:path"; +import pkg from "../package.json"; import { MARKER_LABELS, NODE_LABELS, @@ -92,6 +93,19 @@ describe("neo4j schema conformance", () => { }); }); +// ---- :Application analyzer identity (issue #43) ------------------------------------------------ +// The JSON envelope advertises `analyzer{name,version}` (#29); the Neo4j :Application node is the +// co-primary projection of the same envelope and must not diverge on analyzer identity. + +describe(":Application node carries analyzer identity (issue #43)", () => { + test("version matches package.json (the same source the JSON envelope's analyzer.version uses)", () => { + const appNode = rows.nodes.find((n) => n.labels.includes("Application")); + expect(appNode, "no :Application node projected").toBeDefined(); + expect(appNode!.props.analyzer_version).toBe(pkg.version); + expect(appNode!.props.analyzer_name).toBe("codeanalyzer-typescript"); + }); +}); + // ---- Class inheritance: EXTENDS/IMPLEMENTS (issue #33) ------------------------------------------ // dataflow-app's src/hierarchy.ts is a minimal, first-party heritage fixture: `Rectangle implements // Shape`, `Square extends Rectangle implements Labeled`.