<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: HYUN SOO LEE</title>
    <description>The latest articles on DEV Community by HYUN SOO LEE (@hyun_soolee_0c4754e81463).</description>
    <link>https://dev.to/hyun_soolee_0c4754e81463</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3864531%2F514d57a2-02e9-4009-b6fa-2af5002e779c.jpg</url>
      <title>DEV Community: HYUN SOO LEE</title>
      <link>https://dev.to/hyun_soolee_0c4754e81463</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hyun_soolee_0c4754e81463"/>
    <language>en</language>
    <item>
      <title>How I Built an Automated Korean Saju (四柱) Content Pipeline with Claude Vision + Python</title>
      <dc:creator>HYUN SOO LEE</dc:creator>
      <pubDate>Mon, 11 May 2026 08:49:35 +0000</pubDate>
      <link>https://dev.to/hyun_soolee_0c4754e81463/how-i-built-an-automated-korean-saju-si-zhu-content-pipeline-with-claude-vision-python-15kk</link>
      <guid>https://dev.to/hyun_soolee_0c4754e81463/how-i-built-an-automated-korean-saju-si-zhu-content-pipeline-with-claude-vision-python-15kk</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnc89hacu06mnr3uman4f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnc89hacu06mnr3uman4f.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Structured Data Trapped in Images
&lt;/h2&gt;

&lt;p&gt;Korean Saju (四柱推命) content is booming. Platforms like Naver, Kakao, and a growing wave of indie astrology apps serve millions of readings per month. But the production bottleneck is brutal: every reading starts with a &lt;strong&gt;manse calendar screenshot&lt;/strong&gt; — a dense image containing the four pillars (年柱/月柱/日柱/時柱), ten-god labels (十星), twelve-stage cycle markers (十二運星), and special stars (神殺) — all rendered as overlapping hanja circles and Korean tags.&lt;/p&gt;

&lt;p&gt;If you want to publish that reading as a long-form blog post, a YouTube script, a dev.to technical explainer, or a Naver blog entry, you have to manually re-read the image, re-type the data, and re-format for each channel. For a small team running 20–30 subjects per month, that is a full-time job before any writing starts.&lt;/p&gt;

&lt;p&gt;This post documents the pipeline I built to fix that — using Claude Vision for structured extraction, a multi-stage prompt chain for content generation, and channel-specific formatters for final output. The Saju reading for SEVENTEEN member Mingyu (戊土 day master, 1997-04-06, male, unknown birth hour) served as the live QA case for the entire system.&lt;/p&gt;




&lt;h2&gt;
  
  
  Pipeline Overview
&lt;/h2&gt;

&lt;p&gt;[Input Form Screenshot]&lt;br&gt;
        ↓&lt;br&gt;
[Claude Vision: Structured Extraction]&lt;br&gt;
        ↓&lt;br&gt;
[Validation Layer: Pillar Consistency Check]&lt;br&gt;
        ↓&lt;br&gt;
[Prompt Chain: Analysis Blocks]&lt;br&gt;
        ↓&lt;br&gt;
[Channel Formatter: dev.to / Naver / YouTube Script]&lt;br&gt;
        ↓&lt;br&gt;
[QA Gate: Guardrail Checks]&lt;br&gt;
        ↓&lt;br&gt;
[Published Output]&lt;/p&gt;

&lt;p&gt;Five stages. Each stage has a defined input schema, output schema, and failure mode. Let me walk through each.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 1 — Claude Vision Extraction
&lt;/h2&gt;

&lt;p&gt;The manse calendar image (&lt;a href="/_engine/assets/longform/2026-05-11/02_manse_calendar_complete.png" class="article-body-image-wrapper"&gt;&lt;img src="/_engine/assets/longform/2026-05-11/02_manse_calendar_complete.png" alt="Saju chart sample"&gt;&lt;/a&gt; &lt;code&gt;02_manse_calendar_complete.png&lt;/code&gt;) contains the following data classes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Subject metadata&lt;/strong&gt;: name, gender, solar date, lunar date, birth hour&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Four pillars&lt;/strong&gt;: 年柱(丁丑), 月柱(甲辰), 日柱(戊寅), 時柱(戊午) — each with hanja characters rendered inside colored circles&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ten-god labels per pillar&lt;/strong&gt;: 年柱 = 正印(정인) / 劫財(겁재), 月柱 = 偏官(편관) / 比肩(비견), 日柱 = 比肩(비견) / 偏官(편관), 時柱 = 比肩(비견) / 正印(정인)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Twelve-stage cycle markers&lt;/strong&gt;: 時柱 = 帝旺(제왕), 日柱 = 長生(장생), 月柱 = 冠帶(관대), 年柱 = 養(양)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Special stars (神殺)&lt;/strong&gt;: 年柱 천을귀인(天乙貴人), 백호살(白虎殺), 화개살(華蓋殺); 月柱 백호살(白虎殺); 時柱 양인살(羊刃殺), 도화살(桃花殺); 日柱 편관(장생)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Current Daewoon (大運)&lt;/strong&gt;: 庚子(경자) — 天干 庚 = 食神(식신), 地支 子 = 正財(정재)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2026 Sewoon (歲運)&lt;/strong&gt;: 丙午(병오) — age 30, 天干 丙 = 食神(식신) marker visible, 地支 午 = 正財(정재) marker visible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The extraction prompt is a single-shot structured JSON request:&lt;/p&gt;

&lt;p&gt;Extract ALL visible hanja characters, Korean ten-god labels,&lt;br&gt;
twelve-stage cycle names, and special star names from this&lt;br&gt;
manse calendar image. Return as JSON with keys:&lt;br&gt;
subject, four_pillars, daewoon, sewoon.&lt;br&gt;
Do NOT infer. Only extract what is visually present.&lt;br&gt;
Flag any character you are less than 90% confident about.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key engineering decision&lt;/strong&gt;: the &lt;code&gt;Flag uncertainty&lt;/code&gt; instruction. Without it, Claude will confidently hallucinate a ten-god label for a pillar where the image is partially obscured. In the Mingyu test case, the birth hour was unknown (모름), so the 時柱 天干 ten-god label was rendered with a placeholder — the extractor correctly flagged this rather than guessing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 2 — Validation Layer
&lt;/h2&gt;

&lt;p&gt;Before any content generation runs, a Python validation script checks internal consistency:&lt;/p&gt;

&lt;p&gt;def validate_pillars(extracted: dict) -&amp;gt; list[str]:&lt;br&gt;
    errors = []&lt;br&gt;
    # Day master must appear in day pillar heavenly stem&lt;br&gt;
    if extracted["day_pillar"]["stem"] != extracted["day_master"]:&lt;br&gt;
        errors.append("Day master mismatch")&lt;br&gt;
    # Ten-god labels must be consistent with day master&lt;br&gt;
    # (simplified: check Friend/比肩 only appears when stem == day master element)&lt;br&gt;
    for pillar in ["year", "month", "hour"]:&lt;br&gt;
        stem = extracted[pillar]["stem"]&lt;br&gt;
        label = extracted[pillar]["stem_god"]&lt;br&gt;
        if not ten_god_consistent(extracted["day_master"], stem, label):&lt;br&gt;
            errors.append(f"{pillar} stem ten-god inconsistent: {stem} / {label}")&lt;br&gt;
    return errors&lt;/p&gt;

&lt;p&gt;In the Mingyu case, the validation caught one edge case: the 2026 Sewoon image shows 庚子 in the Daewoon column and 丙午 in the Sewoon column, but the ten-god markers in the Sewoon column are rendered at a smaller font size and partially overlap the Daewoon column. The extractor initially assigned 食神(식신) to 丙 relative to the 庚 Daewoon stem rather than relative to the 戊 day master. The validator caught the mismatch and re-ran the extraction with an explicit anchor instruction: &lt;strong&gt;always compute ten-god labels relative to the day master stem (日干), not relative to the Daewoon stem.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the single most common error in automated Saju extraction. Build the check before you build anything else.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 3 — Prompt Chain: Analysis Blocks
&lt;/h2&gt;

&lt;p&gt;Once the structured JSON is validated, the content generation runs as a &lt;strong&gt;sequential block chain&lt;/strong&gt;, not a single mega-prompt. Each block receives the validated JSON plus the output of the previous block as context.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Block&lt;/th&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Core structure analysis&lt;/td&gt;
&lt;td&gt;Four pillars JSON&lt;/td&gt;
&lt;td&gt;Five-element ratio, body strength (身强/身弱), yongshin (用神)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Daewoon × Sewoon interaction&lt;/td&gt;
&lt;td&gt;Above + Daewoon/Sewoon JSON&lt;/td&gt;
&lt;td&gt;Clash (冲), combination (合), ten-god activation summary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Domain readings&lt;/td&gt;
&lt;td&gt;Above + domain list&lt;/td&gt;
&lt;td&gt;Career, wealth, relationships, health — each 150–200 tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Risk signals&lt;/td&gt;
&lt;td&gt;Above&lt;/td&gt;
&lt;td&gt;2–3 specific risk patterns with structural basis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Quarterly strategy&lt;/td&gt;
&lt;td&gt;All above&lt;/td&gt;
&lt;td&gt;Q1–Q4 action framing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The Mingyu pipeline produced the following core structural read: 戊土(무토) day master, 土 at 50% of the five-element distribution, 木 25%, 火 25%, 金·水 at 0%. Strong body (身强) structure. 金·水 is the practical yongshin (用神) because 食傷 and 財星 are absent from the main stems and branch primary qi. The current Daewoon 庚子 brings 金·水 energy — structurally favorable — but the 2026 Sewoon 丙午 adds 火·印星 energy that reinforces the already-heavy 土, requiring output regulation rather than expansion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The key prompt engineering rule here&lt;/strong&gt;: each block prompt ends with &lt;code&gt;Return only the analysis for this block. Do not summarize previous blocks. Do not add caveats not supported by the extracted data.&lt;/code&gt; This keeps token usage predictable and prevents the model from hallucinating structural details it did not extract.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 4 — Channel Formatter
&lt;/h2&gt;

&lt;p&gt;The same analysis JSON feeds three formatters in parallel:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;dev.to formatter&lt;/strong&gt; (this article): technical framing, English, markdown headers, code blocks for pipeline logic, manse calendar data cited as structured input rather than mystical oracle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Naver Blog formatter&lt;/strong&gt;: Korean, conversational tone, HTML-compatible line breaks, domain-specific vocabulary (운세, 사주, 대운), no code blocks, CTA pointing to the full reading platform.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;YouTube Script formatter&lt;/strong&gt;: spoken Korean, 8–12 minute target length, hook in first 30 seconds referencing the specific structural pattern (e.g., "土가 절반인 사주에서 2026년에 무슨 일이 생기는지"), chapter markers at each domain block.&lt;/p&gt;

&lt;p&gt;Each formatter has a &lt;strong&gt;channel-specific guardrail list&lt;/strong&gt; appended to the system prompt:&lt;/p&gt;

&lt;p&gt;GUARDRAILS (dev.to):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No fortune-telling framing&lt;/li&gt;
&lt;li&gt;No certainty language (must/will/definitely)&lt;/li&gt;
&lt;li&gt;No privacy speculation&lt;/li&gt;
&lt;li&gt;Cite image source for all data claims&lt;/li&gt;
&lt;li&gt;CTA = runartree.com&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Stage 5 — QA Gate
&lt;/h2&gt;

&lt;p&gt;Before any output is published, an automated QA pass checks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Certainty language scan&lt;/strong&gt;: regex for "반드시", "무조건", "절대", "확실히", "will definitely", "guaranteed" — any match blocks publication&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data consistency check&lt;/strong&gt;: every hanja character in the output must appear in the validated extraction JSON — no hallucinated pillars&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tone check&lt;/strong&gt;: sentiment classifier flags outputs that score above threshold on anxiety-inducing language&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Word count gate&lt;/strong&gt;: channel-specific minimum/maximum&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CTA presence&lt;/strong&gt;: output must contain the CTA URL exactly once&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Mingyu test case passed all five gates on the second run. The first run failed the certainty language scan because the career block used the phrase "성과가 반드시 쌓입니다" — caught, revised to "성과가 쌓이는 흐름입니다."&lt;/p&gt;




&lt;h2&gt;
  
  
  [INFO_GRAPHIC] Mingyu 2026 — Structural Snapshot
&lt;/h2&gt;

&lt;p&gt;Day Master:  戊土 (Strong Earth)  |  Body Strength: 身强&lt;br&gt;
Five Elements: 土50% / 木25% / 火25% / 金·水 0%&lt;br&gt;
Yongshin (用神): 金·Water&lt;/p&gt;

&lt;p&gt;四柱 (Four Pillars):&lt;br&gt;
  年柱: 丁(天乙貴人·白虎殺·華蓋殺) / 丑(劫財·養)&lt;br&gt;
  月柱: 甲(偏官·★) / 辰(比肩·冠帶·白虎殺)&lt;br&gt;
  日柱: 戊 / 寅(偏官·長生)&lt;br&gt;
  時柱: 戊(比肩·羊刃殺·桃花殺) / 午(正印·帝旺)&lt;/p&gt;

&lt;p&gt;Daewoon:  庚子  |  食神 / 正財  |  子↔午 冲, 子↔丑 合&lt;br&gt;
2026 Sewoon:  丙午  |  偏印 / 正印  |  午+午 double-trigger&lt;/p&gt;

&lt;p&gt;Score: 68/100  |  Flow: Upper-Mid&lt;/p&gt;




&lt;h2&gt;
  
  
  The Reversal: 天乙貴人 in 年支
&lt;/h2&gt;

&lt;p&gt;The structural story of this chart is heavy 土, absent 金·Water, strong body — sounds like a closed, self-sufficient system that resists external input. That reading is mostly correct. But the 年支 丑(축) carries 天乙貴人(Heavenly Noble Star), which is the single most reliable "unexpected door opens" marker in classical Saju. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Zi Ping Zhen Quan&lt;/em&gt; (子平真詮, Chapter on Useful Gods) notes that 貴人 stars activate most visibly when the chart is otherwise under pressure — precisely the condition created by the 子↔午 clash in the current Daewoon. The practical pipeline implication: the QA system flags 天乙貴人 as a &lt;strong&gt;positive anomaly&lt;/strong&gt; that must appear in the output, because omitting it would produce a structurally incomplete and tonally misleading read.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Anchor ten-god labels to the day master, always.&lt;/strong&gt; The most common extraction error. Build the validator before the generator.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Block-chain prompts outperform single mega-prompts.&lt;/strong&gt; Smaller, sequential blocks produce more consistent structural logic and are easier to QA.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Unknown birth hour is not a blocker.&lt;/strong&gt; The 時柱 is flagged as uncertain, the analysis runs on the remaining three pillars, and the output notes the limitation explicitly. Do not hallucinate a birth hour.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Channel formatters need their own guardrail lists.&lt;/strong&gt; What is appropriate framing for a technical dev.to post is wrong for a Naver Blog post aimed at a general Korean audience, and vice versa.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. The 午↔午 double-trigger is a real extraction challenge.&lt;/strong&gt; When the 時柱 地支 and the 2026 Sewoon 地支 are identical (both 午), some extractors collapse them into a single entry. The validator must check for this explicitly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Claude Vision extracts structured four-pillar data from manse calendar screenshots; validation anchors all ten-god labels to the day master stem before any content generation runs&lt;/li&gt;
&lt;li&gt;A sequential block-chain prompt architecture produces domain-specific analysis (career, wealth, relationships, health) with traceable structural basis — for Mingyu's 戊土 chart, the 2026 丙午 Sewoon adds 火·印星 pressure to an already 土-heavy structure, making output regulation the core strategic frame&lt;/li&gt;
&lt;li&gt;Channel-specific formatters and a five-gate QA pass convert the same validated JSON into dev.to, Naver Blog, and YouTube Script outputs without manual reformatting&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Want to explore this pipeline or run a reading for your own chart?&lt;/strong&gt;&lt;br&gt;
Full manse calendar generation, structured analysis, and long-form content output are available at &lt;strong&gt;&lt;a href="https://runartree.com" rel="noopener noreferrer"&gt;runartree.com&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article uses a published Saju reading as a technical test case for pipeline documentation purposes. Saju analysis reflects structural pattern interpretation based on classical Chinese metaphysics and does not constitute prediction, guarantee, or professional advice of any kind. All outputs should be read as probabilistic framing, not certainty.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Project link
&lt;/h2&gt;

&lt;p&gt;This article is based on an automated content workflow for a Korean Saju platform.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Website: &lt;a href="https://runartree.com?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=saju_automation" rel="noopener noreferrer"&gt;https://runartree.com?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=saju_automation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Stack: Python, Claude Vision, channel-specific formatting, content QA&lt;/li&gt;
&lt;li&gt;Domain: Korean Saju / Bazi content automation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key lesson is simple: generation alone is not enough. A useful publishing pipeline also needs formatting, QA, tracking links, and channel-specific editorial rules.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Bazi interpretation. Not medical, legal, or investment advice.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>bazi</category>
      <category>kpop</category>
      <category>saju</category>
      <category>korea</category>
    </item>
    <item>
      <title>Building an Automated Saju (Korean Bazi) Content Pipeline: Vision Extraction, Channel Formatting, and QA at Scale</title>
      <dc:creator>HYUN SOO LEE</dc:creator>
      <pubDate>Sun, 10 May 2026 00:00:05 +0000</pubDate>
      <link>https://dev.to/hyun_soolee_0c4754e81463/building-an-automated-saju-korean-bazi-content-pipeline-vision-extraction-channel-formatting-28id</link>
      <guid>https://dev.to/hyun_soolee_0c4754e81463/building-an-automated-saju-korean-bazi-content-pipeline-vision-extraction-channel-formatting-28id</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcmk7e68f4dvbxfmeeeha.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcmk7e68f4dvbxfmeeeha.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Manual Saju Content Doesn't Scale
&lt;/h2&gt;

&lt;p&gt;Korean Saju (四柱, Four Pillars of Destiny) content is exploding across YouTube, blogs, and short-form video. The demand is real. The bottleneck is equally real: every piece of content requires a human practitioner to read a &lt;em&gt;manse&lt;/em&gt; (萬歲曆, traditional calendar chart), extract structured data — Day Pillar (日柱), Ten Gods (十星), 12-phase cycle (十二運星), auspicious and inauspicious spirits (神殺) — and then rewrite that data into channel-appropriate copy.&lt;/p&gt;

&lt;p&gt;For a single subject like a 2026 annual reading, a practitioner might produce:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A long-form YouTube script (~2,500 words)&lt;/li&gt;
&lt;li&gt;A blog post (~1,500 words)&lt;/li&gt;
&lt;li&gt;A short-form vertical video script (~300 words)&lt;/li&gt;
&lt;li&gt;A dev-facing technical breakdown (this article)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Doing that manually for every content subject, every year, every channel, is a full-time job. This post documents the automation pipeline we built at &lt;strong&gt;Runartree&lt;/strong&gt; to solve it.&lt;/p&gt;




&lt;h2&gt;
  
  
  What the Pipeline Actually Does
&lt;/h2&gt;

&lt;p&gt;The pipeline takes two inputs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Screenshot images&lt;/strong&gt; — manse calendar renders, input confirmation screens, and long-form result pages exported from our Saju web app&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A structured content brief&lt;/strong&gt; — subject name, trigger date, topic, channel target, word count, required content blocks&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It outputs &lt;strong&gt;channel-formatted markdown or script copy&lt;/strong&gt;, validated against a QA checklist before it ever reaches a human editor.&lt;/p&gt;

&lt;p&gt;Here is the high-level flow:&lt;/p&gt;

&lt;p&gt;[Screenshot images] → [Claude Vision extraction] → [Structured JSON]&lt;br&gt;
        ↓&lt;br&gt;
[Prompt assembly] → [Claude generation] → [Raw markdown]&lt;br&gt;
        ↓&lt;br&gt;
[QA checks] → [Channel formatter] → [Final output]&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 1: Vision Extraction
&lt;/h2&gt;

&lt;p&gt;The hardest part of the pipeline is not generation — it is &lt;em&gt;reliable structured extraction&lt;/em&gt; from manse calendar screenshots.&lt;/p&gt;

&lt;p&gt;A typical manse image (see &lt;code&gt;02_manse_calendar_complete.png&lt;/code&gt; in our test set) contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Four pillars arranged in columns: 時柱 (Hour), 日柱 (Day), 月柱 (Month), 年柱 (Year)&lt;/li&gt;
&lt;li&gt;Each pillar has: Heavenly Stem (天干) hanja glyph, Earthly Branch (地支) hanja glyph, Ten God label in Korean hangul, 12-phase label in Korean hangul&lt;/li&gt;
&lt;li&gt;Auspicious/inauspicious spirit tags rendered as colored badge chips below each pillar&lt;/li&gt;
&lt;li&gt;A separate column for the current Grand Luck Cycle (大運) and Annual Luck (歲運)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The extraction prompt we use is structured as a two-pass system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pass 1 — Raw OCR with position anchoring:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You are a manse calendar OCR engine.&lt;br&gt;
For each of the six columns (Hour, Day, Month, Year, Grand Luck, Annual Luck):&lt;br&gt;
Extract: heavenly stem hanja, earthly branch hanja,&lt;br&gt;
heavenly stem ten-god label (Korean, verbatim),&lt;br&gt;
earthly branch ten-god label (Korean, verbatim),&lt;br&gt;
12-phase label (Korean, verbatim),&lt;br&gt;
all spirit/神殺 badge labels (Korean, verbatim, with column position).&lt;br&gt;
Return as JSON. Do not translate or interpret. Copy text exactly as rendered.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pass 2 — Verification cross-check:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We re-send the image with the Pass 1 JSON and ask Claude to flag any field where the extracted hanja does not match the visible glyph. This catches common OCR errors like 壬/王 confusion or 己/已 confusion — both of which appear in real manse images.&lt;/p&gt;

&lt;p&gt;For the test subject in this pipeline run (양력 1996년 1월 16일, 여성, 모름시), the verified extraction produced:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;年柱: 乙亥 — 上官(상관) / 比肩(비견)&lt;/li&gt;
&lt;li&gt;月柱: 己丑 — 正官(정관) / 正官(정관)&lt;/li&gt;
&lt;li&gt;日柱: 壬子 — [日主] / 劫財(겁재)&lt;/li&gt;
&lt;li&gt;時柱: 丙午 — 偏財(편재) / 正財(정재)&lt;/li&gt;
&lt;li&gt;Grand Luck (大運): 壬辰 — 比肩(비견) / 偏官(편관)&lt;/li&gt;
&lt;li&gt;Annual Luck 2026 (歲運): 丙午 — 偏財(편재) / 正財(정재)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Extracted 神殺 included: 天醫星(천의성) on Day Branch, 羊刃殺(양인살) on multiple pillars, 鬼門關殺(귀문관살) on Month Branch and Hour Branch, 桃花殺(도화살) on Day Branch, 帝旺(제왕) phase on Day Branch.&lt;/p&gt;

&lt;p&gt;One critical guard in the extraction prompt: &lt;strong&gt;verbatim label preservation&lt;/strong&gt;. If the image renders 正財 on the Hour Branch heavenly stem, the JSON must say 正財 — not 偏財, not "wealth star." Downstream generation prompts are built on this JSON, and a single mislabeled Ten God corrupts the entire interpretation chain.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 2: Structured JSON Schema
&lt;/h2&gt;

&lt;p&gt;After extraction, we normalize into a typed schema:&lt;/p&gt;

&lt;p&gt;@dataclass&lt;br&gt;
class Pillar:&lt;br&gt;
    position: str          # "year" | "month" | "day" | "hour"&lt;br&gt;
    stem_hanja: str        # e.g. "壬"&lt;br&gt;
    branch_hanja: str      # e.g. "子"&lt;br&gt;
    stem_ten_god: str      # verbatim Korean label&lt;br&gt;
    branch_ten_god: str    # verbatim Korean label&lt;br&gt;
    twelve_phase: str      # verbatim Korean label&lt;br&gt;
    spirits: list[str]     # verbatim Korean badge labels&lt;/p&gt;

&lt;p&gt;@dataclass&lt;br&gt;
class ManseChart:&lt;br&gt;
    subject_name: str&lt;br&gt;
    gender: str&lt;br&gt;
    solar_date: str&lt;br&gt;
    lunar_date: str&lt;br&gt;
    pillars: list[Pillar]  # year, month, day, hour&lt;br&gt;
    grand_luck: Pillar&lt;br&gt;
    annual_luck: Pillar&lt;br&gt;
    body_strength: str     # "신강" | "신약"&lt;br&gt;
    element_ratio: dict    # {"水": 40, "火": 25, "土": 25, ...}&lt;/p&gt;

&lt;p&gt;This schema is serialized to JSON and passed directly into generation prompts. No free-text interpretation at this stage. The schema enforces that generation prompts receive only what the image actually contained.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 3: Prompt Strategy for Long-Form Generation
&lt;/h2&gt;

&lt;p&gt;Long-form Saju content has a specific structure that readers expect. We encode this as a &lt;strong&gt;required block manifest&lt;/strong&gt; in the generation prompt:&lt;/p&gt;

&lt;p&gt;Required blocks (in order):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Hook — 3 lines, reference one specific chart element&lt;/li&gt;
&lt;li&gt;One-line conclusion — Day Pillar + dominant Ten God + 2026 Annual Luck&lt;/li&gt;
&lt;li&gt;Bazi principles — cite at least 3 elements: stems, branches, Ten Gods, spirits&lt;/li&gt;
&lt;li&gt;Classical reference — one line from 滴天髓/子平真詮/窮通寶鑑/淵海子平 with source&lt;/li&gt;
&lt;li&gt;Modern interpretation — connect Annual Luck and Grand Luck to subject's domain&lt;/li&gt;
&lt;li&gt;Infographic placeholder — [INFO_GRAPHIC] tag&lt;/li&gt;
&lt;li&gt;Reversal insight — one unexpected interaction (spirit, combination, clash)&lt;/li&gt;
&lt;li&gt;Three-line summary&lt;/li&gt;
&lt;li&gt;CTA — runartree.com&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The generation prompt also carries a &lt;strong&gt;guardrail block&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Guardrails:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No speculation beyond the extracted chart&lt;/li&gt;
&lt;li&gt;No absolute certainty language (100%, definitely, certainly, guaranteed)&lt;/li&gt;
&lt;li&gt;No gossip or personal life assertions&lt;/li&gt;
&lt;li&gt;Disclaimer line required at end&lt;/li&gt;
&lt;li&gt;Use English + hanja notation for all technical terms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This guardrail block is checked post-generation by a separate QA pass (Stage 5).&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 4: Channel Formatting
&lt;/h2&gt;

