victor-codegraph 0.8.1__tar.gz → 0.10.0__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 (53) hide show
  1. victor_codegraph-0.10.0/PKG-INFO +174 -0
  2. victor_codegraph-0.10.0/README.md +143 -0
  3. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/pyproject.toml +19 -15
  4. victor_codegraph-0.10.0/tests/test_adapter_validation_v2.py +42 -0
  5. victor_codegraph-0.10.0/tests/test_chunk_contract_v2.py +75 -0
  6. victor_codegraph-0.10.0/tests/test_diagnostics_v2.py +26 -0
  7. victor_codegraph-0.10.0/tests/test_embedding_contract.py +145 -0
  8. victor_codegraph-0.10.0/tests/test_identity_v2.py +121 -0
  9. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/tests/test_python_parser.py +19 -3
  10. victor_codegraph-0.10.0/tests/test_relations_v2.py +491 -0
  11. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/tests/test_repo.py +1 -0
  12. victor_codegraph-0.10.0/tests/test_repository_delta_v2.py +46 -0
  13. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/tests/test_symbol_oid_parity.py +1 -1
  14. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/tests/test_treesitter_relations.py +3 -2
  15. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/victor_codegraph/__init__.py +42 -2
  16. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/victor_codegraph/adapter.py +142 -17
  17. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/victor_codegraph/config.py +11 -0
  18. victor_codegraph-0.10.0/victor_codegraph/embeddings.py +196 -0
  19. victor_codegraph-0.10.0/victor_codegraph/javascript_repository.py +164 -0
  20. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/victor_codegraph/model.py +101 -1
  21. victor_codegraph-0.10.0/victor_codegraph/parser.py +329 -0
  22. victor_codegraph-0.10.0/victor_codegraph/py.typed +0 -0
  23. victor_codegraph-0.10.0/victor_codegraph/python_parser.py +396 -0
  24. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/victor_codegraph/repo.py +15 -6
  25. victor_codegraph-0.10.0/victor_codegraph/repository_index.py +460 -0
  26. victor_codegraph-0.10.0/victor_codegraph/resolution.py +209 -0
  27. victor_codegraph-0.10.0/victor_codegraph/rust_repository.py +236 -0
  28. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/victor_codegraph/sizing.py +64 -52
  29. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/victor_codegraph/treesitter_parser.py +236 -25
  30. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/victor_codegraph/treesitter_tables.py +2 -0
  31. victor_codegraph-0.10.0/victor_codegraph.egg-info/PKG-INFO +174 -0
  32. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/victor_codegraph.egg-info/SOURCES.txt +12 -0
  33. victor_codegraph-0.10.0/victor_codegraph.egg-info/requires.txt +16 -0
  34. victor_codegraph-0.8.1/PKG-INFO +0 -107
  35. victor_codegraph-0.8.1/README.md +0 -77
  36. victor_codegraph-0.8.1/victor_codegraph/parser.py +0 -122
  37. victor_codegraph-0.8.1/victor_codegraph/python_parser.py +0 -253
  38. victor_codegraph-0.8.1/victor_codegraph/resolution.py +0 -68
  39. victor_codegraph-0.8.1/victor_codegraph.egg-info/PKG-INFO +0 -107
  40. victor_codegraph-0.8.1/victor_codegraph.egg-info/requires.txt +0 -13
  41. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/setup.cfg +0 -0
  42. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/tests/test_adapter.py +0 -0
  43. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/tests/test_line_base_contract.py +0 -0
  44. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/tests/test_manifest.py +0 -0
  45. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/tests/test_sizing_and_chunk.py +0 -0
  46. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/tests/test_sizing_overlap.py +0 -0
  47. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/tests/test_symbol_oid_contract.py +0 -0
  48. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/tests/test_treesitter_jsts.py +0 -0
  49. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/tests/test_treesitter_languages.py +0 -0
  50. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/victor_codegraph/languages.py +0 -0
  51. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/victor_codegraph/manifest.py +0 -0
  52. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/victor_codegraph.egg-info/dependency_links.txt +0 -0
  53. {victor_codegraph-0.8.1 → victor_codegraph-0.10.0}/victor_codegraph.egg-info/top_level.txt +0 -0
