File size: 14,371 Bytes
9abace2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
"""

Layer 3: Rule Evaluation

Part of SOVEREIGN PYTHON LLM ENGINE



Deterministic rules for decision-making.

All rules are pure predicates (state -> bool).

"""

from typing import Callable
import re

from ..models.state_machines import AgentState, TaskStatus, MCTSState
from ..models.entities import ActionType, MessageRole


# ==========================================
# Type Aliases
# ==========================================

Rule = Callable[[AgentState], bool]
TaskRule = Callable[[TaskStatus], bool]
MCTSRule = Callable[[MCTSState], bool]


# ==========================================
# Agent Loop Rules
# ==========================================

def should_reflect(state: AgentState) -> bool:
    """

    Rule: Should agent reflect on previous step?



    Triggers:

    - Explicit error in state

    - ERROR keyword in observation

    - FAILED keyword in observation

    - Code execution failure

    """
    # Check for explicit error
    if state.get("error") is not None:
        return True

    # Check observation for error indicators
    observation = state.get("current_observation", "")
    error_keywords = ["ERROR", "FAILED", "Exception", "Traceback"]

    return any(keyword in observation for keyword in error_keywords)


def should_terminate(state: AgentState) -> bool:
    """

    Rule: Should agent loop terminate?



    Terminates when:

    - Final answer is provided

    - Error is set

    - Max steps reached

    - Already terminated flag is set

    """
    has_answer = state.get("final_answer") is not None
    has_error = state.get("error") is not None
    max_steps_reached = state["step_count"] >= state["max_steps"]
    already_terminated = state.get("terminated", False)

    return has_answer or has_error or max_steps_reached or already_terminated


def should_route(state: AgentState) -> bool:
    """

    Rule: Should query be routed to a specific source?



    Routes when:

    - No routing decision has been made yet

    - No context has been retrieved yet

    """
    no_decision = state.get("router_decision") is None
    no_context = state.get("retrieved_context") is None

    return no_decision and no_context


def should_retrieve(state: AgentState) -> bool:
    """

    Rule: Should retrieval be executed?



    Retrieves when:

    - Routing decision exists

    - But context hasn't been retrieved yet

    """
    has_decision = state.get("router_decision") is not None
    no_context = state.get("retrieved_context") is None

    return has_decision and no_context


def should_use_quantum_encoding(state: AgentState) -> bool:
    """

    Rule: Should quantum token encoding be used?



    Uses quantum encoding when:

    - Not already quantum encoded

    - Step count is even (alternating pattern)

    - MoE layer will be used

    """
    not_encoded = not state.get("quantum_encoded", False)
    even_step = state["step_count"] % 2 == 0

    return not_encoded and even_step


def is_code_execution_action(state: AgentState) -> bool:
    """Rule: Is current action a code execution?"""
    action = state.get("current_action")
    return action == ActionType.EXECUTE_CODE.value


def is_tool_execution_action(state: AgentState) -> bool:
    """Rule: Is current action a tool execution?"""
    action = state.get("current_action")
    return action == ActionType.EXECUTE_TOOL.value


def is_reflection_action(state: AgentState) -> bool:
    """Rule: Is current action a reflection?"""
    action = state.get("current_action")
    return action == ActionType.REFLECT.value


def needs_context_compression(state: AgentState) -> bool:
    """

    Rule: Does conversation context need compression?



    Compresses when:

    - Step count > 5 (enough history to summarize)

    - Observation length > 2000 chars (long context)

    """
    enough_steps = state["step_count"] > 5
    observation = state.get("current_observation", "")
    long_observation = len(observation) > 2000

    return enough_steps and long_observation


# ==========================================
# Task Lifecycle Rules
# ==========================================

def can_start_task(status: TaskStatus) -> bool:
    """Rule: Can task be started?"""
    return status == TaskStatus.PENDING


def can_complete_task(status: TaskStatus) -> bool:
    """Rule: Can task be completed?"""
    return status == TaskStatus.IN_PROGRESS


def can_fail_task(status: TaskStatus) -> bool:
    """Rule: Can task fail?"""
    return status in (TaskStatus.PENDING, TaskStatus.IN_PROGRESS)


def can_cancel_task(status: TaskStatus) -> bool:
    """Rule: Can task be cancelled?"""
    return status in (TaskStatus.PENDING, TaskStatus.IN_PROGRESS)


def is_task_terminal(status: TaskStatus) -> bool:
    """Rule: Is task in terminal state?"""
    return status in (TaskStatus.COMPLETED, TaskStatus.FAILED, TaskStatus.CANCELLED)


