htmlgraph 0.23.4__py3-none-any.whl → 0.24.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 (29) hide show
  1. htmlgraph/__init__.py +5 -1
  2. htmlgraph/cigs/__init__.py +77 -0
  3. htmlgraph/cigs/autonomy.py +385 -0
  4. htmlgraph/cigs/cost.py +475 -0
  5. htmlgraph/cigs/messages_basic.py +472 -0
  6. htmlgraph/cigs/messaging.py +365 -0
  7. htmlgraph/cigs/models.py +771 -0
  8. htmlgraph/cigs/pattern_storage.py +427 -0
  9. htmlgraph/cigs/patterns.py +503 -0
  10. htmlgraph/cigs/posttool_analyzer.py +234 -0
  11. htmlgraph/cigs/tracker.py +317 -0
  12. htmlgraph/cli.py +325 -11
  13. htmlgraph/hooks/cigs_pretool_enforcer.py +350 -0
  14. htmlgraph/hooks/posttooluse.py +50 -2
  15. htmlgraph/hooks/task_enforcer.py +60 -4
  16. htmlgraph/models.py +14 -1
  17. htmlgraph/orchestration/headless_spawner.py +525 -35
  18. htmlgraph/orchestrator-system-prompt-optimized.txt +259 -53
  19. htmlgraph/reflection.py +442 -0
  20. htmlgraph/sdk.py +26 -9
  21. {htmlgraph-0.23.4.dist-info → htmlgraph-0.24.0.dist-info}/METADATA +2 -1
  22. {htmlgraph-0.23.4.dist-info → htmlgraph-0.24.0.dist-info}/RECORD +29 -17
  23. {htmlgraph-0.23.4.data → htmlgraph-0.24.0.data}/data/htmlgraph/dashboard.html +0 -0
  24. {htmlgraph-0.23.4.data → htmlgraph-0.24.0.data}/data/htmlgraph/styles.css +0 -0
  25. {htmlgraph-0.23.4.data → htmlgraph-0.24.0.data}/data/htmlgraph/templates/AGENTS.md.template +0 -0
  26. {htmlgraph-0.23.4.data → htmlgraph-0.24.0.data}/data/htmlgraph/templates/CLAUDE.md.template +0 -0
  27. {htmlgraph-0.23.4.data → htmlgraph-0.24.0.data}/data/htmlgraph/templates/GEMINI.md.template +0 -0
  28. {htmlgraph-0.23.4.dist-info → htmlgraph-0.24.0.dist-info}/WHEEL +0 -0
  29. {htmlgraph-0.23.4.dist-info → htmlgraph-0.24.0.dist-info}/entry_points.txt +0 -0
