orchestrated-discussions/smarttools/discussion-vote-counter/config.yaml

112 lines
3.6 KiB
YAML

# discussion-vote-counter - Count votes and determine consensus status
# Usage: cat discussion.md | discussion-parser | discussion-vote-counter
name: discussion-vote-counter
description: Count votes and determine consensus status
category: Discussion
arguments:
- flag: --threshold-ready
variable: threshold_ready
default: "0.67"
description: Fraction of READY votes needed for consensus
- flag: --threshold-reject
variable: threshold_reject
default: "0.01"
description: Fraction of REJECT votes that blocks
- flag: --human-required
variable: human_required
default: "true"
description: Whether human approval is required
- flag: --minimum-votes
variable: minimum_votes
default: "1"
description: Minimum number of votes needed
steps:
- type: code
code: |
import json
data = json.loads(input)
vote_data = data.get("votes", {})
vote_summary = data.get("vote_summary", {})
ready = vote_summary.get("READY", 0)
changes = vote_summary.get("CHANGES", 0)
reject = vote_summary.get("REJECT", 0)
total = vote_summary.get("total", 0)
threshold_ready_val = float(threshold_ready)
threshold_reject_val = float(threshold_reject)
human_required_val = human_required.lower() == "true"
minimum_votes_val = int(minimum_votes)
# Identify human vs AI voters
human_votes = []
ai_votes = []
for name in vote_data.keys():
name_lower = name.lower()
if name_lower.startswith(("ai-", "ai_", "bot-", "bot_")):
ai_votes.append(name)
else:
human_votes.append(name)
# Count human READY votes (explicit loop to avoid exec() scope issues)
human_ready = 0
for name in human_votes:
if vote_data.get(name, "").upper() == "READY":
human_ready += 1
# Calculate ratios
ready_ratio = ready / total if total > 0 else 0
reject_ratio = reject / total if total > 0 else 0
# Identify blockers (explicit loop to avoid exec() scope issues)
blocked_by = []
for name, vote in vote_data.items():
if vote.upper() == "REJECT":
blocked_by.append(name)
# Determine consensus
consensus = {
"reached": False,
"outcome": None,
"reason": None,
"blocked_by": blocked_by
}
if total < minimum_votes_val:
consensus["reason"] = f"Insufficient votes ({total} < {minimum_votes_val})"
elif reject_ratio >= threshold_reject_val and len(blocked_by) > 0:
consensus["reason"] = f"Blocked by REJECT votes from: {', '.join(blocked_by)}"
elif human_required_val and human_ready < 1:
consensus["reason"] = "Human approval required but not received"
elif ready_ratio >= threshold_ready_val:
consensus["reached"] = True
consensus["outcome"] = "READY"
else:
needed = max(1, int(threshold_ready_val * total) + 1 - ready)
consensus["reason"] = f"Need {needed} more READY votes for consensus"
result = json.dumps({
"votes": vote_data,
"vote_summary": vote_summary,
"ratios": {
"ready": round(ready_ratio, 2),
"changes": round(changes / total, 2) if total > 0 else 0,
"reject": round(reject_ratio, 2)
},
"thresholds": {
"ready": threshold_ready_val,
"reject": threshold_reject_val
},
"consensus": consensus,
"human_votes": human_votes,
"human_ready": human_ready,
"ai_votes": ai_votes
}, indent=2)
output_var: result
output: "{result}"