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.
Problem
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.
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.
Goals
Caveats and known risks
- The strip-filter collision (module
content_hash internal vs artifact content_hash wire) 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.
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.
Problem
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.
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.
Goals
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)peertoken; JSON lockfile family (package-lock / npm-shrinkwrap / bun.lock) backfills resolved_version on declared records onlyCaveats and known risks
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".peer— recorded in the spec + SCHEMA_DECISIONS; python's Literal grows when next touched.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.