graphrag-codeproperty-graph 0.5.1__tar.gz → 0.5.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/CHANGELOG.md +17 -0
  2. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/PKG-INFO +1 -1
  3. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/pyproject.toml +1 -1
  4. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/src/codeproperty_graph/vector_loader.py +22 -4
  5. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/tests/test_delta_ingestor_embedding_property.py +58 -0
  6. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/.github/workflows/publish.yml +0 -0
  7. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/.gitignore +0 -0
  8. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/CONTRIBUTING.md +0 -0
  9. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/LICENSE +0 -0
  10. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/NOTICE +0 -0
  11. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/README.md +0 -0
  12. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/docs/ARCHITECTURE.md +0 -0
  13. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/docs/Defining the Master Evidence Graph: A Formal Model for Stateful Software Verdicts.md +0 -0
  14. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/docs/HYBRID-GRAPH.md +0 -0
  15. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/docs/NOTICE.md +0 -0
  16. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/docs/Toward a Master Evidence Graph for Software Verdicts.md +0 -0
  17. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/docs/graphrag_com_redrawn_architecture.md +0 -0
  18. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/docs/graphrag_phased_architecture.md +0 -0
  19. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/docs/neptune_vs_neptune_analytics_cpg_rag_architecture copy.md +0 -0
  20. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/docs/neptune_vs_neptune_analytics_cpg_rag_architecture.md +0 -0
  21. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/examples/README.md +0 -0
  22. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/examples/notebooks/01-CPG-Models-and-GraphDiff.ipynb +0 -0
  23. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/examples/notebooks/02-Delta-Ingestion-Pipeline.ipynb +0 -0
  24. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/examples/notebooks/data/sample_edges.json +0 -0
  25. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/examples/notebooks/data/sample_nodes.json +0 -0
  26. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/sbom/AWS-SERVICES.md +0 -0
  27. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/sbom/SBOM.md +0 -0
  28. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/sbom/codeproperty-graph.cdx.json +0 -0
  29. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/src/codeproperty_graph/__init__.py +0 -0
  30. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/src/codeproperty_graph/artifact_reader.py +0 -0
  31. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/src/codeproperty_graph/artifact_validator.py +0 -0
  32. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/src/codeproperty_graph/code_slice_store.py +0 -0
  33. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/src/codeproperty_graph/cpg_service.py +0 -0
  34. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/src/codeproperty_graph/delta_ingestor.py +0 -0
  35. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/src/codeproperty_graph/graph_diff.py +0 -0
  36. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/src/codeproperty_graph/graph_loader.py +0 -0
  37. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/src/codeproperty_graph/graphson_converter.py +0 -0
  38. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/src/codeproperty_graph/manifest_manager.py +0 -0
  39. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/src/codeproperty_graph/models.py +0 -0
  40. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/src/codeproperty_graph/schema.py +0 -0
  41. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/src/codeproperty_graph/summary_overlay.py +0 -0
  42. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/src/codeproperty_graph/tenant_ops.py +0 -0
  43. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/tests/__init__.py +0 -0
  44. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/tests/test_codeproperty_graph.py +0 -0
  45. {graphrag_codeproperty_graph-0.5.1 → graphrag_codeproperty_graph-0.5.2}/tests/test_cpg_service.py +0 -0
