218 lines
8.0 KiB
Python
Executable File
218 lines
8.0 KiB
Python
Executable File
#!/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()
|