開發歷程:紫微斗數命盤解讀——在不上傳生辰的前提下看懂你的星盤

這是 LocalPapa Notes 開發紀錄系列的第十五篇。

排盤工具上線之後,有個問題馬上出現:使用者看到十二宮星盤,然後呢? 對大多數人來說,「武曲在命宮、廉貞在財帛宮」是一堆沒有意義的名字。缺少解讀,排盤只是一個漂亮的格子。

三條解讀路徑,只有一條不違反承諾

解讀這件事,有三條工程路徑可以走:

A. 本地查表:把解讀文字預先編進 JS,頁面直接查表組字,完全不離開裝置。

B. 我方呼叫 AI:把命盤結果送到後端,呼叫 LLM,回傳解讀文字。解讀品質最高,但你的生辰和命盤會飛到我們的伺服器。

C. 本地計算+一鍵交給使用者自己的 AI:頁面本地算好命盤,提供「複製命盤摘要」按鈕,讓使用者自己貼到 ChatGPT 問。使用者決定要不要上傳。

選哪條?LocalPapa 的定位是「100% 瀏覽器、不上傳」——B 直接排除。C 是個有趣的混合設計,但它把解讀責任推給使用者和第三方 AI,品質不在我們的控制裡。最後選 A:本地查表,解讀完全在你的裝置上完成,關掉頁面、生辰消失,沒有例外。

組合式查表:把 168 格降到 40 筆

命盤解讀的核心是「哪顆星在哪個宮位,意味著什麼」。直覺做法:為 14 顆主星 × 12 個宮位 = 168 個組合各寫一段文字。這樣會有幾個問題:

  1. 手刻 168 段文字,內容幾乎必然有品質不均和格式漂移。
  2. 維護地獄:改一顆星的描述,要遍歷它在 12 個宮的 12 段文字。
  3. OKF 同步:知識庫 .md 也要同步——168 個地方要同步更新,而不是 14 個。

改成組合式

  • 星曜本質(14 筆):每顆星本身的個性——武曲是「財富、剛毅、行動力」,廉貞是「事業欲、規則、複雜情緒」……
  • 宮位領域(12 筆):每個宮位的管轄範疇——命宮是「自我、個性、外在形象」,財帛宮是「財務觀念、賺錢方式、花費傾向」……
  • 合體:解讀時把星曜本質和宮位領域動態組句,「武曲在命宮」→「你在自我個性上帶有財富剛毅行動力的傾向」。

這樣 14 + 12 = 26 筆就能涵蓋基礎解讀(不含命宮詳解)。再加上 14 篇命宮個別詳解(命宮是最重要的宮,值得獨立一篇)和 4 個四化的效果說明,總共 44 筆內容——比 168 少 75%,品質卻更容易把控,OKF 同步也簡單得多。

組合式查表的代價是「犧牲特殊情境的精確性」——武曲在命宮的組合文字,不如逐一手刻的精準。但對 MVP 而言,「涵蓋廣、品質穩定、可維護」比「少數組合最精準」更重要。這是一個刻意的取捨,也標示在頁面上(「一般傾向,非精準論命」)。

單一真實來源,雙輸出

