#!/usr/bin/env python3 """ Generate "The Digital Waqif: Waqf, Faraid, and the Architecture of Legacy" Dual Mentors: FARADI (Ilm al-Faraid) + WAQIF (Waqf builder) 10 Clauses of the Digital Will & Endowment. Each = Clause → Nass → FARADI → WAQIF → Declaration → Execution → Hisbah Two-part generation per clause to bypass token limits. """ import json, os, sys, time, urllib.request, urllib.error OUTPUT_DIR = os.path.expanduser("~/odysseus_book/digital_waqif/chapters") API_URL = "https://opencode.ai/zen/v1/chat/completions" API_KEY = "sk-jl41MVxfeWRY4ElO7cWXw8ZM6KN5r0S1DG3vK2i1SaUsVdj13ilSxyRdIQLz1Csy" with open(os.path.join(os.path.dirname(__file__), "manifest.json")) as f: MANIFEST = json.load(f) SYSTEM_PROMPT = f"""You are a master writer creating a WILL & TESTAMENT PLAYBOOK in the style of a legal-framework book fused with CLASSICAL ISLAMIC WEALTH LAW (Faraid + Waqf jurisprudence) — written for the digital age. DUAL MENTORS: 1. **FARADI** — Inheritance Jurist (Ilm al-Faraid). Voice: "The shares are not yours to design. God designed them. Your job is execution, not imagination. The fractions are fixed. The justice is in the execution." Frameworks: Surah An-Nisa 4:11-12, 4:176; Ashab al-Furud (fixed-share heirs); Awl and Radd; Wasiyyah 1/3 rule. 2. **WAQIF** — Endowment Architect (Waqf builder). Voice: "Perpetuity is a decision, not a wish. Every great legacy was a clause someone wrote while alive. You can't take it with you — but you can send it ahead." Frameworks: Waqf jurisprudence; Umar's palm grove; Habous tradition; Sadaqah Jariyah; tokenized endowments, on-chain waqf. PLAYBOOK FORMAT — EACH CHAPTER = 1 CLAUSE OF THE DIGITAL WILL & ENDOWMENT: Each clause follows this structure: 1. **THE CLAUSE** (150 words) — The rule stated as a legal clause. "Clause N: ..." Imperative. Cold. Precise. 2. **THE NASS** (200 words) — The Quranic/hadith evidence, quoted and explained plainly. 3. **FARADI'S READING** (300 words) — The inheritance jurist unpacks the justice: who is protected, why the fractions, what breaks. 4. **WAQIF'S READING** (300 words) — The endowment architect unpacks the perpetuity: how to design it, how it outlives you. 5. **THE DECLARATION** (250 words) — The Legacy Principle. Format: Hukm (Ruling), Daleel (Evidence), Maqsad (Purpose), Shurut (Conditions), Munkathirat (Nullifiers). 6. **THE EXECUTION** (200 words) — Exactly 3 steps. Actionable THIS WEEK. Numbered. "STEP 1: ... STEP 2: ... STEP 3: ..." 7. **THE HISBAH** (150 words) — Self-audit. One piercing question. "What dies with you that shouldn't?" WRITING STYLE: - Legal-playbook tone: Precise. Cold. No fluff. "You will. You must. You cannot." - Dual mentor labels: "FARADI:" / "WAQIF:" — every exchange labeled. - Frameworks described visually: "Draw four boxes. Label them..." - Classical terms: Wasiyyah, Faraid, Ashab al-Furud, Awl, Radd, Waqf, Waqif, Mauquf (corpus), Manfa'ah (usufruct), Amil, Wasi (executor), Hisbah, Sadaqah Jariyah, Hifz al-Mal, Kalala. - Digital terms: Seed phrase, multi-sig, cold wallet, dead-man switch, smart contract, oracle problem, DAO, tokenized, domain registrar, SaaS, IP, digital inventory, executor duties. - NO academic tone. NO flowery prose. Punchy. Legal. Provocative. Like a lawyer who happens to be a faqih. - Audience: Muslim founders, crypto holders, business owners, families — people with digital wealth and no plan. TARGET: ~1,550 words per clause total. """ def call_api(prompt, max_tokens=3000): 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"] def part1_prompt(clause): return f"""Write the FIRST HALF of {clause['title']} — {clause['subtitle']} FRAMEWORK: {clause['framework']} PART 1 STRUCTURE (target ~750 words): 1. THE CLAUSE (~150 words): The rule stated as a legal clause. "Clause {clause['id']}: ..." Imperative. Cold. Precise. This is the contract language of the Digital Will. 2. THE NASS (~200 words): Quote and explain the evidence plainly. Nass reference: {clause['nass_prompt']} 3. FARADI'S READING (~300 words): The inheritance jurist unpacks the justice. Faradi reference: {clause['faradi_prompt']} 4. WAQIF'S READING (~300 words): The endowment architect unpacks the perpetuity. Waqif reference: {clause['waqif_prompt']} OUTPUT ONLY PART 1. No Declaration. No Execution. No Hisbah. End after WAQIF'S READING.""" def part2_prompt(clause): return f"""Write the SECOND HALF of {clause['title']} — {clause['subtitle']} FRAMEWORK: {clause['framework']} PART 2 STRUCTURE (target ~800 words): 5. THE DECLARATION (~250 words): The Legacy Principle. Format exactly: **HUKM:** [One-sentence ruling: "We shall ... / You shall ... / The estate shall ..."] **DALEEL:** [Evidence summary — 2-3 sentences] **MAQSAD:** [Purpose — which Maqasid is served: Hifz al-Din/Nafs/Aql/Mal/Nasl] **SHURUT:** [Conditions — 3-4 bullets: success metrics, constraints, execution requirements] **MUNKATHIRAT:** [Nullifiers — 2-3 bullets: what invalidates this clause] 6. THE EXECUTION (~200 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] 7. THE HISBAH (~150 words): Self-audit. One piercing question. Start with "What..." or "Where..." or "When..." Make it uncomfortable. Make it actionable. OUTPUT ONLY PART 2. No Clause. No Nass. No FARADI. No WAQIF. Start with '## THE DECLARATION'.""" if __name__ == "__main__": import argparse parser = argparse.ArgumentParser(description="Generate Digital Waqif Clauses (two-part)") parser.add_argument("clause", nargs="?", type=int, help="Clause 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) clauses = [args.clause] if args.clause else list(range(1, 11)) parts = [args.part] if args.part else [1, 2] for cid in clauses: clause = MANIFEST["clauses"][cid - 1] for part_num in parts: print(f"\n🔄 Clause #{cid} Part {part_num}...") prompt = part1_prompt(clause) if part_num == 1 else part2_prompt(clause) try: content = call_api(prompt, max_tokens=3500) fname = os.path.join(OUTPUT_DIR, f"Clause_{cid:02d}_Part{part_num}.md") with open(fname, "w", encoding="utf-8") as f: f.write(content) words = len(content.split()) print(f"✅ Clause #{cid} Part {part_num} saved — {words} words") except Exception as e: print(f"❌ Error: {e}") time.sleep(3) print("\n✅ Generation complete!")