#!/usr/bin/env python3 """ Idea to Draft Expander Takes an idea ID and creates a draft scaffold with relevant context. """ import json import argparse from datetime import datetime from pathlib import Path BRAIN_ROOT = Path(__file__).parent.parent.parent def load_jsonl(filepath): """Load JSONL file, skipping schema lines.""" items = [] if not filepath.exists(): return items with open(filepath, 'r') as f: for line in f: line = line.strip() if not line: continue try: data = json.loads(line) if '_schema' not in data: items.append(data) except json.JSONDecodeError: continue return items def find_idea(idea_id): """Find an idea by ID or partial match.""" ideas = load_jsonl(BRAIN_ROOT / 'content' / 'ideas.jsonl') for idea in ideas: if idea.get('id') == idea_id: return idea # Partial match if idea_id.lower() in idea.get('id', '').lower(): return idea if idea_id.lower() in idea.get('idea', '').lower(): return idea return None def find_related_bookmarks(tags, pillar): """Find bookmarks related to the idea.""" bookmarks = load_jsonl(BRAIN_ROOT / 'knowledge' / 'bookmarks.jsonl') related = [] for bm in bookmarks: bm_tags = set(bm.get('tags', [])) bm_category = bm.get('category', '') if tags and bm_tags.intersection(set(tags)): related.append(bm) elif pillar and bm_category == pillar: related.append(bm) return related[:5] def find_similar_posts(pillar): """Find past posts in same pillar for reference.""" posts = load_jsonl(BRAIN_ROOT / 'content' / 'posts.jsonl') similar = [p for p in posts if p.get('pillar') == pillar] return similar[:3] def generate_draft_scaffold(idea_id): """Generate a draft scaffold from an idea.""" idea = find_idea(idea_id) if not idea: return f"Error: Could not find idea matching '{idea_id}'" pillar = idea.get('pillar', 'general') tags = idea.get('tags', []) related_bookmarks = find_related_bookmarks(tags, pillar) similar_posts = find_similar_posts(pillar) output = f""" # Draft: {idea.get('idea', 'Untitled')} ## Metadata ```yaml source_idea: {idea.get('id', 'unknown')} pillar: {pillar} created: {datetime.now().isoformat()} status: draft tags: {tags} ``` ## Original Idea ``` {idea.get('idea', 'No content')} ``` Source: {idea.get('source', 'Unknown')} Notes: {idea.get('notes', 'None')} --- ## Hook Options 1. [Hook option 1] 2. [Hook option 2] 3. [Hook option 3] --- ## Main Points ### Point 1 [Expand here] ### Point 2 [Expand here] ### Point 3 [Expand here] --- ## Supporting Evidence """ if related_bookmarks: output += "\n### From Your Research\n" for bm in related_bookmarks: output += f"- [{bm.get('title', 'Untitled')}]({bm.get('url', '#')})\n" if bm.get('key_insights'): output += f" Insight: {bm['key_insights'][0]}\n" else: output += "\nNo related bookmarks found. Consider researching this topic.\n" output += """ --- ## Reference: Similar Past Content """ if similar_posts: for post in similar_posts: output += f"- {post.get('type', 'post')}: {post.get('url', 'No URL')}\n" else: output += "\nNo similar past content found.\n" output += """ --- ## Call to Action [What should the reader do?] --- ## Pre-publish Checklist - [ ] Hook is compelling - [ ] Main points are clear and valuable - [ ] Voice matches brand (check identity/voice.md) - [ ] CTA is clear - [ ] Proofread --- *Remember: Check identity/voice.md before finalizing!* """ return output if __name__ == '__main__': parser = argparse.ArgumentParser(description='Expand an idea into a draft') parser.add_argument('idea_id', help='ID or partial match of the idea to expand') args = parser.parse_args() print(generate_draft_scaffold(args.idea_id))