解讀文字放在哪裡?規則和 OKF 一樣:build_ziwei_okf.py 持有,產生器雙輸出——

  1. tools/ziwei-interpret.jswindow.ZiweiInterpret):瀏覽器用的解讀資料,同源 JS、免 fetch、可被 Service Worker 離線快取。頁面的 renderInterpret(chart, lang) 讀它組字。
  2. OKF 星曜頁okf/ziwei/stars/*.md):每顆星的 OKF 頁多了「一般傾向」段落,AI agent 讀知識庫時也能看到同一份解讀知識。

一份資料,兩個出口。修改一次,兩邊同步。

踩到的語言碼坑

初版上線後,切換到中文看解讀,整個解讀區只剩星名,沒有文字。英文切換正常。

根因:ziwei-interpret.js 的解讀資料以 zhen 作為語言鍵;但頁面的語言碼是 zh-TWen。查詢時拿 zh-TW 去找 zh,當然找不到。

修正:在 renderInterpret 入口加一行語言碼正規化——lang.startsWith('zh') ? 'zh' : 'en'。一行,問題消失。但這個 bug 的性質值得記:不是邏輯錯,是介面契約沒對齊。資料持有者(產生器)用一套命名慣例,呼叫者(頁面)用另一套,兩者各自正確但對不上。這類 bug 靜默、難 reproduce、在多語系場景特別容易發生。

三方四正:引擎已算好,頁面只取用

命盤解讀 MVP 只看「單宮」——命宮的星曜傾向。進階一步是三方四正:傳統紫微技法,命宮不能孤立看,要看它和財帛宮(三合之一)、官祿宮(三合之二)、遷移宮(對宮)的主星共同論斷——這四個宮合稱「三方四正」,是命理師評估一個人整體格局的基本切面。

怎麼實作?引擎在排盤時已經算好十二宮的位置和各宮主星。三方四正不需要重新計算——只需要以宮名取宮:從已算好的盤裡,byName('命宮'), byName('財帛宮'), byName('官祿宮'), byName('遷移宮') 各取主星列表,再送進現有的 starEssence 組字邏輯。

新增的程式量非常小:引擎不動、解讀邏輯不動,只多了四個宮名查詢和一段渲染函式。三方四正的說明文字放進 build_ziwei_okf.pySANFANG 結構,產生器同時輸出:

  • ziwei-interpret.jssanfang 區塊(頁面查表用)
  • okf/ziwei/sanfang.md(知識庫用)

空宮(無主星)時顯示「對宮借看」提示,以遷移宮主星借代命宮——傳統做法,也優雅降級。

驗證:取 1990 年生命盤,逐一確認命武曲天相、財帛廉貞天府、官祿紫微、遷移破軍——四宮四星對照傳統論命書吻合。

深度解讀模式的跨服務複用

三方四正落地之後,有一個意外的收穫:這個「產生器持有 → 雙輸出 → 頁面查表 → 空宮降級」的模式被完整驗證,可以移植到其他服務

達摩一掌經後來的六道根性、四柱交互,都是這個模式的複用。每次「新增一個命理服務的解讀層」,不再是從頭設計,而是套用這個已驗證的範式——加一段產生器資料、重跑、頁面多一段渲染函式。

學到的事

  • 解讀架構決定隱私邊界。 三條路選 A 不只是技術決定,是「什麼留在裝置、什麼離開裝置」的價值判斷。
  • 組合式優於窮舉式。 26 筆能覆蓋 168 個組合的基礎解讀,換來的是可維護性和 OKF 同步性。
  • 語言碼要在介面邊界統一。 資料用 zh、頁面用 zh-TW 這類靜默不匹配,在多語系系統裡是慢性病。
  • 三方四正教的不只是命理,是「引擎已算好的資料不要重算」。 取用已有的宮位資料,比為三方四正另寫演算更正確、更可維護。
  • 解讀模式一旦驗證,要打包成可複用範式。 第一次做費工,之後每個命理服務都是套用。

一以貫之的問題

這篇的核心問題是:在不把使用者的生辰送出裝置的前提下,能提供多深的解讀?

答案是:比你想的深。組合式本質加域域、三方四正會照格局、多達十幾段的中英雙語解讀——全部在你的瀏覽器裡完成,關閉頁面即消失,沒有伺服器日誌,沒有資料庫。這不是功能限制的說明,是一個架構選擇的展示。

下一篇,我們把方向轉一個大彎——樂透預測工具的「預測」是什麼意思?時間種子 LCG、確定性娛樂,以及為什麼「預測」這個詞在這裡是個有趣的謊言。想追蹤系列?把 LocalPapa Notes 加入書籤吧。

Dev Log: Zi Wei Chart Interpretation — Reading Your Chart Without Uploading a Single Byte

This is the fifteenth post in the LocalPapa Notes dev-log series.

After the chart engine went live, a gap became obvious: the user sees twelve palace positions filled with star names — then what? For most people, "武曲 in the Life Palace, 廉貞 in the Wealth Palace" is a sequence of unfamiliar names. Without interpretation, a chart is just a pretty grid.

Three interpretation paths — only one keeps the promise

There are three engineering paths for chart interpretation:

A. Local table lookup: pre-encode interpretation text in JS, render directly in the browser. Nothing leaves the device.

B. Server-side AI call: send the chart to a backend, call an LLM, return the interpretation. Highest quality, but the user's birth data and chart travel to our servers.

C. Local computation + one-click to the user's own AI: calculate the chart locally, provide a "copy chart summary" button so the user can paste it into ChatGPT themselves. The user decides whether to upload.

Which to pick? LocalPapa's position is "100% browser, no upload" — B is out immediately. C is an interesting hybrid, but it pushes interpretation quality off our hands to a third-party AI. We chose A: local lookup, interpretation fully on-device. Close the tab, the birth date disappears, no exceptions.

Combinatorial lookup: 168 cases collapsed to 40 entries

The core of chart interpretation is "what does this star in this palace mean." The instinctive approach: write a paragraph for each of 14 major stars × 12 palaces = 168 combinations. Problems with that:

  1. Handcrafting 168 text entries almost guarantees uneven quality and format drift.
  2. Maintenance hell: change one star's description, revisit 12 entries spread across 12 palaces.
  3. OKF sync: the knowledge-base .md files need to stay in sync too — 168 places instead of 14.

The combinatorial approach instead:

  • Star essence (14 entries): each star's core personality — 武曲 is "wealth, fortitude, drive"; 廉貞 is "career ambition, rule-following, complex emotions"…
  • Palace domain (12 entries): each palace's area of governance — Life Palace is "self, personality, outward image"; Wealth Palace is "financial outlook, earning style, spending tendencies"…
  • Combination: at render time, dynamically assemble "star essence + palace domain" into a sentence.

That's 14 + 12 = 26 entries for baseline interpretations. Add 14 individual Life Palace deep-reads (the Life Palace is the most important palace, worth its own detailed entry) and 4 Four-Transformation effect descriptions — total 44 entries, 75% fewer than 168, yet more consistent quality and far easier OKF sync.

The trade-off: combinatorial text sacrifices precision for uncommon combinations — a hand-crafted "武曲 in Life Palace" would be more precise than what a generic combination produces. For MVP, "broad coverage, consistent quality, maintainable" outweighs "maximum precision for select combinations." This trade-off is noted on the page ("general tendencies, not precise fortune-telling").

Single source of truth, dual output

Where do the interpretation texts live? Same rule as OKF: build_ziwei_okf.py holds them, the generator outputs both:

  1. tools/ziwei-interpret.js (window.ZiweiInterpret): browser-side interpretation data, same-origin JS, no fetch, offline-cacheable via Service Worker. The page's renderInterpret(chart, lang) reads it to assemble text.
  2. OKF star pages (okf/ziwei/stars/*.md): each star's OKF page gains a "general tendencies" section — an AI agent reading the knowledge base gets the same interpretation knowledge.

One data source, two outlets. Edit once, both sync.

The language-code trap

After launch, switching to Chinese and viewing interpretations showed only star names — the text was gone. English worked fine.

Root cause: ziwei-interpret.js uses zh and en as its language keys; but the page's language code is zh-TW and en. Querying with zh-TW against a key named zh finds nothing.

Fix: one line at the renderInterpret entry point — lang.startsWith('zh') ? 'zh' : 'en'. One line, problem gone. But the bug's nature is worth noting: it wasn't a logic error — it was an interface contract mismatch. The data-holder (the generator) used one naming convention; the caller (the page) used another; both were internally consistent, just incompatible at the boundary. This kind of bug is silent, hard to reproduce, and especially common in multilingual systems.

Three Directions/Four Alignments: the engine already computed it

The interpretation MVP read only the "single palace" — the Life Palace's star tendencies. The advanced layer is Three Directions/Four Alignments (三方四正): a core Zi Wei technique that says you can't read the Life Palace in isolation. You look at it together with the Wealth Palace (first of the triple), Career Palace (second of the triple), and Migration Palace (the opposite palace) — these four together give a full cross-section of a person's life pattern.

How to implement? The engine already computed all twelve palace positions and each palace's major stars during chart calculation. Three Directions/Four Alignments needs no new computation — it's just looking up palaces by name: byName('Life'), byName('Wealth'), byName('Career'), byName('Migration'), each returning a star list, then feeding into the existing starEssence assembly logic.

The new code footprint is tiny: engine unchanged, interpretation logic unchanged, just four palace-name lookups and a render function. The descriptive text lives in build_ziwei_okf.py's SANFANG structure, generator dual-output:

  • ziwei-interpret.js's sanfang section (page lookup)
  • okf/ziwei/sanfang.md (knowledge base)

Empty palaces (no major star) display a "borrow from opposite palace" prompt, using the Migration Palace's star as a stand-in for an empty Life Palace — traditional practice, and clean graceful degradation.

Verification: took a 1990 birth date, confirmed Life=武曲/天相, Wealth=廉貞/天府, Career=紫微, Migration=破軍 against reference texts.

A reusable deep-reading pattern

Once Three Directions/Four Alignments landed, an unexpected payoff emerged: the "generator holds → dual output → page lookups → empty-palace degradation" pattern was fully validated and could be transplanted to other services.

Da Mo Yi Zhang Jing's Six Paths root nature and four-pillar interaction later both reuse this exact pattern. Every subsequent "add an interpretation layer to a divination service" operation became pattern application, not fresh design — add a generator data section, re-run, add a render function. Done.

What we learned

  • Interpretation architecture defines the privacy boundary. Choosing path A isn't just a technical decision — it's a value judgment about what stays on-device and what doesn't.
  • Combinatorial beats exhaustive. 26 entries covering the base interpretations for 168 combinations, traded for maintainability and OKF sync.
  • Unify language codes at interface boundaries. Data using zh, page using zh-TW — this silent mismatch is a chronic disease in multilingual systems.
  • "The engine already computed it" is the right first question. Don't write a new algorithm for Three Directions/Four Alignments when the palace data is already in the chart object.
  • Once a deep-reading pattern is validated, package it for reuse. First time is expensive; every subsequent service is template application.

The same question, applied to depth

The question this post answers: how deep can chart interpretation go without sending the user's birth data off their device?

Deeper than you'd expect. Combinatorial essence-domain reading, Three Directions/Four Alignments cross-palace analysis, a full bilingual interpretation section — all computed in your browser, gone when you close the tab, no server logs, no database. This isn't a feature limitation statement. It's an architecture choice on display.

Next post, a sharp turn — what does "prediction" mean in a lottery prediction tool? Time-seeded LCG, deterministic entertainment, and why "prediction" is an interesting lie in this context. Want to follow the series? Bookmark LocalPapa Notes.

探索 39+ 個隱私優先的瀏覽器工具
全程本地運算、檔案不上傳。
前往 LocalPapa →
Explore 39+ privacy-first browser tools
Everything runs locally — your files never leave your device.
Visit LocalPapa →

想看英文版?點右上角 EN 切換語言。

Prefer Chinese? Tap at the top-right to switch.