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.
- {victor_coding-0.7.2 → victor_coding-0.14.0}/LICENSE +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/PKG-INFO +11 -12
- {victor_coding-0.7.2 → victor_coding-0.14.0}/pyproject.toml +26 -25
- {victor_coding-0.7.2 → victor_coding-0.14.0}/tests/test_coding_capabilities.py +1 -1
- victor_coding-0.14.0/tests/test_coding_handlers.py +147 -0
- {victor_coding-0.7.2 → victor_coding-0.14.0}/tests/test_coding_vertical_rl.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/tests/test_coding_vertical_teams.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/tests/test_coding_vertical_workflows.py +39 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/tests/test_enhanced_integration.py +2 -2
- {victor_coding-0.7.2 → victor_coding-0.14.0}/tests/test_extension_cache.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/tests/test_framework_lsp_adapter.py +1 -1
- victor_coding-0.14.0/tests/test_graph_backend_marker.py +70 -0
- victor_coding-0.14.0/tests/test_personas.py +143 -0
- victor_coding-0.14.0/tests/test_protocol_providers.py +68 -0
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/assistant.py +2 -2
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/capabilities.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/__init__.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/ccg_builder.py +203 -28
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/chunker.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/embeddings/__init__.py +8 -6
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/embeddings/chunker.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/graph/__init__.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/graph/registry.py +6 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/ignore_patterns.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/indexer.py +100 -77
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/query_expander.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/symbol_store.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/tree_sitter_analysis.py +72 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/tree_sitter_extractor.py +5 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/tree_sitter_manager.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/tree_sitter_service.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/unified_extractor.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase_analyzer.py +42 -687
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/composed_chains.py +2 -114
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/conversation_enhanced.py +18 -160
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/coverage/__init__.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/coverage/manager.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/coverage/parser.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/coverage/parsers/__init__.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/coverage/protocol.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/coverage/visualizer.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/docgen/__init__.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/docgen/formatter.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/docgen/manager.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/docgen/parser.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/docgen/protocol.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/editing/__init__.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/enrichment.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/escape_hatches.py +6 -142
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/handlers.py +13 -51
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/__init__.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/base.py +62 -4
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/manager.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/plugins/__init__.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/plugins/additional.py +52 -381
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/plugins/config.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/plugins/cpp.py +2 -59
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/plugins/go.py +2 -58
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/plugins/java.py +2 -58
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/plugins/javascript.py +5 -53
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/plugins/python.py +2 -65
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/plugins/rust.py +3 -12
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/plugins/typescript.py +2 -59
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/registry.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/languages/tiers.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/lsp/__init__.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/lsp/client.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/lsp/config.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/lsp/framework_adapter.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/lsp/manager.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/middleware.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/mode_config.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/native/__init__.py +5 -5
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/performance/__init__.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/performance/factory.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/performance/protocols.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/performance/registry.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/performance/service_provider.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/performance/settings.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/performance/wrappers.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/prompts.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/protocols.py +47 -64
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/refactor/__init__.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/refactor/analyzer.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/refactor/manager.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/refactor/protocol.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/refactor/transforms/__init__.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/refactor/transforms/base.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/refactor/transforms/extract.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/refactor/transforms/rename.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/review/__init__.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/review/analyzers.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/review/manager.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/review/protocol.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/review/rules.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/rl/__init__.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/rl/config.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/rl/hooks.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/safety.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/safety_enhanced.py +23 -159
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/service_provider.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/teams/__init__.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/teams/personas.py +97 -350
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/teams/specs.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/testgen/__init__.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/testgen/analyzer.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/testgen/generator.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/testgen/manager.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/testgen/protocol.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/tool_dependencies.py +1 -1
- victor_coding-0.14.0/victor_coding/tools/code_executor_tool.py +552 -0
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/tools/code_intelligence_tool.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/tools/code_search_tool.py +76 -246
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/tools/graph_tool.py +48 -23
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/workflows/__init__.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/workflows/bugfix.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/workflows/feature.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/workflows/provider.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/workflows/review.py +1 -1
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding.egg-info/PKG-INFO +11 -12
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding.egg-info/SOURCES.txt +4 -16
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding.egg-info/requires.txt +7 -7
- victor_coding-0.7.2/victor_coding/codebase/embeddings/base.py +0 -247
- victor_coding-0.7.2/victor_coding/codebase/embeddings/lancedb_provider.py +0 -418
- victor_coding-0.7.2/victor_coding/codebase/embeddings/models.py +0 -530
- victor_coding-0.7.2/victor_coding/codebase/embeddings/proximadb_provider.py +0 -624
- victor_coding-0.7.2/victor_coding/codebase/embeddings/registry.py +0 -140
- victor_coding-0.7.2/victor_coding/codebase/graph/protocol.py +0 -110
- victor_coding-0.7.2/victor_coding/completion/__init__.py +0 -119
- victor_coding-0.7.2/victor_coding/completion/manager.py +0 -511
- victor_coding-0.7.2/victor_coding/completion/protocol.py +0 -51
- victor_coding-0.7.2/victor_coding/completion/provider.py +0 -363
- victor_coding-0.7.2/victor_coding/completion/providers/__init__.py +0 -25
- victor_coding-0.7.2/victor_coding/completion/providers/ai.py +0 -409
- victor_coding-0.7.2/victor_coding/completion/providers/lsp.py +0 -313
- victor_coding-0.7.2/victor_coding/completion/providers/snippet.py +0 -532
- victor_coding-0.7.2/victor_coding/completion/registry.py +0 -305
- victor_coding-0.7.2/victor_coding/editing/editor.py +0 -598
- victor_coding-0.7.2/victor_coding/tools/code_executor_tool.py +0 -600
- {victor_coding-0.7.2 → victor_coding-0.14.0}/README.md +0 -0
- {victor_coding-0.7.2 → victor_coding-0.14.0}/setup.cfg +0 -0
- {victor_coding-0.7.2 → victor_coding-0.14.0}/tests/test_api_router_provider.py +0 -0
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/__init__.py +0 -0
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/api/__init__.py +0 -0
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/api/router_provider.py +0 -0
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/architecture_analyzer.py +0 -0
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/symbol_extractor.py +0 -0
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/codebase/symbol_resolver.py +0 -0
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/compat/__init__.py +0 -0
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/compat/settings.py +0 -0
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/plugin.py +0 -0
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/skills.py +0 -0
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding/tools/__init__.py +0 -0
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding.egg-info/dependency_links.txt +0 -0
- {victor_coding-0.7.2 → victor_coding-0.14.0}/victor_coding.egg-info/entry_points.txt +0 -0
- {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 <
|
|
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.
|
|
3
|
+
Version: 0.14.0
|
|
4
4
|
Summary: Coding vertical for Victor AI - Software development, debugging, and code generation
|
|
5
|
-
Author-email: Vijaykumar Singh <
|
|
6
|
-
Maintainer-email: Vijaykumar Singh <
|
|
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.
|
|
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.
|
|
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.
|
|
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:
|
|
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
|
|
38
|
+
Requires-Dist: black==26.10.1; extra == "dev"
|
|
40
39
|
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
41
|
-
Requires-Dist: mypy
|
|
40
|
+
Requires-Dist: mypy==2.4.0; extra == "dev"
|
|
42
41
|
Provides-Extra: native-dev
|
|
43
|
-
Requires-Dist: maturin<2.0,>=1.
|
|
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>=
|
|
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.
|
|
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.
|
|
13
|
+
requires-python = ">=3.12"
|
|
14
14
|
license = {text = "Apache-2.0"}
|
|
15
15
|
authors = [
|
|
16
|
-
{ name = "Vijaykumar Singh", email = "
|
|
16
|
+
{ name = "Vijaykumar Singh", email = "vijay@anvaiops.com" },
|
|
17
17
|
]
|
|
18
18
|
maintainers = [
|
|
19
|
-
{ name = "Vijaykumar Singh", email = "
|
|
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.
|
|
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
|
-
#
|
|
50
|
-
#
|
|
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
|
|
54
|
-
#
|
|
55
|
-
#
|
|
56
|
-
# to victor-ai's proximadb extra
|
|
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.
|
|
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
|
-
"
|
|
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
|
|
70
|
+
"black==26.10.1",
|
|
73
71
|
"ruff>=0.5",
|
|
74
|
-
"mypy
|
|
72
|
+
"mypy==2.4.0",
|
|
75
73
|
]
|
|
76
74
|
native-dev = [
|
|
77
|
-
"maturin>=1.
|
|
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,
|
|
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 = "
|
|
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.
|
|
191
|
+
python_version = "3.12"
|
|
191
192
|
warn_return_any = true
|
|
@@ -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 <
|
|
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 <
|
|
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.
|
|
303
|
+
assert isinstance(manager.get_coding_context(), CodingContext)
|
|
304
304
|
|
|
305
305
|
def test_add_message(self):
|
|
306
306
|
"""Test adding a message."""
|
|
@@ -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"]
|