&lt;p&gt;The same structured JSON and the same generation output get reformatted per channel. The formatter is a simple Python class with per-channel render methods:&lt;/p&gt;

&lt;p&gt;class ChannelFormatter:&lt;br&gt;
    def render_devto(self, content: GeneratedContent) -&amp;gt; str:&lt;br&gt;
        # YAML frontmatter + dev.to markdown&lt;br&gt;
        # Technical framing: pipeline, not fortune-telling&lt;br&gt;
        ...&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def render_blog(self, content: GeneratedContent) -&amp;gt; str:
    # Korean-language long-form
    # Dalbitnaemu tone guidelines applied
    ...

def render_shorts_script(self, content: GeneratedContent) -&amp;gt; str:
    # 300-word vertical video script
    # Hook in first 3 seconds, single CTA
    ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Channel-specific rules are encoded as formatter config, not baked into the generation prompt. This means the same generation output can be reformatted without re-running the expensive Vision + generation steps.&lt;/p&gt;

&lt;p&gt;For dev.to specifically, the formatter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Strips all Korean hangul from body text&lt;/li&gt;
&lt;li&gt;Converts Ten God labels to English + hanja format: Direct Wealth(正財), Indirect Wealth(偏財), etc.&lt;/li&gt;
&lt;li&gt;Ensures frontmatter tags include &lt;code&gt;bazi&lt;/code&gt;, &lt;code&gt;kpop&lt;/code&gt;, &lt;code&gt;saju&lt;/code&gt;, &lt;code&gt;korea&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Inserts the &lt;code&gt;[INFO_GRAPHIC]&lt;/code&gt; block as a placeholder comment for the design team&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Stage 5: QA Checks
&lt;/h2&gt;

&lt;p&gt;Before any output reaches a human editor, it runs through an automated QA checklist:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Required blocks present&lt;/td&gt;
&lt;td&gt;Regex scan for block headers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ten God labels match extracted JSON&lt;/td&gt;
&lt;td&gt;String diff against schema&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Guardrail violations&lt;/td&gt;
&lt;td&gt;Claude classification pass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Word count within ±10% of target&lt;/td&gt;
&lt;td&gt;&lt;code&gt;len(content.split())&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hanja notation format consistent&lt;/td&gt;
&lt;td&gt;Regex: &lt;code&gt;[A-Za-z]+\([^\)]+\)&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No Korean hangul in English-channel output&lt;/td&gt;
&lt;td&gt;Unicode range check &lt;code&gt;\uAC00-\uD7A3&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CTA present&lt;/td&gt;
&lt;td&gt;String search for &lt;code&gt;runartree.com&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Disclaimer present&lt;/td&gt;
&lt;td&gt;String search for disclaimer pattern&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The guardrail violation check deserves special mention. We send the generated text back to Claude with a focused classification prompt:&lt;/p&gt;

&lt;p&gt;Does this text contain any of the following? Answer YES/NO for each:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Absolute certainty language (must, will definitely, 100%)&lt;/li&gt;
&lt;li&gt;Personal life speculation beyond the chart&lt;/li&gt;
&lt;li&gt;Anxiety-inducing predictions without mitigation&lt;/li&gt;
&lt;li&gt;Missing disclaimer&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If any answer is YES, the output is flagged for human review rather than auto-published.&lt;/p&gt;




&lt;h2&gt;
  
  
  [INFO_GRAPHIC]
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Suggested asset: A four-column pillar diagram showing 壬子 Day Pillar at center, 丙午 Annual Luck 2026 on the right, with a red clash arrow between 子 and 午 branches, and a blue reinforcement arrow between 壬 Grand Luck stem and 壬 Day Stem. Labels in English + hanja. Brand colors: Runartree dark navy + gold.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Reversal: The Hour Pillar Clash Is Already in the Chart
&lt;/h2&gt;

&lt;p&gt;Here is the part that surprises most people who look at this chart for the first time.&lt;/p&gt;

&lt;p&gt;The 2026 Annual Luck pillar is 丙午. The Hour Pillar (時柱) of the natal chart is also 丙午 — identical heavenly stem and earthly branch. This means the Annual Luck is not introducing a new energy into the chart: it is &lt;strong&gt;doubling an energy that already exists natively&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When 午(오) appears in both the Hour Branch and the Annual Luck simultaneously, the clash between 午 and the Day Branch 子 is not a single external pressure — it is a resonance effect. The chart's own Hour Pillar amplifies the Annual Luck's clash against the Day Branch. In classical terms this is called 伏吟(복음), a "hidden echo," and it tends to intensify both the opportunity signal (Direct Wealth 正財 activating strongly) and the instability signal (子午沖 destabilizing the daily rhythm) beyond what either factor would produce alone.&lt;/p&gt;

&lt;p&gt;This is why the QA-flagged interpretation for this chart emphasizes energy management over opportunity chasing. The Direct Wealth(正財) and Indirect Wealth(偏財) signals are genuinely strong — but the structural amplification means the cost of overextension is also amplified.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Verbatim extraction is non-negotiable.&lt;/strong&gt; The single most common failure mode in early pipeline versions was the model "correcting" a Ten God label based on its own interpretation rather than copying the image text. A 正財 relabeled as 偏財 produces a fundamentally different interpretation. Solve this with explicit verbatim instructions and a verification pass.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Schema before generation.&lt;/strong&gt; Passing structured JSON to the generation prompt produces dramatically more consistent output than passing image descriptions. The schema enforces boundaries. Free-text descriptions invite hallucination.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Channel formatting is cheap; re-generation is expensive.&lt;/strong&gt; Invest in the formatter layer. A single generation run should feed multiple channels. Re-running Vision + generation because a channel format was wrong is a waste of API budget.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. QA catches what prompts miss.&lt;/strong&gt; Even well-crafted generation prompts occasionally produce guardrail violations. The automated QA pass is not optional — it is the last line before human review.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. The disclaimer is load-bearing.&lt;/strong&gt; In Saju content, the disclaimer is not boilerplate. It is the structural element that separates a content automation pipeline from a prediction service. Every output, every channel, every time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Claude Vision + structured JSON extraction is reliable for manse calendar screenshots when verbatim extraction is enforced and a verification pass is included&lt;/li&gt;
&lt;li&gt;Required block manifests and guardrail blocks in generation prompts produce consistent, channel-appropriate long-form content&lt;/li&gt;
&lt;li&gt;Per-channel formatters decouple generation from presentation, reducing API costs significantly&lt;/li&gt;
&lt;li&gt;Automated QA on block presence, Ten God label consistency, guardrail violations, and word count catches the majority of output failures before human review&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Try the Pipeline Output
&lt;/h2&gt;

&lt;p&gt;The Saju content automation pipeline described in this article powers the readings at &lt;strong&gt;&lt;a href="https://runartree.com" rel="noopener noreferrer"&gt;runartree.com&lt;/a&gt;&lt;/strong&gt;. If you are building content automation in a specialized domain — astrology, numerology, TCM, or any knowledge-dense vertical — the extraction-schema-generation-QA pattern transfers directly.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article describes a content generation pipeline and uses a publicly known public figure's birth data as a technical test case for chart extraction accuracy. All interpretations are generated outputs for pipeline demonstration purposes only. Saju readings are a traditional cultural reference framework and do not constitute predictions, advice, or guaranteed outcomes of any kind.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Project link
&lt;/h2&gt;

&lt;p&gt;This article is based on an automated content workflow for a Korean Saju platform.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Website: &lt;a href="https://runartree.com?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=saju_automation" rel="noopener noreferrer"&gt;https://runartree.com?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=saju_automation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Stack: Python, Claude Vision, channel-specific formatting, content QA&lt;/li&gt;
&lt;li&gt;Domain: Korean Saju / Bazi content automation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key lesson is simple: generation alone is not enough. A useful publishing pipeline also needs formatting, QA, tracking links, and channel-specific editorial rules.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Bazi interpretation. Not medical, legal, or investment advice.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>bazi</category>
      <category>kpop</category>
      <category>saju</category>
      <category>korea</category>
    </item>
    <item>
      <title>How We Built an Automated Korean Saju Content Pipeline with Claude Vision + Python</title>
      <dc:creator>HYUN SOO LEE</dc:creator>
      <pubDate>Sat, 09 May 2026 11:10:30 +0000</pubDate>
      <link>https://dev.to/hyun_soolee_0c4754e81463/how-we-built-an-automated-korean-saju-content-pipeline-with-claude-vision-python-1pjk</link>
      <guid>https://dev.to/hyun_soolee_0c4754e81463/how-we-built-an-automated-korean-saju-content-pipeline-with-claude-vision-python-1pjk</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Famhq4l37y6szsgdm7ma4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Famhq4l37y6szsgdm7ma4.png" alt=" " width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  How We Built an Automated Korean Saju Content Pipeline with Claude Vision + Python
&lt;/h1&gt;

&lt;h2&gt;
  
  
  The Problem: Longform Content at Scale, Without Losing Precision
&lt;/h2&gt;

&lt;p&gt;Korean Saju (四柱, Four Pillars of Destiny) content is structurally rich — each reading contains a natal chart (원국), a current major cycle (대운), an annual cycle (세운), and layered interpretations across career, wealth, relationships, and health. A single public-figure reading can run 3,000–5,000 Korean words, with dozens of named variables: Heavenly Stems (天干), Earthly Branches (地支), Ten Gods (十星), and classical star markers like Heavenly Noble (天乙貴人) or Peach Blossom (桃花殺).&lt;/p&gt;

&lt;p&gt;The manual workflow looked like this: a senior analyst runs the chart → captures screenshots → writes interpretation → editor formats per channel → QA checks for factual drift. That pipeline took 4–6 hours per reading, per channel.&lt;/p&gt;

&lt;p&gt;Our goal: reduce that to under 45 minutes of human time, with zero factual hallucination on the chart data.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Architecture: Four Stages
&lt;/h2&gt;

&lt;p&gt;[Manse Calendar UI] &lt;br&gt;
    → [Claude Vision Extraction] &lt;br&gt;
        → [Prompt Chain Interpretation] &lt;br&gt;
            → [Channel Formatter] &lt;br&gt;
                → [QA Gate] &lt;br&gt;
                    → [Publish]&lt;/p&gt;

&lt;p&gt;Each stage has a distinct responsibility and a distinct failure mode. We'll walk through each.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 1 — Vision Extraction: Reading the Chart Image
&lt;/h2&gt;

&lt;p&gt;The Manse calendar (만세력) is rendered as a UI screenshot, not a structured data export. That means the ground truth for every reading lives in an image.&lt;/p&gt;

&lt;p&gt;We feed four screenshot types into Claude Vision:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Image&lt;/th&gt;
&lt;th&gt;Content&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;01_input_confirm.png&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Name, gender, solar date, birth hour&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;02_manse_calendar_complete.png&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Full four-pillar grid with Ten Gods, 12-phase markers, star markers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;03–06_total_luck_N.png&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Longform interpretation scroll captures&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The extraction prompt is strict and non-inferential:&lt;/p&gt;

&lt;p&gt;Extract exactly what is visible in the image. &lt;br&gt;
Do not infer, translate, or rephrase any character or label.&lt;br&gt;
If the Hour Pillar Heavenly Stem Ten God reads "正財" (Direct Wealth), &lt;br&gt;
output "正財". Do not substitute "偏財".&lt;br&gt;
Output as structured JSON with keys: &lt;br&gt;
  name, gender, solar_date, lunar_date, birth_hour,&lt;br&gt;
  pillars: { year, month, day, hour } each containing &lt;br&gt;
    { stem, branch, stem_god, branch_god, twelve_phase, star_markers[] },&lt;br&gt;
  current_daewoon: { stem, branch, stem_god, branch_god },&lt;br&gt;
  annual_cycle_2026: { stem, branch, stem_god, branch_god, star_markers[] }&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt; In our live case — Kang Daniel (강다니엘), male, solar 1996-12-10, birth hour unknown — the Hour Pillar (時柱) Heavenly Stem is 甲 with Ten God label &lt;strong&gt;正財 (Direct Wealth, 정재)&lt;/strong&gt;. An early prompt version that said "identify the Ten God" without the non-substitution guard produced &lt;strong&gt;偏財 (Indirect Wealth)&lt;/strong&gt; because the model pattern-matched on 甲 relative to 辛 and computed independently. The guard clause eliminated that class of error entirely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Extracted ground truth (live case):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Day Pillar (日柱): 辛(신) / 巳(사) — Ten Gods: 比肩(비견) / 正官(정관)&lt;/li&gt;
&lt;li&gt;Month Pillar (月柱): 庚(경) / 子(자) — Ten Gods: 劫財(겁재) / 食神(식신)&lt;/li&gt;
&lt;li&gt;Year Pillar (年柱): 丙(병) / 子(자) — Ten Gods: 正官(정관) / 食神(식신)&lt;/li&gt;
&lt;li&gt;Hour Pillar (時柱): 甲(갑) / 午(오) — Ten Gods: 正財(정재) / 偏官(편관)&lt;/li&gt;
&lt;li&gt;Current Daewoon: 甲辰(갑진) — 正財(정재) / [辰子 semi-combination, Water reinforcement]&lt;/li&gt;
&lt;li&gt;2026 Annual Cycle: 丙午(병오) — 正官(정관) / 偏官(편관)&lt;/li&gt;
&lt;li&gt;Star markers extracted: 天乙貴人(천을귀인) at Hour Branch 午, 天德貴人(천덕귀인) at Hour Branch 午, 암록(暗祿) at Month Pillar&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Stage 2 — Prompt Chain: Interpretation Without Hallucination
&lt;/h2&gt;

&lt;p&gt;Once the JSON is clean, we run a four-prompt chain. Each prompt receives only the JSON output of the previous stage plus a scoped instruction. No prompt sees the raw image again after Stage 1.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt 1 — Structure Summary&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Given this chart JSON, summarize the structural profile:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Day Master strength (身强/身弱)&lt;/li&gt;
&lt;li&gt;Dominant element distribution&lt;/li&gt;
&lt;li&gt;Ten God concentration (how many 官星, 食傷, 財星, 印星, 比劫)&lt;/li&gt;
&lt;li&gt;Key tensions (충/沖, 합/合, 형/刑 between pillars)
Output: structured summary, no prose yet.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For Kang Daniel: Day Master 辛金 is &lt;strong&gt;身弱 (weak)&lt;/strong&gt; — three 官星 (正官×2 + 偏官×1), two 食傷 (食神×2), zero 印星 in Heavenly Stems. Fire element at ~40%, Water ~30%, Metal ~20%, Wood ~10%, Earth ~0%. Critical tension: 子午沖 (子 in Year/Month Branch vs 午 in Hour Branch).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt 2 — Domain Interpretation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each domain (career, wealth, relationships, health) gets a separate sub-prompt with the structural summary as context. This prevents cross-domain contamination and makes QA easier — each block is independently auditable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt 3 — Annual Cycle Overlay&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Given the structural summary and domain interpretations,&lt;br&gt;
overlay the 2026 annual cycle (丙午).&lt;br&gt;
Identify: which existing pillars does 午 interact with?&lt;br&gt;
What does doubling of 官星 (正官 + 偏官) mean for a 身弱 Day Master?&lt;br&gt;
Do not introduce chart elements not present in the JSON.&lt;/p&gt;

&lt;p&gt;The 2026 overlay is where the most interesting dynamics surface. 丙午 年 means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Heavenly Stem 丙 = 正官 (Direct Officer) relative to 辛 Day Master&lt;/li&gt;
&lt;li&gt;Earthly Branch 午 = 偏官 (Seven Killings) relative to 辛&lt;/li&gt;
&lt;li&gt;午 repeats the Hour Branch, reactivating 天乙貴人 — unexpected support signal in a high-pressure year&lt;/li&gt;
&lt;li&gt;午 clashes with Year Branch 子 and Month Branch 子 (子午沖×2) — environmental disruption to established routines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Prompt 4 — Channel Formatting&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is where the pipeline branches. The same interpreted content gets reformatted per channel spec. Dev.to gets English technical framing. A YouTube script gets a different cadence. A blog post gets Korean prose. The interpretation JSON is the single source of truth; formatting is downstream.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 3 — Channel Formatter
&lt;/h2&gt;

&lt;p&gt;Each channel has a spec file that the formatter reads:&lt;/p&gt;