htmlgraph/__init__.py CHANGED
@@ -55,6 +55,7 @@ from htmlgraph.orchestration import (
55
55
  from htmlgraph.orchestrator_mode import OrchestratorMode, OrchestratorModeManager
56
56
  from htmlgraph.parallel import AggregateResult, ParallelAnalysis, ParallelWorkflow
57
57
  from htmlgraph.query_builder import Condition, Operator, QueryBuilder
58
+ from htmlgraph.reflection import ComputationalReflection, get_reflection_context
58
59
  from htmlgraph.sdk import SDK
59
60
  from htmlgraph.server import serve
60
61
  from htmlgraph.session_manager import SessionManager
@@ -84,7 +85,7 @@ from htmlgraph.types import (
84
85
  )
85
86
  from htmlgraph.work_type_utils import infer_work_type, infer_work_type_from_id
86
87
 
87
- __version__ = "0.23.4"
88
+ __version__ = "0.24.0"
88
89
  __all__ = [
89
90
  # Exceptions
90
91
  "HtmlGraphError",
@@ -178,6 +179,9 @@ __all__ = [
178
179
  # Active Learning Persistence
179
180
  "LearningPersistence",
180
181
  "auto_persist_on_session_end",
182
+ # Computational Reflection (pre-computed context injection)
183
+ "ComputationalReflection",
184
+ "get_reflection_context",
181
185
  # Orchestrator Mode Management
182
186
  "OrchestratorMode",
183
187
  "OrchestratorModeManager",
@@ -0,0 +1,77 @@
1
+ """
2
+ Computational Imperative Guidance System (CIGS)
3
+
4
+ Provides guidance, messaging, and tracking for delegation enforcement in HtmlGraph.
5
+
6
+ Modules:
7
+ - messages_basic: Level 0-1 imperative message templates
8
+ - models: Data models for violations, patterns, and autonomy
9
+ - tracker: Violation tracking and persistence
10
+ - cost: Cost calculation and efficiency metrics
11
+ - patterns: Anti-pattern detection and analysis
12
+ - autonomy: Autonomy level management
13
+ """
14
+
15
+ from htmlgraph.cigs.autonomy import AutonomyRecommender
16
+ from htmlgraph.cigs.messages_basic import (
17
+ BasicMessageGenerator,
18
+ MessageTemplateLibrary,
19
+ OperationContext,
20
+ ToolCategory,
21
+ classify_operation,
22
+ estimate_costs,
23
+ )
24
+ from htmlgraph.cigs.messaging import (
25
+ ImperativeMessageGenerator,
26
+ PositiveReinforcementGenerator,
27
+ )
28
+ from htmlgraph.cigs.models import (
29
+ AutonomyLevel,
30
+ CostMetrics,
31
+ CostPrediction,
32
+ OperationClassification,
33
+ PatternRecord,
34
+ SessionViolationSummary,
35
+ TokenCost,
36
+ ViolationRecord,
37
+ ViolationType,
38
+ )
39
+ from htmlgraph.cigs.patterns import (
40
+ DetectionResult,
41
+ PatternDetector,
42
+ detect_patterns,
43
+ )
44
+ from htmlgraph.cigs.posttool_analyzer import CIGSPostToolAnalyzer
45
+ from htmlgraph.cigs.tracker import ViolationTracker
46
+
47
+ __all__ = [
48
+ # Messages
49
+ "BasicMessageGenerator",
50
+ "PositiveReinforcementGenerator",
51
+ "ImperativeMessageGenerator",
52
+ "MessageTemplateLibrary",
53
+ "OperationContext",
54
+ "ToolCategory",
55
+ "classify_operation",
56
+ "estimate_costs",
57
+ # Models
58
+ "ViolationType",
59
+ "ViolationRecord",
60
+ "SessionViolationSummary",
61
+ "PatternRecord",
62
+ "TokenCost",
63
+ "CostPrediction",
64
+ "OperationClassification",
65
+ "AutonomyLevel",
66
+ "CostMetrics",
67
+ # Autonomy
68
+ "AutonomyRecommender",
69
+ # Patterns
70
+ "PatternDetector",
71
+ "DetectionResult",
72
+ "detect_patterns",
73
+ # Tracker
74
+ "ViolationTracker",
75
+ # PostTool Analysis
76
+ "CIGSPostToolAnalyzer",
77
+ ]
@@ -0,0 +1,385 @@
1
+ """
2
+ AutonomyRecommender - Adaptive autonomy level management for CIGS.
3
+
4
+ Recommends appropriate autonomy levels based on:
5
+ - Average compliance from last 5 sessions
6
+ - Anti-pattern count
7
+ - Circuit breaker triggers
8
+
9
+ Reference: .htmlgraph/spikes/computational-imperative-guidance-system-design.md (Part 5, Section 5.4)
10
+
11
+ Decision Matrix:
12
+ - Observer (>90% compliance): Minimal guidance, trust developer
13
+ - Consultant (70-90% compliance): Moderate guidance, gentle nudges
14
+ - Collaborator (50-70% compliance): High guidance, active collaboration
15
+ - Operator (<50% compliance): Strict enforcement, mandatory acknowledgment
16
+ """
17
+
18
+ from dataclasses import dataclass, field
19
+
20
+ from htmlgraph.cigs.models import (
21
+ AutonomyLevel,
22
+ PatternRecord,
23
+ SessionViolationSummary,
24
+ )
25
+
26
+
27
+ @dataclass
28
+ class AutonomyRecommender:
29
+ """
30
+ Recommend autonomy level based on compliance history and patterns.
31
+
32
+ Implements a four-level decision matrix that adapts guidance intensity
33
+ based on demonstrated delegation compliance and detected anti-patterns.
34
+
35
+ Attributes:
36
+ compliance_history: List of compliance rates from recent sessions (0.0-1.0)
37
+ anti_pattern_count: Number of distinct anti-patterns detected
38
+ circuit_breaker_active: Whether circuit breaker was triggered in recent sessions
39
+ """
40
+
41
+ compliance_history: list[float] = field(default_factory=list)
42
+ anti_pattern_count: int = 0
43
+ circuit_breaker_active: bool = False
44
+
45
+ # Decision matrix thresholds
46
+ OBSERVER_THRESHOLD = 0.90
47
+ CONSULTANT_THRESHOLD = 0.70
48
+ COLLABORATOR_THRESHOLD = 0.50
49
+
50
+ def recommend(
51
+ self,
52
+ violations: SessionViolationSummary,
53
+ patterns: list[PatternRecord] | None = None,
54
+ compliance_history: list[float] | None = None,
55
+ ) -> AutonomyLevel:
56
+ """
57
+ Recommend autonomy level for next session.
58
+
59
+ Implements decision matrix:
60
+ - Observer (>90% compliance, no anti-patterns)
61
+ - Consultant (70-90% compliance OR 1-2 anti-patterns)
62
+ - Collaborator (50-70% compliance OR 3+ anti-patterns)
63
+ - Operator (<50% compliance OR circuit breaker triggered)
64
+
65
+ Args:
66
+ violations: Summary of violations from current/recent session
67
+ patterns: Detected behavioral patterns (if any)
68
+ compliance_history: Optional list of compliance rates from last 5 sessions
69
+
70
+ Returns:
71
+ AutonomyLevel recommendation with messaging intensity and enforcement mode
72
+ """
73
+ # Calculate average compliance
74
+ if compliance_history:
75
+ avg_compliance = sum(compliance_history) / len(compliance_history)
76
+ else:
77
+ avg_compliance = violations.compliance_rate
78
+
79
+ # Count anti-patterns
80
+ anti_pattern_count = 0
81
+ if patterns:
82
+ anti_pattern_count = len(
83
+ [p for p in patterns if p.pattern_type == "anti-pattern"]
84
+ )
85
+
86
+ # Check circuit breaker status
87
+ circuit_breaker_active = violations.circuit_breaker_triggered
88
+
89
+ # Apply decision matrix
90
+ return self._apply_decision_matrix(
91
+ avg_compliance=avg_compliance,
92
+ anti_pattern_count=anti_pattern_count,
93
+ circuit_breaker_active=circuit_breaker_active,
94
+ violations_count=violations.total_violations,
95
+ patterns=patterns or [],
96
+ )
97
+
98
+ def _apply_decision_matrix(
99
+ self,
100
+ avg_compliance: float,
101
+ anti_pattern_count: int,
102
+ circuit_breaker_active: bool,
103
+ violations_count: int,
104
+ patterns: list[PatternRecord],
105
+ ) -> AutonomyLevel:
106
+ """
107
+ Apply the decision matrix to determine autonomy level.
108
+
109
+ Decision Logic:
110
+ 1. If circuit breaker active -> OPERATOR (strict)
111
+ 2. If avg_compliance > 90% AND no anti-patterns -> OBSERVER (minimal)
112
+ 3. If avg_compliance > 70% OR anti_pattern_count <= 2 -> CONSULTANT (moderate)
113
+ 4. If avg_compliance > 50% OR anti_pattern_count <= 4 -> COLLABORATOR (high)
114
+ 5. Otherwise -> OPERATOR (strict)
115
+
116
+ Args:
117
+ avg_compliance: Average compliance rate (0.0-1.0)
118
+ anti_pattern_count: Number of anti-patterns detected
119
+ circuit_breaker_active: Whether circuit breaker is active
120
+ violations_count: Total violation count
121
+ patterns: List of detected patterns
122
+
123
+ Returns:
124
+ AutonomyLevel recommendation
125
+ """
126
+ # Circuit breaker takes precedence
127
+ if circuit_breaker_active:
128
+ return AutonomyLevel(
129
+ level="operator",
130
+ messaging_intensity="maximal",
131
+ enforcement_mode="strict",
132
+ reason=f"Circuit breaker triggered ({violations_count} violations). Strict enforcement required.",
133
+ based_on_violations=violations_count,
134
+ based_on_patterns=[
135
+ p.name for p in patterns if p.pattern_type == "anti-pattern"
136
+ ],
137
+ )
138
+
139
+ # Observer: Excellent compliance, no patterns
140
+ if avg_compliance >= self.OBSERVER_THRESHOLD and anti_pattern_count == 0:
141
+ return AutonomyLevel(
142
+ level="observer",
143
+ messaging_intensity="minimal",
144
+ enforcement_mode="guidance",
145
+ reason=f"Excellent compliance ({avg_compliance:.0%}). Minimal guidance needed.",
146
+ based_on_violations=violations_count,
147
+ based_on_patterns=[
148
+ p.name for p in patterns if p.pattern_type == "anti-pattern"
149
+ ],
150
+ )
151
+
152
+ # Consultant: Good compliance (70-90%) AND few anti-patterns (<=2)
153
+ if (
154
+ self.CONSULTANT_THRESHOLD <= avg_compliance < self.OBSERVER_THRESHOLD
155
+ ) and anti_pattern_count <= 2:
156
+ anti_pattern_list = [
157
+ p.name for p in patterns if p.pattern_type == "anti-pattern"
158
+ ]
159
+ pattern_note = (
160
+ f", {anti_pattern_count} anti-pattern(s)"
161
+ if anti_pattern_count > 0
162
+ else ""
163
+ )
164
+
165
+ return AutonomyLevel(
166
+ level="consultant",
167
+ messaging_intensity="moderate",
168
+ enforcement_mode="guidance",
169
+ reason=f"Good compliance ({avg_compliance:.0%}){pattern_note}. Moderate guidance recommended.",
170
+ based_on_violations=violations_count,
171
+ based_on_patterns=anti_pattern_list,
172
+ )
173
+
174
+ # Collaborator: Moderate compliance (50-70%) AND moderate anti-patterns (3-4)
175
+ if (
176
+ self.COLLABORATOR_THRESHOLD <= avg_compliance < self.CONSULTANT_THRESHOLD
177
+ ) and (2 < anti_pattern_count <= 4):
178
+ anti_pattern_list = [
179
+ p.name for p in patterns if p.pattern_type == "anti-pattern"
180
+ ]
181
+ return AutonomyLevel(
182
+ level="collaborator",
183
+ messaging_intensity="high",
184
+ enforcement_mode="strict",
185
+ reason=f"Moderate compliance ({avg_compliance:.0%}), {anti_pattern_count} anti-pattern(s). Active guidance needed.",
186
+ based_on_violations=violations_count,
187
+ based_on_patterns=anti_pattern_list,
188
+ )
189
+
190
+ # Operator: Low compliance (<50%) OR many anti-patterns (5+)
191
+ anti_pattern_list = [
192
+ p.name for p in patterns if p.pattern_type == "anti-pattern"
193
+ ]
194
+ return AutonomyLevel(
195
+ level="operator",
196
+ messaging_intensity="maximal",
197
+ enforcement_mode="strict",
198
+ reason=f"Low compliance ({avg_compliance:.0%}), {anti_pattern_count} anti-pattern(s). Strict enforcement required.",
199
+ based_on_violations=violations_count,
200
+ based_on_patterns=anti_pattern_list,
201
+ )
202
+
203
+ def recommend_from_compliance_history(
204
+ self,
205
+ compliance_history: list[float],
206
+ anti_pattern_count: int = 0,
207
+ circuit_breaker_active: bool = False,
208
+ ) -> AutonomyLevel:
209
+ """
210
+ Recommend autonomy level from compliance history alone.
211
+
212
+ Convenience method for cross-session recommendations when
213
+ only compliance history is available.
214
+
215
+ Args:
216
+ compliance_history: List of compliance rates from last 5 sessions
217
+ anti_pattern_count: Number of anti-patterns detected
218
+ circuit_breaker_active: Whether circuit breaker was triggered
219
+
220
+ Returns:
221
+ AutonomyLevel recommendation
222
+ """
223
+ if not compliance_history:
224
+ # Default to Consultant if no history
225
+ return AutonomyLevel(
226
+ level="consultant",
227
+ messaging_intensity="moderate",
228
+ enforcement_mode="guidance",
229
+ reason="No compliance history. Defaulting to moderate guidance.",
230
+ based_on_violations=0,
231
+ based_on_patterns=[],
232
+ )
233
+
234
+ avg_compliance = sum(compliance_history) / len(compliance_history)
235
+
236
+ # Create minimal summary for decision matrix
237
+ violations = SessionViolationSummary(
238
+ session_id="unknown",
239
+ total_violations=0,
240
+ violations_by_type={},
241
+ total_waste_tokens=0,
242
+ circuit_breaker_triggered=circuit_breaker_active,
243
+ compliance_rate=avg_compliance,
244
+ )
245
+
246
+ return self.recommend(
247
+ violations=violations,
248
+ patterns=None,
249
+ compliance_history=compliance_history,
250
+ )
251
+
252
+ def evaluate_autonomy_transition(
253
+ self,
254
+ current_level: str,
255
+ new_level: str,
256
+ ) -> dict[str, str | int]:
257
+ """
258
+ Evaluate transition between autonomy levels.
259
+
260
+ Returns metadata about the transition for logging/reporting.
261
+
262
+ Args:
263
+ current_level: Current autonomy level ("observer", "consultant", etc.)
264
+ new_level: New autonomy level
265
+
266
+ Returns:
267
+ Dictionary with transition details
268
+ """
269
+ level_order = ["observer", "consultant", "collaborator", "operator"]
270
+
271
+ current_idx = (
272
+ level_order.index(current_level) if current_level in level_order else -1
273
+ )
274
+ new_idx = level_order.index(new_level) if new_level in level_order else -1
275
+
276
+ if new_idx < 0 or current_idx < 0:
277
+ return {
278
+ "transition": "unknown",
279
+ "direction": "unknown",
280
+ "severity": "unknown",
281
+ }
282
+
283
+ if new_idx > current_idx:
284
+ direction = "escalated"
285
+ severity = "high" if new_idx - current_idx > 1 else "moderate"
286
+ elif new_idx < current_idx:
287
+ direction = "relaxed"
288
+ severity = "high" if current_idx - new_idx > 1 else "moderate"
289
+ else:
290
+ direction = "unchanged"
291
+ severity = "none"
292
+
293
+ return {
294
+ "transition": f"{current_level} → {new_level}",
295
+ "direction": direction,
296
+ "severity": severity,
297
+ "escalation_level": new_idx,
298
+ }
299
+
300
+ def get_messaging_config(self, level: str) -> dict[str, str | bool | int]:
301
+ """
302
+ Get messaging configuration for an autonomy level.
303
+
304
+ Returns imperative message configuration based on autonomy level.
305
+
306
+ Args:
307
+ level: Autonomy level ("observer", "consultant", "collaborator", "operator")
308
+
309
+ Returns:
310
+ Dictionary with messaging configuration
311
+ """
312
+ config: dict[str, dict[str, str | bool | int]] = {
313
+ "observer": {
314
+ "prefix": "💡 GUIDANCE",
315
+ "tone": "informative",
316
+ "includes_cost": False,
317
+ "includes_suggestion": True,
318
+ "requires_acknowledgment": False,
319
+ "escalation_level": 0,
320
+ },
321
+ "consultant": {
322
+ "prefix": "🔴 IMPERATIVE",
323
+ "tone": "commanding",
324
+ "includes_cost": True,
325
+ "includes_suggestion": True,
326
+ "requires_acknowledgment": False,
327
+ "escalation_level": 1,
328
+ },
329
+ "collaborator": {
330
+ "prefix": "⚠️ FINAL WARNING",
331
+ "tone": "urgent",
332
+ "includes_cost": True,
333
+ "includes_suggestion": True,
334
+ "includes_consequences": True,
335
+ "requires_acknowledgment": False,
336
+ "escalation_level": 2,
337
+ },
338
+ "operator": {
339
+ "prefix": "🚨 CIRCUIT BREAKER",
340
+ "tone": "blocking",
341
+ "includes_cost": True,
342
+ "includes_suggestion": True,
343
+ "includes_consequences": True,
344
+ "requires_acknowledgment": True,
345
+ "escalation_level": 3,
346
+ },
347
+ }
348
+
349
+ return config.get(level, config["consultant"])
350
+
351
+ def estimate_next_level(
352
+ self,
353
+ current_compliance: float,
354
+ projected_violations: int = 0,
355
+ ) -> str:
356
+ """
357
+ Estimate the autonomy level for next session.
358
+
359
+ Projects autonomy level based on current trajectory.
360
+
361
+ Args:
362
+ current_compliance: Current session's compliance rate
363
+ projected_violations: Projected violations for next session (0 = assume improvement)
364
+
365
+ Returns:
366
+ Estimated next autonomy level
367
+ """
368
+ # If violations decrease, estimate improvement
369
+ if projected_violations == 0:
370
+ estimated_compliance = min(1.0, current_compliance + 0.05)
371
+ else:
372
+ # Assume violations stay constant or worsen
373
+ estimated_compliance = max(0.0, current_compliance - 0.05)
374
+
375
+ violations = SessionViolationSummary(
376
+ session_id="projected",
377
+ total_violations=0,
378
+ violations_by_type={},
379
+ total_waste_tokens=0,
380
+ circuit_breaker_triggered=False,
381
+ compliance_rate=estimated_compliance,
382
+ )
383
+
384
+ recommendation = self.recommend(violations)
385
+ return recommendation.level