This is the thirteenth post in the LocalPapa Notes dev-log series. The divination service arc begins here.
If the OKF post was about "giving AI a knowledge pack it can read," this one goes the opposite direction — translating a high-barrier traditional metaphysical system into algorithms a browser can run.
Why start with Zi Wei Dou Shu?
LocalPapa's position is clear: 100% browser-local, nothing uploaded. Divination is inherently high-privacy territory — your birth data is more sensitive than a phone number. That makes "local-first" not just a technical choice, but an ethical default.
Zi Wei Dou Shu is one of the most complex Chinese metaphysical systems: twelve palaces, fourteen major stars, four transformations, decade luck periods — each with intricate calculation rules. That complexity is precisely why it was worth getting right — done well, it becomes the foundation every other divination service builds on.
Two-track architecture: static knowledge + dynamic computation
The most important decision before writing any code: what counts as "knowledge," and what counts as "computation"?
- Static knowledge layer: the nature of the fourteen major stars, the domain of the twelve palaces, the rules of the four transformations, the Five-Element Bureau patterns — these are the same for everyone. They belong in the OKF knowledge pack, where AI agents can read them directly.
- Dynamic computation layer: given your birth data (date, time, sex), derive the Life Palace, place the twelve palaces, place the major stars — the result is different for every person. This belongs in the browser, running locally; the result never leaves your device.
This separation lets ziwei-engine.js and build_ziwei_okf.py each do their job without coupling.
Five key algorithms inside the chart engine
ziwei-engine.js is a pure computation module — no DOM, fully decoupled from the UI. It contains five core algorithms:
1. Solar-to-lunar conversion
Uses a standard 1900–2100 lunarInfo compressed table (three 32-bit integers per year, encoding month lengths, whether there's a leap month, and where). Lunar conversion is the foundation for everything — year stems and branches, month branch, day stems and branches all derive from it.
2. Five Tigers calculation for the Life Palace stem (命宮天干)
The Life Palace branch is derived from birth month and birth hour. The stem comes from the "Five Tigers" rule: depending on the year's heavenly stem (five groups: 甲己, 乙庚, ...), you find the starting stem, then count forward to the branch of the Life Palace month. This stem determines the Life Master's Five-Element affiliation and the Four Transformation calculations.
3. Nayin Five-Element Bureau
The "Five-Element Bureau" (五行局) determines both the starting age of decade luck periods and the algorithm for placing the Purple Star. It comes from the nayin of the Life Palace's stem-branch pair — every pair in the 60-cycle has a corresponding nayin element (metal, wood, water, fire, earth), each mapping to a bureau number (2, 3, 4, 5, or 6).
4. The ancient Purple Star placement algorithm
This is the most interesting part of the engine, and the part most often glossed over in documentation. The core formula is:
Find the smallest positive integer n such that bureau × n ≡ day (mod bureau) — that n is the palace index where the Purple Star lands. Then apply "even-numbered days go clockwise, odd-numbered days go counter-clockwise" to get the actual palace position.
The "even clockwise, odd counter-clockwise" (偶順奇逆) rule gets simplified or mis-stated in many online sources. We traced it back to classic algorithm texts to get it right.
5. Decade luck direction
Decade luck periods flow clockwise for yang-males and yin-females, counter-clockwise for yin-males and yang-females. The first version had this reversed — a common error that shows up in many online tools as well. We only caught it through cross-validation against known charts. Cross-validation is not optional for a divination engine.
How we verified accuracy
There's no unit test that can directly tell you if a chart is "correct" — you need known reference cases. We used three:
- 1984-02-02 → Lunar 甲子/Year 1 Month 1 Day 1 (Chinese New Year, unambiguous)
- 2000-01-01 → Lunar 己卯/Year 11 Month 25
- 庚午 Year, lunar day 25, Earth Five Bureau → Purple Star in 午 palace (stated in classic texts)
We checked four transformations, Lucky Star placement, Heavenly Benefactor, Heavenly Horse, and the Life Palace stem against multiple sources before going live. That process is what caught the decade-luck-direction bug.
CSS Grid 4×4 for the traditional palace layout
The traditional twelve-palace layout is:
`` 巳 午 未 申 辰 酉 卯 戌 寅 丑 子 亥 ``
Three palaces on each side, the central 2×2 left for the chart master's information panel. We used a CSS Grid 4×4, mapping each palace's grid-area to its position, merging the four center cells into grid-area: center. Stars are colour-coded by type: major stars (purple), auspicious stars (blue), inauspicious stars (red). Life-year four transformations appear as coloured badges beside star names (Prosperity orange, Authority green, Intellect blue, Obstruction red) — so the key stars are visible at a glance.
build_ziwei_okf.py: the bridge between knowledge and tool
Same philosophy as build_okf.py: never hand-craft 40 Markdowns. Python structured data holds the knowledge; the generator outputs both:
okf/ziwei/: 40 OKF .md files covering the fourteen major stars, twelve palaces, four transformations, Five-Element Bureau, and concept pages — AI agents can read this knowledge base directly
tools/ziwei-interpret.js (added later): the browser-side window.ZiweiInterpret, no fetch required, offline-cacheable via the Service Worker
The root build_okf.py index and llms.txt gained a "Knowledge bases" section pointing to the Zi Wei knowledge base — so an agent can navigate to the star/palace definitions from the entry point. This "knowledge entry point" design extends the OKF thread from the previous post.
Honest labelling: divination is interpretation, not prediction
Every divination service page carries this line: This service provides traditional metaphysical interpretations for reference only; it does not constitute any prediction or advice.
We also document the divergences between schools of thought: the disputed month assignment for leap-month birth dates, the split between early- and late-hour Zi calculation, the four-transformation table for 庚-stem (太陽/武曲 vs 太陽/天同 depending on the version). There is no single "correct" school — we chose one, documented the source, and let users know this is a real variance, not an error.
What we learned
- Separate "knowledge" from "computation" before writing a line of code. Knowledge belongs in OKF, static-cacheable; computation belongs in a local engine that never uploads. Clear separation → clean maintenance.
- A divination engine must be cross-validated. Use known reference charts — that's how we caught the decade-luck direction reversal. Without it, you don't know what you got wrong.
- Traditional mnemonics need to be traced to source texts. Online versions of "偶順奇逆" vary and many are imprecise. Old algorithm books are the ground truth.
- Laying out a chart is not the same as reading it. Placing stars is step one; interpretation is another layer (we added combinatorial lookup and Three Directions/Four Alignments later).
- A well-validated engine is the foundation for every divination service after it. Yizhang, zodiac matching, tarot, Western astrology — all of them reuse the lunar calendar table from this engine.
The same question, applied to privacy
Earlier tools asked "can this be done in the browser." Divination services ask a sharper version: can this be done in the browser such that the user never has to trust any server?
Your birth data shouldn't fly to a cloud to come back as a chart — all computation happens on your device and disappears when you close the tab. This is local-first at its most compelling: the more sensitive the data, the more obvious the answer.
In the next dev log, we continue the divination arc — see how Yizhang (達摩一掌經) uses a "copy-of-Zi-Wei" three-layer architecture to ship a new service with minimal new code. Want to follow the series? Bookmark LocalPapa Notes.