From fa8f41a7da78e567eb3b12101b56ca5aeb63cb90 Mon Sep 17 00:00:00 2001 From: Rahul Krishna Date: Tue, 7 Jul 2026 00:28:42 -0400 Subject: [PATCH 1/2] feat: add analyzer{name,version} to the schema-v2 envelope MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consumers (the CLDK SDK, tooling correlating multiple analysis.json artifacts) need to know which analyzer produced a given output and at what version, independent of schema_version. Add a V2Analyzer{name, version} type and a required analyzer field on V2Application, populated from the literal package name and the existing ANALYZER_VERSION constant (src/utils/version.ts) — the same version stamped into the cache, not a new hardcoded literal. --- src/schema/v2/emit.ts | 3 +++ src/schema/v2/model.ts | 7 +++++++ test/schema-v2.test.ts | 6 ++++++ 3 files changed, 16 insertions(+) diff --git a/src/schema/v2/emit.ts b/src/schema/v2/emit.ts index 3f0098b..db70c9e 100644 --- a/src/schema/v2/emit.ts +++ b/src/schema/v2/emit.ts @@ -12,6 +12,7 @@ import * as path from "node:path"; import type { AnalysisOptions } from "../../options"; +import { ANALYZER_VERSION } from "../../utils/version"; import type { TSApplication, TSCallable, @@ -30,6 +31,7 @@ import type { V2Application, V2BodyNode, V2CallEdge, V2Callable, V2External, V2F const LANGUAGE = "typescript"; const SCHEMA_VERSION = "2.0.0"; +const ANALYZER_NAME = "codeanalyzer-typescript"; /** Highest analysis level this emitter populates today (L1 tree, L2 call graph, L3/L4 dataflow). */ const MAX_IMPLEMENTED = 4; @@ -371,6 +373,7 @@ export function toV2Detailed(app: TSApplication, opts: AnalysisOptions): ToV2Res language: LANGUAGE, max_level: Math.min(level, MAX_IMPLEMENTED), ...(k_limit !== undefined ? { k_limit } : {}), + analyzer: { name: ANALYZER_NAME, version: ANALYZER_VERSION }, application: root, }; return { application, idBySig, collisions, dangling }; diff --git a/src/schema/v2/model.ts b/src/schema/v2/model.ts index a2a19af..493fee6 100644 --- a/src/schema/v2/model.ts +++ b/src/schema/v2/model.ts @@ -25,9 +25,16 @@ export interface V2Application { language: string; // "typescript" max_level: number; // highest level populated; consumers read this, not key-sniffing k_limit?: number; // access-path depth bound for the L3/L4 dataflow (present at L3+) + analyzer: V2Analyzer; // which analyzer produced this artifact, and at what version application: V2Root; } +/** Analyzer identity — lets consumers correlate an `analysis.json` with the tool/version that emitted it. */ +export interface V2Analyzer { + name: string; // "codeanalyzer-typescript" + version: string; // ANALYZER_VERSION (src/utils/version.ts) +} + export interface V2Root { id: string; // can:/// kind: "application"; diff --git a/test/schema-v2.test.ts b/test/schema-v2.test.ts index a33584e..7bf6463 100644 --- a/test/schema-v2.test.ts +++ b/test/schema-v2.test.ts @@ -103,6 +103,12 @@ describe("schema v2 — L1 envelope", () => { expect(key).not.toContain("\\"); } }); + + test("envelope carries analyzer{name,version}", () => { + expect(v2.analyzer?.name).toBe("codeanalyzer-typescript"); + expect(typeof v2.analyzer?.version).toBe("string"); + expect(v2.analyzer.version.length).toBeGreaterThan(0); + }); }); describe("schema v2 — L1 identity", () => { From 6ccab28142b0e5b47bd534137789fb0c6391444c Mon Sep 17 00:00:00 2001 From: Rahul Krishna Date: Tue, 7 Jul 2026 00:34:28 -0400 Subject: [PATCH 2/2] fix: correct ANALYZER_VERSION drift and pin envelope test to package.json ANALYZER_VERSION was "0.1.0" while package.json was "0.5.0", so the new analyzer{name,version} manifest advertised a false version. Bump it to match, and assert analyzer.version equals package.json's version (imported, not hardcoded) so future drift fails the schema-v2 gate. --- src/utils/version.ts | 2 +- test/schema-v2.test.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils/version.ts b/src/utils/version.ts index d2cd3e6..c33aa41 100644 --- a/src/utils/version.ts +++ b/src/utils/version.ts @@ -3,4 +3,4 @@ * the analyzer invalidates stale per-file Modules (whose source is unchanged but whose extracted * shape may differ across analyzer versions). */ -export const ANALYZER_VERSION = "0.1.0"; +export const ANALYZER_VERSION = "0.5.0"; diff --git a/test/schema-v2.test.ts b/test/schema-v2.test.ts index 7bf6463..6e151e3 100644 --- a/test/schema-v2.test.ts +++ b/test/schema-v2.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 { analyze } from "../src/core"; import type { AnalysisOptions } from "../src/options"; import type { GraphSelector, TSApplication } from "../src/schema"; @@ -106,8 +107,7 @@ describe("schema v2 — L1 envelope", () => { test("envelope carries analyzer{name,version}", () => { expect(v2.analyzer?.name).toBe("codeanalyzer-typescript"); - expect(typeof v2.analyzer?.version).toBe("string"); - expect(v2.analyzer.version.length).toBeGreaterThan(0); + expect(v2.analyzer?.version).toBe(pkg.version); }); });