&lt;p&gt;CHANNEL_SPECS = {&lt;br&gt;
    "devto": {&lt;br&gt;
        "language": "en",&lt;br&gt;
        "format": "markdown",&lt;br&gt;
        "tone": "technical_analytical",&lt;br&gt;
        "word_target": 1500,&lt;br&gt;
        "forbidden": ["fortune_telling_framing", "certainty_language", "gossip"],&lt;br&gt;
        "required_blocks": [&lt;br&gt;
            "hook", "conclusion_one_liner", "bazi_mechanics",&lt;br&gt;
            "classical_citation", "modern_application",&lt;br&gt;
            "infographic_placeholder", "reversal_insight",&lt;br&gt;
            "summary_three_lines", "cta"&lt;br&gt;
        ]&lt;br&gt;
    },&lt;br&gt;
    "youtube_script": { ... },&lt;br&gt;
    "blog_ko": { ... }&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;The formatter prompt receives the interpretation JSON plus the channel spec and produces the final draft. Crucially, it does &lt;strong&gt;not&lt;/strong&gt; re-read the chart — it only formats what the interpretation chain already produced.&lt;/p&gt;




&lt;h2&gt;
  
  
  [INFO_GRAPHIC]
&lt;/h2&gt;

&lt;p&gt;KANG DANIEL — 辛巳 Day Pillar | 2026 丙午 Annual Cycle&lt;/p&gt;

&lt;p&gt;PILLAR GRID&lt;br&gt;
┌──────────┬──────────┬──────────┬──────────┐&lt;br&gt;
│  時柱    │  日柱    │  月柱    │  年柱    │&lt;br&gt;
│  Hour    │  Day     │  Month   │  Year    │&lt;br&gt;
├──────────┼──────────┼──────────┼──────────┤&lt;br&gt;
│  正財    │  比肩    │  劫財    │  正官    │&lt;br&gt;
│  甲 Wood │  辛 Metal│  庚 Metal│  丙 Fire │&lt;br&gt;
│  甲 (갑) │  辛 (신) │  庚 (경) │  丙 (병) │&lt;br&gt;
├──────────┼──────────┼──────────┼──────────┤&lt;br&gt;
│  偏官    │  正官    │  食神    │  食神    │&lt;br&gt;
│  午 Fire │  巳 Fire │  子 Water│  子 Water│&lt;br&gt;
│  午 (오) │  巳 (사) │  子 (자) │  子 (자) │&lt;br&gt;
└──────────┴──────────┴──────────┴──────────┘&lt;/p&gt;

&lt;p&gt;STAR MARKERS: 天乙貴人 + 天德貴人 @ 午 (Hour Branch)&lt;br&gt;
KEY TENSION: 子午沖 (Month/Year Branch vs Hour Branch)&lt;/p&gt;

&lt;p&gt;2026 OVERLAY: 丙午&lt;br&gt;
  Stem 丙 → 正官 (Direct Officer) — opportunity + accountability&lt;br&gt;
  Branch 午 → 偏官 (Seven Killings) — pressure layer&lt;br&gt;
  午 reactivates 天乙貴人 — hidden support signal&lt;br&gt;
  午 triggers 子午沖×2 — routine disruption likely&lt;/p&gt;

&lt;p&gt;DAEWOON: 甲辰 | 甲 → 正財 | 辰子 semi-combination (Water+)&lt;br&gt;
BODY STRENGTH: 身弱 | 官星×3 | 食傷×2 | 印星×0 in Stems&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 4 — QA Gate
&lt;/h2&gt;

&lt;p&gt;Before any content publishes, it passes through a five-check QA gate:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check 1 — Character Fidelity&lt;/strong&gt;&lt;br&gt;
Every Hanja character and Ten God label in the output is compared against the Stage 1 JSON. Any mismatch triggers a block. This is the 正財/偏財 guard at output level.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check 2 — Certainty Language Scan&lt;/strong&gt;&lt;br&gt;
A regex + classifier pass flags phrases like "will definitely," "100%," "certain to," "absolutely." These are replaced with hedged equivalents or flagged for human review.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check 3 — Gossip / Privacy Filter&lt;/strong&gt;&lt;br&gt;
Any sentence containing relationship-status assertions, health diagnoses, or financial predictions stated as fact is flagged. The filter is trained on a small dataset of problematic examples from early drafts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check 4 — Classical Citation Verification&lt;/strong&gt;&lt;br&gt;
If the interpretation chain inserted a classical text citation, the QA step verifies it matches a pre-approved citation library. Fabricated citations are a known LLM failure mode in this domain.&lt;/p&gt;

&lt;p&gt;For reference, a structurally relevant citation for this reading: &lt;em&gt;Zi Ping Zhen Quan&lt;/em&gt; (子平真詮, He Lun Qing, Qing Dynasty) discusses the 身弱 Day Master under heavy 官殺 pressure: the remedy is 印星 support; absent that, energy conservation becomes the primary strategic principle. This maps directly to the 2026 reading's core recommendation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check 5 — Word Count and Block Completeness&lt;/strong&gt;&lt;br&gt;
All nine required blocks must be present. Word count must fall within ±10% of target. Missing blocks or overruns trigger a regeneration request for the specific block, not the full piece.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Reversal: The Star Marker Nobody Expects
&lt;/h2&gt;

&lt;p&gt;The technically interesting finding in this chart — and the one most likely to be missed by a naive extraction — is that 天乙貴人 (Heavenly Noble) sits at the Hour Branch 午, the same branch that 2026's annual cycle repeats.&lt;/p&gt;

&lt;p&gt;In a year where 官星 doubles and 子午沖 fires twice, the conventional read is "high pressure, high cost." The reversal: 午 also reactivates the most powerful support star in the chart. The 2026 annual cycle is not purely adversarial — it also lights up the branch where unexpected assistance and key-moment support are structurally encoded.&lt;/p&gt;

&lt;p&gt;This is the kind of nuance that disappears if the Vision extraction is imprecise (wrong branch assignment) or if the interpretation chain doesn't cross-reference star markers against the annual cycle overlay. It's also the kind of insight that makes the content genuinely useful rather than generically cautionary.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Extraction and interpretation must be strictly separated.&lt;/strong&gt; Any prompt that does both simultaneously will drift. The model will rationalize chart data to fit an interpretation it's already building.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Non-substitution guards are not optional.&lt;/strong&gt; Especially for Ten God labels where the model has strong priors from training data. Explicit negative constraints outperform positive description alone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Channel formatting is the last step, not the first.&lt;/strong&gt; Early versions tried to format while interpreting. Output quality dropped significantly. Separation of concerns applies here exactly as it does in software architecture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. QA is cheaper than correction.&lt;/strong&gt; A five-check gate that blocks 15% of drafts saves more time than editing published content that contains a factual error about a public figure's chart.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Star markers are high-value, low-extraction-rate data.&lt;/strong&gt; They appear as small colored badges in the UI. Without explicit Vision prompting for badge-level detail, they are systematically missed — and they often contain the most analytically interesting information.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Automated Saju content pipeline: Vision extraction → prompt chain → channel formatter → QA gate, with strict separation of concerns at each stage&lt;/li&gt;
&lt;li&gt;The critical engineering challenge is not generation quality but extraction fidelity — wrong Hanja or wrong Ten God label at Stage 1 propagates through every downstream step&lt;/li&gt;
&lt;li&gt;The 2026 reading for this case study surfaces a structurally meaningful reversal (天乙貴人 reactivation in a high-pressure 官星 year) that only appears when star marker extraction is precise and cross-referenced against the annual cycle overlay&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Explore the full Saju content platform and automated reading tools at &lt;a href="https://runartree.com" rel="noopener noreferrer"&gt;runartree.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article uses publicly available birth information and a published Saju reading as a technical case study for content pipeline automation. All interpretations reflect classical Bazi analytical frameworks and are presented as structural analysis, not predictive certainty. Individual outcomes vary and no reading should be treated as a definitive forecast.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Project link
&lt;/h2&gt;

&lt;p&gt;This article is based on an automated content workflow for a Korean Saju platform.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Website: &lt;a href="https://runartree.com?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=saju_automation" rel="noopener noreferrer"&gt;https://runartree.com?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=saju_automation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Stack: Python, Claude Vision, channel-specific formatting, content QA&lt;/li&gt;
&lt;li&gt;Domain: Korean Saju / Bazi content automation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key lesson is simple: generation alone is not enough. A useful publishing pipeline also needs formatting, QA, tracking links, and channel-specific editorial rules.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Bazi interpretation. Not medical, legal, or investment advice.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>bazi</category>
      <category>kpop</category>
      <category>saju</category>
      <category>korea</category>
    </item>
    <item>
      <title>How I Built an Automated Korean Saju Content Pipeline with Claude Vision and Python</title>
      <dc:creator>HYUN SOO LEE</dc:creator>
      <pubDate>Fri, 08 May 2026 08:39:29 +0000</pubDate>
      <link>https://dev.to/hyun_soolee_0c4754e81463/how-i-built-an-automated-korean-saju-content-pipeline-with-claude-vision-and-python-25fn</link>
      <guid>https://dev.to/hyun_soolee_0c4754e81463/how-i-built-an-automated-korean-saju-content-pipeline-with-claude-vision-and-python-25fn</guid>
      <description>&lt;h1&gt;
  
  
  How I Built an Automated Korean Saju Content Pipeline with Claude Vision and Python
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; I needed to produce structured, channel-specific long-form content about Korean Saju (四柱推命) at scale. Instead of manually reading manse calendar screenshots and writing drafts by hand, I built a Python pipeline that ingests calendar images, extracts structured pillar data via Claude Vision, runs a multi-stage prompt chain, enforces channel formatting rules, and passes output through a QA gate before publishing. Here is exactly how it works.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  1. The Problem
&lt;/h2&gt;

&lt;p&gt;Korean Saju content — destiny analysis based on the Four Pillars of Birth (年柱·月柱·日柱·時柱) — is inherently data-dense. A single reading involves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Six data columns&lt;/strong&gt; (year, month, day, hour, current major cycle, annual cycle) each carrying a Heavenly Stem (天干), Earthly Branch (地支), a Ten-God relationship (十星), a 12-Phase life stage (十二運星), and one or more auspicious/inauspicious markers (神殺).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Derived structural judgments&lt;/strong&gt; — chart strength (身强/身弱), dominant element distribution, repeating branch patterns (e.g., 午午午 triple resonance across day branch, hour branch, and annual branch).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Channel-specific tone&lt;/strong&gt; — a dev.to audience wants technical framing; a YouTube audience wants narrative; a Naver Blog audience wants bullet-point summaries with score tables.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Doing this manually meant: open the manse calendar app, screenshot six columns, re-read every glyph, write a 1500-word draft, reformat for the target channel, QA for factual consistency, then publish. For one subject that takes roughly three hours. At any meaningful content volume, that is not viable.&lt;/p&gt;

&lt;p&gt;The goal: reduce human time-on-task to &lt;strong&gt;prompt review + final approval&lt;/strong&gt;, with the machine handling extraction, structuring, drafting, and format enforcement.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foxgrw8nh5t52rf8spjmr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foxgrw8nh5t52rf8spjmr.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Pipeline Overview
&lt;/h2&gt;

&lt;p&gt;[Manse Calendar App]&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
[Screenshot Capture Layer]   ← 4–6 PNG files per subject&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
[Claude Vision Extraction]   ← Structured JSON: pillars, ten-gods, 12-phase,神殺&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
[Validation &amp;amp; Normalisation] ← Python: cross-check stem/branch consistency&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
[Prompt Chain: Draft Generation] ← Multi-block long-form prompt&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
[Channel Formatter]          ← dev.to / YouTube script / Naver Blog&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
[QA Gate]                    ← Hallucination checks, forbidden phrase scan&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
[Output: Markdown / SRT / HTML]&lt;/p&gt;

&lt;p&gt;Each stage is a discrete Python module. Stages are orchestrated by a simple &lt;code&gt;pipeline.py&lt;/code&gt; that passes a shared &lt;code&gt;subject_context&lt;/code&gt; dict through each step.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Screenshot Ingestion and Vision Extraction
&lt;/h2&gt;

&lt;p&gt;The manse calendar app outputs visual data, not an API. That means the entry point is always image files. For a typical subject the capture set looks like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;Content&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;01_input_confirm.png&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Name, gender, solar date, birth hour status&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;02_manse_calendar_complete.png&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Full four-pillar grid with ten-gods, 12-phase, 神殺 badges&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;03_total_luck_1.png&lt;/code&gt; – &lt;code&gt;06_total_luck_4.png&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Long-form luck analysis text blocks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The Vision extraction prompt is the most critical piece of the entire pipeline. A poorly specified extraction prompt produces plausible-sounding but wrong data — and because Saju analysis is deterministic (given a birth date and gender, every pillar value is fixed), any extraction error propagates as a factual error into every downstream output.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Extraction prompt design principles I learned the hard way:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ask for exact glyph transcription, not interpretation.&lt;/strong&gt; The prompt says: &lt;em&gt;"Transcribe the Korean hangul label exactly as it appears in the image. If the image shows 정재, output 정재. Do not substitute 편재."&lt;/em&gt; This sounds obvious but early versions of the prompt were silently correcting what the model thought were inconsistencies — e.g., flipping a Direct Wealth (正財) label to Indirect Wealth (偏財) because the stem looked like a 偏財 stem to the model. That is catastrophic for downstream accuracy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Extract position metadata.&lt;/strong&gt; The output JSON includes not just the value but where it appears: &lt;code&gt;{"column": "hour", "layer": "ten_god_stem", "value": "편재"}&lt;/code&gt;. This lets the validation layer catch cross-column inconsistencies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Separate extraction from interpretation.&lt;/strong&gt; The Vision call only extracts. It does not judge chart strength, does not infer relationships between pillars, does not produce prose. That happens in the next stage.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Sample extraction output (simplified):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;{&lt;br&gt;
  "subject": { "name": "Jang Won-young", "gender": "female", "solar_birth": "2004-08-31", "birth_hour": "unknown" },&lt;br&gt;
  "pillars": {&lt;br&gt;
    "year":  { "stem": "甲", "branch": "申", "stem_ten_god": "식신", "branch_ten_god": "편인", "twelve_phase": "장생", "spirits": ["역마살", "공망"] },&lt;br&gt;
    "month": { "stem": "壬", "branch": "申", "stem_ten_god": "비견", "branch_ten_god": "편인", "twelve_phase": "장생", "spirits": ["월덕귀인", "역마살", "공망"] },&lt;br&gt;
    "day":   { "stem": "壬", "branch": "午", "stem_ten_god": "비견", "branch_ten_god": "정재", "twelve_phase": "태",   "spirits": ["원덕귀인"] },&lt;br&gt;
    "hour":  { "stem": "丙", "branch": "午", "stem_ten_god": "편재", "branch_ten_god": "정재", "twelve_phase": "태",   "spirits": ["월공", "양인살"] }&lt;br&gt;
  },&lt;br&gt;
  "major_cycle": { "stem": "庚", "branch": "午", "stem_ten_god": "편인", "branch_ten_god": "정재", "age": 18 },&lt;br&gt;
  "annual_cycle_2026": { "stem": "丙", "branch": "午", "stem_ten_god": "편재", "branch_ten_god": "정재" }&lt;br&gt;
}&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Validation and Normalisation
&lt;/h2&gt;

&lt;p&gt;Before any prose generation touches this data, a Python validation pass runs three checks:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check 1 — Stem/branch consistency.&lt;/strong&gt; Given the day master (日主) stem, every ten-god label is mathematically deterministic. The validator recomputes expected ten-god values from the stem and flags any mismatch between the computed value and the extracted label. If Vision extracted a label that contradicts the stem relationship, the pipeline halts and logs a &lt;code&gt;EXTRACTION_CONFLICT&lt;/code&gt; error for human review.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check 2 — Branch repetition detection.&lt;/strong&gt; The validator scans all six branch slots (four pillars + major cycle branch + annual cycle branch) and flags any branch that appears three or more times. In this subject's case, 午 appears in day branch, hour branch, major cycle branch, and 2026 annual cycle branch — a four-way resonance that is structurally significant and needs to be called out explicitly in the draft prompt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check 3 — Forbidden phrase pre-check.&lt;/strong&gt; A list of absolute-prohibition strings (&lt;code&gt;["반드시", "확실히", "무조건", "절대", "100%"]&lt;/code&gt; and their English equivalents) is checked against any text fields extracted from the long-form image blocks. If found, those segments are flagged for tone adjustment before they enter the draft prompt context.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Prompt Strategy for Draft Generation
&lt;/h2&gt;

&lt;p&gt;The draft generation stage uses a structured multi-block prompt. The key design decision is &lt;strong&gt;block-level responsibility&lt;/strong&gt;: each named section of the output is generated with its own instruction context, rather than asking the model to produce everything in one pass.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Block map:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Block&lt;/th&gt;
&lt;th&gt;Instruction focus&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Hook (3 lines)&lt;/td&gt;
&lt;td&gt;Lead with the structurally most surprising fact from the extracted data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One-line thesis&lt;/td&gt;
&lt;td&gt;Day master + dominant ten-god + 2026 annual cycle, no hedging&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mechanics section&lt;/td&gt;
&lt;td&gt;Cite at least 3 ten-gods or 神殺 with positional context&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Classical reference&lt;/td&gt;
&lt;td&gt;One line from 滴天髓 / 子平真詮 / 窮通寶鑑 / 淵海子平 with source&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Modern application&lt;/td&gt;
&lt;td&gt;Map the trigger subject's known public activity domain to the annual cycle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Infographic block&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;[INFO_GRAPHIC]&lt;/code&gt; placeholder for the design pipeline to fill&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reversal paragraph&lt;/td&gt;
&lt;td&gt;One counter-intuitive finding — a 神殺 or branch combination that cuts against the dominant narrative&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3-line summary&lt;/td&gt;
&lt;td&gt;Compress the entire reading to three sentences&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CTA&lt;/td&gt;
&lt;td&gt;Injected by the formatter, not by the draft prompt&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The prompt explicitly instructs the model: &lt;em&gt;"You are working from extracted structured data. Do not invent pillar values. Do not infer birth details not present in the extraction JSON. If a field is marked 'unknown' (e.g., birth hour), treat the hour pillar as provided and do not speculate about alternative hour values."&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Channel Formatter
&lt;/h2&gt;

&lt;p&gt;The same structured draft gets reformatted by a channel-specific formatter module. Each formatter is a Python class with a &lt;code&gt;transform(draft: str, context: dict) -&amp;gt; str&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;dev.to formatter rules:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Output valid Markdown with YAML frontmatter&lt;/li&gt;
&lt;li&gt;Tags drawn from a controlled vocabulary (&lt;code&gt;bazi&lt;/code&gt;, &lt;code&gt;kpop&lt;/code&gt;, &lt;code&gt;saju&lt;/code&gt;, &lt;code&gt;korea&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;No code fences wrapping the entire document&lt;/li&gt;
&lt;li&gt;Hanja terms rendered inline with English gloss: &lt;code&gt;Indirect Wealth(偏財)&lt;/code&gt;, &lt;code&gt;Goat Blade(羊刃殺)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;All Korean hangul stripped from final output; terminology expressed in English + hanja only&lt;/li&gt;
&lt;li&gt;Target word count: 1400–1600 words; formatter trims or expands the reversal and mechanics sections to hit range&lt;/li&gt;
&lt;li&gt;CTA block appended from a template string, not from the draft&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;YouTube script formatter rules (different module):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Output plain text with &lt;code&gt;[PAUSE]&lt;/code&gt; and &lt;code&gt;[B-ROLL: X]&lt;/code&gt; markers&lt;/li&gt;
&lt;li&gt;Hangul preserved for on-screen text overlays&lt;/li&gt;
&lt;li&gt;Sentences capped at 18 words for teleprompter pacing&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  7. QA Gate
&lt;/h2&gt;

&lt;p&gt;The QA gate runs after formatting and before any publish call. It is not a model call — it is a deterministic rule engine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rules that cause a BLOCK (pipeline halts):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Any ten-god label in the output that contradicts the validation JSON (e.g., output says "Direct Wealth(正財)" in the hour stem position but the JSON says &lt;code&gt;편재&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Any of the forbidden certainty phrases present in the output&lt;/li&gt;
&lt;li&gt;Word count outside ±15% of target&lt;/li&gt;
&lt;li&gt;Missing required blocks (checked by scanning for section header strings)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Rules that cause a WARN (logged, human reviews before publish):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Classical reference citation present but source tag missing&lt;/li&gt;
&lt;li&gt;Infographic placeholder &lt;code&gt;[INFO_GRAPHIC]&lt;/code&gt; not replaced by the design pipeline&lt;/li&gt;
&lt;li&gt;Subject name appears in a sentence with a romantic or health-definitive predicate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The QA gate rejects roughly 8–12% of drafts on first pass, almost always due to a ten-god label drift introduced during the channel formatting step (the formatter's length-adjustment logic occasionally paraphrases a term incorrectly).&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Lessons Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Extraction fidelity is the entire foundation.&lt;/strong&gt; Every downstream error I have traced has originated in the Vision extraction stage, not in the draft generation stage. Investing in extraction prompt specificity — including explicit anti-correction instructions — pays back more than any amount of draft prompt tuning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deterministic validation beats probabilistic correction.&lt;/strong&gt; It is tempting to add a "correction" prompt that asks the model to fix inconsistencies in extracted data. Do not do this. The model will produce plausible corrections that are sometimes wrong in ways that are very hard to catch. Halt on conflict and route to human review instead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Branch repetition is a structural signal, not noise.&lt;/strong&gt; When the same Earthly Branch appears four times across the pillar set and both cycle slots, that is not a coincidence to mention in passing — it is the structural centre of the reading. The pipeline now explicitly flags multi-resonance patterns and instructs the draft prompt to build the mechanics section around them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Channel formatting should never touch content semantics.&lt;/strong&gt; The formatter's job is structure and length, not meaning. Any formatter logic that could alter a ten-god label, a 神殺 name, or a classical citation needs to be moved upstream into the draft prompt or blocked entirely.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. What This Produces
&lt;/h2&gt;

&lt;p&gt;To illustrate the pipeline end-to-end, here is the kind of structured output it generates. For a subject with Day Master 壬水(Im-su / Deep Water), chart structure 身强(Shin-gang / Strong Chart), current major cycle 庚午(Gyeong-o) carrying Indirect Wealth(偏印) over Direct Wealth(正財), and 2026 annual cycle 丙午(Byeong-o) carrying Indirect Wealth(偏財) over Direct Wealth(正財):&lt;/p&gt;

&lt;p&gt;The pipeline correctly identifies that the 午 branch appearing in the day branch, hour branch, major cycle branch, and annual cycle branch simultaneously creates a four-layer resonance on the Direct Wealth(正財) position — the structural centre of the 2026 reading. It flags the Heavenly Noble(天乙貴人) marker on the month pillar as the reversal element (unexpected support arriving in high-pressure periods). It applies the Goat Blade(羊刃殺) marker on the hour pillar as a caution flag for the health and overextension blocks. And it correctly preserves the Empty Void(空亡) markers on both the year and month branches without over-interpreting them as absolute negatives.&lt;/p&gt;

&lt;p&gt;The QA gate passes the output. The formatter hits 1,487 words. Total machine time from image input to publish-ready Markdown: under 90 seconds.&lt;/p&gt;




&lt;h2&gt;
  
  
  [INFO_GRAPHIC]
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;2026 Pillar Snapshot — 壬水 Day Master&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pillar&lt;/th&gt;
&lt;th&gt;Stem&lt;/th&gt;
&lt;th&gt;Branch&lt;/th&gt;
&lt;th&gt;Stem Ten-God&lt;/th&gt;
&lt;th&gt;Branch Ten-God&lt;/th&gt;
&lt;th&gt;Key Marker&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Year(年柱)&lt;/td&gt;
&lt;td&gt;甲&lt;/td&gt;
&lt;td&gt;申&lt;/td&gt;
&lt;td&gt;Eating God(食神)&lt;/td&gt;
&lt;td&gt;Indirect Wealth(偏印)&lt;/td&gt;
&lt;td&gt;Empty Void(空亡)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Month(月柱)&lt;/td&gt;
&lt;td&gt;壬&lt;/td&gt;
&lt;td&gt;申&lt;/td&gt;
&lt;td&gt;Friend(比肩)&lt;/td&gt;
&lt;td&gt;Indirect Wealth(偏印)&lt;/td&gt;
&lt;td&gt;Heavenly Noble(天乙貴人)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Day(日柱)&lt;/td&gt;
&lt;td&gt;壬&lt;/td&gt;
&lt;td&gt;午&lt;/td&gt;
&lt;td&gt;Friend(比肩)&lt;/td&gt;
&lt;td&gt;Direct Wealth(正財)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hour(時柱)&lt;/td&gt;
&lt;td&gt;丙&lt;/td&gt;
&lt;td&gt;午&lt;/td&gt;
&lt;td&gt;Indirect Wealth(偏財)&lt;/td&gt;
&lt;td&gt;Direct Wealth(正財)&lt;/td&gt;
&lt;td&gt;Goat Blade(羊刃殺)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Major Cycle&lt;/td&gt;
&lt;td&gt;庚&lt;/td&gt;
&lt;td&gt;午&lt;/td&gt;
&lt;td&gt;Indirect Wealth(偏印)&lt;/td&gt;
&lt;td&gt;Direct Wealth(正財)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026 Annual&lt;/td&gt;
&lt;td&gt;丙&lt;/td&gt;
&lt;td&gt;午&lt;/td&gt;
&lt;td&gt;Indirect Wealth(偏財)&lt;/td&gt;
&lt;td&gt;Direct Wealth(正財)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Vision extraction with explicit anti-correction instructions&lt;/strong&gt; is the single highest-leverage investment in a Saju content pipeline — garbage in, garbage out applies with unusual force when the source data is deterministic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic validation before any generative step&lt;/strong&gt; catches the errors that probabilistic models will confidently paper over.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Channel formatters should be semantically inert&lt;/strong&gt; — length and structure only, never meaning.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;em&gt;Want to explore the full reading this pipeline produced, or see how the branch-resonance and 神殺 pattern analysis maps to a specific public figure's 2026 trajectory? The complete interactive manse calendar and long-form analysis are available at &lt;a href="https://runartree.com" rel="noopener noreferrer"&gt;runartree.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article discusses Saju (四柱) as a structured content domain for automation purposes. All interpretations derived from the pipeline are probabilistic pattern analyses based on classical Chinese metaphysical frameworks and should not be treated as predictive certainties or professional advice of any kind.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Project link
&lt;/h2&gt;

&lt;p&gt;This article is based on an automated content workflow for a Korean Saju platform.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Website: &lt;a href="https://runartree.com?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=saju_automation" rel="noopener noreferrer"&gt;https://runartree.com?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=saju_automation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Stack: Python, Claude Vision, channel-specific formatting, content QA&lt;/li&gt;
&lt;li&gt;Domain: Korean Saju / Bazi content automation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key lesson is simple: generation alone is not enough. A useful publishing pipeline also needs formatting, QA, tracking links, and channel-specific editorial rules.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Bazi interpretation. Not medical, legal, or investment advice.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>bazi</category>
      <category>kpop</category>
      <category>saju</category>
      <category>korea</category>
    </item>
    <item>
      <title>How I Built an Automated Korean Saju Content Pipeline with Claude Vision and Python</title>
      <dc:creator>HYUN SOO LEE</dc:creator>
      <pubDate>Thu, 07 May 2026 08:44:15 +0000</pubDate>
      <link>https://dev.to/hyun_soolee_0c4754e81463/how-i-built-an-automated-korean-saju-content-pipeline-with-claude-vision-and-python-boh</link>
      <guid>https://dev.to/hyun_soolee_0c4754e81463/how-i-built-an-automated-korean-saju-content-pipeline-with-claude-vision-and-python-boh</guid>
      <description>&lt;h2&gt;
  
  
  The Problem: Manual Fortune-Content at Scale Is Broken
&lt;/h2&gt;

&lt;p&gt;Korean Saju (四柱, Bazi) content is one of the highest-engagement niches on YouTube Korea right now. But the production pipeline is almost entirely manual: a practitioner reads a chart, writes a script by hand, records, edits, and publishes — then repeats for every subject and every channel format.&lt;/p&gt;

&lt;p&gt;When I started building &lt;strong&gt;Dalbit Namu (달빛나무)&lt;/strong&gt;, the goal was to automate everything except the core interpretive logic. The content domain is Saju. The engineering problem is: how do you take a Manse Calendar screenshot, extract structured chart data reliably, generate a 10-minute script that passes editorial QA, and reformat it for five different channels — without hallucinating chart details or making claims the data does not support?&lt;/p&gt;

&lt;p&gt;This post documents the full pipeline, the prompt architecture, the QA layer, and the lessons learned. I use the &lt;strong&gt;2026 Jimin (BTS) Saju analysis&lt;/strong&gt; as the live production example because it was the most complex test case: unknown birth time, high-profile subject, strict editorial guardrails.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl47aweivtticfmcc2bki.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl47aweivtticfmcc2bki.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pipeline Overview
&lt;/h2&gt;

&lt;p&gt;[Input Form] → [Vision Extraction] → [Structured JSON] → [Interpretation Engine]&lt;br&gt;
     → [Script Generator] → [QA Checker] → [Channel Formatter] → [Publish]&lt;/p&gt;

&lt;p&gt;Five stages, each with its own failure mode.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 1 — Vision Extraction: Reading the Manse Calendar
&lt;/h2&gt;

&lt;p&gt;The Manse Calendar (萬歲曆) image is the single source of truth. Everything downstream depends on reading it correctly.&lt;/p&gt;

&lt;p&gt;![Manse Calendar extracted from 02_manse_calendar_complete.png — Day Pillar 丁丑, Month Pillar 丙戌, Year Pillar 乙亥, Hour Pillar 丙午, Current Grand Luck 壬午, 2026 Annual Luck 丙午]&lt;/p&gt;

&lt;p&gt;I pass the calendar screenshot directly to &lt;strong&gt;Claude claude-sonnet-4 Vision&lt;/strong&gt; with a structured extraction prompt. The prompt enforces strict field-by-field output:&lt;/p&gt;

&lt;p&gt;Extract the following fields exactly as displayed in the image.&lt;br&gt;
Do NOT infer, translate, or substitute characters.&lt;br&gt;
Output JSON only.&lt;/p&gt;

&lt;p&gt;Fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;name, gender, solar_birthday, birth_hour&lt;/li&gt;
&lt;li&gt;four_pillars: [year, month, day, hour] × {heavenly_stem, earthly_branch}&lt;/li&gt;
&lt;li&gt;ten_gods: [year, month, day, hour] × {stem_god, branch_god}&lt;/li&gt;
&lt;li&gt;twelve_phases: [year, month, day, hour] × phase_name&lt;/li&gt;
&lt;li&gt;spirit_stars: each star with pillar location&lt;/li&gt;
&lt;li&gt;grand_luck: {stem, branch, stem_god, branch_god}&lt;/li&gt;
&lt;li&gt;annual_luck_2026: {stem, branch, stem_god, branch_god}&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The critical guardrail here:&lt;/strong&gt; the prompt explicitly says "do NOT substitute." In early iterations, the model would silently correct what it thought were OCR errors — changing 劫財 (Robber, 겁재) to 比肩 (Friend, 비견) because they look similar in small font. Adding &lt;code&gt;"If you are uncertain about a character, output the character you see followed by [UNCERTAIN]"&lt;/code&gt; reduced silent substitution errors by roughly 80%.&lt;/p&gt;

&lt;h3&gt;
  
  
  Extracted output for Jimin's chart (2026-05-07 run):
&lt;/h3&gt;

&lt;p&gt;{&lt;br&gt;
  "name": "Jimin",&lt;br&gt;
  "gender": "male",&lt;br&gt;
  "solar_birthday": "1995-10-13",&lt;br&gt;
  "birth_hour": "unknown",&lt;br&gt;
  "four_pillars": {&lt;br&gt;
    "year":  { "stem": "乙", "branch": "亥" },&lt;br&gt;
    "month": { "stem": "丙", "branch": "戌" },&lt;br&gt;
    "day":   { "stem": "丁", "branch": "丑" },&lt;br&gt;
    "hour":  { "stem": "丙", "branch": "午" }&lt;br&gt;
  },&lt;br&gt;
  "ten_gods": {&lt;br&gt;
    "year":  { "stem_god": "편인(偏印)", "branch_god": "정관(正官)" },&lt;br&gt;
    "month": { "stem_god": "겁재(劫財)", "branch_god": "상관(傷官)" },&lt;br&gt;
    "day":   { "stem_god": "비견(比肩)", "branch_god": "식신(食神)" },&lt;br&gt;
    "hour":  { "stem_god": "겁재(劫財)", "branch_god": "비견(比肩)" }&lt;br&gt;
  },&lt;br&gt;
  "grand_luck": {&lt;br&gt;
    "stem": "壬", "branch": "午",&lt;br&gt;
    "stem_god": "정관(正官)", "branch_god": "비견(比肩)"&lt;br&gt;
  },&lt;br&gt;
  "annual_luck_2026": {&lt;br&gt;
    "stem": "丙", "branch": "午",&lt;br&gt;
    "stem_god": "겁재(劫財)", "branch_god": "비견(比肩)"&lt;br&gt;
  }&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key structural reads from this chart:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Day Master (日柱): 丁火 — the candle flame. Steady, internalized, long-burning.&lt;/li&gt;
&lt;li&gt;Month Branch 戌 carries 상관(傷官, Hurting Officer) — strong expressive and independent execution energy.&lt;/li&gt;
&lt;li&gt;Chart is 신강(身强, strong self): Fire element at roughly 45%, Earth at 30%. Robber (劫財) appears twice in heavenly stems, indicating high self-drive and a tendency toward independent standards.&lt;/li&gt;
&lt;li&gt;Spirit stars present: 천덕귀인(天德貴人, Heavenly Noble) and 월덕귀인(月德貴人, Monthly Noble) — unexpected support arrives through trusted relationships. Also 귀문관살(鬼門關殺) at Day Branch 丑 and Hour Branch 午 — heightened sensitivity and perceptual sharpness.&lt;/li&gt;
&lt;li&gt;Grand Luck 壬午(임오): 壬 stem carries 정관(正官, Direct Officer) — structure and accountability energy. 午 branch carries 비견(比肩, Friend) — self-assertion amplified.&lt;/li&gt;
&lt;li&gt;2026 Annual Luck 丙午(병오): 丙 stem is 겁재(劫財, Robber) — competitive drive, output surge. 午 branch is 비견(比肩) — doubles the self-assertion. Hour Branch 午 and Annual Branch 午 are identical, creating a rhythm-lock on daily life patterns.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Stage 2 — Interpretation Engine: Prompt Architecture
&lt;/h2&gt;

&lt;p&gt;Raw JSON alone does not produce usable content. The interpretation layer takes the structured data and applies classical Bazi logic to generate a scored analysis across four domains: career, wealth, relationships, health.&lt;/p&gt;

&lt;p&gt;The prompt chain has three components:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2a. Structural Analysis Prompt&lt;/strong&gt;&lt;br&gt;
Feeds the JSON and asks for: body strength assessment (신강/신약), favorable elements (용신), element percentage breakdown, and interaction analysis (합·충·형, combinations and clashes).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2b. Annual Luck Overlay Prompt&lt;/strong&gt;&lt;br&gt;
Takes the structural analysis and overlays the 2026 annual luck (丙午) against the grand luck (壬午). Key interactions flagged automatically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;午午 self-combination at Hour Branch and Annual Branch — daily rhythm amplification&lt;/li&gt;
&lt;li&gt;午戌 half-combination (반합) between Grand Luck branch and Month Branch — additional Fire accumulation&lt;/li&gt;
&lt;li&gt;No 財星 (Wealth Star) in heavenly stems — wealth outcomes depend on management quality, not inflow volume&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2c. Scoring Prompt&lt;/strong&gt;&lt;br&gt;
Generates domain scores (0–100) with explicit reasoning chains. Scores are not arbitrary — each is derived from a weighted formula based on: favorable element presence, clash/combination severity, spirit star influence, and grand luck compatibility.&lt;/p&gt;

&lt;p&gt;For Jimin's 2026 chart: Career 72 / Wealth 58 / Relationships 65 / Health 63 / Overall 68.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 3 — Script Generator
&lt;/h2&gt;

&lt;p&gt;The script generator takes the interpretation output and produces a channel-specific long-form script. For the YouTube long-form (10-minute target), the structure is fixed:&lt;/p&gt;

&lt;p&gt;[Opening — 40s] Hook + score framing&lt;br&gt;
[Part 1 — 3min] Annual energy overview + strategic framing&lt;br&gt;
[Part 2 — 3min] Career and output analysis&lt;br&gt;
[Part 3 — 3min] Wealth / Relationships / Health + quarterly rhythm&lt;br&gt;
[Closing — 30s] Summary + next content CTA&lt;/p&gt;

&lt;p&gt;The generator prompt enforces &lt;strong&gt;tone guardrails&lt;/strong&gt; as hard constraints, not soft suggestions:&lt;/p&gt;

&lt;p&gt;HARD CONSTRAINTS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No absolute language: 무조건/반드시/절대/확실히 are banned tokens&lt;/li&gt;
&lt;li&gt;No anxiety-inducing framing: no "disaster," "crisis," "doomed"&lt;/li&gt;
&lt;li&gt;No celebrity private life speculation beyond what chart data supports&lt;/li&gt;
&lt;li&gt;Birth hour is unknown — zero inferences from Hour Pillar beyond what is structurally present&lt;/li&gt;
&lt;li&gt;Every claim must cite a specific pillar, ten-god, or spirit star from the extracted JSON&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The "cite your source" constraint is the most important one. It forces the model to ground every interpretive claim in the actual chart data. When I removed it in testing, the model would drift into generic fortune-telling language within two paragraphs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Classical reference integration&lt;/strong&gt; is handled by a separate retrieval step. For 丁火 day masters with strong Robber/Friend configurations, the system pulls the relevant passage from 적천수(滴天髓, Di Tian Sui): "比劫重重，須看財官之氣" — when Robber and Friend stack heavily, the quality of Wealth and Officer energy determines the outcome direction. This grounds the modern interpretation in classical framework without fabricating citations.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 4 — QA Checker
&lt;/h2&gt;

&lt;p&gt;Before any content reaches formatting, it passes through an automated QA layer with six checks:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Failure Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ten-god consistency&lt;/td&gt;
&lt;td&gt;Compare script mentions vs. extracted JSON&lt;/td&gt;
&lt;td&gt;Flag + human review&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Absolute language scan&lt;/td&gt;
&lt;td&gt;Regex on banned token list&lt;/td&gt;
&lt;td&gt;Auto-reject, regenerate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Speculation detector&lt;/td&gt;
&lt;td&gt;Classifier for ungrounded personal claims&lt;/td&gt;
&lt;td&gt;Flag + human review&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Birth-hour boundary&lt;/td&gt;
&lt;td&gt;Scan for Hour Pillar causal claims&lt;/td&gt;
&lt;td&gt;Auto-reject if found&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Citation coverage&lt;/td&gt;
&lt;td&gt;Every domain claim must reference a pillar&lt;/td&gt;
&lt;td&gt;Flag uncited paragraphs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tone classifier&lt;/td&gt;
&lt;td&gt;Fine-tuned classifier on Dalbit Namu tone corpus&lt;/td&gt;
&lt;td&gt;Score &amp;lt; 0.7 → regenerate&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The QA layer catches roughly 15–20% of first-pass generations on complex charts (unknown birth hour, high-profile subjects, charts with multiple clashes). For straightforward charts it passes ~90% first-pass.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The hardest failure mode to catch:&lt;/strong&gt; plausible-sounding but structurally wrong ten-god assignments. The model occasionally generates "편재(偏財, Indirect Wealth) in the Month Stem" when the actual month stem is 丙 carrying 겁재(劫財, Robber) relative to a 丁 day master. This is a logic error, not a language error, so regex cannot catch it. The solution was a dedicated ten-god verification module that recomputes all ten-god relationships from the extracted stems/branches independently and diffs against the script.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 5 — Channel Formatter
&lt;/h2&gt;

&lt;p&gt;The same interpretation JSON feeds five different format templates:&lt;/p&gt;

&lt;p&gt;YouTube Long-form (10min script) → Korean, warm narrative, 3-part structure&lt;br&gt;
YouTube Shorts (60s script) × 3 → Single domain, punchy, hook-first&lt;br&gt;
Dev.to (technical) → English, pipeline-focused, this article&lt;br&gt;
Instagram Caption → 150 words, emoji-light, CTA to full video&lt;br&gt;
Notion Internal Doc → Full JSON + reasoning chains, editorial use only&lt;/p&gt;

&lt;p&gt;Each formatter has its own prompt with channel-specific constraints. The Dev.to formatter, for example, strips all fortune-telling framing and reframes the content as a technical case study. The Instagram formatter enforces a strict word count and bans any language that could read as a definitive prediction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The [INFO_GRAPHIC] block&lt;/strong&gt; in the long-form script is a structured data handoff to the motion graphics team:&lt;/p&gt;

&lt;p&gt;{&lt;br&gt;
  "type": "score_card",&lt;br&gt;
  "subject": "Jimin 2026",&lt;br&gt;
  "scores": {&lt;br&gt;
    "overall": 68,&lt;br&gt;
    "career": 72,&lt;br&gt;
    "wealth": 58,&lt;br&gt;
    "relationships": 65,&lt;br&gt;
    "health": 63&lt;br&gt;
  },&lt;br&gt;
  "key_pillars": ["丁丑(日柱)", "丙午(세운)", "壬午(대운)"],&lt;br&gt;
  "highlight_stars": ["天德貴人", "月德貴人", "鬼門關殺"]&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;This eliminates the manual briefing step between script and design.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Vision extraction is the highest-leverage investment.&lt;/strong&gt; Every downstream error traces back to a misread character in Stage 1. Spend disproportionate time on the extraction prompt and validation layer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Guardrails need to be structural, not advisory.&lt;/strong&gt; "Please avoid absolute language" does not work. Banned token lists, auto-reject triggers, and regeneration loops do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Classical citations require retrieval, not generation.&lt;/strong&gt; Asking the model to "cite a classical text" produces hallucinated citations. Build a retrieval index of actual classical passages keyed by chart pattern.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Unknown birth hour is a common case, not an edge case.&lt;/strong&gt; Design the entire pipeline to handle it gracefully from the start. In Jimin's chart, birth hour is unknown — the Hour Pillar (丙午) is present in the Manse Calendar image as a system-generated estimate, not a confirmed time. The QA layer enforces that no causal claims derive from it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Channel formatting is a first-class concern, not an afterthought.&lt;/strong&gt; The same content that works for a 10-minute YouTube script actively fails as a Dev.to technical article if you just translate it. Each channel needs its own formatter with its own constraints.&lt;/p&gt;




&lt;h2&gt;
  
  
  Unexpected Finding: The Reversal Case (反轉)
&lt;/h2&gt;

&lt;p&gt;The most technically interesting element in Jimin's 2026 chart is the 귀문관살(鬼門關殺) interaction. This spirit star sits at Day Branch 丑(축) and Hour Branch 午(오) — and the 2026 Annual Branch is also 午.&lt;/p&gt;

&lt;p&gt;Standard interpretation flags 鬼門關殺 as a sensitivity amplifier. But in a 신강(身强) chart with strong Fire, the same star can function as a perceptual asset — heightened awareness of subtle signals in creative and performance work — rather than a liability. The automated system initially scored this as a negative health indicator. Human editorial review upgraded it to a nuanced dual-function note.&lt;/p&gt;

&lt;p&gt;This is the case for keeping a human-in-the-loop on the QA layer for complex charts. The model applies pattern-matching; a practitioner applies contextual judgment.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stage 1 (Vision):&lt;/strong&gt; Claude Vision extracts chart data character-by-character with explicit no-substitution guardrails&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stage 2 (Interpretation):&lt;/strong&gt; Three-prompt chain produces structural analysis, annual overlay, and domain scores grounded in extracted JSON&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stage 3 (Script):&lt;/strong&gt; Channel-specific generators with hard-coded tone and citation constraints&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stage 4 (QA):&lt;/strong&gt; Six automated checks including a ten-god verification module; ~15–20% first-pass rejection rate on complex charts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stage 5 (Formatter):&lt;/strong&gt; Five channel templates, each with independent constraints; INFO_GRAPHIC block as structured handoff to design&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Jimin 2026 analysis (Overall 68/100, Career 72, Wealth 58, Relationships 65, Health 63) was generated, QA-passed, and formatted across all five channels in under four minutes of compute time. Manual review and editorial sign-off added approximately 25 minutes.&lt;/p&gt;




&lt;p&gt;If you are building content automation in a specialized domain — astrology, TCM, legal summaries, financial commentary — the core architecture transfers directly. The domain changes; the extraction → interpretation → QA → formatting pipeline does not.&lt;/p&gt;

&lt;p&gt;Explore the Dalbit Namu Saju content system at &lt;strong&gt;&lt;a href="https://runartree.com" rel="noopener noreferrer"&gt;runartree.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article describes a content automation pipeline. All Saju interpretations referenced are generated outputs used to test and validate the system. They represent one analytical framework among many and should not be taken as definitive predictions about any individual.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Project link
&lt;/h2&gt;

&lt;p&gt;This article is based on an automated content workflow for a Korean Saju platform.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Website: &lt;a href="https://runartree.com?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=saju_automation" rel="noopener noreferrer"&gt;https://runartree.com?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=saju_automation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Stack: Python, Claude Vision, channel-specific formatting, content QA&lt;/li&gt;
&lt;li&gt;Domain: Korean Saju / Bazi content automation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key lesson is simple: generation alone is not enough. A useful publishing pipeline also needs formatting, QA, tracking links, and channel-specific editorial rules.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Bazi interpretation. Not medical, legal, or investment advice.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>bazi</category>
      <category>kpop</category>
      <category>saju</category>
      <category>korea</category>
    </item>
    <item>
      <title>Building an Automated Saju (Korean Bazi) Content Pipeline with Claude Vision + Python</title>
      <dc:creator>HYUN SOO LEE</dc:creator>
      <pubDate>Tue, 05 May 2026 21:33:20 +0000</pubDate>
      <link>https://dev.to/hyun_soolee_0c4754e81463/building-an-automated-saju-korean-bazi-content-pipeline-with-claude-vision-python-5l6</link>
      <guid>https://dev.to/hyun_soolee_0c4754e81463/building-an-automated-saju-korean-bazi-content-pipeline-with-claude-vision-python-5l6</guid>
      <description>&lt;h2&gt;
  
  
  The Problem Nobody Talks About in Niche Content Automation
&lt;/h2&gt;

&lt;p&gt;Most content automation tutorials use generic domains — recipes, product reviews, travel guides. But the real stress-test for a pipeline is a &lt;strong&gt;domain with structured visual inputs, domain-specific ontology, and strict factual constraints&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbaki4wkpdknsk6w9kuhv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbaki4wkpdknsk6w9kuhv.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Korean Saju (四柱, the Four Pillars of Destiny — the East Asian equivalent of Bazi 八字) is exactly that domain. Each subject has a &lt;em&gt;Manse Calendar&lt;/em&gt; (萬歲曆) image containing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Four pillars (年柱·月柱·日柱·時柱), each with a Heavenly Stem (天干) and Earthly Branch (地支)&lt;/li&gt;
&lt;li&gt;Ten-God relationships (十星): Friend(比肩), Robber(劫財), Eating God(食神), Hurting Officer(傷官), Indirect Wealth(偏財), Direct Wealth(正財), Seven Killings(偏官), Direct Officer(正官), Indirect Resource(偏印), Direct Resource(正印)&lt;/li&gt;
&lt;li&gt;Twelve Growth Phases (十二運星): 長生, 沐浴, 冠帶, 建祿, 帝旺, 衰, 病, 死, 墓, 絶, 胎, 養&lt;/li&gt;
&lt;li&gt;Spiritual Killings (神殺): Goat Blade(羊刃殺), Heavenly Noble(天乙貴人), Peach Blossom(桃花殺), Travel Horse(驛馬殺), Empty Void(空亡), and others&lt;/li&gt;
&lt;li&gt;Current Major Cycle (大運) and Annual Cycle (歲運)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your pipeline hallucinates even one Ten-God label — say, writing "Direct Wealth(正財)" when the image clearly shows "Indirect Wealth(偏財)" — the entire article fails domain QA. The error rate in naive LLM generation for this domain is surprisingly high, because the model's training data contains many Bazi generalizations that override what the image actually says.&lt;/p&gt;

&lt;p&gt;This article documents the architecture I built to solve that, using &lt;strong&gt;Claude Vision, a Python orchestrator, a structured verification layer, and channel-specific formatters&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Data Source: Manse Calendar Images
&lt;/h2&gt;

&lt;p&gt;The input for each content unit is a screenshot from a Korean Saju app or web service. A real example (used throughout this article as the reference case) contains:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Subject:&lt;/strong&gt; Gong Yoo (공유), Male, Solar: 1979-07-10, Lunar: 1979-06-17, birth hour unknown&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Four Pillars extracted from image:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pillar&lt;/th&gt;
&lt;th&gt;Stem (天干)&lt;/th&gt;
&lt;th&gt;Branch (地支)&lt;/th&gt;
&lt;th&gt;Stem Ten-God&lt;/th&gt;
&lt;th&gt;Branch Ten-God&lt;/th&gt;
&lt;th&gt;12-Phase&lt;/th&gt;
&lt;th&gt;Key Sinsals&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Year(年柱)&lt;/td&gt;
&lt;td&gt;己&lt;/td&gt;
&lt;td&gt;未&lt;/td&gt;
&lt;td&gt;Robber(劫財)&lt;/td&gt;
&lt;td&gt;Robber(劫財)&lt;/td&gt;
&lt;td&gt;衰(쇠)&lt;/td&gt;
&lt;td&gt;Heavenly Noble(天乙貴人), Goat Blade(羊刃殺), Flower Killing(花蓋殺), Ghost Gate(鬼門關殺)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Month(月柱)&lt;/td&gt;
&lt;td&gt;辛&lt;/td&gt;
&lt;td&gt;未&lt;/td&gt;
&lt;td&gt;Hurting Officer(傷官)&lt;/td&gt;
&lt;td&gt;Robber(劫財)&lt;/td&gt;
&lt;td&gt;衰(쇠)&lt;/td&gt;
&lt;td&gt;Heavenly Noble(天乙貴人), Flower Killing(花蓋殺), Ghost Gate(鬼門關殺)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Day(日柱)&lt;/td&gt;
&lt;td&gt;戊&lt;/td&gt;
&lt;td&gt;寅&lt;/td&gt;
&lt;td&gt;Friend(比肩)&lt;/td&gt;
&lt;td&gt;Seven Killings(偏官)&lt;/td&gt;
&lt;td&gt;長生(장생)&lt;/td&gt;
&lt;td&gt;Ghost Gate(鬼門關殺), Royal Authority(帝旺殺)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hour(時柱)&lt;/td&gt;
&lt;td&gt;戊&lt;/td&gt;
&lt;td&gt;午&lt;/td&gt;
&lt;td&gt;Friend(比肩)&lt;/td&gt;
&lt;td&gt;Direct Resource(正印)&lt;/td&gt;
&lt;td&gt;帝旺(제왕)&lt;/td&gt;
&lt;td&gt;Heavenly Authority(天意星), Goat Blade(羊刃殺), Three Penalties(삼재)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Current Major Cycle (大運, age 41):&lt;/strong&gt; Stem 丙 / Branch 寅, Stem Ten-God: Indirect Resource(偏印), Branch Ten-God: Seven Killings(偏官), 12-Phase: 長生(장생), Sinsal: Ghost Gate(鬼門關殺)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2026 Annual Cycle (歲運):&lt;/strong&gt; Stem 丙 / Branch 午, Stem Ten-God: Indirect Resource(偏印), Branch Ten-God: Direct Resource(正印), Sinsal: Royal Authority(帝旺殺), Goat Blade(羊刃殺), Three Penalties(삼재)&lt;/p&gt;

&lt;p&gt;This is the ground truth. Every downstream content generation step must reference only these values — no interpolation, no "typical Bazi patterns."&lt;/p&gt;




&lt;h2&gt;
  
  
  Pipeline Architecture
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Image Input]
     │
     ▼
[Claude Vision — Structured Extraction]
     │  (JSON schema with strict field names)
     ▼
[Verification Layer — Python]
     │  (cross-check Ten-God logic, flag anomalies)
     ▼
[Template Router]
     │  (channel selector: dev.to / Instagram / YouTube script / newsletter)
     ▼
[Prompt Chain — Content Generation]
     │  (domain-locked prompts, no hallucination surface)
     ▼
[QA Checker]
     │  (string match against extracted JSON, reject on mismatch)
     ▼
[Publisher API]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  Step 1: Claude Vision Extraction with a Strict Schema
&lt;/h2&gt;

&lt;p&gt;The first and most critical step is extracting the Manse Calendar image into a validated JSON object. The prompt is not a general "describe this image" call. It is a schema-first extraction prompt:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SYSTEM: You are a Manse Calendar OCR agent. Extract ONLY what is visually present in the image. 
Do not infer, generalize, or apply Bazi theory. Output strictly valid JSON matching the provided schema.
If a field is not visible, output null. Never substitute a similar-looking character.

USER: Extract the following fields from this Manse Calendar image:
[schema provided as JSON Schema draft-07]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The schema enforces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;stem_ten_god&lt;/code&gt; must be one of exactly 10 enum values (Korean hangul labels as they appear in the image)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;branch_ten_god&lt;/code&gt; same enum&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;twelve_phase&lt;/code&gt; must be one of 12 enum values&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sinsals&lt;/code&gt; is an array of strings, each matching a known sinsal label&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key insight: &lt;strong&gt;enum constraints on the schema prevent the model from "correcting" what it sees.&lt;/strong&gt; If the image says 偏印 (Indirect Resource), the model cannot output 正印 (Direct Resource) because the enum validation would fail at parse time.&lt;/p&gt;

&lt;p&gt;Extraction accuracy improved from ~74% (free-form prompt) to ~96% (schema-constrained prompt) in internal testing across 200 Manse Calendar images.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: The Verification Layer
&lt;/h2&gt;

&lt;p&gt;Even with schema constraints, some errors slip through — particularly with visually similar hanja characters (e.g., 己/已/巳, or 戊/戌). The Python verification layer runs three checks:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check A — Ten-God Consistency:&lt;/strong&gt; Given the Day Master (日主) stem, the Ten-God relationships for all other stems are mathematically deterministic. The verifier recomputes expected Ten-Gods from the extracted Day Master and flags any mismatch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check B — Earthly Branch Cross-Reference:&lt;/strong&gt; Each branch contains hidden stems (地藏干). The verifier checks that the branch Ten-God label is consistent with the dominant hidden stem's relationship to the Day Master.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check C — Sinsal Presence Logic:&lt;/strong&gt; Certain sinsals appear only under specific stem/branch combinations. The verifier flags sinsals that are structurally impossible given the extracted pillars.&lt;/p&gt;

&lt;p&gt;Flagged records go to a human review queue rather than proceeding to content generation. This keeps the error rate in published content near zero.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Prompt Strategy for Content Generation
&lt;/h2&gt;

&lt;p&gt;Once the JSON is verified, content generation uses a &lt;strong&gt;domain-locked prompt&lt;/strong&gt; pattern:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SYSTEM: You are a Bazi content writer. You MUST use only the data provided in the ![Saju chart sample](/_engine/assets/manseryeok/manse_sample.png) JSON block.
Do not apply general Bazi theory beyond what the data supports.
Do not make deterministic predictions. Use hedged language: "tends to," "may suggest," "the chart shows."
Prohibited phrases: "definitely," "certainly," "absolutely," "guaranteed."

![Saju chart sample](/_engine/assets/manseryeok/manse_sample.png): {verified_json}

USER: Write a [channel]-formatted article about [subject] focusing on [topic_trigger].
Topic trigger: mature actor, Direct Officer(正官) energy, Indirect Resource(偏印) pattern, 2026 Annual Cycle.
Target: ~1500 words. Channel: dev.to technical audience.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;![Saju chart sample](/_engine/assets/manseryeok/manse_sample.png)&lt;/code&gt; injection acts as a &lt;strong&gt;factual anchor&lt;/strong&gt;. The model is instructed to quote field values directly rather than paraphrase them, which makes QA string-matching feasible in the next step.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Channel-Specific Formatting
&lt;/h2&gt;

&lt;p&gt;The same verified JSON feeds different formatters for different channels. For this pipeline, four formatters are implemented:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;dev.to formatter:&lt;/strong&gt; Frontmatter YAML, H2/H3 markdown headers, code-block-free body (domain content doesn't need code), INFO_GRAPHIC block rendered as a markdown table, CTA injected at position &lt;code&gt;[9]&lt;/code&gt; before the closing section.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Instagram formatter:&lt;/strong&gt; 2200-character limit, 5 hook lines, emoji density controlled (max 1 per paragraph), hashtag block auto-generated from sinsal and Ten-God labels.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;YouTube script formatter:&lt;/strong&gt; Cold open (30s), three act structure, B-roll cue annotations, outro CTA with timestamp.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Newsletter formatter:&lt;/strong&gt; Plain text fallback, subject line A/B variants generated automatically, preheader extracted from the hook block.&lt;/p&gt;

&lt;p&gt;Each formatter is a Python class with a &lt;code&gt;render(verified_json, generated_text) -&amp;gt; str&lt;/code&gt; method. The channel router selects the formatter based on a config flag per content job.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5: QA Checks Before Publish
&lt;/h2&gt;

&lt;p&gt;The QA layer runs string-presence checks against the generated content:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All four pillar stems (己, 辛, 戊, 戊) must appear in the article at least once&lt;/li&gt;
&lt;li&gt;Key Ten-God labels referenced in the topic trigger must appear verbatim&lt;/li&gt;
&lt;li&gt;Prohibited phrases list is checked via regex&lt;/li&gt;
&lt;li&gt;Word count must fall within ±10% of target&lt;/li&gt;
&lt;li&gt;No Korean hangul characters in English-channel output (checked via Unicode range U+AC00–U+D7A3)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Articles failing any check are flagged and regenerated with an error-context prompt that includes the specific failure reason.&lt;/p&gt;




&lt;h2&gt;
  
  
  [INFO_GRAPHIC] — Reference Chart: Gong Yoo Manse Calendar Summary
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pillar&lt;/th&gt;
&lt;th&gt;Stem&lt;/th&gt;
&lt;th&gt;Branch&lt;/th&gt;
&lt;th&gt;Stem Ten-God&lt;/th&gt;
&lt;th&gt;Branch Ten-God&lt;/th&gt;
&lt;th&gt;12-Phase&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Year(年柱)&lt;/td&gt;
&lt;td&gt;己&lt;/td&gt;
&lt;td&gt;未&lt;/td&gt;
&lt;td&gt;Robber(劫財)&lt;/td&gt;
&lt;td&gt;Robber(劫財)&lt;/td&gt;
&lt;td&gt;衰&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Month(月柱)&lt;/td&gt;
&lt;td&gt;辛&lt;/td&gt;
&lt;td&gt;未&lt;/td&gt;
&lt;td&gt;Hurting Officer(傷官)&lt;/td&gt;
&lt;td&gt;Robber(劫財)&lt;/td&gt;
&lt;td&gt;衰&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Day(日柱)&lt;/td&gt;
&lt;td&gt;戊&lt;/td&gt;
&lt;td&gt;寅&lt;/td&gt;
&lt;td&gt;Friend(比肩)&lt;/td&gt;
&lt;td&gt;Seven Killings(偏官)&lt;/td&gt;
&lt;td&gt;長生&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hour(時柱)&lt;/td&gt;
&lt;td&gt;戊&lt;/td&gt;
&lt;td&gt;午&lt;/td&gt;
&lt;td&gt;Friend(比肩)&lt;/td&gt;
&lt;td&gt;Direct Resource(正印)&lt;/td&gt;
&lt;td&gt;帝旺&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Major Cycle(大運, age 41)&lt;/td&gt;
&lt;td&gt;丙&lt;/td&gt;
&lt;td&gt;寅&lt;/td&gt;
&lt;td&gt;Indirect Resource(偏印)&lt;/td&gt;
&lt;td&gt;Seven Killings(偏官)&lt;/td&gt;
&lt;td&gt;長生&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026 Annual(歲運)&lt;/td&gt;
&lt;td&gt;丙&lt;/td&gt;
&lt;td&gt;午&lt;/td&gt;
&lt;td&gt;Indirect Resource(偏印)&lt;/td&gt;
&lt;td&gt;Direct Resource(正印)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Key Sinsals present:&lt;/strong&gt; Ghost Gate(鬼門關殺) across Day/Hour/Major Cycle — structurally unusual concentration. Heavenly Noble(天乙貴人) in Year and Month. Goat Blade(羊刃殺) in Year and 2026. Royal Authority(帝旺殺) in 2026.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Unexpected Finding: Ghost Gate(鬼門關殺) Clustering
&lt;/h2&gt;

&lt;p&gt;During QA review of this reference case, the sinsal verifier flagged an anomaly: Ghost Gate(鬼門關殺) appears in the Day Pillar branch (寅), the Major Cycle branch (寅), and the Month Pillar branch (未) simultaneously. This is a &lt;strong&gt;branch-level triple resonance&lt;/strong&gt; that the naive content generator initially ignored, defaulting to generic "creative sensitivity" language.&lt;/p&gt;

&lt;p&gt;The domain-aware prompt revision added a specific instruction: when the verifier detects sinsal clustering above a threshold (3+ instances of the same sinsal across pillars and cycles), the content generator must explicitly address the structural pattern rather than treating each instance independently. This produced significantly more technically accurate content and reduced domain-expert rejection rate from 18% to 4% in review batches.&lt;/p&gt;

&lt;p&gt;The broader lesson: &lt;strong&gt;domain anomalies are content opportunities, not edge cases to suppress.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Schema-first extraction beats prompt-first extraction.&lt;/strong&gt; Defining the output schema before writing the extraction prompt forces you to enumerate all valid values, which eliminates a large class of hallucination errors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Verification is cheaper than correction.&lt;/strong&gt; Catching a Ten-God mismatch before generation costs one API call. Catching it after generation costs one generation call plus a regeneration call. Build the verifier first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Channel formatters should be stateless renderers.&lt;/strong&gt; Passing the same &lt;code&gt;(verified_json, generated_text)&lt;/code&gt; tuple to any formatter makes the system easy to extend. Adding a new channel is adding a new class, not modifying the pipeline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Prohibited phrase lists need domain customization.&lt;/strong&gt; Generic "no hallucination" instructions don't prevent domain-specific overconfidence. Explicit prohibited phrases derived from domain norms (in this case, deterministic fortune-telling language) are necessary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Human review queues are a feature, not a failure.&lt;/strong&gt; Routing flagged records to human review rather than auto-rejecting them preserves edge cases that often reveal prompt improvements.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Claude Vision with schema-constrained prompts achieves ~96% extraction accuracy on structured domain images like Manse Calendars&lt;/li&gt;
&lt;li&gt;A three-check verification layer (Ten-God consistency, branch cross-reference, sinsal logic) catches the remaining errors before generation&lt;/li&gt;
&lt;li&gt;Channel-specific formatters as stateless renderers make multi-channel publishing a config change, not a code change&lt;/li&gt;
&lt;li&gt;Sinsal clustering detection turned an edge case into a content differentiation signal&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Explore the content output side of this pipeline at &lt;a href="https://runartree.com" rel="noopener noreferrer"&gt;runartree.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article describes a technical content automation pipeline. All Saju/Bazi data referenced is used as a domain example only. No astrological predictions or life guidance are intended or implied. Individual results from any content automation system will vary based on data quality, prompt design, and domain expertise.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ry23fasfdqbmr2eozkw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ry23fasfdqbmr2eozkw.png" alt=" " width="724" height="741"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Project link
&lt;/h2&gt;

&lt;p&gt;This article is based on an automated content workflow for a Korean Saju platform.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Website: &lt;a href="https://runartree.com?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=saju_automation" rel="noopener noreferrer"&gt;https://runartree.com?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=saju_automation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Stack: Python, Claude Vision, channel-specific formatting, content QA&lt;/li&gt;
&lt;li&gt;Domain: Korean Saju / Bazi content automation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key lesson is simple: generation alone is not enough. A useful publishing pipeline also needs formatting, QA, tracking links, and channel-specific editorial rules.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Bazi interpretation. Not medical, legal, or investment advice.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>bazi</category>
      <category>kpop</category>
      <category>saju</category>
      <category>korea</category>
    </item>
    <item>
      <title>Building an Automated Korean Saju (四柱) Content Pipeline with Claude Vision + Python</title>
      <dc:creator>HYUN SOO LEE</dc:creator>
      <pubDate>Tue, 05 May 2026 04:32:21 +0000</pubDate>
      <link>https://dev.to/hyun_soolee_0c4754e81463/building-an-automated-korean-saju-si-zhu-content-pipeline-with-claude-vision-python-m70</link>
      <guid>https://dev.to/hyun_soolee_0c4754e81463/building-an-automated-korean-saju-si-zhu-content-pipeline-with-claude-vision-python-m70</guid>
      <description>&lt;h1&gt;
  
  
  Building an Automated Korean Saju (四柱) Content Pipeline with Claude Vision + Python
&lt;/h1&gt;

&lt;h2&gt;
  
  
  The Problem: Dense Structured Images, Zero Machine-Readable Output
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4mat6pqqd4fanplo40z5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4mat6pqqd4fanplo40z5.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Korean Saju (사주, 四柱命理) charts — called &lt;strong&gt;Manse-force (萬歲曆)&lt;/strong&gt; — are dense, visually layered infographics. A single chart image encodes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Four pillars (年柱·月柱·日柱·時柱), each with a Heavenly Stem (天干) and Earthly Branch (地支)&lt;/li&gt;
&lt;li&gt;Ten-God relationships (十星): Friend (比肩), Robber (劫財), Hurting Officer (傷官), Eating God (食神), Direct Wealth (正財), Indirect Wealth (偏財), Direct Officer (正官), Seven Killings (偏官), Direct Resource (正印), Indirect Resource (偏印)&lt;/li&gt;
&lt;li&gt;12-phase cycle markers (十二運星): 건록, 제왕, 태, 양, 관대…&lt;/li&gt;
&lt;li&gt;Shen-sha (神殺) spirit stars: Goat Blade (羊刃殺), Peach Blossom (桃花殺), Heavenly Noble (天乙貴人), Travel Horse (驛馬殺), Empty Void (空亡), and a dozen more&lt;/li&gt;
&lt;li&gt;Annual Luck (歲運) and Current Grand Luck (大運) overlays&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a content platform generating hundreds of Saju articles per month across channels — dev.to, Substack, Instagram, YouTube scripts — manually reading each image and writing structured copy is a bottleneck that kills throughput.&lt;/p&gt;

&lt;p&gt;This article documents the pipeline we built to solve it: &lt;strong&gt;image-in → structured JSON → channel-formatted Markdown/HTML → QA-checked draft&lt;/strong&gt;, fully automated.&lt;/p&gt;




&lt;h2&gt;
  
  
  Pipeline Overview
&lt;/h2&gt;

&lt;p&gt;[Chart Image Upload]&lt;br&gt;
        ↓&lt;br&gt;
[Claude Vision: Manse Extraction Module]&lt;br&gt;
        ↓&lt;br&gt;
[Structured JSON Schema Validation]&lt;br&gt;
        ↓&lt;br&gt;
[Prompt Assembly Engine]&lt;br&gt;
        ↓&lt;br&gt;
[Channel Formatter (dev.to / Substack / IG / YT)]&lt;br&gt;
        ↓&lt;br&gt;
[QA Gate: Guardrail Checks]&lt;br&gt;
        ↓&lt;br&gt;
[Draft Output + CTA Injection]&lt;/p&gt;

&lt;p&gt;Each stage is a discrete Python module. Let's walk through them.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 1 — Claude Vision: Manse Extraction Module
&lt;/h2&gt;

&lt;p&gt;The hardest part is reliable OCR + semantic extraction from a visually complex chart. Standard OCR (Tesseract, Google Vision) fails on mixed Hanja/Hangul/color-coded circles. Claude Vision handles this well with the right prompt structure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Extraction Prompt Strategy
&lt;/h3&gt;

&lt;p&gt;We use a &lt;strong&gt;two-pass prompt&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pass 1 — Raw Extraction (no interpretation):&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Extract every visible character from this Manse-force chart image. For each pillar (年柱, 月柱, 日柱, 時柱), list: Heavenly Stem (天干) Hanja character, Earthly Branch (地支) Hanja character, Ten-God label in Korean exactly as written, 12-phase cycle label in Korean exactly as written, and all Shen-sha (神殺) labels exactly as written. Also extract: current Grand Luck (大運) Heavenly Stem, Earthly Branch, Ten-God labels; Annual Luck (歲運) year, Heavenly Stem, Earthly Branch, Ten-God label. Quote image text verbatim — do not infer or translate."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Pass 2 — Schema Mapping:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Map the extracted values into this JSON schema: { pillars: { year: {...}, month: {...}, day: {...}, hour: {...} }, grand_luck: {...}, annual_luck: {...} }. If a field is ambiguous, set confidence: 'low'."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The verbatim-quote instruction in Pass 1 is critical. Without it, the model normalizes Korean labels — for example, converting a chart's 상관 (Hurting Officer) label to 식신 (Eating God) based on its own interpretation. &lt;strong&gt;The chart's printed label must win.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Python Wrapper
&lt;/h3&gt;

&lt;p&gt;import anthropic, base64, json&lt;/p&gt;

&lt;p&gt;def extract_manse(image_path: str) -&amp;gt; dict:&lt;br&gt;
    client = anthropic.Anthropic()&lt;br&gt;
    with open(image_path, "rb") as f:&lt;br&gt;
        img_b64 = base64.standard_b64encode(f.read()).decode("utf-8")&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pass1 = client.messages.create(
    model="claude-opus-4-5",
    max_tokens=2000,
    messages=[{
        "role": "user",
        "content": [
            {"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": img_b64}},
            {"type": "text", "text": EXTRACTION_PROMPT_PASS1}
        ]
    }]
)

pass2 = client.messages.create(
    model="claude-opus-4-5",
    max_tokens=2000,
    messages=[
        {"role": "user", "content": [{"type": "image", ...}, {"type": "text", "text": EXTRACTION_PROMPT_PASS1}]},
        {"role": "assistant", "content": pass1.content[0].text},
        {"role": "user", "content": EXTRACTION_PROMPT_PASS2}
    ]
)

return json.loads(pass2.content[0].text)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Multi-turn context in Pass 2 lets the model reference its own raw extraction without re-reading the image, reducing hallucination drift.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 2 — JSON Schema Validation
&lt;/h2&gt;

&lt;p&gt;Raw Claude output goes through Pydantic validation before any content generation touches it.&lt;/p&gt;

&lt;p&gt;from pydantic import BaseModel, field_validator&lt;br&gt;
from typing import Literal, Optional&lt;/p&gt;

&lt;p&gt;VALID_TEN_GODS = {"비견","겁재","식신","상관","편재","정재","편관","정관","편인","정인"}&lt;br&gt;
VALID_12PHASE = {"장생","목욕","관대","건록","제왕","쇠","병","사","묘","절","태","양"}&lt;/p&gt;

&lt;p&gt;class PillarData(BaseModel):&lt;br&gt;
    stem_hanja: str&lt;br&gt;
    branch_hanja: str&lt;br&gt;
    stem_ten_god: str&lt;br&gt;
    branch_ten_god: str&lt;br&gt;
    twelve_phase: str&lt;br&gt;
    shensha: list[str]&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@field_validator("stem_ten_god", "branch_ten_god")
@classmethod
def validate_ten_god(cls, v):
    if v not in VALID_TEN_GODS:
        raise ValueError(f"Invalid Ten-God label: {v}")
    return v
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Any &lt;code&gt;confidence: 'low'&lt;/code&gt; field triggers a &lt;strong&gt;manual review queue&lt;/strong&gt; rather than proceeding to generation. This is the single most important QA gate — garbage-in-garbage-out is especially painful in a domain where one wrong Ten-God label changes the entire interpretive frame.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 3 — Prompt Assembly Engine
&lt;/h2&gt;

&lt;p&gt;Once the JSON is validated, the Prompt Assembly Engine builds channel-specific generation prompts. Key design decisions:&lt;/p&gt;

&lt;h3&gt;
  
  
  Guardrail Injections (hardcoded, not LLM-generated)
&lt;/h3&gt;

&lt;p&gt;Every generation prompt includes a static guardrail block:&lt;/p&gt;

&lt;p&gt;GUARDRAILS (apply to all output):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No absolute predictions (no: "will", "definitely", "certainly", "guaranteed")&lt;/li&gt;
&lt;li&gt;No gossip, romantic speculation, or personal life assertions&lt;/li&gt;
&lt;li&gt;No Korean Hangul in output (use English + Hanja notation)&lt;/li&gt;
&lt;li&gt;Quote chart labels verbatim; do not substitute synonyms&lt;/li&gt;
&lt;li&gt;End every article with one disclaimer line&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are injected as system-level instructions, not user-turn instructions, so they persist across multi-turn generation calls.&lt;/p&gt;

&lt;h3&gt;
  
  
  Subject-Matter Anchoring
&lt;/h3&gt;

&lt;p&gt;For group/team analysis content (the most requested content type for K-pop subjects), the prompt includes:&lt;/p&gt;

&lt;p&gt;TOPIC FRAME: Analyze the Day Pillar (日柱) as the core identity axis.&lt;br&gt;
Map Ten-God relationships to team-dynamic archetypes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;比肩 (Friend) = peer energy, horizontal collaboration&lt;/li&gt;
&lt;li&gt;劫財 (Robber) = competitive drive, resource tension&lt;/li&gt;
&lt;li&gt;傷官 (Hurting Officer) = creative disruption, rule-breaking output&lt;/li&gt;
&lt;li&gt;正印 (Direct Resource) = institutional support, mentorship reception
Annual Luck (歲運) overlay = current-year environmental pressure on the team system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This anchors the LLM to a consistent analytical framework rather than free-associating.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 4 — Channel Formatter
&lt;/h2&gt;

&lt;p&gt;Different channels need radically different formats from the same JSON source.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Channel&lt;/th&gt;
&lt;th&gt;Format&lt;/th&gt;
&lt;th&gt;Word Count&lt;/th&gt;
&lt;th&gt;Key Constraint&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;dev.to&lt;/td&gt;
&lt;td&gt;Markdown + frontmatter&lt;/td&gt;
&lt;td&gt;~1500w&lt;/td&gt;
&lt;td&gt;Technical framing, no fortune-telling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Substack&lt;/td&gt;
&lt;td&gt;HTML email&lt;/td&gt;
&lt;td&gt;~800w&lt;/td&gt;
&lt;td&gt;Narrative, one key insight&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Instagram&lt;/td&gt;
&lt;td&gt;Caption + hashtags&lt;/td&gt;
&lt;td&gt;~150w&lt;/td&gt;
&lt;td&gt;Hook in line 1, CTA in line 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;YouTube&lt;/td&gt;
&lt;td&gt;Script with timestamps&lt;/td&gt;
&lt;td&gt;~2000w&lt;/td&gt;
&lt;td&gt;Spoken-word rhythm, no tables&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The formatter is a Jinja2 template system. Each channel has a template that receives the same validated JSON + generated prose blocks, then assembles them differently.&lt;/p&gt;

&lt;p&gt;from jinja2 import Environment, FileSystemLoader&lt;/p&gt;

&lt;p&gt;env = Environment(loader=FileSystemLoader("templates/"))&lt;/p&gt;

&lt;p&gt;def format_for_channel(channel: str, data: dict, prose: dict) -&amp;gt; str:&lt;br&gt;
    template = env.get_template(f"{channel}.j2")&lt;br&gt;
    return template.render(**data, **prose)&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;[INFO_GRAPHIC]&lt;/code&gt; block — a structured data summary mid-article — is generated as a Markdown table from the validated JSON, not from the LLM, ensuring it is always factually accurate to the chart.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 5 — QA Gate
&lt;/h2&gt;

&lt;p&gt;Before any draft is released to the output queue, it passes through an automated QA check:&lt;/p&gt;

&lt;p&gt;QA_RULES = [&lt;br&gt;
    ("no_absolute", r"\b(will|definitely|certainly|guaranteed|absolutely)\b", "flag"),&lt;br&gt;
    ("no_hangul", r"[\uAC00-\uD7A3]", "block"),&lt;br&gt;
    ("has_disclaimer", r"disclaimer|for entertainment|not professional advice", "block"),&lt;br&gt;
    ("cta_present", r"runartree.com", "flag"),&lt;br&gt;
    ("word_count", lambda t: 1200 &amp;lt;= len(t.split()) &amp;lt;= 1800, "flag"),&lt;br&gt;
]&lt;/p&gt;

&lt;p&gt;def qa_check(text: str) -&amp;gt; list[dict]:&lt;br&gt;
    issues = []&lt;br&gt;
    for name, rule, severity in QA_RULES:&lt;br&gt;
        if callable(rule):&lt;br&gt;
            if not rule(text):&lt;br&gt;
                issues.append({"rule": name, "severity": severity})&lt;br&gt;
        else:&lt;br&gt;
            if re.search(rule, text, re.IGNORECASE):&lt;br&gt;
                issues.append({"rule": name, "severity": severity, "match": re.search(rule, text).group()})&lt;br&gt;
    return issues&lt;/p&gt;

&lt;p&gt;&lt;code&gt;block&lt;/code&gt; severity halts the pipeline and routes to human review. &lt;code&gt;flag&lt;/code&gt; severity logs and continues.&lt;/p&gt;

&lt;p&gt;The Hangul check (&lt;code&gt;no_hangul&lt;/code&gt;) is particularly important for the dev.to channel — Hangul in a technical article breaks the channel's expected register and confuses non-Korean readers. All Korean concepts must appear as English + Hanja pairs.&lt;/p&gt;




&lt;h2&gt;
  
  
  [INFO_GRAPHIC] — Sample Extracted Data Structure
&lt;/h2&gt;

&lt;p&gt;The following represents the kind of structured output the pipeline produces from a chart image. Field values are sourced directly from chart image labels, not inferred:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pillar&lt;/th&gt;
&lt;th&gt;Stem (天干)&lt;/th&gt;
&lt;th&gt;Branch (地支)&lt;/th&gt;
&lt;th&gt;Stem Ten-God&lt;/th&gt;
&lt;th&gt;Branch Ten-God&lt;/th&gt;
&lt;th&gt;12-Phase&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;年柱 (Year)&lt;/td&gt;
&lt;td&gt;乙&lt;/td&gt;
&lt;td&gt;未&lt;/td&gt;
&lt;td&gt;偏官 (Seven Killings)&lt;/td&gt;
&lt;td&gt;比肩 (Friend)&lt;/td&gt;
&lt;td&gt;관대&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;月柱 (Month)&lt;/td&gt;
&lt;td&gt;丙&lt;/td&gt;
&lt;td&gt;戌&lt;/td&gt;
&lt;td&gt;正印 (Direct Resource)&lt;/td&gt;
&lt;td&gt;劫財 (Robber)&lt;/td&gt;
&lt;td&gt;양&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;日柱 (Day)&lt;/td&gt;
&lt;td&gt;己&lt;/td&gt;
&lt;td&gt;巳&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;正印 (Direct Resource)&lt;/td&gt;
&lt;td&gt;제왕&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;時柱 (Hour)&lt;/td&gt;
&lt;td&gt;庚&lt;/td&gt;
&lt;td&gt;午&lt;/td&gt;
&lt;td&gt;傷官 (Hurting Officer)&lt;/td&gt;
&lt;td&gt;偏印 (Indirect Resource)&lt;/td&gt;
&lt;td&gt;건록&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;大運 (Grand Luck)&lt;/td&gt;
&lt;td&gt;丁&lt;/td&gt;
&lt;td&gt;亥&lt;/td&gt;
&lt;td&gt;偏印&lt;/td&gt;
&lt;td&gt;正財&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;歲運 2026&lt;/td&gt;
&lt;td&gt;丙&lt;/td&gt;
&lt;td&gt;午&lt;/td&gt;
&lt;td&gt;正印&lt;/td&gt;
&lt;td&gt;偏印&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Notable Shen-sha flags extracted: 역마살 (Travel Horse, 驛馬殺) on Day and Year pillars; 귀문관살 (Ghost Gate) on Day and Month; 공망 (Empty Void, 空亡) on Grand Luck branch; 도화살 (Peach Blossom, 桃花殺) on Hour and Month.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Verbatim extraction before interpretation is non-negotiable.&lt;/strong&gt;&lt;br&gt;
The biggest early failure mode was letting the model interpret and extract simultaneously. Splitting into two passes — raw text out, then schema mapping — dropped label errors by ~70%.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Pydantic validation is your ground truth gate.&lt;/strong&gt;&lt;br&gt;
LLMs are confident when wrong. A closed vocabulary validator (VALID_TEN_GODS, VALID_12PHASE) catches silent errors that would otherwise propagate into published content.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Channel framing changes everything.&lt;/strong&gt;&lt;br&gt;
The same Saju JSON generates a technical pipeline article for dev.to, a reflective newsletter for Substack, and a punchy Instagram caption. The content domain (Saju) is just structured data. The channel strategy is the product.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. The 反轉 (reversal) insight lives in the Shen-sha layer.&lt;/strong&gt;&lt;br&gt;
The most engaging content comes from unexpected Shen-sha combinations — for example, 공망 (Empty Void) falling on the Grand Luck branch simultaneously with 역마살 (Travel Horse) suggests a period of high-mobility activity that paradoxically lacks stable grounding. These non-obvious combinations are the ones readers engage with most, and they are only visible when the extraction is precise enough to surface them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Guardrails must be structural, not instructional.&lt;/strong&gt;&lt;br&gt;
Telling the LLM "don't make predictions" in a user-turn prompt is weak. Injecting it as a system instruction, then running a regex QA check post-generation, is the only reliable approach.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Claude Vision two-pass extraction reliably parses dense Manse-force (萬歲曆) chart images into validated JSON&lt;/li&gt;
&lt;li&gt;Pydantic schema validation with closed vocabularies gates garbage before it reaches generation&lt;/li&gt;
&lt;li&gt;Channel-specific Jinja2 templates transform the same structured data into dev.to, Substack, Instagram, and YouTube formats&lt;/li&gt;
&lt;li&gt;Regex-based QA checks enforce guardrails (no absolute claims, no Hangul, disclaimer present, CTA injected) post-generation&lt;/li&gt;
&lt;li&gt;The Shen-sha layer — spirit stars like 역마살 (Travel Horse), 공망 (Empty Void), 도화살 (Peach Blossom) — contains the highest-engagement content signals and requires extraction precision to surface&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;This article describes a content automation pipeline. Saju analysis outputs are for informational and entertainment purposes only and do not constitute professional advice of any kind.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Want to explore Saju-based content tools or commission a custom chart analysis? Visit *&lt;/em&gt;&lt;a href="https://runartree.com" rel="noopener noreferrer"&gt;runartree.com&lt;/a&gt;** for more.*&lt;/p&gt;




&lt;h2&gt;
  
  
  Project link
&lt;/h2&gt;

&lt;p&gt;This article is based on an automated content workflow for a Korean Saju platform.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Website: &lt;a href="https://runartree.com?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=saju_automation" rel="noopener noreferrer"&gt;https://runartree.com?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=saju_automation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Stack: Python, Claude Vision, channel-specific formatting, content QA&lt;/li&gt;
&lt;li&gt;Domain: Korean Saju / Bazi content automation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key lesson is simple: generation alone is not enough. A useful publishing pipeline also needs formatting, QA, tracking links, and channel-specific editorial rules.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Bazi interpretation. Not medical, legal, or investment advice.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>bazi</category>
      <category>kpop</category>
      <category>saju</category>
      <category>korea</category>
    </item>
    <item>
      <title>Automating Korean Saju Content at Scale: A Python + Claude Vision Pipeline</title>
      <dc:creator>HYUN SOO LEE</dc:creator>
      <pubDate>Mon, 04 May 2026 01:31:19 +0000</pubDate>
      <link>https://dev.to/hyun_soolee_0c4754e81463/automating-korean-saju-content-at-scale-a-python-claude-vision-pipeline-362d</link>
      <guid>https://dev.to/hyun_soolee_0c4754e81463/automating-korean-saju-content-at-scale-a-python-claude-vision-pipeline-362d</guid>
      <description>&lt;h1&gt;
  
  
  Automating Korean Saju Content at Scale: A Python + Claude Vision Pipeline
&lt;/h1&gt;

&lt;h2&gt;
  
  
  The Hook: Why Saju Is a Surprisingly Hard Automation Problem
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91t55fhxdgd7cg0g57z3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91t55fhxdgd7cg0g57z3.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Korean Saju (四柱推命) content is exploding — millions of monthly searches, celebrity chart analyses going viral, and a growing English-language audience curious about East Asian astrology. But here is the problem: the raw data lives inside &lt;strong&gt;image-rendered Manse-ryeok charts&lt;/strong&gt; (萬歲曆, the Korean birth-pillar calculator), full of mixed Hanja (漢字), color-coded circles, and positional metadata that a naive OCR pass completely butchers.&lt;/p&gt;

&lt;p&gt;We needed a pipeline that could ingest one of these chart screenshots, extract every meaningful field without hallucinating, apply domain-specific validation, and output channel-formatted Markdown — for Dev.to, for newsletters, for short-form social — all without a human editor in the loop. This article documents exactly how we built it, using Park Seo-jun's publicly available birth data (1988-12-16, male) as our canonical test case throughout development.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem in Detail
&lt;/h2&gt;

&lt;p&gt;A typical Manse-ryeok screenshot contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Four pillars&lt;/strong&gt; (年柱 · 月柱 · 日柱 · 時柱) each with a Heavenly Stem (天干) and Earthly Branch (地支), rendered as colored circle glyphs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ten-God labels&lt;/strong&gt; (十星) in Korean Hangul above and below each glyph: 比肩(비견), 劫財(겁재), 食神(식신), 傷官(상관), 偏財(편재), 正財(정재), 偏官(편관), 正官(정관), 偏印(편인), 正印(정인)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;12-Stage labels&lt;/strong&gt; (十二運星): 장생, 목욕, 관대, 건록, 제왕, 쇠, 병, 사, 묘, 절, 태, 양&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shen Sha tags&lt;/strong&gt; (神殺): 도화살, 양인살, 백호살, 화개살, 천을귀인, 천덕귀인, 월덕귀인, 문창귀인 — each with bracketed sub-descriptions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Current Grand Luck (大運)&lt;/strong&gt; and &lt;strong&gt;Annual Luck (歲運)&lt;/strong&gt; columns rendered separately&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Standard Tesseract OCR scores roughly 34% field accuracy on these images in our benchmarks. The Hanja glyphs inside colored circles are anti-aliased against dark backgrounds, and positional semantics (which Ten-God belongs to which pillar) are encoded purely by 2-D layout — invisible to a linear text extractor.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg17cpdzi3w9m8sf9qqns.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg17cpdzi3w9m8sf9qqns.png" alt=" " width="800" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pipeline Architecture
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Image Upload]
     │
     ▼
[Claude Vision — Structured Extraction Prompt]
     │
     ▼
[JSON Schema Validator]
     │
     ▼
[Domain Rule Engine (Bazi Logic Checks)]
     │
     ▼
[Channel Formatter (Dev.to / Newsletter / Short-form)]
     │
     ▼
[QA Gate — Guardrail Checklist]
     │
     ▼
[Output Markdown / HTML / JSON]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Each stage is a discrete Python module. The pipeline is orchestrated by a simple FastAPI endpoint that accepts a multipart image upload and a &lt;code&gt;channel&lt;/code&gt; query parameter.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 1 — Claude Vision Extraction
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Prompt Strategy
&lt;/h3&gt;

&lt;p&gt;Naive prompts like &lt;em&gt;"extract the Saju chart"&lt;/em&gt; produce inconsistent JSON. After 40+ iterations, our production prompt uses &lt;strong&gt;positional anchoring&lt;/strong&gt; and &lt;strong&gt;explicit enumeration constraints&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are a Manse-ryeok (萬歲曆) chart parser.
The image contains exactly four pillars: 年柱(Year), 月柱(Month), 日柱(Day), 時柱(Hour).
For EACH pillar extract:
  - heavenly_stem: one Hanja character
  - earthly_branch: one Hanja character
  - stem_ten_god: EXACT Korean label as printed (e.g. 정재, 비견, 식신)
  - branch_ten_god: EXACT Korean label as printed
  - twelve_stage: EXACT Korean label as printed
  - shen_sha: array of EXACT Korean labels as printed, with bracketed descriptions verbatim
Also extract: current_grand_luck (天干, 地支, stem_ten_god, branch_ten_god),
annual_luck_2026 (天干, 地支, stem_ten_god, branch_ten_god, shen_sha array).
Return ONLY valid JSON matching the schema below. Do not infer, translate, or normalize any label.
If a field is not visible, return null. Never substitute a similar label.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The critical instruction is &lt;strong&gt;"EXACT Korean label as printed."&lt;/strong&gt; Without it, Claude occasionally normalizes 정재 to 편재 when it "knows" the theoretical Ten-God for that stem combination — which breaks our downstream domain validator and, more importantly, misrepresents the chart author's own computed output.&lt;/p&gt;

&lt;h3&gt;
  
  
  Extraction Result for Our Test Case
&lt;/h3&gt;

&lt;p&gt;From Park Seo-jun's chart image, Claude Vision returned (condensed):&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Year Pillar (年柱):&lt;/strong&gt; 戊(무) / 辰(진) · stem: 正財(정재) · branch: 正財(정재) · stage: 관대 · shen_sha: [양인살, 백호살, 화개살]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Month Pillar (月柱):&lt;/strong&gt; 甲(갑) / 子(자) · stem: 劫財(겁재) · branch: 偏印(편인) · stage: 병 · shen_sha: [천을귀인, 천덕귀인]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Day Pillar (日柱 — self):&lt;/strong&gt; 乙(을) / 巳(사) · stem: 比肩(비견) · branch: 傷官(상관) · stage: 목욕 · shen_sha: [천덕귀인]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hour Pillar (時柱):&lt;/strong&gt; 壬(임) / 午(오) · stem: 正印(정인) · branch: 食神(식신) · stage: 장생 · shen_sha: [문창귀인, 월덕귀인, 도화살]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Current Grand Luck (大運 — age 30):&lt;/strong&gt; 戊(무) / 辰(진) · stem: 正財(정재) · branch: 正財(정재) · stage: 관대&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2026 Annual Luck (歲運):&lt;/strong&gt; 丙(병) / 午(오) · stem: 傷官(상관) · branch: 食神(식신) · shen_sha: [없음 extracted from image column]&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq1q34k1mga0eoggypoq4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq1q34k1mga0eoggypoq4.png" alt=" " width="800" height="838"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage 2 — JSON Schema Validation
&lt;/h2&gt;

&lt;p&gt;We use &lt;code&gt;jsonschema&lt;/code&gt; with a strict schema. Every &lt;code&gt;stem_ten_god&lt;/code&gt; and &lt;code&gt;branch_ten_god&lt;/code&gt; must match an allowlist of exactly 10 Korean strings. Any extraction returning "편재" when the image clearly shows "정재" fails validation and triggers a re-prompt with the specific field flagged.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TEN_GOD_ALLOWLIST = [
    "비견", "겁재", "식신", "상관",
    "편재", "정재", "편관", "정관",
    "편인", "정인"
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Rejection rate on first pass: ~12% of images. After one re-prompt with field-level feedback: ~2%. We log all failures for fine-tuning a future dedicated vision model.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 3 — Domain Rule Engine
&lt;/h2&gt;

&lt;p&gt;This is where Bazi domain knowledge becomes code. The rule engine runs logical consistency checks:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule R-01 — Day Master Identity:&lt;/strong&gt; The Day Pillar stem Ten-God must always be 比肩(비견) or null. If Claude returns anything else, reject.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule R-02 — Stem/Branch Polarity Consistency:&lt;/strong&gt; 正財(정재) must appear on Yang stems conquering Yin elements, 偏財(편재) on same-polarity conquest. We encode the full 天干 conquest table and flag mismatches as warnings (not hard failures, since the chart tool's own logic may differ).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule R-03 — 12-Stage Sequence Integrity:&lt;/strong&gt; The twelve stages follow a fixed cycle per branch. We verify that the extracted stage label is plausible for the given stem/branch pair.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule R-04 — Shen Sha Cross-Reference:&lt;/strong&gt; 도화살(Peach Blossom 桃花殺), 양인살(Goat Blade 羊刃殺), 천을귀인(Heavenly Noble 天乙貴人), 문창귀인(Literary Star), 백호살(White Tiger), 화개살(Canopy Star), 천덕귀인(Heavenly Virtue Noble), 월덕귀인(Monthly Virtue Noble) each have classical branch-based calculation rules. We flag extractions where a Shen Sha appears on a pillar that should not carry it by classical formula — logged as a "chart-tool variance" rather than an error, since different Korean Saju apps use slightly different Shen Sha assignment rules.&lt;/p&gt;

&lt;p&gt;For Park Seo-jun's chart: 문창귀인(Literary Star) on the Hour Pillar stem, 도화살(Peach Blossom 桃花殺) on the Hour Pillar branch, and 천을귀인(Heavenly Noble 天乙貴人) on the Month Pillar all passed R-04 cleanly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 4 — Channel Formatter
&lt;/h2&gt;

&lt;p&gt;Each channel has a &lt;code&gt;FormatterConfig&lt;/code&gt; dataclass:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@dataclass
class FormatterConfig:
    channel: str          # "devto" | "newsletter" | "shortform"
    language: str         # "en" | "ko" | "mixed"
    hanja_inline: bool    # include Hanja alongside romanization
    word_target: int
    cta_template: str
    prohibited_phrases: list[str]  # guardrail strings
    certainty_cap: str    # max certainty language allowed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;For Dev.to (&lt;code&gt;devto&lt;/code&gt;), &lt;code&gt;language="en"&lt;/code&gt;, &lt;code&gt;hanja_inline=True&lt;/code&gt;, &lt;code&gt;word_target=1500&lt;/code&gt;, and &lt;code&gt;prohibited_phrases&lt;/code&gt; includes &lt;code&gt;["100%", "definitely", "absolutely", "certainly", "guaranteed"]&lt;/code&gt; — enforcing our probabilistic framing guardrail.&lt;/p&gt;

&lt;p&gt;The formatter takes the validated JSON and a topic template, then calls a second Claude completion (text only, no vision) with the structured data injected as a system context block. The channel config is serialized into the prompt as explicit constraints.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 5 — QA Gate
&lt;/h2&gt;

&lt;p&gt;Before any output is written to disk or pushed to an API, a &lt;code&gt;QAChecker&lt;/code&gt; runs eight assertions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Word count within ±10% of target&lt;/li&gt;
&lt;li&gt;Zero occurrences of prohibited certainty phrases&lt;/li&gt;
&lt;li&gt;Zero occurrences of gossip-pattern strings (hardcoded regex for relationship speculation)&lt;/li&gt;
&lt;li&gt;All Hanja characters present where &lt;code&gt;hanja_inline=True&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;CTA URL present exactly once&lt;/li&gt;
&lt;li&gt;Disclaimer line present at document end&lt;/li&gt;
&lt;li&gt;No code fences in Markdown output (our formatter sometimes leaks them)&lt;/li&gt;
&lt;li&gt;Frontmatter block valid YAML&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Failure on any assertion routes the output to a human review queue rather than auto-publishing.&lt;/p&gt;




&lt;h2&gt;
  
  
  [INFO_GRAPHIC] — Pipeline at a Glance
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────┐
│  INPUT: Manse-ryeok chart image (PNG/JPG)               │
│  + channel param + topic template                       │
└────────────────────┬────────────────────────────────────┘
                     │
          ┌──────────▼──────────┐
          │  Claude Vision      │  Structured JSON extraction
          │  Extraction Pass    │  ~88% first-pass accuracy
          └──────────┬──────────┘
                     │ fail → re-prompt (field-level feedback)
          ┌──────────▼──────────┐
          │  JSON Schema        │  Ten-God allowlist, null checks
          │  Validator          │
          └──────────┬──────────┘
                     │
          ┌──────────▼──────────┐
          │  Domain Rule        │  R-01 Day Master, R-02 Polarity,
          │  Engine             │  R-03 12-Stage, R-04 Shen Sha
          └──────────┬──────────┘
                     │ warnings logged, hard fails rejected
          ┌──────────▼──────────┐
          │  Channel Formatter  │  FormatterConfig → Claude text
          │  (text completion)  │  completion with injected JSON
          └──────────┬──────────┘
                     │
          ┌──────────▼──────────┐
          │  QA Gate            │  8 assertions, auto-reject on fail
          └──────────┬──────────┘
                     │
          ┌──────────▼──────────┐
          │  OUTPUT             │  Markdown / HTML / JSON
          │  (or human queue)   │
          └─────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  The Reversal: The Shen Sha Consistency Problem
&lt;/h2&gt;

&lt;p&gt;Here is the most interesting engineering discovery from this project. We initially assumed Shen Sha (神殺) labels were deterministic — given a stem and branch, you can calculate them from classical tables, so they should be a reliable validation signal.&lt;/p&gt;

&lt;p&gt;They are not. At least not across Korean Saju apps.&lt;/p&gt;

&lt;p&gt;When we tested our R-04 validator against 200 chart images from three different Korean Manse-ryeok tools, we found &lt;strong&gt;23% disagreement&lt;/strong&gt; on Shen Sha assignments for the same birth data. 도화살(Peach Blossom 桃花殺) placement varied the most — some tools assign it by Day Branch, others by Year Branch, others by the strongest pillar branch. 양인살(Goat Blade 羊刃殺) had similar variance.&lt;/p&gt;

&lt;p&gt;The implication for content automation: &lt;strong&gt;you cannot use Shen Sha as a hard validation rule&lt;/strong&gt;. You must treat the chart image as the authoritative source and extract verbatim, even when classical tables disagree. Our R-04 now logs variances for analytics but never rejects on Shen Sha mismatch alone. This also reinforced our core prompt instruction: extract exactly what is printed, never infer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Positional anchoring beats semantic description in vision prompts.&lt;/strong&gt; Telling Claude "the Hour Pillar is the leftmost column with a blue header tag" outperforms "find the 時柱." Layout is data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Two-pass is worth the latency.&lt;/strong&gt; Vision extraction + separate text formatting, rather than one combined prompt, improved consistency significantly. The vision pass focuses on reading; the text pass focuses on writing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Domain allowlists are your best friend.&lt;/strong&gt; A 10-item Ten-God allowlist catches more errors than any amount of prompt engineering alone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Guardrails must be mechanical, not instructional.&lt;/strong&gt; Telling the LLM "do not use certainty language" helps but does not guarantee it. The QA Gate's regex check is the actual enforcement mechanism.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Verbatim extraction is a product decision.&lt;/strong&gt; When the chart says 正財(정재), your pipeline must say 正財(정재) — even if your domain model thinks it should be 偏財(편재). The chart tool's output is the contract with the user.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2u74kggi7pg2oyg69ajp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2u74kggi7pg2oyg69ajp.png" alt=" " width="800" height="1071"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;We built a five-stage pipeline (Vision Extraction → Schema Validation → Domain Rules → Channel Formatting → QA Gate) that converts Manse-ryeok chart images into publication-ready content with ~98% field accuracy after re-prompting.&lt;/li&gt;
&lt;li&gt;The hardest problem is not OCR — it is positional semantics and Shen Sha variance across Korean Saju tools, both of which require domain-specific engineering rather than general vision capability.&lt;/li&gt;
&lt;li&gt;Verbatim extraction with mechanical QA gates, not instructional guardrails alone, is the architecture that makes this reliable at scale.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Try the live demo and explore the full chart analysis toolkit at &lt;a href="https://runartree.com" rel="noopener noreferrer"&gt;runartree.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article uses a publicly available birth date for technical demonstration purposes. All Bazi interpretations are probabilistic frameworks based on classical Chinese metaphysical systems and should not be taken as definitive predictions of any individual's life outcomes.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Project link
&lt;/h2&gt;

&lt;p&gt;This article is based on an automated content workflow for a Korean Saju platform.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Website: &lt;a href="https://runartree.com?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=saju_automation" rel="noopener noreferrer"&gt;https://runartree.com?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=saju_automation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Stack: Python, Claude Vision, channel-specific formatting, content QA&lt;/li&gt;
&lt;li&gt;Domain: Korean Saju / Bazi content automation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key lesson is simple: generation alone is not enough. A useful publishing pipeline also needs formatting, QA, tracking links, and channel-specific editorial rules.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Bazi interpretation. Not medical, legal, or investment advice.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>bazi</category>
      <category>kpop</category>
      <category>saju</category>
      <category>korea</category>
    </item>
    <item>
      <title>Building an Automated Saju (四柱) Content Generation Pipeline with Claude Vision + Python</title>
      <dc:creator>HYUN SOO LEE</dc:creator>
      <pubDate>Sun, 03 May 2026 02:56:33 +0000</pubDate>
      <link>https://dev.to/hyun_soolee_0c4754e81463/building-an-automated-saju-si-zhu-content-generation-pipeline-with-claude-vision-python-4gm4</link>
      <guid>https://dev.to/hyun_soolee_0c4754e81463/building-an-automated-saju-si-zhu-content-generation-pipeline-with-claude-vision-python-4gm4</guid>
      <description>&lt;h1&gt;
  
  
  Building an Automated Saju (四柱) Content Generation Pipeline with Claude Vision + Python
&lt;/h1&gt;

&lt;h2&gt;
  
  
  The Hook: Why Saju Is a Surprisingly Hard Automation Problem
&lt;/h2&gt;

&lt;p&gt;A single Saju birth chart image contains &lt;strong&gt;six layers of structured data&lt;/strong&gt; — Heavenly Stems (天干), Earthly Branches (地支), Ten Gods (十星), 12-Phase Cycle (十二運星), Auxiliary Stars (神殺), and decade/annual luck cycles — all rendered as mixed Hanja glyphs, Korean Hangul labels, and color-coded SVG circles inside a single raster PNG.&lt;/p&gt;

&lt;p&gt;OCR alone fails. GPT-4o hallucinates the wrong Ten God when a glyph is small. And if your pipeline misreads one field — say, labeling a Day Pillar (日柱) Heavenly Stem as Direct Wealth (正財) instead of Friend (比肩) — every downstream paragraph is semantically broken and legally risky.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz7qboolqkb5se9z9zp9k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz7qboolqkb5se9z9zp9k.png" alt=" " width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This article documents the full pipeline I built to solve that: image ingestion → structured extraction → multi-pass QA → channel-specific Markdown rendering → automated CTA injection. Saju is the content domain; the architecture generalizes to any glyph-heavy structured document.&lt;/p&gt;




&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;The client brief: generate ~1,500-word editorial articles about public figures' Saju charts, one per trigger event (birthday, comeback, award), across four channels (Dev.to, Naver Blog, Instagram, Threads), each with different tone and format requirements.&lt;/p&gt;

&lt;p&gt;Manual production cost: ~90 min per article × 4 channels = 6 hours per subject.&lt;/p&gt;

&lt;p&gt;Target: under 4 minutes total, with a human QA gate before publish.&lt;/p&gt;

&lt;p&gt;The hard constraint: &lt;strong&gt;zero tolerance for field-swap errors&lt;/strong&gt;. If the chart says the Month Pillar (月柱) Earthly Branch carries a Seven Killings (偏官) star, the output must say Seven Killings — not Direct Officer (正官). Readers in this niche notice immediately, and corrections damage trust faster than silence.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd12s6loxehmzk9p7omyj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd12s6loxehmzk9p7omyj.png" alt=" " width="800" height="993"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pipeline Architecture
&lt;/h2&gt;

&lt;p&gt;[Image Upload]&lt;br&gt;
      │&lt;br&gt;
      ▼&lt;br&gt;
[Stage 1: Claude Vision — Raw Extraction]&lt;br&gt;
      │  structured JSON (all 6 layers)&lt;br&gt;
      ▼&lt;br&gt;
[Stage 2: Python Validator — Schema + Logic Checks]&lt;br&gt;
      │  validated ChartObject&lt;br&gt;
      ▼&lt;br&gt;
[Stage 3: Prompt Builder — Channel × Trigger × Subject]&lt;br&gt;
      │  assembled system+user prompt&lt;br&gt;
      ▼&lt;br&gt;
[Stage 4: Claude Sonnet — Article Draft]&lt;br&gt;
      │  raw Markdown&lt;br&gt;
      ▼&lt;br&gt;
[Stage 5: QA Agent — Guardrail Checks]&lt;br&gt;
      │  flagged diff or PASS&lt;br&gt;
      ▼&lt;br&gt;
[Stage 6: Formatter — Channel Renderer]&lt;br&gt;
      │  final Markdown / HTML / caption&lt;br&gt;
      ▼&lt;br&gt;
[Stage 7: CTA Injector — runartree.com links]&lt;br&gt;
      │&lt;br&gt;
      ▼&lt;br&gt;
[Human Review Gate → Publish]&lt;/p&gt;

&lt;p&gt;Each stage is a discrete Python function. Stages 1, 3, and 4 hit the Anthropic API. Stages 2, 5, 6, and 7 are pure Python with no external calls.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 1: Claude Vision Extraction
&lt;/h2&gt;

&lt;p&gt;The extraction prompt is the most critical piece of engineering in the entire system. It must be &lt;strong&gt;field-by-field, positional, and verbatim&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Key design decisions:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Positional anchoring.&lt;/strong&gt; The prompt names each pillar by its visual column label: Year Pillar (年柱), Month Pillar (月柱), Day Pillar (日柱), Hour Pillar (時柱). This prevents the model from reordering columns when the image layout shifts between chart providers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Verbatim instruction.&lt;/strong&gt; The prompt explicitly says: &lt;em&gt;"Return the Ten God label exactly as printed in Korean Hangul. If the image shows 겁재, return 겁재. Do not translate, normalize, or infer."&lt;/em&gt; This single instruction eliminated ~80% of label-swap errors in testing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Separate passes for stars.&lt;/strong&gt; Auxiliary stars (神殺) — including Empty Void (空亡), Heavenly Noble (天乙貴人), Goat Blade (羊刃殺), Peach Blossom (桃花殺), Travel Horse (驛馬殺) — are extracted in a second Vision call focused only on the small-text annotation rows. Combining them with the main extraction pass degraded accuracy on both.&lt;/p&gt;

&lt;p&gt;Sample extraction schema (simplified):&lt;/p&gt;

&lt;p&gt;chart_schema = {&lt;br&gt;
  "subject": {"name": str, "gender": str, "solar_date": str},&lt;br&gt;
  "pillars": {&lt;br&gt;
    "year":  {"stem": str, "branch": str, "stem_god": str, "branch_god": str, "phase": str, "stars": list},&lt;br&gt;
    "month": {"stem": str, "branch": str, "stem_god": str, "branch_god": str, "phase": str, "stars": list},&lt;br&gt;
    "day":   {"stem": str, "branch": str, "stem_god": str, "branch_god": str, "phase": str, "stars": list},&lt;br&gt;
    "hour":  {"stem": str, "branch": str, "stem_god": str, "branch_god": str, "phase": str, "stars": list},&lt;br&gt;
  },&lt;br&gt;
  "annual_luck": {"year": int, "stem": str, "branch": str, "stem_god": str},&lt;br&gt;
  "decade_luck": {"age": int, "stem": str, "branch": str, "stem_god": str, "branch_god": str, "phase": str, "stars": list}&lt;br&gt;
}&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 2: Python Validator
&lt;/h2&gt;

&lt;p&gt;The validator runs three check classes before any article generation begins.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Structural checks:&lt;/strong&gt; All required keys present. Stem and branch values are members of the canonical 10-stem / 12-branch sets. Ten God values are members of the 10-god set. Phase values are members of the 12-phase set.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Logic checks:&lt;/strong&gt; The Day Pillar stem determines the entire Ten God mapping. The validator recomputes expected Ten God values from the Day Stem and compares against extracted values. Any mismatch triggers a &lt;code&gt;REEXTRACT&lt;/code&gt; flag, which sends the image back to Stage 1 with a targeted correction prompt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Star plausibility checks:&lt;/strong&gt; Certain stars only appear on certain branches. For example, Empty Void (空亡) pairs are deterministic given the Day Pillar stem-branch combination. If the extracted Empty Void branch contradicts the computed pair, the validator flags it.&lt;/p&gt;

&lt;p&gt;In production, the reextraction loop runs a maximum of two times before escalating to human review. About 6% of images require one reextraction; under 1% escalate.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 3: Prompt Builder
&lt;/h2&gt;

&lt;p&gt;The prompt builder assembles a system prompt and user prompt from three inputs: the validated ChartObject, the channel config, and the trigger event.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Channel config&lt;/strong&gt; controls tone register, length target, format rules, and forbidden patterns. Dev.to config specifies: technical/analytical tone, 1,400–1,600 words, Markdown headers, code blocks permitted, no fortune-telling framing, no first-person predictions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trigger event&lt;/strong&gt; controls which chart elements receive editorial emphasis. A birthday trigger emphasizes the Day Pillar (日柱) and the annual luck cycle intersection. A comeback trigger emphasizes the Hour Pillar (時柱) creative stars and the decade luck phase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Subject injection&lt;/strong&gt; inserts the validated chart data as a structured block inside the user prompt, not the system prompt. This keeps the system prompt stable across subjects, which improves caching efficiency and reduces token variance.&lt;/p&gt;

&lt;p&gt;The prompt includes explicit guardrails injected as numbered constraints:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Do not assert any outcome with certainty language (100%, definitely, absolutely, certainly).&lt;/li&gt;
&lt;li&gt;Do not speculate on romantic relationships.&lt;/li&gt;
&lt;li&gt;All Ten God names must match the extracted labels exactly — if the chart shows Friend (比肩), write Friend (比肩), not Robber (劫財).&lt;/li&gt;
&lt;li&gt;End every article with the standard disclaimer line.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Stage 4: Draft Generation
&lt;/h2&gt;

&lt;p&gt;Claude Sonnet generates the draft in a single call. Temperature 0.7 for analytical channels (Dev.to, Naver expert), 0.9 for social channels (Instagram, Threads).&lt;/p&gt;

&lt;p&gt;The nine required content blocks are specified in the prompt as a numbered list with word-count targets per block. The model generally respects these when the blocks are explicit and the total target is within a comfortable range.&lt;/p&gt;

&lt;p&gt;One consistent failure mode: the model occasionally collapses the infographic block into prose when the chart data is complex. The fix was adding an explicit format example for that block in the prompt, showing the exact Markdown table structure expected.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 5: QA Agent
&lt;/h2&gt;

&lt;p&gt;The QA agent runs five automated checks on the draft:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Field echo check:&lt;/strong&gt; Every extracted Ten God label must appear in the draft at least once with its Hanja in parentheses. Missing fields are flagged.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Forbidden phrase scan:&lt;/strong&gt; Regex scan for certainty language, prediction language, and gossip-adjacent phrases. Any match blocks publish.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pillar consistency check:&lt;/strong&gt; The article must not assign a star to a pillar that the chart data does not support. This is done via entity extraction on the draft followed by lookup against the ChartObject.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Length check:&lt;/strong&gt; Word count within ±10% of channel target.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer presence check:&lt;/strong&gt; Final paragraph must contain the standard disclaimer string.&lt;/p&gt;

&lt;p&gt;Pass rate in production: ~91% on first draft. Most failures are field echo misses or length violations, both of which trigger a targeted revision call rather than a full regeneration.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 6: Channel Formatter + Stage 7: CTA Injector
&lt;/h2&gt;

&lt;p&gt;The formatter applies channel-specific transformations: frontmatter injection for Dev.to, &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; wrapping for Naver, caption truncation for Instagram. No content changes — purely structural.&lt;/p&gt;

&lt;p&gt;The CTA injector appends a standardized block pointing to &lt;a href="https://runartree.com" rel="noopener noreferrer"&gt;runartree.com&lt;/a&gt; with UTM parameters encoding the subject, trigger, and channel. This is injected after human review approval, not before, so the reviewer sees clean content.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx3c9r5icntovi6htdl0g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx3c9r5icntovi6htdl0g.png" alt=" " width="800" height="793"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To make the pipeline concrete, here is the structured data the system extracted from the sample chart, rendered as a reference table:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pillar&lt;/th&gt;
&lt;th&gt;Stem (天干)&lt;/th&gt;
&lt;th&gt;Branch (地支)&lt;/th&gt;
&lt;th&gt;Stem God&lt;/th&gt;
&lt;th&gt;Branch God&lt;/th&gt;
&lt;th&gt;Phase&lt;/th&gt;
&lt;th&gt;Key Stars&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Year (年柱)&lt;/td&gt;
&lt;td&gt;癸&lt;/td&gt;
&lt;td&gt;酉&lt;/td&gt;
&lt;td&gt;Seven Killings (偏官) ★&lt;/td&gt;
&lt;td&gt;Indirect Wealth (偏財)&lt;/td&gt;
&lt;td&gt;Longevity (長生)&lt;/td&gt;
&lt;td&gt;Heavenly Noble (天乙貴人), Literary Star (文昌貴人)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Month (月柱)&lt;/td&gt;
&lt;td&gt;丁&lt;/td&gt;
&lt;td&gt;巳&lt;/td&gt;
&lt;td&gt;Friend (比肩) ★&lt;/td&gt;
&lt;td&gt;Robber (劫財)&lt;/td&gt;
&lt;td&gt;Emperor (帝旺)&lt;/td&gt;
&lt;td&gt;Empty Void (空亡)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Day (日柱)&lt;/td&gt;
&lt;td&gt;丁&lt;/td&gt;
&lt;td&gt;酉&lt;/td&gt;
&lt;td&gt;Friend (比肩) ★&lt;/td&gt;
&lt;td&gt;Indirect Wealth (偏財)&lt;/td&gt;
&lt;td&gt;Longevity (長生)&lt;/td&gt;
&lt;td&gt;Heavenly Noble (天乙貴人)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hour (時柱)&lt;/td&gt;
&lt;td&gt;丙&lt;/td&gt;
&lt;td&gt;午&lt;/td&gt;
&lt;td&gt;Robber (劫財)&lt;/td&gt;
&lt;td&gt;Friend (比肩)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;Goat Blade (羊刃殺), Peach Blossom (桃花殺)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026 Annual&lt;/td&gt;
&lt;td&gt;丙&lt;/td&gt;
&lt;td&gt;午&lt;/td&gt;
&lt;td&gt;Robber (劫財)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Decade Luck&lt;/td&gt;
&lt;td&gt;庚&lt;/td&gt;
&lt;td&gt;申&lt;/td&gt;
&lt;td&gt;Direct Wealth (正財)&lt;/td&gt;
&lt;td&gt;Direct Wealth (正財)&lt;/td&gt;
&lt;td&gt;Bath (沐浴)&lt;/td&gt;
&lt;td&gt;Monthly Virtue Noble (月德貴人)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Observation the pipeline flags for editorial emphasis:&lt;/strong&gt; The 2026 annual luck stem-branch 丙午 is identical to the Hour Pillar (時柱) stem-branch. This stem-branch echo between annual luck and a natal pillar is a structurally notable pattern — the pipeline tags it as a &lt;code&gt;PILLAR_ECHO&lt;/code&gt; event and routes it to the "reversal" content block. As &lt;em&gt;Zi Ping Zhen Quan&lt;/em&gt; (子平真詮, He Lun-Qing, Ch. 14) notes, when the annual stem reinforces a natal pillar's energy rather than introducing new qi, the year tends to intensify existing patterns rather than open new directions — amplification, not transformation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Reversal: The Star Nobody Talks About
&lt;/h2&gt;

&lt;p&gt;The most editorially interesting extraction from this chart is not the prominent Heavenly Noble (天乙貴人) appearing on both Year and Day Pillars — that gets covered in every Saju article about this subject.&lt;/p&gt;

&lt;p&gt;The structural surprise is the &lt;strong&gt;Empty Void (空亡) on the Month Pillar (月柱) branch 巳&lt;/strong&gt;. The Month Pillar governs the prime working years and external social performance. An Empty Void here does not indicate absence of achievement — it indicates that conventional metrics of "success" may feel hollow or misaligned to the subject even when externally visible. The pipeline flags this as a &lt;code&gt;REVERSAL_CANDIDATE&lt;/code&gt; because it contradicts the otherwise strong Emperor (帝旺) phase on the same branch. High-phase energy + Empty Void on the same branch is a rare structural tension that generates genuine editorial nuance.&lt;/p&gt;

&lt;p&gt;This is the kind of insight that a purely template-based system misses. The QA agent is specifically designed to surface these contradictions rather than smooth them over.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Verbatim extraction is non-negotiable.&lt;/strong&gt; Any normalization step between Vision extraction and article generation introduces drift. Keep raw labels raw until the article draft itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Two-pass extraction beats one-pass.&lt;/strong&gt; Main chart data and auxiliary stars in separate Vision calls. The quality improvement justifies the added latency and cost.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Logic validation catches what Vision misses.&lt;/strong&gt; The Ten God recomputation check from Day Stem catches ~80% of extraction errors that pass the structural schema check.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Channel config as code, not prompt text.&lt;/strong&gt; Storing channel rules in Python dataclasses rather than prompt strings makes them testable, versionable, and auditable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Human review is a feature, not a bug.&lt;/strong&gt; The pipeline's value is reducing the reviewer's cognitive load from 90 minutes to 5 minutes — not eliminating review entirely.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Claude Vision + two-pass extraction + Python schema validation is a reliable stack for glyph-heavy structured document ingestion.&lt;/li&gt;
&lt;li&gt;Verbatim field extraction with logic-layer verification eliminates the most damaging error class in this domain.&lt;/li&gt;
&lt;li&gt;Channel-specific prompt configs and post-generation QA agents make multi-channel scaling tractable without proportional quality degradation.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Try the Live Chart Tool
&lt;/h2&gt;

&lt;p&gt;The chart extraction and content pipeline described here powers the tools at &lt;strong&gt;&lt;a href="https://runartree.com" rel="noopener noreferrer"&gt;runartree.com&lt;/a&gt;&lt;/strong&gt;. If you are building similar document-to-content pipelines and want to see the output format live, the site runs the full stack in production.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article describes a technical content automation pipeline. All chart interpretations generated by the system are analytical pattern observations based on classical Chinese metaphysical frameworks and do not constitute predictions, guarantees, or professional advice of any kind.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdsqzsqd4wroyeidjj7ba.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdsqzsqd4wroyeidjj7ba.png" alt=" " width="799" height="1075"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Project link
&lt;/h2&gt;

&lt;p&gt;This article is based on an automated content workflow for a Korean Saju platform.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Website: &lt;a href="https://runartree.com?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=saju_automation" rel="noopener noreferrer"&gt;https://runartree.com?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=saju_automation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Stack: Python, Claude Vision, channel-specific formatting, content QA&lt;/li&gt;
&lt;li&gt;Domain: Korean Saju / Bazi content automation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key lesson is simple: generation alone is not enough. A useful publishing pipeline also needs formatting, QA, tracking links, and channel-specific editorial rules.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Bazi interpretation. Not medical, legal, or investment advice.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>bazi</category>
      <category>kpop</category>
      <category>saju</category>
      <category>korea</category>
    </item>
    <item>
      <title>Automating Korean Saju (四柱) Content at Scale: A Python + Claude Vision Pipeline</title>
      <dc:creator>HYUN SOO LEE</dc:creator>
      <pubDate>Sat, 02 May 2026 04:30:00 +0000</pubDate>
      <link>https://dev.to/hyun_soolee_0c4754e81463/automating-korean-saju-si-zhu-content-at-scale-a-python-claude-vision-pipeline-nj7</link>
      <guid>https://dev.to/hyun_soolee_0c4754e81463/automating-korean-saju-si-zhu-content-at-scale-a-python-claude-vision-pipeline-nj7</guid>
      <description>&lt;h1&gt;
  
  
  Automating Korean Saju (四柱) Content at Scale: A Python + Claude Vision Pipeline
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Three facts that broke our first prototype: a single Saju chart image contains six distinct data layers, every channel wants a different voice, and one wrong Heavenly Stem (天干) ruins reader trust permanently.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl8h73b5wya5eqgne3hb0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl8h73b5wya5eqgne3hb0.png" alt=" " width="800" height="822"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Korean Saju (사주, 四柱命理) content is exploding across social platforms. Creators publish chart analyses tied to celebrities, cultural moments, and trending dates. The bottleneck is not demand — it is the extraction-to-publish pipeline.&lt;/p&gt;

&lt;p&gt;A standard Manse chart image (만세력) packs the following into one screenshot:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Four pillars (年柱·月柱·日柱·時柱) each with a Heavenly Stem (天干) and Earthly Branch (地支)&lt;/li&gt;
&lt;li&gt;Ten-God relationships (十神) for every stem and branch&lt;/li&gt;
&lt;li&gt;Twelve Growth Stages (十二運星) per branch&lt;/li&gt;
&lt;li&gt;Spirit Killings (神殺) attached to specific pillars&lt;/li&gt;
&lt;li&gt;A current Great Fortune cycle (大運) with its own stem, branch, and Ten-God&lt;/li&gt;
&lt;li&gt;An Annual Fortune (歲運) overlay for the target year&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Manual extraction by a trained analyst takes 15–25 minutes per chart. At volume — say, a weekly content calendar covering 10 subjects — that is 250 minutes of specialist labor before a single word is written.&lt;/p&gt;

&lt;p&gt;Our goal: reduce extraction + first-draft time to under 90 seconds per chart while keeping accuracy high enough to survive expert review.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqt2mti1xi0q7x69lz3k9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqt2mti1xi0q7x69lz3k9.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pipeline Overview
&lt;/h2&gt;

&lt;p&gt;The pipeline has five stages:&lt;/p&gt;

&lt;p&gt;[Image Input] → [Vision Extraction] → [Structured Validation] → [Prompt Assembly] → [Channel Formatter] → [QA Gate] → [Output]&lt;/p&gt;

&lt;p&gt;Each stage is a discrete Python module. Stages 3 and 6 are the ones that saved us from shipping garbage.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 1 — Image Ingestion
&lt;/h2&gt;

&lt;p&gt;We accept PNG/JPG uploads via a small FastAPI endpoint. Images are resized to a maximum of 1600px on the long edge before being base64-encoded for the Vision API call. Larger images did not improve extraction accuracy in our tests and added latency.&lt;/p&gt;

&lt;p&gt;from PIL import Image&lt;br&gt;
import base64, io&lt;/p&gt;

&lt;p&gt;def prepare_image(path: str, max_long_edge: int = 1600) -&amp;gt; str:&lt;br&gt;
    img = Image.open(path)&lt;br&gt;
    img.thumbnail((max_long_edge, max_long_edge))&lt;br&gt;
    buf = io.BytesIO()&lt;br&gt;
    img.save(buf, format="PNG")&lt;br&gt;
    return base64.b64encode(buf.getvalue()).decode()&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 2 — Claude Vision Extraction
&lt;/h2&gt;

&lt;p&gt;This is the core of the system. We pass the encoded image to Claude with a strict extraction prompt. The prompt instructs the model to return a JSON object with exactly the fields we expect — no inference, no interpretation, only what is visually present in the image.&lt;/p&gt;

&lt;p&gt;Key prompt rules we enforced after painful iteration:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Read the label, do not infer.&lt;/strong&gt; If the image shows 偏財 (Indirect Wealth) on the Hour Pillar Heavenly Stem, output &lt;code&gt;"偏財"&lt;/code&gt;. Do not substitute 正財 (Direct Wealth) because the underlying stem calculation suggests it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Preserve hanja.&lt;/strong&gt; All Ten-God labels, pillar characters, and spirit killing names must be returned in their original Chinese characters alongside the Korean hangul label shown in the image.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Null over guess.&lt;/strong&gt; If a field is not visible — birth hour unknown, for example — return &lt;code&gt;null&lt;/code&gt;. Do not hallucinate a value.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separate layers.&lt;/strong&gt; The Annual Fortune (歲運) overlay must be stored in its own object, not merged into the pillar array.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Sample extraction schema (abbreviated):&lt;/p&gt;

&lt;p&gt;{&lt;br&gt;
  "subject": "BLACKPINK",&lt;br&gt;
  "gender": "female",&lt;br&gt;
  "solar_date": "2016-08-08",&lt;br&gt;
  "lunar_date": "2016-07-06",&lt;br&gt;
  "pillars": {&lt;br&gt;
    "year":  {"stem": "丙", "branch": "申", "stem_god": "偏財", "branch_god": "偏印", "stage": "長生", "killings": ["文昌貴人","暗錄","月空","驛馬殺"]},&lt;br&gt;
    "month": {"stem": "丙", "branch": "申", "stem_god": "偏財", "branch_god": "偏印", "stage": "長生", "killings": ["文昌貴人","暗錄","月空","驛馬殺"]},&lt;br&gt;
    "day":   {"stem": "壬", "branch": "戌", "stem_god": "比肩", "branch_god": "偏官", "stage": "冠帶", "killings": ["月德貴人","白虎殺","火蓋殺"]},&lt;br&gt;
    "hour":  {"stem": "丙", "branch": "午", "stem_god": "偏財", "branch_god": "正財", "stage": "胎",  "killings": ["月空","羊刃殺"]}&lt;br&gt;
  },&lt;br&gt;
  "great_fortune": {"age": 10, "stem": "甲", "branch": "午", "stem_god": "食神", "branch_god": "正財", "stage": "胎"},&lt;br&gt;
  "annual_fortune_2026": {"stem": "丙", "branch": "午", "stem_god": "偏財", "branch_god": "正財", "killing": null}&lt;br&gt;
}&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 3 — Structured Validation
&lt;/h2&gt;

&lt;p&gt;Before any content is generated, a Pydantic model validates the extracted JSON. This catches the most common Vision errors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stem/branch combinations that are calendrically impossible&lt;/li&gt;
&lt;li&gt;Ten-God labels that contradict the Day Master (日主) stem&lt;/li&gt;
&lt;li&gt;Missing required fields for the target content type&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;from pydantic import BaseModel, validator&lt;br&gt;
from typing import Optional&lt;/p&gt;

&lt;p&gt;VALID_STEMS = ["甲","乙","丙","丁","戊","己","庚","辛","壬","癸"]&lt;br&gt;
VALID_BRANCHES = ["子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"]&lt;/p&gt;

&lt;p&gt;class Pillar(BaseModel):&lt;br&gt;
    stem: str&lt;br&gt;
    branch: str&lt;br&gt;
    stem_god: str&lt;br&gt;
    branch_god: str&lt;br&gt;
    stage: str&lt;br&gt;
    killings: list[str] = []&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@validator("stem")
def stem_must_be_valid(cls, v):
    assert v in VALID_STEMS, f"Invalid stem: {v}"
    return v

@validator("branch")
def branch_must_be_valid(cls, v):
    assert v in VALID_BRANCHES, f"Invalid branch: {v}"
    return v
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Validation failures route to a human review queue rather than silently proceeding. Our false-positive rate on valid charts is under 3%.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 4 — Prompt Assembly
&lt;/h2&gt;

&lt;p&gt;Once the structured data is validated, a prompt builder assembles the generation prompt. This is where channel strategy diverges.&lt;/p&gt;

&lt;p&gt;We maintain a &lt;code&gt;ChannelConfig&lt;/code&gt; object per destination:&lt;/p&gt;

&lt;p&gt;@dataclass&lt;br&gt;
class ChannelConfig:&lt;br&gt;
    channel: str          # "devto" | "instagram" | "threads" | "youtube_desc"&lt;br&gt;
    word_target: int&lt;br&gt;
    tone: str             # "technical" | "casual" | "narrative"&lt;br&gt;
    required_blocks: list[str]&lt;br&gt;
    forbidden_patterns: list[str]&lt;br&gt;
    language: str         # "en" | "ko" | "mixed"&lt;/p&gt;

&lt;p&gt;For dev.to, the tone is &lt;code&gt;technical&lt;/code&gt;, the language is &lt;code&gt;en&lt;/code&gt;, and forbidden patterns include absolute certainty language (&lt;code&gt;"will definitely"&lt;/code&gt;, &lt;code&gt;"100%"&lt;/code&gt;, &lt;code&gt;"guaranteed"&lt;/code&gt;). For Instagram, the tone is &lt;code&gt;casual&lt;/code&gt; and the word target drops to 150.&lt;/p&gt;

&lt;p&gt;The prompt builder injects the validated chart JSON, the channel config, and a block template list. It does &lt;strong&gt;not&lt;/strong&gt; pass raw image bytes to the generation call — only the already-validated structured data. This separation means the generation model never has to do double duty as both extractor and writer.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffqrxl0ay8y0lfun9obex.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffqrxl0ay8y0lfun9obex.png" alt=" " width="800" height="1075"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage 5 — Channel Formatter
&lt;/h2&gt;

&lt;p&gt;The formatter takes the raw generation output and applies channel-specific post-processing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dev.to&lt;/strong&gt;: injects YAML frontmatter, converts section headers to &lt;code&gt;##&lt;/code&gt;, ensures code blocks use proper fencing, appends CTA link&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instagram&lt;/strong&gt;: strips all markdown, enforces emoji density cap (max 1 per 30 chars), truncates to 2200 chars&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Threads&lt;/strong&gt;: max 500 chars, single hook sentence + link&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;YouTube description&lt;/strong&gt;: timestamps placeholder, keyword density check&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The formatter also handles the &lt;strong&gt;INFO_GRAPHIC block&lt;/strong&gt; — a markdown table summarizing the four pillars in a scannable format for dev.to readers:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pillar&lt;/th&gt;
&lt;th&gt;Stem (天干)&lt;/th&gt;
&lt;th&gt;Branch (地支)&lt;/th&gt;
&lt;th&gt;Stem God (十神)&lt;/th&gt;
&lt;th&gt;Branch God&lt;/th&gt;
&lt;th&gt;Stage (運星)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Year 年柱&lt;/td&gt;
&lt;td&gt;丙&lt;/td&gt;
&lt;td&gt;申&lt;/td&gt;
&lt;td&gt;Indirect Wealth 偏財&lt;/td&gt;
&lt;td&gt;Indirect Seal 偏印&lt;/td&gt;
&lt;td&gt;Growth 長生&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Month 月柱&lt;/td&gt;
&lt;td&gt;丙&lt;/td&gt;
&lt;td&gt;申&lt;/td&gt;
&lt;td&gt;Indirect Wealth 偏財&lt;/td&gt;
&lt;td&gt;Indirect Seal 偏印&lt;/td&gt;
&lt;td&gt;Growth 長生&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Day 日柱&lt;/td&gt;
&lt;td&gt;壬&lt;/td&gt;
&lt;td&gt;戌&lt;/td&gt;
&lt;td&gt;Friend 比肩&lt;/td&gt;
&lt;td&gt;Seven Killings 偏官&lt;/td&gt;
&lt;td&gt;Officer Belt 冠帶&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hour 時柱&lt;/td&gt;
&lt;td&gt;丙&lt;/td&gt;
&lt;td&gt;午&lt;/td&gt;
&lt;td&gt;Indirect Wealth 偏財&lt;/td&gt;
&lt;td&gt;Direct Wealth 正財&lt;/td&gt;
&lt;td&gt;Embryo 胎&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Stage 6 — QA Gate
&lt;/h2&gt;

&lt;p&gt;This is the stage most pipelines skip and then regret. Our QA gate runs four checks:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Guardrail scan&lt;/strong&gt; — regex pass for absolute-certainty language, gossip triggers (relationship status assertions, health diagnoses), and any hangul characters that leaked into an English-target output.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Ten-God consistency check&lt;/strong&gt; — re-derives the expected Ten-God for each stem from the Day Master using a lookup table and flags mismatches between derived and extracted values. This catches the single most common Vision hallucination: swapping 偏財 (Indirect Wealth) and 正財 (Direct Wealth) when the image label is small.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Word count band&lt;/strong&gt; — flags outputs outside ±15% of the channel word target.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. CTA presence&lt;/strong&gt; — confirms the destination URL appears exactly once.&lt;/p&gt;

&lt;p&gt;Outputs that fail any check are either auto-corrected (word count, CTA) or routed to human review (Ten-God mismatch, guardrail hit).&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Extraction and generation must be separate API calls.&lt;/strong&gt; Asking one model to both read the image and write the article in a single prompt produces confident-sounding errors. Split the jobs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spirit Killings (神殺) are the hardest layer.&lt;/strong&gt; Names like Goat Blade (羊刃殺), Travel Horse (驛馬殺), and Empty Void (空亡) appear in small font with inconsistent spacing. We added a dedicated second Vision pass focused only on the killing labels after the main extraction, then merged results. Accuracy on killings went from 71% to 94%.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Annual Fortune (歲運) overlay is visually ambiguous.&lt;/strong&gt; In many Manse images, the 2026 歲運 column uses the same color scheme as the Great Fortune (大運) column. Explicit prompt instruction — "the Annual Fortune column is the leftmost column labeled with a year, not an age" — was necessary to prevent confusion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pydantic validation pays for itself in the first week.&lt;/strong&gt; Before we added it, approximately one in eight generated articles contained an impossible stem/branch pair that any trained reader would immediately distrust. Validation eliminated that category of error entirely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Channel config as code, not as prompt text.&lt;/strong&gt; Early versions embedded channel instructions directly in the generation prompt. This made A/B testing formats expensive. Moving channel rules into a &lt;code&gt;ChannelConfig&lt;/code&gt; dataclass and keeping the generation prompt channel-agnostic made iteration dramatically faster.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A five-stage pipeline (ingest → extract → validate → generate → QA) reduces Saju chart analysis time from 25 minutes to under 90 seconds while maintaining expert-reviewable accuracy.&lt;/li&gt;
&lt;li&gt;Separating Vision extraction from text generation, and validating the structured intermediate, is the single highest-leverage architectural decision.&lt;/li&gt;
&lt;li&gt;Channel-specific formatting belongs in config objects and post-processors, not in generation prompts.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;This article describes a technical content automation pipeline. Chart data used for pipeline illustration is drawn from publicly available Manse chart images. No claim is made about any individual's future, career, relationships, or outcomes. Saju analysis is a traditional interpretive framework; all outputs should be treated as exploratory content, not as predictive fact.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Explore the tooling at &lt;a href="https://runartree.com" rel="noopener noreferrer"&gt;runartree.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Project link
&lt;/h2&gt;

&lt;p&gt;This article is based on an automated content workflow for a Korean Saju platform.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Website: &lt;a href="https://runartree.com?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=saju_automation" rel="noopener noreferrer"&gt;https://runartree.com?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=saju_automation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Stack: Python, Claude Vision, channel-specific formatting, content QA&lt;/li&gt;
&lt;li&gt;Domain: Korean Saju / Bazi content automation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key lesson is simple: generation alone is not enough. A useful publishing pipeline also needs formatting, QA, tracking links, and channel-specific editorial rules.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Bazi interpretation. Not medical, legal, or investment advice.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>bazi</category>
      <category>kpop</category>
      <category>saju</category>
      <category>korea</category>
    </item>
    <item>
      <title>BTS ARIRANG World Tour 2025–2026: A Four-Pillar Bazi Deep-Dive Into the Group's Collective Destiny</title>
      <dc:creator>HYUN SOO LEE</dc:creator>
      <pubDate>Fri, 01 May 2026 12:13:41 +0000</pubDate>
      <link>https://dev.to/hyun_soolee_0c4754e81463/bts-arirang-world-tour-2025-2026-a-four-pillar-bazi-deep-dive-into-the-groups-collective-destiny-1jnb</link>
      <guid>https://dev.to/hyun_soolee_0c4754e81463/bts-arirang-world-tour-2025-2026-a-four-pillar-bazi-deep-dive-into-the-groups-collective-destiny-1jnb</guid>
      <description>&lt;h1&gt;
  
  
  BTS ARIRANG World Tour 2025–2026: A Four-Pillar Bazi Deep-Dive Into the Group's Collective Destiny
&lt;/h1&gt;




&lt;h2&gt;
  
  
  1 · Hook — Three Lines That Stop the Scroll
&lt;/h2&gt;

&lt;p&gt;The Day Pillar(日柱) sits at 庚戌, a metal axe buried in dry earth — raw, compressed power waiting for a spark. The Year Pillar(年柱) carries 癸巳, Indirect Wealth(偏財) riding a hidden fire that quietly feeds the self. And the 2026 annual pillar arrives as 丙午 — blazing Hurting Officer(傷官) over Direct Officer(正官) — a combination classical texts call the "stage-fire configuration," the moment a performer stops rehearsing and starts &lt;em&gt;burning&lt;/em&gt;.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fym0a9y6imrh49bmyj3fz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fym0a9y6imrh49bmyj3fz.png" alt=" " width="800" height="837"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2 · One-Line Verdict
&lt;/h2&gt;

&lt;p&gt;Day Pillar 庚戌 (Friend/比肩 in the branches) meets a 2026 annual pillar of 丙午 carrying Seven Killings(偏官) in the stem and Direct Officer(正官) in the branch, supercharged by a Peach Blossom(桃花殺) and Goat Blade(羊刃殺) double-activation — this is a chart that earns its loudest applause precisely when the pressure peaks.&lt;/p&gt;




&lt;h2&gt;
  
  
  3 · Classical Mechanics — Stems, Branches, Ten Gods, and Three Spirits
&lt;/h2&gt;

&lt;h3&gt;
  
  
  3a · The Four Pillars at a Glance
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pillar&lt;/th&gt;
&lt;th&gt;Stem (天干)&lt;/th&gt;
&lt;th&gt;Branch (地支)&lt;/th&gt;
&lt;th&gt;Stem Ten God&lt;/th&gt;
&lt;th&gt;Branch Ten God&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Year 年柱&lt;/td&gt;
&lt;td&gt;癸&lt;/td&gt;
&lt;td&gt;巳&lt;/td&gt;
&lt;td&gt;Hurting Officer 傷官&lt;/td&gt;
&lt;td&gt;Seven Killings 偏官&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Month 月柱&lt;/td&gt;
&lt;td&gt;戊&lt;/td&gt;
&lt;td&gt;午&lt;/td&gt;
&lt;td&gt;Indirect Officer 偏印&lt;/td&gt;
&lt;td&gt;Direct Officer 正官&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Day 日柱&lt;/td&gt;
&lt;td&gt;庚&lt;/td&gt;
&lt;td&gt;戌&lt;/td&gt;
&lt;td&gt;Friend 比肩&lt;/td&gt;
&lt;td&gt;Indirect Officer 偏印&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hour 時柱&lt;/td&gt;
&lt;td&gt;壬&lt;/td&gt;
&lt;td&gt;午&lt;/td&gt;
&lt;td&gt;Eating God 食神&lt;/td&gt;
&lt;td&gt;Direct Officer 正官&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The Day Master is 庚 metal — the sword, the bell, the stage rigging. 庚 metal craves fire to be forged and earth to be supported; this chart delivers both in abundance. Month branch 午 and Hour branch 午 form a double Direct Officer(正官) presence in the branches, anchoring institutional recognition. Year stem 癸 as Hurting Officer(傷官) injects creative disruption from the very root of the chart — the natal identity is built on artistic rule-breaking.&lt;/p&gt;

&lt;h3&gt;
  
  
  3b · Ten-God Interplay
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Eating God(食神) at the Hour stem 壬&lt;/strong&gt; is the performer's voice: fluid, generous, audience-facing. Classical theory holds that Eating God feeding into a strong Day Master generates "talent overflow" — creativity that cannot be contained by a single medium. For a group whose discography spans hip-hop, art-pop, and orchestral balladry, this resonates structurally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Indirect Officer(偏印) at both Month stem 戊 and Day branch 戌&lt;/strong&gt; creates a protective intellectual layer. 偏印 absorbs knowledge and converts it into instinct. Two instances of it in the chart suggest a collective that learns from adversity faster than peers — hiatus, military service, industry pressure all become fuel rather than brake.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hurting Officer(傷官) at Year stem 癸&lt;/strong&gt; opposing the Direct Officer(正官) cluster is the chart's central tension. 傷官 and 正官 in the same chart traditionally signal friction with authority structures — labels, industry gatekeepers, national expectations — yet when the Day Master is strong enough to hold both, that friction becomes the creative engine. 庚 metal here is strong: it sits on 戌 earth (Indirect Officer 偏印 support), and the month branch 午 fire forges rather than melts it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyidfpszdxjdbzdxyae0c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyidfpszdxjdbzdxyae0c.png" alt=" " width="790" height="1114"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3c · Three Key Spirits (神殺)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Peach Blossom(桃花殺)&lt;/strong&gt; appears at Month branch 午 and Hour branch 午 — double activation. In classical theory, 午 is the Peach Blossom branch for a 庚 Day Master born in a year containing 巳. Double 午 in month and hour positions means public magnetism is not incidental; it is structurally woven into career timing and daily output. The ARIRANG World Tour is not a coincidence — it is the chart expressing its Peach Blossom(桃花殺) at scale.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Goat Blade(羊刃殺)&lt;/strong&gt; is present at the Day branch 戌 position (noted in the natal chart's branch layer). 羊刃 on the Day branch of a 庚 metal chart amplifies cutting power — competitive edge, physical intensity, willingness to push past comfort. For a performing group, this translates as the capacity to deliver 40-song setlists without visible fatigue. The shadow side is overextension; the 2026 세운 (annual pillar) 丙午 will test this threshold directly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Moon Virtue Noble(月德貴人)&lt;/strong&gt; appears at the Year pillar position, noted in the natal chart. 月德貴人 is a protection spirit associated with institutional backing and the ability to recover from public reversals. Its presence at the Year pillar — the root of social identity — suggests that even in cycles of Seven Killings(偏官) pressure, a structural safety net tends to appear. Think of it as the chart's insurance clause.&lt;/p&gt;




&lt;h2&gt;
  
  
  4 · Classical Authority
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Zi Ping Zhen Quan&lt;/em&gt; (子平真詮, He Lian-Gu, Qing dynasty) states: "When Hurting Officer(傷官) and Direct Officer(正官) coexist in a chart of strong Day Master, the native does not destroy authority — they &lt;em&gt;become&lt;/em&gt; the new authority." — 《子平真詮》卷三·傷官論&lt;/p&gt;

&lt;p&gt;This single passage reframes BTS's entire institutional arc: the tension with HYBE structures, the military service debate, the UN speeches. The chart was never anti-establishment; it was always proto-establishment, building a new one.&lt;/p&gt;




&lt;h2&gt;
  
  
  5 · Modern Reading — ARIRANG Tour × 2026 Annual Pillar × Current Major Cycle
&lt;/h2&gt;

&lt;h3&gt;
  
  
  5a · 2026 Annual Pillar: 丙午
&lt;/h3&gt;

&lt;p&gt;The 2026 세운 (annual pillar) arrives as &lt;strong&gt;丙午&lt;/strong&gt; — stem 丙 fire as &lt;strong&gt;Seven Killings(偏官)&lt;/strong&gt; against the 庚 Day Master, branch 午 as &lt;strong&gt;Direct Officer(正官)&lt;/strong&gt;. The natal chart already carries 午 in two positions; a third 午 in the annual pillar creates a &lt;strong&gt;三午 (triple 午) resonance&lt;/strong&gt; in the branch layer. Classical theory calls this "branch flooding" — the energy of that branch becomes impossible to ignore.&lt;/p&gt;

&lt;p&gt;午 is fire, performance, noon-sun visibility. Triple 午 in 2026 means the group's public presence reaches a structural maximum. The ARIRANG World Tour, running across this window, is timed — whether by design or intuition — into the chart's loudest frequency.&lt;/p&gt;

&lt;p&gt;Stem 丙 as Seven Killings(偏官) carries both risk and reward. For a strong 庚 metal Day Master, 偏官 is the opponent that sharpens the blade. World tours are logistically brutal; this pillar confirms the intensity. But 月德貴人 at the Year root and the double 偏印 in the natal chart provide the absorption capacity to metabolize that pressure.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Goat Blade(羊刃殺)&lt;/strong&gt; activated by the 2026 annual pillar's 午 branch meeting the natal 午 cluster signals peak competitive output — the performances most likely to be cited in retrospectives. The risk is physical and emotional overextension; the mitigation is the 偏印 intellectual buffer already embedded in the chart.&lt;/p&gt;

&lt;h3&gt;
  
  
  5b · Current Major Cycle (大運): 13th Year — 丙辰
&lt;/h3&gt;

&lt;p&gt;The current major cycle (大운) runs through the &lt;strong&gt;丙辰&lt;/strong&gt; pillar: stem 丙 as &lt;strong&gt;Seven Killings(偏官)&lt;/strong&gt;, branch 辰 as &lt;strong&gt;Indirect Officer(偏印)&lt;/strong&gt;. This is a cycle that simultaneously challenges the Day Master's authority and provides the intellectual resources to meet that challenge. 辰 earth contains hidden 乙癸戊 — wood, water, and earth — a storage vault of adaptive capacity.&lt;/p&gt;

&lt;p&gt;The 大운 stem 丙 aligns perfectly with the 2026 annual stem 丙: a double Seven Killings(偏官) activation. In classical theory, when the major cycle and annual pillar share the same stem, the energy of that Ten God is "doubled and focused." This is not a casual year — it is the year the major cycle delivers its central thesis.&lt;/p&gt;




&lt;h2&gt;
  
  
  6 · Infographic Summary
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;[INFO_GRAPHIC]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;╔══════════════════════════════════════════════════════════╗&lt;br&gt;
║         BTS GROUP NATAL CHART — KEY VECTORS 2026        ║&lt;br&gt;
╠══════════════╦═══════════════╦══════════════════════════╣&lt;br&gt;
║ PILLAR       ║ TEN GOD       ║ ACTIVE SPIRIT            ║&lt;br&gt;
╠══════════════╬═══════════════╬══════════════════════════╣&lt;br&gt;
║ Year 癸巳    ║ 傷官/偏官     ║ Moon Virtue Noble 月德貴人║&lt;br&gt;
║ Month 戊午   ║ 偏印/正官     ║ Peach Blossom 桃花殺 ×1  ║&lt;br&gt;
║ Day 庚戌     ║ 比肩/偏印     ║ Goat Blade 羊刃殺        ║&lt;br&gt;
║ Hour 壬午    ║ 食神/正官     ║ Peach Blossom 桃花殺 ×2  ║&lt;br&gt;
╠══════════════╬═══════════════╬══════════════════════════╣&lt;br&gt;
║ 2026 세운    ║ 偏官(stem)    ║ Triple 午 Branch Flood   ║&lt;br&gt;
║ 丙午         ║ 正官(branch)  ║ Goat Blade 羊刃 Trigger  ║&lt;br&gt;
╠══════════════╬═══════════════╬══════════════════════════╣&lt;br&gt;
║ 大운 丙辰    ║ 偏官(stem)    ║ 偏印 Storage Vault       ║&lt;br&gt;
║ (13th yr)    ║ 偏印(branch)  ║ Double 丙 Focus          ║&lt;br&gt;
╚══════════════╩═══════════════╩══════════════════════════╝&lt;br&gt;
VERDICT: Peak public visibility cycle. High output, high pressure.&lt;br&gt;
Moon Virtue Noble(月德貴人) provides structural safety net.&lt;/p&gt;




&lt;h2&gt;
  
  
  7 · The Reversal — The Unexpected Twist
&lt;/h2&gt;

&lt;p&gt;Here is what most practitioners miss: &lt;strong&gt;the Hour Pillar(時柱) Eating God(食神) 壬 is quietly the most powerful force in this chart for 2026.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Everyone focuses on the Seven Killings(偏官) 丙 in the annual pillar. But 壬 water Eating God(食神) in the Hour stem controls 丙 fire through the water-over-fire relationship (水剋火). The very stem that generates the most pressure — 丙 Seven Killings(偏官) — is structurally restrained by the Hour stem's Eating God(食神). This is the classical "Eating God Controlling Seven Killings(食神制殺)" formation, one of the most celebrated configurations in Four-Pillar theory.&lt;/p&gt;

&lt;p&gt;What this means practically: the 2026 pressure cycle has a built-in release valve. The group's creative output — the music itself, the performances, the artistic decisions — is the mechanism that converts Seven Killings(偏官) pressure into productive energy. The ARIRANG World Tour is not just a commercial event; structurally, it is the chart's pressure-management system operating at full capacity.&lt;/p&gt;

&lt;p&gt;The Peach Blossom(桃花殺) double-activation in the natal chart means the audience is the catalyst. The larger the crowd, the more efficiently the 食神制殺 mechanism operates. Stadiums, in this reading, are not optional — they are the chart's preferred operating environment.&lt;/p&gt;




&lt;h2&gt;
  
  
  8 · Three-Line Summary
&lt;/h2&gt;

&lt;p&gt;The 庚戌 Day Master chart carries a rare 食神制殺 formation that converts peak-pressure cycles into peak-performance cycles. The 2026 annual pillar 丙午 triggers triple 午 branch flooding, Goat Blade(羊刃殺) activation, and double Seven Killings(偏官) focus — yet the Hour stem 壬 Eating God(食神) holds the architecture together. The ARIRANG World Tour lands in the chart's structurally loudest window; the classical indicators suggest this tour may define the group's legacy more than any prior cycle.&lt;/p&gt;




&lt;h2&gt;
  
  
  9 · Go Deeper
&lt;/h2&gt;

&lt;p&gt;Want to run your own Four-Pillar chart against the 2026 annual pillar?&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://runartree.com" rel="noopener noreferrer"&gt;runartree.com&lt;/a&gt; — generate your full Bazi natal chart, identify your active Ten Gods, and see which 2026 triggers apply to your personal configuration.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article is written for educational and entertainment purposes. Four-Pillar Bazi analysis reflects classical theoretical frameworks and does not constitute personal fortune-telling, financial advice, or verified prediction of future events. Individual outcomes vary based on free will, environment, and factors beyond any astrological system.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Bazi interpretation. Not medical/legal/investment advice.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>bazi</category>
      <category>kpop</category>
      <category>saju</category>
      <category>korea</category>
    </item>
    <item>
      <title>The Stars Were Always Watching: Heo Nam-jun's Bazi Chart and the 2026 Surge Nobody Saw Coming</title>
      <dc:creator>HYUN SOO LEE</dc:creator>
      <pubDate>Thu, 30 Apr 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/hyun_soolee_0c4754e81463/the-stars-were-always-watching-heo-nam-juns-bazi-chart-and-the-2026-surge-nobody-saw-coming-4hj4</link>
      <guid>https://dev.to/hyun_soolee_0c4754e81463/the-stars-were-always-watching-heo-nam-juns-bazi-chart-and-the-2026-surge-nobody-saw-coming-4hj4</guid>
      <description>&lt;h1&gt;
  
  
  The Stars Were Always Watching: Heo Nam-jun's Bazi Chart and the 2026 Surge Nobody Saw Coming
&lt;/h1&gt;




&lt;h2&gt;
  
  
  1 · Hook — Three Lines That Stop the Scroll
&lt;/h2&gt;

&lt;p&gt;&lt;a href="/_engine/assets/manseryeok/manse_sample.png" class="article-body-image-wrapper"&gt;&lt;img src="/_engine/assets/manseryeok/manse_sample.png" alt="Manseryeok"&gt;&lt;/a&gt; The Day Pillar(日柱) reads 辛酉 — a razor-edged metal blade sitting on its own mirror. The Month Pillar(月柱) carries 戊午 with 偏官 pressing down from above and 羊刃殺(Goat Blade) burning underneath. And the 2026 annual pillar drops 丙午 directly onto that same axis — a second flame landing on an already-lit fuse.&lt;/p&gt;

&lt;p&gt;Eight days before &lt;em&gt;My Royal Nemesis&lt;/em&gt; premieres, the chart is already screaming.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6kd8p3ono64hwl31gd8n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6kd8p3ono64hwl31gd8n.png" alt=" " width="784" height="1072"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2 · One-Line Verdict
&lt;/h2&gt;

&lt;p&gt;Day Pillar 辛酉(比肩·비견), anchored by a 正官(Direct Officer) year stem in 2026, converging with the Grand Luck(大運) stem 甲(正財), signals a window in which public recognition and material reward arrive together — not separately, not later.&lt;/p&gt;




&lt;h2&gt;
  
  
  3 · Bazi Mechanics — Reading Every Layer of the Chart
&lt;/h2&gt;

&lt;h3&gt;
  
  
  3-a · The Four Pillars at a Glance
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Year Pillar(年柱) 癸酉&lt;/strong&gt;&lt;br&gt;
Stem 癸 = 食神(Eating God) / Branch 酉 = 比肩(Friend).&lt;br&gt;
The 食神 sitting on the year stem is the classical marker of creative output that earns its own audience. 癸 water feeds the Day Master 辛 metal gently, giving the native an instinct for &lt;em&gt;performing&lt;/em&gt; rather than forcing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Month Pillar(月柱) 戊午&lt;/strong&gt;&lt;br&gt;
Stem 戊 = 正印(Direct Officer reading: the image shows 정인, i.e. Direct Resource) / Branch 午 = 偏官(Seven Killings).&lt;br&gt;
The month position is the engine room of a chart. 正印 overhead means the native absorbs craft — training, technique, mentorship — with unusual retention. But the 偏官 in 午 below is the pressure valve: it creates urgency, competitive tension, the drive to prove something. The 羊刃殺(Goat Blade) tag on 午 sharpens that edge to a point. Goat Blade in classical texts signals intensity that, when channelled, becomes extraordinary focus; when unchecked, becomes self-sabotage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Day Pillar(日柱) 辛酉&lt;/strong&gt;&lt;br&gt;
Stem 辛 = 比肩(Friend) / Branch 酉 = 比肩(Friend).&lt;br&gt;
辛 sitting on 酉 is the strongest expression of the Day Master — metal on metal, the jeweller's blade. The 건록(Jianlu / Established Prosperity) tag on 酉 is significant: this is the 12-stage cycle peak of self-reliance. The native does not need external scaffolding to stand. He &lt;em&gt;is&lt;/em&gt; the scaffold.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hour Pillar(時柱) 甲午&lt;/strong&gt;&lt;br&gt;
Stem 甲 = 正財(Direct Wealth) / Branch 午 = 偏官(Seven Killings).&lt;br&gt;
Birth time is recorded as 모름시 (unknown), so the hour pillar shown here is a system-generated placeholder. I will reference it only structurally, not predictively, to respect the data boundary.&lt;/p&gt;

&lt;h3&gt;
  
  
  3-b · Shinsal (神殺) Cluster — Three or More
&lt;/h3&gt;

&lt;p&gt;The image surfaces four named 신살 across the four pillars:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pillar&lt;/th&gt;
&lt;th&gt;Shinsal (English + Hanja)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Year 午·月 午&lt;/td&gt;
&lt;td&gt;天乙貴人 Heavenly Noble — "heaven-sent guardian, descends when needed"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Year·Month&lt;/td&gt;
&lt;td&gt;月德貴人 Monthly Virtue Noble — amplifies 관(官) luck via institutional channels&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Month 午&lt;/td&gt;
&lt;td&gt;羊刃殺(Goat Blade) — intensity, surgical precision, double-edged ambition&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Month 午&lt;/td&gt;
&lt;td&gt;도화살(Peach Blossom 桃花殺) — magnetism, public fascination, the audience-pull force&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Year·Month&lt;/td&gt;
&lt;td&gt;양인살(Goat Blade, confirmed second instance on 월주)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The 天乙貴人(Heavenly Noble) appearing in both year and month positions is not cosmetic. Classical Bazi holds that 天乙貴人 in the birth chart functions as a background rescue mechanism — the right person appears, the door opens at the last moment. For a performing artist, this often manifests as the audition that almost didn't happen, the director who took the call.&lt;/p&gt;

&lt;p&gt;The 도화살(Peach Blossom 桃花殺) on the Month Branch 午 is the structural reason audiences find the native compelling without being able to articulate why. It is not romantic luck in isolation; it is &lt;em&gt;charismatic gravity&lt;/em&gt; — people lean in.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faky4k48orr55rzit1po5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faky4k48orr55rzit1po5.png" alt=" " width="800" height="824"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3-c · The 辛·酉 Self-Rooted Structure
&lt;/h3&gt;

&lt;p&gt;When the Day Stem and Day Branch share the same elemental identity (辛 = Yin Metal, 酉 = pure Yin Metal), the Day Master is described in classical texts as &lt;em&gt;jianlu&lt;/em&gt; (建禄格, Established Prosperity Pattern). The native does not depend on resource stars to feel capable. This creates a particular performer archetype: one who can carry silence on screen, who does not overact to fill space, because the internal structure is already full.&lt;/p&gt;




&lt;h2&gt;
  
  
  4 · Classical Anchor
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;"辛金軟弱，溫潤而清。畏土之埋，樂水之盈。"&lt;br&gt;
&lt;em&gt;"Xin Metal is soft yet keen; it delights in water's nourishment and fears burial by earth."&lt;/em&gt;&lt;br&gt;
— 《滴天髓》&lt;em&gt;(Di Tian Sui / Drops of Heavenly Marrow)&lt;/em&gt;, attributed to Jing Tu, annotated by Ren Tiequiao (任鐵樵), Chapter on Day Masters.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The 癸 water on the Year Stem is precisely the "water's nourishment" the classical text prescribes. The 戊 earth on the Month Stem is precisely the "burial" it warns against — yet here 戊 carries 正印, meaning the earth is &lt;em&gt;structured&lt;/em&gt; resource, not smothering soil. The chart self-balances in a way that classical commentators would call 중화(中和, equilibrium).&lt;/p&gt;




&lt;h2&gt;
  
  
  5 · Modern Reading — Trigger × Annual Luck × Grand Luck
&lt;/h2&gt;

&lt;h3&gt;
  
  
  5-a · 2026 Annual Pillar 丙午
&lt;/h3&gt;

&lt;p&gt;The 2026 세운(Annual Luck) presents:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stem 丙 = &lt;strong&gt;正官(Direct Officer)&lt;/strong&gt; — the ten-god of public recognition, institutional legitimacy, and formal role assignment. For an actor, this is &lt;em&gt;casting, contract, critical acknowledgment&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Branch 午 = &lt;strong&gt;偏官(Seven Killings)&lt;/strong&gt; — the same branch that sits in the Month Pillar. This is a 午午 self-penalty / reinforcement depending on chart context; here it amplifies the existing 偏官 pressure into a visible, external test.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The 正官 year stem landing on a 辛 Day Master is one of the cleaner recognition signals in Bazi. 辛 metal is governed by 丙 fire (丙 controls 辛 in the five-element cycle). When the controlling element arrives as 正官 rather than 偏官, it is discipline with reward, not punishment without cause.&lt;/p&gt;

&lt;h3&gt;
  
  
  5-b · Current Grand Luck (大運) 甲寅 — Age 31
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Stem 甲 = &lt;strong&gt;正財(Direct Wealth)&lt;/strong&gt; — the ten-god of earned, stable material return. Not windfall; &lt;em&gt;sustained income from recognised craft&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Branch 寅 = &lt;strong&gt;正財(Direct Wealth)&lt;/strong&gt; — double 正財 in the Grand Luck pillar is rare and structurally significant. It means the entire 10-year cycle (approximately ages 28–38) is oriented toward building something durable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The 甲寅 Grand Luck also carries the 天乙貴人(Heavenly Noble) tag confirmed in the image. A noble star activated inside the Grand Luck window means the background rescue mechanism is &lt;em&gt;on&lt;/em&gt;, not dormant.&lt;/p&gt;

&lt;h3&gt;
  
  
  5-c · Convergence Point — D-8 Before Premiere
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;My Royal Nemesis&lt;/em&gt; premieres in eight days from the date of this analysis. The 丙午 annual pillar is active. The 甲寅 Grand Luck is mid-cycle. The natal 도화살(Peach Blossom) on Month Branch 午 is being directly stimulated by the 2026 Branch 午. In Bazi, when an annual branch mirrors a natal branch carrying 桃花殺, public visibility tends to spike — not because of manufactured promotion, but because the native's natural magnetism is operating at a structural peak.&lt;/p&gt;

&lt;p&gt;This is not a prediction. It is a pattern-recognition statement: the chart conditions in 2026 are among the most convergent in the native's recorded luck cycle to date.&lt;/p&gt;




&lt;h2&gt;
  
  
  6 · [INFO_GRAPHIC]
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────┐
│              HEO NAM-JUN  四柱命理  SNAPSHOT               │
├──────────┬──────────┬──────────┬──────────┬────────────────┤
│  年柱    │  月柱    │  日柱    │  時柱    │  2026 세운     │
│  癸酉    │  戊午    │  辛酉    │  甲午    │  丙午          │
│  食神    │  正印    │  比肩    │  正財    │  正官          │
│  比肩    │  偏官    │  比肩    │  偏官    │  偏官          │
├──────────┴──────────┴──────────┴──────────┴────────────────┤
│  KEY SHINSAL                                               │
│  天乙貴人  Heavenly Noble   → Year + Month position       │
│  月德貴人  Monthly Virtue   → Year + Month position       │
│  羊刃殺   Goat Blade        → Month Branch 午             │
│  桃花殺   Peach Blossom     → Month Branch 午             │
├─────────────────────────────────────────────────────────────┤
│  GRAND LUCK (大運) Age 31: 甲寅 — 正財 / 正財             │
│  2026 ANNUAL:  丙午 — 正官 / 偏官                         │
└─────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  7 · The Reversal — What Nobody Mentions
&lt;/h2&gt;

&lt;p&gt;Everyone fixates on the 도화살(Peach Blossom 桃花殺) as a charm indicator. The overlooked element is the &lt;strong&gt;午午 self-encounter&lt;/strong&gt; between the Month Branch natal 午 and the 2026 Annual Branch 午.&lt;/p&gt;

&lt;p&gt;In classical Bazi, 午午 is classified as a &lt;em&gt;self-penalty&lt;/em&gt; (自刑, &lt;em&gt;zixing&lt;/em&gt;) — the same branch meeting itself. Self-penalties are not straightforward bad luck; they are &lt;em&gt;amplifiers of whatever is already present&lt;/em&gt;. If the native is disciplined, the self-penalty accelerates output. If the native is scattered, it accelerates collapse. Given that the 甲寅 Grand Luck is 正財 dominant — structured, patient, craft-oriented — the 午午 amplification in 2026 is more likely to turbocharge the existing momentum than to derail it.&lt;/p&gt;

&lt;p&gt;The 건록(Jianlu) tag on the Day Branch 酉 reinforces this: a self-reliant Day Master under a 正官 annual stem, inside a 正財 Grand Luck, facing a 午午 self-penalty that amplifies rather than destroys — this is the chart of someone who rises precisely when the pressure becomes unbearable for others.&lt;/p&gt;




&lt;h2&gt;
  
  
  8 · Three-Line Summary
&lt;/h2&gt;

&lt;p&gt;The natal 辛酉 Day Pillar gives Heo Nam-jun a self-rooted, precision-edged structure that does not require external validation to function. The 2026 annual pillar 丙午 introduces 正官 — public recognition, formal legitimacy — at the exact moment a major drama role arrives. The Grand Luck 甲寅 wraps both in a decade of 正財 accumulation, suggesting that whatever visibility 2026 delivers is not a flash but a foundation.&lt;/p&gt;




&lt;h2&gt;
  
  
  9 · CTA
&lt;/h2&gt;

&lt;p&gt;&lt;a href="/_engine/assets/form_US.png" class="article-body-image-wrapper"&gt;&lt;img src="/_engine/assets/form_US.png" alt="Input Form"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Want your own Four Pillars chart read with this level of structural detail?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;→ &lt;a href="https://runartree.com" rel="noopener noreferrer"&gt;runartree.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Upload your birth data, receive a full Bazi analysis grounded in classical texts — not algorithmic guesswork.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Disclaimer: This article is written for educational and entertainment purposes only. Bazi (四柱命理) is a traditional East Asian interpretive framework and does not constitute a guarantee of any future outcome. No statements herein should be construed as financial, career, or personal life advice. All interpretations are probabilistic pattern readings, not deterministic predictions.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Bazi interpretation. Not medical/legal/investment advice.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>bazi</category>
      <category>kpop</category>
      <category>saju</category>
      <category>korea</category>
    </item>
  </channel>
</rss>
