Files
workspace/tools/ideas.py

224 lines
6.5 KiB
Python
Executable File

#!/usr/bin/env python3
"""
ideas - Idea incubator
Capture, develop, and track ideas over time.
"""
import json
import sys
import random
from datetime import datetime
from pathlib import Path
WORKSPACE = Path("/home/wdjones/.openclaw/workspace")
IDEAS_FILE = WORKSPACE / "data" / "ideas.json"
STAGES = ['seed', 'growing', 'ready', 'planted', 'archived']
STAGE_EMOJI = {'seed': '🌱', 'growing': '🌿', 'ready': '🌻', 'planted': '🌳', 'archived': '📦'}
def load_ideas() -> list:
"""Load ideas."""
IDEAS_FILE.parent.mkdir(parents=True, exist_ok=True)
if IDEAS_FILE.exists():
with open(IDEAS_FILE) as f:
return json.load(f)
return []
def save_ideas(ideas: list):
"""Save ideas."""
with open(IDEAS_FILE, 'w') as f:
json.dump(ideas, f, indent=2)
def add_idea(title: str, description: str = None, tags: list = None):
"""Add a new idea."""
ideas = load_ideas()
idea = {
'id': len(ideas) + 1,
'title': title,
'description': description,
'tags': tags or [],
'stage': 'seed',
'notes': [],
'created': datetime.now().isoformat(),
'updated': datetime.now().isoformat(),
}
ideas.append(idea)
save_ideas(ideas)
print(f"🌱 Idea #{idea['id']}: {title}")
def add_note(idea_id: int, note: str):
"""Add a development note to an idea."""
ideas = load_ideas()
for idea in ideas:
if idea['id'] == idea_id:
idea['notes'].append({
'text': note,
'date': datetime.now().isoformat(),
})
idea['updated'] = datetime.now().isoformat()
save_ideas(ideas)
print(f"📝 Note added to idea #{idea_id}")
return
print(f"Idea not found: #{idea_id}")
def advance(idea_id: int):
"""Advance an idea to the next stage."""
ideas = load_ideas()
for idea in ideas:
if idea['id'] == idea_id:
current = idea['stage']
idx = STAGES.index(current)
if idx < len(STAGES) - 2: # Don't auto-advance to archived
idea['stage'] = STAGES[idx + 1]
idea['updated'] = datetime.now().isoformat()
save_ideas(ideas)
emoji = STAGE_EMOJI[idea['stage']]
print(f"{emoji} Idea #{idea_id} advanced to: {idea['stage']}")
else:
print("Idea already at final stage")
return
print(f"Idea not found: #{idea_id}")
def archive(idea_id: int):
"""Archive an idea."""
ideas = load_ideas()
for idea in ideas:
if idea['id'] == idea_id:
idea['stage'] = 'archived'
idea['updated'] = datetime.now().isoformat()
save_ideas(ideas)
print(f"📦 Idea #{idea_id} archived")
return
print(f"Idea not found: #{idea_id}")
def show_idea(idea_id: int):
"""Show idea details."""
ideas = load_ideas()
for idea in ideas:
if idea['id'] == idea_id:
emoji = STAGE_EMOJI[idea['stage']]
print(f"\n{emoji} Idea #{idea['id']}: {idea['title']}")
print("=" * 50)
print(f"Stage: {idea['stage']}")
print(f"Created: {idea['created'][:10]}")
if idea.get('description'):
print(f"\n{idea['description']}")
if idea.get('tags'):
print(f"\nTags: {' '.join('#' + t for t in idea['tags'])}")
if idea['notes']:
print(f"\n📝 Development Notes ({len(idea['notes'])})")
for note in idea['notes'][-5:]:
print(f" [{note['date'][:10]}] {note['text']}")
print()
return
print(f"Idea not found: #{idea_id}")
def list_ideas(stage: str = None):
"""List ideas."""
ideas = load_ideas()
if stage:
ideas = [i for i in ideas if i['stage'] == stage]
else:
ideas = [i for i in ideas if i['stage'] != 'archived']
if not ideas:
print("No ideas yet. Add with: ideas add <title>")
return
print(f"\n💡 Ideas ({len(ideas)})")
print("=" * 50)
for stage in STAGES[:-1]: # Exclude archived
stage_ideas = [i for i in ideas if i['stage'] == stage]
if stage_ideas:
emoji = STAGE_EMOJI[stage]
print(f"\n{emoji} {stage.title()} ({len(stage_ideas)})")
for idea in stage_ideas:
notes = len(idea['notes'])
print(f" #{idea['id']} {idea['title'][:35]} ({notes} notes)")
print()
def random_idea():
"""Get a random idea to work on."""
ideas = load_ideas()
active = [i for i in ideas if i['stage'] in ['seed', 'growing']]
if not active:
print("No active ideas")
return
idea = random.choice(active)
emoji = STAGE_EMOJI[idea['stage']]
print(f"\n🎲 Random idea to develop:\n")
print(f" {emoji} #{idea['id']} {idea['title']}")
if idea.get('description'):
print(f" {idea['description'][:60]}...")
print()
def main():
if len(sys.argv) < 2:
print("Usage:")
print(" ideas add <title> - Add new idea")
print(" ideas note <id> <text> - Add development note")
print(" ideas advance <id> - Move to next stage")
print(" ideas show <id> - Show idea details")
print(" ideas list [stage] - List ideas")
print(" ideas random - Random idea to work on")
print(" ideas archive <id> - Archive idea")
print("")
print(f"Stages: {''.join(STAGES[:-1])}")
list_ideas()
return
cmd = sys.argv[1]
if cmd == 'add' and len(sys.argv) > 2:
title = ' '.join(sys.argv[2:])
add_idea(title)
elif cmd == 'note' and len(sys.argv) > 3:
idea_id = int(sys.argv[2])
note = ' '.join(sys.argv[3:])
add_note(idea_id, note)
elif cmd == 'advance' and len(sys.argv) > 2:
advance(int(sys.argv[2]))
elif cmd == 'show' and len(sys.argv) > 2:
show_idea(int(sys.argv[2]))
elif cmd == 'list':
stage = sys.argv[2] if len(sys.argv) > 2 else None
list_ideas(stage)
elif cmd == 'random':
random_idea()
elif cmd == 'archive' and len(sys.argv) > 2:
archive(int(sys.argv[2]))
else:
print("Unknown command. Run 'ideas' for help.")
if __name__ == "__main__":
main()