1_general_forum/currency-ledger/scripts/task-management/assess-work-session.py

251 lines
10 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/usr/bin/env python3
"""
Assess work session effort and recommend SC payout
Converts human collaboration into fair compensation through structured evaluation
Version: 0.1 (Prototype for 6_0_3_0)
"""
import argparse
import csv
import yaml
from datetime import datetime
from pathlib import Path
class SessionAssessor:
def __init__(self):
# Fix: Need to go up 3 levels from scripts/task-management/ to currency-ledger/
self.base_path = Path(__file__).parent.parent.parent
self.policies_path = self.base_path / "policies" / "task-management"
self.ledger_path = self.base_path / "ledger"
print(f"Debug: Base path = {self.base_path}")
print(f"Debug: Policies path = {self.policies_path}")
def load_assessment_template(self):
"""Load effort assessment scoring criteria"""
template_file = self.policies_path / "effort-assessment-template.yml"
print(f"Debug: Looking for template at {template_file}")
with open(template_file, 'r') as f:
return yaml.safe_load(f)
def get_task_data(self, task_id):
"""Retrieve task budget information"""
budget_file = self.ledger_path / "task-management" / "task-budgets.csv"
with open(budget_file, 'r') as f:
reader = csv.DictReader(f)
for row in reader:
if row['task_id'] == task_id:
return row
raise ValueError(f"Task {task_id} not found in task budgets")
def calculate_payout_percentage(self, attacker_score, defender_score, collaboration_score, template):
"""Calculate SC payout percentage based on effort scores"""
total_score = attacker_score + defender_score + collaboration_score
max_score = 30 # 3 categories × 10 points each
# Use template scoring ranges
payout_ranges = template['payout_calculation']
if total_score >= 27: # 90%+ of max
return 95 # excellent_session range
elif total_score >= 24: # 80%+ of max
return 85 # good_session range
elif total_score >= 18: # 60%+ of max
return 70 # adequate_session range
elif total_score >= 6: # 20%+ of max
return 40 # poor_session range
else:
return 10 # failed_session range
def create_session_log(self, session_data):
"""Log session details for transparency"""
session_file = self.ledger_path / "task-management" / "session-logs.csv"
# Create header if file doesn't exist
if not session_file.exists():
with open(session_file, 'w', newline='') as f:
writer = csv.writer(f)
writer.writerow([
'session_id', 'task_id', 'start_time', 'end_time',
'attacker', 'defender', 'mission_leader',
'attacker_effort_score', 'defender_learning_score', 'collaboration_score',
'total_score', 'recommended_payout_percent', 'session_notes'
])
# Add session record
with open(session_file, 'a', newline='') as f:
writer = csv.writer(f)
writer.writerow([
session_data['session_id'],
session_data['task_id'],
session_data['start_time'],
session_data['end_time'],
session_data['attacker'],
session_data['defender'],
session_data['mission_leader'],
session_data['attacker_effort_score'],
session_data['defender_learning_score'],
session_data['collaboration_score'],
session_data['total_score'],
session_data['recommended_payout_percent'],
session_data['session_notes']
])
def create_pending_sc_entries(self, task_data, session_data):
"""Create entries in pending-sc for democratic validation"""
pending_file = self.ledger_path / "pending-sc" / "transactions.csv"
# Calculate actual SC amounts
payout_percent = session_data['recommended_payout_percent'] / 100
attacker_sc = int(int(task_data['attacker_sc']) * payout_percent)
defender_sc = int(int(task_data['defender_sc']) * payout_percent)
# Create pending SC entries (integrate with existing system)
entries = [
{
'timestamp': datetime.now().isoformat(),
'type': 'PENDING_SC',
'amount': attacker_sc,
'from': '',
'to': task_data['attacker_alias'],
'reference': f"task-{task_data['task_id']}-attacker",
'description': f"Task {task_data['task_id']}: {task_data['title']} - Attacker role ({session_data['recommended_payout_percent']}% effort payout)",
'validator_required': 'team-captain',
'phase': 'validation',
'evidence_link': task_data['forgejo_issue_url'],
'status': 'PENDING_VALIDATION',
'vesting_tranche': ''
},
{
'timestamp': datetime.now().isoformat(),
'type': 'PENDING_SC',
'amount': defender_sc,
'from': '',
'to': task_data['defender_alias'],
'reference': f"task-{task_data['task_id']}-defender",
'description': f"Task {task_data['task_id']}: {task_data['title']} - Defender role ({session_data['recommended_payout_percent']}% effort payout)",
'validator_required': 'team-captain',
'phase': 'validation',
'evidence_link': task_data['forgejo_issue_url'],
'status': 'PENDING_VALIDATION',
'vesting_tranche': ''
}
]
# Append to existing pending-sc file
with open(pending_file, 'a', newline='') as f:
writer = csv.writer(f)
for entry in entries:
writer.writerow([
entry['timestamp'],
entry['type'],
entry['amount'],
entry['from'],
entry['to'],
entry['reference'],
entry['description'],
entry['validator_required'],
entry['phase'],
entry['evidence_link'],
entry['status'],
entry['vesting_tranche']
])
return attacker_sc, defender_sc
def main():
parser = argparse.ArgumentParser(
description="Assess work session and recommend SC payout"
)
parser.add_argument('--task-id', required=True,
help='Task ID (e.g., 6_1_3_0)')
parser.add_argument('--mission-leader', required=True,
help='Mission leader conducting assessment')
parser.add_argument('--start-time', required=True,
help='Session start time (ISO format)')
parser.add_argument('--end-time', required=True,
help='Session end time (ISO format)')
parser.add_argument('--attacker-effort-score', type=int, required=True,
choices=range(1, 11), help='Attacker effort score (1-10)')
parser.add_argument('--defender-learning-score', type=int, required=True,
choices=range(1, 11), help='Defender learning score (1-10)')
parser.add_argument('--collaboration-score', type=int, required=True,
choices=range(1, 11), help='Collaboration quality score (1-10)')
parser.add_argument('--session-notes', required=True,
help='Detailed assessment notes')
parser.add_argument('--override-payout', type=int,
help='Override calculated payout percentage (60-100)')
args = parser.parse_args()
# Initialize assessor
assessor = SessionAssessor()
# Load assessment template
template = assessor.load_assessment_template()
# Get task data
task_data = assessor.get_task_data(args.task_id)
# Calculate or use override payout percentage
if args.override_payout:
if args.override_payout < 60 or args.override_payout > 100:
print("❌ Override payout must be between 60-100%")
return
payout_percent = args.override_payout
print(f"⚠️ Using override payout: {payout_percent}%")
else:
payout_percent = assessor.calculate_payout_percentage(
args.attacker_effort_score,
args.defender_learning_score,
args.collaboration_score,
template
)
# Generate session ID
session_id = f"sess_{args.task_id}_{datetime.now().strftime('%Y%m%d_%H%M')}"
# Prepare session data
session_data = {
'session_id': session_id,
'task_id': args.task_id,
'start_time': args.start_time,
'end_time': args.end_time,
'attacker': task_data['attacker_alias'],
'defender': task_data['defender_alias'],
'mission_leader': args.mission_leader,
'attacker_effort_score': args.attacker_effort_score,
'defender_learning_score': args.defender_learning_score,
'collaboration_score': args.collaboration_score,
'total_score': args.attacker_effort_score + args.defender_learning_score + args.collaboration_score,
'recommended_payout_percent': payout_percent,
'session_notes': args.session_notes
}
# Log session
assessor.create_session_log(session_data)
# Create pending SC entries
attacker_sc, defender_sc = assessor.create_pending_sc_entries(task_data, session_data)
# Output results
print(f"✅ Session Assessed: {session_id}")
print(f"📊 Total Score: {session_data['total_score']}/30")
print(f"💰 Recommended Payout: {payout_percent}%")
print(f"⚔️ Attacker SC: {attacker_sc} SC ({task_data['attacker_alias']})")
print(f"🛡️ Defender SC: {defender_sc} SC ({task_data['defender_alias']})")
print(f"📝 Session logged in: ledger/task-management/session-logs.csv")
print(f"⏳ Pending SC created in: ledger/pending-sc/transactions.csv")
print()
print("🔧 Next Steps:")
print("1. Team Captain reviews pending SC entries")
print("2. Community lazy consensus period (48h)")
print("3. SC awards processed via existing validation system")
print(f"4. Check status: python3 scripts/validate-pending-sc.py")
if __name__ == "__main__":
main()