#!/usr/bin/env python3 """ Generate "The Sufi Who Fooled the Algorithm" — Kiyosaki-Style × Shah's Teaching Stories. Dual Mentors: SHAH (Idries Shah) + CFO (Modern CFO). 10 chapters. Each = HOOK + SHAH/CFO DIALOGUE + FRAMEWORK + LIE + PROTOCOL + REFLECTION. Two-part generation per chapter to bypass token limits. """ import json, os, sys, time, urllib.request, urllib.error OUTPUT_DIR = os.path.expanduser("~/odysseus_book/shah_kiyosaki/chapters") API_URL = "https://opencode.ai/zen/v1/chat/completions" API_KEY = "sk-jl41MVxfeWRY4ElO7cWXw8ZM6KN5r0S1DG3vK2i1SaUsVdj13ilSxyRdIQLz1Csy" # Load manifest with open(os.path.join(os.path.dirname(__file__), "manifest.json")) as f: MANIFEST = json.load(f) CHAPTER_SPECS = MANIFEST["chapters"] SYSTEM_PROMPT = f"""You are a master writer blending THREE voices: 1. **SHAH (Idries Shah)** — The storyteller who disarms with humor, then drops the knife. Voice: wry, paradoxical, teaching stories (Nasrudin), direct transmission. "You think you know? Watch." Uses Shah's actual teaching stories from Tales of the Dervishes, Learning How to Learn, The Commanding Self, Knowing How to Know, Caravan of Dreams. 2. **CFO (Modern CFO)** — Numbers-driven, conventional wisdom, "Rich Dad" energy. Voice: "Max the match," "Diversify," "Leverage is free money," "Your 401k is your future." Pragmatic, contrarian in a business sense. 3. **NARRATOR (Achebe Oral Tradition)** — Sets the scene. Oral rhythm, proverbs, the land speaks, objects carry memory, communal voice. "The land speaks. The market speaks. The algorithm speaks." WRITING STYLE — KIYOSAKI × SHAH × ACHEBE: 1. **HOOK (100 words)**: Scene with Shah's teaching story. Concrete. Visceral. The story IS the entry point. 2. **SHAH/CFO DIALOGUE (400 words)**: Rapid-fire exchange. Shah tells the story / drops the paradox. CFO gives conventional wisdom. 6-8 exchanges. "SHAH: ... CFO: ... SHAH: ... CFO: ..." 3. **THE FRAMEWORK (500 words)**: Visual quadrant/diagram described in text. "Draw four boxes. Label them..." Shah's story maps to Kiyosaki's visual framework. Four boxes. Arrows. Labels. Why this geometry matters. 3. **THE LIE WE'RE TOLD (300 words)**: Bold, contrarian. "THE LIE: [conventional wisdom]. THE TRUTH: [Shah's paradox / Kiyosaki's contrarian take]." Punchy. Punchy. Punchy. 4. **THE PROTOCOL (300 words)**: Exactly 3 steps. Numbered. Actionable THIS WEEK. "STEP 1: ... STEP 2: ... STEP 3: ..." Kiyosaki's action-oriented. 5. **SHAH/CFO FINAL WORD (150 words)**: SHAH: [final paradox]. CFO: [final pragmatic takeaway]. Short. Punchy. Memorable. 6. **REFLECTION (100 words)**: One piercing question. "What..." or "Where..." or "When..." Uncomfortable. Actionable. VOICE RULES: - Short sentences. Fragments encouraged. Repetition as rhythm. - "SHAH:" / "CFO:" — every exchange labeled. - Diagrams described in text: "Draw four boxes. Label them..." - Bold assertions: "Your attention is not yours." "The menu is not the meal." - Kiyosaki catchphrases Shah-ized: "Savers are losers" → "Consumers are losers," "Mind your own business" → "Mind your own shadow," "Rich don't work for money" → "Believers work for barakah." - Shah's humor preserved — Nasrudin's absurdity as the entry point. - NO academic tone. NO flowery prose. Punchy. Practical. Provocative. - Audience: Muslim professionals, entrepreneurs, high earners feeling the spiritual void in the digital age. TARGET: ~2,000 words per chapter (Hook 100 + Dialogue 400 + Framework 500 + Lie 300 + Protocol 300 + Final Word 150 + Reflection 100 = ~2,000) """ # Build prompts from manifest CHAPTER_PROMPTS_PART1 = {} CHAPTER_PROMPTS_PART2 = {} for spec in MANIFEST["chapters"]: cid = spec["id"] CHAPTER_PROMPTS_PART1[cid] = f"""Write the FIRST HALF of Chapter {cid}: "{spec['title']}" — {spec['subtitle']} FRAMEWORK: {spec['framework']} SHAH'S STORY (use this exact story as the hook): {spec['shah_story']} CFO's HOOK (use this exact hook): {spec['cfo_hook']} PART 1 STRUCTURE (target ~1,200 words): 1. HOOK (~100 words): Use SHAH'S STORY exactly as written. Then CFO's hook as counterpoint. 2. SHAH/CFO DIALOGUE (~400 words): Rapid exchange. SHAH tells the story / drops the paradox. CFO gives conventional wisdom. Format: SHAH: [Shah's story insight / paradox] CFO: [conventional wisdom / business frame] SHAH: [deeper paradox] CFO: [pushback / practical concern] ... 6-8 exchanges total. 3. THE FRAMEWORK (~500 words): Describe the visual framework: {spec['framework']} "Draw four boxes. Label them..." Explain each quadrant. Arrows between them. Why this geometry matters. Map Shah's story to the framework. Map CFO's worldview to the framework. OUTPUT ONLY PART 1. No protocol. No reflection. No lie. End after framework explanation.""" CHAPTER_PROMPTS_PART2[cid] = f"""Write the SECOND HALF of Chapter {spec['id']}: "{spec['title']}" — {spec['subtitle']} FRAMEWORK: {spec['framework']} PART 2 STRUCTURE (target ~1,000 words): 4. THE LIE WE'RE TOLD (~300 words): Bold, contrarian. Format: THE LIE: [conventional wisdom in one sentence] THE TRUTH: [Shah's paradox / Kiyosaki's contrarian take in one sentence] Then 2-3 paragraphs unpacking. Use spec['lie'] as anchor: {spec['lie']} 5. THE PROTOCOL (~300 words): Exactly 3 steps. Numbered. Actionable THIS WEEK. Format: STEP 1: [Specific action with timeframe] STEP 2: [Specific action with timeframe] STEP 3: [Specific action with timeframe] Based on spec['protocol']: {spec['protocol']} 6. SHAH/CFO FINAL WORD (~150 words): SHAH: [Final paradox / Shah's parting wisdom] CFO: [Final pragmatic takeaway / Kiyosaki-style action] Short. Punchy. Memorable. 7. REFLECTION (~100 words): One piercing question. Start with "What..." or "Where..." or "When..." Make it uncomfortable. Make it actionable. OUTPUT ONLY PART 2. No hook. No dialogue. No framework. Start with '## THE LIE WE'RE TOLD'.""" def call_api(prompt, max_tokens=2800): data = { "model": "deepseek-v4-flash", "messages": [ {"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": prompt} ], "temperature": 0.85, "max_tokens": max_tokens } headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", "User-Agent": "curl/7.88.1" } req = urllib.request.Request(API_URL, data=json.dumps(data).encode(), headers=headers) with urllib.request.urlopen(req, timeout=90) as resp: return json.loads(resp.read())["choices"][0]["message"]["content"] if __name__ == "__main__": import argparse parser = argparse.ArgumentParser(description="Generate Shah-Kiyosaki chapters (two-part)") parser.add_argument("chapter", nargs="?", type=int, help="Chapter number (1-10)") parser.add_argument("--part", type=int, choices=[1, 2], help="Part 1 or 2") args = parser.parse_args() if not os.path.exists(OUTPUT_DIR): os.makedirs(OUTPUT_DIR) chapters = [args.chapter] if args.chapter else list(range(1, 11)) parts = [args.part] if args.part else [1, 2] for chap_num in chapters: for part_num in parts: print(f"\n🔄 Chapter {chap_num} Part {part_num}...") prompt = CHAPTER_PROMPTS_PART1[chap_num] if part_num == 1 else CHAPTER_PROMPTS_PART2[chap_num] try: content = call_api(prompt, max_tokens=3000) fname = os.path.join(OUTPUT_DIR, f"Chapter_{chap_num:02d}_Part{part_num}.md") with open(fname, "w", encoding="utf-8") as f: f.write(content) words = len(content.split()) print(f"✅ Chapter {chap_num} Part {part_num} saved — {words} words") except Exception as e: print(f"❌ Error: {e}") time.sleep(3) print("\n✅ Generation complete!")