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.
Files changed (197) hide show
  1. codeframe/__init__.py +11 -0
  2. codeframe/__main__.py +20 -0
  3. codeframe/adapters/__init__.py +5 -0
  4. codeframe/adapters/e2b/__init__.py +13 -0
  5. codeframe/adapters/e2b/adapter.py +342 -0
  6. codeframe/adapters/e2b/budget.py +71 -0
  7. codeframe/adapters/e2b/credential_scanner.py +134 -0
  8. codeframe/adapters/llm/__init__.py +92 -0
  9. codeframe/adapters/llm/anthropic.py +414 -0
  10. codeframe/adapters/llm/base.py +444 -0
  11. codeframe/adapters/llm/mock.py +281 -0
  12. codeframe/adapters/llm/openai.py +483 -0
  13. codeframe/agents/__init__.py +8 -0
  14. codeframe/agents/dependency_resolver.py +714 -0
  15. codeframe/auth/__init__.py +16 -0
  16. codeframe/auth/api_key_router.py +238 -0
  17. codeframe/auth/api_keys.py +156 -0
  18. codeframe/auth/dependencies.py +358 -0
  19. codeframe/auth/manager.py +178 -0
  20. codeframe/auth/models.py +30 -0
  21. codeframe/auth/router.py +93 -0
  22. codeframe/auth/schemas.py +15 -0
  23. codeframe/auth/scopes.py +53 -0
  24. codeframe/cli/__init__.py +12 -0
  25. codeframe/cli/__main__.py +20 -0
  26. codeframe/cli/api_client.py +275 -0
  27. codeframe/cli/app.py +5688 -0
  28. codeframe/cli/auth.py +122 -0
  29. codeframe/cli/auth_commands.py +958 -0
  30. codeframe/cli/commands/__init__.py +5 -0
  31. codeframe/cli/config_commands.py +79 -0
  32. codeframe/cli/dashboard_commands.py +67 -0
  33. codeframe/cli/engines_commands.py +205 -0
  34. codeframe/cli/env_commands.py +409 -0
  35. codeframe/cli/helpers.py +56 -0
  36. codeframe/cli/hooks_commands.py +208 -0
  37. codeframe/cli/import_commands.py +129 -0
  38. codeframe/cli/pr_commands.py +549 -0
  39. codeframe/cli/proof_commands.py +415 -0
  40. codeframe/cli/stats_commands.py +311 -0
  41. codeframe/cli/telemetry_runtime.py +153 -0
  42. codeframe/cli/validators.py +123 -0
  43. codeframe/config/rate_limits.py +165 -0
  44. codeframe/core/__init__.py +15 -0
  45. codeframe/core/adapters/__init__.py +43 -0
  46. codeframe/core/adapters/agent_adapter.py +114 -0
  47. codeframe/core/adapters/builtin.py +326 -0
  48. codeframe/core/adapters/claude_code.py +62 -0
  49. codeframe/core/adapters/codex.py +393 -0
  50. codeframe/core/adapters/git_utils.py +40 -0
  51. codeframe/core/adapters/kilocode.py +126 -0
  52. codeframe/core/adapters/opencode.py +48 -0
  53. codeframe/core/adapters/streaming_chat.py +483 -0
  54. codeframe/core/adapters/subprocess_adapter.py +213 -0
  55. codeframe/core/adapters/verification_wrapper.py +269 -0
  56. codeframe/core/agent.py +2183 -0
  57. codeframe/core/agents_config.py +569 -0
  58. codeframe/core/api_key_service.py +211 -0
  59. codeframe/core/artifacts.py +428 -0
  60. codeframe/core/blocker_detection.py +218 -0
  61. codeframe/core/blockers.py +433 -0
  62. codeframe/core/checkpoints.py +481 -0
  63. codeframe/core/conductor.py +2255 -0
  64. codeframe/core/config.py +827 -0
  65. codeframe/core/config_watcher.py +268 -0
  66. codeframe/core/context.py +542 -0
  67. codeframe/core/context_packager.py +234 -0
  68. codeframe/core/credentials.py +735 -0
  69. codeframe/core/dependency_analyzer.py +229 -0
  70. codeframe/core/dependency_graph.py +290 -0
  71. codeframe/core/diagnostic_agent.py +712 -0
  72. codeframe/core/diagnostics.py +616 -0
  73. codeframe/core/editor.py +556 -0
  74. codeframe/core/engine_registry.py +256 -0
  75. codeframe/core/engine_stats.py +231 -0
  76. codeframe/core/environment.py +697 -0
  77. codeframe/core/events.py +375 -0
  78. codeframe/core/executor.py +1005 -0
  79. codeframe/core/fix_tracker.py +480 -0
  80. codeframe/core/gates.py +1322 -0
  81. codeframe/core/git.py +477 -0
  82. codeframe/core/github_connect_service.py +178 -0
  83. codeframe/core/github_integration_config.py +118 -0
  84. codeframe/core/github_issues_service.py +449 -0
  85. codeframe/core/hooks.py +184 -0
  86. codeframe/core/importers/__init__.py +1 -0
  87. codeframe/core/importers/ralph.py +540 -0
  88. codeframe/core/installer.py +650 -0
  89. codeframe/core/models.py +1026 -0
  90. codeframe/core/notifications_config.py +183 -0
  91. codeframe/core/planner.py +437 -0
  92. codeframe/core/prd.py +670 -0
  93. codeframe/core/prd_discovery.py +1118 -0
  94. codeframe/core/prd_stress_test.py +499 -0
  95. codeframe/core/progress.py +126 -0
  96. codeframe/core/proof/__init__.py +34 -0
  97. codeframe/core/proof/capture.py +79 -0
  98. codeframe/core/proof/evidence.py +56 -0
  99. codeframe/core/proof/ledger.py +574 -0
  100. codeframe/core/proof/models.py +162 -0
  101. codeframe/core/proof/obligations.py +103 -0
  102. codeframe/core/proof/runner.py +233 -0
  103. codeframe/core/proof/scope.py +81 -0
  104. codeframe/core/proof/stubs.py +156 -0
  105. codeframe/core/quick_fixes.py +558 -0
  106. codeframe/core/react_agent.py +1650 -0
  107. codeframe/core/reconciliation.py +183 -0
  108. codeframe/core/replay.py +788 -0
  109. codeframe/core/review.py +285 -0
  110. codeframe/core/runtime.py +1134 -0
  111. codeframe/core/sandbox/__init__.py +27 -0
  112. codeframe/core/sandbox/context.py +98 -0
  113. codeframe/core/sandbox/worktree.py +20 -0
  114. codeframe/core/schedule.py +396 -0
  115. codeframe/core/stall_detector.py +71 -0
  116. codeframe/core/stall_monitor.py +134 -0
  117. codeframe/core/state_machine.py +121 -0
  118. codeframe/core/streaming.py +502 -0
  119. codeframe/core/task_tree.py +400 -0
  120. codeframe/core/tasks.py +1022 -0
  121. codeframe/core/telemetry.py +232 -0
  122. codeframe/core/templates.py +221 -0
  123. codeframe/core/tools.py +942 -0
  124. codeframe/core/workspace.py +887 -0
  125. codeframe/core/worktrees.py +276 -0
  126. codeframe/git/__init__.py +5 -0
  127. codeframe/git/github_integration.py +505 -0
  128. codeframe/lib/__init__.py +0 -0
  129. codeframe/lib/audit_logger.py +248 -0
  130. codeframe/lib/metrics_tracker.py +800 -0
  131. codeframe/lib/quality/__init__.py +7 -0
  132. codeframe/lib/quality/complexity_analyzer.py +316 -0
  133. codeframe/lib/quality/owasp_patterns.py +284 -0
  134. codeframe/lib/quality/security_scanner.py +250 -0
  135. codeframe/lib/rate_limiter.py +312 -0
  136. codeframe/notifications/__init__.py +0 -0
  137. codeframe/notifications/webhook.py +380 -0
  138. codeframe/planning/__init__.py +30 -0
  139. codeframe/planning/issue_generator.py +219 -0
  140. codeframe/planning/prd_template_functions.py +137 -0
  141. codeframe/planning/prd_templates.py +975 -0
  142. codeframe/planning/task_scheduler.py +511 -0
  143. codeframe/planning/task_templates.py +533 -0
  144. codeframe/platform_store/__init__.py +5 -0
  145. codeframe/platform_store/database.py +277 -0
  146. codeframe/platform_store/repositories/__init__.py +24 -0
  147. codeframe/platform_store/repositories/api_key_repository.py +245 -0
  148. codeframe/platform_store/repositories/audit_repository.py +67 -0
  149. codeframe/platform_store/repositories/base.py +295 -0
  150. codeframe/platform_store/repositories/interactive_sessions.py +165 -0
  151. codeframe/platform_store/repositories/token_repository.py +598 -0
  152. codeframe/platform_store/repositories/workspace_registry_repository.py +175 -0
  153. codeframe/platform_store/schema_manager.py +321 -0
  154. codeframe/templates/AGENTS.md.default +94 -0
  155. codeframe/tui/__init__.py +5 -0
  156. codeframe/tui/app.py +256 -0
  157. codeframe/tui/data_service.py +103 -0
  158. codeframe/ui/__init__.py +0 -0
  159. codeframe/ui/dependencies.py +103 -0
  160. codeframe/ui/models.py +999 -0
  161. codeframe/ui/response_models.py +201 -0
  162. codeframe/ui/routers/__init__.py +5 -0
  163. codeframe/ui/routers/_helpers.py +29 -0
  164. codeframe/ui/routers/batches_v2.py +315 -0
  165. codeframe/ui/routers/blockers_v2.py +320 -0
  166. codeframe/ui/routers/checkpoints_v2.py +310 -0
  167. codeframe/ui/routers/costs_v2.py +322 -0
  168. codeframe/ui/routers/diagnose_v2.py +225 -0
  169. codeframe/ui/routers/discovery_v2.py +417 -0
  170. codeframe/ui/routers/environment_v2.py +284 -0
  171. codeframe/ui/routers/events_v2.py +75 -0
  172. codeframe/ui/routers/gates_v2.py +166 -0
  173. codeframe/ui/routers/git_v2.py +284 -0
  174. codeframe/ui/routers/github_integrations_v2.py +532 -0
  175. codeframe/ui/routers/interactive_sessions_v2.py +238 -0
  176. codeframe/ui/routers/pr_v2.py +709 -0
  177. codeframe/ui/routers/prd_v2.py +695 -0
  178. codeframe/ui/routers/proof_v2.py +755 -0
  179. codeframe/ui/routers/review_v2.py +360 -0
  180. codeframe/ui/routers/schedule_v2.py +214 -0
  181. codeframe/ui/routers/session_chat_ws.py +354 -0
  182. codeframe/ui/routers/settings_v2.py +562 -0
  183. codeframe/ui/routers/streaming_v2.py +155 -0
  184. codeframe/ui/routers/tasks_v2.py +1098 -0
  185. codeframe/ui/routers/templates_v2.py +232 -0
  186. codeframe/ui/routers/terminal_ws.py +267 -0
  187. codeframe/ui/routers/workspace_v2.py +527 -0
  188. codeframe/ui/server.py +568 -0
  189. codeframe/ui/shared.py +241 -0
  190. codeframe/workspace/__init__.py +5 -0
  191. codeframe/workspace/manager.py +249 -0
  192. codeframe_ai-0.9.0.dist-info/METADATA +517 -0
  193. codeframe_ai-0.9.0.dist-info/RECORD +197 -0
  194. codeframe_ai-0.9.0.dist-info/WHEEL +5 -0
  195. codeframe_ai-0.9.0.dist-info/entry_points.txt +3 -0
  196. codeframe_ai-0.9.0.dist-info/licenses/LICENSE +661 -0
  197. codeframe_ai-0.9.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,183 @@
