The Digital Khalifah: Stewardship at Scale — 10 Organizational Sprints, Playbook Style

This commit is contained in:
Hermes Bot
2026-08-06 18:47:47 +08:00
commit d309fa0b65
36 changed files with 6853 additions and 0 deletions
+104
View File
@@ -0,0 +1,104 @@
#!/usr/bin/env python3
"""Upload 'The Digital Khalifah' to BookStack."""
import os, sys, json, subprocess, time, urllib.request
BS_ID = "is2FJhIWpKEIY13qxHsmboYqukpgRn0U"
BS_SECRET = "yQdxQaAKtTatZEeOLAS92umUfRNBqQFq"
BS_BASE = "https://docs.falahos.my/api"
CHAPTERS_DIR = os.path.expanduser("~/odysseus_book/digital_khalifah/chapters")
PDF_PATH = os.path.expanduser("~/odysseus_book/digital_khalifah/pdf/The_Digital_Mujtahid.pdf")
CHAPTERS = [
"Principle #1: The Problem Statement",
"Principle #2: Evidence Gathering",
"Principle #3: Stakeholder Consultation",
"Principle #4: The Product Decision",
"Principle #5: Minimum Viable Principle",
"Principle #6: Technical Debt",
"Principle #7: Pricing",
"Principle #8: Growth Metrics",
"Principle #9: Team Organization",
"Principle #10: Legacy Product",
]
def api_call(method, path, data=None):
url = f"{BS_BASE}/{path}"
headers = {
"Authorization": f"Token {BS_ID}:{BS_SECRET}",
"User-Agent": "curl/7.88.1",
"Content-Type": "application/json",
}
body = json.dumps(data).encode() if data else None
req = urllib.request.Request(url, data=body, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read())
def markdown_to_html(md):
text = md.replace('&', '&').replace('<', '<').replace('>', '>')
parts = text.split('**')
for i in range(1, len(parts), 2):
parts[i] = f'<b>{parts[i]}</b>'
text = ''.join(parts)
parts = text.split('*')
for i in range(1, len(parts), 2):
parts[i] = f'<i>{parts[i]}</i>'
text = ''.join(parts)
text = text.replace('\n', '<br>\n')
return text
def main():
print("📚 Creating BookStack book...")
book_data = {
"name": "The Digital Khalifah: Product Thinking from First Principles",
"description": "Playbook Style — Principle-Driven Product Development. Dual Mentors: Product Lead (Marty Cagan) + Mujtahid (Classical Usul al-Fiqh). 10 Principles for Building Products That Matter. By Jauhari Che Wan.",
"tags": [
{"name": "Series", "value": "Product Lead × Mujtahid Playbook"},
{"name": "Author", "value": "Jauhari Che Wan"},
{"name": "Shelf", "value": "721"}
]
}
result = api_call("POST", "books", book_data)
book_id = result.get("id")
print(f" Book ID: {book_id}")
print("📖 Uploading chapters...")
for i, title in enumerate(CHAPTERS):
fname = f"Principle_0{i+1}.md" if i < 9 else f"Principle_{i+1}.md"
fpath = os.path.join(CHAPTERS_DIR, fname)
if not os.path.exists(fpath):
print(f" WARNING: {fname} not found")
continue
with open(fpath) as f:
content = f.read()
lines = content.split('\n')
body_start = 0
for j, line in enumerate(lines):
if line.startswith('# ') or line.startswith('## ') or line.strip() == '':
continue
else:
body_start = j
break
body = '\n'.join(lines[body_start:])
html_body = markdown_to_html(body)
page_name = f"Principle #{i+1}: {title}"
print(f" Uploading {page_name}...")
data = {
"book_id": book_id,
"name": page_name,
"html": html_body,
"priority": i + 1,
"tags": [{"name": "Part", "value": f"Principle #{i+1}"}]
}
try:
page_result = api_call("POST", "pages", data)
print(f" Page ID: {page_result.get('id')}")
except Exception as e:
print(f" Error: {str(e)[:100]}")
time.sleep(0.3)
print(f"\n✅ BookStack upload complete! Book ID: {book_id}")
if __name__ == "__main__":
main()