victor-coding 0.7.2__tar.gz → 0.14.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 (156) hide show
  1. {victor_coding-0.7.2 → victor_coding-0.14.0}/LICENSE +1 -1
  2. {victor_coding-0.7.2 → victor_coding-0.14.0}/PKG-INFO +11 -12
  3. {victor_coding-0.7.2 → victor_coding-0.14.0}/pyproject.toml +26 -25
  4. {victor_coding-0.7.2 → victor_coding-0.14.0}/tests/test_coding_capabilities.py +1 -1
  5. victor_coding-0.14.0/tests/test_coding_handlers.py +147 -0
  6. {victor_coding-0.7.2 → victor_coding-0.14.0}/tests/test_coding_vertical_rl.py +1 -1
  7. {victor_coding-0.7.2 → victor_coding-0.14.0}/tests/test_coding_vertical_teams.py +1 -1
  8. {victor_coding-0.7.2 → victor_coding-0.14.0}/tests/test_coding_vertical_workflows.py +39 -1
  9. {victor_coding-0.7.2 → victor_coding-0.14.0}/tests/test_enhanced_integration.py +2 -2
  10. {victor_coding-0.7.2 → victor_coding-0.14.0}/tests/test_extension_cache.py +1 -1
  11. {victor_coding-0.7.2 → victor_coding-0.14.0}/tests/test_framework_lsp_adapter.py +1 -1
  12. victor_coding-0.14.0/tests/test_graph_backend_marker.py +70 -0
  13. victor_coding-0.14.0/tests/test_personas.py +143 -0
  14. victor_coding-0.14.0/tests/test_protocol_providers.py +68 -0
  15. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/assistant.py +2 -2
  16. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/capabilities.py +1 -1
  17. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/__init__.py +1 -1
  18. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/ccg_builder.py +203 -28
  19. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/chunker.py +1 -1
  20. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/embeddings/__init__.py +8 -6
  21. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/embeddings/chunker.py +1 -1
  22. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/graph/__init__.py +1 -1
  23. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/graph/registry.py +6 -1
  24. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/ignore_patterns.py +1 -1
  25. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/indexer.py +100 -77
  26. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/query_expander.py +1 -1
  27. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/symbol_store.py +1 -1
  28. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/tree_sitter_analysis.py +72 -1
  29. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/tree_sitter_extractor.py +5 -1
  30. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/tree_sitter_manager.py +1 -1
  31. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/tree_sitter_service.py +1 -1
  32. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/unified_extractor.py +1 -1
  33. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase_analyzer.py +42 -687
  34. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/composed_chains.py +2 -114
  35. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/conversation_enhanced.py +18 -160
  36. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/coverage/__init__.py +1 -1
  37. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/coverage/manager.py +1 -1
  38. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/coverage/parser.py +1 -1
  39. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/coverage/parsers/__init__.py +1 -1
  40. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/coverage/protocol.py +1 -1
  41. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/coverage/visualizer.py +1 -1
  42. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/docgen/__init__.py +1 -1
  43. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/docgen/formatter.py +1 -1
  44. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/docgen/manager.py +1 -1
  45. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/docgen/parser.py +1 -1
  46. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/docgen/protocol.py +1 -1
  47. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/editing/__init__.py +1 -1
  48. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/enrichment.py +1 -1
  49. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/escape_hatches.py +6 -142
  50. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/handlers.py +13 -51
  51. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/__init__.py +1 -1
  52. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/base.py +62 -4
  53. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/manager.py +1 -1
  54. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/plugins/__init__.py +1 -1
  55. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/plugins/additional.py +52 -381
  56. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/plugins/config.py +1 -1
  57. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/plugins/cpp.py +2 -59
  58. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/plugins/go.py +2 -58
  59. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/plugins/java.py +2 -58
  60. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/plugins/javascript.py +5 -53
  61. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/plugins/python.py +2 -65
  62. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/plugins/rust.py +3 -12
  63. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/plugins/typescript.py +2 -59
  64. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/registry.py +1 -1
  65. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/tiers.py +1 -1
  66. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/lsp/__init__.py +1 -1
  67. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/lsp/client.py +1 -1
  68. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/lsp/config.py +1 -1
  69. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/lsp/framework_adapter.py +1 -1
  70. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/lsp/manager.py +1 -1
  71. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/middleware.py +1 -1
  72. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/mode_config.py +1 -1
  73. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/native/__init__.py +5 -5
  74. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/performance/__init__.py +1 -1
  75. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/performance/factory.py +1 -1
  76. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/performance/protocols.py +1 -1
  77. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/performance/registry.py +1 -1
  78. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/performance/service_provider.py +1 -1
  79. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/performance/settings.py +1 -1
  80. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/performance/wrappers.py +1 -1
  81. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/prompts.py +1 -1
  82. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/protocols.py +47 -64
  83. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/refactor/__init__.py +1 -1
  84. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/refactor/analyzer.py +1 -1
  85. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/refactor/manager.py +1 -1
  86. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/refactor/protocol.py +1 -1
  87. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/refactor/transforms/__init__.py +1 -1
  88. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/refactor/transforms/base.py +1 -1
  89. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/refactor/transforms/extract.py +1 -1
  90. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/refactor/transforms/rename.py +1 -1
  91. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/review/__init__.py +1 -1
  92. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/review/analyzers.py +1 -1
  93. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/review/manager.py +1 -1
  94. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/review/protocol.py +1 -1
  95. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/review/rules.py +1 -1
  96. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/rl/__init__.py +1 -1
  97. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/rl/config.py +1 -1
  98. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/rl/hooks.py +1 -1
  99. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/safety.py +1 -1
  100. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/safety_enhanced.py +23 -159
  101. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/service_provider.py +1 -1
  102. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/teams/__init__.py +1 -1
  103. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/teams/personas.py +97 -350
  104. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/teams/specs.py +1 -1
  105. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/testgen/__init__.py +1 -1
  106. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/testgen/analyzer.py +1 -1
  107. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/testgen/generator.py +1 -1
  108. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/testgen/manager.py +1 -1
  109. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/testgen/protocol.py +1 -1
  110. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/tool_dependencies.py +1 -1
  111. victor_coding-0.14.0/victor_coding/tools/code_executor_tool.py +552 -0
  112. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/tools/code_intelligence_tool.py +1 -1
  113. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/tools/code_search_tool.py +76 -246
  114. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/tools/graph_tool.py +48 -23
  115. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/workflows/__init__.py +1 -1
  116. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/workflows/bugfix.py +1 -1
  117. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/workflows/feature.py +1 -1
  118. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/workflows/provider.py +1 -1
  119. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/workflows/review.py +1 -1
  120. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding.egg-info/PKG-INFO +11 -12
  121. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding.egg-info/SOURCES.txt +4 -16
  122. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding.egg-info/requires.txt +7 -7
  123. victor_coding-0.7.2/victor_coding/codebase/embeddings/base.py +0 -247
  124. victor_coding-0.7.2/victor_coding/codebase/embeddings/lancedb_provider.py +0 -418
  125. victor_coding-0.7.2/victor_coding/codebase/embeddings/models.py +0 -530
  126. victor_coding-0.7.2/victor_coding/codebase/embeddings/proximadb_provider.py +0 -624
  127. victor_coding-0.7.2/victor_coding/codebase/embeddings/registry.py +0 -140
  128. victor_coding-0.7.2/victor_coding/codebase/graph/protocol.py +0 -110
  129. victor_coding-0.7.2/victor_coding/completion/__init__.py +0 -119
  130. victor_coding-0.7.2/victor_coding/completion/manager.py +0 -511
  131. victor_coding-0.7.2/victor_coding/completion/protocol.py +0 -51
  132. victor_coding-0.7.2/victor_coding/completion/provider.py +0 -363
  133. victor_coding-0.7.2/victor_coding/completion/providers/__init__.py +0 -25
  134. victor_coding-0.7.2/victor_coding/completion/providers/ai.py +0 -409
  135. victor_coding-0.7.2/victor_coding/completion/providers/lsp.py +0 -313
  136. victor_coding-0.7.2/victor_coding/completion/providers/snippet.py +0 -532
  137. victor_coding-0.7.2/victor_coding/completion/registry.py +0 -305
  138. victor_coding-0.7.2/victor_coding/editing/editor.py +0 -598
  139. victor_coding-0.7.2/victor_coding/tools/code_executor_tool.py +0 -600
  140. {victor_coding-0.7.2 → victor_coding-0.14.0}/README.md +0 -0
  141. {victor_coding-0.7.2 → victor_coding-0.14.0}/setup.cfg +0 -0
  142. {victor_coding-0.7.2 → victor_coding-0.14.0}/tests/test_api_router_provider.py +0 -0
  143. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/__init__.py +0 -0
  144. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/api/__init__.py +0 -0
  145. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/api/router_provider.py +0 -0
  146. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/architecture_analyzer.py +0 -0
  147. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/symbol_extractor.py +0 -0
  148. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/symbol_resolver.py +0 -0
  149. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/compat/__init__.py +0 -0
  150. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/compat/settings.py +0 -0
  151. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/plugin.py +0 -0
  152. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/skills.py +0 -0
  153. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/tools/__init__.py +0 -0
  154. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding.egg-info/dependency_links.txt +0 -0
  155. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding.egg-info/entry_points.txt +0 -0
  156. {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding.egg-info/top_level.txt +0 -0
@@ -175,7 +175,7 @@
175
175
 
176
176
  END OF TERMS AND CONDITIONS
177
177
 
178
- Copyright 2025 Vijaykumar Singh <singhvjd@gmail.com>
178
+ Copyright 2025 Vijaykumar Singh <vijay@anvaiops.com>
179
179
 
180
180
  Licensed under the Apache License, Version 2.0 (the "License");
181
181
  you may not use this file except in compliance with the License.
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: victor-coding
3
- Version: 0.7.2
3
+ Version: 0.14.0
4
4
  Summary: Coding vertical for Victor AI - Software development, debugging, and code generation
5
- Author-email: Vijaykumar Singh <singhvjd@gmail.com>
6
- Maintainer-email: Vijaykumar Singh <singhvjd@gmail.com>
5
+ Author-email: Vijaykumar Singh <vijay@anvaiops.com>
6
+ Maintainer-email: Vijaykumar Singh <vijay@anvaiops.com>
7
7
  License: Apache-2.0
8
8
  Project-URL: Homepage, https://github.com/vjsingh1984/victor-coding
9
9
  Project-URL: Repository, https://github.com/vjsingh1984/victor-coding
@@ -13,34 +13,33 @@ Keywords: victor,vertical,coding,development,debugging,refactoring
13
13
  Classifier: Development Status :: 4 - Beta
14
14
  Classifier: Intended Audience :: Developers
15
15
  Classifier: Programming Language :: Python :: 3
16
- Classifier: Programming Language :: Python :: 3.11
17
16
  Classifier: Programming Language :: Python :: 3.12
18
17
  Classifier: Topic :: Software Development
19
- Requires-Python: >=3.11
18
+ Requires-Python: >=3.12
20
19
  Description-Content-Type: text/markdown
21
20
  License-File: LICENSE
22
- Requires-Dist: victor-contracts[yaml]<1.0,>=0.6.0
23
- Requires-Dist: numpy<2.3,>=1.24
21
+ Requires-Dist: victor-contracts[yaml]<1.0,>=0.11.0
24
22
  Requires-Dist: victor-codegraph[treesitter]>=0.1.0
25
23
  Requires-Dist: defusedxml<1.0,>=0.7
26
24
  Provides-Extra: runtime
27
25
  Requires-Dist: victor-ai<1.0,>=0.7.6; extra == "runtime"
28
26
  Provides-Extra: native
29
27
  Provides-Extra: proximadb
30
- Requires-Dist: proximadb<0.3,>=0.2; extra == "proximadb"
28
+ Requires-Dist: proximadb<0.5,>=0.4.1; extra == "proximadb"
31
29
  Provides-Extra: codegraph
32
30
  Requires-Dist: victor-codegraph<1.0,>=0.1.0; extra == "codegraph"
33
31
  Provides-Extra: dev
34
- Requires-Dist: pytest>=8.0; extra == "dev"
32
+ Requires-Dist: numpy<2.6,>=1.24; extra == "dev"
33
+ Requires-Dist: pytest<9.2,>=8.0; extra == "dev"
35
34
  Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
36
35
  Requires-Dist: pytest-cov>=4.1; extra == "dev"
37
36
  Requires-Dist: pytest-xdist>=3.0; extra == "dev"
38
37
  Requires-Dist: pytest-benchmark>=5.0; extra == "dev"
39
- Requires-Dist: black==26.1.0; extra == "dev"
38
+ Requires-Dist: black==26.10.1; extra == "dev"
40
39
  Requires-Dist: ruff>=0.5; extra == "dev"
41
- Requires-Dist: mypy>=1.10; extra == "dev"
40
+ Requires-Dist: mypy==2.4.0; extra == "dev"
42
41
  Provides-Extra: native-dev
43
- Requires-Dist: maturin<2.0,>=1.0; extra == "native-dev"
42
+ Requires-Dist: maturin<2.0,>=1.10; extra == "native-dev"
44
43
  Dynamic: license-file
45
44
 
46
45
  # victor-coding
@@ -1,22 +1,22 @@
1
1
  [build-system]
2
2
  requires = [
3
- "setuptools>=61.0",
3
+ "setuptools>=83.0.0",
4
4
  "wheel",
5
5
  ]
6
6
  build-backend = "setuptools.build_meta"
7
7
 
8
8
  [project]
9
9
  name = "victor-coding"
10
- version = "0.7.2"
10
+ version = "0.14.0"
11
11
  description = "Coding vertical for Victor AI - Software development, debugging, and code generation"
12
12
  readme = "README.md"
13
- requires-python = ">=3.11"
13
+ requires-python = ">=3.12"
14
14
  license = {text = "Apache-2.0"}
15
15
  authors = [
16
- { name = "Vijaykumar Singh", email = "singhvjd@gmail.com" },
16
+ { name = "Vijaykumar Singh", email = "vijay@anvaiops.com" },
17
17
  ]
18
18
  maintainers = [
19
- { name = "Vijaykumar Singh", email = "singhvjd@gmail.com" },
19
+ { name = "Vijaykumar Singh", email = "vijay@anvaiops.com" },
20
20
  ]
21
21
  keywords = [
22
22
  "victor",
@@ -30,13 +30,11 @@ classifiers = [
30
30
  "Development Status :: 4 - Beta",
31
31
  "Intended Audience :: Developers",
32
32
  "Programming Language :: Python :: 3",
33
- "Programming Language :: Python :: 3.11",
34
33
  "Programming Language :: Python :: 3.12",
35
34
  "Topic :: Software Development",
36
35
  ]
37
36
  dependencies = [
38
- "victor-contracts[yaml]>=0.6.0,<1.0", # Definition-layer contract for external verticals
39
- "numpy>=1.24,<2.3", # Required by victor.storage.embeddings; numba-compatible
37
+ "victor-contracts[yaml]>=0.11.0,<1.0", # Definition-layer contract for external verticals
40
38
  "victor-codegraph[treesitter]>=0.1.0", # Shared code->CPG chunker (ADR-014); [treesitter] supplies the grammars the delegation parses JS/Go/TS/Rust with
41
39
  "defusedxml>=0.7,<1.0", # XXE-hardened XML parsing for coverage reports
42
40
  ]
@@ -46,16 +44,15 @@ runtime = [
46
44
  "victor-ai>=0.7.6,<1.0", # Runtime support - optional, contract-first architecture
47
45
  ]
48
46
  native = [
49
- # Native extensions are handled by maturin
50
- # Install with: pip install -e .[native]
51
- # or build with: maturin develop --release
47
+ # Compatibility extra. Build the separate distribution from ./native;
48
+ # see native/README.md. Installing this empty extra does not build Rust.
52
49
  ]
53
- # ProximaDB embedding provider (optional backend).
54
- # Imported lazily with graceful ImportError fallback in
55
- # victor_coding/codebase/embeddings/proximadb_provider.py. Pin kept identical
56
- # to victor-ai's proximadb extra so the backend version stays aligned.
50
+ # ProximaDB embedding backend (optional). The provider lives in victor-ai
51
+ # (victor/storage/vector_stores/proximadb_provider.py) and is resolved through
52
+ # victor_contracts.embeddings_runtime; this pass-through extra keeps the pin
53
+ # identical to victor-ai's proximadb extra.
57
54
  proximadb = [
58
- "proximadb>=0.2,<0.3",
55
+ "proximadb>=0.4.1,<0.5",
59
56
  ]
60
57
  # Shared code->CPG chunker (ADR-014). Opt-in: when installed AND
61
58
  # VICTOR_CODING_USE_CODEGRAPH=1, CodeChunker delegates to it. Published on PyPI
@@ -64,17 +61,18 @@ codegraph = [
64
61
  "victor-codegraph>=0.1.0,<1.0",
65
62
  ]
66
63
  dev = [
67
- "pytest>=8.0",
64
+ "numpy>=1.24,<2.6", # Synthetic embeddings in indexer tests
65
+ "pytest>=8.0,<9.2", # pytest 9.2 (2026-10-27) removed Function._nodeid, which pytest-benchmark reads in fixture setup (verticals CI _nodeid AttributeErrors)
68
66
  "pytest-asyncio>=0.23",
69
67
  "pytest-cov>=4.1",
70
68
  "pytest-xdist>=3.0",
71
69
  "pytest-benchmark>=5.0",
72
- "black==26.1.0",
70
+ "black==26.10.1",
73
71
  "ruff>=0.5",
74
- "mypy>=1.10",
72
+ "mypy==2.4.0",
75
73
  ]
76
74
  native-dev = [
77
- "maturin>=1.0,<2.0", # Build Rust extensions
75
+ "maturin>=1.10,<2.0", # Build Rust extensions
78
76
  ]
79
77
 
80
78
  [project.urls]
@@ -145,7 +143,7 @@ coding-compaction = "victor_coding.protocols:CodingCompactionProvider"
145
143
  [tool.setuptools.packages.find]
146
144
  # Auto-discover all `victor_coding*` subpackages. An explicit `packages` list
147
145
  # here previously omitted nested subpackages (languages.plugins,
148
- # codebase.embeddings, codebase.graph, compat, completion.providers,
146
+ # codebase.embeddings, codebase.graph, compat,
149
147
  # coverage.parsers, native, performance, refactor.transforms), which silently
150
148
  # broke the published wheel (ModuleNotFoundError) while editable installs
151
149
  # worked — because the whole source tree is on sys.path under `-e`.
@@ -156,20 +154,23 @@ exclude = ["tests*", "docs*", "native*"]
156
154
  [tool.black]
157
155
  line-length = 100
158
156
  target-version = [
159
- "py311",
160
157
  "py312",
161
158
  ]
162
159
 
163
160
  [tool.ruff]
161
+ extend-exclude = [
162
+ # Parser input corpus for the golden tests: data, not code. Editing it
163
+ # shifts the pinned line numbers.
164
+ "tests/codebase/goldens/samples",
165
+ ]
164
166
  line-length = 100
165
- target-version = "py311"
167
+ target-version = "py312"
166
168
 
167
169
  [tool.ruff.lint]
168
170
  select = ["E", "W", "F", "B", "C4"]
169
171
  ignore = [
170
172
  "E501", # line too long (handled by formatter)
171
173
  "E402", # module level import not at top of file (sometimes necessary)
172
- "F401", # unused imports (often intentional re-exports)
173
174
  "F811", # redefined while unused (type imports shadowing runtime)
174
175
  "B007", # loop control variable not used within loop body
175
176
  "B008", # do not perform function calls in argument defaults
@@ -187,5 +188,5 @@ ignore = [
187
188
  "__init__.py" = ["F401"]
188
189
  "tests/**/*.py" = ["B017", "B018", "E741", "F841"]
189
190
  [tool.mypy]
190
- python_version = "3.11"
191
+ python_version = "3.12"
191
192
  warn_return_any = true
@@ -1,4 +1,4 @@
1
- # Copyright 2026 Vijaykumar Singh <singhvjd@gmail.com>
1
+ # Copyright 2026 Vijaykumar Singh <vijay@anvaiops.com>
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -0,0 +1,147 @@
1
+ # Copyright 2026 Vijaykumar Singh <vijay@anvaiops.com>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Pre-move characterization for victor-coding compute handlers (dedup F5).
16
+
17
+ Pins the observable contract before the envelope is extracted to the shared
18
+ kernel: command construction, output-key handling, the two handlers' DIFFERENT
19
+ failure policies (code_validation always COMPLETED with all_passed inside the
20
+ output; test_runner FAILED when the suite fails), and registration semantics.
21
+ """
22
+
23
+ from typing import Any, Dict
24
+ from unittest.mock import AsyncMock, MagicMock
25
+
26
+ import pytest
27
+
28
+ from victor_contracts.testing import MockComputeNode, MockToolResult, MockWorkflowContext
29
+ from victor_coding.handlers import HANDLERS, CodeValidationHandler, TestRunnerHandler
30
+
31
+
32
+ def registry(result: MockToolResult) -> MagicMock:
33
+ r = MagicMock()
34
+ r.execute = AsyncMock(return_value=result)
35
+ return r
36
+
37
+
38
+ class TestCodeValidationHandler:
39
+ @pytest.mark.asyncio
40
+ async def test_lint_check_passes_through_shell_command(self):
41
+ reg = registry(MockToolResult(success=True, output="clean"))
42
+ ctx = MockWorkflowContext()
43
+ node = MockComputeNode(
44
+ node_id="v1",
45
+ input_mapping={"files": ["a.py"], "checks": ["lint"]},
46
+ output_key="validation",
47
+ )
48
+ result = await CodeValidationHandler()(node, ctx, reg)
49
+ cmd = reg.execute.call_args.kwargs["command"]
50
+ assert cmd == "ruff check a.py"
51
+ assert result.status.value == "completed"
52
+ assert ctx.get("validation")["all_passed"] is True
53
+ assert ctx.get("validation")["checks"]["lint"]["passed"] is True
54
+
55
+ @pytest.mark.asyncio
56
+ async def test_failed_check_still_completes_with_all_passed_false(self):
57
+ """code_validation's fail policy: COMPLETED status, failure in output."""
58
+ reg = registry(MockToolResult(success=False, error="E501"))
59
+ ctx = MockWorkflowContext()
60
+ node = MockComputeNode(node_id="v2", input_mapping={"files": ["b.py"], "checks": ["lint"]})
61
+ result = await CodeValidationHandler()(node, ctx, reg)
62
+ assert result.status.value == "completed"
63
+ assert ctx.get("v2")["all_passed"] is False
64
+
65
+ @pytest.mark.asyncio
66
+ async def test_unknown_check_passes_with_message(self):
67
+ reg = registry(MockToolResult(success=True))
68
+ node = MockComputeNode(
69
+ node_id="v3", input_mapping={"files": ["x.py"], "checks": ["nonexistent"]}
70
+ )
71
+ ctx = MockWorkflowContext()
72
+ result = await CodeValidationHandler()(node, ctx, reg)
73
+ assert result.status.value == "completed"
74
+ assert ctx.get("v3")["checks"]["nonexistent"]["passed"] is True
75
+
76
+ @pytest.mark.asyncio
77
+ async def test_exception_is_contained_per_check(self):
78
+ """Actual behavior: _run_check catches exceptions and reports them as
79
+ failed checks — the node still COMPLETES (no outer try/except)."""
80
+ reg = MagicMock()
81
+ reg.execute = AsyncMock(side_effect=RuntimeError("boom"))
82
+ node = MockComputeNode(node_id="v4", input_mapping={"files": ["c.py"]})
83
+ ctx = MockWorkflowContext()
84
+ result = await CodeValidationHandler()(node, ctx, reg)
85
+ assert result.status.value == "completed"
86
+ assert ctx.get("v4")["all_passed"] is False
87
+ assert "boom" in ctx.get("v4")["checks"]["lint"]["error"]
88
+
89
+
90
+ class TestTestRunnerHandler:
91
+ @pytest.mark.asyncio
92
+ async def test_pytest_command_with_coverage(self):
93
+ reg = registry(MockToolResult(success=True, output="3 passed"))
94
+ node = MockComputeNode(
95
+ node_id="t1",
96
+ input_mapping={"test_path": "tests/", "framework": "pytest", "coverage": True},
97
+ output_key="test_results",
98
+ )
99
+ ctx = MockWorkflowContext()
100
+ result = await TestRunnerHandler()(node, ctx, reg)
101
+ cmd = reg.execute.call_args.kwargs["command"]
102
+ assert cmd == "pytest tests/ -v --cov --cov-report=json"
103
+ assert result.status.value == "completed"
104
+ assert ctx.get("test_results")["passed"] is True
105
+
106
+ @pytest.mark.asyncio
107
+ async def test_failed_suite_fails_the_node(self):
108
+ """test_runner's fail policy: FAILED status on suite failure (unlike
109
+ code_validation — the kernel must parameterize this)."""
110
+ reg = registry(MockToolResult(success=False, output="1 failed"))
111
+ node = MockComputeNode(node_id="t2", input_mapping={"framework": "pytest"})
112
+ ctx = MockWorkflowContext()
113
+ result = await TestRunnerHandler()(node, ctx, reg)
114
+ assert result.status.value == "failed"
115
+
116
+ @pytest.mark.asyncio
117
+ async def test_unittest_framework_command(self):
118
+ reg = registry(MockToolResult(success=True))
119
+ node = MockComputeNode(node_id="t3", input_mapping={"framework": "unittest"})
120
+ ctx = MockWorkflowContext()
121
+ await TestRunnerHandler()(node, ctx, reg)
122
+ cmd = reg.execute.call_args.kwargs["command"]
123
+ assert cmd.startswith("python -m unittest discover")
124
+
125
+
126
+ class TestRegistration:
127
+ def test_handlers_table_and_registrar_signature(self):
128
+ assert set(HANDLERS) == {"code_validation", "test_runner"}
129
+ # The UI introspects this signature; the kernel must keep it.
130
+ import inspect
131
+
132
+ from victor_coding.handlers import register_handlers
133
+
134
+ params = inspect.signature(register_handlers).parameters
135
+ assert "registrar" in params
136
+
137
+ def test_register_via_explicit_registrar(self):
138
+ entries: Dict[str, Any] = {}
139
+
140
+ class Registrar:
141
+ def __call__(self, name: str, handler: Any) -> None:
142
+ entries[name] = handler
143
+
144
+ from victor_coding.handlers import register_handlers
145
+
146
+ register_handlers(Registrar())
147
+ assert set(entries) == set(HANDLERS)
@@ -1,4 +1,4 @@
1
- # Copyright 2025 Vijaykumar Singh <singhvjd@gmail.com>
1
+ # Copyright 2025 Vijaykumar Singh <vijay@anvaiops.com>
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2025 Vijaykumar Singh <singhvjd@gmail.com>
1
+ # Copyright 2025 Vijaykumar Singh <vijay@anvaiops.com>
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2025 Vijaykumar Singh <singhvjd@gmail.com>
1
+ # Copyright 2025 Vijaykumar Singh <vijay@anvaiops.com>
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -285,3 +285,41 @@ class TestWorkflowIntegration:
285
285
  # Most agent nodes should have allowed_tools
286
286
  # (not all require it, but most do)
287
287
  pass # Just ensure no crashes
288
+
289
+
290
+ class TestSharedEscapeHatches:
291
+ """Generic hatches come from the framework registry, not a local copy."""
292
+
293
+ SHARED = {
294
+ "complexity_check": "condition",
295
+ "complexity_assessment": "condition",
296
+ "format_implementation_plan": "transform",
297
+ }
298
+
299
+ def test_provider_resolves_the_shared_hatches(self):
300
+ config = CodingWorkflowProvider()._get_config()
301
+ for name, kind in self.SHARED.items():
302
+ registry = (
303
+ config.condition_registry if kind == "condition" else config.transform_registry
304
+ )
305
+ assert name in registry, f"{name} missing from the coding workflow {kind}s"
306
+ assert callable(registry[name])
307
+
308
+ def test_refactor_workflow_still_routes_on_complexity(self):
309
+ """refactor.yaml branches on complexity_assessment."""
310
+ config = CodingWorkflowProvider()._get_config()
311
+ assess = config.condition_registry["complexity_assessment"]
312
+ assert assess({"files_affected": list(range(30))}) in {
313
+ "high",
314
+ "complex",
315
+ "medium",
316
+ "low",
317
+ "simple",
318
+ }
319
+
320
+ def test_not_redefined_locally(self):
321
+ import victor_coding.escape_hatches as local
322
+
323
+ for name in self.SHARED:
324
+ assert not hasattr(local, name), f"{name} copied back into victor_coding.escape_hatches"
325
+ assert not set(self.SHARED) & (set(local.CONDITIONS) | set(local.TRANSFORMS))
@@ -1,4 +1,4 @@
1
- # Copyright 2025 Vijaykumar Singh <singhvjd@gmail.com>
1
+ # Copyright 2025 Vijaykumar Singh <vijay@anvaiops.com>
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -300,7 +300,7 @@ class TestEnhancedCodingConversationManager:
300
300
  manager = EnhancedCodingConversationManager()
301
301
 
302
302
  assert manager._conversation_coordinator is not None
303
- assert isinstance(manager._coding_context, CodingContext)
303
+ assert isinstance(manager.get_coding_context(), CodingContext)
304
304
 
305
305
  def test_add_message(self):
306
306
  """Test adding a message."""
@@ -1,4 +1,4 @@
1
- # Copyright 2025 Vijaykumar Singh <singhvjd@gmail.com>
1
+ # Copyright 2025 Vijaykumar Singh <vijay@anvaiops.com>
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2026 Vijaykumar Singh <singhvjd@gmail.com>
1
+ # Copyright 2026 Vijaykumar Singh <vijay@anvaiops.com>
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -0,0 +1,70 @@
1
+ # Copyright 2026 Vijaykumar Singh <vijay@anvaiops.com>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """The graph tool and index shim must honor `.victor/graph_backend`.
16
+
17
+ Previously: the `graph` tool probed project.db's sqlite tables (dropping the
18
+ tool from the LLM schema on marker'd repos whose graph lives elsewhere) and
19
+ hardcoded SqliteGraphStore; the indexer accepted `graph_store_name` and
20
+ silently dropped it; the shim defaulted to sqlite. A repo flipped to another
21
+ backend got sqlite everywhere.
22
+ """
23
+
24
+ from pathlib import Path
25
+
26
+ from victor_coding.tools.graph_tool import (
27
+ _project_graph_has_data,
28
+ _resolved_graph_backend,
29
+ )
30
+
31
+
32
+ def _mark(tmp_path: Path, backend: str) -> Path:
33
+ marker_dir = tmp_path / ".victor"
34
+ marker_dir.mkdir(exist_ok=True)
35
+ (marker_dir / "graph_backend").write_text(backend)
36
+ return tmp_path
37
+
38
+
39
+ def test_resolved_backend_reads_marker(tmp_path: Path):
40
+ assert _resolved_graph_backend(tmp_path) == "sqlite"
41
+ _mark(tmp_path, "proxima")
42
+ assert _resolved_graph_backend(tmp_path) == "proxima"
43
+
44
+
45
+ def test_has_data_advertises_tool_on_marked_repos(tmp_path: Path):
46
+ # A proxima-marked repo must not be probed via project.db's sqlite
47
+ # tables (which are legitimately empty there) — the tool stays
48
+ # advertised and the load path constructs the real store.
49
+ _mark(tmp_path, "proxima")
50
+ assert _project_graph_has_data(tmp_path) is True
51
+
52
+
53
+ def test_shim_default_is_auto():
54
+ import inspect
55
+
56
+ from victor_coding.codebase.graph.registry import create_graph_store
57
+
58
+ sig = inspect.signature(create_graph_store)
59
+ assert sig.parameters["name"].default == "auto"
60
+
61
+
62
+ def test_indexer_threads_graph_store_name():
63
+ import inspect
64
+
65
+ from victor_coding.codebase.indexer import CodebaseIndex
66
+
67
+ src = inspect.getsource(CodebaseIndex.__init__)
68
+ assert (
69
+ 'name=graph_store_name or "auto"' in src
70
+ ), "graph_store_name must reach create_graph_store, not be dropped"
@@ -0,0 +1,143 @@
1
+ # Copyright 2026 Vijaykumar Singh <vijay@anvaiops.com>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Pre-move characterization for victor-coding personas (dedup F6).
16
+
17
+ Coding was the only personas vertical with NO test file. These pin the
18
+ observable contract before the kernel extraction: inventory, trait
19
+ normalization, prompt hints, backstory shape, helper semantics, and explicit-provider
20
+ registration (registration tuples included). Import-time registration was
21
+ removed by FEP-0042.
22
+ """
23
+
24
+ from victor_contracts.testing.personas import (
25
+ assert_explicit_persona_registration,
26
+ assert_import_registers_no_personas,
27
+ )
28
+ from victor_coding.teams.personas import (
29
+ CODING_PERSONAS,
30
+ CodingPersonaTraits,
31
+ CommunicationStyle,
32
+ DecisionStyle,
33
+ apply_persona_to_spec,
34
+ get_persona,
35
+ get_persona_by_expertise,
36
+ get_personas_for_role,
37
+ list_personas,
38
+ )
39
+
40
+
41
+ class TestInventory:
42
+ def test_eight_personas_with_expected_ids(self):
43
+ assert set(CODING_PERSONAS) == {
44
+ "code_archaeologist",
45
+ "security_auditor",
46
+ "architect",
47
+ "refactoring_strategist",
48
+ "craftsman",
49
+ "debugger",
50
+ "quality_guardian",
51
+ "test_specialist",
52
+ }
53
+
54
+ def test_every_persona_complete(self):
55
+ for pid, persona in CODING_PERSONAS.items():
56
+ assert persona.name, pid
57
+ assert persona.role in ("researcher", "planner", "executor", "reviewer"), pid
58
+ assert persona.expertise, pid
59
+ assert persona.strengths, pid
60
+ assert persona.approach, pid
61
+
62
+
63
+ class TestTraits:
64
+ def test_trait_scales_normalized(self):
65
+ traits = CodingPersonaTraits(attention_to_detail=2.0, risk_tolerance=-1.0, verbosity=0.5)
66
+ # values are stored as given (no clamping in the dataclass)
67
+ assert traits.attention_to_detail == 2.0
68
+ assert traits.risk_tolerance == -1.0
69
+
70
+ def test_prompt_hints_composition(self):
71
+ traits = CodingPersonaTraits(
72
+ communication_style=CommunicationStyle.CONCISE,
73
+ decision_style=DecisionStyle.CONSERVATIVE,
74
+ attention_to_detail=0.9,
75
+ risk_tolerance=0.1,
76
+ )
77
+ hints = traits.to_prompt_hints()
78
+ assert "brief" in hints.lower()
79
+ assert "proven" in hints.lower()
80
+ assert "edge cases" in hints.lower()
81
+ assert "thorough testing" in hints.lower()
82
+
83
+ def test_framework_traits_mapping(self):
84
+ traits = CodingPersonaTraits(attention_to_detail=0.8, risk_tolerance=0.4, verbosity=0.6)
85
+ fw = traits.to_framework_traits(name="X", role="executor", description="d", strengths=["s"])
86
+ assert fw.risk_tolerance == 0.4
87
+ assert fw.verbosity == 0.6
88
+ # coding's mapping: creativity = 1 - attention_to_detail
89
+ assert abs(fw.creativity - 0.2) < 1e-9
90
+ assert fw.custom_traits["decision_style"]
91
+ assert fw.custom_traits["attention_to_detail"] == 0.8
92
+
93
+
94
+ class TestPersonaSemantics:
95
+ def test_get_expertise_list_merges_primary_and_secondary(self):
96
+ p = get_persona("architect")
97
+ lst = p.get_expertise_list()
98
+ assert lst
99
+ assert all(isinstance(e, str) for e in lst)
100
+
101
+ def test_generate_backstory_shape(self):
102
+ story = get_persona("debugger").generate_backstory()
103
+ assert story.startswith("You are ")
104
+ assert "Bug Hunter" in story
105
+ assert story.endswith(".")
106
+
107
+ def test_helpers(self):
108
+ assert set(list_personas()) == set(CODING_PERSONAS)
109
+ planners = get_personas_for_role("planner")
110
+ assert planners
111
+ assert all(p.role == "planner" for p in planners)
112
+ found = get_persona_by_expertise(CODING_PERSONAS["architect"].expertise[0])
113
+ assert found
114
+
115
+ def test_apply_persona_to_spec_merges(self):
116
+ from victor_contracts import TeamMemberSpec
117
+
118
+ spec = TeamMemberSpec(role="planner", goal="ship", name="a1")
119
+ out = apply_persona_to_spec(spec, "architect")
120
+ # documented contract: same object, enhanced in place
121
+ assert out is spec
122
+ assert getattr(spec, "expertise", None) or getattr(spec, "backstory", None)
123
+ # unknown persona: unchanged spec returned
124
+ spec2 = TeamMemberSpec(role="planner", goal="ship", name="a2")
125
+ assert apply_persona_to_spec(spec2, "no_such_persona") is spec2
126
+
127
+
128
+ class TestPersonaRegistration:
129
+ """FEP-0042: personas reach the host through ``get_personas()`` on activation;
130
+ nothing registers at import, and the explicit-provider helper still works."""
131
+
132
+ def test_teams_import_registers_nothing_and_emits_no_deprecation(self):
133
+ assert_import_registers_no_personas("victor_coding.teams", "victor_coding.teams.personas")
134
+
135
+ def test_explicit_provider_helper_registers_every_persona_without_warning(self):
136
+ from victor_coding.teams.personas import _register_personas_with_framework
137
+
138
+ calls = assert_explicit_persona_registration(
139
+ _register_personas_with_framework, CODING_PERSONAS, "coding"
140
+ )
141
+ debugger = next(c for c in calls if c["name"] == "debugger")
142
+ assert debugger["category"] == "execution"
143
+ assert debugger["tags"] == ["debugging", "troubleshooting", "root-cause"]