88 lines
3.0 KiB
Python
88 lines
3.0 KiB
Python
"""Agent OS consensus engine runtime."""
|
|
|
|
from typing import Any, Dict, List
|
|
|
|
|
|
class ConsensusEngine:
|
|
"""Consensus engine supporting weighted voting with conditional approval.
|
|
|
|
Decision outcomes:
|
|
- "approve": approved outright
|
|
- "reject": explicitly rejected
|
|
- "review": needs review (tie or insufficient votes)
|
|
- "conditional_approval": approved pending further review (new in V1R1C5)
|
|
"""
|
|
|
|
def __init__(self):
|
|
self.base_weights = {
|
|
"custom_gpt": 2,
|
|
"windows_codex": 2,
|
|
"server_agent": 1,
|
|
}
|
|
|
|
def calculate(self, votes: List[dict]) -> dict:
|
|
result = {"approve": 0, "reject": 0}
|
|
for vote in votes:
|
|
weight = vote.get("weight", self.base_weights.get(vote.get("agent_type"), 1))
|
|
result[vote.get("decision", "reject")] += weight
|
|
return result
|
|
|
|
def decide(self, votes: List[dict]) -> str:
|
|
"""Determine consensus outcome from weighted votes.
|
|
|
|
Returns one of: "approve", "reject", "review", "conditional_approval".
|
|
"""
|
|
result = self.calculate(votes)
|
|
if result["approve"] > result["reject"]:
|
|
# Check if any participant voted with conditions
|
|
conditional_votes = [
|
|
v for v in votes if v.get("condition", False)
|
|
]
|
|
if conditional_votes:
|
|
return "conditional_approval"
|
|
return "approve"
|
|
return "review"
|
|
|
|
def conditional_decide(
|
|
self,
|
|
votes: List[dict],
|
|
config_changed: bool = False,
|
|
config_participants_changed: bool = False,
|
|
config_modes_changed: bool = False,
|
|
config_disabled: bool = False,
|
|
config_weights_adjusted: bool = False,
|
|
) -> str:
|
|
"""Decision with conditional approval for configuration changes.
|
|
|
|
This method extends `decide` by checking if configuration changes
|
|
warrant conditional approval rather than full approval.
|
|
|
|
Conditional approval triggers:
|
|
1. participants list modified (V1R1C5)
|
|
2. modes list modified (V1R1C5)
|
|
3. consensus disabled (V1R1C5)
|
|
4. weights adjusted beyond threshold (V1R1C5)
|
|
"""
|
|
base_decision = self.decide(votes)
|
|
|
|
# If configuration shows major changes, override to conditional_approval
|
|
if config_disabled:
|
|
# Disabling consensus is a critical change
|
|
if base_decision == "approve":
|
|
return "conditional_approval"
|
|
return base_decision
|
|
|
|
if config_participants_changed or config_modes_changed:
|
|
# Participants or modes changed — treat as conditional
|
|
if base_decision == "approve":
|
|
return "conditional_approval"
|
|
return base_decision
|
|
|
|
if config_weights_adjusted:
|
|
# Weights adjusted beyond threshold — treat as conditional
|
|
if base_decision == "approve":
|
|
return "conditional_approval"
|
|
return base_decision
|
|
|
|
return base_decision
|