@@ -0,0 +1,174 @@
1
+ Metadata-Version: 2.4
2
+ Name: victor-codegraph
3
+ Version: 0.10.0
4
+ Summary: Repository-to-Code-Semantic-Graph compiler with stable identity, bounded chunks, incremental deltas, and ProximaRecord projection.
5
+ Author-email: Vijaykumar Singh <vijay@anvaiops.com>
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/anvai-labs/victor
8
+ Project-URL: Repository, https://github.com/anvai-labs/victor
9
+ Keywords: code-graph,cpg,semantic-graph,chunking,tree-sitter,ast,embeddings,rag
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: Apache Software License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Topic :: Software Development :: Libraries
17
+ Requires-Python: >=3.12
18
+ Description-Content-Type: text/markdown
19
+ Provides-Extra: embeddings
20
+ Requires-Dist: sentence-transformers<6,>=3; extra == "embeddings"
21
+ Provides-Extra: treesitter
22
+ Requires-Dist: tree-sitter>=0.26.0; extra == "treesitter"
23
+ Requires-Dist: tree-sitter-language-pack>=1.21.3; extra == "treesitter"
24
+ Provides-Extra: contracts
25
+ Requires-Dist: victor-contracts<1.0,>=0.9.1; extra == "contracts"
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest>=9.1.1; extra == "dev"
28
+ Requires-Dist: ruff>=0.16.7; extra == "dev"
29
+ Requires-Dist: tree-sitter>=0.26.0; extra == "dev"
30
+ Requires-Dist: tree-sitter-language-pack>=1.21.3; extra == "dev"
31
+
32
+ # victor-codegraph
33
+
34
+ Shared **repository → Code Semantic Graph compiler**: symbol and relation extraction,
35
+ hard-bounded embeddable chunks, repository-wide resolution/deltas, diagnostics, and a
36
+ `ProximaRecord` projection. One compiler, three
37
+ consumers — Victor (owner), the ProximaDB SDK (`[codegraph]` extra), and AnvaiOps (SaaS
38
+ code-graph vertical).
39
+
40
+ > Design: ProximaDB `ADR-029` (authoritative) · Victor `ADR-014` (owner/donor) ·
41
+ > AnvaiOps `ADR-0018` (consumer). This package is the **TD-CG1** scaffold.
42
+
43
+ ## Why
44
+
45
+ The same tree-sitter code→symbol+relation chunker existed twice (ProximaDB SDK `code.py`
46
+ and Victor `victor-coding`) and was about to be written a third time in AnvaiOps. This
47
+ package is the single neutral home. It merges the best of both donors and fixes their two
48
+ gaps:
49
+
50
+ - **Size-capping** — ProximaDB's `code.py` emitted one chunk per symbol with *no* size
51
+ bound (a huge function became a huge chunk). Here, oversized symbols are body-split with
52
+ overlap (LlamaIndex `CodeSplitter` discipline). See `sizing.py`.
53
+ - **Real JS/TS** — the donor JS/TS parser was a stub returning no symbols. Here JS/TS get a
54
+ real tree-sitter extractor (functions, classes, methods, `const … = () =>`, imports).
55
+
56
+ ## Install
57
+
58
+ Published on PyPI as [`victor-codegraph`](https://pypi.org/project/victor-codegraph/).
59
+ This source tree is version **0.10.0**; consumers should use a compatible `<1.0` pin.
60
+
61
+ ```bash
62
+ # from PyPI
63
+ pip install victor-codegraph # Python-only (stdlib ast) path, zero native deps
64
+ pip install "victor-codegraph[treesitter]" # + multi-language tree-sitter grammars
65
+
66
+ # dev (monorepo): editable, with tree-sitter grammars + test tooling
67
+ make -C victor-codegraph dev # = pip install -e ../victor-contracts && pip install -e ".[dev]"
68
+ pip install -e ./victor-codegraph # minimal editable install
69
+ ```
70
+
71
+ ### Releasing
72
+
73
+ CI: `.github/workflows/ci-codegraph.yml` runs the suite (editable install, grammars on) for every
74
+ PR touching `victor-codegraph/**`. Publishing: push a tag `victor-codegraph-v0.1.0` to trigger
75
+ `.github/workflows/release-codegraph.yml`, which builds and publishes via **PyPI Trusted Publishing**
76
+ (OIDC — no API token). Configure the publisher once on PyPI (owner `vjsingh1984`, repo `victor`,
77
+ workflow `release-codegraph.yml`, environments `pypi` / `testpypi`); see the header of that workflow.
78
+
79
+ ## 0.9 consumer qualification and migration
80
+
81
+ | Surface | Contract / limit |
82
+ |---|---|
83
+ | Python references | Exact import aliases and dotted modules; lexical scope precedes arity. Unknown receivers, wildcard ambiguity and shadowed bindings remain explicit unresolved references. No runtime execution/type inference. |
84
+ | ES modules | Relative named/default/namespace imports, explicit named re-exports and exported arrow functions. Type-only imports produce dependencies, never runtime call evidence. Re-export traversal is cycle-safe and bounded to 64 bindings. Package/tsconfig aliases, star exports and dynamic exports remain unresolved. |
85
+ | Object-literal identity | Methods include structural object scopes, including anonymous callback ancestry. Whitespace/comments and checkout root do not affect IDs; inserting/reordering anonymous siblings can change structural ordinals. |
86
+ | Source evidence | Python call spans include UTF-8 byte offsets/lengths and end coordinates. New binding metadata is diagnostic evidence, not runtime authorization or a complete language semantic model. |
87
+ | Victor persistence | The canonical snapshot supplies symbols. CLI distinguishes attempted upserts from persisted totals, exposes partial parses and accepts exact opaque IDs; ambiguous display names are not chosen arbitrarily. Default file exclusions can differ from the package walker. |
88
+
89
+ Rebuild derived indexes after upgrading from older parser versions; an unchanged
90
+ source hash alone does not migrate older IDs/edges. Victor users can run
91
+ `victor graph index --force --no-ccg --no-embeddings`. Consumers must stage a new
92
+ complete generation and switch readers after validation; never mix old and new
93
+ symbol identities. The AnvaiOps adapter/generation migration remains consumer-owned.
94
+ The package adds no commercial runtime, account, entitlement or billing dependency.
95
+
96
+
97
+ ## Use
98
+
99
+ ```python
100
+ from victor_codegraph import chunk, parse, parse_repo, to_proxima_records, ChunkConfig
101
+
102
+ # Size-capped, embeddable chunks:
103
+ chunks = chunk(source, file_path="app/service.py", config=ChunkConfig(max_chunk_tokens=512))
104
+
105
+ # Symbols + relations:
106
+ parsed = parse(source, file_path="app/service.py")
107
+
108
+ # Project to the ProximaDB substrate-keystone record shape (one symbol = row+node+vector):
109
+ records = to_proxima_records(parsed, repo_graph_id="myrepo", branch_id="main",
110
+ embedder=my_embed_fn) # embedder optional
111
+
112
+ # Repository-wide resolution + file/import/containment graph:
113
+ repository = parse_repo(".", repo_id="myrepo")
114
+ records = to_proxima_records(repository, repo_graph_id="myrepo")
115
+ ```
116
+
117
+ ## Design principles (the "best posture" this encodes)
118
+
119
+ 1. Chunk at **symbol** granularity (not statement, not fixed-size).
120
+ 2. **Newline-preferred and hard-bounded** — forced character splits are explicit; an optional
121
+ tokenizer callback enforces the real model limit.
122
+ 3. Extract a **Code Semantic Graph** (CALLS/EXTENDS/IMPLEMENTS/CONTAINS/IMPORTS). Full
123
+ intra-procedural CFG/CDG/DDG is a separate optional layer, not implied here.
124
+ 4. **One structural v2 ID** across symbols, chunks, relations, and records; line IDs remain aliases.
125
+ 5. **Deletion-complete deltas** — incremental output can be checked against a full rebuild.
126
+ 6. **Observable fallback** — every parse reports status, capability tier, and diagnostics.
127
+ 7. **Explicit uncertainty** — unresolved targets become structured external-reference nodes.
128
+
129
+ ## Status
130
+
131
+ `0.10.0` source version. Python (`ast`) is the full, offline frontend. JS/TS, Go, Rust,
132
+ Java, C, and C++ have conformance fixtures; other mapped tree-sitter languages report
133
+ symbols-tier or fallback status rather than implying full fidelity.
134
+
135
+ ### Rust graph fidelity
136
+
137
+ Rust indexing retains inline module scopes and discriminates same-named trait
138
+ implementations and conditional definitions in stable identities. Repository
139
+ resolution follows declared library modules and explicit top-level `use` paths,
140
+ including grouped imports, aliases, and local Cargo path dependencies. Hyphenated
141
+ Cargo dependency names are normalized to their Rust underscore names.
142
+
143
+ Binary-owned or ambiguous files, conditional items/imports, `#[path]` overrides,
144
+ workspace-inherited dependencies, re-export chains, macros and unknown receiver
145
+ types retain unresolved references. Glob imports retain a module dependency but
146
+ do not guess call targets. This is a conservative static graph, not rustc name
147
+ resolution or evidence that a call executes. Publish this package before a Victor
148
+ release that requires its exact repository graph contract.
149
+
150
+
151
+ ### Embedding conformance (0.10.0)
152
+
153
+ The accepted FEP-0040 supplies store-neutral
154
+ `EmbeddingProfile`, `SymbolEmbedding`, `embed_symbols` and an optional
155
+ `SentenceTransformerEncoder`. The base compiler stays dependency-free. The
156
+ `embeddings` extra loads sentence-transformers only when explicitly selected;
157
+ private source is not sent to a remote model by default.
158
+
159
+ The contract uses canonical compiler IDs and `symbol-summary-v1` (name,
160
+ signature and documentation), with an immutable model revision, dimensions,
161
+ token limit, normalization, query prefix and separate input/source hashes.
162
+ Inference errors propagate; hash placeholders, zero vectors and malformed batches
163
+ are not semantic evidence. File/container symbols marked `embedding_excluded`
164
+ remain graph evidence only.
165
+
166
+ These APIs are introduced in 0.10.0 and are unavailable in 0.9.0. Install the
167
+ exact published `victor-codegraph[treesitter,embeddings]==0.10.0` when selecting
168
+ local model execution; the base package has no mandatory model dependency.
169
+ Current evidence covers
170
+ synthetic document-vector persistence parity and local LanceDB collection/query
171
+ profile enforcement. Labeled relevance and hosted lifecycle remain separate
172
+ acceptance gates. Victor binds a new LanceDB table to the complete profile in its
173
+ Arrow schema and rejects incompatible query encoders and mixed/orphan row markers.
174
+ Legacy tables require a fresh destination; they are never silently relabeled.
@@ -0,0 +1,143 @@
1
+ # victor-codegraph
2
+
3
+ Shared **repository → Code Semantic Graph compiler**: symbol and relation extraction,
4
+ hard-bounded embeddable chunks, repository-wide resolution/deltas, diagnostics, and a
5
+ `ProximaRecord` projection. One compiler, three
6
+ consumers — Victor (owner), the ProximaDB SDK (`[codegraph]` extra), and AnvaiOps (SaaS
7
+ code-graph vertical).
8
+
9
+ > Design: ProximaDB `ADR-029` (authoritative) · Victor `ADR-014` (owner/donor) ·
10
+ > AnvaiOps `ADR-0018` (consumer). This package is the **TD-CG1** scaffold.
11
+
12
+ ## Why
13
+
14
+ The same tree-sitter code→symbol+relation chunker existed twice (ProximaDB SDK `code.py`
15
+ and Victor `victor-coding`) and was about to be written a third time in AnvaiOps. This
16
+ package is the single neutral home. It merges the best of both donors and fixes their two
17
+ gaps:
18
+
19
+ - **Size-capping** — ProximaDB's `code.py` emitted one chunk per symbol with *no* size
20
+ bound (a huge function became a huge chunk). Here, oversized symbols are body-split with
21
+ overlap (LlamaIndex `CodeSplitter` discipline). See `sizing.py`.
22
+ - **Real JS/TS** — the donor JS/TS parser was a stub returning no symbols. Here JS/TS get a
23
+ real tree-sitter extractor (functions, classes, methods, `const … = () =>`, imports).
24
+
25
+ ## Install
26
+
27
+ Published on PyPI as [`victor-codegraph`](https://pypi.org/project/victor-codegraph/).
28
+ This source tree is version **0.10.0**; consumers should use a compatible `<1.0` pin.
29
+
30
+ ```bash
31
+ # from PyPI
32
+ pip install victor-codegraph # Python-only (stdlib ast) path, zero native deps
33
+ pip install "victor-codegraph[treesitter]" # + multi-language tree-sitter grammars
34
+
35
+ # dev (monorepo): editable, with tree-sitter grammars + test tooling
36
+ make -C victor-codegraph dev # = pip install -e ../victor-contracts && pip install -e ".[dev]"
37
+ pip install -e ./victor-codegraph # minimal editable install
38
+ ```
39
+
40
+ ### Releasing
41
+
42
+ CI: `.github/workflows/ci-codegraph.yml` runs the suite (editable install, grammars on) for every
43
+ PR touching `victor-codegraph/**`. Publishing: push a tag `victor-codegraph-v0.1.0` to trigger
44
+ `.github/workflows/release-codegraph.yml`, which builds and publishes via **PyPI Trusted Publishing**
45
+ (OIDC — no API token). Configure the publisher once on PyPI (owner `vjsingh1984`, repo `victor`,
46
+ workflow `release-codegraph.yml`, environments `pypi` / `testpypi`); see the header of that workflow.
47
+
48
+ ## 0.9 consumer qualification and migration
49
+
50
+ | Surface | Contract / limit |
51
+ |---|---|
52
+ | Python references | Exact import aliases and dotted modules; lexical scope precedes arity. Unknown receivers, wildcard ambiguity and shadowed bindings remain explicit unresolved references. No runtime execution/type inference. |
53
+ | ES modules | Relative named/default/namespace imports, explicit named re-exports and exported arrow functions. Type-only imports produce dependencies, never runtime call evidence. Re-export traversal is cycle-safe and bounded to 64 bindings. Package/tsconfig aliases, star exports and dynamic exports remain unresolved. |
54
+ | Object-literal identity | Methods include structural object scopes, including anonymous callback ancestry. Whitespace/comments and checkout root do not affect IDs; inserting/reordering anonymous siblings can change structural ordinals. |
55
+ | Source evidence | Python call spans include UTF-8 byte offsets/lengths and end coordinates. New binding metadata is diagnostic evidence, not runtime authorization or a complete language semantic model. |
56
+ | Victor persistence | The canonical snapshot supplies symbols. CLI distinguishes attempted upserts from persisted totals, exposes partial parses and accepts exact opaque IDs; ambiguous display names are not chosen arbitrarily. Default file exclusions can differ from the package walker. |
57
+
58
+ Rebuild derived indexes after upgrading from older parser versions; an unchanged
59
+ source hash alone does not migrate older IDs/edges. Victor users can run
60
+ `victor graph index --force --no-ccg --no-embeddings`. Consumers must stage a new
61
+ complete generation and switch readers after validation; never mix old and new
62
+ symbol identities. The AnvaiOps adapter/generation migration remains consumer-owned.
63
+ The package adds no commercial runtime, account, entitlement or billing dependency.
64
+
65
+
66
+ ## Use
67
+
68
+ ```python
69
+ from victor_codegraph import chunk, parse, parse_repo, to_proxima_records, ChunkConfig
70
+
71
+ # Size-capped, embeddable chunks:
72
+ chunks = chunk(source, file_path="app/service.py", config=ChunkConfig(max_chunk_tokens=512))
73
+
74
+ # Symbols + relations:
75
+ parsed = parse(source, file_path="app/service.py")
76
+
77
+ # Project to the ProximaDB substrate-keystone record shape (one symbol = row+node+vector):
78
+ records = to_proxima_records(parsed, repo_graph_id="myrepo", branch_id="main",
79
+ embedder=my_embed_fn) # embedder optional
80
+
81
+ # Repository-wide resolution + file/import/containment graph:
82
+ repository = parse_repo(".", repo_id="myrepo")
83
+ records = to_proxima_records(repository, repo_graph_id="myrepo")
84
+ ```
85
+
86
+ ## Design principles (the "best posture" this encodes)
87
+
88
+ 1. Chunk at **symbol** granularity (not statement, not fixed-size).
89
+ 2. **Newline-preferred and hard-bounded** — forced character splits are explicit; an optional
90
+ tokenizer callback enforces the real model limit.
91
+ 3. Extract a **Code Semantic Graph** (CALLS/EXTENDS/IMPLEMENTS/CONTAINS/IMPORTS). Full
92
+ intra-procedural CFG/CDG/DDG is a separate optional layer, not implied here.
93
+ 4. **One structural v2 ID** across symbols, chunks, relations, and records; line IDs remain aliases.
94
+ 5. **Deletion-complete deltas** — incremental output can be checked against a full rebuild.
95
+ 6. **Observable fallback** — every parse reports status, capability tier, and diagnostics.
96
+ 7. **Explicit uncertainty** — unresolved targets become structured external-reference nodes.
97
+
98
+ ## Status
99
+
100
+ `0.10.0` source version. Python (`ast`) is the full, offline frontend. JS/TS, Go, Rust,
101
+ Java, C, and C++ have conformance fixtures; other mapped tree-sitter languages report
102
+ symbols-tier or fallback status rather than implying full fidelity.
103
+
104
+ ### Rust graph fidelity
105
+
106
+ Rust indexing retains inline module scopes and discriminates same-named trait
107
+ implementations and conditional definitions in stable identities. Repository
108
+ resolution follows declared library modules and explicit top-level `use` paths,
109
+ including grouped imports, aliases, and local Cargo path dependencies. Hyphenated
110
+ Cargo dependency names are normalized to their Rust underscore names.
111
+
112
+ Binary-owned or ambiguous files, conditional items/imports, `#[path]` overrides,
113
+ workspace-inherited dependencies, re-export chains, macros and unknown receiver
114
+ types retain unresolved references. Glob imports retain a module dependency but
115
+ do not guess call targets. This is a conservative static graph, not rustc name
116
+ resolution or evidence that a call executes. Publish this package before a Victor
117
+ release that requires its exact repository graph contract.
118
+
119
+
120
+ ### Embedding conformance (0.10.0)
121
+
122
+ The accepted FEP-0040 supplies store-neutral
123
+ `EmbeddingProfile`, `SymbolEmbedding`, `embed_symbols` and an optional
124
+ `SentenceTransformerEncoder`. The base compiler stays dependency-free. The
125
+ `embeddings` extra loads sentence-transformers only when explicitly selected;
126
+ private source is not sent to a remote model by default.
127
+
128
+ The contract uses canonical compiler IDs and `symbol-summary-v1` (name,
129
+ signature and documentation), with an immutable model revision, dimensions,
130
+ token limit, normalization, query prefix and separate input/source hashes.
131
+ Inference errors propagate; hash placeholders, zero vectors and malformed batches
132
+ are not semantic evidence. File/container symbols marked `embedding_excluded`
133
+ remain graph evidence only.
134
+
135
+ These APIs are introduced in 0.10.0 and are unavailable in 0.9.0. Install the
136
+ exact published `victor-codegraph[treesitter,embeddings]==0.10.0` when selecting
137
+ local model execution; the base package has no mandatory model dependency.
138
+ Current evidence covers
139
+ synthetic document-vector persistence parity and local LanceDB collection/query
140
+ profile enforcement. Labeled relevance and hosted lifecycle remain separate
141
+ acceptance gates. Victor binds a new LanceDB table to the complete profile in its
142
+ Arrow schema and rejects incompatible query encoders and mixed/orphan row markers.
143
+ Legacy tables require a fresh destination; they are never silently relabeled.
@@ -1,20 +1,21 @@
1
1
  [build-system]
2
- requires = ["setuptools>=61.0", "wheel"]
2
+ requires = ["setuptools>=84.0.0", "wheel"]
3
3
  build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "victor-codegraph"
7
- version = "0.8.1"
8
- description = "Code->CPG chunker: tree-sitter symbol + relation extraction, size-capped chunks, ProximaRecord projection. Shared by Victor, ProximaDB SDK, and AnvaiOps."
7
+ version = "0.10.0"
8
+ description = "Repository-to-Code-Semantic-Graph compiler with stable identity, bounded chunks, incremental deltas, and ProximaRecord projection."
9
9
  readme = "README.md"
10
- requires-python = ">=3.10"
10
+ requires-python = ">=3.12"
11
11
  license = { text = "Apache-2.0" }
12
12
  authors = [
13
- { name = "Vijaykumar Singh", email = "singhvjd@gmail.com" },
13
+ { name = "Vijaykumar Singh", email = "vijay@anvaiops.com" },
14
14
  ]
15
15
  keywords = [
16
16
  "code-graph",
17
17
  "cpg",
18
+ "semantic-graph",
18
19
  "chunking",
19
20
  "tree-sitter",
20
21
  "ast",
@@ -26,9 +27,8 @@ classifiers = [
26
27
  "Intended Audience :: Developers",
27
28
  "License :: OSI Approved :: Apache Software License",
28
29
  "Programming Language :: Python :: 3",
29
- "Programming Language :: Python :: 3.10",
30
- "Programming Language :: Python :: 3.11",
31
30
  "Programming Language :: Python :: 3.12",
31
+ "Programming Language :: Python :: 3.13",
32
32
  "Topic :: Software Development :: Libraries",
33
33
  ]
34
34
 
@@ -40,18 +40,19 @@ classifiers = [
40
40
  dependencies = []
41
41
 
42
42
  [project.optional-dependencies]
43
+ embeddings = ["sentence-transformers>=3,<6"]
43
44
  treesitter = [
44
- "tree-sitter>=0.23",
45
- "tree-sitter-language-pack>=1.0",
45
+ "tree-sitter>=0.26.0",
46
+ "tree-sitter-language-pack>=1.21.3",
46
47
  ]
47
48
  contracts = [
48
- "victor-contracts>=0.7.0,<1.0",
49
+ "victor-contracts>=0.9.1,<1.0",
49
50
  ]
50
51
  dev = [
51
- "pytest>=8.0",
52
- "ruff>=0.5",
53
- "tree-sitter>=0.23",
54
- "tree-sitter-language-pack>=1.0",
52
+ "pytest>=9.1.1",
53
+ "ruff>=0.16.7",
54
+ "tree-sitter>=0.26.0",
55
+ "tree-sitter-language-pack>=1.21.3",
55
56
  ]
56
57
 
57
58
  [project.urls]
@@ -64,7 +65,7 @@ include = ["victor_codegraph*"]
64
65
 
65
66
  [tool.ruff]
66
67
  line-length = 100
67
- target-version = "py310"
68
+ target-version = "py312"
68
69
 
69
70
  # Pin the rule set explicitly: the CI workflow installs the latest ruff, whose
70
71
  # evolving defaults must not be able to red a path-filtered pipeline overnight.
@@ -77,3 +78,6 @@ select = ["E4", "E7", "E9", "F"]
77
78
  [tool.pytest.ini_options]
78
79
  testpaths = ["tests"]
79
80
  addopts = ""
81
+
82
+ [tool.setuptools.package-data]
83
+ victor_codegraph = ["py.typed"]
@@ -0,0 +1,42 @@
1
+ from __future__ import annotations
2
+
3
+ import pytest
4
+
5
+ from victor_codegraph import parse, to_proxima_records
6
+
7
+
8
+ def test_batch_embedder_cardinality_mismatch_fails():
9
+ parsed = parse("def a(): pass\ndef b(): pass\n", file_path="m.py")
10
+ with pytest.raises(ValueError, match="one vector per symbol"):
11
+ to_proxima_records(parsed, "repo", batch_embedder=lambda texts: [[0.0] * 3], dim=3)
12
+
13
+
14
+ def test_embedding_dimension_mismatch_fails():
15
+ parsed = parse("def a(): pass\n", file_path="m.py")
16
+ with pytest.raises(ValueError, match="dimension"):
17
+ to_proxima_records(parsed, "repo", embedder=lambda text: [0.0, 1.0], dim=3)
18
+
19
+
20
+ def test_non_finite_embedding_fails_before_storage():
21
+ parsed = parse("def a(): pass\n", file_path="m.py")
22
+ with pytest.raises(ValueError, match="finite numeric"):
23
+ to_proxima_records(parsed, "repo", embedder=lambda text: [0.0, float("nan")], dim=2)
24
+
25
+
26
+ def test_repeated_calls_are_one_edge_with_all_call_sites():
27
+ parsed = parse("def a():\n b()\n b()\n\ndef b(): pass\n", file_path="m.py")
28
+ records = to_proxima_records(parsed, "repo")
29
+ calls = [
30
+ r for r in records if "graph_edge" in r["labels"] and r["edge"]["edge_type"] == "CALLS"
31
+ ]
32
+ assert len(calls) == 1
33
+ assert [site["line"] for site in calls[0]["props"]["call_sites"]] == [2, 3]
34
+
35
+
36
+ def test_legacy_oid_mode_keeps_edge_endpoints_attached():
37
+ parsed = parse("def a(): return b()\n\ndef b(): return 1\n", file_path="m.py")
38
+ records = to_proxima_records(parsed, "repo", stable_oid=False)
39
+ nodes = {r["oid"] for r in records if "graph_node" in r["labels"]}
40
+ edge = next(r for r in records if "graph_edge" in r["labels"])
41
+ assert edge["edge"]["from_oid"] in nodes
42
+ assert edge["edge"]["to_oid"] in nodes
@@ -0,0 +1,75 @@
1
+ from __future__ import annotations
2
+
3
+ import pytest
4
+
5
+ from victor_codegraph import ChunkConfig, chunk
6
+
7
+
8
+ def test_fallback_caps_a_single_oversized_line():
9
+ config = ChunkConfig(max_chunk_tokens=10, chunk_overlap_tokens=2, chars_per_token=1)
10
+ chunks = chunk("x" * 100, language="text", file_path="notes.txt", config=config)
11
+ assert len(chunks) > 1
12
+ assert all(len(c.text) <= config.max_chunk_chars for c in chunks)
13
+
14
+
15
+ def test_python_chunks_report_exact_nonzero_byte_spans():
16
+ source = "prefix = 1\n\ndef f():\n return 1\n"
17
+ function = next(
18
+ c for c in chunk(source, file_path="m.py") if c.metadata.get("simple_name") == "f"
19
+ )
20
+ assert function.start_pos == source.index("def f")
21
+ assert function.end_pos == function.start_pos + len(function.text.encode())
22
+
23
+
24
+ def test_chunking_preserves_module_level_semantic_content_without_container_duplication():
25
+ source = """import os
26
+ GLOBAL = configure()
27
+
28
+ class Service:
29
+ def run(self):
30
+ return work()
31
+
32
+ main()
33
+ """
34
+ chunks = chunk(source, file_path="m.py", config=ChunkConfig(max_chunk_tokens=1000))
35
+ text = "\n".join(c.text for c in chunks)
36
+ assert "import os" in text
37
+ assert "GLOBAL = configure()" in text
38
+ assert "main()" in text
39
+ assert sum(c.text.count("return work()") for c in chunks) == 1
40
+
41
+
42
+ def test_include_tests_and_language_filters_are_effective():
43
+ assert (
44
+ chunk(
45
+ "def test_it():\n pass\n",
46
+ file_path="test_demo.py",
47
+ config=ChunkConfig(include_tests=False),
48
+ )
49
+ == []
50
+ )
51
+ assert (
52
+ chunk(
53
+ "def f():\n pass\n",
54
+ file_path="m.py",
55
+ config=ChunkConfig(languages=["rust"]),
56
+ )
57
+ == []
58
+ )
59
+
60
+
61
+ def test_custom_token_counter_is_a_hard_limit():
62
+ source = "def f():\n" + "\n".join(f" value_{i} = {i}" for i in range(30))
63
+ config = ChunkConfig(
64
+ max_chunk_tokens=8,
65
+ chunk_overlap_tokens=0,
66
+ token_counter=lambda text: len(text.split()),
67
+ )
68
+ chunks = chunk(source, file_path="m.py", config=config)
69
+ assert all(config.estimate_tokens(c.text) <= config.max_chunk_tokens for c in chunks)
70
+
71
+
72
+ def test_impossible_token_counter_fails_instead_of_emitting_over_budget_chunk():
73
+ config = ChunkConfig(max_chunk_tokens=1, token_counter=lambda text: 2 if text else 0)
74
+ with pytest.raises(ValueError, match="cannot fit"):
75
+ chunk("x", language="text", file_path="notes.txt", config=config)
@@ -0,0 +1,26 @@
1
+ from __future__ import annotations
2
+
3
+ from victor_codegraph import CapabilityTier, ChunkConfig, ParseStatus, parse
4
+
5
+
6
+ def test_syntax_error_reports_fallback_diagnostic():
7
+ parsed = parse("def broken(:\n", file_path="bad.py")
8
+ assert parsed.status == ParseStatus.FALLBACK
9
+ assert parsed.diagnostics
10
+ assert parsed.diagnostics[0].code == "syntax_error"
11
+
12
+
13
+ def test_unknown_language_reports_fallback_instead_of_silent_success():
14
+ parsed = parse("plain text", language="unknown", file_path="x.unknown")
15
+ assert parsed.status == ParseStatus.FALLBACK
16
+ assert parsed.capability_tier == CapabilityTier.FALLBACK
17
+ assert parsed.diagnostics
18
+
19
+
20
+ def test_extract_relations_config_is_effective():
21
+ parsed = parse(
22
+ "def f():\n return g()\n",
23
+ file_path="m.py",
24
+ config=ChunkConfig(extract_relations=False),
25
+ )
26
+ assert parsed.relations == []