# ==========================================
# MCTS Search Rules
# ==========================================

def mcts_should_terminate(state: MCTSState) -> bool:
    """

    Rule: Should MCTS search terminate?



    Terminates when:

    - Max iterations reached

    - Perfect score achieved (1.0)

    - Already terminated flag set

    """
    max_iterations = state["iteration"] >= state["max_iterations"]
    perfect_score = state["best_score"] >= 1.0
    already_terminated = state.get("terminated", False)

    return max_iterations or perfect_score or already_terminated


def mcts_should_expand(state: MCTSState, node_visit_count: int) -> bool:
    """

    Rule: Should node be expanded?



    Expands when:

    - Node has been visited at least once

    - OR node is the root

    """
    return node_visit_count > 0 or state["current_node_id"] == state["root_node_id"]


def mcts_is_in_selection_phase(state: MCTSState) -> bool:
    """Rule: Is MCTS in selection phase?"""
    return state["phase"] == "selection"


def mcts_is_in_expansion_phase(state: MCTSState) -> bool:
    """Rule: Is MCTS in expansion phase?"""
    return state["phase"] == "expansion"


def mcts_is_in_evaluation_phase(state: MCTSState) -> bool:
    """Rule: Is MCTS in evaluation phase?"""
    return state["phase"] == "evaluation"


def mcts_is_in_backpropagation_phase(state: MCTSState) -> bool:
    """Rule: Is MCTS in backpropagation phase?"""
    return state["phase"] == "backpropagation"


# ==========================================
# Quantum MoE Rules
# ==========================================

def should_activate_moe(token_count: int, threshold: int = 10) -> bool:
    """

    Rule: Should MoE layer be activated?



    Activates when:

    - Token count exceeds threshold

    """
    return token_count >= threshold


def should_use_top_k_gating(num_experts: int, sparsity_target: float = 0.025) -> bool:
    """

    Rule: Should top-K gating be used?



    Always true for quantum MoE (1000 experts, 2.5% sparsity).

    """
    return num_experts >= 100  # Use sparse gating for large expert counts


def expert_is_activated(expert_id: int, activated_experts: list[int]) -> bool:
    """Rule: Is expert activated?"""
    return expert_id in activated_experts


def jordan_sum_is_valid(weights: list[float], tolerance: float = 1e-6) -> bool:
    """

    Rule: Do Jordan softmax weights sum to -1?



    Validates quantum MoE constraint.

    """
    total = sum(weights)
    return abs(total - (-1.0)) < tolerance


# ==========================================
# Message & Conversation Rules
# ==========================================

def is_system_message(role: MessageRole | str) -> bool:
    """Rule: Is message from system?"""
    if isinstance(role, str):
        return role.lower() == "system"
    return role == MessageRole.SYSTEM


def is_user_message(role: MessageRole | str) -> bool:
    """Rule: Is message from user?"""
    if isinstance(role, str):
        return role.lower() == "user"
    return role == MessageRole.USER


def is_assistant_message(role: MessageRole | str) -> bool:
    """Rule: Is message from assistant?"""
    if isinstance(role, str):
        return role.lower() == "assistant"
    return role == MessageRole.ASSISTANT


def is_tool_message(role: MessageRole | str) -> bool:
    """Rule: Is message from tool?"""
    if isinstance(role, str):
        return role.lower() in ("tool", "ipython")
    return role in (MessageRole.TOOL, MessageRole.IPYTHON)


def conversation_alternates_correctly(messages: list[dict[str, str]]) -> bool:
    """

    Rule: Do messages alternate between user and assistant?



    Checks if conversation follows proper turn-taking.

    """
    if len(messages) < 2:
        return True

    for i in range(len(messages) - 1):
        curr_role = messages[i]["role"]
        next_role = messages[i + 1]["role"]

        # Skip system messages
        if curr_role == "system" or next_role == "system":
            continue

        # User should be followed by assistant, and vice versa
        if curr_role == "user" and next_role != "assistant":
            return False
        if curr_role == "assistant" and next_role not in ("user", "tool"):
            return False

    return True


# ==========================================
# Content Validation Rules
# ==========================================

def contains_code_block(text: str) -> bool:
    """Rule: Does text contain markdown code block?"""
    return bool(re.search(r'```\w*\n', text))


