Repository navigation
Description
Is your feature request related to a problem? Please describe.
Schema v2 is code-only: nothing represents package.json manifests, lockfiles, tsconfig/rc configs, Dockerfiles, CI workflows, or the dependencies an app declares. Python shipped the three-family answer (artifact / dependency / config_key contained under the application node, ungated at every level); TS emits none of it, so cross-analyzer artifact queries dead-end at this repo.
Describe the solution you'd like
- Model: TSArtifact / TSDependency / TSConfigKey mirroring python's shipped shapes field-for-field;
application.artifacts{}with contained children; ids stamped per-run by assignIds (@artifact/marker) -
src/artifacts/— walk (SKIP_DIRS, sorted) + rules table → artifact_kind/format; sha256 + size always; text capture under--artifact-text-max-bytes(256 KiB default, truncate+flag) - deps extraction: every package.json (workspaces included) → declared records with scope mapping incl. the coined additive
peertoken; JSON lockfile family (package-lock / npm-shrinkwrap / bun.lock) backfills resolved_version on declared records only - config extraction: .env-family flat keys (namespace "env") + JSON dotted keys
- Neo4j 2.2.0: :TSArtifact/:TSDependency/:TSConfigKey + TS_HAS_ARTIFACT/TS_DECLARES_DEPENDENCY/TS_DEFINES_CONFIG + constraints; schema.neo4j.json regen
- Wire gate: artifact content_hash MUST appear on the wire — restructure the internal-field strip so the module-cache trio's key names don't eat artifact fields
- Fixture app covering every format + level-invariance, conformance, determinism, Neo4j row tests; python-sdk TS-model extras-tolerance verified
Describe alternatives you've considered
Not stated in the original issue.
Additional context
Plan
docs/design/specs/artifacts-and-dependencies.md (committed on the work branch). Parity anchor: codeanalyzer-python's SHIPPED layer (51ee29e) — implementation over draft where they differ.
Scope boundary
Additive only: no existing field, id tier, or level moves; schema_version stays put (python precedent), Neo4j contract bumps additively to 2.2.0. NOT in scope: import→package binding / unresolved_imports / purl (not in python's shipped unit), transitive lockfile records (direct:false reserved), YAML parsing (yarn.lock/pnpm-lock/yaml configs are inventory-only artifacts), caching of the scan.
Caveats and known risks
- The strip-filter collision (module
content_hashinternal vs artifactcontent_hashwire) is called out in the spec — key-name stripping must become structural or scoped. TSArtifact.source= producing subsystem (python's field), colliding in NAME with module.source semantics — inherited parity, documented, not "fixed".- One shared-vocabulary token coined: dependency scope
peer— recorded in the spec + SCHEMA_DECISIONS; python's Literal grows when next touched. - yarn.lock / pnpm-lock.yaml ship as artifacts WITHOUT resolved_version — absence is the documented signal, not a parse failure.
Definition of done
Spec's DoD verbatim: identical artifacts at all levels; fixture asserts every format + peer scope + wire content_hash; Neo4j 2.2.0 rows + regen; two-run byte-identical determinism; suite/typecheck green; CLAUDE.md + SCHEMA_DECISIONS + README/--help updated.
Activity
docs(design): spec the repository-artifact layer, python parity (#101)
feat(schema): the repository-artifact layer — artifacts, dependencies…
docs(design): record the artifact-layer spec as implemented (#101)
feat(schema)!: recalibrate the artifact layer to python PR #160 (#101)
rahlk commentedon Aug 30, 2026
The python train is complete and released (codeanalyzer-python 1.3.0, 2026-08-29): artifacts + dependencies (#157/#160), ConfigKey family (#152/#163), the level-graded
config_useedge (#162/#164), and deployment-env namespaces (#165/#168). The epic (codellm-devkit/.github#45) now carries a "Contract as shipped" section — where this issue's original text follows the epic's older sketch, the shipped contract supersedes it. The load-bearing deltas:Artifact/Package/ConfigKey(shared MERGE targets across analyzers) — notJArtifact/TSArtifact-style triplets. Language-specific edges keep the prefix: your*_PROVIDES,*_UNRESOLVED_IMPORT,*_USES_CONFIG.can://artifact/<app>/<path>(neutral namespace); packages by purl (pkg:maven/…/pkg:npm/…); config keys<artifact-id>@key/<dotted.key>.--app-nameagreement is the join precondition.application.artifactssibling map, config keys nested per artifact; the code tree stays code-only.roles: string[](never-drop inventory: unmatched decodable →unknown, binaries hash-only), not a closedartifact_kindenum.kind{runtime, dev, optional, build},prov{declared, lockfile, installed-metadata, heuristic},direct: falsefor lockfile-only transitives,locked_version.--artifact-text/--no-artifact-text,--artifact-text-max-bytes; extraction parses full on-disk text, never the stored copy.ENV, compose/k8senv) mint bindableenvkeys, DockerfileARGa non-bindabledockerfilenamespace.SCHEMA_VERSIONstays 2.0.0 until the layer settles across all analyzers.Copy-from reference: the three specs in codeanalyzer-python
docs/design/specs/(2026-08-27 artifacts, 2026-08-28 config-key family, 2026-08-28 config-use edge) and the v1.3.0 release assets —schema.json+schema.cypherare the machine-readable contract;analyzing-canpy-graphs-skill.tar.gzdocuments the query surface the layer should support.Your plan already anchors on the shipped python layer (51ee29e) — note the anchor has since moved: 1.3.0 additionally landed the level-graded
config_usetiers, deployment-env namespaces,direct: falsetransitives, and the text-capture controls, so re-sync the parity anchor to the v1.3.0 tag rather than that commit. TS-specific:package.jsondev/peer/optional map ontokind{dev, optional}; purlpkg:npm/<name>; tsconfig JSONC tolerance is your analogue of our overlay posture (parse failure → artifact kept,extraction: "partial").docs(design): spec the artifact layer at python v1.3.0 parity (#101)
docs(design): require the consumer query skill, with decision guidance (
docs(plan): implementation plan for the v1.3.0 artifact layer (#101)
feat(artifacts): text-capture policy — flags, cap, text_truncated (#101)
feat(artifacts): never-drop inventory — unknown roles, binary hash-on…
feat(artifacts): lockfile transitives as direct:false records (#101)
feat(artifacts): ConfigKey family — env/JSONC/ini extraction, key ids (…
fix(artifacts): gate config-key extraction on dependency-manifest role (
fix(artifacts): make parseJsonc's trailing-comma strip string-aware (#…
5 remaining items
feat(artifacts): deployment-env keys — Dockerfile ENV/ARG, compose, k…
fix(schema): disambiguate config-key ids across namespace dual-mints (#…
fix(artifacts): mint bare compose list env entries, python v1.3.0 par…
feat(schema): config_access body nodes for env reads (#101)
test(schema): pin config_access ctor attribution and key disambiguati…
feat(callgraph): config_use literal tier + first-class unresolved rea…
fix(callgraph): assert config-use invariants for real, not by id-suff…
test(callgraph): make the ARG-never-bindable guard live, not vacuous (#…
feat(dataflow): config_use intra + interprocedural tiers (#101)
fix(dataflow): catch destructuring reassignment in config_use widening (
feat(neo4j): ConfigKey/DEFINES_CONFIG/TS_USES_CONFIG; revert the vers…
docs: consumer query skill + artifact-layer docs (#101)
fix(schema): tolerate a same-version cache missing config_accesses/ca…
docs: put the measured transitive-dependency split into the skill (#101)
feat(callgraph)!: defuse linker, propagation tiers, and the repositor…