🚀 HISTORIC: First Effort-Based Work Assessment System
- Implemented complete task-SC integration prototype (6_0_3_0)
- Created effort assessment framework with 30-point scoring system
- Built session-based work logging with ADM triangle support
- Integrated seamlessly with existing currency ledger validation
- Successfully tested system by using it to assess its own creation
FIRST EVER SC AWARDS THROUGH EFFORT-BASED ASSESSMENT:
- Task 6_1_3_0: 153 SC (robbert_founder) + 17 SC (claude_assistant)
- Session score: 26/30 → 85% payout (fair human assessment)
- Complete audit trail from work session to SC distribution
New Files:
- policies/task-management/effort-assessment-template.yml
- policies/task-management/mission-leader-rules.yml
- scripts/task-management/create-task-with-budget.py
- scripts/task-management/assess-work-session.py
- ledger/task-management/task-budgets.csv
- ledger/task-management/session-logs.csv
This establishes the foundation for planetary-scale collaboration
where effort, learning, and genuine progress are fairly rewarded.
The future of work begins today. 🌍
master
parent
003decc7a9
commit
d58f096966
|
@ -2,3 +2,5 @@ timestamp,type,amount,from,to,reference,description,approver,phase,evidence_link
|
||||||
# Smartup Credits (SC) Transaction Ledger
|
# Smartup Credits (SC) Transaction Ledger
|
||||||
# Format: ISO timestamp, SC/REDEEM, amount, from_user, to_user, task_id, description, approver, phase, link_to_work
|
# Format: ISO timestamp, SC/REDEEM, amount, from_user, to_user, task_id, description, approver, phase, link_to_work
|
||||||
# Example: 2025-01-15T10:30:00Z,SC,50,,alice,task-123,Backend API completion,bob,validation,https://forgejo.../issues/123
|
# Example: 2025-01-15T10:30:00Z,SC,50,,alice,task-123,Backend API completion,bob,validation,https://forgejo.../issues/123
|
||||||
|
2025-08-05T17:15:00Z,SC,153,,robbert_founder,task-6_1_3_0-attacker,Task 6_1_3_0: Prototype Effort-Based Task-SC Integration System - Attacker role (85% effort payout),robbert_founder,validation,https://smartup-zero-forgejo.fly.dev/smartup-zero/3_1_leadership_team/issues/1
|
||||||
|
2025-08-05T17:15:00Z,SC,17,,claude_assistant,task-6_1_3_0-defender,Task 6_1_3_0: Prototype Effort-Based Task-SC Integration System - Defender role (85% effort payout),robbert_founder,validation,https://smartup-zero-forgejo.fly.dev/smartup-zero/3_1_leadership_team/issues/1
|
||||||
|
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
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
|
||||||
|
sess_6_1_3_0_20250805_1708,6_1_3_0,2025-08-05T14:00:00Z,2025-08-05T17:00:00Z,robbert_founder,claude_assistant,robbert_founder,9,8,9,26,85,"Exceptional systems design session. Robbert demonstrated deep architectural thinking, balancing complexity with practicality. Claude showed strong learning engagement, asking clarifying questions and contributing meaningful insights. Excellent collaborative problem-solving - true ADM triangle in action. Built complete task creation system with proper integration to existing currency ledger. This session establishes the foundation for effort-based work culture."
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
task_id,forgejo_issue_url,objective_id,team_repo,total_sc_budget,attacker_alias,defender_alias,attacker_sc,defender_sc,created_date,captain_alias,status,title,description
|
||||||
|
6_1_3_0,https://smartup-zero-forgejo.fly.dev/smartup-zero/3_1_leadership_team/issues/1,5_3_0,3_1_leadership_team,200,robbert_founder,claude_assistant,180,20,2025-08-05T16:43:28.898517,robbert_founder,created,Prototype Effort-Based Task-SC Integration System,Build working 0.1 prototype connecting task creation → effort assessment → SC payout via existing currency ledger. This is the foundational task establishing effort-based work culture in Smartup Zero.
|
|
|
@ -7,3 +7,4 @@ timestamp,event_type,amount_eur_delta,total_eur_balance,sc_outstanding,sc_liabil
|
||||||
# NOTE: Pending SC (82,200) tracked separately until validated
|
# NOTE: Pending SC (82,200) tracked separately until validated
|
||||||
# Current liability: €0 (no validated SC yet)
|
# Current liability: €0 (no validated SC yet)
|
||||||
# Contingent liability: €82,200 (if all pending SC validated)
|
# Contingent liability: €82,200 (if all pending SC validated)
|
||||||
|
2025-08-05T17:15:00Z,SC_MINTED,0,0,170,170,0.0,Task 6_1_3_0 effort-based SC awards validated,6_1_3_0
|
||||||
|
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
# Effort-Based Work Assessment Framework
|
||||||
|
# Version: 0.1 (Prototype for 6_0_3_0)
|
||||||
|
# Updated: 2025-01-16
|
||||||
|
|
||||||
|
session_evaluation:
|
||||||
|
attacker_effort:
|
||||||
|
scoring_range: "1-10"
|
||||||
|
criteria:
|
||||||
|
- "time_invested: Hours logged vs task complexity"
|
||||||
|
- "approach_quality: Systematic vs random problem-solving"
|
||||||
|
- "communication: Clear progress updates, blockers identified"
|
||||||
|
- "handoff_quality: Good briefing for next contributor"
|
||||||
|
- "collaboration: Effective mentoring of defender"
|
||||||
|
|
||||||
|
defender_learning:
|
||||||
|
scoring_range: "1-10"
|
||||||
|
criteria:
|
||||||
|
- "engagement_level: Asked questions, participated actively"
|
||||||
|
- "skill_acquisition: Demonstrated understanding of new concepts"
|
||||||
|
- "contribution: Provided valuable input beyond observation"
|
||||||
|
- "knowledge_transfer: Can explain what was learned"
|
||||||
|
|
||||||
|
collaborative_quality:
|
||||||
|
scoring_range: "1-10"
|
||||||
|
criteria:
|
||||||
|
- "adm_triangle_function: All three roles (A/D/Engelbot) working effectively"
|
||||||
|
- "problem_solving: Used collective intelligence well"
|
||||||
|
- "documentation: Session well-recorded for future contributors"
|
||||||
|
- "handoff_preparation: Next contributor can pick up easily"
|
||||||
|
|
||||||
|
payout_calculation:
|
||||||
|
excellent_session: "95-100%" # High scores across all areas (27-30 total)
|
||||||
|
good_session: "80-95%" # Solid effort, good collaboration (24-27 total)
|
||||||
|
adequate_session: "60-80%" # Some issues but genuine work done (18-24 total)
|
||||||
|
poor_session: "20-60%" # Problems with effort or collaboration (6-18 total)
|
||||||
|
failed_session: "0-20%" # No real work attempted (0-6 total)
|
||||||
|
|
||||||
|
# Special cases for nuanced assessment
|
||||||
|
partial_payout_scenarios:
|
||||||
|
time_vs_progress: "2 hours on 4-hour task with major breakthrough = full payout"
|
||||||
|
learning_intensive: "Complex task where defender learning is primary value"
|
||||||
|
research_dead_end: "Thorough investigation proving approach won't work"
|
||||||
|
handoff_quality: "Incomplete work but excellent documentation for next person"
|
||||||
|
breakthrough_discovery: "Unexpected insights that advance the mission significantly"
|
|
@ -0,0 +1,37 @@
|
||||||
|
# Mission Leader Role Definition
|
||||||
|
# Version: 0.1 (Prototype for 6_0_3_0)
|
||||||
|
# Updated: 2025-01-16
|
||||||
|
|
||||||
|
role_definition:
|
||||||
|
title: "Mission Leader (Field Commander)"
|
||||||
|
core_responsibility: "Ensure objective has all roles needed for progress"
|
||||||
|
shift_max: 8_hours
|
||||||
|
scope: "Real-time coordination of live work sessions"
|
||||||
|
authority: "Recommend SC payouts (60-100%), staff roles, coordinate handoffs"
|
||||||
|
reports_to: "Team Captain (strategic oversight)"
|
||||||
|
|
||||||
|
qualification_requirements:
|
||||||
|
minimum_sk: 100 # Proven community contribution
|
||||||
|
team_captain_appointment: true # TC must approve mission leaders
|
||||||
|
cross_team_experience: true # Understanding of multiple disciplines
|
||||||
|
timezone_availability: true # Commit to specific coverage hours
|
||||||
|
|
||||||
|
responsibilities:
|
||||||
|
primary_staffing: "All critical roles for objective progress are filled"
|
||||||
|
session_coordination: "Brief incoming contributors, manage handoffs"
|
||||||
|
effort_assessment: "Evaluate work sessions, recommend SC payouts"
|
||||||
|
escalation: "Alert TC when roles cannot be staffed or issues arise"
|
||||||
|
documentation: "Maintain session logs, progress reports"
|
||||||
|
|
||||||
|
assessment_authority:
|
||||||
|
can_recommend: "60-100% of budgeted SC based on effort quality"
|
||||||
|
must_document: "Rationale for all payout recommendations"
|
||||||
|
escalation_required: "Payouts below 60% need TC approval"
|
||||||
|
cannot_override: "Team Captain has final approval authority"
|
||||||
|
|
||||||
|
# Bootstrap phase (single captain scenario)
|
||||||
|
bootstrap_rules:
|
||||||
|
self_assessment_allowed: true # When TC is also mission leader
|
||||||
|
transparency_required: true # All assessments documented publicly
|
||||||
|
community_review: true # Subject to lazy consensus validation
|
||||||
|
conservative_bias: true # When in doubt, recommend lower payout
|
|
@ -0,0 +1,250 @@
|
||||||
|
#!/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()
|
|
@ -0,0 +1,217 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Create task with SC budget allocation and ADM assignment tracking
|
||||||
|
Integrates with existing Smartup Zero currency ledger system
|
||||||
|
Version: 0.1 (Prototype for 6_0_3_0)
|
||||||
|
Location: 1_general_forum/currency-ledger/scripts/task-management/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import csv
|
||||||
|
import yaml
|
||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
class TaskManager:
|
||||||
|
def __init__(self):
|
||||||
|
# Set paths relative to currency-ledger root
|
||||||
|
self.base_path = Path(__file__).parent.parent.parent
|
||||||
|
self.policies_path = self.base_path / "policies" / "task-management"
|
||||||
|
self.ledger_path = self.base_path / "ledger" / "task-management"
|
||||||
|
|
||||||
|
# Ensure directories exist
|
||||||
|
self.policies_path.mkdir(parents=True, exist_ok=True)
|
||||||
|
self.ledger_path.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
def load_credit_rates(self):
|
||||||
|
"""Load SC rates and ADM split configuration"""
|
||||||
|
with open(self.base_path / "policies" / "credit-rates.yml", 'r') as f:
|
||||||
|
return yaml.safe_load(f)
|
||||||
|
|
||||||
|
def generate_task_id(self, objective_id):
|
||||||
|
"""
|
||||||
|
Generate next sequential task ID
|
||||||
|
Prototype version: 6_[seq]_[objective_suffix]
|
||||||
|
Future: Full admin index implementation with proper hierarchy
|
||||||
|
"""
|
||||||
|
# Get existing tasks to determine next sequence
|
||||||
|
existing_tasks = self.get_existing_tasks(objective_id)
|
||||||
|
next_seq = len(existing_tasks) + 1
|
||||||
|
|
||||||
|
# Extract objective suffix (e.g., "5_3_0" -> "3_0")
|
||||||
|
obj_parts = objective_id.split('_')[1:] if '_' in objective_id else ["0", "0"]
|
||||||
|
obj_suffix = '_'.join(obj_parts)
|
||||||
|
|
||||||
|
return f"6_{next_seq}_{obj_suffix}"
|
||||||
|
|
||||||
|
def get_existing_tasks(self, objective_id):
|
||||||
|
"""Get list of existing tasks for this objective"""
|
||||||
|
budget_file = self.ledger_path / "task-budgets.csv"
|
||||||
|
if not budget_file.exists():
|
||||||
|
return []
|
||||||
|
|
||||||
|
tasks = []
|
||||||
|
with open(budget_file, 'r') as f:
|
||||||
|
reader = csv.DictReader(f)
|
||||||
|
for row in reader:
|
||||||
|
if row['objective_id'] == objective_id:
|
||||||
|
tasks.append(row)
|
||||||
|
return tasks
|
||||||
|
|
||||||
|
def calculate_adm_split(self, total_sc, rates):
|
||||||
|
"""Calculate 90/10 split for Attacker/Defender"""
|
||||||
|
attacker_sc = int(total_sc * rates['adm_split']['attacker_percentage'] / 100)
|
||||||
|
defender_sc = int(total_sc * rates['adm_split']['defender_percentage'] / 100)
|
||||||
|
return attacker_sc, defender_sc
|
||||||
|
|
||||||
|
def create_task_budget_record(self, task_data):
|
||||||
|
"""Record task budget in tracking CSV"""
|
||||||
|
budget_file = self.ledger_path / "task-budgets.csv"
|
||||||
|
|
||||||
|
# Create header if file doesn't exist
|
||||||
|
if not budget_file.exists():
|
||||||
|
with open(budget_file, 'w', newline='') as f:
|
||||||
|
writer = csv.writer(f)
|
||||||
|
writer.writerow([
|
||||||
|
'task_id', 'forgejo_issue_url', 'objective_id', 'team_repo',
|
||||||
|
'total_sc_budget', 'attacker_alias', 'defender_alias',
|
||||||
|
'attacker_sc', 'defender_sc', 'created_date', 'captain_alias',
|
||||||
|
'status', 'title', 'description'
|
||||||
|
])
|
||||||
|
|
||||||
|
# Add task record
|
||||||
|
with open(budget_file, 'a', newline='') as f:
|
||||||
|
writer = csv.writer(f)
|
||||||
|
writer.writerow([
|
||||||
|
task_data['task_id'],
|
||||||
|
task_data['forgejo_url'],
|
||||||
|
task_data['objective_id'],
|
||||||
|
task_data['team_repo'],
|
||||||
|
task_data['total_sc_budget'],
|
||||||
|
task_data['attacker_alias'],
|
||||||
|
task_data['defender_alias'],
|
||||||
|
task_data['attacker_sc'],
|
||||||
|
task_data['defender_sc'],
|
||||||
|
task_data['created_date'],
|
||||||
|
task_data['captain_alias'],
|
||||||
|
task_data['status'],
|
||||||
|
task_data['title'],
|
||||||
|
task_data['description']
|
||||||
|
])
|
||||||
|
|
||||||
|
def generate_forgejo_issue_template(self, task_data):
|
||||||
|
"""Generate Forgejo issue description template"""
|
||||||
|
template = f"""# {task_data['task_id']}: {task_data['title']}
|
||||||
|
|
||||||
|
## 🎯 Task Overview
|
||||||
|
**Objective**: {task_data['objective_id']}
|
||||||
|
**Team**: {task_data['team_repo']}
|
||||||
|
**SC Budget**: {task_data['total_sc_budget']} SC
|
||||||
|
|
||||||
|
## 💰 ADM Split
|
||||||
|
- **Attacker (Senior)**: {task_data['attacker_sc']} SC ({task_data['attacker_alias'] or 'TBD'})
|
||||||
|
- **Defender (Junior)**: {task_data['defender_sc']} SC ({task_data['defender_alias'] or 'TBD'})
|
||||||
|
|
||||||
|
## 📋 Description
|
||||||
|
{task_data['description']}
|
||||||
|
|
||||||
|
## ✅ Completion Criteria
|
||||||
|
- [ ] Deliverables completed as specified
|
||||||
|
- [ ] Defender has learned and can explain the work
|
||||||
|
- [ ] Documentation updated for next contributor
|
||||||
|
- [ ] Evidence links provided for validation
|
||||||
|
|
||||||
|
## 🔗 Integration
|
||||||
|
**Currency Ledger Integration**: This task uses the effort-based SC payout system.
|
||||||
|
**Assessment**: Mission Leader will evaluate effort quality for SC payout percentage.
|
||||||
|
**Validation**: Follows existing democratic validation through validate-pending-sc.py
|
||||||
|
|
||||||
|
**Created**: {task_data['created_date']}
|
||||||
|
**Captain**: {task_data['captain_alias']}
|
||||||
|
**Status**: {task_data['status']}
|
||||||
|
"""
|
||||||
|
return template
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Create task with SC budget allocation"
|
||||||
|
)
|
||||||
|
parser.add_argument('--objective', required=True,
|
||||||
|
help='Objective ID (e.g., 5_3_0)')
|
||||||
|
parser.add_argument('--team-repo', required=True,
|
||||||
|
help='Team repo (e.g., 3_1_leadership_team)')
|
||||||
|
parser.add_argument('--title', required=True,
|
||||||
|
help='Task title')
|
||||||
|
parser.add_argument('--description', required=True,
|
||||||
|
help='Task description')
|
||||||
|
parser.add_argument('--sc-budget', type=int, required=True,
|
||||||
|
choices=[25, 50, 100, 200],
|
||||||
|
help='SC budget (25/50/100/200)')
|
||||||
|
parser.add_argument('--captain', required=True,
|
||||||
|
help='Team captain alias')
|
||||||
|
parser.add_argument('--attacker',
|
||||||
|
help='Attacker alias (optional)')
|
||||||
|
parser.add_argument('--defender',
|
||||||
|
help='Defender alias (optional)')
|
||||||
|
parser.add_argument('--forgejo-url',
|
||||||
|
help='Forgejo issue URL (if already created)')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# Initialize task manager
|
||||||
|
tm = TaskManager()
|
||||||
|
|
||||||
|
# Load credit rates
|
||||||
|
rates = tm.load_credit_rates()
|
||||||
|
|
||||||
|
# Generate task ID
|
||||||
|
task_id = tm.generate_task_id(args.objective)
|
||||||
|
|
||||||
|
# Calculate ADM split
|
||||||
|
attacker_sc, defender_sc = tm.calculate_adm_split(args.sc_budget, rates)
|
||||||
|
|
||||||
|
# Prepare task data
|
||||||
|
task_data = {
|
||||||
|
'task_id': task_id,
|
||||||
|
'forgejo_url': args.forgejo_url or 'TBD - Create manually',
|
||||||
|
'objective_id': args.objective,
|
||||||
|
'team_repo': args.team_repo,
|
||||||
|
'total_sc_budget': args.sc_budget,
|
||||||
|
'attacker_alias': args.attacker or '',
|
||||||
|
'defender_alias': args.defender or '',
|
||||||
|
'attacker_sc': attacker_sc,
|
||||||
|
'defender_sc': defender_sc,
|
||||||
|
'created_date': datetime.now().isoformat(),
|
||||||
|
'captain_alias': args.captain,
|
||||||
|
'status': 'created',
|
||||||
|
'title': args.title,
|
||||||
|
'description': args.description
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create task budget record
|
||||||
|
tm.create_task_budget_record(task_data)
|
||||||
|
|
||||||
|
# Generate Forgejo template
|
||||||
|
template = tm.generate_forgejo_issue_template(task_data)
|
||||||
|
|
||||||
|
# Output results
|
||||||
|
print(f"✅ Task Created: {task_id}")
|
||||||
|
print(f"📊 SC Budget: {args.sc_budget} SC")
|
||||||
|
print(f"⚔️ Attacker: {attacker_sc} SC")
|
||||||
|
print(f"🛡️ Defender: {defender_sc} SC")
|
||||||
|
print(f"📁 Recorded in: ledger/task-management/task-budgets.csv")
|
||||||
|
print()
|
||||||
|
print("📋 FORGEJO ISSUE TEMPLATE:")
|
||||||
|
print("=" * 50)
|
||||||
|
print(template)
|
||||||
|
print("=" * 50)
|
||||||
|
print()
|
||||||
|
print("🔧 Next Steps:")
|
||||||
|
print("1. Create Forgejo issue with above template")
|
||||||
|
print("2. Update task record with Forgejo URL")
|
||||||
|
print("3. Assign ADM pair if not already specified")
|
||||||
|
print("4. Begin work session")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
Loading…
Reference in New Issue