def contains_json(text: str) -> bool:
    """Rule: Does text contain JSON object/array?"""
    import json
    try:
        json.loads(text)
        return True
    except:
        # Try to find JSON-like structure
        return bool(re.search(r'\{[^{}]*\}|\[[^\[\]]*\]', text))


def contains_error_keywords(text: str) -> bool:
    """Rule: Does text contain error keywords?"""
    error_keywords = [
        "error", "exception", "failed", "failure", "traceback",
        "invalid", "incorrect", "wrong", "cannot", "unable"
    ]
    text_lower = text.lower()
    return any(keyword in text_lower for keyword in error_keywords)


def contains_success_keywords(text: str) -> bool:
    """Rule: Does text contain success keywords?"""
    success_keywords = [
        "success", "successful", "completed", "done", "finished",
        "passed", "correct", "valid", "works"
    ]
    text_lower = text.lower()
    return any(keyword in text_lower for keyword in success_keywords)


def is_empty_or_whitespace(text: str) -> bool:
    """Rule: Is text empty or whitespace-only?"""
    return not text.strip()


def exceeds_length_limit(text: str, limit: int) -> bool:
    """Rule: Does text exceed length limit?"""
    return len(text) > limit


# ==========================================
# Numeric Validation Rules
# ==========================================

def is_in_range(value: float, min_val: float, max_val: float) -> bool:
    """Rule: Is value in range [min_val, max_val]?"""
    return min_val <= value <= max_val


def is_positive(value: float) -> bool:
    """Rule: Is value positive?"""
    return value > 0


def is_non_negative(value: float) -> bool:
    """Rule: Is value non-negative?"""
    return value >= 0


def is_probability(value: float) -> bool:
    """Rule: Is value a valid probability [0, 1]?"""
    return 0.0 <= value <= 1.0


def is_temperature(value: float) -> bool:
    """Rule: Is value a valid temperature [0, 2]?"""
    return 0.0 <= value <= 2.0


# ==========================================
# Composite Rules (Logical Combinations)
# ==========================================

def all_rules(*rules: Rule) -> Rule:
    """

    Combine rules with AND logic.



    Returns:

        Rule that passes if ALL input rules pass

    """
    def combined_rule(state: AgentState) -> bool:
        return all(rule(state) for rule in rules)
    return combined_rule


def any_rules(*rules: Rule) -> Rule:
    """

    Combine rules with OR logic.



    Returns:

        Rule that passes if ANY input rule passes

    """
    def combined_rule(state: AgentState) -> bool:
        return any(rule(state) for rule in rules)
    return combined_rule


def not_rule(rule: Rule) -> Rule:
    """

    Negate a rule.



    Returns:

        Rule that passes if input rule fails

    """
    def negated_rule(state: AgentState) -> bool:
        return not rule(state)
    return negated_rule


# ==========================================
# Rule Registry
# ==========================================

AGENT_RULES = {
    "should_reflect": should_reflect,
    "should_terminate": should_terminate,
    "should_route": should_route,
    "should_retrieve": should_retrieve,
    "should_use_quantum_encoding": should_use_quantum_encoding,
    "is_code_execution": is_code_execution_action,
    "is_tool_execution": is_tool_execution_action,
    "is_reflection": is_reflection_action,
    "needs_compression": needs_context_compression
}

TASK_RULES = {
    "can_start": can_start_task,
    "can_complete": can_complete_task,
    "can_fail": can_fail_task,
    "can_cancel": can_cancel_task,
    "is_terminal": is_task_terminal
}

MCTS_RULES = {
    "should_terminate": mcts_should_terminate,
    "should_expand": lambda state: mcts_should_expand(state, 1),
    "is_selection": mcts_is_in_selection_phase,
    "is_expansion": mcts_is_in_expansion_phase,
    "is_evaluation": mcts_is_in_evaluation_phase,
    "is_backpropagation": mcts_is_in_backpropagation_phase
}


def get_agent_rule(name: str) -> Rule:
    """Get agent rule by name"""
    if name not in AGENT_RULES:
        raise ValueError(f"Unknown agent rule: {name}")
    return AGENT_RULES[name]


def get_task_rule(name: str) -> TaskRule:
    """Get task rule by name"""
    if name not in TASK_RULES:
        raise ValueError(f"Unknown task rule: {name}")
    return TASK_RULES[name]


def get_mcts_rule(name: str) -> MCTSRule:
    """Get MCTS rule by name"""
    if name not in MCTS_RULES:
        raise ValueError(f"Unknown MCTS rule: {name}")
    return MCTS_RULES[name]