ouroboros-ai 0.1.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.

Potentially problematic release.


This version of ouroboros-ai might be problematic. Click here for more details.

Files changed (81) hide show
  1. ouroboros/__init__.py +15 -0
  2. ouroboros/__main__.py +9 -0
  3. ouroboros/bigbang/__init__.py +39 -0
  4. ouroboros/bigbang/ambiguity.py +464 -0
  5. ouroboros/bigbang/interview.py +530 -0
  6. ouroboros/bigbang/seed_generator.py +610 -0
  7. ouroboros/cli/__init__.py +9 -0
  8. ouroboros/cli/commands/__init__.py +7 -0
  9. ouroboros/cli/commands/config.py +79 -0
  10. ouroboros/cli/commands/init.py +425 -0
  11. ouroboros/cli/commands/run.py +201 -0
  12. ouroboros/cli/commands/status.py +85 -0
  13. ouroboros/cli/formatters/__init__.py +31 -0
  14. ouroboros/cli/formatters/panels.py +157 -0
  15. ouroboros/cli/formatters/progress.py +112 -0
  16. ouroboros/cli/formatters/tables.py +166 -0
  17. ouroboros/cli/main.py +60 -0
  18. ouroboros/config/__init__.py +81 -0
  19. ouroboros/config/loader.py +292 -0
  20. ouroboros/config/models.py +332 -0
  21. ouroboros/core/__init__.py +62 -0
  22. ouroboros/core/ac_tree.py +401 -0
  23. ouroboros/core/context.py +472 -0
  24. ouroboros/core/errors.py +246 -0
  25. ouroboros/core/seed.py +212 -0
  26. ouroboros/core/types.py +205 -0
  27. ouroboros/evaluation/__init__.py +110 -0
  28. ouroboros/evaluation/consensus.py +350 -0
  29. ouroboros/evaluation/mechanical.py +351 -0
  30. ouroboros/evaluation/models.py +235 -0
  31. ouroboros/evaluation/pipeline.py +286 -0
  32. ouroboros/evaluation/semantic.py +302 -0
  33. ouroboros/evaluation/trigger.py +278 -0
  34. ouroboros/events/__init__.py +5 -0
  35. ouroboros/events/base.py +80 -0
  36. ouroboros/events/decomposition.py +153 -0
  37. ouroboros/events/evaluation.py +248 -0
  38. ouroboros/execution/__init__.py +44 -0
  39. ouroboros/execution/atomicity.py +451 -0
  40. ouroboros/execution/decomposition.py +481 -0
  41. ouroboros/execution/double_diamond.py +1386 -0
  42. ouroboros/execution/subagent.py +275 -0
  43. ouroboros/observability/__init__.py +63 -0
  44. ouroboros/observability/drift.py +383 -0
  45. ouroboros/observability/logging.py +504 -0
  46. ouroboros/observability/retrospective.py +338 -0
  47. ouroboros/orchestrator/__init__.py +78 -0
  48. ouroboros/orchestrator/adapter.py +391 -0
  49. ouroboros/orchestrator/events.py +278 -0
  50. ouroboros/orchestrator/runner.py +597 -0
  51. ouroboros/orchestrator/session.py +486 -0
  52. ouroboros/persistence/__init__.py +23 -0
  53. ouroboros/persistence/checkpoint.py +511 -0
  54. ouroboros/persistence/event_store.py +183 -0
  55. ouroboros/persistence/migrations/__init__.py +1 -0
  56. ouroboros/persistence/migrations/runner.py +100 -0
  57. ouroboros/persistence/migrations/scripts/001_initial.sql +20 -0
  58. ouroboros/persistence/schema.py +56 -0
  59. ouroboros/persistence/uow.py +230 -0
  60. ouroboros/providers/__init__.py +28 -0
  61. ouroboros/providers/base.py +133 -0
  62. ouroboros/providers/claude_code_adapter.py +212 -0
  63. ouroboros/providers/litellm_adapter.py +316 -0
  64. ouroboros/py.typed +0 -0
  65. ouroboros/resilience/__init__.py +67 -0
  66. ouroboros/resilience/lateral.py +595 -0
  67. ouroboros/resilience/stagnation.py +727 -0
  68. ouroboros/routing/__init__.py +60 -0
  69. ouroboros/routing/complexity.py +272 -0
  70. ouroboros/routing/downgrade.py +664 -0
  71. ouroboros/routing/escalation.py +340 -0
  72. ouroboros/routing/router.py +204 -0
  73. ouroboros/routing/tiers.py +247 -0
  74. ouroboros/secondary/__init__.py +40 -0
  75. ouroboros/secondary/scheduler.py +467 -0
  76. ouroboros/secondary/todo_registry.py +483 -0
  77. ouroboros_ai-0.1.0.dist-info/METADATA +607 -0
  78. ouroboros_ai-0.1.0.dist-info/RECORD +81 -0
  79. ouroboros_ai-0.1.0.dist-info/WHEEL +4 -0
  80. ouroboros_ai-0.1.0.dist-info/entry_points.txt +2 -0
  81. ouroboros_ai-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,275 @@
