tapps-agents 3.5.39__py3-none-any.whl → 3.5.41__py3-none-any.whl
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.
- tapps_agents/__init__.py +2 -2
- tapps_agents/agents/enhancer/agent.py +2728 -2728
- tapps_agents/agents/implementer/agent.py +35 -13
- tapps_agents/agents/reviewer/agent.py +43 -10
- tapps_agents/agents/reviewer/scoring.py +59 -68
- tapps_agents/agents/reviewer/tools/__init__.py +24 -0
- tapps_agents/agents/reviewer/tools/ruff_grouping.py +250 -0
- tapps_agents/agents/reviewer/tools/scoped_mypy.py +284 -0
- tapps_agents/beads/__init__.py +11 -0
- tapps_agents/beads/hydration.py +213 -0
- tapps_agents/beads/specs.py +206 -0
- tapps_agents/cli/commands/health.py +19 -3
- tapps_agents/cli/commands/simple_mode.py +842 -676
- tapps_agents/cli/commands/task.py +227 -0
- tapps_agents/cli/commands/top_level.py +13 -0
- tapps_agents/cli/main.py +658 -651
- tapps_agents/cli/parsers/top_level.py +1978 -1881
- tapps_agents/core/config.py +1622 -1622
- tapps_agents/core/init_project.py +3012 -2897
- tapps_agents/epic/markdown_sync.py +105 -0
- tapps_agents/epic/orchestrator.py +1 -2
- tapps_agents/epic/parser.py +427 -423
- tapps_agents/experts/adaptive_domain_detector.py +0 -2
- tapps_agents/experts/knowledge/api-design-integration/api-security-patterns.md +15 -15
- tapps_agents/experts/knowledge/api-design-integration/external-api-integration.md +19 -44
- tapps_agents/health/checks/outcomes.backup_20260204_064058.py +324 -0
- tapps_agents/health/checks/outcomes.backup_20260204_064256.py +324 -0
- tapps_agents/health/checks/outcomes.backup_20260204_064600.py +324 -0
- tapps_agents/health/checks/outcomes.py +134 -46
- tapps_agents/health/orchestrator.py +12 -4
- tapps_agents/hooks/__init__.py +33 -0
- tapps_agents/hooks/config.py +140 -0
- tapps_agents/hooks/events.py +135 -0
- tapps_agents/hooks/executor.py +128 -0
- tapps_agents/hooks/manager.py +143 -0
- tapps_agents/session/__init__.py +19 -0
- tapps_agents/session/manager.py +256 -0
- tapps_agents/simple_mode/code_snippet_handler.py +382 -0
- tapps_agents/simple_mode/intent_parser.py +29 -4
- tapps_agents/simple_mode/orchestrators/base.py +185 -59
- tapps_agents/simple_mode/orchestrators/build_orchestrator.py +2667 -2642
- tapps_agents/simple_mode/orchestrators/fix_orchestrator.py +2 -2
- tapps_agents/simple_mode/workflow_suggester.py +37 -3
- tapps_agents/workflow/agent_handlers/implementer_handler.py +18 -3
- tapps_agents/workflow/cursor_executor.py +2337 -2118
- tapps_agents/workflow/direct_execution_fallback.py +16 -3
- tapps_agents/workflow/message_formatter.py +2 -1
- tapps_agents/workflow/models.py +38 -1
- tapps_agents/workflow/parallel_executor.py +43 -4
- tapps_agents/workflow/parser.py +375 -357
- tapps_agents/workflow/rules_generator.py +337 -337
- tapps_agents/workflow/skill_invoker.py +9 -3
- {tapps_agents-3.5.39.dist-info → tapps_agents-3.5.41.dist-info}/METADATA +5 -1
- {tapps_agents-3.5.39.dist-info → tapps_agents-3.5.41.dist-info}/RECORD +58 -54
- tapps_agents/agents/analyst/SKILL.md +0 -85
- tapps_agents/agents/architect/SKILL.md +0 -80
- tapps_agents/agents/debugger/SKILL.md +0 -66
- tapps_agents/agents/designer/SKILL.md +0 -78
- tapps_agents/agents/documenter/SKILL.md +0 -95
- tapps_agents/agents/enhancer/SKILL.md +0 -189
- tapps_agents/agents/implementer/SKILL.md +0 -117
- tapps_agents/agents/improver/SKILL.md +0 -55
- tapps_agents/agents/ops/SKILL.md +0 -64
- tapps_agents/agents/orchestrator/SKILL.md +0 -238
- tapps_agents/agents/planner/story_template.md +0 -37
- tapps_agents/agents/reviewer/templates/quality-dashboard.html.j2 +0 -150
- tapps_agents/agents/tester/SKILL.md +0 -71
- {tapps_agents-3.5.39.dist-info → tapps_agents-3.5.41.dist-info}/WHEEL +0 -0
- {tapps_agents-3.5.39.dist-info → tapps_agents-3.5.41.dist-info}/entry_points.txt +0 -0
- {tapps_agents-3.5.39.dist-info → tapps_agents-3.5.41.dist-info}/licenses/LICENSE +0 -0
- {tapps_agents-3.5.39.dist-info → tapps_agents-3.5.41.dist-info}/top_level.txt +0 -0
tapps_agents/core/config.py
CHANGED
|
@@ -1,1622 +1,1622 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Configuration management for TappsCodingAgents.
|
|
3
|
-
|
|
4
|
-
Provides Pydantic models for type-safe configuration and YAML loading.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
from pathlib import Path
|
|
8
|
-
from typing import Any
|
|
9
|
-
|
|
10
|
-
import yaml
|
|
11
|
-
from pydantic import BaseModel, Field, model_validator
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class ScoringWeightsConfig(BaseModel):
|
|
15
|
-
"""Configuration for code scoring weights (must sum to 1.0). 7-category: Structure, DevEx added (MCP_SYSTEMS_IMPROVEMENT_RECOMMENDATIONS §3.2)."""
|
|
16
|
-
|
|
17
|
-
complexity: float = Field(
|
|
18
|
-
default=0.18, ge=0.0, le=1.0, description="Weight for complexity score"
|
|
19
|
-
)
|
|
20
|
-
security: float = Field(
|
|
21
|
-
default=0.27, ge=0.0, le=1.0, description="Weight for security score"
|
|
22
|
-
)
|
|
23
|
-
maintainability: float = Field(
|
|
24
|
-
default=0.24, ge=0.0, le=1.0, description="Weight for maintainability score"
|
|
25
|
-
)
|
|
26
|
-
test_coverage: float = Field(
|
|
27
|
-
default=0.13, ge=0.0, le=1.0, description="Weight for test coverage score"
|
|
28
|
-
)
|
|
29
|
-
performance: float = Field(
|
|
30
|
-
default=0.08, ge=0.0, le=1.0, description="Weight for performance score"
|
|
31
|
-
)
|
|
32
|
-
structure: float = Field(
|
|
33
|
-
default=0.05, ge=0.0, le=1.0, description="Weight for structure score (project layout, key files)"
|
|
34
|
-
)
|
|
35
|
-
devex: float = Field(
|
|
36
|
-
default=0.05, ge=0.0, le=1.0, description="Weight for developer experience score (docs, config, tooling)"
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
@model_validator(mode="after")
|
|
40
|
-
def validate_weights_sum(self):
|
|
41
|
-
"""Ensure weights sum to approximately 1.0"""
|
|
42
|
-
total = (
|
|
43
|
-
self.complexity
|
|
44
|
-
+ self.security
|
|
45
|
-
+ self.maintainability
|
|
46
|
-
+ self.test_coverage
|
|
47
|
-
+ self.performance
|
|
48
|
-
+ self.structure
|
|
49
|
-
+ self.devex
|
|
50
|
-
)
|
|
51
|
-
if abs(total - 1.0) > 0.01: # Allow small floating point errors
|
|
52
|
-
raise ValueError(f"Scoring weights must sum to 1.0, got {total}")
|
|
53
|
-
return self
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
class TestCoverageConfig(BaseModel):
|
|
57
|
-
"""Test coverage configuration for quality gates."""
|
|
58
|
-
|
|
59
|
-
enabled: bool = Field(default=True, description="Enable test coverage checks")
|
|
60
|
-
threshold: float = Field(
|
|
61
|
-
default=0.8, ge=0.0, le=1.0, description="Minimum coverage threshold (0.0-1.0)"
|
|
62
|
-
)
|
|
63
|
-
critical_services_threshold: float = Field(
|
|
64
|
-
default=0.8,
|
|
65
|
-
ge=0.0,
|
|
66
|
-
le=1.0,
|
|
67
|
-
description="Minimum coverage for critical services (0.0-1.0)",
|
|
68
|
-
)
|
|
69
|
-
warning_threshold: float = Field(
|
|
70
|
-
default=0.6,
|
|
71
|
-
ge=0.0,
|
|
72
|
-
le=1.0,
|
|
73
|
-
description="Coverage threshold for warnings (0.0-1.0)",
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
class QualityGatesConfig(BaseModel):
|
|
78
|
-
"""Quality gates configuration."""
|
|
79
|
-
|
|
80
|
-
enabled: bool = Field(default=True, description="Enable quality gates")
|
|
81
|
-
test_coverage: TestCoverageConfig = Field(
|
|
82
|
-
default_factory=TestCoverageConfig, description="Test coverage configuration"
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
class ScoringConfig(BaseModel):
|
|
87
|
-
"""Configuration for code scoring system"""
|
|
88
|
-
|
|
89
|
-
weights: ScoringWeightsConfig = Field(default_factory=ScoringWeightsConfig)
|
|
90
|
-
quality_threshold: float = Field(
|
|
91
|
-
default=70.0, ge=0.0, le=100.0, description="Minimum overall score to pass"
|
|
92
|
-
)
|
|
93
|
-
quality_gates: QualityGatesConfig = Field(
|
|
94
|
-
default_factory=QualityGatesConfig, description="Quality gates configuration"
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
class ReviewerAgentContext7Config(BaseModel):
|
|
99
|
-
"""Context7 configuration for Reviewer Agent"""
|
|
100
|
-
|
|
101
|
-
auto_detect: bool = Field(
|
|
102
|
-
default=True, description="Enable automatic library detection"
|
|
103
|
-
)
|
|
104
|
-
topics: list[str] = Field(
|
|
105
|
-
default_factory=lambda: ["best-practices", "routing", "api-design"],
|
|
106
|
-
description="Default topics to fetch for detected libraries"
|
|
107
|
-
)
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
class ReviewerAgentConfig(BaseModel):
|
|
111
|
-
"""Configuration specific to Reviewer Agent"""
|
|
112
|
-
|
|
113
|
-
quality_threshold: float = Field(
|
|
114
|
-
default=70.0, ge=0.0, le=100.0, description="Minimum score to pass review"
|
|
115
|
-
)
|
|
116
|
-
include_scoring: bool = Field(
|
|
117
|
-
default=True, description="Include code scoring in review"
|
|
118
|
-
)
|
|
119
|
-
include_llm_feedback: bool = Field(
|
|
120
|
-
default=True, description="Include LLM-generated feedback"
|
|
121
|
-
)
|
|
122
|
-
max_file_size: int = Field(
|
|
123
|
-
default=1024 * 1024,
|
|
124
|
-
ge=1024,
|
|
125
|
-
description="Maximum file size in bytes (1MB default)",
|
|
126
|
-
)
|
|
127
|
-
min_confidence_threshold: float = Field(
|
|
128
|
-
default=0.8,
|
|
129
|
-
ge=0.0,
|
|
130
|
-
le=1.0,
|
|
131
|
-
description="Minimum expert confidence threshold (0.0-1.0)",
|
|
132
|
-
)
|
|
133
|
-
operation_timeout: float = Field(
|
|
134
|
-
default=300.0,
|
|
135
|
-
ge=10.0,
|
|
136
|
-
description="Timeout in seconds for reviewer operations (default: 5 minutes)",
|
|
137
|
-
)
|
|
138
|
-
tool_timeout: float = Field(
|
|
139
|
-
default=30.0,
|
|
140
|
-
ge=5.0,
|
|
141
|
-
description="Timeout in seconds for individual quality tools (default: 30 seconds)",
|
|
142
|
-
)
|
|
143
|
-
enable_parallel_tools: bool = Field(
|
|
144
|
-
default=True,
|
|
145
|
-
description="Enable parallel execution of quality tools (Ruff, mypy, bandit)",
|
|
146
|
-
)
|
|
147
|
-
context7: ReviewerAgentContext7Config = Field(
|
|
148
|
-
default_factory=ReviewerAgentContext7Config,
|
|
149
|
-
description="Context7 integration settings for Reviewer Agent"
|
|
150
|
-
)
|
|
151
|
-
# NEW: Library detection config
|
|
152
|
-
auto_library_detection: bool = Field(
|
|
153
|
-
default=True,
|
|
154
|
-
description="Automatically detect libraries from code and dependency files"
|
|
155
|
-
)
|
|
156
|
-
library_detection_depth: str = Field(
|
|
157
|
-
default="both",
|
|
158
|
-
description="What to detect: 'code' (imports only), 'dependencies' (requirements.txt/pyproject.toml), or 'both'"
|
|
159
|
-
)
|
|
160
|
-
# NEW: Context7 integration config
|
|
161
|
-
auto_context7_lookups: bool = Field(
|
|
162
|
-
default=True,
|
|
163
|
-
description="Automatically lookup library documentation from Context7"
|
|
164
|
-
)
|
|
165
|
-
context7_timeout: int = Field(
|
|
166
|
-
default=30,
|
|
167
|
-
ge=1,
|
|
168
|
-
le=300,
|
|
169
|
-
description="Timeout for Context7 lookups in seconds"
|
|
170
|
-
)
|
|
171
|
-
context7_cache_enabled: bool = Field(
|
|
172
|
-
default=True,
|
|
173
|
-
description="Cache Context7 responses to avoid duplicate lookups"
|
|
174
|
-
)
|
|
175
|
-
# NEW: Pattern detection config
|
|
176
|
-
pattern_detection_enabled: bool = Field(
|
|
177
|
-
default=True,
|
|
178
|
-
description="Enable domain-specific pattern detection"
|
|
179
|
-
)
|
|
180
|
-
pattern_confidence_threshold: float = Field(
|
|
181
|
-
default=0.5,
|
|
182
|
-
ge=0.0,
|
|
183
|
-
le=1.0,
|
|
184
|
-
description="Minimum confidence to report detected patterns (0.0-1.0)"
|
|
185
|
-
)
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
class PlannerAgentConfig(BaseModel):
|
|
189
|
-
"""Configuration specific to Planner Agent"""
|
|
190
|
-
|
|
191
|
-
stories_dir: str | None = Field(
|
|
192
|
-
default=None, description="Directory for storing stories (default: stories/)"
|
|
193
|
-
)
|
|
194
|
-
default_priority: str = Field(
|
|
195
|
-
default="medium",
|
|
196
|
-
description="Default priority for new stories (high/medium/low)",
|
|
197
|
-
)
|
|
198
|
-
min_confidence_threshold: float = Field(
|
|
199
|
-
default=0.6,
|
|
200
|
-
ge=0.0,
|
|
201
|
-
le=1.0,
|
|
202
|
-
description="Minimum expert confidence threshold (0.0-1.0)",
|
|
203
|
-
)
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
class ImplementerAgentContext7Config(BaseModel):
|
|
207
|
-
"""Context7 configuration for Implementer Agent"""
|
|
208
|
-
|
|
209
|
-
auto_detect: bool = Field(
|
|
210
|
-
default=True, description="Enable automatic library detection"
|
|
211
|
-
)
|
|
212
|
-
detect_from_prompt: bool = Field(
|
|
213
|
-
default=True, description="Detect libraries from prompt/specification text"
|
|
214
|
-
)
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
class ImplementerAgentConfig(BaseModel):
|
|
218
|
-
"""Configuration specific to Implementer Agent"""
|
|
219
|
-
|
|
220
|
-
require_review: bool = Field(
|
|
221
|
-
default=True, description="Require code review before writing files"
|
|
222
|
-
)
|
|
223
|
-
auto_approve_threshold: float = Field(
|
|
224
|
-
default=80.0, ge=0.0, le=100.0, description="Auto-approve if score >= threshold"
|
|
225
|
-
)
|
|
226
|
-
backup_files: bool = Field(
|
|
227
|
-
default=True, description="Create backup before overwriting existing files"
|
|
228
|
-
)
|
|
229
|
-
max_file_size: int = Field(
|
|
230
|
-
default=10 * 1024 * 1024,
|
|
231
|
-
ge=1024,
|
|
232
|
-
description="Maximum file size in bytes (10MB default)",
|
|
233
|
-
)
|
|
234
|
-
min_confidence_threshold: float = Field(
|
|
235
|
-
default=0.7,
|
|
236
|
-
ge=0.0,
|
|
237
|
-
le=1.0,
|
|
238
|
-
description="Minimum expert confidence threshold (0.0-1.0)",
|
|
239
|
-
)
|
|
240
|
-
context7: ImplementerAgentContext7Config = Field(
|
|
241
|
-
default_factory=ImplementerAgentContext7Config,
|
|
242
|
-
description="Context7 integration settings for Implementer Agent"
|
|
243
|
-
)
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
class TesterAgentConfig(BaseModel):
|
|
247
|
-
"""Configuration specific to Tester Agent"""
|
|
248
|
-
|
|
249
|
-
test_framework: str = Field(
|
|
250
|
-
default="pytest", description="Test framework to use (pytest/unittest)"
|
|
251
|
-
)
|
|
252
|
-
tests_dir: str | None = Field(
|
|
253
|
-
default=None, description="Directory for tests (default: tests/)"
|
|
254
|
-
)
|
|
255
|
-
coverage_threshold: float = Field(
|
|
256
|
-
default=80.0, ge=0.0, le=100.0, description="Target test coverage percentage"
|
|
257
|
-
)
|
|
258
|
-
auto_write_tests: bool = Field(
|
|
259
|
-
default=True, description="Automatically write generated tests to files"
|
|
260
|
-
)
|
|
261
|
-
min_confidence_threshold: float = Field(
|
|
262
|
-
default=0.7,
|
|
263
|
-
ge=0.0,
|
|
264
|
-
le=1.0,
|
|
265
|
-
description="Minimum expert confidence threshold (0.0-1.0)",
|
|
266
|
-
)
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
class DebuggerAgentContext7Config(BaseModel):
|
|
270
|
-
"""Context7 configuration for Debugger Agent"""
|
|
271
|
-
|
|
272
|
-
auto_detect: bool = Field(
|
|
273
|
-
default=True, description="Enable automatic library detection"
|
|
274
|
-
)
|
|
275
|
-
detect_from_errors: bool = Field(
|
|
276
|
-
default=True, description="Detect libraries from error messages and stack traces"
|
|
277
|
-
)
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
class DebuggerAgentConfig(BaseModel):
|
|
281
|
-
"""Configuration specific to Debugger Agent"""
|
|
282
|
-
|
|
283
|
-
include_code_examples: bool = Field(
|
|
284
|
-
default=True, description="Include code examples in fix suggestions"
|
|
285
|
-
)
|
|
286
|
-
max_context_lines: int = Field(
|
|
287
|
-
default=50,
|
|
288
|
-
ge=10,
|
|
289
|
-
le=200,
|
|
290
|
-
description="Maximum lines of code context to include in analysis",
|
|
291
|
-
)
|
|
292
|
-
min_confidence_threshold: float = Field(
|
|
293
|
-
default=0.7,
|
|
294
|
-
ge=0.0,
|
|
295
|
-
le=1.0,
|
|
296
|
-
description="Minimum expert confidence threshold (0.0-1.0)",
|
|
297
|
-
)
|
|
298
|
-
context7: DebuggerAgentContext7Config = Field(
|
|
299
|
-
default_factory=DebuggerAgentContext7Config,
|
|
300
|
-
description="Context7 integration settings for Debugger Agent"
|
|
301
|
-
)
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
class DocumenterAgentConfig(BaseModel):
|
|
305
|
-
"""Configuration specific to Documenter Agent"""
|
|
306
|
-
|
|
307
|
-
docs_dir: str | None = Field(
|
|
308
|
-
default=None, description="Directory for generated docs (default: docs/)"
|
|
309
|
-
)
|
|
310
|
-
include_examples: bool = Field(
|
|
311
|
-
default=True, description="Include code examples in documentation"
|
|
312
|
-
)
|
|
313
|
-
docstring_format: str = Field(
|
|
314
|
-
default="google", description="Docstring format (google/numpy/sphinx)"
|
|
315
|
-
)
|
|
316
|
-
min_confidence_threshold: float = Field(
|
|
317
|
-
default=0.5,
|
|
318
|
-
ge=0.0,
|
|
319
|
-
le=1.0,
|
|
320
|
-
description="Minimum expert confidence threshold (0.0-1.0)",
|
|
321
|
-
)
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
class Context7KnowledgeBaseConfig(BaseModel):
|
|
325
|
-
"""Configuration for Context7 knowledge base caching"""
|
|
326
|
-
|
|
327
|
-
enabled: bool = Field(default=True, description="Enable KB caching")
|
|
328
|
-
location: str = Field(
|
|
329
|
-
default=".tapps-agents/kb/context7-cache", description="KB cache directory"
|
|
330
|
-
)
|
|
331
|
-
sharding: bool = Field(default=True, description="Enable library-based sharding")
|
|
332
|
-
indexing: bool = Field(default=True, description="Enable indexing")
|
|
333
|
-
max_cache_size: str = Field(default="100MB", description="Maximum cache size")
|
|
334
|
-
hit_rate_threshold: float = Field(
|
|
335
|
-
default=0.7, ge=0.0, le=1.0, description="Target hit rate threshold"
|
|
336
|
-
)
|
|
337
|
-
fuzzy_match_threshold: float = Field(
|
|
338
|
-
default=0.7, ge=0.0, le=1.0, description="Fuzzy match confidence threshold"
|
|
339
|
-
)
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
class Context7RefreshConfig(BaseModel):
|
|
343
|
-
"""Configuration for Context7 auto-refresh system"""
|
|
344
|
-
|
|
345
|
-
enabled: bool = Field(default=True, description="Enable auto-refresh")
|
|
346
|
-
default_max_age_days: int = Field(
|
|
347
|
-
default=30, ge=1, description="Default max age for cache entries (days)"
|
|
348
|
-
)
|
|
349
|
-
check_on_access: bool = Field(default=True, description="Check staleness on access")
|
|
350
|
-
auto_queue: bool = Field(
|
|
351
|
-
default=True, description="Automatically queue stale entries"
|
|
352
|
-
)
|
|
353
|
-
auto_process_on_startup: bool = Field(
|
|
354
|
-
default=False, description="Process queue on agent startup"
|
|
355
|
-
)
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
class Context7Config(BaseModel):
|
|
359
|
-
"""Configuration for Context7 integration"""
|
|
360
|
-
|
|
361
|
-
enabled: bool = Field(default=True, description="Enable Context7 integration")
|
|
362
|
-
default_token_limit: int = Field(
|
|
363
|
-
default=3000, ge=100, description="Default token limit for Context7 docs"
|
|
364
|
-
)
|
|
365
|
-
cache_duration: int = Field(
|
|
366
|
-
default=3600, ge=0, description="Cache duration in seconds"
|
|
367
|
-
)
|
|
368
|
-
integration_level: str = Field(
|
|
369
|
-
default="optional", description="Integration level (mandatory/optional)"
|
|
370
|
-
)
|
|
371
|
-
usage_requirement: str | None = Field(
|
|
372
|
-
default=None, description="Usage requirement description"
|
|
373
|
-
)
|
|
374
|
-
bypass_forbidden: bool = Field(
|
|
375
|
-
default=True, description="Allow bypassing if Context7 unavailable"
|
|
376
|
-
)
|
|
377
|
-
# Enhancement: Automatic Context7 detection and fetching
|
|
378
|
-
auto_detect: bool = Field(
|
|
379
|
-
default=True, description="Enable automatic library detection from code, prompts, and errors"
|
|
380
|
-
)
|
|
381
|
-
auto_fetch: bool = Field(
|
|
382
|
-
default=True, description="Automatically fetch docs for detected libraries"
|
|
383
|
-
)
|
|
384
|
-
proactive_suggestions: bool = Field(
|
|
385
|
-
default=True, description="Proactively suggest Context7 lookups when library patterns detected"
|
|
386
|
-
)
|
|
387
|
-
|
|
388
|
-
knowledge_base: Context7KnowledgeBaseConfig = Field(
|
|
389
|
-
default_factory=Context7KnowledgeBaseConfig
|
|
390
|
-
)
|
|
391
|
-
refresh: Context7RefreshConfig = Field(default_factory=Context7RefreshConfig)
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
class QualityToolsConfig(BaseModel):
|
|
395
|
-
"""Configuration for quality analysis tools (Phase 6 - 2025 Standards)"""
|
|
396
|
-
|
|
397
|
-
# Ruff configuration
|
|
398
|
-
ruff_enabled: bool = Field(default=True, description="Enable Ruff linting")
|
|
399
|
-
ruff_config_path: str | None = Field(
|
|
400
|
-
default=None,
|
|
401
|
-
description="Path to ruff.toml or pyproject.toml (auto-detected if None)",
|
|
402
|
-
)
|
|
403
|
-
|
|
404
|
-
# mypy configuration
|
|
405
|
-
mypy_enabled: bool = Field(default=True, description="Enable mypy type checking")
|
|
406
|
-
mypy_strict: bool = Field(default=False, description="Enable strict mode for mypy")
|
|
407
|
-
mypy_config_path: str | None = Field(
|
|
408
|
-
default=None,
|
|
409
|
-
description="Path to mypy.ini or pyproject.toml (auto-detected if None)",
|
|
410
|
-
)
|
|
411
|
-
|
|
412
|
-
# jscpd configuration
|
|
413
|
-
jscpd_enabled: bool = Field(
|
|
414
|
-
default=True, description="Enable jscpd duplication detection"
|
|
415
|
-
)
|
|
416
|
-
duplication_threshold: float = Field(
|
|
417
|
-
default=3.0,
|
|
418
|
-
ge=0.0,
|
|
419
|
-
le=100.0,
|
|
420
|
-
description="Maximum duplication percentage threshold",
|
|
421
|
-
)
|
|
422
|
-
min_duplication_lines: int = Field(
|
|
423
|
-
default=5, ge=3, description="Minimum lines for duplication detection"
|
|
424
|
-
)
|
|
425
|
-
|
|
426
|
-
# TypeScript/JavaScript configuration
|
|
427
|
-
typescript_enabled: bool = Field(
|
|
428
|
-
default=True, description="Enable TypeScript/JavaScript support"
|
|
429
|
-
)
|
|
430
|
-
eslint_config: str | None = Field(
|
|
431
|
-
default=None, description="Path to ESLint config file"
|
|
432
|
-
)
|
|
433
|
-
tsconfig_path: str | None = Field(default=None, description="Path to tsconfig.json")
|
|
434
|
-
|
|
435
|
-
# Dependency security auditing
|
|
436
|
-
pip_audit_enabled: bool = Field(
|
|
437
|
-
default=True, description="Enable pip-audit security scanning"
|
|
438
|
-
)
|
|
439
|
-
dependency_audit_threshold: str = Field(
|
|
440
|
-
default="high",
|
|
441
|
-
description="Minimum severity threshold (low/medium/high/critical)",
|
|
442
|
-
)
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
class ToolingTargetsConfig(BaseModel):
|
|
446
|
-
"""Pin runtime/tool targets so agents and CI behave deterministically."""
|
|
447
|
-
|
|
448
|
-
python: str = Field(
|
|
449
|
-
default="3.13.3",
|
|
450
|
-
description="Target Python version for this project (pin exact patch where possible)",
|
|
451
|
-
)
|
|
452
|
-
python_requires: str = Field(
|
|
453
|
-
default=">=3.13",
|
|
454
|
-
description="PEP 440 requires-python constraint enforced by packaging/CI",
|
|
455
|
-
)
|
|
456
|
-
os_targets: list[str] = Field(
|
|
457
|
-
default_factory=lambda: ["windows", "linux"],
|
|
458
|
-
description="Primary OS targets (used for setup/doctor guidance)",
|
|
459
|
-
)
|
|
460
|
-
node: str | None = Field(
|
|
461
|
-
default=None,
|
|
462
|
-
description="Optional Node.js version (only needed if TypeScript/jscpd tooling is enabled)",
|
|
463
|
-
)
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
class ToolingPolicyConfig(BaseModel):
|
|
467
|
-
"""Policy for how missing/optional tools are handled."""
|
|
468
|
-
|
|
469
|
-
external_tools_mode: str = Field(
|
|
470
|
-
default="soft",
|
|
471
|
-
description="How to handle missing external tools: soft=warn/skip, hard=fail",
|
|
472
|
-
)
|
|
473
|
-
mypy_staged: bool = Field(
|
|
474
|
-
default=True, description="Stage mypy enforcement module-by-module"
|
|
475
|
-
)
|
|
476
|
-
mypy_stage_paths: list[str] = Field(
|
|
477
|
-
default_factory=lambda: [
|
|
478
|
-
"tapps_agents/core",
|
|
479
|
-
"tapps_agents/workflow",
|
|
480
|
-
"tapps_agents/context7",
|
|
481
|
-
],
|
|
482
|
-
description="Paths enforced by mypy during the staged rollout",
|
|
483
|
-
)
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
class ToolingConfig(BaseModel):
|
|
487
|
-
"""Canonical tooling/targets configuration (single source of truth)."""
|
|
488
|
-
|
|
489
|
-
targets: ToolingTargetsConfig = Field(default_factory=ToolingTargetsConfig)
|
|
490
|
-
policy: ToolingPolicyConfig = Field(default_factory=ToolingPolicyConfig)
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
class ArchitectAgentConfig(BaseModel):
|
|
494
|
-
"""Configuration specific to Architect Agent"""
|
|
495
|
-
|
|
496
|
-
min_confidence_threshold: float = Field(
|
|
497
|
-
default=0.75,
|
|
498
|
-
ge=0.0,
|
|
499
|
-
le=1.0,
|
|
500
|
-
description="Minimum expert confidence threshold (0.0-1.0)",
|
|
501
|
-
)
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
class DesignerAgentConfig(BaseModel):
|
|
505
|
-
"""Configuration specific to Designer Agent"""
|
|
506
|
-
|
|
507
|
-
min_confidence_threshold: float = Field(
|
|
508
|
-
default=0.65,
|
|
509
|
-
ge=0.0,
|
|
510
|
-
le=1.0,
|
|
511
|
-
description="Minimum expert confidence threshold (0.0-1.0)",
|
|
512
|
-
)
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
class OpsAgentConfig(BaseModel):
|
|
516
|
-
"""Configuration specific to Ops Agent"""
|
|
517
|
-
|
|
518
|
-
min_confidence_threshold: float = Field(
|
|
519
|
-
default=0.75,
|
|
520
|
-
ge=0.0,
|
|
521
|
-
le=1.0,
|
|
522
|
-
description="Minimum expert confidence threshold (0.0-1.0)",
|
|
523
|
-
)
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
class EnhancerAgentConfig(BaseModel):
|
|
527
|
-
"""Configuration specific to Enhancer Agent"""
|
|
528
|
-
|
|
529
|
-
min_confidence_threshold: float = Field(
|
|
530
|
-
default=0.6,
|
|
531
|
-
ge=0.0,
|
|
532
|
-
le=1.0,
|
|
533
|
-
description="Minimum expert confidence threshold (0.0-1.0)",
|
|
534
|
-
)
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
class AnalystAgentConfig(BaseModel):
|
|
538
|
-
"""Configuration specific to Analyst Agent"""
|
|
539
|
-
|
|
540
|
-
min_confidence_threshold: float = Field(
|
|
541
|
-
default=0.65,
|
|
542
|
-
ge=0.0,
|
|
543
|
-
le=1.0,
|
|
544
|
-
description="Minimum expert confidence threshold (0.0-1.0)",
|
|
545
|
-
)
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
class OrchestratorAgentConfig(BaseModel):
|
|
549
|
-
"""Configuration specific to Orchestrator Agent"""
|
|
550
|
-
|
|
551
|
-
min_confidence_threshold: float = Field(
|
|
552
|
-
default=0.6,
|
|
553
|
-
ge=0.0,
|
|
554
|
-
le=1.0,
|
|
555
|
-
description="Minimum expert confidence threshold (0.0-1.0)",
|
|
556
|
-
)
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
class EvaluatorAgentConfig(BaseModel):
|
|
560
|
-
"""Configuration specific to Evaluator Agent"""
|
|
561
|
-
|
|
562
|
-
auto_run: bool = Field(
|
|
563
|
-
default=False,
|
|
564
|
-
description="Run evaluator automatically at end of workflows (build, full, etc.)"
|
|
565
|
-
)
|
|
566
|
-
output_dir: str = Field(
|
|
567
|
-
default=".tapps-agents/evaluations",
|
|
568
|
-
description="Directory for evaluation reports"
|
|
569
|
-
)
|
|
570
|
-
thresholds: dict[str, float] = Field(
|
|
571
|
-
default_factory=lambda: {
|
|
572
|
-
"quality_score": 70.0,
|
|
573
|
-
"workflow_completion": 0.8,
|
|
574
|
-
},
|
|
575
|
-
description="Thresholds for evaluation metrics"
|
|
576
|
-
)
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
class CleanupAgentConfig(BaseModel):
|
|
580
|
-
"""Configuration specific to Cleanup Agent"""
|
|
581
|
-
|
|
582
|
-
dry_run_default: bool = Field(
|
|
583
|
-
default=True,
|
|
584
|
-
description="Run in dry-run mode by default (preview changes without executing)"
|
|
585
|
-
)
|
|
586
|
-
backup_enabled: bool = Field(
|
|
587
|
-
default=True,
|
|
588
|
-
description="Create backups before destructive operations"
|
|
589
|
-
)
|
|
590
|
-
interactive_mode: bool = Field(
|
|
591
|
-
default=True,
|
|
592
|
-
description="Prompt for confirmation on risky operations"
|
|
593
|
-
)
|
|
594
|
-
default_pattern: str = Field(
|
|
595
|
-
default="*.md",
|
|
596
|
-
description="Default file pattern for analysis"
|
|
597
|
-
)
|
|
598
|
-
age_threshold_days: int = Field(
|
|
599
|
-
default=90,
|
|
600
|
-
ge=1,
|
|
601
|
-
le=365,
|
|
602
|
-
description="Days threshold for detecting outdated files"
|
|
603
|
-
)
|
|
604
|
-
similarity_threshold: float = Field(
|
|
605
|
-
default=0.8,
|
|
606
|
-
ge=0.0,
|
|
607
|
-
le=1.0,
|
|
608
|
-
description="Content similarity threshold for detecting near-duplicates"
|
|
609
|
-
)
|
|
610
|
-
backup_dir: str = Field(
|
|
611
|
-
default=".cleanup-backups",
|
|
612
|
-
description="Directory for cleanup backups"
|
|
613
|
-
)
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
class ExpertConfig(BaseModel):
|
|
617
|
-
"""Configuration for expert consultation system"""
|
|
618
|
-
|
|
619
|
-
# Agent-specific confidence thresholds
|
|
620
|
-
agent_confidence_thresholds: dict[str, float] = Field(
|
|
621
|
-
default_factory=lambda: {
|
|
622
|
-
"reviewer": 0.8,
|
|
623
|
-
"architect": 0.75,
|
|
624
|
-
"implementer": 0.7,
|
|
625
|
-
"designer": 0.65,
|
|
626
|
-
"tester": 0.7,
|
|
627
|
-
"ops": 0.75,
|
|
628
|
-
"enhancer": 0.6,
|
|
629
|
-
"analyst": 0.65,
|
|
630
|
-
"planner": 0.6,
|
|
631
|
-
"debugger": 0.7,
|
|
632
|
-
"documenter": 0.5,
|
|
633
|
-
"orchestrator": 0.6,
|
|
634
|
-
"default": 0.7,
|
|
635
|
-
},
|
|
636
|
-
description="Agent-specific confidence thresholds (0.0-1.0)",
|
|
637
|
-
)
|
|
638
|
-
|
|
639
|
-
# Confidence calculation weights
|
|
640
|
-
weight_max_confidence: float = Field(
|
|
641
|
-
default=0.35, ge=0.0, le=1.0, description="Weight for maximum expert confidence"
|
|
642
|
-
)
|
|
643
|
-
weight_agreement: float = Field(
|
|
644
|
-
default=0.25, ge=0.0, le=1.0, description="Weight for expert agreement level"
|
|
645
|
-
)
|
|
646
|
-
weight_rag_quality: float = Field(
|
|
647
|
-
default=0.2, ge=0.0, le=1.0, description="Weight for RAG knowledge base quality"
|
|
648
|
-
)
|
|
649
|
-
weight_domain_relevance: float = Field(
|
|
650
|
-
default=0.1, ge=0.0, le=1.0, description="Weight for domain relevance"
|
|
651
|
-
)
|
|
652
|
-
weight_project_context: float = Field(
|
|
653
|
-
default=0.1, ge=0.0, le=1.0, description="Weight for project context relevance"
|
|
654
|
-
)
|
|
655
|
-
|
|
656
|
-
# Agreement and similarity thresholds
|
|
657
|
-
high_agreement_threshold: float = Field(
|
|
658
|
-
default=0.75,
|
|
659
|
-
ge=0.0,
|
|
660
|
-
le=1.0,
|
|
661
|
-
description="High agreement threshold for expert consensus (0.0-1.0)",
|
|
662
|
-
)
|
|
663
|
-
similarity_threshold: float = Field(
|
|
664
|
-
default=0.6,
|
|
665
|
-
ge=0.0,
|
|
666
|
-
le=1.0,
|
|
667
|
-
description="Similarity threshold for expert response comparison (0.0-1.0)",
|
|
668
|
-
)
|
|
669
|
-
|
|
670
|
-
# RAG (Retrieval-Augmented Generation) parameters
|
|
671
|
-
rag_max_length: int = Field(
|
|
672
|
-
default=2000,
|
|
673
|
-
ge=100,
|
|
674
|
-
le=10000,
|
|
675
|
-
description="Maximum length for RAG context retrieval (characters)",
|
|
676
|
-
)
|
|
677
|
-
rag_max_results: int = Field(
|
|
678
|
-
default=8, ge=1, le=20, description="Maximum number of RAG results to retrieve"
|
|
679
|
-
)
|
|
680
|
-
rag_default_quality: float = Field(
|
|
681
|
-
default=0.8,
|
|
682
|
-
ge=0.0,
|
|
683
|
-
le=1.0,
|
|
684
|
-
description="Default RAG quality score when not provided (0.0-1.0)",
|
|
685
|
-
)
|
|
686
|
-
|
|
687
|
-
# Profile confidence threshold
|
|
688
|
-
profile_confidence_threshold: float = Field(
|
|
689
|
-
default=0.7,
|
|
690
|
-
ge=0.0,
|
|
691
|
-
le=1.0,
|
|
692
|
-
description="Minimum confidence threshold for including profile values (0.0-1.0)",
|
|
693
|
-
)
|
|
694
|
-
|
|
695
|
-
# Supporting expert weight
|
|
696
|
-
supporting_expert_weight: float = Field(
|
|
697
|
-
default=0.15,
|
|
698
|
-
ge=0.0,
|
|
699
|
-
le=1.0,
|
|
700
|
-
description="Approximate weight for supporting experts in agreement calculation",
|
|
701
|
-
)
|
|
702
|
-
|
|
703
|
-
@model_validator(mode="after")
|
|
704
|
-
def validate_weights_sum(self):
|
|
705
|
-
"""Ensure confidence weights sum to approximately 1.0"""
|
|
706
|
-
total = (
|
|
707
|
-
self.weight_max_confidence
|
|
708
|
-
+ self.weight_agreement
|
|
709
|
-
+ self.weight_rag_quality
|
|
710
|
-
+ self.weight_domain_relevance
|
|
711
|
-
+ self.weight_project_context
|
|
712
|
-
)
|
|
713
|
-
if abs(total - 1.0) > 0.01: # Allow small floating point errors
|
|
714
|
-
raise ValueError(f"Expert confidence weights must sum to 1.0, got {total}")
|
|
715
|
-
return self
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
class AgentsConfig(BaseModel):
|
|
719
|
-
"""Configuration for all agents"""
|
|
720
|
-
|
|
721
|
-
reviewer: ReviewerAgentConfig = Field(default_factory=ReviewerAgentConfig)
|
|
722
|
-
planner: PlannerAgentConfig = Field(default_factory=PlannerAgentConfig)
|
|
723
|
-
implementer: ImplementerAgentConfig = Field(default_factory=ImplementerAgentConfig)
|
|
724
|
-
tester: TesterAgentConfig = Field(default_factory=TesterAgentConfig)
|
|
725
|
-
debugger: DebuggerAgentConfig = Field(default_factory=DebuggerAgentConfig)
|
|
726
|
-
documenter: DocumenterAgentConfig = Field(default_factory=DocumenterAgentConfig)
|
|
727
|
-
architect: ArchitectAgentConfig = Field(default_factory=ArchitectAgentConfig)
|
|
728
|
-
designer: DesignerAgentConfig = Field(default_factory=DesignerAgentConfig)
|
|
729
|
-
ops: OpsAgentConfig = Field(default_factory=OpsAgentConfig)
|
|
730
|
-
enhancer: EnhancerAgentConfig = Field(default_factory=EnhancerAgentConfig)
|
|
731
|
-
analyst: AnalystAgentConfig = Field(default_factory=AnalystAgentConfig)
|
|
732
|
-
orchestrator: OrchestratorAgentConfig = Field(
|
|
733
|
-
default_factory=OrchestratorAgentConfig
|
|
734
|
-
)
|
|
735
|
-
evaluator: EvaluatorAgentConfig = Field(default_factory=EvaluatorAgentConfig)
|
|
736
|
-
cleanup_agent: CleanupAgentConfig = Field(default_factory=CleanupAgentConfig)
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
class CheckpointFrequencyConfig(BaseModel):
|
|
740
|
-
"""Configuration for checkpoint frequency"""
|
|
741
|
-
|
|
742
|
-
mode: str = Field(
|
|
743
|
-
default="every_step",
|
|
744
|
-
description="Checkpoint frequency mode: every_step, every_n_steps, on_gates, time_based, manual",
|
|
745
|
-
)
|
|
746
|
-
interval: int = Field(
|
|
747
|
-
default=1,
|
|
748
|
-
ge=1,
|
|
749
|
-
description="Interval for every_n_steps (step count) or time_based (seconds)",
|
|
750
|
-
)
|
|
751
|
-
enabled: bool = Field(
|
|
752
|
-
default=True,
|
|
753
|
-
description="Enable checkpointing",
|
|
754
|
-
)
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
class StateCleanupPolicyConfig(BaseModel):
|
|
758
|
-
"""Configuration for state cleanup policies"""
|
|
759
|
-
|
|
760
|
-
enabled: bool = Field(
|
|
761
|
-
default=True,
|
|
762
|
-
description="Enable automatic state cleanup",
|
|
763
|
-
)
|
|
764
|
-
retention_days: int | None = Field(
|
|
765
|
-
default=None,
|
|
766
|
-
ge=1,
|
|
767
|
-
description="Delete states older than N days (None = no retention limit)",
|
|
768
|
-
)
|
|
769
|
-
max_size_mb: int | None = Field(
|
|
770
|
-
default=None,
|
|
771
|
-
ge=1,
|
|
772
|
-
description="Maximum total state size in MB (None = no size limit)",
|
|
773
|
-
)
|
|
774
|
-
cleanup_schedule: str = Field(
|
|
775
|
-
default="daily",
|
|
776
|
-
description="Cleanup schedule: daily, weekly, monthly, on_startup, manual",
|
|
777
|
-
)
|
|
778
|
-
keep_latest: int = Field(
|
|
779
|
-
default=10,
|
|
780
|
-
ge=1,
|
|
781
|
-
description="Always keep the N most recent states",
|
|
782
|
-
)
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
class StatePersistenceConfig(BaseModel):
|
|
786
|
-
"""Configuration for state persistence and checkpointing"""
|
|
787
|
-
|
|
788
|
-
enabled: bool = Field(
|
|
789
|
-
default=True,
|
|
790
|
-
description="Enable state persistence",
|
|
791
|
-
)
|
|
792
|
-
storage_location: str = Field(
|
|
793
|
-
default=".tapps-agents/workflow-state",
|
|
794
|
-
description="Directory for storing workflow state",
|
|
795
|
-
)
|
|
796
|
-
format: str = Field(
|
|
797
|
-
default="json",
|
|
798
|
-
description="State storage format: json, json_gzip",
|
|
799
|
-
)
|
|
800
|
-
compression: bool = Field(
|
|
801
|
-
default=False,
|
|
802
|
-
description="Enable compression for state files",
|
|
803
|
-
)
|
|
804
|
-
checkpoint: CheckpointFrequencyConfig = Field(
|
|
805
|
-
default_factory=CheckpointFrequencyConfig,
|
|
806
|
-
description="Checkpoint frequency configuration",
|
|
807
|
-
)
|
|
808
|
-
cleanup: StateCleanupPolicyConfig = Field(
|
|
809
|
-
default_factory=StateCleanupPolicyConfig,
|
|
810
|
-
description="State cleanup policy configuration",
|
|
811
|
-
)
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
class BranchCleanupConfig(BaseModel):
|
|
815
|
-
"""Configuration for Git branch cleanup after workflow execution"""
|
|
816
|
-
|
|
817
|
-
enabled: bool = Field(
|
|
818
|
-
default=True,
|
|
819
|
-
description="Enable automatic branch cleanup",
|
|
820
|
-
)
|
|
821
|
-
delete_branches_on_cleanup: bool = Field(
|
|
822
|
-
default=True,
|
|
823
|
-
description="Delete associated Git branches when worktrees are removed",
|
|
824
|
-
)
|
|
825
|
-
retention_days: int = Field(
|
|
826
|
-
default=7,
|
|
827
|
-
ge=0,
|
|
828
|
-
description="Number of days to retain branches before cleanup (0 = immediate cleanup)",
|
|
829
|
-
)
|
|
830
|
-
auto_cleanup_on_completion: bool = Field(
|
|
831
|
-
default=True,
|
|
832
|
-
description="Automatically cleanup branches when workflow step completes",
|
|
833
|
-
)
|
|
834
|
-
patterns: dict[str, str] = Field(
|
|
835
|
-
default_factory=lambda: {
|
|
836
|
-
"workflow": "workflow/*",
|
|
837
|
-
"agent": "agent/*",
|
|
838
|
-
},
|
|
839
|
-
description="Branch patterns to match for cleanup (wildcards supported)",
|
|
840
|
-
)
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
class WorkflowDocsCleanupConfig(BaseModel):
|
|
844
|
-
"""Configuration for workflow documentation cleanup"""
|
|
845
|
-
|
|
846
|
-
enabled: bool = Field(
|
|
847
|
-
default=True,
|
|
848
|
-
description="Enable workflow documentation cleanup",
|
|
849
|
-
)
|
|
850
|
-
keep_latest: int = Field(
|
|
851
|
-
default=5,
|
|
852
|
-
ge=1,
|
|
853
|
-
le=100,
|
|
854
|
-
description="Keep N most recent workflows visible",
|
|
855
|
-
)
|
|
856
|
-
retention_days: int = Field(
|
|
857
|
-
default=30,
|
|
858
|
-
ge=1,
|
|
859
|
-
description="Archive workflows older than N days",
|
|
860
|
-
)
|
|
861
|
-
archive_enabled: bool = Field(
|
|
862
|
-
default=True,
|
|
863
|
-
description="Enable archival of old workflows",
|
|
864
|
-
)
|
|
865
|
-
archive_dir: Path = Field(
|
|
866
|
-
default=Path(".tapps-agents/archives/workflows/"),
|
|
867
|
-
description="Directory for archived workflows (relative to project root)",
|
|
868
|
-
)
|
|
869
|
-
exclude_patterns: list[str] = Field(
|
|
870
|
-
default_factory=list,
|
|
871
|
-
description="Workflow IDs or patterns to never archive",
|
|
872
|
-
)
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
class SessionsCleanupConfig(BaseModel):
|
|
876
|
-
"""Configuration for .tapps-agents/sessions cleanup (enhancer + SessionManager)."""
|
|
877
|
-
|
|
878
|
-
keep_latest: int = Field(
|
|
879
|
-
default=50,
|
|
880
|
-
ge=1,
|
|
881
|
-
le=500,
|
|
882
|
-
description="Keep N most recent enhancer session files",
|
|
883
|
-
)
|
|
884
|
-
max_age_days: int = Field(
|
|
885
|
-
default=30,
|
|
886
|
-
ge=1,
|
|
887
|
-
description="Remove enhancer sessions older than N days; also used for SessionManager cleanup (hours = max_age_days * 24)",
|
|
888
|
-
)
|
|
889
|
-
auto_cleanup_on_enhance: bool = Field(
|
|
890
|
-
default=False,
|
|
891
|
-
description="When True, run sessions cleanup after each enhancer save so the folder does not grow unbounded",
|
|
892
|
-
)
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
class CleanupConfig(BaseModel):
|
|
896
|
-
"""Configuration for cleanup operations"""
|
|
897
|
-
|
|
898
|
-
workflow_docs: WorkflowDocsCleanupConfig = Field(
|
|
899
|
-
default_factory=WorkflowDocsCleanupConfig,
|
|
900
|
-
description="Workflow documentation cleanup configuration",
|
|
901
|
-
)
|
|
902
|
-
sessions: SessionsCleanupConfig = Field(
|
|
903
|
-
default_factory=SessionsCleanupConfig,
|
|
904
|
-
description="Sessions cleanup (enhancer + long-running agent sessions)",
|
|
905
|
-
)
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
class WorkflowArtifactConfig(BaseModel):
|
|
909
|
-
"""Configuration for workflow artifact paths and naming."""
|
|
910
|
-
|
|
911
|
-
base_dir: str = Field(
|
|
912
|
-
default="docs/workflows",
|
|
913
|
-
description="Base directory for workflow artifacts (relative to project root)",
|
|
914
|
-
)
|
|
915
|
-
simple_mode_subdir: str = Field(
|
|
916
|
-
default="simple-mode",
|
|
917
|
-
description="Subdirectory for Simple Mode workflow artifacts",
|
|
918
|
-
)
|
|
919
|
-
auto_detect_existing: bool = Field(
|
|
920
|
-
default=True,
|
|
921
|
-
description="Auto-detect existing artifacts and adjust paths to avoid conflicts",
|
|
922
|
-
)
|
|
923
|
-
naming_pattern: str = Field(
|
|
924
|
-
default="{workflow_id}/{step_name}.md",
|
|
925
|
-
description="Pattern for artifact file naming. Supports: {workflow_id}, {step_name}, {timestamp}, {agent}",
|
|
926
|
-
)
|
|
927
|
-
print_paths_on_completion: bool = Field(
|
|
928
|
-
default=True,
|
|
929
|
-
description="Print artifact file paths after each step completes",
|
|
930
|
-
)
|
|
931
|
-
|
|
932
|
-
def get_artifact_dir(self, project_root: str | None = None) -> str:
|
|
933
|
-
"""Get the full artifact directory path."""
|
|
934
|
-
from pathlib import Path
|
|
935
|
-
base = Path(project_root) if project_root else Path.cwd()
|
|
936
|
-
return str(base / self.base_dir / self.simple_mode_subdir)
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
class WorkflowFailureConfig(BaseModel):
|
|
940
|
-
"""On-step-failure behavior: retry, skip, escalate, or fail (plan 3.1)."""
|
|
941
|
-
|
|
942
|
-
on_step_fail: str = Field(
|
|
943
|
-
default="fail",
|
|
944
|
-
description="Behavior on step failure: 'fail' | 'retry' | 'skip' | 'escalate'.",
|
|
945
|
-
)
|
|
946
|
-
retry_count: int = Field(
|
|
947
|
-
default=1,
|
|
948
|
-
ge=0,
|
|
949
|
-
le=10,
|
|
950
|
-
description="Max retries when on_step_fail=='retry'.",
|
|
951
|
-
)
|
|
952
|
-
escalate_to_pause: bool = Field(
|
|
953
|
-
default=True,
|
|
954
|
-
description="When on_step_fail is 'escalate' or 'fail', set status to 'paused' (True) or 'failed' (False).",
|
|
955
|
-
)
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
class WorkflowConfig(BaseModel):
|
|
959
|
-
"""Configuration for workflow execution"""
|
|
960
|
-
|
|
961
|
-
failure: WorkflowFailureConfig = Field(
|
|
962
|
-
default_factory=WorkflowFailureConfig,
|
|
963
|
-
description="On-step-failure behavior: retry, skip, escalate (plan 3.1).",
|
|
964
|
-
)
|
|
965
|
-
polling_interval: float = Field(
|
|
966
|
-
default=5.0,
|
|
967
|
-
ge=1.0,
|
|
968
|
-
description="Seconds between status checks when polling for completion",
|
|
969
|
-
)
|
|
970
|
-
timeout_seconds: float = Field(
|
|
971
|
-
default=3600.0,
|
|
972
|
-
ge=1.0,
|
|
973
|
-
description="Maximum time to wait for step completion (seconds)",
|
|
974
|
-
)
|
|
975
|
-
duration_threshold_seconds: float = Field(
|
|
976
|
-
default=30.0,
|
|
977
|
-
ge=1.0,
|
|
978
|
-
description="Duration threshold for background agent routing (seconds). Tasks estimated to take longer use background agents.",
|
|
979
|
-
)
|
|
980
|
-
state_persistence: StatePersistenceConfig = Field(
|
|
981
|
-
default_factory=StatePersistenceConfig,
|
|
982
|
-
description="State persistence and checkpointing configuration",
|
|
983
|
-
)
|
|
984
|
-
branch_cleanup: BranchCleanupConfig = Field(
|
|
985
|
-
default_factory=BranchCleanupConfig,
|
|
986
|
-
description="Git branch cleanup configuration for workflow worktrees",
|
|
987
|
-
)
|
|
988
|
-
artifacts: WorkflowArtifactConfig = Field(
|
|
989
|
-
default_factory=WorkflowArtifactConfig,
|
|
990
|
-
description="Artifact paths and naming configuration",
|
|
991
|
-
)
|
|
992
|
-
graceful_partial_completion: bool = Field(
|
|
993
|
-
default=True,
|
|
994
|
-
description="Save partial results on failure instead of losing all progress",
|
|
995
|
-
)
|
|
996
|
-
pre_flight_validation: bool = Field(
|
|
997
|
-
default=True,
|
|
998
|
-
description="Run pre-flight validation before workflow execution",
|
|
999
|
-
)
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
class ContextBudgetConfig(BaseModel):
|
|
1003
|
-
"""Context budget when assembling Context7 and expert chunks (plan 3.2)."""
|
|
1004
|
-
|
|
1005
|
-
max_tokens_per_step: int = Field(
|
|
1006
|
-
default=0,
|
|
1007
|
-
ge=0,
|
|
1008
|
-
description="Max tokens per step (0=no hard limit).",
|
|
1009
|
-
)
|
|
1010
|
-
max_chunks_per_step: int = Field(
|
|
1011
|
-
default=50,
|
|
1012
|
-
ge=1,
|
|
1013
|
-
le=500,
|
|
1014
|
-
description="Max chunks when injecting Context7 or expert docs.",
|
|
1015
|
-
)
|
|
1016
|
-
priority: list[str] = Field(
|
|
1017
|
-
default_factory=lambda: ["current_task", "open_files", "recent_changes", "context7", "experts"],
|
|
1018
|
-
description="Priority order when assembling context (for future use).",
|
|
1019
|
-
)
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
class BugFixAgentConfig(BaseModel):
|
|
1023
|
-
"""Configuration for Bug Fix Agent."""
|
|
1024
|
-
|
|
1025
|
-
max_iterations: int = Field(
|
|
1026
|
-
default=3,
|
|
1027
|
-
ge=1,
|
|
1028
|
-
le=10,
|
|
1029
|
-
description="Maximum iterations for fix loopback (1-10)",
|
|
1030
|
-
)
|
|
1031
|
-
auto_commit: bool = Field(
|
|
1032
|
-
default=True,
|
|
1033
|
-
description="Automatically commit changes to main branch when quality passes",
|
|
1034
|
-
)
|
|
1035
|
-
quality_thresholds: dict[str, float] = Field(
|
|
1036
|
-
default_factory=lambda: {
|
|
1037
|
-
"overall_min": 7.0,
|
|
1038
|
-
"security_min": 6.5,
|
|
1039
|
-
"maintainability_min": 7.0,
|
|
1040
|
-
},
|
|
1041
|
-
description="Quality thresholds for bug fixes (lower than full SDLC)",
|
|
1042
|
-
)
|
|
1043
|
-
escalation_threshold: int = Field(
|
|
1044
|
-
default=2,
|
|
1045
|
-
ge=1,
|
|
1046
|
-
le=5,
|
|
1047
|
-
description="Escalate to human after N failed iterations (1-5)",
|
|
1048
|
-
)
|
|
1049
|
-
escalation_enabled: bool = Field(
|
|
1050
|
-
default=True,
|
|
1051
|
-
description="Enable human escalation after failed iterations",
|
|
1052
|
-
)
|
|
1053
|
-
pre_commit_security_scan: bool = Field(
|
|
1054
|
-
default=True,
|
|
1055
|
-
description="Run security scan before committing changes",
|
|
1056
|
-
)
|
|
1057
|
-
metrics_enabled: bool = Field(
|
|
1058
|
-
default=True,
|
|
1059
|
-
description="Enable metrics collection for observability",
|
|
1060
|
-
)
|
|
1061
|
-
commit_strategy: str = Field(
|
|
1062
|
-
default="direct_main",
|
|
1063
|
-
description="Commit strategy: 'direct_main' (commit directly) or 'pull_request' (create PR)",
|
|
1064
|
-
)
|
|
1065
|
-
auto_merge_pr: bool = Field(
|
|
1066
|
-
default=False,
|
|
1067
|
-
description="Auto-merge PR if quality gates pass (requires PR workflow)",
|
|
1068
|
-
)
|
|
1069
|
-
require_pr_review: bool = Field(
|
|
1070
|
-
default=False,
|
|
1071
|
-
description="Require human review before merging PR",
|
|
1072
|
-
)
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
class ContinuousBugFixConfig(BaseModel):
|
|
1076
|
-
"""Configuration for Continuous Bug Fix feature."""
|
|
1077
|
-
|
|
1078
|
-
max_iterations: int = Field(
|
|
1079
|
-
default=10,
|
|
1080
|
-
ge=1,
|
|
1081
|
-
le=100,
|
|
1082
|
-
description="Maximum loop iterations (1-100)",
|
|
1083
|
-
)
|
|
1084
|
-
commit_strategy: str = Field(
|
|
1085
|
-
default="one-per-bug",
|
|
1086
|
-
description="Commit strategy: 'one-per-bug' (default) or 'batch'",
|
|
1087
|
-
)
|
|
1088
|
-
auto_commit: bool = Field(
|
|
1089
|
-
default=True,
|
|
1090
|
-
description="Automatically commit fixes after bug-fix-agent succeeds",
|
|
1091
|
-
)
|
|
1092
|
-
test_path: str = Field(
|
|
1093
|
-
default="tests/",
|
|
1094
|
-
description="Default test directory or file to run",
|
|
1095
|
-
)
|
|
1096
|
-
skip_patterns: list[str] = Field(
|
|
1097
|
-
default_factory=list,
|
|
1098
|
-
description="Patterns for bugs to skip (not yet implemented)",
|
|
1099
|
-
)
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
class BeadsConfig(BaseModel):
|
|
1103
|
-
"""Configuration for Beads (bd) task-tracking integration."""
|
|
1104
|
-
|
|
1105
|
-
enabled: bool = Field(
|
|
1106
|
-
default=True,
|
|
1107
|
-
description="Enable Beads (bd) integration. When false, all beads features are no-ops.",
|
|
1108
|
-
)
|
|
1109
|
-
required: bool = Field(
|
|
1110
|
-
default=False,
|
|
1111
|
-
description="When true, workflows fail if bd is unavailable or .beads not initialized.",
|
|
1112
|
-
)
|
|
1113
|
-
sync_epic: bool = Field(
|
|
1114
|
-
default=True,
|
|
1115
|
-
description="When beads.enabled is true, sync epic to bd (create issues + deps) before *epic run.",
|
|
1116
|
-
)
|
|
1117
|
-
hooks_simple_mode: bool = Field(
|
|
1118
|
-
default=True,
|
|
1119
|
-
description="When beads.enabled is true, create/close bd issues at start/end of *build and *fix.",
|
|
1120
|
-
)
|
|
1121
|
-
hooks_workflow: bool = Field(
|
|
1122
|
-
default=True,
|
|
1123
|
-
description="When beads.enabled is true, create/close a bd issue at start/end of CLI workflow runs.",
|
|
1124
|
-
)
|
|
1125
|
-
hooks_review: bool = Field(
|
|
1126
|
-
default=False,
|
|
1127
|
-
description="When beads.enabled is true, create/close for *review.",
|
|
1128
|
-
)
|
|
1129
|
-
hooks_test: bool = Field(
|
|
1130
|
-
default=False,
|
|
1131
|
-
description="When beads.enabled is true, create/close for *test.",
|
|
1132
|
-
)
|
|
1133
|
-
hooks_refactor: bool = Field(
|
|
1134
|
-
default=False,
|
|
1135
|
-
description="When beads.enabled is true, create/close for *refactor.",
|
|
1136
|
-
)
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
class SimpleModeConfig(BaseModel):
|
|
1140
|
-
"""Configuration for Simple Mode."""
|
|
1141
|
-
|
|
1142
|
-
enabled: bool = Field(
|
|
1143
|
-
default=True, description="Enable Simple Mode (intent-based agent orchestration)"
|
|
1144
|
-
)
|
|
1145
|
-
auto_detect: bool = Field(
|
|
1146
|
-
default=True,
|
|
1147
|
-
description="Auto-enable Simple Mode for first-time users",
|
|
1148
|
-
)
|
|
1149
|
-
show_advanced: bool = Field(
|
|
1150
|
-
default=False, description="Show advanced agent-specific options"
|
|
1151
|
-
)
|
|
1152
|
-
natural_language: bool = Field(
|
|
1153
|
-
default=True, description="Enable natural language command parsing"
|
|
1154
|
-
)
|
|
1155
|
-
fast_mode_default: bool = Field(
|
|
1156
|
-
default=False,
|
|
1157
|
-
description="Default to fast mode for Simple Mode workflows (skip documentation steps)",
|
|
1158
|
-
)
|
|
1159
|
-
state_persistence_enabled: bool = Field(
|
|
1160
|
-
default=True,
|
|
1161
|
-
description="Enable workflow state persistence for resume capability",
|
|
1162
|
-
)
|
|
1163
|
-
checkpoint_retention_days: int = Field(
|
|
1164
|
-
default=30,
|
|
1165
|
-
ge=1,
|
|
1166
|
-
description="Days to retain workflow checkpoints",
|
|
1167
|
-
)
|
|
1168
|
-
documentation_organized: bool = Field(
|
|
1169
|
-
default=True,
|
|
1170
|
-
description="Organize documentation by workflow ID",
|
|
1171
|
-
)
|
|
1172
|
-
create_latest_symlink: bool = Field(
|
|
1173
|
-
default=False,
|
|
1174
|
-
description="Create 'latest' symlink to most recent workflow",
|
|
1175
|
-
)
|
|
1176
|
-
context7_refresh_after_planning: bool = Field(
|
|
1177
|
-
default=True,
|
|
1178
|
-
description="After build planning (Step 2), refresh Context7 cache for libraries from the plan. Set false to disable.",
|
|
1179
|
-
)
|
|
1180
|
-
context7_refresh_max_libraries: int = Field(
|
|
1181
|
-
default=10,
|
|
1182
|
-
ge=1,
|
|
1183
|
-
le=50,
|
|
1184
|
-
description="Max number of libraries to warm in post-planning Context7 refresh (limits API use).",
|
|
1185
|
-
)
|
|
1186
|
-
enable_checkpoints: bool = Field(
|
|
1187
|
-
default=True,
|
|
1188
|
-
description="Enable mid-execution workflow checkpoints (Checkpoint 1: After Enhance, Checkpoint 2: After Planning, Checkpoint 3: Quality Gate)",
|
|
1189
|
-
)
|
|
1190
|
-
checkpoint_confidence_threshold: float = Field(
|
|
1191
|
-
default=0.70,
|
|
1192
|
-
ge=0.0,
|
|
1193
|
-
le=1.0,
|
|
1194
|
-
description="Minimum confidence threshold for checkpoint recommendations (0.0-1.0)",
|
|
1195
|
-
)
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
class AutoEnhancementConfig(BaseModel):
|
|
1199
|
-
"""Configuration for automatic prompt enhancement"""
|
|
1200
|
-
|
|
1201
|
-
enabled: bool = Field(
|
|
1202
|
-
default=True, description="Enable auto-enhancement globally"
|
|
1203
|
-
)
|
|
1204
|
-
mode: str = Field(
|
|
1205
|
-
default="cursor-skills",
|
|
1206
|
-
description="Enhancement mode: cursor-skills, structured, or smart",
|
|
1207
|
-
)
|
|
1208
|
-
min_prompt_length: int = Field(
|
|
1209
|
-
default=20, description="Minimum prompt length to trigger enhancement"
|
|
1210
|
-
)
|
|
1211
|
-
quality_threshold: float = Field(
|
|
1212
|
-
default=50.0,
|
|
1213
|
-
ge=0.0,
|
|
1214
|
-
le=100.0,
|
|
1215
|
-
description="Quality score below which to enhance",
|
|
1216
|
-
)
|
|
1217
|
-
|
|
1218
|
-
commands: dict[str, dict[str, Any]] = Field(
|
|
1219
|
-
default_factory=lambda: {
|
|
1220
|
-
"implementer": {"enabled": True, "synthesis_mode": "full"},
|
|
1221
|
-
"planner": {"enabled": True, "synthesis_mode": "quick"},
|
|
1222
|
-
"analyst": {"enabled": True, "synthesis_mode": "quick"},
|
|
1223
|
-
"architect": {"enabled": False}, # Off by default to avoid over-use
|
|
1224
|
-
"designer": {"enabled": False}, # Off by default to avoid over-use
|
|
1225
|
-
},
|
|
1226
|
-
description="Per-command enhancement settings",
|
|
1227
|
-
)
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
class EvaluationConfig(BaseModel):
|
|
1231
|
-
"""Configuration for Evaluation & Quality Assurance Engine (Tier 1)"""
|
|
1232
|
-
|
|
1233
|
-
enabled: bool = Field(
|
|
1234
|
-
default=True, description="Enable comprehensive evaluation engine"
|
|
1235
|
-
)
|
|
1236
|
-
include_behavioral_validation: bool = Field(
|
|
1237
|
-
default=True, description="Include behavioral correctness validation"
|
|
1238
|
-
)
|
|
1239
|
-
include_spec_compliance: bool = Field(
|
|
1240
|
-
default=True, description="Include specification compliance checking"
|
|
1241
|
-
)
|
|
1242
|
-
include_architectural_checks: bool = Field(
|
|
1243
|
-
default=True, description="Include architectural pattern adherence checking"
|
|
1244
|
-
)
|
|
1245
|
-
issue_severity_thresholds: dict[str, int] = Field(
|
|
1246
|
-
default_factory=lambda: {
|
|
1247
|
-
"critical": 0, # Hard fail
|
|
1248
|
-
"high": 5, # Soft fail/loopback
|
|
1249
|
-
"medium": 10,
|
|
1250
|
-
"low": 20,
|
|
1251
|
-
},
|
|
1252
|
-
description="Maximum allowed issues by severity for gate passing",
|
|
1253
|
-
)
|
|
1254
|
-
enable_remediation_loop: bool = Field(
|
|
1255
|
-
default=True, description="Enable automatic remediation loops"
|
|
1256
|
-
)
|
|
1257
|
-
max_remediation_retries: int = Field(
|
|
1258
|
-
default=3, ge=1, le=10, description="Maximum remediation retry attempts"
|
|
1259
|
-
)
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
class PromptLearningConfig(BaseModel):
|
|
1263
|
-
"""Configuration for Continual System Prompt Learning (Tier 1)"""
|
|
1264
|
-
|
|
1265
|
-
enabled: bool = Field(
|
|
1266
|
-
default=True, description="Enable prompt learning system"
|
|
1267
|
-
)
|
|
1268
|
-
feedback_collection_enabled: bool = Field(
|
|
1269
|
-
default=True, description="Enable feedback collection from Cursor IDE"
|
|
1270
|
-
)
|
|
1271
|
-
ab_testing_enabled: bool = Field(
|
|
1272
|
-
default=True, description="Enable A/B testing for prompt variations"
|
|
1273
|
-
)
|
|
1274
|
-
auto_optimize_enabled: bool = Field(
|
|
1275
|
-
default=True, description="Enable automatic prompt optimization"
|
|
1276
|
-
)
|
|
1277
|
-
min_samples_for_optimization: int = Field(
|
|
1278
|
-
default=10, ge=5, description="Minimum feedback samples before optimization"
|
|
1279
|
-
)
|
|
1280
|
-
optimization_interval_hours: int = Field(
|
|
1281
|
-
default=24, ge=1, description="Hours between optimization runs"
|
|
1282
|
-
)
|
|
1283
|
-
prompt_version_retention_days: int = Field(
|
|
1284
|
-
default=90, ge=7, description="Days to retain prompt version history"
|
|
1285
|
-
)
|
|
1286
|
-
auto_update_skills: bool = Field(
|
|
1287
|
-
default=False, description="Automatically update Skills with learned prompts"
|
|
1288
|
-
)
|
|
1289
|
-
require_approval_for_updates: bool = Field(
|
|
1290
|
-
default=True, description="Require approval before updating prompts"
|
|
1291
|
-
)
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
class KnowledgeEngineConfig(BaseModel):
|
|
1295
|
-
"""Configuration for Knowledge Ecosystem Enhancement (Tier 1)"""
|
|
1296
|
-
|
|
1297
|
-
enabled: bool = Field(
|
|
1298
|
-
default=True, description="Enable always-on knowledge orchestration engine"
|
|
1299
|
-
)
|
|
1300
|
-
auto_detect_domains: bool = Field(
|
|
1301
|
-
default=True, description="Automatically detect project domains"
|
|
1302
|
-
)
|
|
1303
|
-
auto_create_experts: bool = Field(
|
|
1304
|
-
default=True, description="Automatically create project experts"
|
|
1305
|
-
)
|
|
1306
|
-
knowledge_ingestion_enabled: bool = Field(
|
|
1307
|
-
default=True, description="Enable automatic knowledge ingestion"
|
|
1308
|
-
)
|
|
1309
|
-
proactive_consultation: bool = Field(
|
|
1310
|
-
default=True, description="Proactively consult experts before needed"
|
|
1311
|
-
)
|
|
1312
|
-
metrics_tracking_enabled: bool = Field(
|
|
1313
|
-
default=True, description="Enable metrics tracking for knowledge quality"
|
|
1314
|
-
)
|
|
1315
|
-
kb_maintenance_schedule: str = Field(
|
|
1316
|
-
default="weekly", description="KB maintenance schedule: daily, weekly, monthly"
|
|
1317
|
-
)
|
|
1318
|
-
governance_enabled: bool = Field(
|
|
1319
|
-
default=True, description="Enable governance and safety layer"
|
|
1320
|
-
)
|
|
1321
|
-
require_approval_for_writes: bool = Field(
|
|
1322
|
-
default=False, description="Require approval before writing to knowledge base"
|
|
1323
|
-
)
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
class ContextIntelligenceConfig(BaseModel):
|
|
1327
|
-
"""Configuration for Context Intelligence Engine (Tier 1)"""
|
|
1328
|
-
|
|
1329
|
-
enabled: bool = Field(
|
|
1330
|
-
default=True, description="Enable context intelligence engine"
|
|
1331
|
-
)
|
|
1332
|
-
dynamic_gathering_enabled: bool = Field(
|
|
1333
|
-
default=True, description="Enable dynamic context gathering"
|
|
1334
|
-
)
|
|
1335
|
-
repository_exploration_enabled: bool = Field(
|
|
1336
|
-
default=True, description="Enable autonomous repository exploration"
|
|
1337
|
-
)
|
|
1338
|
-
pattern_recognition_enabled: bool = Field(
|
|
1339
|
-
default=True, description="Enable pattern recognition and cataloging"
|
|
1340
|
-
)
|
|
1341
|
-
similarity_detection_enabled: bool = Field(
|
|
1342
|
-
default=True, description="Enable similarity detection for code reuse"
|
|
1343
|
-
)
|
|
1344
|
-
historical_analysis_enabled: bool = Field(
|
|
1345
|
-
default=True, description="Enable historical context analysis"
|
|
1346
|
-
)
|
|
1347
|
-
relevance_ranking_enabled: bool = Field(
|
|
1348
|
-
default=True, description="Enable relevance-based context ranking"
|
|
1349
|
-
)
|
|
1350
|
-
token_budget_management_enabled: bool = Field(
|
|
1351
|
-
default=True, description="Enable token budget management"
|
|
1352
|
-
)
|
|
1353
|
-
default_token_budget: int = Field(
|
|
1354
|
-
default=4000, ge=1000, le=16000, description="Default token budget for context"
|
|
1355
|
-
)
|
|
1356
|
-
progressive_loading_enabled: bool = Field(
|
|
1357
|
-
default=True, description="Enable progressive context loading"
|
|
1358
|
-
)
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
class AnalyticsConfig(BaseModel):
|
|
1362
|
-
"""Configuration for analytics and dual-write from execution metrics."""
|
|
1363
|
-
|
|
1364
|
-
record_from_execution: bool = Field(
|
|
1365
|
-
default=True,
|
|
1366
|
-
description="When True, also write to .tapps-agents/analytics/ when recording execution metrics (step and workflow). Set False for metrics-only (no analytics).",
|
|
1367
|
-
)
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
class GuardrailConfig(BaseModel):
|
|
1371
|
-
"""Security guardrails for subprocess and file writes (plan 2.2)."""
|
|
1372
|
-
|
|
1373
|
-
sandbox_subprocess: bool = Field(
|
|
1374
|
-
default=True,
|
|
1375
|
-
description="When True, never use shell for subprocess; use cwd=project_root.",
|
|
1376
|
-
)
|
|
1377
|
-
allowed_paths_write: list[str] = Field(
|
|
1378
|
-
default_factory=list,
|
|
1379
|
-
description="When non-empty, writes must be under project_root and under one of these prefixes (e.g. src, tests, docs, .tapps-agents). When empty, only under project_root.",
|
|
1380
|
-
)
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
class HumanOversightConfig(BaseModel):
|
|
1384
|
-
"""Human-in-the-loop oversight for *build and *full (plan 2.3)."""
|
|
1385
|
-
|
|
1386
|
-
checkpoints_before_steps: list[str] = Field(
|
|
1387
|
-
default_factory=list,
|
|
1388
|
-
description="Step/agent names before which to prompt: e.g. implementer, designer. If --auto, skipped.",
|
|
1389
|
-
)
|
|
1390
|
-
require_diff_review_implementer: bool = Field(
|
|
1391
|
-
default=False,
|
|
1392
|
-
description="Reserved: when implementer supports preview/diff, require review before apply. Not implemented.",
|
|
1393
|
-
)
|
|
1394
|
-
branch_for_agent_changes: bool = Field(
|
|
1395
|
-
default=True,
|
|
1396
|
-
description="For *build and *full: create branch tapps-agents/build-{workflow_id}; merge to main only after human review.",
|
|
1397
|
-
)
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
class ProjectConfig(BaseModel):
|
|
1401
|
-
"""Root configuration model for TappsCodingAgents project"""
|
|
1402
|
-
|
|
1403
|
-
# Project metadata
|
|
1404
|
-
project_name: str | None = Field(default=None, description="Project name")
|
|
1405
|
-
version: str | None = Field(default=None, description="Project version")
|
|
1406
|
-
|
|
1407
|
-
# CLI / runtime
|
|
1408
|
-
offline_mode: bool = Field(
|
|
1409
|
-
default=False,
|
|
1410
|
-
description="Use offline mode (no network) when possible for CLI and agents",
|
|
1411
|
-
)
|
|
1412
|
-
|
|
1413
|
-
# Core configuration
|
|
1414
|
-
tooling: ToolingConfig = Field(
|
|
1415
|
-
default_factory=ToolingConfig,
|
|
1416
|
-
description="Canonical runtime/tool targets and policy (used by doctor/CI/agents)",
|
|
1417
|
-
)
|
|
1418
|
-
agents: AgentsConfig = Field(default_factory=AgentsConfig)
|
|
1419
|
-
scoring: ScoringConfig = Field(default_factory=ScoringConfig)
|
|
1420
|
-
expert: ExpertConfig = Field(
|
|
1421
|
-
default_factory=ExpertConfig,
|
|
1422
|
-
description="Expert consultation system configuration",
|
|
1423
|
-
)
|
|
1424
|
-
context7: Context7Config | None = Field(
|
|
1425
|
-
default_factory=Context7Config, description="Context7 integration configuration"
|
|
1426
|
-
)
|
|
1427
|
-
context_budget: ContextBudgetConfig = Field(
|
|
1428
|
-
default_factory=ContextBudgetConfig,
|
|
1429
|
-
description="Context budget: max_chunks for Context7/expert injection; surface cached_at (plan 3.2).",
|
|
1430
|
-
)
|
|
1431
|
-
quality_tools: QualityToolsConfig | None = Field(
|
|
1432
|
-
default_factory=QualityToolsConfig,
|
|
1433
|
-
description="Quality analysis tools configuration (Phase 6)",
|
|
1434
|
-
)
|
|
1435
|
-
workflow: WorkflowConfig = Field(
|
|
1436
|
-
default_factory=WorkflowConfig,
|
|
1437
|
-
description="Workflow execution configuration",
|
|
1438
|
-
)
|
|
1439
|
-
analytics: AnalyticsConfig = Field(
|
|
1440
|
-
default_factory=AnalyticsConfig,
|
|
1441
|
-
description="Analytics and dual-write from execution metrics (health usage, outcomes).",
|
|
1442
|
-
)
|
|
1443
|
-
guardrails: GuardrailConfig = Field(
|
|
1444
|
-
default_factory=GuardrailConfig,
|
|
1445
|
-
description="Security guardrails: subprocess sandbox, path allowlist for writes (plan 2.2).",
|
|
1446
|
-
)
|
|
1447
|
-
human_oversight: HumanOversightConfig = Field(
|
|
1448
|
-
default_factory=HumanOversightConfig,
|
|
1449
|
-
description="Human oversight: step checkpoints, branch-for-agent-changes (plan 2.3). require_diff_review_implementer reserved.",
|
|
1450
|
-
)
|
|
1451
|
-
simple_mode: SimpleModeConfig = Field(
|
|
1452
|
-
default_factory=SimpleModeConfig,
|
|
1453
|
-
description="Simple Mode configuration (intent-based orchestration)",
|
|
1454
|
-
)
|
|
1455
|
-
beads: BeadsConfig = Field(
|
|
1456
|
-
default_factory=BeadsConfig,
|
|
1457
|
-
description="Beads (bd) task-tracking integration. See docs/BEADS_INTEGRATION.md.",
|
|
1458
|
-
)
|
|
1459
|
-
bug_fix_agent: BugFixAgentConfig = Field(
|
|
1460
|
-
default_factory=BugFixAgentConfig,
|
|
1461
|
-
description="Bug Fix Agent configuration (automated bug fixing with auto-commit)",
|
|
1462
|
-
)
|
|
1463
|
-
continuous_bug_fix: ContinuousBugFixConfig = Field(
|
|
1464
|
-
default_factory=ContinuousBugFixConfig,
|
|
1465
|
-
description="Continuous Bug Fix configuration (automated bug finding and fixing loop)",
|
|
1466
|
-
)
|
|
1467
|
-
auto_enhancement: AutoEnhancementConfig = Field(
|
|
1468
|
-
default_factory=AutoEnhancementConfig,
|
|
1469
|
-
description="Automatic prompt enhancement configuration",
|
|
1470
|
-
)
|
|
1471
|
-
|
|
1472
|
-
# Tier 1 Enhancement Configurations
|
|
1473
|
-
evaluation: EvaluationConfig = Field(
|
|
1474
|
-
default_factory=EvaluationConfig,
|
|
1475
|
-
description="Evaluation & Quality Assurance Engine configuration (Tier 1)",
|
|
1476
|
-
)
|
|
1477
|
-
prompt_learning: PromptLearningConfig = Field(
|
|
1478
|
-
default_factory=PromptLearningConfig,
|
|
1479
|
-
description="Continual System Prompt Learning configuration (Tier 1)",
|
|
1480
|
-
)
|
|
1481
|
-
knowledge_engine: KnowledgeEngineConfig = Field(
|
|
1482
|
-
default_factory=KnowledgeEngineConfig,
|
|
1483
|
-
description="Knowledge Ecosystem Enhancement configuration (Tier 1)",
|
|
1484
|
-
)
|
|
1485
|
-
context_intelligence: ContextIntelligenceConfig = Field(
|
|
1486
|
-
default_factory=ContextIntelligenceConfig,
|
|
1487
|
-
description="Context Intelligence Engine configuration (Tier 1)",
|
|
1488
|
-
)
|
|
1489
|
-
cleanup: CleanupConfig = Field(
|
|
1490
|
-
default_factory=CleanupConfig,
|
|
1491
|
-
description="Cleanup operations configuration",
|
|
1492
|
-
)
|
|
1493
|
-
|
|
1494
|
-
model_config = {
|
|
1495
|
-
"extra": "ignore", # Ignore unknown fields
|
|
1496
|
-
"validate_assignment": True,
|
|
1497
|
-
}
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
def load_config(config_path: Path | None = None) -> ProjectConfig:
|
|
1501
|
-
"""
|
|
1502
|
-
Load configuration from YAML file.
|
|
1503
|
-
|
|
1504
|
-
Args:
|
|
1505
|
-
config_path: Path to config.yaml file. If None, looks for `.tapps-agents/config.yaml`
|
|
1506
|
-
in current directory or parent directories.
|
|
1507
|
-
|
|
1508
|
-
Returns:
|
|
1509
|
-
ProjectConfig instance with loaded values
|
|
1510
|
-
|
|
1511
|
-
Raises:
|
|
1512
|
-
FileNotFoundError: If config file doesn't exist and no defaults available
|
|
1513
|
-
ValueError: If config file is invalid
|
|
1514
|
-
"""
|
|
1515
|
-
if config_path is None:
|
|
1516
|
-
# Look for .tapps-agents/config.yaml in current and parent directories
|
|
1517
|
-
current = Path.cwd()
|
|
1518
|
-
for parent in [current] + list(current.parents):
|
|
1519
|
-
candidate = parent / ".tapps-agents" / "config.yaml"
|
|
1520
|
-
if candidate.exists():
|
|
1521
|
-
config_path = candidate
|
|
1522
|
-
break
|
|
1523
|
-
|
|
1524
|
-
if config_path is None:
|
|
1525
|
-
# Return defaults if no config file found
|
|
1526
|
-
return ProjectConfig()
|
|
1527
|
-
|
|
1528
|
-
if not config_path.exists():
|
|
1529
|
-
# Return defaults if file doesn't exist
|
|
1530
|
-
return ProjectConfig()
|
|
1531
|
-
|
|
1532
|
-
try:
|
|
1533
|
-
# Use utf-8-sig to automatically handle UTF-8 BOM (common on Windows)
|
|
1534
|
-
# This prevents YAML parsing failures when files have BOM prefix (\xef\xbb\xbf)
|
|
1535
|
-
with open(config_path, encoding="utf-8-sig") as f:
|
|
1536
|
-
data = yaml.safe_load(f)
|
|
1537
|
-
|
|
1538
|
-
if data is None:
|
|
1539
|
-
# Empty file, return defaults
|
|
1540
|
-
return ProjectConfig()
|
|
1541
|
-
|
|
1542
|
-
# Validate and load config
|
|
1543
|
-
return ProjectConfig(**data)
|
|
1544
|
-
except yaml.YAMLError as e:
|
|
1545
|
-
raise ValueError(f"Invalid YAML in config file {config_path}: {e}") from e
|
|
1546
|
-
except Exception as e:
|
|
1547
|
-
raise ValueError(f"Error loading config from {config_path}: {e}") from e
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
def save_config(config_path: Path, config: ProjectConfig) -> None:
|
|
1551
|
-
"""
|
|
1552
|
-
Save configuration to a YAML file.
|
|
1553
|
-
|
|
1554
|
-
Args:
|
|
1555
|
-
config_path: Path to the config file
|
|
1556
|
-
config: ProjectConfig instance to save
|
|
1557
|
-
|
|
1558
|
-
Raises:
|
|
1559
|
-
OSError: If the file cannot be written
|
|
1560
|
-
"""
|
|
1561
|
-
config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
1562
|
-
|
|
1563
|
-
# Load existing config to preserve other settings
|
|
1564
|
-
existing_data: dict[str, Any] = {}
|
|
1565
|
-
if config_path.exists():
|
|
1566
|
-
try:
|
|
1567
|
-
# Use utf-8-sig to handle UTF-8 BOM (common on Windows)
|
|
1568
|
-
with open(config_path, encoding="utf-8-sig") as f:
|
|
1569
|
-
existing_data = yaml.safe_load(f) or {}
|
|
1570
|
-
except Exception:
|
|
1571
|
-
# If we can't read existing config, start fresh
|
|
1572
|
-
existing_data = {}
|
|
1573
|
-
|
|
1574
|
-
# Merge with new config (convert to dict, preserving existing values)
|
|
1575
|
-
new_data = config.model_dump(exclude_none=True, mode="json")
|
|
1576
|
-
|
|
1577
|
-
def deep_merge(existing: dict[str, Any], new: dict[str, Any]) -> dict[str, Any]:
|
|
1578
|
-
"""Recursively merge new dict into existing dict."""
|
|
1579
|
-
result = existing.copy()
|
|
1580
|
-
for key, value in new.items():
|
|
1581
|
-
if key in result and isinstance(result[key], dict) and isinstance(value, dict):
|
|
1582
|
-
# Recursively merge nested dictionaries
|
|
1583
|
-
result[key] = deep_merge(result[key], value)
|
|
1584
|
-
else:
|
|
1585
|
-
# Overwrite with new value
|
|
1586
|
-
result[key] = value
|
|
1587
|
-
return result
|
|
1588
|
-
|
|
1589
|
-
# Deep merge: preserve existing nested values
|
|
1590
|
-
existing_data = deep_merge(existing_data, new_data)
|
|
1591
|
-
|
|
1592
|
-
# Save
|
|
1593
|
-
with open(config_path, "w", encoding="utf-8") as f:
|
|
1594
|
-
yaml.dump(existing_data, f, default_flow_style=False, sort_keys=False, allow_unicode=True)
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
def get_default_config() -> dict[str, Any]:
|
|
1598
|
-
"""
|
|
1599
|
-
Get default configuration as a dictionary (for template generation).
|
|
1600
|
-
|
|
1601
|
-
Returns:
|
|
1602
|
-
Dictionary representation of default config with Path objects as strings
|
|
1603
|
-
"""
|
|
1604
|
-
config = ProjectConfig()
|
|
1605
|
-
# Use model_dump with mode="json" to serialize Path objects as strings
|
|
1606
|
-
# This is required for YAML serialization (yaml.safe_dump can't handle Path objects)
|
|
1607
|
-
return config.model_dump(exclude_none=True, mode="json")
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
def get_expert_config(config: ProjectConfig | None = None) -> ExpertConfig:
|
|
1611
|
-
"""
|
|
1612
|
-
Get expert configuration, loading from file if needed.
|
|
1613
|
-
|
|
1614
|
-
Args:
|
|
1615
|
-
config: Optional ProjectConfig instance. If None, loads from file.
|
|
1616
|
-
|
|
1617
|
-
Returns:
|
|
1618
|
-
ExpertConfig instance
|
|
1619
|
-
"""
|
|
1620
|
-
if config is None:
|
|
1621
|
-
config = load_config()
|
|
1622
|
-
return config.expert
|
|
1
|
+
"""
|
|
2
|
+
Configuration management for TappsCodingAgents.
|
|
3
|
+
|
|
4
|
+
Provides Pydantic models for type-safe configuration and YAML loading.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
import yaml
|
|
11
|
+
from pydantic import BaseModel, Field, model_validator
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ScoringWeightsConfig(BaseModel):
|
|
15
|
+
"""Configuration for code scoring weights (must sum to 1.0). 7-category: Structure, DevEx added (MCP_SYSTEMS_IMPROVEMENT_RECOMMENDATIONS §3.2)."""
|
|
16
|
+
|
|
17
|
+
complexity: float = Field(
|
|
18
|
+
default=0.18, ge=0.0, le=1.0, description="Weight for complexity score"
|
|
19
|
+
)
|
|
20
|
+
security: float = Field(
|
|
21
|
+
default=0.27, ge=0.0, le=1.0, description="Weight for security score"
|
|
22
|
+
)
|
|
23
|
+
maintainability: float = Field(
|
|
24
|
+
default=0.24, ge=0.0, le=1.0, description="Weight for maintainability score"
|
|
25
|
+
)
|
|
26
|
+
test_coverage: float = Field(
|
|
27
|
+
default=0.13, ge=0.0, le=1.0, description="Weight for test coverage score"
|
|
28
|
+
)
|
|
29
|
+
performance: float = Field(
|
|
30
|
+
default=0.08, ge=0.0, le=1.0, description="Weight for performance score"
|
|
31
|
+
)
|
|
32
|
+
structure: float = Field(
|
|
33
|
+
default=0.05, ge=0.0, le=1.0, description="Weight for structure score (project layout, key files)"
|
|
34
|
+
)
|
|
35
|
+
devex: float = Field(
|
|
36
|
+
default=0.05, ge=0.0, le=1.0, description="Weight for developer experience score (docs, config, tooling)"
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
@model_validator(mode="after")
|
|
40
|
+
def validate_weights_sum(self):
|
|
41
|
+
"""Ensure weights sum to approximately 1.0"""
|
|
42
|
+
total = (
|
|
43
|
+
self.complexity
|
|
44
|
+
+ self.security
|
|
45
|
+
+ self.maintainability
|
|
46
|
+
+ self.test_coverage
|
|
47
|
+
+ self.performance
|
|
48
|
+
+ self.structure
|
|
49
|
+
+ self.devex
|
|
50
|
+
)
|
|
51
|
+
if abs(total - 1.0) > 0.01: # Allow small floating point errors
|
|
52
|
+
raise ValueError(f"Scoring weights must sum to 1.0, got {total}")
|
|
53
|
+
return self
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class TestCoverageConfig(BaseModel):
|
|
57
|
+
"""Test coverage configuration for quality gates."""
|
|
58
|
+
|
|
59
|
+
enabled: bool = Field(default=True, description="Enable test coverage checks")
|
|
60
|
+
threshold: float = Field(
|
|
61
|
+
default=0.8, ge=0.0, le=1.0, description="Minimum coverage threshold (0.0-1.0)"
|
|
62
|
+
)
|
|
63
|
+
critical_services_threshold: float = Field(
|
|
64
|
+
default=0.8,
|
|
65
|
+
ge=0.0,
|
|
66
|
+
le=1.0,
|
|
67
|
+
description="Minimum coverage for critical services (0.0-1.0)",
|
|
68
|
+
)
|
|
69
|
+
warning_threshold: float = Field(
|
|
70
|
+
default=0.6,
|
|
71
|
+
ge=0.0,
|
|
72
|
+
le=1.0,
|
|
73
|
+
description="Coverage threshold for warnings (0.0-1.0)",
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class QualityGatesConfig(BaseModel):
|
|
78
|
+
"""Quality gates configuration."""
|
|
79
|
+
|
|
80
|
+
enabled: bool = Field(default=True, description="Enable quality gates")
|
|
81
|
+
test_coverage: TestCoverageConfig = Field(
|
|
82
|
+
default_factory=TestCoverageConfig, description="Test coverage configuration"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class ScoringConfig(BaseModel):
|
|
87
|
+
"""Configuration for code scoring system"""
|
|
88
|
+
|
|
89
|
+
weights: ScoringWeightsConfig = Field(default_factory=ScoringWeightsConfig)
|
|
90
|
+
quality_threshold: float = Field(
|
|
91
|
+
default=70.0, ge=0.0, le=100.0, description="Minimum overall score to pass"
|
|
92
|
+
)
|
|
93
|
+
quality_gates: QualityGatesConfig = Field(
|
|
94
|
+
default_factory=QualityGatesConfig, description="Quality gates configuration"
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class ReviewerAgentContext7Config(BaseModel):
|
|
99
|
+
"""Context7 configuration for Reviewer Agent"""
|
|
100
|
+
|
|
101
|
+
auto_detect: bool = Field(
|
|
102
|
+
default=True, description="Enable automatic library detection"
|
|
103
|
+
)
|
|
104
|
+
topics: list[str] = Field(
|
|
105
|
+
default_factory=lambda: ["best-practices", "routing", "api-design"],
|
|
106
|
+
description="Default topics to fetch for detected libraries"
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class ReviewerAgentConfig(BaseModel):
|
|
111
|
+
"""Configuration specific to Reviewer Agent"""
|
|
112
|
+
|
|
113
|
+
quality_threshold: float = Field(
|
|
114
|
+
default=70.0, ge=0.0, le=100.0, description="Minimum score to pass review"
|
|
115
|
+
)
|
|
116
|
+
include_scoring: bool = Field(
|
|
117
|
+
default=True, description="Include code scoring in review"
|
|
118
|
+
)
|
|
119
|
+
include_llm_feedback: bool = Field(
|
|
120
|
+
default=True, description="Include LLM-generated feedback"
|
|
121
|
+
)
|
|
122
|
+
max_file_size: int = Field(
|
|
123
|
+
default=1024 * 1024,
|
|
124
|
+
ge=1024,
|
|
125
|
+
description="Maximum file size in bytes (1MB default)",
|
|
126
|
+
)
|
|
127
|
+
min_confidence_threshold: float = Field(
|
|
128
|
+
default=0.8,
|
|
129
|
+
ge=0.0,
|
|
130
|
+
le=1.0,
|
|
131
|
+
description="Minimum expert confidence threshold (0.0-1.0)",
|
|
132
|
+
)
|
|
133
|
+
operation_timeout: float = Field(
|
|
134
|
+
default=300.0,
|
|
135
|
+
ge=10.0,
|
|
136
|
+
description="Timeout in seconds for reviewer operations (default: 5 minutes)",
|
|
137
|
+
)
|
|
138
|
+
tool_timeout: float = Field(
|
|
139
|
+
default=30.0,
|
|
140
|
+
ge=5.0,
|
|
141
|
+
description="Timeout in seconds for individual quality tools (default: 30 seconds)",
|
|
142
|
+
)
|
|
143
|
+
enable_parallel_tools: bool = Field(
|
|
144
|
+
default=True,
|
|
145
|
+
description="Enable parallel execution of quality tools (Ruff, mypy, bandit)",
|
|
146
|
+
)
|
|
147
|
+
context7: ReviewerAgentContext7Config = Field(
|
|
148
|
+
default_factory=ReviewerAgentContext7Config,
|
|
149
|
+
description="Context7 integration settings for Reviewer Agent"
|
|
150
|
+
)
|
|
151
|
+
# NEW: Library detection config
|
|
152
|
+
auto_library_detection: bool = Field(
|
|
153
|
+
default=True,
|
|
154
|
+
description="Automatically detect libraries from code and dependency files"
|
|
155
|
+
)
|
|
156
|
+
library_detection_depth: str = Field(
|
|
157
|
+
default="both",
|
|
158
|
+
description="What to detect: 'code' (imports only), 'dependencies' (requirements.txt/pyproject.toml), or 'both'"
|
|
159
|
+
)
|
|
160
|
+
# NEW: Context7 integration config
|
|
161
|
+
auto_context7_lookups: bool = Field(
|
|
162
|
+
default=True,
|
|
163
|
+
description="Automatically lookup library documentation from Context7"
|
|
164
|
+
)
|
|
165
|
+
context7_timeout: int = Field(
|
|
166
|
+
default=30,
|
|
167
|
+
ge=1,
|
|
168
|
+
le=300,
|
|
169
|
+
description="Timeout for Context7 lookups in seconds"
|
|
170
|
+
)
|
|
171
|
+
context7_cache_enabled: bool = Field(
|
|
172
|
+
default=True,
|
|
173
|
+
description="Cache Context7 responses to avoid duplicate lookups"
|
|
174
|
+
)
|
|
175
|
+
# NEW: Pattern detection config
|
|
176
|
+
pattern_detection_enabled: bool = Field(
|
|
177
|
+
default=True,
|
|
178
|
+
description="Enable domain-specific pattern detection"
|
|
179
|
+
)
|
|
180
|
+
pattern_confidence_threshold: float = Field(
|
|
181
|
+
default=0.5,
|
|
182
|
+
ge=0.0,
|
|
183
|
+
le=1.0,
|
|
184
|
+
description="Minimum confidence to report detected patterns (0.0-1.0)"
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class PlannerAgentConfig(BaseModel):
|
|
189
|
+
"""Configuration specific to Planner Agent"""
|
|
190
|
+
|
|
191
|
+
stories_dir: str | None = Field(
|
|
192
|
+
default=None, description="Directory for storing stories (default: stories/)"
|
|
193
|
+
)
|
|
194
|
+
default_priority: str = Field(
|
|
195
|
+
default="medium",
|
|
196
|
+
description="Default priority for new stories (high/medium/low)",
|
|
197
|
+
)
|
|
198
|
+
min_confidence_threshold: float = Field(
|
|
199
|
+
default=0.6,
|
|
200
|
+
ge=0.0,
|
|
201
|
+
le=1.0,
|
|
202
|
+
description="Minimum expert confidence threshold (0.0-1.0)",
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
class ImplementerAgentContext7Config(BaseModel):
|
|
207
|
+
"""Context7 configuration for Implementer Agent"""
|
|
208
|
+
|
|
209
|
+
auto_detect: bool = Field(
|
|
210
|
+
default=True, description="Enable automatic library detection"
|
|
211
|
+
)
|
|
212
|
+
detect_from_prompt: bool = Field(
|
|
213
|
+
default=True, description="Detect libraries from prompt/specification text"
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
class ImplementerAgentConfig(BaseModel):
|
|
218
|
+
"""Configuration specific to Implementer Agent"""
|
|
219
|
+
|
|
220
|
+
require_review: bool = Field(
|
|
221
|
+
default=True, description="Require code review before writing files"
|
|
222
|
+
)
|
|
223
|
+
auto_approve_threshold: float = Field(
|
|
224
|
+
default=80.0, ge=0.0, le=100.0, description="Auto-approve if score >= threshold"
|
|
225
|
+
)
|
|
226
|
+
backup_files: bool = Field(
|
|
227
|
+
default=True, description="Create backup before overwriting existing files"
|
|
228
|
+
)
|
|
229
|
+
max_file_size: int = Field(
|
|
230
|
+
default=10 * 1024 * 1024,
|
|
231
|
+
ge=1024,
|
|
232
|
+
description="Maximum file size in bytes (10MB default)",
|
|
233
|
+
)
|
|
234
|
+
min_confidence_threshold: float = Field(
|
|
235
|
+
default=0.7,
|
|
236
|
+
ge=0.0,
|
|
237
|
+
le=1.0,
|
|
238
|
+
description="Minimum expert confidence threshold (0.0-1.0)",
|
|
239
|
+
)
|
|
240
|
+
context7: ImplementerAgentContext7Config = Field(
|
|
241
|
+
default_factory=ImplementerAgentContext7Config,
|
|
242
|
+
description="Context7 integration settings for Implementer Agent"
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
class TesterAgentConfig(BaseModel):
|
|
247
|
+
"""Configuration specific to Tester Agent"""
|
|
248
|
+
|
|
249
|
+
test_framework: str = Field(
|
|
250
|
+
default="pytest", description="Test framework to use (pytest/unittest)"
|
|
251
|
+
)
|
|
252
|
+
tests_dir: str | None = Field(
|
|
253
|
+
default=None, description="Directory for tests (default: tests/)"
|
|
254
|
+
)
|
|
255
|
+
coverage_threshold: float = Field(
|
|
256
|
+
default=80.0, ge=0.0, le=100.0, description="Target test coverage percentage"
|
|
257
|
+
)
|
|
258
|
+
auto_write_tests: bool = Field(
|
|
259
|
+
default=True, description="Automatically write generated tests to files"
|
|
260
|
+
)
|
|
261
|
+
min_confidence_threshold: float = Field(
|
|
262
|
+
default=0.7,
|
|
263
|
+
ge=0.0,
|
|
264
|
+
le=1.0,
|
|
265
|
+
description="Minimum expert confidence threshold (0.0-1.0)",
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
class DebuggerAgentContext7Config(BaseModel):
|
|
270
|
+
"""Context7 configuration for Debugger Agent"""
|
|
271
|
+
|
|
272
|
+
auto_detect: bool = Field(
|
|
273
|
+
default=True, description="Enable automatic library detection"
|
|
274
|
+
)
|
|
275
|
+
detect_from_errors: bool = Field(
|
|
276
|
+
default=True, description="Detect libraries from error messages and stack traces"
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
class DebuggerAgentConfig(BaseModel):
|
|
281
|
+
"""Configuration specific to Debugger Agent"""
|
|
282
|
+
|
|
283
|
+
include_code_examples: bool = Field(
|
|
284
|
+
default=True, description="Include code examples in fix suggestions"
|
|
285
|
+
)
|
|
286
|
+
max_context_lines: int = Field(
|
|
287
|
+
default=50,
|
|
288
|
+
ge=10,
|
|
289
|
+
le=200,
|
|
290
|
+
description="Maximum lines of code context to include in analysis",
|
|
291
|
+
)
|
|
292
|
+
min_confidence_threshold: float = Field(
|
|
293
|
+
default=0.7,
|
|
294
|
+
ge=0.0,
|
|
295
|
+
le=1.0,
|
|
296
|
+
description="Minimum expert confidence threshold (0.0-1.0)",
|
|
297
|
+
)
|
|
298
|
+
context7: DebuggerAgentContext7Config = Field(
|
|
299
|
+
default_factory=DebuggerAgentContext7Config,
|
|
300
|
+
description="Context7 integration settings for Debugger Agent"
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
class DocumenterAgentConfig(BaseModel):
|
|
305
|
+
"""Configuration specific to Documenter Agent"""
|
|
306
|
+
|
|
307
|
+
docs_dir: str | None = Field(
|
|
308
|
+
default=None, description="Directory for generated docs (default: docs/)"
|
|
309
|
+
)
|
|
310
|
+
include_examples: bool = Field(
|
|
311
|
+
default=True, description="Include code examples in documentation"
|
|
312
|
+
)
|
|
313
|
+
docstring_format: str = Field(
|
|
314
|
+
default="google", description="Docstring format (google/numpy/sphinx)"
|
|
315
|
+
)
|
|
316
|
+
min_confidence_threshold: float = Field(
|
|
317
|
+
default=0.5,
|
|
318
|
+
ge=0.0,
|
|
319
|
+
le=1.0,
|
|
320
|
+
description="Minimum expert confidence threshold (0.0-1.0)",
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
class Context7KnowledgeBaseConfig(BaseModel):
|
|
325
|
+
"""Configuration for Context7 knowledge base caching"""
|
|
326
|
+
|
|
327
|
+
enabled: bool = Field(default=True, description="Enable KB caching")
|
|
328
|
+
location: str = Field(
|
|
329
|
+
default=".tapps-agents/kb/context7-cache", description="KB cache directory"
|
|
330
|
+
)
|
|
331
|
+
sharding: bool = Field(default=True, description="Enable library-based sharding")
|
|
332
|
+
indexing: bool = Field(default=True, description="Enable indexing")
|
|
333
|
+
max_cache_size: str = Field(default="100MB", description="Maximum cache size")
|
|
334
|
+
hit_rate_threshold: float = Field(
|
|
335
|
+
default=0.7, ge=0.0, le=1.0, description="Target hit rate threshold"
|
|
336
|
+
)
|
|
337
|
+
fuzzy_match_threshold: float = Field(
|
|
338
|
+
default=0.7, ge=0.0, le=1.0, description="Fuzzy match confidence threshold"
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
class Context7RefreshConfig(BaseModel):
|
|
343
|
+
"""Configuration for Context7 auto-refresh system"""
|
|
344
|
+
|
|
345
|
+
enabled: bool = Field(default=True, description="Enable auto-refresh")
|
|
346
|
+
default_max_age_days: int = Field(
|
|
347
|
+
default=30, ge=1, description="Default max age for cache entries (days)"
|
|
348
|
+
)
|
|
349
|
+
check_on_access: bool = Field(default=True, description="Check staleness on access")
|
|
350
|
+
auto_queue: bool = Field(
|
|
351
|
+
default=True, description="Automatically queue stale entries"
|
|
352
|
+
)
|
|
353
|
+
auto_process_on_startup: bool = Field(
|
|
354
|
+
default=False, description="Process queue on agent startup"
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
class Context7Config(BaseModel):
|
|
359
|
+
"""Configuration for Context7 integration"""
|
|
360
|
+
|
|
361
|
+
enabled: bool = Field(default=True, description="Enable Context7 integration")
|
|
362
|
+
default_token_limit: int = Field(
|
|
363
|
+
default=3000, ge=100, description="Default token limit for Context7 docs"
|
|
364
|
+
)
|
|
365
|
+
cache_duration: int = Field(
|
|
366
|
+
default=3600, ge=0, description="Cache duration in seconds"
|
|
367
|
+
)
|
|
368
|
+
integration_level: str = Field(
|
|
369
|
+
default="optional", description="Integration level (mandatory/optional)"
|
|
370
|
+
)
|
|
371
|
+
usage_requirement: str | None = Field(
|
|
372
|
+
default=None, description="Usage requirement description"
|
|
373
|
+
)
|
|
374
|
+
bypass_forbidden: bool = Field(
|
|
375
|
+
default=True, description="Allow bypassing if Context7 unavailable"
|
|
376
|
+
)
|
|
377
|
+
# Enhancement: Automatic Context7 detection and fetching
|
|
378
|
+
auto_detect: bool = Field(
|
|
379
|
+
default=True, description="Enable automatic library detection from code, prompts, and errors"
|
|
380
|
+
)
|
|
381
|
+
auto_fetch: bool = Field(
|
|
382
|
+
default=True, description="Automatically fetch docs for detected libraries"
|
|
383
|
+
)
|
|
384
|
+
proactive_suggestions: bool = Field(
|
|
385
|
+
default=True, description="Proactively suggest Context7 lookups when library patterns detected"
|
|
386
|
+
)
|
|
387
|
+
|
|
388
|
+
knowledge_base: Context7KnowledgeBaseConfig = Field(
|
|
389
|
+
default_factory=Context7KnowledgeBaseConfig
|
|
390
|
+
)
|
|
391
|
+
refresh: Context7RefreshConfig = Field(default_factory=Context7RefreshConfig)
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
class QualityToolsConfig(BaseModel):
|
|
395
|
+
"""Configuration for quality analysis tools (Phase 6 - 2025 Standards)"""
|
|
396
|
+
|
|
397
|
+
# Ruff configuration
|
|
398
|
+
ruff_enabled: bool = Field(default=True, description="Enable Ruff linting")
|
|
399
|
+
ruff_config_path: str | None = Field(
|
|
400
|
+
default=None,
|
|
401
|
+
description="Path to ruff.toml or pyproject.toml (auto-detected if None)",
|
|
402
|
+
)
|
|
403
|
+
|
|
404
|
+
# mypy configuration
|
|
405
|
+
mypy_enabled: bool = Field(default=True, description="Enable mypy type checking")
|
|
406
|
+
mypy_strict: bool = Field(default=False, description="Enable strict mode for mypy")
|
|
407
|
+
mypy_config_path: str | None = Field(
|
|
408
|
+
default=None,
|
|
409
|
+
description="Path to mypy.ini or pyproject.toml (auto-detected if None)",
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
# jscpd configuration
|
|
413
|
+
jscpd_enabled: bool = Field(
|
|
414
|
+
default=True, description="Enable jscpd duplication detection"
|
|
415
|
+
)
|
|
416
|
+
duplication_threshold: float = Field(
|
|
417
|
+
default=3.0,
|
|
418
|
+
ge=0.0,
|
|
419
|
+
le=100.0,
|
|
420
|
+
description="Maximum duplication percentage threshold",
|
|
421
|
+
)
|
|
422
|
+
min_duplication_lines: int = Field(
|
|
423
|
+
default=5, ge=3, description="Minimum lines for duplication detection"
|
|
424
|
+
)
|
|
425
|
+
|
|
426
|
+
# TypeScript/JavaScript configuration
|
|
427
|
+
typescript_enabled: bool = Field(
|
|
428
|
+
default=True, description="Enable TypeScript/JavaScript support"
|
|
429
|
+
)
|
|
430
|
+
eslint_config: str | None = Field(
|
|
431
|
+
default=None, description="Path to ESLint config file"
|
|
432
|
+
)
|
|
433
|
+
tsconfig_path: str | None = Field(default=None, description="Path to tsconfig.json")
|
|
434
|
+
|
|
435
|
+
# Dependency security auditing
|
|
436
|
+
pip_audit_enabled: bool = Field(
|
|
437
|
+
default=True, description="Enable pip-audit security scanning"
|
|
438
|
+
)
|
|
439
|
+
dependency_audit_threshold: str = Field(
|
|
440
|
+
default="high",
|
|
441
|
+
description="Minimum severity threshold (low/medium/high/critical)",
|
|
442
|
+
)
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
class ToolingTargetsConfig(BaseModel):
|
|
446
|
+
"""Pin runtime/tool targets so agents and CI behave deterministically."""
|
|
447
|
+
|
|
448
|
+
python: str = Field(
|
|
449
|
+
default="3.13.3",
|
|
450
|
+
description="Target Python version for this project (pin exact patch where possible)",
|
|
451
|
+
)
|
|
452
|
+
python_requires: str = Field(
|
|
453
|
+
default=">=3.13",
|
|
454
|
+
description="PEP 440 requires-python constraint enforced by packaging/CI",
|
|
455
|
+
)
|
|
456
|
+
os_targets: list[str] = Field(
|
|
457
|
+
default_factory=lambda: ["windows", "linux"],
|
|
458
|
+
description="Primary OS targets (used for setup/doctor guidance)",
|
|
459
|
+
)
|
|
460
|
+
node: str | None = Field(
|
|
461
|
+
default=None,
|
|
462
|
+
description="Optional Node.js version (only needed if TypeScript/jscpd tooling is enabled)",
|
|
463
|
+
)
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
class ToolingPolicyConfig(BaseModel):
|
|
467
|
+
"""Policy for how missing/optional tools are handled."""
|
|
468
|
+
|
|
469
|
+
external_tools_mode: str = Field(
|
|
470
|
+
default="soft",
|
|
471
|
+
description="How to handle missing external tools: soft=warn/skip, hard=fail",
|
|
472
|
+
)
|
|
473
|
+
mypy_staged: bool = Field(
|
|
474
|
+
default=True, description="Stage mypy enforcement module-by-module"
|
|
475
|
+
)
|
|
476
|
+
mypy_stage_paths: list[str] = Field(
|
|
477
|
+
default_factory=lambda: [
|
|
478
|
+
"tapps_agents/core",
|
|
479
|
+
"tapps_agents/workflow",
|
|
480
|
+
"tapps_agents/context7",
|
|
481
|
+
],
|
|
482
|
+
description="Paths enforced by mypy during the staged rollout",
|
|
483
|
+
)
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
class ToolingConfig(BaseModel):
|
|
487
|
+
"""Canonical tooling/targets configuration (single source of truth)."""
|
|
488
|
+
|
|
489
|
+
targets: ToolingTargetsConfig = Field(default_factory=ToolingTargetsConfig)
|
|
490
|
+
policy: ToolingPolicyConfig = Field(default_factory=ToolingPolicyConfig)
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
class ArchitectAgentConfig(BaseModel):
|
|
494
|
+
"""Configuration specific to Architect Agent"""
|
|
495
|
+
|
|
496
|
+
min_confidence_threshold: float = Field(
|
|
497
|
+
default=0.75,
|
|
498
|
+
ge=0.0,
|
|
499
|
+
le=1.0,
|
|
500
|
+
description="Minimum expert confidence threshold (0.0-1.0)",
|
|
501
|
+
)
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
class DesignerAgentConfig(BaseModel):
|
|
505
|
+
"""Configuration specific to Designer Agent"""
|
|
506
|
+
|
|
507
|
+
min_confidence_threshold: float = Field(
|
|
508
|
+
default=0.65,
|
|
509
|
+
ge=0.0,
|
|
510
|
+
le=1.0,
|
|
511
|
+
description="Minimum expert confidence threshold (0.0-1.0)",
|
|
512
|
+
)
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
class OpsAgentConfig(BaseModel):
|
|
516
|
+
"""Configuration specific to Ops Agent"""
|
|
517
|
+
|
|
518
|
+
min_confidence_threshold: float = Field(
|
|
519
|
+
default=0.75,
|
|
520
|
+
ge=0.0,
|
|
521
|
+
le=1.0,
|
|
522
|
+
description="Minimum expert confidence threshold (0.0-1.0)",
|
|
523
|
+
)
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
class EnhancerAgentConfig(BaseModel):
|
|
527
|
+
"""Configuration specific to Enhancer Agent"""
|
|
528
|
+
|
|
529
|
+
min_confidence_threshold: float = Field(
|
|
530
|
+
default=0.6,
|
|
531
|
+
ge=0.0,
|
|
532
|
+
le=1.0,
|
|
533
|
+
description="Minimum expert confidence threshold (0.0-1.0)",
|
|
534
|
+
)
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
class AnalystAgentConfig(BaseModel):
|
|
538
|
+
"""Configuration specific to Analyst Agent"""
|
|
539
|
+
|
|
540
|
+
min_confidence_threshold: float = Field(
|
|
541
|
+
default=0.65,
|
|
542
|
+
ge=0.0,
|
|
543
|
+
le=1.0,
|
|
544
|
+
description="Minimum expert confidence threshold (0.0-1.0)",
|
|
545
|
+
)
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
class OrchestratorAgentConfig(BaseModel):
|
|
549
|
+
"""Configuration specific to Orchestrator Agent"""
|
|
550
|
+
|
|
551
|
+
min_confidence_threshold: float = Field(
|
|
552
|
+
default=0.6,
|
|
553
|
+
ge=0.0,
|
|
554
|
+
le=1.0,
|
|
555
|
+
description="Minimum expert confidence threshold (0.0-1.0)",
|
|
556
|
+
)
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
class EvaluatorAgentConfig(BaseModel):
|
|
560
|
+
"""Configuration specific to Evaluator Agent"""
|
|
561
|
+
|
|
562
|
+
auto_run: bool = Field(
|
|
563
|
+
default=False,
|
|
564
|
+
description="Run evaluator automatically at end of workflows (build, full, etc.)"
|
|
565
|
+
)
|
|
566
|
+
output_dir: str = Field(
|
|
567
|
+
default=".tapps-agents/evaluations",
|
|
568
|
+
description="Directory for evaluation reports"
|
|
569
|
+
)
|
|
570
|
+
thresholds: dict[str, float] = Field(
|
|
571
|
+
default_factory=lambda: {
|
|
572
|
+
"quality_score": 70.0,
|
|
573
|
+
"workflow_completion": 0.8,
|
|
574
|
+
},
|
|
575
|
+
description="Thresholds for evaluation metrics"
|
|
576
|
+
)
|
|
577
|
+
|
|
578
|
+
|
|
579
|
+
class CleanupAgentConfig(BaseModel):
|
|
580
|
+
"""Configuration specific to Cleanup Agent"""
|
|
581
|
+
|
|
582
|
+
dry_run_default: bool = Field(
|
|
583
|
+
default=True,
|
|
584
|
+
description="Run in dry-run mode by default (preview changes without executing)"
|
|
585
|
+
)
|
|
586
|
+
backup_enabled: bool = Field(
|
|
587
|
+
default=True,
|
|
588
|
+
description="Create backups before destructive operations"
|
|
589
|
+
)
|
|
590
|
+
interactive_mode: bool = Field(
|
|
591
|
+
default=True,
|
|
592
|
+
description="Prompt for confirmation on risky operations"
|
|
593
|
+
)
|
|
594
|
+
default_pattern: str = Field(
|
|
595
|
+
default="*.md",
|
|
596
|
+
description="Default file pattern for analysis"
|
|
597
|
+
)
|
|
598
|
+
age_threshold_days: int = Field(
|
|
599
|
+
default=90,
|
|
600
|
+
ge=1,
|
|
601
|
+
le=365,
|
|
602
|
+
description="Days threshold for detecting outdated files"
|
|
603
|
+
)
|
|
604
|
+
similarity_threshold: float = Field(
|
|
605
|
+
default=0.8,
|
|
606
|
+
ge=0.0,
|
|
607
|
+
le=1.0,
|
|
608
|
+
description="Content similarity threshold for detecting near-duplicates"
|
|
609
|
+
)
|
|
610
|
+
backup_dir: str = Field(
|
|
611
|
+
default=".cleanup-backups",
|
|
612
|
+
description="Directory for cleanup backups"
|
|
613
|
+
)
|
|
614
|
+
|
|
615
|
+
|
|
616
|
+
class ExpertConfig(BaseModel):
|
|
617
|
+
"""Configuration for expert consultation system"""
|
|
618
|
+
|
|
619
|
+
# Agent-specific confidence thresholds
|
|
620
|
+
agent_confidence_thresholds: dict[str, float] = Field(
|
|
621
|
+
default_factory=lambda: {
|
|
622
|
+
"reviewer": 0.8,
|
|
623
|
+
"architect": 0.75,
|
|
624
|
+
"implementer": 0.7,
|
|
625
|
+
"designer": 0.65,
|
|
626
|
+
"tester": 0.7,
|
|
627
|
+
"ops": 0.75,
|
|
628
|
+
"enhancer": 0.6,
|
|
629
|
+
"analyst": 0.65,
|
|
630
|
+
"planner": 0.6,
|
|
631
|
+
"debugger": 0.7,
|
|
632
|
+
"documenter": 0.5,
|
|
633
|
+
"orchestrator": 0.6,
|
|
634
|
+
"default": 0.7,
|
|
635
|
+
},
|
|
636
|
+
description="Agent-specific confidence thresholds (0.0-1.0)",
|
|
637
|
+
)
|
|
638
|
+
|
|
639
|
+
# Confidence calculation weights
|
|
640
|
+
weight_max_confidence: float = Field(
|
|
641
|
+
default=0.35, ge=0.0, le=1.0, description="Weight for maximum expert confidence"
|
|
642
|
+
)
|
|
643
|
+
weight_agreement: float = Field(
|
|
644
|
+
default=0.25, ge=0.0, le=1.0, description="Weight for expert agreement level"
|
|
645
|
+
)
|
|
646
|
+
weight_rag_quality: float = Field(
|
|
647
|
+
default=0.2, ge=0.0, le=1.0, description="Weight for RAG knowledge base quality"
|
|
648
|
+
)
|
|
649
|
+
weight_domain_relevance: float = Field(
|
|
650
|
+
default=0.1, ge=0.0, le=1.0, description="Weight for domain relevance"
|
|
651
|
+
)
|
|
652
|
+
weight_project_context: float = Field(
|
|
653
|
+
default=0.1, ge=0.0, le=1.0, description="Weight for project context relevance"
|
|
654
|
+
)
|
|
655
|
+
|
|
656
|
+
# Agreement and similarity thresholds
|
|
657
|
+
high_agreement_threshold: float = Field(
|
|
658
|
+
default=0.75,
|
|
659
|
+
ge=0.0,
|
|
660
|
+
le=1.0,
|
|
661
|
+
description="High agreement threshold for expert consensus (0.0-1.0)",
|
|
662
|
+
)
|
|
663
|
+
similarity_threshold: float = Field(
|
|
664
|
+
default=0.6,
|
|
665
|
+
ge=0.0,
|
|
666
|
+
le=1.0,
|
|
667
|
+
description="Similarity threshold for expert response comparison (0.0-1.0)",
|
|
668
|
+
)
|
|
669
|
+
|
|
670
|
+
# RAG (Retrieval-Augmented Generation) parameters
|
|
671
|
+
rag_max_length: int = Field(
|
|
672
|
+
default=2000,
|
|
673
|
+
ge=100,
|
|
674
|
+
le=10000,
|
|
675
|
+
description="Maximum length for RAG context retrieval (characters)",
|
|
676
|
+
)
|
|
677
|
+
rag_max_results: int = Field(
|
|
678
|
+
default=8, ge=1, le=20, description="Maximum number of RAG results to retrieve"
|
|
679
|
+
)
|
|
680
|
+
rag_default_quality: float = Field(
|
|
681
|
+
default=0.8,
|
|
682
|
+
ge=0.0,
|
|
683
|
+
le=1.0,
|
|
684
|
+
description="Default RAG quality score when not provided (0.0-1.0)",
|
|
685
|
+
)
|
|
686
|
+
|
|
687
|
+
# Profile confidence threshold
|
|
688
|
+
profile_confidence_threshold: float = Field(
|
|
689
|
+
default=0.7,
|
|
690
|
+
ge=0.0,
|
|
691
|
+
le=1.0,
|
|
692
|
+
description="Minimum confidence threshold for including profile values (0.0-1.0)",
|
|
693
|
+
)
|
|
694
|
+
|
|
695
|
+
# Supporting expert weight
|
|
696
|
+
supporting_expert_weight: float = Field(
|
|
697
|
+
default=0.15,
|
|
698
|
+
ge=0.0,
|
|
699
|
+
le=1.0,
|
|
700
|
+
description="Approximate weight for supporting experts in agreement calculation",
|
|
701
|
+
)
|
|
702
|
+
|
|
703
|
+
@model_validator(mode="after")
|
|
704
|
+
def validate_weights_sum(self):
|
|
705
|
+
"""Ensure confidence weights sum to approximately 1.0"""
|
|
706
|
+
total = (
|
|
707
|
+
self.weight_max_confidence
|
|
708
|
+
+ self.weight_agreement
|
|
709
|
+
+ self.weight_rag_quality
|
|
710
|
+
+ self.weight_domain_relevance
|
|
711
|
+
+ self.weight_project_context
|
|
712
|
+
)
|
|
713
|
+
if abs(total - 1.0) > 0.01: # Allow small floating point errors
|
|
714
|
+
raise ValueError(f"Expert confidence weights must sum to 1.0, got {total}")
|
|
715
|
+
return self
|
|
716
|
+
|
|
717
|
+
|
|
718
|
+
class AgentsConfig(BaseModel):
|
|
719
|
+
"""Configuration for all agents"""
|
|
720
|
+
|
|
721
|
+
reviewer: ReviewerAgentConfig = Field(default_factory=ReviewerAgentConfig)
|
|
722
|
+
planner: PlannerAgentConfig = Field(default_factory=PlannerAgentConfig)
|
|
723
|
+
implementer: ImplementerAgentConfig = Field(default_factory=ImplementerAgentConfig)
|
|
724
|
+
tester: TesterAgentConfig = Field(default_factory=TesterAgentConfig)
|
|
725
|
+
debugger: DebuggerAgentConfig = Field(default_factory=DebuggerAgentConfig)
|
|
726
|
+
documenter: DocumenterAgentConfig = Field(default_factory=DocumenterAgentConfig)
|
|
727
|
+
architect: ArchitectAgentConfig = Field(default_factory=ArchitectAgentConfig)
|
|
728
|
+
designer: DesignerAgentConfig = Field(default_factory=DesignerAgentConfig)
|
|
729
|
+
ops: OpsAgentConfig = Field(default_factory=OpsAgentConfig)
|
|
730
|
+
enhancer: EnhancerAgentConfig = Field(default_factory=EnhancerAgentConfig)
|
|
731
|
+
analyst: AnalystAgentConfig = Field(default_factory=AnalystAgentConfig)
|
|
732
|
+
orchestrator: OrchestratorAgentConfig = Field(
|
|
733
|
+
default_factory=OrchestratorAgentConfig
|
|
734
|
+
)
|
|
735
|
+
evaluator: EvaluatorAgentConfig = Field(default_factory=EvaluatorAgentConfig)
|
|
736
|
+
cleanup_agent: CleanupAgentConfig = Field(default_factory=CleanupAgentConfig)
|
|
737
|
+
|
|
738
|
+
|
|
739
|
+
class CheckpointFrequencyConfig(BaseModel):
|
|
740
|
+
"""Configuration for checkpoint frequency"""
|
|
741
|
+
|
|
742
|
+
mode: str = Field(
|
|
743
|
+
default="every_step",
|
|
744
|
+
description="Checkpoint frequency mode: every_step, every_n_steps, on_gates, time_based, manual",
|
|
745
|
+
)
|
|
746
|
+
interval: int = Field(
|
|
747
|
+
default=1,
|
|
748
|
+
ge=1,
|
|
749
|
+
description="Interval for every_n_steps (step count) or time_based (seconds)",
|
|
750
|
+
)
|
|
751
|
+
enabled: bool = Field(
|
|
752
|
+
default=True,
|
|
753
|
+
description="Enable checkpointing",
|
|
754
|
+
)
|
|
755
|
+
|
|
756
|
+
|
|
757
|
+
class StateCleanupPolicyConfig(BaseModel):
|
|
758
|
+
"""Configuration for state cleanup policies"""
|
|
759
|
+
|
|
760
|
+
enabled: bool = Field(
|
|
761
|
+
default=True,
|
|
762
|
+
description="Enable automatic state cleanup",
|
|
763
|
+
)
|
|
764
|
+
retention_days: int | None = Field(
|
|
765
|
+
default=None,
|
|
766
|
+
ge=1,
|
|
767
|
+
description="Delete states older than N days (None = no retention limit)",
|
|
768
|
+
)
|
|
769
|
+
max_size_mb: int | None = Field(
|
|
770
|
+
default=None,
|
|
771
|
+
ge=1,
|
|
772
|
+
description="Maximum total state size in MB (None = no size limit)",
|
|
773
|
+
)
|
|
774
|
+
cleanup_schedule: str = Field(
|
|
775
|
+
default="daily",
|
|
776
|
+
description="Cleanup schedule: daily, weekly, monthly, on_startup, manual",
|
|
777
|
+
)
|
|
778
|
+
keep_latest: int = Field(
|
|
779
|
+
default=10,
|
|
780
|
+
ge=1,
|
|
781
|
+
description="Always keep the N most recent states",
|
|
782
|
+
)
|
|
783
|
+
|
|
784
|
+
|
|
785
|
+
class StatePersistenceConfig(BaseModel):
|
|
786
|
+
"""Configuration for state persistence and checkpointing"""
|
|
787
|
+
|
|
788
|
+
enabled: bool = Field(
|
|
789
|
+
default=True,
|
|
790
|
+
description="Enable state persistence",
|
|
791
|
+
)
|
|
792
|
+
storage_location: str = Field(
|
|
793
|
+
default=".tapps-agents/workflow-state",
|
|
794
|
+
description="Directory for storing workflow state",
|
|
795
|
+
)
|
|
796
|
+
format: str = Field(
|
|
797
|
+
default="json",
|
|
798
|
+
description="State storage format: json, json_gzip",
|
|
799
|
+
)
|
|
800
|
+
compression: bool = Field(
|
|
801
|
+
default=False,
|
|
802
|
+
description="Enable compression for state files",
|
|
803
|
+
)
|
|
804
|
+
checkpoint: CheckpointFrequencyConfig = Field(
|
|
805
|
+
default_factory=CheckpointFrequencyConfig,
|
|
806
|
+
description="Checkpoint frequency configuration",
|
|
807
|
+
)
|
|
808
|
+
cleanup: StateCleanupPolicyConfig = Field(
|
|
809
|
+
default_factory=StateCleanupPolicyConfig,
|
|
810
|
+
description="State cleanup policy configuration",
|
|
811
|
+
)
|
|
812
|
+
|
|
813
|
+
|
|
814
|
+
class BranchCleanupConfig(BaseModel):
|
|
815
|
+
"""Configuration for Git branch cleanup after workflow execution"""
|
|
816
|
+
|
|
817
|
+
enabled: bool = Field(
|
|
818
|
+
default=True,
|
|
819
|
+
description="Enable automatic branch cleanup",
|
|
820
|
+
)
|
|
821
|
+
delete_branches_on_cleanup: bool = Field(
|
|
822
|
+
default=True,
|
|
823
|
+
description="Delete associated Git branches when worktrees are removed",
|
|
824
|
+
)
|
|
825
|
+
retention_days: int = Field(
|
|
826
|
+
default=7,
|
|
827
|
+
ge=0,
|
|
828
|
+
description="Number of days to retain branches before cleanup (0 = immediate cleanup)",
|
|
829
|
+
)
|
|
830
|
+
auto_cleanup_on_completion: bool = Field(
|
|
831
|
+
default=True,
|
|
832
|
+
description="Automatically cleanup branches when workflow step completes",
|
|
833
|
+
)
|
|
834
|
+
patterns: dict[str, str] = Field(
|
|
835
|
+
default_factory=lambda: {
|
|
836
|
+
"workflow": "workflow/*",
|
|
837
|
+
"agent": "agent/*",
|
|
838
|
+
},
|
|
839
|
+
description="Branch patterns to match for cleanup (wildcards supported)",
|
|
840
|
+
)
|
|
841
|
+
|
|
842
|
+
|
|
843
|
+
class WorkflowDocsCleanupConfig(BaseModel):
|
|
844
|
+
"""Configuration for workflow documentation cleanup"""
|
|
845
|
+
|
|
846
|
+
enabled: bool = Field(
|
|
847
|
+
default=True,
|
|
848
|
+
description="Enable workflow documentation cleanup",
|
|
849
|
+
)
|
|
850
|
+
keep_latest: int = Field(
|
|
851
|
+
default=5,
|
|
852
|
+
ge=1,
|
|
853
|
+
le=100,
|
|
854
|
+
description="Keep N most recent workflows visible",
|
|
855
|
+
)
|
|
856
|
+
retention_days: int = Field(
|
|
857
|
+
default=30,
|
|
858
|
+
ge=1,
|
|
859
|
+
description="Archive workflows older than N days",
|
|
860
|
+
)
|
|
861
|
+
archive_enabled: bool = Field(
|
|
862
|
+
default=True,
|
|
863
|
+
description="Enable archival of old workflows",
|
|
864
|
+
)
|
|
865
|
+
archive_dir: Path = Field(
|
|
866
|
+
default=Path(".tapps-agents/archives/workflows/"),
|
|
867
|
+
description="Directory for archived workflows (relative to project root)",
|
|
868
|
+
)
|
|
869
|
+
exclude_patterns: list[str] = Field(
|
|
870
|
+
default_factory=list,
|
|
871
|
+
description="Workflow IDs or patterns to never archive",
|
|
872
|
+
)
|
|
873
|
+
|
|
874
|
+
|
|
875
|
+
class SessionsCleanupConfig(BaseModel):
|
|
876
|
+
"""Configuration for .tapps-agents/sessions cleanup (enhancer + SessionManager)."""
|
|
877
|
+
|
|
878
|
+
keep_latest: int = Field(
|
|
879
|
+
default=50,
|
|
880
|
+
ge=1,
|
|
881
|
+
le=500,
|
|
882
|
+
description="Keep N most recent enhancer session files",
|
|
883
|
+
)
|
|
884
|
+
max_age_days: int = Field(
|
|
885
|
+
default=30,
|
|
886
|
+
ge=1,
|
|
887
|
+
description="Remove enhancer sessions older than N days; also used for SessionManager cleanup (hours = max_age_days * 24)",
|
|
888
|
+
)
|
|
889
|
+
auto_cleanup_on_enhance: bool = Field(
|
|
890
|
+
default=False,
|
|
891
|
+
description="When True, run sessions cleanup after each enhancer save so the folder does not grow unbounded",
|
|
892
|
+
)
|
|
893
|
+
|
|
894
|
+
|
|
895
|
+
class CleanupConfig(BaseModel):
|
|
896
|
+
"""Configuration for cleanup operations"""
|
|
897
|
+
|
|
898
|
+
workflow_docs: WorkflowDocsCleanupConfig = Field(
|
|
899
|
+
default_factory=WorkflowDocsCleanupConfig,
|
|
900
|
+
description="Workflow documentation cleanup configuration",
|
|
901
|
+
)
|
|
902
|
+
sessions: SessionsCleanupConfig = Field(
|
|
903
|
+
default_factory=SessionsCleanupConfig,
|
|
904
|
+
description="Sessions cleanup (enhancer + long-running agent sessions)",
|
|
905
|
+
)
|
|
906
|
+
|
|
907
|
+
|
|
908
|
+
class WorkflowArtifactConfig(BaseModel):
|
|
909
|
+
"""Configuration for workflow artifact paths and naming."""
|
|
910
|
+
|
|
911
|
+
base_dir: str = Field(
|
|
912
|
+
default="docs/workflows",
|
|
913
|
+
description="Base directory for workflow artifacts (relative to project root)",
|
|
914
|
+
)
|
|
915
|
+
simple_mode_subdir: str = Field(
|
|
916
|
+
default="simple-mode",
|
|
917
|
+
description="Subdirectory for Simple Mode workflow artifacts",
|
|
918
|
+
)
|
|
919
|
+
auto_detect_existing: bool = Field(
|
|
920
|
+
default=True,
|
|
921
|
+
description="Auto-detect existing artifacts and adjust paths to avoid conflicts",
|
|
922
|
+
)
|
|
923
|
+
naming_pattern: str = Field(
|
|
924
|
+
default="{workflow_id}/{step_name}.md",
|
|
925
|
+
description="Pattern for artifact file naming. Supports: {workflow_id}, {step_name}, {timestamp}, {agent}",
|
|
926
|
+
)
|
|
927
|
+
print_paths_on_completion: bool = Field(
|
|
928
|
+
default=True,
|
|
929
|
+
description="Print artifact file paths after each step completes",
|
|
930
|
+
)
|
|
931
|
+
|
|
932
|
+
def get_artifact_dir(self, project_root: str | None = None) -> str:
|
|
933
|
+
"""Get the full artifact directory path."""
|
|
934
|
+
from pathlib import Path
|
|
935
|
+
base = Path(project_root) if project_root else Path.cwd()
|
|
936
|
+
return str(base / self.base_dir / self.simple_mode_subdir)
|
|
937
|
+
|
|
938
|
+
|
|
939
|
+
class WorkflowFailureConfig(BaseModel):
|
|
940
|
+
"""On-step-failure behavior: retry, skip, escalate, or fail (plan 3.1)."""
|
|
941
|
+
|
|
942
|
+
on_step_fail: str = Field(
|
|
943
|
+
default="fail",
|
|
944
|
+
description="Behavior on step failure: 'fail' | 'retry' | 'skip' | 'escalate'.",
|
|
945
|
+
)
|
|
946
|
+
retry_count: int = Field(
|
|
947
|
+
default=1,
|
|
948
|
+
ge=0,
|
|
949
|
+
le=10,
|
|
950
|
+
description="Max retries when on_step_fail=='retry'.",
|
|
951
|
+
)
|
|
952
|
+
escalate_to_pause: bool = Field(
|
|
953
|
+
default=True,
|
|
954
|
+
description="When on_step_fail is 'escalate' or 'fail', set status to 'paused' (True) or 'failed' (False).",
|
|
955
|
+
)
|
|
956
|
+
|
|
957
|
+
|
|
958
|
+
class WorkflowConfig(BaseModel):
|
|
959
|
+
"""Configuration for workflow execution"""
|
|
960
|
+
|
|
961
|
+
failure: WorkflowFailureConfig = Field(
|
|
962
|
+
default_factory=WorkflowFailureConfig,
|
|
963
|
+
description="On-step-failure behavior: retry, skip, escalate (plan 3.1).",
|
|
964
|
+
)
|
|
965
|
+
polling_interval: float = Field(
|
|
966
|
+
default=5.0,
|
|
967
|
+
ge=1.0,
|
|
968
|
+
description="Seconds between status checks when polling for completion",
|
|
969
|
+
)
|
|
970
|
+
timeout_seconds: float = Field(
|
|
971
|
+
default=3600.0,
|
|
972
|
+
ge=1.0,
|
|
973
|
+
description="Maximum time to wait for step completion (seconds)",
|
|
974
|
+
)
|
|
975
|
+
duration_threshold_seconds: float = Field(
|
|
976
|
+
default=30.0,
|
|
977
|
+
ge=1.0,
|
|
978
|
+
description="Duration threshold for background agent routing (seconds). Tasks estimated to take longer use background agents.",
|
|
979
|
+
)
|
|
980
|
+
state_persistence: StatePersistenceConfig = Field(
|
|
981
|
+
default_factory=StatePersistenceConfig,
|
|
982
|
+
description="State persistence and checkpointing configuration",
|
|
983
|
+
)
|
|
984
|
+
branch_cleanup: BranchCleanupConfig = Field(
|
|
985
|
+
default_factory=BranchCleanupConfig,
|
|
986
|
+
description="Git branch cleanup configuration for workflow worktrees",
|
|
987
|
+
)
|
|
988
|
+
artifacts: WorkflowArtifactConfig = Field(
|
|
989
|
+
default_factory=WorkflowArtifactConfig,
|
|
990
|
+
description="Artifact paths and naming configuration",
|
|
991
|
+
)
|
|
992
|
+
graceful_partial_completion: bool = Field(
|
|
993
|
+
default=True,
|
|
994
|
+
description="Save partial results on failure instead of losing all progress",
|
|
995
|
+
)
|
|
996
|
+
pre_flight_validation: bool = Field(
|
|
997
|
+
default=True,
|
|
998
|
+
description="Run pre-flight validation before workflow execution",
|
|
999
|
+
)
|
|
1000
|
+
|
|
1001
|
+
|
|
1002
|
+
class ContextBudgetConfig(BaseModel):
|
|
1003
|
+
"""Context budget when assembling Context7 and expert chunks (plan 3.2)."""
|
|
1004
|
+
|
|
1005
|
+
max_tokens_per_step: int = Field(
|
|
1006
|
+
default=0,
|
|
1007
|
+
ge=0,
|
|
1008
|
+
description="Max tokens per step (0=no hard limit).",
|
|
1009
|
+
)
|
|
1010
|
+
max_chunks_per_step: int = Field(
|
|
1011
|
+
default=50,
|
|
1012
|
+
ge=1,
|
|
1013
|
+
le=500,
|
|
1014
|
+
description="Max chunks when injecting Context7 or expert docs.",
|
|
1015
|
+
)
|
|
1016
|
+
priority: list[str] = Field(
|
|
1017
|
+
default_factory=lambda: ["current_task", "open_files", "recent_changes", "context7", "experts"],
|
|
1018
|
+
description="Priority order when assembling context (for future use).",
|
|
1019
|
+
)
|
|
1020
|
+
|
|
1021
|
+
|
|
1022
|
+
class BugFixAgentConfig(BaseModel):
|
|
1023
|
+
"""Configuration for Bug Fix Agent."""
|
|
1024
|
+
|
|
1025
|
+
max_iterations: int = Field(
|
|
1026
|
+
default=3,
|
|
1027
|
+
ge=1,
|
|
1028
|
+
le=10,
|
|
1029
|
+
description="Maximum iterations for fix loopback (1-10)",
|
|
1030
|
+
)
|
|
1031
|
+
auto_commit: bool = Field(
|
|
1032
|
+
default=True,
|
|
1033
|
+
description="Automatically commit changes to main branch when quality passes",
|
|
1034
|
+
)
|
|
1035
|
+
quality_thresholds: dict[str, float] = Field(
|
|
1036
|
+
default_factory=lambda: {
|
|
1037
|
+
"overall_min": 7.0,
|
|
1038
|
+
"security_min": 6.5,
|
|
1039
|
+
"maintainability_min": 7.0,
|
|
1040
|
+
},
|
|
1041
|
+
description="Quality thresholds for bug fixes (lower than full SDLC)",
|
|
1042
|
+
)
|
|
1043
|
+
escalation_threshold: int = Field(
|
|
1044
|
+
default=2,
|
|
1045
|
+
ge=1,
|
|
1046
|
+
le=5,
|
|
1047
|
+
description="Escalate to human after N failed iterations (1-5)",
|
|
1048
|
+
)
|
|
1049
|
+
escalation_enabled: bool = Field(
|
|
1050
|
+
default=True,
|
|
1051
|
+
description="Enable human escalation after failed iterations",
|
|
1052
|
+
)
|
|
1053
|
+
pre_commit_security_scan: bool = Field(
|
|
1054
|
+
default=True,
|
|
1055
|
+
description="Run security scan before committing changes",
|
|
1056
|
+
)
|
|
1057
|
+
metrics_enabled: bool = Field(
|
|
1058
|
+
default=True,
|
|
1059
|
+
description="Enable metrics collection for observability",
|
|
1060
|
+
)
|
|
1061
|
+
commit_strategy: str = Field(
|
|
1062
|
+
default="direct_main",
|
|
1063
|
+
description="Commit strategy: 'direct_main' (commit directly) or 'pull_request' (create PR)",
|
|
1064
|
+
)
|
|
1065
|
+
auto_merge_pr: bool = Field(
|
|
1066
|
+
default=False,
|
|
1067
|
+
description="Auto-merge PR if quality gates pass (requires PR workflow)",
|
|
1068
|
+
)
|
|
1069
|
+
require_pr_review: bool = Field(
|
|
1070
|
+
default=False,
|
|
1071
|
+
description="Require human review before merging PR",
|
|
1072
|
+
)
|
|
1073
|
+
|
|
1074
|
+
|
|
1075
|
+
class ContinuousBugFixConfig(BaseModel):
|
|
1076
|
+
"""Configuration for Continuous Bug Fix feature."""
|
|
1077
|
+
|
|
1078
|
+
max_iterations: int = Field(
|
|
1079
|
+
default=10,
|
|
1080
|
+
ge=1,
|
|
1081
|
+
le=100,
|
|
1082
|
+
description="Maximum loop iterations (1-100)",
|
|
1083
|
+
)
|
|
1084
|
+
commit_strategy: str = Field(
|
|
1085
|
+
default="one-per-bug",
|
|
1086
|
+
description="Commit strategy: 'one-per-bug' (default) or 'batch'",
|
|
1087
|
+
)
|
|
1088
|
+
auto_commit: bool = Field(
|
|
1089
|
+
default=True,
|
|
1090
|
+
description="Automatically commit fixes after bug-fix-agent succeeds",
|
|
1091
|
+
)
|
|
1092
|
+
test_path: str = Field(
|
|
1093
|
+
default="tests/",
|
|
1094
|
+
description="Default test directory or file to run",
|
|
1095
|
+
)
|
|
1096
|
+
skip_patterns: list[str] = Field(
|
|
1097
|
+
default_factory=list,
|
|
1098
|
+
description="Patterns for bugs to skip (not yet implemented)",
|
|
1099
|
+
)
|
|
1100
|
+
|
|
1101
|
+
|
|
1102
|
+
class BeadsConfig(BaseModel):
|
|
1103
|
+
"""Configuration for Beads (bd) task-tracking integration."""
|
|
1104
|
+
|
|
1105
|
+
enabled: bool = Field(
|
|
1106
|
+
default=True,
|
|
1107
|
+
description="Enable Beads (bd) integration. When false, all beads features are no-ops.",
|
|
1108
|
+
)
|
|
1109
|
+
required: bool = Field(
|
|
1110
|
+
default=False,
|
|
1111
|
+
description="When true, workflows fail if bd is unavailable or .beads not initialized.",
|
|
1112
|
+
)
|
|
1113
|
+
sync_epic: bool = Field(
|
|
1114
|
+
default=True,
|
|
1115
|
+
description="When beads.enabled is true, sync epic to bd (create issues + deps) before *epic run.",
|
|
1116
|
+
)
|
|
1117
|
+
hooks_simple_mode: bool = Field(
|
|
1118
|
+
default=True,
|
|
1119
|
+
description="When beads.enabled is true, create/close bd issues at start/end of *build and *fix.",
|
|
1120
|
+
)
|
|
1121
|
+
hooks_workflow: bool = Field(
|
|
1122
|
+
default=True,
|
|
1123
|
+
description="When beads.enabled is true, create/close a bd issue at start/end of CLI workflow runs.",
|
|
1124
|
+
)
|
|
1125
|
+
hooks_review: bool = Field(
|
|
1126
|
+
default=False,
|
|
1127
|
+
description="When beads.enabled is true, create/close for *review.",
|
|
1128
|
+
)
|
|
1129
|
+
hooks_test: bool = Field(
|
|
1130
|
+
default=False,
|
|
1131
|
+
description="When beads.enabled is true, create/close for *test.",
|
|
1132
|
+
)
|
|
1133
|
+
hooks_refactor: bool = Field(
|
|
1134
|
+
default=False,
|
|
1135
|
+
description="When beads.enabled is true, create/close for *refactor.",
|
|
1136
|
+
)
|
|
1137
|
+
|
|
1138
|
+
|
|
1139
|
+
class SimpleModeConfig(BaseModel):
|
|
1140
|
+
"""Configuration for Simple Mode."""
|
|
1141
|
+
|
|
1142
|
+
enabled: bool = Field(
|
|
1143
|
+
default=True, description="Enable Simple Mode (intent-based agent orchestration)"
|
|
1144
|
+
)
|
|
1145
|
+
auto_detect: bool = Field(
|
|
1146
|
+
default=True,
|
|
1147
|
+
description="Auto-enable Simple Mode for first-time users",
|
|
1148
|
+
)
|
|
1149
|
+
show_advanced: bool = Field(
|
|
1150
|
+
default=False, description="Show advanced agent-specific options"
|
|
1151
|
+
)
|
|
1152
|
+
natural_language: bool = Field(
|
|
1153
|
+
default=True, description="Enable natural language command parsing"
|
|
1154
|
+
)
|
|
1155
|
+
fast_mode_default: bool = Field(
|
|
1156
|
+
default=False,
|
|
1157
|
+
description="Default to fast mode for Simple Mode workflows (skip documentation steps)",
|
|
1158
|
+
)
|
|
1159
|
+
state_persistence_enabled: bool = Field(
|
|
1160
|
+
default=True,
|
|
1161
|
+
description="Enable workflow state persistence for resume capability",
|
|
1162
|
+
)
|
|
1163
|
+
checkpoint_retention_days: int = Field(
|
|
1164
|
+
default=30,
|
|
1165
|
+
ge=1,
|
|
1166
|
+
description="Days to retain workflow checkpoints",
|
|
1167
|
+
)
|
|
1168
|
+
documentation_organized: bool = Field(
|
|
1169
|
+
default=True,
|
|
1170
|
+
description="Organize documentation by workflow ID",
|
|
1171
|
+
)
|
|
1172
|
+
create_latest_symlink: bool = Field(
|
|
1173
|
+
default=False,
|
|
1174
|
+
description="Create 'latest' symlink to most recent workflow",
|
|
1175
|
+
)
|
|
1176
|
+
context7_refresh_after_planning: bool = Field(
|
|
1177
|
+
default=True,
|
|
1178
|
+
description="After build planning (Step 2), refresh Context7 cache for libraries from the plan. Set false to disable.",
|
|
1179
|
+
)
|
|
1180
|
+
context7_refresh_max_libraries: int = Field(
|
|
1181
|
+
default=10,
|
|
1182
|
+
ge=1,
|
|
1183
|
+
le=50,
|
|
1184
|
+
description="Max number of libraries to warm in post-planning Context7 refresh (limits API use).",
|
|
1185
|
+
)
|
|
1186
|
+
enable_checkpoints: bool = Field(
|
|
1187
|
+
default=True,
|
|
1188
|
+
description="Enable mid-execution workflow checkpoints (Checkpoint 1: After Enhance, Checkpoint 2: After Planning, Checkpoint 3: Quality Gate)",
|
|
1189
|
+
)
|
|
1190
|
+
checkpoint_confidence_threshold: float = Field(
|
|
1191
|
+
default=0.70,
|
|
1192
|
+
ge=0.0,
|
|
1193
|
+
le=1.0,
|
|
1194
|
+
description="Minimum confidence threshold for checkpoint recommendations (0.0-1.0)",
|
|
1195
|
+
)
|
|
1196
|
+
|
|
1197
|
+
|
|
1198
|
+
class AutoEnhancementConfig(BaseModel):
|
|
1199
|
+
"""Configuration for automatic prompt enhancement"""
|
|
1200
|
+
|
|
1201
|
+
enabled: bool = Field(
|
|
1202
|
+
default=True, description="Enable auto-enhancement globally"
|
|
1203
|
+
)
|
|
1204
|
+
mode: str = Field(
|
|
1205
|
+
default="cursor-skills",
|
|
1206
|
+
description="Enhancement mode: cursor-skills, structured, or smart",
|
|
1207
|
+
)
|
|
1208
|
+
min_prompt_length: int = Field(
|
|
1209
|
+
default=20, description="Minimum prompt length to trigger enhancement"
|
|
1210
|
+
)
|
|
1211
|
+
quality_threshold: float = Field(
|
|
1212
|
+
default=50.0,
|
|
1213
|
+
ge=0.0,
|
|
1214
|
+
le=100.0,
|
|
1215
|
+
description="Quality score below which to enhance",
|
|
1216
|
+
)
|
|
1217
|
+
|
|
1218
|
+
commands: dict[str, dict[str, Any]] = Field(
|
|
1219
|
+
default_factory=lambda: {
|
|
1220
|
+
"implementer": {"enabled": True, "synthesis_mode": "full"},
|
|
1221
|
+
"planner": {"enabled": True, "synthesis_mode": "quick"},
|
|
1222
|
+
"analyst": {"enabled": True, "synthesis_mode": "quick"},
|
|
1223
|
+
"architect": {"enabled": False}, # Off by default to avoid over-use
|
|
1224
|
+
"designer": {"enabled": False}, # Off by default to avoid over-use
|
|
1225
|
+
},
|
|
1226
|
+
description="Per-command enhancement settings",
|
|
1227
|
+
)
|
|
1228
|
+
|
|
1229
|
+
|
|
1230
|
+
class EvaluationConfig(BaseModel):
|
|
1231
|
+
"""Configuration for Evaluation & Quality Assurance Engine (Tier 1)"""
|
|
1232
|
+
|
|
1233
|
+
enabled: bool = Field(
|
|
1234
|
+
default=True, description="Enable comprehensive evaluation engine"
|
|
1235
|
+
)
|
|
1236
|
+
include_behavioral_validation: bool = Field(
|
|
1237
|
+
default=True, description="Include behavioral correctness validation"
|
|
1238
|
+
)
|
|
1239
|
+
include_spec_compliance: bool = Field(
|
|
1240
|
+
default=True, description="Include specification compliance checking"
|
|
1241
|
+
)
|
|
1242
|
+
include_architectural_checks: bool = Field(
|
|
1243
|
+
default=True, description="Include architectural pattern adherence checking"
|
|
1244
|
+
)
|
|
1245
|
+
issue_severity_thresholds: dict[str, int] = Field(
|
|
1246
|
+
default_factory=lambda: {
|
|
1247
|
+
"critical": 0, # Hard fail
|
|
1248
|
+
"high": 5, # Soft fail/loopback
|
|
1249
|
+
"medium": 10,
|
|
1250
|
+
"low": 20,
|
|
1251
|
+
},
|
|
1252
|
+
description="Maximum allowed issues by severity for gate passing",
|
|
1253
|
+
)
|
|
1254
|
+
enable_remediation_loop: bool = Field(
|
|
1255
|
+
default=True, description="Enable automatic remediation loops"
|
|
1256
|
+
)
|
|
1257
|
+
max_remediation_retries: int = Field(
|
|
1258
|
+
default=3, ge=1, le=10, description="Maximum remediation retry attempts"
|
|
1259
|
+
)
|
|
1260
|
+
|
|
1261
|
+
|
|
1262
|
+
class PromptLearningConfig(BaseModel):
|
|
1263
|
+
"""Configuration for Continual System Prompt Learning (Tier 1)"""
|
|
1264
|
+
|
|
1265
|
+
enabled: bool = Field(
|
|
1266
|
+
default=True, description="Enable prompt learning system"
|
|
1267
|
+
)
|
|
1268
|
+
feedback_collection_enabled: bool = Field(
|
|
1269
|
+
default=True, description="Enable feedback collection from Cursor IDE"
|
|
1270
|
+
)
|
|
1271
|
+
ab_testing_enabled: bool = Field(
|
|
1272
|
+
default=True, description="Enable A/B testing for prompt variations"
|
|
1273
|
+
)
|
|
1274
|
+
auto_optimize_enabled: bool = Field(
|
|
1275
|
+
default=True, description="Enable automatic prompt optimization"
|
|
1276
|
+
)
|
|
1277
|
+
min_samples_for_optimization: int = Field(
|
|
1278
|
+
default=10, ge=5, description="Minimum feedback samples before optimization"
|
|
1279
|
+
)
|
|
1280
|
+
optimization_interval_hours: int = Field(
|
|
1281
|
+
default=24, ge=1, description="Hours between optimization runs"
|
|
1282
|
+
)
|
|
1283
|
+
prompt_version_retention_days: int = Field(
|
|
1284
|
+
default=90, ge=7, description="Days to retain prompt version history"
|
|
1285
|
+
)
|
|
1286
|
+
auto_update_skills: bool = Field(
|
|
1287
|
+
default=False, description="Automatically update Skills with learned prompts"
|
|
1288
|
+
)
|
|
1289
|
+
require_approval_for_updates: bool = Field(
|
|
1290
|
+
default=True, description="Require approval before updating prompts"
|
|
1291
|
+
)
|
|
1292
|
+
|
|
1293
|
+
|
|
1294
|
+
class KnowledgeEngineConfig(BaseModel):
|
|
1295
|
+
"""Configuration for Knowledge Ecosystem Enhancement (Tier 1)"""
|
|
1296
|
+
|
|
1297
|
+
enabled: bool = Field(
|
|
1298
|
+
default=True, description="Enable always-on knowledge orchestration engine"
|
|
1299
|
+
)
|
|
1300
|
+
auto_detect_domains: bool = Field(
|
|
1301
|
+
default=True, description="Automatically detect project domains"
|
|
1302
|
+
)
|
|
1303
|
+
auto_create_experts: bool = Field(
|
|
1304
|
+
default=True, description="Automatically create project experts"
|
|
1305
|
+
)
|
|
1306
|
+
knowledge_ingestion_enabled: bool = Field(
|
|
1307
|
+
default=True, description="Enable automatic knowledge ingestion"
|
|
1308
|
+
)
|
|
1309
|
+
proactive_consultation: bool = Field(
|
|
1310
|
+
default=True, description="Proactively consult experts before needed"
|
|
1311
|
+
)
|
|
1312
|
+
metrics_tracking_enabled: bool = Field(
|
|
1313
|
+
default=True, description="Enable metrics tracking for knowledge quality"
|
|
1314
|
+
)
|
|
1315
|
+
kb_maintenance_schedule: str = Field(
|
|
1316
|
+
default="weekly", description="KB maintenance schedule: daily, weekly, monthly"
|
|
1317
|
+
)
|
|
1318
|
+
governance_enabled: bool = Field(
|
|
1319
|
+
default=True, description="Enable governance and safety layer"
|
|
1320
|
+
)
|
|
1321
|
+
require_approval_for_writes: bool = Field(
|
|
1322
|
+
default=False, description="Require approval before writing to knowledge base"
|
|
1323
|
+
)
|
|
1324
|
+
|
|
1325
|
+
|
|
1326
|
+
class ContextIntelligenceConfig(BaseModel):
|
|
1327
|
+
"""Configuration for Context Intelligence Engine (Tier 1)"""
|
|
1328
|
+
|
|
1329
|
+
enabled: bool = Field(
|
|
1330
|
+
default=True, description="Enable context intelligence engine"
|
|
1331
|
+
)
|
|
1332
|
+
dynamic_gathering_enabled: bool = Field(
|
|
1333
|
+
default=True, description="Enable dynamic context gathering"
|
|
1334
|
+
)
|
|
1335
|
+
repository_exploration_enabled: bool = Field(
|
|
1336
|
+
default=True, description="Enable autonomous repository exploration"
|
|
1337
|
+
)
|
|
1338
|
+
pattern_recognition_enabled: bool = Field(
|
|
1339
|
+
default=True, description="Enable pattern recognition and cataloging"
|
|
1340
|
+
)
|
|
1341
|
+
similarity_detection_enabled: bool = Field(
|
|
1342
|
+
default=True, description="Enable similarity detection for code reuse"
|
|
1343
|
+
)
|
|
1344
|
+
historical_analysis_enabled: bool = Field(
|
|
1345
|
+
default=True, description="Enable historical context analysis"
|
|
1346
|
+
)
|
|
1347
|
+
relevance_ranking_enabled: bool = Field(
|
|
1348
|
+
default=True, description="Enable relevance-based context ranking"
|
|
1349
|
+
)
|
|
1350
|
+
token_budget_management_enabled: bool = Field(
|
|
1351
|
+
default=True, description="Enable token budget management"
|
|
1352
|
+
)
|
|
1353
|
+
default_token_budget: int = Field(
|
|
1354
|
+
default=4000, ge=1000, le=16000, description="Default token budget for context"
|
|
1355
|
+
)
|
|
1356
|
+
progressive_loading_enabled: bool = Field(
|
|
1357
|
+
default=True, description="Enable progressive context loading"
|
|
1358
|
+
)
|
|
1359
|
+
|
|
1360
|
+
|
|
1361
|
+
class AnalyticsConfig(BaseModel):
|
|
1362
|
+
"""Configuration for analytics and dual-write from execution metrics."""
|
|
1363
|
+
|
|
1364
|
+
record_from_execution: bool = Field(
|
|
1365
|
+
default=True,
|
|
1366
|
+
description="When True, also write to .tapps-agents/analytics/ when recording execution metrics (step and workflow). Set False for metrics-only (no analytics).",
|
|
1367
|
+
)
|
|
1368
|
+
|
|
1369
|
+
|
|
1370
|
+
class GuardrailConfig(BaseModel):
|
|
1371
|
+
"""Security guardrails for subprocess and file writes (plan 2.2)."""
|
|
1372
|
+
|
|
1373
|
+
sandbox_subprocess: bool = Field(
|
|
1374
|
+
default=True,
|
|
1375
|
+
description="When True, never use shell for subprocess; use cwd=project_root.",
|
|
1376
|
+
)
|
|
1377
|
+
allowed_paths_write: list[str] = Field(
|
|
1378
|
+
default_factory=list,
|
|
1379
|
+
description="When non-empty, writes must be under project_root and under one of these prefixes (e.g. src, tests, docs, .tapps-agents). When empty, only under project_root.",
|
|
1380
|
+
)
|
|
1381
|
+
|
|
1382
|
+
|
|
1383
|
+
class HumanOversightConfig(BaseModel):
|
|
1384
|
+
"""Human-in-the-loop oversight for *build and *full (plan 2.3)."""
|
|
1385
|
+
|
|
1386
|
+
checkpoints_before_steps: list[str] = Field(
|
|
1387
|
+
default_factory=list,
|
|
1388
|
+
description="Step/agent names before which to prompt: e.g. implementer, designer. If --auto, skipped.",
|
|
1389
|
+
)
|
|
1390
|
+
require_diff_review_implementer: bool = Field(
|
|
1391
|
+
default=False,
|
|
1392
|
+
description="Reserved: when implementer supports preview/diff, require review before apply. Not implemented.",
|
|
1393
|
+
)
|
|
1394
|
+
branch_for_agent_changes: bool = Field(
|
|
1395
|
+
default=True,
|
|
1396
|
+
description="For *build and *full: create branch tapps-agents/build-{workflow_id}; merge to main only after human review.",
|
|
1397
|
+
)
|
|
1398
|
+
|
|
1399
|
+
|
|
1400
|
+
class ProjectConfig(BaseModel):
|
|
1401
|
+
"""Root configuration model for TappsCodingAgents project"""
|
|
1402
|
+
|
|
1403
|
+
# Project metadata
|
|
1404
|
+
project_name: str | None = Field(default=None, description="Project name")
|
|
1405
|
+
version: str | None = Field(default=None, description="Project version")
|
|
1406
|
+
|
|
1407
|
+
# CLI / runtime
|
|
1408
|
+
offline_mode: bool = Field(
|
|
1409
|
+
default=False,
|
|
1410
|
+
description="Use offline mode (no network) when possible for CLI and agents",
|
|
1411
|
+
)
|
|
1412
|
+
|
|
1413
|
+
# Core configuration
|
|
1414
|
+
tooling: ToolingConfig = Field(
|
|
1415
|
+
default_factory=ToolingConfig,
|
|
1416
|
+
description="Canonical runtime/tool targets and policy (used by doctor/CI/agents)",
|
|
1417
|
+
)
|
|
1418
|
+
agents: AgentsConfig = Field(default_factory=AgentsConfig)
|
|
1419
|
+
scoring: ScoringConfig = Field(default_factory=ScoringConfig)
|
|
1420
|
+
expert: ExpertConfig = Field(
|
|
1421
|
+
default_factory=ExpertConfig,
|
|
1422
|
+
description="Expert consultation system configuration",
|
|
1423
|
+
)
|
|
1424
|
+
context7: Context7Config | None = Field(
|
|
1425
|
+
default_factory=Context7Config, description="Context7 integration configuration"
|
|
1426
|
+
)
|
|
1427
|
+
context_budget: ContextBudgetConfig = Field(
|
|
1428
|
+
default_factory=ContextBudgetConfig,
|
|
1429
|
+
description="Context budget: max_chunks for Context7/expert injection; surface cached_at (plan 3.2).",
|
|
1430
|
+
)
|
|
1431
|
+
quality_tools: QualityToolsConfig | None = Field(
|
|
1432
|
+
default_factory=QualityToolsConfig,
|
|
1433
|
+
description="Quality analysis tools configuration (Phase 6)",
|
|
1434
|
+
)
|
|
1435
|
+
workflow: WorkflowConfig = Field(
|
|
1436
|
+
default_factory=WorkflowConfig,
|
|
1437
|
+
description="Workflow execution configuration",
|
|
1438
|
+
)
|
|
1439
|
+
analytics: AnalyticsConfig = Field(
|
|
1440
|
+
default_factory=AnalyticsConfig,
|
|
1441
|
+
description="Analytics and dual-write from execution metrics (health usage, outcomes).",
|
|
1442
|
+
)
|
|
1443
|
+
guardrails: GuardrailConfig = Field(
|
|
1444
|
+
default_factory=GuardrailConfig,
|
|
1445
|
+
description="Security guardrails: subprocess sandbox, path allowlist for writes (plan 2.2).",
|
|
1446
|
+
)
|
|
1447
|
+
human_oversight: HumanOversightConfig = Field(
|
|
1448
|
+
default_factory=HumanOversightConfig,
|
|
1449
|
+
description="Human oversight: step checkpoints, branch-for-agent-changes (plan 2.3). require_diff_review_implementer reserved.",
|
|
1450
|
+
)
|
|
1451
|
+
simple_mode: SimpleModeConfig = Field(
|
|
1452
|
+
default_factory=SimpleModeConfig,
|
|
1453
|
+
description="Simple Mode configuration (intent-based orchestration)",
|
|
1454
|
+
)
|
|
1455
|
+
beads: BeadsConfig = Field(
|
|
1456
|
+
default_factory=BeadsConfig,
|
|
1457
|
+
description="Beads (bd) task-tracking integration. See docs/BEADS_INTEGRATION.md.",
|
|
1458
|
+
)
|
|
1459
|
+
bug_fix_agent: BugFixAgentConfig = Field(
|
|
1460
|
+
default_factory=BugFixAgentConfig,
|
|
1461
|
+
description="Bug Fix Agent configuration (automated bug fixing with auto-commit)",
|
|
1462
|
+
)
|
|
1463
|
+
continuous_bug_fix: ContinuousBugFixConfig = Field(
|
|
1464
|
+
default_factory=ContinuousBugFixConfig,
|
|
1465
|
+
description="Continuous Bug Fix configuration (automated bug finding and fixing loop)",
|
|
1466
|
+
)
|
|
1467
|
+
auto_enhancement: AutoEnhancementConfig = Field(
|
|
1468
|
+
default_factory=AutoEnhancementConfig,
|
|
1469
|
+
description="Automatic prompt enhancement configuration",
|
|
1470
|
+
)
|
|
1471
|
+
|
|
1472
|
+
# Tier 1 Enhancement Configurations
|
|
1473
|
+
evaluation: EvaluationConfig = Field(
|
|
1474
|
+
default_factory=EvaluationConfig,
|
|
1475
|
+
description="Evaluation & Quality Assurance Engine configuration (Tier 1)",
|
|
1476
|
+
)
|
|
1477
|
+
prompt_learning: PromptLearningConfig = Field(
|
|
1478
|
+
default_factory=PromptLearningConfig,
|
|
1479
|
+
description="Continual System Prompt Learning configuration (Tier 1)",
|
|
1480
|
+
)
|
|
1481
|
+
knowledge_engine: KnowledgeEngineConfig = Field(
|
|
1482
|
+
default_factory=KnowledgeEngineConfig,
|
|
1483
|
+
description="Knowledge Ecosystem Enhancement configuration (Tier 1)",
|
|
1484
|
+
)
|
|
1485
|
+
context_intelligence: ContextIntelligenceConfig = Field(
|
|
1486
|
+
default_factory=ContextIntelligenceConfig,
|
|
1487
|
+
description="Context Intelligence Engine configuration (Tier 1)",
|
|
1488
|
+
)
|
|
1489
|
+
cleanup: CleanupConfig = Field(
|
|
1490
|
+
default_factory=CleanupConfig,
|
|
1491
|
+
description="Cleanup operations configuration",
|
|
1492
|
+
)
|
|
1493
|
+
|
|
1494
|
+
model_config = {
|
|
1495
|
+
"extra": "ignore", # Ignore unknown fields
|
|
1496
|
+
"validate_assignment": True,
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
|
|
1500
|
+
def load_config(config_path: Path | None = None) -> ProjectConfig:
|
|
1501
|
+
"""
|
|
1502
|
+
Load configuration from YAML file.
|
|
1503
|
+
|
|
1504
|
+
Args:
|
|
1505
|
+
config_path: Path to config.yaml file. If None, looks for `.tapps-agents/config.yaml`
|
|
1506
|
+
in current directory or parent directories.
|
|
1507
|
+
|
|
1508
|
+
Returns:
|
|
1509
|
+
ProjectConfig instance with loaded values
|
|
1510
|
+
|
|
1511
|
+
Raises:
|
|
1512
|
+
FileNotFoundError: If config file doesn't exist and no defaults available
|
|
1513
|
+
ValueError: If config file is invalid
|
|
1514
|
+
"""
|
|
1515
|
+
if config_path is None:
|
|
1516
|
+
# Look for .tapps-agents/config.yaml in current and parent directories
|
|
1517
|
+
current = Path.cwd()
|
|
1518
|
+
for parent in [current] + list(current.parents):
|
|
1519
|
+
candidate = parent / ".tapps-agents" / "config.yaml"
|
|
1520
|
+
if candidate.exists():
|
|
1521
|
+
config_path = candidate
|
|
1522
|
+
break
|
|
1523
|
+
|
|
1524
|
+
if config_path is None:
|
|
1525
|
+
# Return defaults if no config file found
|
|
1526
|
+
return ProjectConfig()
|
|
1527
|
+
|
|
1528
|
+
if not config_path.exists():
|
|
1529
|
+
# Return defaults if file doesn't exist
|
|
1530
|
+
return ProjectConfig()
|
|
1531
|
+
|
|
1532
|
+
try:
|
|
1533
|
+
# Use utf-8-sig to automatically handle UTF-8 BOM (common on Windows)
|
|
1534
|
+
# This prevents YAML parsing failures when files have BOM prefix (\xef\xbb\xbf)
|
|
1535
|
+
with open(config_path, encoding="utf-8-sig") as f:
|
|
1536
|
+
data = yaml.safe_load(f)
|
|
1537
|
+
|
|
1538
|
+
if data is None:
|
|
1539
|
+
# Empty file, return defaults
|
|
1540
|
+
return ProjectConfig()
|
|
1541
|
+
|
|
1542
|
+
# Validate and load config
|
|
1543
|
+
return ProjectConfig(**data)
|
|
1544
|
+
except yaml.YAMLError as e:
|
|
1545
|
+
raise ValueError(f"Invalid YAML in config file {config_path}: {e}") from e
|
|
1546
|
+
except Exception as e:
|
|
1547
|
+
raise ValueError(f"Error loading config from {config_path}: {e}") from e
|
|
1548
|
+
|
|
1549
|
+
|
|
1550
|
+
def save_config(config_path: Path, config: ProjectConfig) -> None:
|
|
1551
|
+
"""
|
|
1552
|
+
Save configuration to a YAML file.
|
|
1553
|
+
|
|
1554
|
+
Args:
|
|
1555
|
+
config_path: Path to the config file
|
|
1556
|
+
config: ProjectConfig instance to save
|
|
1557
|
+
|
|
1558
|
+
Raises:
|
|
1559
|
+
OSError: If the file cannot be written
|
|
1560
|
+
"""
|
|
1561
|
+
config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
1562
|
+
|
|
1563
|
+
# Load existing config to preserve other settings
|
|
1564
|
+
existing_data: dict[str, Any] = {}
|
|
1565
|
+
if config_path.exists():
|
|
1566
|
+
try:
|
|
1567
|
+
# Use utf-8-sig to handle UTF-8 BOM (common on Windows)
|
|
1568
|
+
with open(config_path, encoding="utf-8-sig") as f:
|
|
1569
|
+
existing_data = yaml.safe_load(f) or {}
|
|
1570
|
+
except Exception:
|
|
1571
|
+
# If we can't read existing config, start fresh
|
|
1572
|
+
existing_data = {}
|
|
1573
|
+
|
|
1574
|
+
# Merge with new config (convert to dict, preserving existing values)
|
|
1575
|
+
new_data = config.model_dump(exclude_none=True, mode="json")
|
|
1576
|
+
|
|
1577
|
+
def deep_merge(existing: dict[str, Any], new: dict[str, Any]) -> dict[str, Any]:
|
|
1578
|
+
"""Recursively merge new dict into existing dict."""
|
|
1579
|
+
result = existing.copy()
|
|
1580
|
+
for key, value in new.items():
|
|
1581
|
+
if key in result and isinstance(result[key], dict) and isinstance(value, dict):
|
|
1582
|
+
# Recursively merge nested dictionaries
|
|
1583
|
+
result[key] = deep_merge(result[key], value)
|
|
1584
|
+
else:
|
|
1585
|
+
# Overwrite with new value
|
|
1586
|
+
result[key] = value
|
|
1587
|
+
return result
|
|
1588
|
+
|
|
1589
|
+
# Deep merge: preserve existing nested values
|
|
1590
|
+
existing_data = deep_merge(existing_data, new_data)
|
|
1591
|
+
|
|
1592
|
+
# Save
|
|
1593
|
+
with open(config_path, "w", encoding="utf-8") as f:
|
|
1594
|
+
yaml.dump(existing_data, f, default_flow_style=False, sort_keys=False, allow_unicode=True)
|
|
1595
|
+
|
|
1596
|
+
|
|
1597
|
+
def get_default_config() -> dict[str, Any]:
|
|
1598
|
+
"""
|
|
1599
|
+
Get default configuration as a dictionary (for template generation).
|
|
1600
|
+
|
|
1601
|
+
Returns:
|
|
1602
|
+
Dictionary representation of default config with Path objects as strings
|
|
1603
|
+
"""
|
|
1604
|
+
config = ProjectConfig()
|
|
1605
|
+
# Use model_dump with mode="json" to serialize Path objects as strings
|
|
1606
|
+
# This is required for YAML serialization (yaml.safe_dump can't handle Path objects)
|
|
1607
|
+
return config.model_dump(exclude_none=True, mode="json")
|
|
1608
|
+
|
|
1609
|
+
|
|
1610
|
+
def get_expert_config(config: ProjectConfig | None = None) -> ExpertConfig:
|
|
1611
|
+
"""
|
|
1612
|
+
Get expert configuration, loading from file if needed.
|
|
1613
|
+
|
|
1614
|
+
Args:
|
|
1615
|
+
config: Optional ProjectConfig instance. If None, loads from file.
|
|
1616
|
+
|
|
1617
|
+
Returns:
|
|
1618
|
+
ExpertConfig instance
|
|
1619
|
+
"""
|
|
1620
|
+
if config is None:
|
|
1621
|
+
config = load_config()
|
|
1622
|
+
return config.expert
|