How is compatibility (궁합) actually calculated?
Three lookups against real charts — from the code, not a fortune line.
Give Bokki two birth dates and it runs the same three lookups every time. Your two birth-year elements are set against a five-element chart. Your two day-master elements — the stem Saju reads as “you,” not “your year” — are set against the same chart. Your two zodiac animals are set against a trine-and-clash table. That's the whole engine: no dice, no cards, no free-text prompt to an AI. computeCompatibility(a, b, locale) takes two already-computed charts and returns exactly five things — a four-tier label plus three short paragraphs of prose. It never returns a percentage, because it never keeps one.
Two of the three lookups reuse the same five-element wheel Bokki's own 용신 (favorable-element) engine runs: around the rim, Wood feeds Fire, Fire feeds Earth, Earth feeds Metal, Metal feeds Water, Water feeds Wood (相生, generating); across the middle, Wood breaks Earth, Earth dams Water, Water quenches Fire, Fire melts Metal, Metal cuts Wood (相剋, restraining). compatibility.ts keeps its own copy of that table rather than importing analysis.ts's, but the values match exactly. The first lookup applies this wheel to each person's birth-year stem element; the second applies the identical wheel to each person's day-master element — a different character in the same chart, and the one Saju treats as the true self. The third lookup is unrelated to the wheel: the two zodiac animals (year branch) checked against four three-way trine groups (Rat–Dragon–Monkey, Ox–Snake–Rooster, Tiger–Horse–Dog, Rabbit–Goat–Pig) and six direct-opposite clash pairs.
Take two real birth dates: 2 November 1988 (year pillar 戊辰, a yang-Earth Dragon) and 8 June 1996 (year pillar 丙子, a yang-Fire Rat). Lookup one, birth-year elements: Fire feeds Earth, so the 1996 chart's Fire generates the 1988 chart's Earth — a “gen” match. Lookup two, zodiac: Dragon and Rat both sit in the Rat–Dragon–Monkey trine — an instinctive match. Lookup three, day masters: the 1988 chart's day stem is 辛 (yin Metal), the 1996 chart's is 丙 (yang Fire), and Fire controls Metal — a “ctrl” match, friction rather than ease. Same two people, three separate reads: warm, warm, and tested. Run the internal tally by hand and it shows why the label still lands warm — base 58, +14 for the generating elements, +20 for the trine, −6 for the controlling day masters, landing at 86, which crosses the ≥85 line into golden (“A rare match” on screen). One tense axis does not outvote two easy ones; it just means this pair would do well to expect the day-to-day friction to sit specifically between who they each are underneath, not in the outer rhythm of the relationship.
That 86 above is real — it is what compatibility.ts actually computes for those two dates, and we had to reconstruct it by hand to write this paragraph, because Bokki has never shown it to anyone. The function clamps the running total to 38–98 and sorts it into one of four bands, and only the band's name ever reaches the screen: ≥85 is “golden” (“A rare match” / 귀한 인연), ≥70 is “warm” (“Warm and well-matched” / 따뜻이 잘 맞는), ≥55 is “tending” (“A bond worth tending” / 가꿀 만한 인연), and anything lower is “opposites” (“Opposites that teach” / 서로를 가르치는). The return type has no field for the number that decided which of the four you got. That is not an oversight — the type declaration is commented “NOT a score (D-003: no numbers/%)” in Bokki's own source. We could show you a percentage. The code above proves we compute something close to one internally. We show you a sentence instead, on purpose, every time.
No percentage or score ever reaches the screen, in any locale — see above; the number exists for one line inside one function and dies there. No probability that the relationship lasts, and no verdict on whether to stay together or walk away; that is not a Saju question, and Bokki will not manufacture an answer to it. No reading of the other person's private feelings — that is a different tool with a different boundary, at /heart, and compatibility.ts never imports it. And no deeper classical layers some 궁합 traditions add on top of the three lookups above: no 납음오행 (nayin sound-element) table, no comparison of the month or hour pillars, no 원진살, 귀문관살, or the other clash-adjacent 신살 some schools use to warn a couple apart. Bokki runs three plain lookups and stops exactly there.