1
+ """SubAgent isolation and lifecycle management.
2
+
3
+ This module provides:
4
+ - SubAgent result validation
5
+ - SubAgent lifecycle events (started, completed, failed)
6
+ - Error handling that doesn't propagate to parent execution
7
+
8
+ Story 3.4: SubAgent Isolation
9
+ - AC 1, 2: SubAgents receive filtered context
10
+ - AC 3: Main context not modified by SubAgent
11
+ - AC 4: SubAgent results validated before integration
12
+ - AC 5: Failed SubAgent doesn't crash main execution
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ from typing import TYPE_CHECKING, Any
18
+
19
+ from ouroboros.core.errors import OuroborosError
20
+ from ouroboros.core.types import Result
21
+ from ouroboros.events.base import BaseEvent
22
+ from ouroboros.observability.logging import get_logger
23
+
24
+ if TYPE_CHECKING:
25
+ from ouroboros.execution.double_diamond import CycleResult
26
+
27
+ log = get_logger(__name__)
28
+
29
+
30
+ # =============================================================================
31
+ # Errors
32
+ # =============================================================================
33
+
34
+
35
+ class SubAgentError(OuroborosError):
36
+ """Error during SubAgent execution.
37
+
38
+ Attributes:
39
+ subagent_id: The SubAgent execution ID.
40
+ parent_id: The parent execution ID.
41
+ is_retriable: Whether the error is potentially retriable.
42
+ """
43
+
44
+ def __init__(
45
+ self,
46
+ message: str,
47
+ *,
48
+ subagent_id: str | None = None,
49
+ parent_id: str | None = None,
50
+ is_retriable: bool = False,
51
+ details: dict[str, Any] | None = None,
52
+ ) -> None:
53
+ super().__init__(message, details)
54
+ self.subagent_id = subagent_id
55
+ self.parent_id = parent_id
56
+ self.is_retriable = is_retriable
57
+
58
+
59
+ class ValidationError(SubAgentError):
60
+ """Error during SubAgent result validation."""
61
+
62
+ pass
63
+
64
+
65
+ # =============================================================================
66
+ # Result Validation (AC 4)
67
+ # =============================================================================
68
+
69
+
70
+ def validate_child_result(
71
+ child_result: CycleResult,
72
+ expected_ac: str, # noqa: ARG001 - reserved for future semantic validation
73
+ ) -> Result[CycleResult, ValidationError]:
74
+ """Validate a child SubAgent result before integration.
75
+
76
+ This function performs structural validation:
77
+ - Success status check
78
+ - Required phases present (for non-decomposed results)
79
+ - AC content matches expected
80
+
81
+ Semantic validation (goal alignment, drift) is deferred to Epic 5 Stage 2.
82
+
83
+ Args:
84
+ child_result: The CycleResult from child SubAgent execution.
85
+ expected_ac: The expected acceptance criterion content.
86
+
87
+ Returns:
88
+ Result containing the validated CycleResult or ValidationError.
89
+ """
90
+ from ouroboros.execution.double_diamond import Phase
91
+
92
+ # Check success status
93
+ if not child_result.success:
94
+ log.warning(
95
+ "subagent.validation.unsuccessful",
96
+ execution_id=child_result.execution_id,
97
+ current_ac=child_result.current_ac[:50],
98
+ )
99
+ return Result.err(
100
+ ValidationError(
101
+ f"Child result unsuccessful: {child_result.execution_id}",
102
+ subagent_id=child_result.execution_id,
103
+ is_retriable=False,
104
+ )
105
+ )
106
+
107
+ # For non-decomposed results, check required phases
108
+ if not child_result.is_decomposed:
109
+ required_phases = {Phase.DISCOVER, Phase.DEFINE, Phase.DESIGN, Phase.DELIVER}
110
+ present_phases = set(child_result.phase_results.keys())
111
+ missing_phases = required_phases - present_phases
112
+
113
+ if missing_phases:
114
+ log.warning(
115
+ "subagent.validation.missing_phases",
116
+ execution_id=child_result.execution_id,
117
+ missing=[p.value for p in missing_phases],
118
+ )
119
+ return Result.err(
120
+ ValidationError(
121
+ f"Missing required phases: {[p.value for p in missing_phases]}",
122
+ subagent_id=child_result.execution_id,
123
+ is_retriable=False,
124
+ details={"missing_phases": [p.value for p in missing_phases]},
125
+ )
126
+ )
127
+ else:
128
+ # Decomposed results only need DISCOVER and DEFINE phases
129
+ required_phases = {Phase.DISCOVER, Phase.DEFINE}
130
+ present_phases = set(child_result.phase_results.keys())
131
+ missing_phases = required_phases - present_phases
132
+
133
+ if missing_phases:
134
+ log.warning(
135
+ "subagent.validation.missing_phases_decomposed",
136
+ execution_id=child_result.execution_id,
137
+ missing=[p.value for p in missing_phases],
138
+ )
139
+ return Result.err(
140
+ ValidationError(
141
+ f"Decomposed result missing phases: {[p.value for p in missing_phases]}",
142
+ subagent_id=child_result.execution_id,
143
+ is_retriable=False,
144
+ )
145
+ )
146
+
147
+ log.info(
148
+ "subagent.validation.passed",
149
+ execution_id=child_result.execution_id,
150
+ is_decomposed=child_result.is_decomposed,
151
+ phase_count=len(child_result.phase_results),
152
+ )
153
+
154
+ return Result.ok(child_result)
155
+
156
+
157
+ # =============================================================================
158
+ # Lifecycle Events
159
+ # =============================================================================
160
+
161
+
162
+ def create_subagent_started_event(
163
+ subagent_id: str,
164
+ parent_execution_id: str,
165
+ child_ac: str,
166
+ depth: int,
167
+ ) -> BaseEvent:
168
+ """Create event for SubAgent execution start.
169
+
170
+ Args:
171
+ subagent_id: The SubAgent execution ID.
172
+ parent_execution_id: The parent execution ID.
173
+ child_ac: The acceptance criterion for this SubAgent.
174
+ depth: Current depth in AC decomposition tree.
175
+
176
+ Returns:
177
+ BaseEvent with type 'execution.subagent.started'.
178
+ """
179
+ return BaseEvent(
180
+ type="execution.subagent.started",
181
+ aggregate_type="execution",
182
+ aggregate_id=subagent_id,
183
+ data={
184
+ "parent_execution_id": parent_execution_id,
185
+ "child_ac": child_ac[:200], # Truncate for storage
186
+ "depth": depth,
187
+ },
188
+ )
189
+
190
+
191
+ def create_subagent_completed_event(
192
+ subagent_id: str,
193
+ parent_execution_id: str,
194
+ success: bool,
195
+ child_count: int = 0,
196
+ ) -> BaseEvent:
197
+ """Create event for SubAgent execution completion.
198
+
199
+ Args:
200
+ subagent_id: The SubAgent execution ID.
201
+ parent_execution_id: The parent execution ID.
202
+ success: Whether the SubAgent completed successfully.
203
+ child_count: Number of child SubAgents spawned (if decomposed).
204
+
205
+ Returns:
206
+ BaseEvent with type 'execution.subagent.completed'.
207
+ """
208
+ return BaseEvent(
209
+ type="execution.subagent.completed",
210
+ aggregate_type="execution",
211
+ aggregate_id=subagent_id,
212
+ data={
213
+ "parent_execution_id": parent_execution_id,
214
+ "success": success,
215
+ "child_count": child_count,
216
+ },
217
+ )
218
+
219
+
220
+ def create_subagent_failed_event(
221
+ subagent_id: str,
222
+ parent_execution_id: str,
223
+ error_message: str,
224
+ is_retriable: bool = False,
225
+ ) -> BaseEvent:
226
+ """Create event for SubAgent execution failure.
227
+
228
+ Args:
229
+ subagent_id: The SubAgent execution ID.
230
+ parent_execution_id: The parent execution ID.
231
+ error_message: Description of the failure.
232
+ is_retriable: Whether the failure might be resolved by retry.
233
+
234
+ Returns:
235
+ BaseEvent with type 'execution.subagent.failed'.
236
+ """
237
+ return BaseEvent(
238
+ type="execution.subagent.failed",
239
+ aggregate_type="execution",
240
+ aggregate_id=subagent_id,
241
+ data={
242
+ "parent_execution_id": parent_execution_id,
243
+ "error_message": error_message[:500], # Truncate for storage
244
+ "is_retriable": is_retriable,
245
+ },
246
+ )
247
+
248
+
249
+ def create_subagent_validated_event(
250
+ subagent_id: str,
251
+ parent_execution_id: str,
252
+ validation_passed: bool,
253
+ validation_message: str = "",
254
+ ) -> BaseEvent:
255
+ """Create event for SubAgent result validation.
256
+
257
+ Args:
258
+ subagent_id: The SubAgent execution ID.
259
+ parent_execution_id: The parent execution ID.
260
+ validation_passed: Whether validation passed.
261
+ validation_message: Additional validation details.
262
+
263
+ Returns:
264
+ BaseEvent with type 'execution.subagent.validated'.
265
+ """
266
+ return BaseEvent(
267
+ type="execution.subagent.validated",
268
+ aggregate_type="execution",
269
+ aggregate_id=subagent_id,
270
+ data={
271
+ "parent_execution_id": parent_execution_id,
272
+ "validation_passed": validation_passed,
273
+ "validation_message": validation_message[:200],
274
+ },
275
+ )
@@ -0,0 +1,63 @@
1
+ """Observability module for Ouroboros.
2
+
3
+ This module provides structured logging, drift measurement, and retrospective
4
+ analysis for observability across the application.
5
+
6
+ Main components:
7
+ - Logging: configure_logging, get_logger, bind_context, unbind_context
8
+ - Drift: DriftMeasurement, DriftMetrics for goal alignment tracking
9
+ - Retrospective: RetrospectiveAnalyzer for periodic self-assessment
10
+ """
11
+
12
+ from ouroboros.observability.drift import (
13
+ DRIFT_THRESHOLD,
14
+ DriftMeasuredEvent,
15
+ DriftMeasurement,
16
+ DriftMetrics,
17
+ DriftThresholdExceededEvent,
18
+ calculate_constraint_drift,
19
+ calculate_goal_drift,
20
+ calculate_ontology_drift,
21
+ )
22
+ from ouroboros.observability.logging import (
23
+ LoggingConfig,
24
+ LogMode,
25
+ bind_context,
26
+ configure_logging,
27
+ get_logger,
28
+ unbind_context,
29
+ )
30
+ from ouroboros.observability.retrospective import (
31
+ DEFAULT_RETROSPECTIVE_INTERVAL,
32
+ HumanAttentionRequiredEvent,
33
+ RetrospectiveAnalyzer,
34
+ RetrospectiveCompletedEvent,
35
+ RetrospectiveResult,
36
+ should_trigger_retrospective,
37
+ )
38
+
39
+ __all__ = [
40
+ # Logging
41
+ "LogMode",
42
+ "LoggingConfig",
43
+ "bind_context",
44
+ "configure_logging",
45
+ "get_logger",
46
+ "unbind_context",
47
+ # Drift
48
+ "DRIFT_THRESHOLD",
49
+ "DriftMeasuredEvent",
50
+ "DriftMeasurement",
51
+ "DriftMetrics",
52
+ "DriftThresholdExceededEvent",
53
+ "calculate_constraint_drift",
54
+ "calculate_goal_drift",
55
+ "calculate_ontology_drift",
56
+ # Retrospective
57
+ "DEFAULT_RETROSPECTIVE_INTERVAL",
58
+ "HumanAttentionRequiredEvent",
59
+ "RetrospectiveAnalyzer",
60
+ "RetrospectiveCompletedEvent",
61
+ "RetrospectiveResult",
62
+ "should_trigger_retrospective",
63
+ ]