@@ -2,6 +2,23 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.5.2] - 2026-09-16
6
+
7
+ ### Fixed
8
+ - **`VectorLoader` no longer writes the raw embedding vector as a Neptune node
9
+ property.** The 0.5.1 on-node write (`SET n += {embedding: <array>, ...}`) was a
10
+ Neo4j-era pattern: Neo4j stores list-valued properties, but the graph backend is
11
+ now Neptune Database, whose openCypher rejects arrays ("Property value must be a
12
+ simple literal"). Every per-node write failed with `BadRequestException`, flooding
13
+ the ingest log with warnings. The embedding **vector** already lives in the vector
14
+ store (AOSS/OpenSearch), which is the sole surface used for kNN retrieval — nothing
15
+ reads the on-node vector. `VectorLoader.load` now writes only **scalar embedding
16
+ provenance** to the node (`hasEmbedding`, `embeddingModel`, `embeddingDimensions`,
17
+ `embeddingTarget`, `embeddedTime`), which Neptune accepts, preserving the
18
+ graph-side "this node has an embedding" signal without duplicating unqueryable data.
19
+ Covered by `tests/test_delta_ingestor_embedding_property.py`
20
+ (`test_vector_loader_writes_scalar_provenance_not_array`). (PSAPI-66782.)
21
+
5
22
  ## [0.5.1] - 2026-09-15
6
23
 
7
24
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: graphrag-codeproperty-graph
3
- Version: 0.5.1
3
+ Version: 0.5.2
4
4
  Summary: Code Property Graphs — Joern/Semgrep extraction, AI vulnerability enrichment, risk scoring
5
5
  Project-URL: Repository, https://github.com/kanjani-ai-research/codeproperty-graph
6
6
  Author-email: Evan Erwee <evan@erwee.com>
@@ -7,7 +7,7 @@ packages = ["src/codeproperty_graph"]
7
7
 
8
8
  [project]
9
9
  name = "graphrag-codeproperty-graph"
10
- version = "0.5.1"
10
+ version = "0.5.2"
11
11
  description = "Code Property Graphs — Joern/Semgrep extraction, AI vulnerability enrichment, risk scoring"
12
12
  readme = "README.md"
13
13
  requires-python = ">=3.11"
@@ -163,7 +163,17 @@ class VectorLoader:
163
163
  result.total_loaded += count
164
164
  logger.info(f"Loaded {count} vectors for target '{target}'")
165
165
 
166
- # Also write embedding as a node property on Neptune (client schema conformance)
166
+ # Write embedding PROVENANCE (scalar metadata) onto the graph node.
167
+ #
168
+ # The embedding VECTOR itself lives in the vector store (AOSS/OpenSearch),
169
+ # which is the sole surface used for kNN retrieval. We deliberately do NOT
170
+ # write the raw vector as a node property: the original Neo4j schema stored
171
+ # `SET n.embedding = <array>` (Neo4j supports list-valued properties), but
172
+ # the graph backend here is Neptune Database, whose openCypher rejects
173
+ # array/list property values ("Property value must be a simple literal").
174
+ # Storing scalar provenance (model, dimensions, timestamp, presence flag)
175
+ # keeps the "this node has an embedding" graph-side signal — queryable and
176
+ # filterable — without duplicating the vector where nothing reads it.
167
177
  if self._graph_store and records:
168
178
  written = 0
169
179
  for raw in records:
@@ -171,13 +181,21 @@ class VectorLoader:
171
181
  try:
172
182
  await self._graph_store.update_node_properties(
173
183
  record.cpg_node_id,
174
- {"embedding": record.vector, "embeddedTime": record.metadata.get("embedded_time", "")},
184
+ {
185
+ "hasEmbedding": True,
186
+ "embeddingModel": record.embedding_model,
187
+ "embeddingDimensions": (
188
+ record.embedding_dimensions or len(record.vector)
189
+ ),
190
+ "embeddingTarget": record.embedding_target,
191
+ "embeddedTime": record.metadata.get("embedded_time", ""),
192
+ },
175
193
  )
176
194
  written += 1
177
195
  except Exception as e:
178
- logger.debug(f"Failed to write embedding property for {record.cpg_node_id}: {e}")
196
+ logger.debug(f"Failed to write embedding provenance for {record.cpg_node_id}: {e}")
179
197
  if written:
180
- logger.info(f"Wrote embedding property to {written} Neptune nodes")
198
+ logger.info(f"Wrote embedding provenance to {written} Neptune nodes")
181
199
 
182
200
  if result.errors:
183
201
  logger.warning(f"Encountered {len(result.errors)} validation errors during load")
@@ -69,3 +69,61 @@ async def test_vector_loader_receives_graph_store():
69
69
  )
70
70
  # And it should be the SAME store GraphLoader got.
71
71
  assert GL.call_args.kwargs.get("graph_store") is graph_store
72
+
73
+
74
+ # ─── Wave (Neptune fix): on-node write must be SCALAR provenance, not the array ──
75
+ #
76
+ # Neptune Database openCypher rejects list/array property values ("Property value
77
+ # must be a simple literal"). The raw embedding vector lives in the vector store
78
+ # (AOSS); the graph node must carry only scalar provenance. This test drives
79
+ # VectorLoader.load directly and asserts what actually reaches update_node_properties.
80
+
81
+ from codeproperty_graph import VectorLoader
82
+
83
+
84
+ @pytest.mark.asyncio
85
+ async def test_vector_loader_writes_scalar_provenance_not_array():
86
+ graph_store = MagicMock(name="neptune_store")
87
+ graph_store.update_node_properties = AsyncMock(return_value=True)
88
+
89
+ vector_store = MagicMock(name="opensearch_store")
90
+ vector_store.put_vectors = AsyncMock(return_value=1)
91
+
92
+ loader = VectorLoader(vector_store=vector_store, graph_store=graph_store)
93
+
94
+ records = [{
95
+ "cpg_node_id": "n1",
96
+ "embedding_target": "class_summary",
97
+ "vector": [0.1] * 768,
98
+ "text": "summary text",
99
+ "embedding_model": "nomic-embed-text",
100
+ "embedding_dimensions": 768,
101
+ "metadata": {"embedded_time": "2026-09-16T07:50:43Z"},
102
+ }]
103
+
104
+ await loader.load(records)
105
+
106
+ # The on-node write must have happened...
107
+ assert graph_store.update_node_properties.await_count == 1
108
+ node_id, props = graph_store.update_node_properties.await_args.args
109
+
110
+ assert node_id == "n1"
111
+ # ...and it must NOT include the raw vector array (the Neptune-rejecting bug).
112
+ assert "embedding" not in props, (
113
+ "VectorLoader must not write the raw embedding array to the Neptune node "
114
+ "(Neptune Database rejects list-valued properties)"
115
+ )
116
+ # ...every value written must be a Neptune-safe scalar literal.
117
+ for key, value in props.items():
118
+ assert not isinstance(value, (list, dict, tuple, set)), (
119
+ f"Node property {key!r} must be a scalar literal, got {type(value).__name__}"
120
+ )
121
+ # ...and the useful provenance is present.
122
+ assert props["hasEmbedding"] is True
123
+ assert props["embeddingModel"] == "nomic-embed-text"
124
+ assert props["embeddingDimensions"] == 768
125
+ assert props["embeddingTarget"] == "class_summary"
126
+ assert props["embeddedTime"] == "2026-09-16T07:50:43Z"
127
+
128
+ # The VECTOR itself still goes to the vector store (AOSS).
129
+ assert vector_store.put_vectors.await_count >= 1