Skip to content

Neo4j projection omits import/export bindings, callable parameters, and config-read edges #182

Description

@rahlk

Problem

Three gaps in the Neo4j projection, each of which makes a python-sdk accessor refuse rather than answer. All three are recoverable from data the analyzer already computes for analysis.json. Measured on main @ 2064b6b (cants on itself: 139 modules, 1008 callables):

gap analysis.json graph
1. import / export bindings 801 imports, 67 exports none — get_imports() / get_exports() refuse
2. callable parameters 1546 parameters on 970 callables none — get_method_parameters() refuses over Neo4j, answers in process
3. unresolved config reads config_reads 10 (artifacts-app, -a 2) none — TS_USES_CONFIG (resolved reads, :TSBodyNode → :ConfigKey) IS projected; only the unresolved counterpart is missing

Row 3 corrects this issue as first filed: TypeScript does not emit DEFINES_CONFIG alone.

language config relationship types
Python DEFINES_CONFIG, PY_USES_CONFIG, PY_READS_CONFIG_UNRESOLVED
TypeScript DEFINES_CONFIG, TS_USES_CONFIG
Java DEFINES_CONFIG (codeanalyzer-java#231)

Design

Spec: docs/design/specs/neo4j-bindings-parameters-config.md (decisions D1–D6, also in .claude/SCHEMA_DECISIONS.md). Additive on Neo4j contract 2.0.0; ships in 1.4.0.

Scope boundary

In scope: the three rows above. Out of scope: #179 (:TSCallable.code one line short), #180 (structuredClone ceiling), #181 (exit code on failure), #177 (declaration merging) — all filed separately.

Goals

  • D1 resolved_module on TSImport / re-export TSExport (ts-morph resolution at build time)
  • D2 TS_IMPORTS aggregated per (importer, target): spellings[], imported_names[], aliases[], type_only_names[]; externals to the @external/<root> ghost
  • D3 exports_json on :TSModule + TS_RE_EXPORTS aggregated like D2
  • D4 parameters_json on :TSCallable, python encoding, null when empty
  • D5 TS_READS_CONFIG_UNRESOLVED :TSApplication → :TSExternal | :TSCallable, _k = key|reason
  • schema.ts + regenerated schema.neo4j.json; conformance, edge-identity and bolt tests
  • consumer skill docs/skills/analyzing-cants-graphs/ documents the three query shapes

Caveats and known risks

  • Parity clause: python fixes the vocabulary for D2/D4/D5; D3 is coined here (no sibling has ES-module exports). Java #231 must spell JAVA_READS_CONFIG_UNRESOLVED the same way.
  • Size cost (measured): full python-shape parameters_json = 430 KB on cants self = 1.4 % of graph.cypher. Accepted over a minimal shape (148 KB) to avoid a second parameter vocabulary.
  • TS_READS_CONFIG_UNRESOLVED inherits python's per-site collapse (_k = key|reason, no site): counts differ from analysis.json, presence/absence agrees.
  • Declaration merging mints one can:// id for a value and a type of the same name; the Neo4j MERGE collapses them into one node #177: parameters_json is a property on the existing node, so a merged value/type node keeps the last writer's list exactly as it keeps the last writer's kind — not worsened, not fixed.

Definition of done

  • The three python-sdk accessors that refuse on a TypeScript graph answer, with no SDK change beyond reading the new data (the SDK's reconstruct.callable_ already decodes parameters_json), and the SDK's documented tolerances for them can be deleted.
  • Snapshot on test/fixtures/sample-app shows TS_IMPORTS to :TSModule for the four relative specifiers and to ghosts for commander, neo4j-driver, node:*; artifacts-app shows one TS_READS_CONFIG_UNRESOLVED per distinct (callee, key, reason) in config_reads.
  • L1 ⊆ L2 ⊆ L3 ⊆ L4 gate green; bun test green; schema.neo4j.json regenerated.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions