codeframe-ai 0.9.0__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.
- codeframe/__init__.py +11 -0
- codeframe/__main__.py +20 -0
- codeframe/adapters/__init__.py +5 -0
- codeframe/adapters/e2b/__init__.py +13 -0
- codeframe/adapters/e2b/adapter.py +342 -0
- codeframe/adapters/e2b/budget.py +71 -0
- codeframe/adapters/e2b/credential_scanner.py +134 -0
- codeframe/adapters/llm/__init__.py +92 -0
- codeframe/adapters/llm/anthropic.py +414 -0
- codeframe/adapters/llm/base.py +444 -0
- codeframe/adapters/llm/mock.py +281 -0
- codeframe/adapters/llm/openai.py +483 -0
- codeframe/agents/__init__.py +8 -0
- codeframe/agents/dependency_resolver.py +714 -0
- codeframe/auth/__init__.py +16 -0
- codeframe/auth/api_key_router.py +238 -0
- codeframe/auth/api_keys.py +156 -0
- codeframe/auth/dependencies.py +358 -0
- codeframe/auth/manager.py +178 -0
- codeframe/auth/models.py +30 -0
- codeframe/auth/router.py +93 -0
- codeframe/auth/schemas.py +15 -0
- codeframe/auth/scopes.py +53 -0
- codeframe/cli/__init__.py +12 -0
- codeframe/cli/__main__.py +20 -0
- codeframe/cli/api_client.py +275 -0
- codeframe/cli/app.py +5688 -0
- codeframe/cli/auth.py +122 -0
- codeframe/cli/auth_commands.py +958 -0
- codeframe/cli/commands/__init__.py +5 -0
- codeframe/cli/config_commands.py +79 -0
- codeframe/cli/dashboard_commands.py +67 -0
- codeframe/cli/engines_commands.py +205 -0
- codeframe/cli/env_commands.py +409 -0
- codeframe/cli/helpers.py +56 -0
- codeframe/cli/hooks_commands.py +208 -0
- codeframe/cli/import_commands.py +129 -0
- codeframe/cli/pr_commands.py +549 -0
- codeframe/cli/proof_commands.py +415 -0
- codeframe/cli/stats_commands.py +311 -0
- codeframe/cli/telemetry_runtime.py +153 -0
- codeframe/cli/validators.py +123 -0
- codeframe/config/rate_limits.py +165 -0
- codeframe/core/__init__.py +15 -0
- codeframe/core/adapters/__init__.py +43 -0
- codeframe/core/adapters/agent_adapter.py +114 -0
- codeframe/core/adapters/builtin.py +326 -0
- codeframe/core/adapters/claude_code.py +62 -0
- codeframe/core/adapters/codex.py +393 -0
- codeframe/core/adapters/git_utils.py +40 -0
- codeframe/core/adapters/kilocode.py +126 -0
- codeframe/core/adapters/opencode.py +48 -0
- codeframe/core/adapters/streaming_chat.py +483 -0
- codeframe/core/adapters/subprocess_adapter.py +213 -0
- codeframe/core/adapters/verification_wrapper.py +269 -0
- codeframe/core/agent.py +2183 -0
- codeframe/core/agents_config.py +569 -0
- codeframe/core/api_key_service.py +211 -0
- codeframe/core/artifacts.py +428 -0
- codeframe/core/blocker_detection.py +218 -0
- codeframe/core/blockers.py +433 -0
- codeframe/core/checkpoints.py +481 -0
- codeframe/core/conductor.py +2255 -0
- codeframe/core/config.py +827 -0
- codeframe/core/config_watcher.py +268 -0
- codeframe/core/context.py +542 -0
- codeframe/core/context_packager.py +234 -0
- codeframe/core/credentials.py +735 -0
- codeframe/core/dependency_analyzer.py +229 -0
- codeframe/core/dependency_graph.py +290 -0
- codeframe/core/diagnostic_agent.py +712 -0
- codeframe/core/diagnostics.py +616 -0
- codeframe/core/editor.py +556 -0
- codeframe/core/engine_registry.py +256 -0
- codeframe/core/engine_stats.py +231 -0
- codeframe/core/environment.py +697 -0
- codeframe/core/events.py +375 -0
- codeframe/core/executor.py +1005 -0
- codeframe/core/fix_tracker.py +480 -0
- codeframe/core/gates.py +1322 -0
- codeframe/core/git.py +477 -0
- codeframe/core/github_connect_service.py +178 -0
- codeframe/core/github_integration_config.py +118 -0
- codeframe/core/github_issues_service.py +449 -0
- codeframe/core/hooks.py +184 -0
- codeframe/core/importers/__init__.py +1 -0
- codeframe/core/importers/ralph.py +540 -0
- codeframe/core/installer.py +650 -0
- codeframe/core/models.py +1026 -0
- codeframe/core/notifications_config.py +183 -0
- codeframe/core/planner.py +437 -0
- codeframe/core/prd.py +670 -0
- codeframe/core/prd_discovery.py +1118 -0
- codeframe/core/prd_stress_test.py +499 -0
- codeframe/core/progress.py +126 -0
- codeframe/core/proof/__init__.py +34 -0
- codeframe/core/proof/capture.py +79 -0
- codeframe/core/proof/evidence.py +56 -0
- codeframe/core/proof/ledger.py +574 -0
- codeframe/core/proof/models.py +162 -0
- codeframe/core/proof/obligations.py +103 -0
- codeframe/core/proof/runner.py +233 -0
- codeframe/core/proof/scope.py +81 -0
- codeframe/core/proof/stubs.py +156 -0
- codeframe/core/quick_fixes.py +558 -0
- codeframe/core/react_agent.py +1650 -0
- codeframe/core/reconciliation.py +183 -0
- codeframe/core/replay.py +788 -0
- codeframe/core/review.py +285 -0
- codeframe/core/runtime.py +1134 -0
- codeframe/core/sandbox/__init__.py +27 -0
- codeframe/core/sandbox/context.py +98 -0
- codeframe/core/sandbox/worktree.py +20 -0
- codeframe/core/schedule.py +396 -0
- codeframe/core/stall_detector.py +71 -0
- codeframe/core/stall_monitor.py +134 -0
- codeframe/core/state_machine.py +121 -0
- codeframe/core/streaming.py +502 -0
- codeframe/core/task_tree.py +400 -0
- codeframe/core/tasks.py +1022 -0
- codeframe/core/telemetry.py +232 -0
- codeframe/core/templates.py +221 -0
- codeframe/core/tools.py +942 -0
- codeframe/core/workspace.py +887 -0
- codeframe/core/worktrees.py +276 -0
- codeframe/git/__init__.py +5 -0
- codeframe/git/github_integration.py +505 -0
- codeframe/lib/__init__.py +0 -0
- codeframe/lib/audit_logger.py +248 -0
- codeframe/lib/metrics_tracker.py +800 -0
- codeframe/lib/quality/__init__.py +7 -0
- codeframe/lib/quality/complexity_analyzer.py +316 -0
- codeframe/lib/quality/owasp_patterns.py +284 -0
- codeframe/lib/quality/security_scanner.py +250 -0
- codeframe/lib/rate_limiter.py +312 -0
- codeframe/notifications/__init__.py +0 -0
- codeframe/notifications/webhook.py +380 -0
- codeframe/planning/__init__.py +30 -0
- codeframe/planning/issue_generator.py +219 -0
- codeframe/planning/prd_template_functions.py +137 -0
- codeframe/planning/prd_templates.py +975 -0
- codeframe/planning/task_scheduler.py +511 -0
- codeframe/planning/task_templates.py +533 -0
- codeframe/platform_store/__init__.py +5 -0
- codeframe/platform_store/database.py +277 -0
- codeframe/platform_store/repositories/__init__.py +24 -0
- codeframe/platform_store/repositories/api_key_repository.py +245 -0
- codeframe/platform_store/repositories/audit_repository.py +67 -0
- codeframe/platform_store/repositories/base.py +295 -0
- codeframe/platform_store/repositories/interactive_sessions.py +165 -0
- codeframe/platform_store/repositories/token_repository.py +598 -0
- codeframe/platform_store/repositories/workspace_registry_repository.py +175 -0
- codeframe/platform_store/schema_manager.py +321 -0
- codeframe/templates/AGENTS.md.default +94 -0
- codeframe/tui/__init__.py +5 -0
- codeframe/tui/app.py +256 -0
- codeframe/tui/data_service.py +103 -0
- codeframe/ui/__init__.py +0 -0
- codeframe/ui/dependencies.py +103 -0
- codeframe/ui/models.py +999 -0
- codeframe/ui/response_models.py +201 -0
- codeframe/ui/routers/__init__.py +5 -0
- codeframe/ui/routers/_helpers.py +29 -0
- codeframe/ui/routers/batches_v2.py +315 -0
- codeframe/ui/routers/blockers_v2.py +320 -0
- codeframe/ui/routers/checkpoints_v2.py +310 -0
- codeframe/ui/routers/costs_v2.py +322 -0
- codeframe/ui/routers/diagnose_v2.py +225 -0
- codeframe/ui/routers/discovery_v2.py +417 -0
- codeframe/ui/routers/environment_v2.py +284 -0
- codeframe/ui/routers/events_v2.py +75 -0
- codeframe/ui/routers/gates_v2.py +166 -0
- codeframe/ui/routers/git_v2.py +284 -0
- codeframe/ui/routers/github_integrations_v2.py +532 -0
- codeframe/ui/routers/interactive_sessions_v2.py +238 -0
- codeframe/ui/routers/pr_v2.py +709 -0
- codeframe/ui/routers/prd_v2.py +695 -0
- codeframe/ui/routers/proof_v2.py +755 -0
- codeframe/ui/routers/review_v2.py +360 -0
- codeframe/ui/routers/schedule_v2.py +214 -0
- codeframe/ui/routers/session_chat_ws.py +354 -0
- codeframe/ui/routers/settings_v2.py +562 -0
- codeframe/ui/routers/streaming_v2.py +155 -0
- codeframe/ui/routers/tasks_v2.py +1098 -0
- codeframe/ui/routers/templates_v2.py +232 -0
- codeframe/ui/routers/terminal_ws.py +267 -0
- codeframe/ui/routers/workspace_v2.py +527 -0
- codeframe/ui/server.py +568 -0
- codeframe/ui/shared.py +241 -0
- codeframe/workspace/__init__.py +5 -0
- codeframe/workspace/manager.py +249 -0
- codeframe_ai-0.9.0.dist-info/METADATA +517 -0
- codeframe_ai-0.9.0.dist-info/RECORD +197 -0
- codeframe_ai-0.9.0.dist-info/WHEEL +5 -0
- codeframe_ai-0.9.0.dist-info/entry_points.txt +3 -0
- codeframe_ai-0.9.0.dist-info/licenses/LICENSE +661 -0
- codeframe_ai-0.9.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,533 @@
|
|
|
1
|
+
"""Task Template System for CodeFRAME.
|
|
2
|
+
|
|
3
|
+
This module provides a template system for common task patterns:
|
|
4
|
+
- TaskTemplate: Dataclass defining a task template
|
|
5
|
+
- TemplateTask: Individual task within a template
|
|
6
|
+
- TaskTemplateManager: Manage and apply templates
|
|
7
|
+
- BUILTIN_TEMPLATES: Predefined templates for common patterns
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
from dataclasses import dataclass, field
|
|
12
|
+
from typing import Dict, List, Optional, Any
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class TemplateTask:
|
|
19
|
+
"""Individual task within a template.
|
|
20
|
+
|
|
21
|
+
Attributes:
|
|
22
|
+
title: Task title
|
|
23
|
+
description: Task description
|
|
24
|
+
estimated_hours: Time estimate in hours
|
|
25
|
+
complexity_score: Complexity rating (1-5)
|
|
26
|
+
uncertainty_level: "low", "medium", "high" (optional)
|
|
27
|
+
depends_on_indices: List of task indices this task depends on
|
|
28
|
+
tags: Optional tags for the task
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
title: str
|
|
32
|
+
description: str
|
|
33
|
+
estimated_hours: float
|
|
34
|
+
complexity_score: int
|
|
35
|
+
uncertainty_level: str = "medium"
|
|
36
|
+
depends_on_indices: List[int] = field(default_factory=list)
|
|
37
|
+
tags: List[str] = field(default_factory=list)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@dataclass
|
|
41
|
+
class TaskTemplate:
|
|
42
|
+
"""Template for generating a set of related tasks.
|
|
43
|
+
|
|
44
|
+
Attributes:
|
|
45
|
+
id: Unique identifier for the template
|
|
46
|
+
name: Human-readable name
|
|
47
|
+
description: Description of what this template is for
|
|
48
|
+
category: Category (backend, frontend, testing, etc.)
|
|
49
|
+
tasks: List of TemplateTask objects
|
|
50
|
+
tags: Optional tags for the template
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
id: str
|
|
54
|
+
name: str
|
|
55
|
+
description: str
|
|
56
|
+
category: str
|
|
57
|
+
tasks: List[TemplateTask]
|
|
58
|
+
tags: List[str] = field(default_factory=list)
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def total_estimated_hours(self) -> float:
|
|
62
|
+
"""Calculate total estimated hours for all tasks."""
|
|
63
|
+
return sum(t.estimated_hours for t in self.tasks)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
# Predefined builtin templates
|
|
67
|
+
BUILTIN_TEMPLATES: List[TaskTemplate] = [
|
|
68
|
+
TaskTemplate(
|
|
69
|
+
id="api-endpoint",
|
|
70
|
+
name="API Endpoint",
|
|
71
|
+
description="Create a new REST API endpoint with validation, handlers, and tests",
|
|
72
|
+
category="backend",
|
|
73
|
+
tags=["api", "rest", "backend"],
|
|
74
|
+
tasks=[
|
|
75
|
+
TemplateTask(
|
|
76
|
+
title="Define API schema and models",
|
|
77
|
+
description="Create request/response models and validation schemas",
|
|
78
|
+
estimated_hours=1.0,
|
|
79
|
+
complexity_score=2,
|
|
80
|
+
uncertainty_level="low",
|
|
81
|
+
depends_on_indices=[],
|
|
82
|
+
),
|
|
83
|
+
TemplateTask(
|
|
84
|
+
title="Implement endpoint handler",
|
|
85
|
+
description="Write the endpoint logic and business rules",
|
|
86
|
+
estimated_hours=2.0,
|
|
87
|
+
complexity_score=3,
|
|
88
|
+
uncertainty_level="medium",
|
|
89
|
+
depends_on_indices=[0],
|
|
90
|
+
),
|
|
91
|
+
TemplateTask(
|
|
92
|
+
title="Add error handling",
|
|
93
|
+
description="Implement proper error responses and edge cases",
|
|
94
|
+
estimated_hours=1.0,
|
|
95
|
+
complexity_score=2,
|
|
96
|
+
uncertainty_level="low",
|
|
97
|
+
depends_on_indices=[1],
|
|
98
|
+
),
|
|
99
|
+
TemplateTask(
|
|
100
|
+
title="Write unit tests",
|
|
101
|
+
description="Create comprehensive unit tests for the endpoint",
|
|
102
|
+
estimated_hours=1.5,
|
|
103
|
+
complexity_score=2,
|
|
104
|
+
uncertainty_level="low",
|
|
105
|
+
depends_on_indices=[1],
|
|
106
|
+
),
|
|
107
|
+
TemplateTask(
|
|
108
|
+
title="Add API documentation",
|
|
109
|
+
description="Document endpoint in OpenAPI/Swagger spec",
|
|
110
|
+
estimated_hours=0.5,
|
|
111
|
+
complexity_score=1,
|
|
112
|
+
uncertainty_level="low",
|
|
113
|
+
depends_on_indices=[0, 1],
|
|
114
|
+
),
|
|
115
|
+
],
|
|
116
|
+
),
|
|
117
|
+
TaskTemplate(
|
|
118
|
+
id="ui-component",
|
|
119
|
+
name="UI Component",
|
|
120
|
+
description="Create a new React/frontend UI component with styling and tests",
|
|
121
|
+
category="frontend",
|
|
122
|
+
tags=["ui", "react", "frontend", "component"],
|
|
123
|
+
tasks=[
|
|
124
|
+
TemplateTask(
|
|
125
|
+
title="Design component interface",
|
|
126
|
+
description="Define props, state, and component API",
|
|
127
|
+
estimated_hours=0.5,
|
|
128
|
+
complexity_score=2,
|
|
129
|
+
uncertainty_level="low",
|
|
130
|
+
depends_on_indices=[],
|
|
131
|
+
),
|
|
132
|
+
TemplateTask(
|
|
133
|
+
title="Implement component structure",
|
|
134
|
+
description="Create the component with JSX/TSX structure",
|
|
135
|
+
estimated_hours=1.5,
|
|
136
|
+
complexity_score=3,
|
|
137
|
+
uncertainty_level="medium",
|
|
138
|
+
depends_on_indices=[0],
|
|
139
|
+
),
|
|
140
|
+
TemplateTask(
|
|
141
|
+
title="Add styling",
|
|
142
|
+
description="Style the component with CSS/Tailwind",
|
|
143
|
+
estimated_hours=1.0,
|
|
144
|
+
complexity_score=2,
|
|
145
|
+
uncertainty_level="low",
|
|
146
|
+
depends_on_indices=[1],
|
|
147
|
+
),
|
|
148
|
+
TemplateTask(
|
|
149
|
+
title="Implement interactions",
|
|
150
|
+
description="Add event handlers and state management",
|
|
151
|
+
estimated_hours=1.0,
|
|
152
|
+
complexity_score=3,
|
|
153
|
+
uncertainty_level="medium",
|
|
154
|
+
depends_on_indices=[1],
|
|
155
|
+
),
|
|
156
|
+
TemplateTask(
|
|
157
|
+
title="Write component tests",
|
|
158
|
+
description="Create unit and integration tests",
|
|
159
|
+
estimated_hours=1.5,
|
|
160
|
+
complexity_score=2,
|
|
161
|
+
uncertainty_level="low",
|
|
162
|
+
depends_on_indices=[1, 2, 3],
|
|
163
|
+
),
|
|
164
|
+
TemplateTask(
|
|
165
|
+
title="Add accessibility features",
|
|
166
|
+
description="Ensure WCAG compliance and keyboard navigation",
|
|
167
|
+
estimated_hours=0.5,
|
|
168
|
+
complexity_score=2,
|
|
169
|
+
uncertainty_level="low",
|
|
170
|
+
depends_on_indices=[1],
|
|
171
|
+
),
|
|
172
|
+
],
|
|
173
|
+
),
|
|
174
|
+
TaskTemplate(
|
|
175
|
+
id="database-migration",
|
|
176
|
+
name="Database Migration",
|
|
177
|
+
description="Create a database schema migration with rollback support",
|
|
178
|
+
category="backend",
|
|
179
|
+
tags=["database", "migration", "schema"],
|
|
180
|
+
tasks=[
|
|
181
|
+
TemplateTask(
|
|
182
|
+
title="Design schema changes",
|
|
183
|
+
description="Document the schema modifications needed",
|
|
184
|
+
estimated_hours=0.5,
|
|
185
|
+
complexity_score=2,
|
|
186
|
+
uncertainty_level="low",
|
|
187
|
+
depends_on_indices=[],
|
|
188
|
+
),
|
|
189
|
+
TemplateTask(
|
|
190
|
+
title="Write migration script",
|
|
191
|
+
description="Create the forward migration SQL/script",
|
|
192
|
+
estimated_hours=1.0,
|
|
193
|
+
complexity_score=3,
|
|
194
|
+
uncertainty_level="medium",
|
|
195
|
+
depends_on_indices=[0],
|
|
196
|
+
),
|
|
197
|
+
TemplateTask(
|
|
198
|
+
title="Write rollback script",
|
|
199
|
+
description="Create the rollback migration for reversal",
|
|
200
|
+
estimated_hours=0.5,
|
|
201
|
+
complexity_score=2,
|
|
202
|
+
uncertainty_level="low",
|
|
203
|
+
depends_on_indices=[1],
|
|
204
|
+
),
|
|
205
|
+
TemplateTask(
|
|
206
|
+
title="Update model definitions",
|
|
207
|
+
description="Update ORM models to match new schema",
|
|
208
|
+
estimated_hours=1.0,
|
|
209
|
+
complexity_score=2,
|
|
210
|
+
uncertainty_level="low",
|
|
211
|
+
depends_on_indices=[1],
|
|
212
|
+
),
|
|
213
|
+
TemplateTask(
|
|
214
|
+
title="Test migration",
|
|
215
|
+
description="Test migration on staging/test database",
|
|
216
|
+
estimated_hours=1.0,
|
|
217
|
+
complexity_score=2,
|
|
218
|
+
uncertainty_level="medium",
|
|
219
|
+
depends_on_indices=[1, 2, 3],
|
|
220
|
+
),
|
|
221
|
+
],
|
|
222
|
+
),
|
|
223
|
+
TaskTemplate(
|
|
224
|
+
id="test-suite",
|
|
225
|
+
name="Test Suite",
|
|
226
|
+
description="Create a comprehensive test suite for a feature",
|
|
227
|
+
category="testing",
|
|
228
|
+
tags=["testing", "quality", "tdd"],
|
|
229
|
+
tasks=[
|
|
230
|
+
TemplateTask(
|
|
231
|
+
title="Identify test scenarios",
|
|
232
|
+
description="Document all test cases and edge cases",
|
|
233
|
+
estimated_hours=1.0,
|
|
234
|
+
complexity_score=2,
|
|
235
|
+
uncertainty_level="low",
|
|
236
|
+
depends_on_indices=[],
|
|
237
|
+
),
|
|
238
|
+
TemplateTask(
|
|
239
|
+
title="Set up test fixtures",
|
|
240
|
+
description="Create test data and mock objects",
|
|
241
|
+
estimated_hours=1.0,
|
|
242
|
+
complexity_score=2,
|
|
243
|
+
uncertainty_level="low",
|
|
244
|
+
depends_on_indices=[0],
|
|
245
|
+
),
|
|
246
|
+
TemplateTask(
|
|
247
|
+
title="Write unit tests",
|
|
248
|
+
description="Create unit tests for individual functions",
|
|
249
|
+
estimated_hours=2.0,
|
|
250
|
+
complexity_score=2,
|
|
251
|
+
uncertainty_level="low",
|
|
252
|
+
depends_on_indices=[1],
|
|
253
|
+
),
|
|
254
|
+
TemplateTask(
|
|
255
|
+
title="Write integration tests",
|
|
256
|
+
description="Create integration tests for component interactions",
|
|
257
|
+
estimated_hours=2.0,
|
|
258
|
+
complexity_score=3,
|
|
259
|
+
uncertainty_level="medium",
|
|
260
|
+
depends_on_indices=[1],
|
|
261
|
+
),
|
|
262
|
+
TemplateTask(
|
|
263
|
+
title="Add edge case tests",
|
|
264
|
+
description="Test error conditions and boundary cases",
|
|
265
|
+
estimated_hours=1.0,
|
|
266
|
+
complexity_score=2,
|
|
267
|
+
uncertainty_level="low",
|
|
268
|
+
depends_on_indices=[2, 3],
|
|
269
|
+
),
|
|
270
|
+
],
|
|
271
|
+
),
|
|
272
|
+
TaskTemplate(
|
|
273
|
+
id="feature-flag",
|
|
274
|
+
name="Feature Flag",
|
|
275
|
+
description="Implement a feature behind a feature flag for gradual rollout",
|
|
276
|
+
category="backend",
|
|
277
|
+
tags=["feature-flag", "rollout", "backend"],
|
|
278
|
+
tasks=[
|
|
279
|
+
TemplateTask(
|
|
280
|
+
title="Define feature flag",
|
|
281
|
+
description="Create feature flag configuration",
|
|
282
|
+
estimated_hours=0.5,
|
|
283
|
+
complexity_score=1,
|
|
284
|
+
uncertainty_level="low",
|
|
285
|
+
depends_on_indices=[],
|
|
286
|
+
),
|
|
287
|
+
TemplateTask(
|
|
288
|
+
title="Implement feature code",
|
|
289
|
+
description="Write the feature implementation",
|
|
290
|
+
estimated_hours=3.0,
|
|
291
|
+
complexity_score=3,
|
|
292
|
+
uncertainty_level="medium",
|
|
293
|
+
depends_on_indices=[0],
|
|
294
|
+
),
|
|
295
|
+
TemplateTask(
|
|
296
|
+
title="Add flag checks",
|
|
297
|
+
description="Wrap feature code with flag checks",
|
|
298
|
+
estimated_hours=0.5,
|
|
299
|
+
complexity_score=1,
|
|
300
|
+
uncertainty_level="low",
|
|
301
|
+
depends_on_indices=[1],
|
|
302
|
+
),
|
|
303
|
+
TemplateTask(
|
|
304
|
+
title="Write tests with flag variations",
|
|
305
|
+
description="Test both enabled and disabled states",
|
|
306
|
+
estimated_hours=1.0,
|
|
307
|
+
complexity_score=2,
|
|
308
|
+
uncertainty_level="low",
|
|
309
|
+
depends_on_indices=[1, 2],
|
|
310
|
+
),
|
|
311
|
+
],
|
|
312
|
+
),
|
|
313
|
+
TaskTemplate(
|
|
314
|
+
id="bug-fix",
|
|
315
|
+
name="Bug Fix",
|
|
316
|
+
description="Standard workflow for fixing a bug with proper testing",
|
|
317
|
+
category="general",
|
|
318
|
+
tags=["bug", "fix", "maintenance"],
|
|
319
|
+
tasks=[
|
|
320
|
+
TemplateTask(
|
|
321
|
+
title="Reproduce and document bug",
|
|
322
|
+
description="Create reliable reproduction steps",
|
|
323
|
+
estimated_hours=0.5,
|
|
324
|
+
complexity_score=2,
|
|
325
|
+
uncertainty_level="medium",
|
|
326
|
+
depends_on_indices=[],
|
|
327
|
+
),
|
|
328
|
+
TemplateTask(
|
|
329
|
+
title="Write failing test",
|
|
330
|
+
description="Create test that demonstrates the bug",
|
|
331
|
+
estimated_hours=0.5,
|
|
332
|
+
complexity_score=2,
|
|
333
|
+
uncertainty_level="low",
|
|
334
|
+
depends_on_indices=[0],
|
|
335
|
+
),
|
|
336
|
+
TemplateTask(
|
|
337
|
+
title="Implement fix",
|
|
338
|
+
description="Fix the underlying issue",
|
|
339
|
+
estimated_hours=1.0,
|
|
340
|
+
complexity_score=3,
|
|
341
|
+
uncertainty_level="high",
|
|
342
|
+
depends_on_indices=[1],
|
|
343
|
+
),
|
|
344
|
+
TemplateTask(
|
|
345
|
+
title="Verify fix",
|
|
346
|
+
description="Ensure test passes and no regressions",
|
|
347
|
+
estimated_hours=0.5,
|
|
348
|
+
complexity_score=1,
|
|
349
|
+
uncertainty_level="low",
|
|
350
|
+
depends_on_indices=[2],
|
|
351
|
+
),
|
|
352
|
+
],
|
|
353
|
+
),
|
|
354
|
+
TaskTemplate(
|
|
355
|
+
id="refactoring",
|
|
356
|
+
name="Code Refactoring",
|
|
357
|
+
description="Refactor code while maintaining behavior",
|
|
358
|
+
category="general",
|
|
359
|
+
tags=["refactoring", "cleanup", "maintenance"],
|
|
360
|
+
tasks=[
|
|
361
|
+
TemplateTask(
|
|
362
|
+
title="Ensure test coverage",
|
|
363
|
+
description="Verify adequate tests exist for code being refactored",
|
|
364
|
+
estimated_hours=1.0,
|
|
365
|
+
complexity_score=2,
|
|
366
|
+
uncertainty_level="low",
|
|
367
|
+
depends_on_indices=[],
|
|
368
|
+
),
|
|
369
|
+
TemplateTask(
|
|
370
|
+
title="Plan refactoring approach",
|
|
371
|
+
description="Document the changes to be made",
|
|
372
|
+
estimated_hours=0.5,
|
|
373
|
+
complexity_score=2,
|
|
374
|
+
uncertainty_level="low",
|
|
375
|
+
depends_on_indices=[0],
|
|
376
|
+
),
|
|
377
|
+
TemplateTask(
|
|
378
|
+
title="Implement refactoring",
|
|
379
|
+
description="Make the code changes incrementally",
|
|
380
|
+
estimated_hours=2.0,
|
|
381
|
+
complexity_score=3,
|
|
382
|
+
uncertainty_level="medium",
|
|
383
|
+
depends_on_indices=[1],
|
|
384
|
+
),
|
|
385
|
+
TemplateTask(
|
|
386
|
+
title="Verify no regressions",
|
|
387
|
+
description="Run all tests and verify behavior",
|
|
388
|
+
estimated_hours=0.5,
|
|
389
|
+
complexity_score=1,
|
|
390
|
+
uncertainty_level="low",
|
|
391
|
+
depends_on_indices=[2],
|
|
392
|
+
),
|
|
393
|
+
],
|
|
394
|
+
),
|
|
395
|
+
]
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
class TaskTemplateManager:
|
|
399
|
+
"""Manager for task templates.
|
|
400
|
+
|
|
401
|
+
Handles:
|
|
402
|
+
- Loading and storing templates
|
|
403
|
+
- Retrieving templates by ID or category
|
|
404
|
+
- Applying templates to generate task definitions
|
|
405
|
+
- Registering custom templates
|
|
406
|
+
"""
|
|
407
|
+
|
|
408
|
+
def __init__(self):
|
|
409
|
+
"""Initialize with builtin templates."""
|
|
410
|
+
self.templates: Dict[str, TaskTemplate] = {}
|
|
411
|
+
|
|
412
|
+
# Load builtin templates
|
|
413
|
+
for template in BUILTIN_TEMPLATES:
|
|
414
|
+
self.templates[template.id] = template
|
|
415
|
+
|
|
416
|
+
logger.info(f"TaskTemplateManager initialized with {len(self.templates)} templates")
|
|
417
|
+
|
|
418
|
+
def get_template(self, template_id: str) -> Optional[TaskTemplate]:
|
|
419
|
+
"""Get a template by ID.
|
|
420
|
+
|
|
421
|
+
Args:
|
|
422
|
+
template_id: Template identifier
|
|
423
|
+
|
|
424
|
+
Returns:
|
|
425
|
+
TaskTemplate if found, None otherwise
|
|
426
|
+
"""
|
|
427
|
+
return self.templates.get(template_id)
|
|
428
|
+
|
|
429
|
+
def list_templates(self, category: Optional[str] = None) -> List[TaskTemplate]:
|
|
430
|
+
"""List all available templates.
|
|
431
|
+
|
|
432
|
+
Args:
|
|
433
|
+
category: Optional category filter
|
|
434
|
+
|
|
435
|
+
Returns:
|
|
436
|
+
List of TaskTemplate objects
|
|
437
|
+
"""
|
|
438
|
+
templates = list(self.templates.values())
|
|
439
|
+
|
|
440
|
+
if category:
|
|
441
|
+
templates = [t for t in templates if t.category == category]
|
|
442
|
+
|
|
443
|
+
return sorted(templates, key=lambda t: t.name)
|
|
444
|
+
|
|
445
|
+
def get_categories(self) -> List[str]:
|
|
446
|
+
"""Get list of all template categories.
|
|
447
|
+
|
|
448
|
+
Returns:
|
|
449
|
+
List of category names
|
|
450
|
+
"""
|
|
451
|
+
categories = set(t.category for t in self.templates.values())
|
|
452
|
+
return sorted(categories)
|
|
453
|
+
|
|
454
|
+
def register_template(self, template: TaskTemplate) -> None:
|
|
455
|
+
"""Register a custom template.
|
|
456
|
+
|
|
457
|
+
Args:
|
|
458
|
+
template: TaskTemplate to register
|
|
459
|
+
"""
|
|
460
|
+
self.templates[template.id] = template
|
|
461
|
+
logger.info(f"Registered template: {template.id}")
|
|
462
|
+
|
|
463
|
+
def apply_template(
|
|
464
|
+
self,
|
|
465
|
+
template_id: str,
|
|
466
|
+
context: Dict[str, Any],
|
|
467
|
+
issue_number: str = "1",
|
|
468
|
+
) -> List[Dict[str, Any]]:
|
|
469
|
+
"""Apply a template to generate task definitions.
|
|
470
|
+
|
|
471
|
+
Args:
|
|
472
|
+
template_id: ID of template to apply
|
|
473
|
+
context: Context variables for template substitution
|
|
474
|
+
issue_number: Parent issue number for task numbering
|
|
475
|
+
|
|
476
|
+
Returns:
|
|
477
|
+
List of task dictionaries ready for creation
|
|
478
|
+
|
|
479
|
+
Raises:
|
|
480
|
+
ValueError: If template not found
|
|
481
|
+
"""
|
|
482
|
+
template = self.get_template(template_id)
|
|
483
|
+
if not template:
|
|
484
|
+
raise ValueError(f"Template '{template_id}' not found")
|
|
485
|
+
|
|
486
|
+
tasks = []
|
|
487
|
+
for idx, template_task in enumerate(template.tasks):
|
|
488
|
+
task_number = f"{issue_number}.{idx + 1}"
|
|
489
|
+
|
|
490
|
+
task_dict = {
|
|
491
|
+
"task_number": task_number,
|
|
492
|
+
"title": self._apply_context(template_task.title, context),
|
|
493
|
+
"description": self._apply_context(template_task.description, context),
|
|
494
|
+
"estimated_hours": template_task.estimated_hours,
|
|
495
|
+
"complexity_score": template_task.complexity_score,
|
|
496
|
+
"uncertainty_level": template_task.uncertainty_level,
|
|
497
|
+
"depends_on_indices": template_task.depends_on_indices,
|
|
498
|
+
"tags": template_task.tags,
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
tasks.append(task_dict)
|
|
502
|
+
|
|
503
|
+
logger.info(f"Applied template '{template_id}': generated {len(tasks)} tasks")
|
|
504
|
+
return tasks
|
|
505
|
+
|
|
506
|
+
def calculate_template_hours(self, template: TaskTemplate) -> float:
|
|
507
|
+
"""Calculate total estimated hours for a template.
|
|
508
|
+
|
|
509
|
+
Args:
|
|
510
|
+
template: TaskTemplate to calculate
|
|
511
|
+
|
|
512
|
+
Returns:
|
|
513
|
+
Total hours
|
|
514
|
+
"""
|
|
515
|
+
return template.total_estimated_hours
|
|
516
|
+
|
|
517
|
+
def _apply_context(self, text: str, context: Dict[str, Any]) -> str:
|
|
518
|
+
"""Apply context variables to text.
|
|
519
|
+
|
|
520
|
+
Simple placeholder replacement using {variable} syntax.
|
|
521
|
+
|
|
522
|
+
Args:
|
|
523
|
+
text: Text with optional placeholders
|
|
524
|
+
context: Context variables
|
|
525
|
+
|
|
526
|
+
Returns:
|
|
527
|
+
Text with placeholders replaced
|
|
528
|
+
"""
|
|
529
|
+
result = text
|
|
530
|
+
for key, value in context.items():
|
|
531
|
+
placeholder = "{" + key + "}"
|
|
532
|
+
result = result.replace(placeholder, str(value))
|
|
533
|
+
return result
|