Spec
docs/design/specs/repository-artifact-layer.md (committed in codellm-devkit/.github)
Summary
Adds a repository-artifact layer to canonical schema v2 across the three analyzers: the producer-side evidence a cross-service / whole-application analysis needs but no analyzer emits today. Schema impact is additive — three new application-contained node kinds (artifact, dependency, config_key), one new typed edge (config_use / *_USES_CONFIG), their Neo4j projections, and one shared scope enum with its ecosystem mapping table. Nothing existing is renamed or repurposed. This is roadmap group D (candidates 15–18); it lands into the v2 catalog group A stands up, so group A gates it.
Affected repos
codeanalyzer-schema — v2 model definitions (three node kinds + config_use edge + scope mapping table), Neo4j contract projection. Gates all analyzers.
codeanalyzer-python — :PyArtifact / :PyDependency / :PyConfigKey emitter, non-source discovery walk, pyproject.toml / requirements* / lockfile parsing, PY_USES_CONFIG
codeanalyzer-typescript — :TSArtifact / :TSDependency / :TSConfigKey, package.json (incl. dev/peer/optional) + lockfiles, tsconfig.json JSONC tolerance, TS_USES_CONFIG
codeanalyzer-java — :JArtifact / :JDependency / :JConfigKey, pom.xml / Gradle coordinate parsing (net-new), config_use in analysis.json (Neo4j J_USES_CONFIG deferred)
python-sdk — v2 Pydantic model mirror (co-evolution rule); facade surface exposure is later, out of scope here
Design decisions
- Artifacts are first-class nodes in the containment tree, not top-level sibling maps. The canonical keystone allows one node vocabulary reachable from
application by containment; sibling maps would introduce a second. This is a strict superset of the source proposal — the two string back-references (dependency→manifest, config→file) become containment edges, artifacts get durable can://…/@artifact/… ids, and the JSON matches the Neo4j graph the source doc already drew.
artifact_kind is a typed closed enum (build_manifest | dependency_lockfile | configuration | deployment_manifest | container | infrastructure | ci | script | documentation | data | other). other is the catch-all — coverage over classification; a file is never dropped for lack of a parser.
- Raw text captured by default, 256 KiB cap,
--artifact-text / --no-artifact-text flag; path + content_hash always present so a truncated/binary artifact still dereferences. Emit contract, not schema-versioned.
scope enum + ecosystem mapping table are coined once in the schema, not per-analyzer: runtime | development | test | build | optional | unknown, with the Maven/npm/pypi mapping in the contract.
config_use (candidate 18) is scoped in with a per-projection split, not deferred whole. The edge name and its (namespace, key) join are identical across all three languages and both projections. analysis.json carries it for all three; Neo4j carries PY_USES_CONFIG + TS_USES_CONFIG now.
- Scope guard:
J_USES_CONFIG (Java's Neo4j config-use edge) is explicitly OUT — Java's Neo4j projector has no body-node label until its v1→v2 migration (candidate 9). SDK facade/query surface for the artifact layer is OUT (later). This spec implements no analyzer — that is the codeanalyzer-backend rung, per repo, after the epic exists.
Release plan
codeanalyzer-schema lands first — the v2 models, config_use edge, scope table, Neo4j contract. Gates everything.
- The three analyzers implement in parallel, each on its own release train — none gates another. Per analyzer, units (artifact inventory → dependencies → config definitions → config uses) may land as separate PRs.
python-sdk mirrors the v2 models after any ONE analyzer is conformant — it does not wait for all three.
J_USES_CONFIG rides Java's candidate-9 v1→v2 Neo4j migration, not this epic. Java's analysis.json carries the config_use facts meanwhile; the projection-parity gate records the Java-Neo4j edge as a known, quantified gap.
- Blocked by group A (the v2 catalog these node kinds land into must exist first).
Definition of done (epic-level)
- Every sub-issue closed and its PR's gate green.
artifact / dependency / config_key node kinds and the config_use edge defined once in codeanalyzer-schema with identical field names, enum values, and edge payload across python / java / typescript (parity clause holds — no renamed/repurposed shared vocabulary).
- The
scope enum and its ecosystem mapping table are encoded in the schema, not per-analyzer.
- Each analyzer's output validates against the v2 models;
analysis.json round-trips through the schema for all three languages.
PY_USES_CONFIG and TS_USES_CONFIG present in Neo4j; J_USES_CONFIG recorded as a known gap by the projection-parity gate, not silently absent.
python-sdk v2 models mirror the three node kinds and the edge.
- Existing source/program-graph behavior unchanged; docs / CHANGELOG updated.
Spec
docs/design/specs/repository-artifact-layer.md(committed incodellm-devkit/.github)Summary
Adds a repository-artifact layer to canonical schema v2 across the three analyzers: the producer-side evidence a cross-service / whole-application analysis needs but no analyzer emits today. Schema impact is additive — three new application-contained node kinds (
artifact,dependency,config_key), one new typed edge (config_use/*_USES_CONFIG), their Neo4j projections, and one sharedscopeenum with its ecosystem mapping table. Nothing existing is renamed or repurposed. This is roadmap group D (candidates 15–18); it lands into the v2 catalog group A stands up, so group A gates it.Affected repos
codeanalyzer-schema— v2 model definitions (three node kinds +config_useedge +scopemapping table), Neo4j contract projection. Gates all analyzers.codeanalyzer-python—:PyArtifact/:PyDependency/:PyConfigKeyemitter, non-source discovery walk,pyproject.toml/requirements*/ lockfile parsing,PY_USES_CONFIGcodeanalyzer-typescript—:TSArtifact/:TSDependency/:TSConfigKey,package.json(incl. dev/peer/optional) + lockfiles,tsconfig.jsonJSONC tolerance,TS_USES_CONFIGcodeanalyzer-java—:JArtifact/:JDependency/:JConfigKey,pom.xml/ Gradle coordinate parsing (net-new),config_useinanalysis.json(Neo4jJ_USES_CONFIGdeferred)python-sdk— v2 Pydantic model mirror (co-evolution rule); facade surface exposure is later, out of scope hereDesign decisions
applicationby containment; sibling maps would introduce a second. This is a strict superset of the source proposal — the two string back-references (dependency→manifest, config→file) become containment edges, artifacts get durablecan://…/@artifact/…ids, and the JSON matches the Neo4j graph the source doc already drew.artifact_kindis a typed closed enum (build_manifest | dependency_lockfile | configuration | deployment_manifest | container | infrastructure | ci | script | documentation | data | other).otheris the catch-all — coverage over classification; a file is never dropped for lack of a parser.--artifact-text/--no-artifact-textflag;path+content_hashalways present so a truncated/binary artifact still dereferences. Emit contract, not schema-versioned.scopeenum + ecosystem mapping table are coined once in the schema, not per-analyzer: runtime | development | test | build | optional | unknown, with the Maven/npm/pypi mapping in the contract.config_use(candidate 18) is scoped in with a per-projection split, not deferred whole. The edge name and its (namespace,key) join are identical across all three languages and both projections.analysis.jsoncarries it for all three; Neo4j carriesPY_USES_CONFIG+TS_USES_CONFIGnow.J_USES_CONFIG(Java's Neo4j config-use edge) is explicitly OUT — Java's Neo4j projector has no body-node label until its v1→v2 migration (candidate 9). SDK facade/query surface for the artifact layer is OUT (later). This spec implements no analyzer — that is the codeanalyzer-backend rung, per repo, after the epic exists.Release plan
codeanalyzer-schemalands first — the v2 models,config_useedge,scopetable, Neo4j contract. Gates everything.python-sdkmirrors the v2 models after any ONE analyzer is conformant — it does not wait for all three.J_USES_CONFIGrides Java's candidate-9 v1→v2 Neo4j migration, not this epic. Java'sanalysis.jsoncarries theconfig_usefacts meanwhile; the projection-parity gate records the Java-Neo4j edge as a known, quantified gap.Definition of done (epic-level)
artifact/dependency/config_keynode kinds and theconfig_useedge defined once incodeanalyzer-schemawith identical field names, enum values, and edge payload across python / java / typescript (parity clause holds — no renamed/repurposed shared vocabulary).scopeenum and its ecosystem mapping table are encoded in the schema, not per-analyzer.analysis.jsonround-trips through the schema for all three languages.PY_USES_CONFIGandTS_USES_CONFIGpresent in Neo4j;J_USES_CONFIGrecorded as a known gap by the projection-parity gate, not silently absent.python-sdkv2 models mirror the three node kinds and the edge.