1
+ """Continuous reconciliation engine for batch execution.
2
+
3
+ Periodically checks if tasks have been externally modified (GitHub issue
4
+ closed, task manually completed, blocker resolved) and adjusts the running
5
+ batch accordingly.
6
+
7
+ This module is headless (no FastAPI, no HTTP). It exposes a standalone
8
+ ReconciliationEngine that can be driven by a background thread in the
9
+ conductor.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import logging
15
+ from dataclasses import dataclass, field
16
+ from typing import TYPE_CHECKING, Callable, Optional
17
+
18
+ from codeframe.core import blockers, tasks
19
+ from codeframe.core.state_machine import TaskStatus
20
+
21
+ if TYPE_CHECKING:
22
+ from codeframe.core.workspace import Workspace
23
+
24
+ logger = logging.getLogger(__name__)
25
+
26
+
27
+ @dataclass
28
+ class ExternalStateChange:
29
+ """A detected external change to a task's state."""
30
+
31
+ task_id: str
32
+ change_type: str # "completed", "closed", "blocker_resolved"
33
+ source: str # "manual", "github"
34
+ details: dict = field(default_factory=dict)
35
+
36
+
37
+ @dataclass
38
+ class ReconciliationResult:
39
+ """Accumulated result from a reconciliation check."""
40
+
41
+ changes_detected: list[ExternalStateChange] = field(default_factory=list)
42
+ tasks_skipped: list[str] = field(default_factory=list)
43
+ tasks_requeued: list[str] = field(default_factory=list)
44
+ errors: list[str] = field(default_factory=list)
45
+
46
+
47
+ class ReconciliationEngine:
48
+ """Checks tasks for external state changes and applies adjustments.
49
+
50
+ The engine is stateless per invocation — call check_all_active() to scan,
51
+ then apply_changes() to act on the results.
52
+
53
+ Args:
54
+ workspace: The workspace to check tasks in.
55
+ github_checker: Optional callable(task_id, task) -> list[ExternalStateChange]
56
+ for GitHub issue state sync. If None, GitHub checks are skipped.
57
+ """
58
+
59
+ def __init__(
60
+ self,
61
+ workspace: Workspace,
62
+ *,
63
+ github_checker: Optional[Callable] = None,
64
+ ) -> None:
65
+ self._workspace = workspace
66
+ self._github_checker = github_checker
67
+
68
+ def check_task(self, task_id: str) -> list[ExternalStateChange]:
69
+ """Check a single task for external state changes.
70
+
71
+ Returns a list of detected changes (may be empty).
72
+ """
73
+ task = tasks.get(self._workspace, task_id)
74
+ if task is None:
75
+ return []
76
+
77
+ changes: list[ExternalStateChange] = []
78
+
79
+ # Task was completed externally (e.g., manually marked DONE)
80
+ if task.status == TaskStatus.DONE:
81
+ changes.append(ExternalStateChange(
82
+ task_id=task_id,
83
+ change_type="completed",
84
+ source="manual",
85
+ details={"status": task.status.value},
86
+ ))
87
+
88
+ # Task is blocked but all blockers have been answered
89
+ elif task.status == TaskStatus.BLOCKED:
90
+ task_blockers = blockers.list_for_task(self._workspace, task_id)
91
+ if task_blockers and all(
92
+ b.status.value in ("ANSWERED", "RESOLVED") for b in task_blockers
93
+ ):
94
+ changes.append(ExternalStateChange(
95
+ task_id=task_id,
96
+ change_type="blocker_resolved",
97
+ source="manual",
98
+ details={"blockers_resolved": len(task_blockers)},
99
+ ))
100
+
101
+ # Check GitHub issue state if checker is available
102
+ if self._github_checker:
103
+ try:
104
+ gh_changes = self._github_checker(task_id, task)
105
+ changes.extend(gh_changes)
106
+ except Exception as exc:
107
+ logger.warning("GitHub check failed for task %s: %s", task_id, exc)
108
+
109
+ return changes
110
+
111
+ def check_all_active(
112
+ self, active_task_ids: list[str]
113
+ ) -> ReconciliationResult:
114
+ """Check all active tasks for external state changes.
115
+
116
+ Individual task check failures are caught and logged — a single
117
+ failure never crashes the entire reconciliation pass.
118
+ """
119
+ result = ReconciliationResult()
120
+
121
+ for task_id in active_task_ids:
122
+ try:
123
+ changes = self.check_task(task_id)
124
+ result.changes_detected.extend(changes)
125
+ except Exception as exc:
126
+ error_msg = f"Reconciliation check failed for {task_id}: {exc}"
127
+ result.errors.append(error_msg)
128
+ logger.warning(error_msg)
129
+
130
+ return result
131
+
132
+ def apply_changes(
133
+ self,
134
+ result: ReconciliationResult,
135
+ batch: object,
136
+ active_processes: dict,
137
+ ) -> None:
138
+ """Apply detected changes to the batch and running processes.
139
+
140
+ For completed/closed tasks: terminate the subprocess and skip.
141
+ For blocker_resolved tasks: mark for re-queue.
142
+
143
+ All exceptions are caught and appended to result.errors.
144
+ """
145
+ for change in result.changes_detected:
146
+ try:
147
+ if change.change_type in ("completed", "closed"):
148
+ # Terminate subprocess if running
149
+ proc = active_processes.get(change.task_id)
150
+ if proc is not None:
151
+ try:
152
+ proc.terminate()
153
+ except OSError:
154
+ pass # Process already dead
155
+
156
+ result.tasks_skipped.append(change.task_id)
157
+
158
+ # Update batch results
159
+ if hasattr(batch, "results"):
160
+ status = "COMPLETED" if change.change_type == "completed" else "FAILED"
161
+ batch.results[change.task_id] = status
162
+
163
+ logger.info(
164
+ "Task %s %s externally (%s) — skipped in batch",
165
+ change.task_id, change.change_type, change.source,
166
+ )
167
+
168
+ elif change.change_type == "blocker_resolved":
169
+ result.tasks_requeued.append(change.task_id)
170
+
171
+ # Update batch results to signal re-queue
172
+ if hasattr(batch, "results"):
173
+ batch.results[change.task_id] = "READY"
174
+
175
+ logger.info(
176
+ "Task %s blocker resolved — re-queued",
177
+ change.task_id,
178
+ )
179
+
180
+ except Exception as exc:
181
+ error_msg = f"Failed to apply change for {change.task_id}: {exc}"
182
+ result.errors.append(error_msg)
183
+ logger.warning(error_msg)