dsh-metaphysics 0.66.0 → 0.67.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/client.almanac.js +25 -25
- package/client.chart.js +145 -135
- package/client.chenggu.js +25 -25
- package/client.convert.js +25 -25
- package/client.daliuren.js +102 -94
- package/client.fengshui.js +29 -29
- package/client.js +1 -1
- package/client.liuyao.js +85 -77
- package/client.mbti.js +26 -26
- package/client.name.js +70 -68
- package/client.numerology.js +27 -27
- package/client.qimen.js +95 -87
- package/client.star.js +30 -30
- package/client.tarot.js +109 -101
- package/client.xiaoliuren.js +27 -27
- package/client.zeri.js +24 -24
- package/engine/bazi.js +29 -0
- package/engine/geju.js +200 -0
- package/engine/hehua.js +185 -0
- package/engine/interpret.js +23 -0
- package/engine/plain-summary.js +23 -1
- package/package.json +1 -1
- package//345/221/275/347/220/206/346/216/222/347/233/230.html +469 -5
package/engine/bazi.js
CHANGED
|
@@ -12,6 +12,7 @@ import { bool } from './bool.js';
|
|
|
12
12
|
import { nayinOf } from './nayin.js';
|
|
13
13
|
import { SANHE } from './sanhe.js';
|
|
14
14
|
import { analyzeBaziFrame, scoreLuck } from './geju.js';
|
|
15
|
+
import { judgeHehua } from './hehua.js';
|
|
15
16
|
import { branchStructureOf, weightPctOf } from './structure.js';
|
|
16
17
|
|
|
17
18
|
// 地支藏干(本气 / 中气 / 余气)
|
|
@@ -265,6 +266,8 @@ export function buildRelations(pillars, keys = ['year', 'month', 'day', 'hour'])
|
|
|
265
266
|
branches: uniq(branchOut),
|
|
266
267
|
anhe: anheOf(pillars, keys),
|
|
267
268
|
anheNote: '暗合只作取象与风水参考,不参与旺衰与格局;只出现一对时按课里可忽略',
|
|
269
|
+
// 五合化与不化:另起一层判四条件,上面的 stems 文案保持不变(那里只说「待定」)
|
|
270
|
+
hehua: judgeHehua(pillars, pillars.month ? pillars.month.branch : '', pillars.day ? pillars.day.stem : '', keys),
|
|
268
271
|
};
|
|
269
272
|
}
|
|
270
273
|
|
|
@@ -889,6 +892,32 @@ export function buildBazi(input) {
|
|
|
889
892
|
out.strength.weightPct.placeholderHour = true;
|
|
890
893
|
out.strength.weightPct.note = '时柱暂缺:时柱权重不计入合计(本盘 81%),不重新归一化;补上出生时刻后再按 100% 看';
|
|
891
894
|
}
|
|
895
|
+
// 财库与三平衡都用到了时支:财库看四支有没有库、有没有冲开,三平衡数地支阴阳。
|
|
896
|
+
// 与结构同一条规矩——照实标占位,不把编出来的时支说成实有。
|
|
897
|
+
if (out.frame && out.frame.caiKu) {
|
|
898
|
+
const ck = out.frame.caiKu;
|
|
899
|
+
ck.placeholderHour = true;
|
|
900
|
+
// 判「这一条要不要紧」不能看占位时支碰巧有没有库/冲,要看结论本身是否依赖未知的时支:
|
|
901
|
+
// 库与冲都已落在年月日三支上才稳;库没找到、或库找到了但冲没找到,
|
|
902
|
+
// 都可能是因为真正的时支里正好有那一支,结论必须存疑。
|
|
903
|
+
const atHour = (ck.positions || []).includes('hour') || (ck.openerPositions || []).includes('hour');
|
|
904
|
+
const robust = ck.present && ck.opened && !atHour;
|
|
905
|
+
ck.note = robust
|
|
906
|
+
? '时柱暂缺:库与冲都已落在年月日三支上,结论不受时支影响'
|
|
907
|
+
: '时柱暂缺:库或开库可能落在未知的时支上,这一条只按正午占位算,补上出生时刻后可能整条改变';
|
|
908
|
+
ck.detail = `${ck.detail}(时支为占位值)`;
|
|
909
|
+
}
|
|
910
|
+
if (out.frame && out.frame.balance) {
|
|
911
|
+
const bal = out.frame.balance;
|
|
912
|
+
bal.placeholderHour = true;
|
|
913
|
+
bal.note = '时柱暂缺:阴阳的八位与五行占比都按正午时柱占位算过,补上出生时刻后层次可能变化';
|
|
914
|
+
bal.text = `${bal.text}(阴阳与五行未含真实时柱,层次只作方向)`;
|
|
915
|
+
}
|
|
916
|
+
if (out.relations && out.relations.hehua) {
|
|
917
|
+
const hh = out.relations.hehua;
|
|
918
|
+
hh.placeholderHour = true;
|
|
919
|
+
hh.text = `${hh.text}\n(时柱暂缺:只判了年月日三干,日干与时干那一组无从判起)`;
|
|
920
|
+
}
|
|
892
921
|
out.notes = [
|
|
893
922
|
'时柱暂缺:未提供出生时刻,时柱不对外给出,也不计入神煞与干支关系',
|
|
894
923
|
'旺衰、格局、用神、调候暂以正午时柱估算,补上出生时刻后可能改变',
|
package/engine/geju.js
CHANGED
|
@@ -849,6 +849,198 @@ export function scoreLuck(ganzhi, frame) {
|
|
|
849
849
|
return { ganzhi, score: total, tier, stemTenGod: godStem, reasons, note: `${godStem}运,${tier}(${total})` };
|
|
850
850
|
}
|
|
851
851
|
|
|
852
|
+
// ── 财库 ────────────────────────────────────────────────────
|
|
853
|
+
|
|
854
|
+
// 五行之墓:木墓未、火墓戌、金墓丑、水墓辰;土取戊土十二长生的墓位(戌)。
|
|
855
|
+
// 这样取,问真《专业知识·八字断财富技法》那张表五格全部对得上:
|
|
856
|
+
// 木日主财土 → 土墓戌;水日主财火 → 火墓戌;火日主财金 → 金墓丑;
|
|
857
|
+
// 土日主财水 → 水墓辰;金日主财木 → 木墓未。
|
|
858
|
+
// 若改用「水土同宫」把土墓放辰,只有木日主一格会落到辰,与问真表冲突,故取戌。
|
|
859
|
+
const TOMB_OF = { 木: '未', 火: '戌', 土: '戌', 金: '丑', 水: '辰' };
|
|
860
|
+
const BRANCH_CHONG = {
|
|
861
|
+
子: '午', 午: '子', 丑: '未', 未: '丑', 寅: '申', 申: '寅',
|
|
862
|
+
卯: '酉', 酉: '卯', 辰: '戌', 戌: '辰', 巳: '亥', 亥: '巳',
|
|
863
|
+
};
|
|
864
|
+
const CAIKU_WEAK_PCT = 8;
|
|
865
|
+
|
|
866
|
+
/**
|
|
867
|
+
* 财库:日主所克五行(财)的墓库,落在四支上;库被冲开才是「开库」。
|
|
868
|
+
* @param {object} p
|
|
869
|
+
* @param {string} p.dayStem 日干
|
|
870
|
+
* @param {object} p.pillars 四柱
|
|
871
|
+
* @param {object} p.wuxing 五行分值
|
|
872
|
+
* @param {object} p.yongshen 喜忌结果
|
|
873
|
+
*/
|
|
874
|
+
export function caiKuOf({ dayStem, pillars = {}, wuxing = {}, yongshen = {} }) {
|
|
875
|
+
const roles = elementRoles(dayStem);
|
|
876
|
+
const caiEl = roles.cai;
|
|
877
|
+
const store = TOMB_OF[caiEl] || '';
|
|
878
|
+
const keys = ['year', 'month', 'day', 'hour'].filter((k) => pillars[k] && pillars[k].branch);
|
|
879
|
+
const at = keys.filter((k) => pillars[k].branch === store);
|
|
880
|
+
const openerBranch = BRANCH_CHONG[store] || '';
|
|
881
|
+
const openers = keys.filter((k) => pillars[k].branch === openerBranch);
|
|
882
|
+
|
|
883
|
+
const total = Object.values(wuxing).reduce((n, v) => n + (Number(v) || 0), 0);
|
|
884
|
+
const w = (el) => Math.round((Number(wuxing[el]) || 0) * 10) / 10;
|
|
885
|
+
const pctOf = (el) => (total > 0 ? Math.round((w(el) / total) * 1000) / 10 : 0);
|
|
886
|
+
const caiPct = pctOf(caiEl);
|
|
887
|
+
const caiWeak = caiPct < CAIKU_WEAK_PCT;
|
|
888
|
+
|
|
889
|
+
const favor = Array.isArray(yongshen.favor) ? yongshen.favor : [];
|
|
890
|
+
const avoid = Array.isArray(yongshen.avoid) ? yongshen.avoid : [];
|
|
891
|
+
const favorable = favor.includes(caiEl);
|
|
892
|
+
const avoidable = avoid.includes(caiEl);
|
|
893
|
+
const opened = at.length > 0 && openers.length > 0;
|
|
894
|
+
// 财星入库:库支的藏干里出现财这一行(不论本气/中气/余气),与「财库」是两件事。
|
|
895
|
+
// 没有库支时这两项一律为假——不能拿「本该是库的那一支」的藏干去充数。
|
|
896
|
+
const hiddenEls = at.length ? (HIDDEN[store] || []).map((h) => STEM_ELEMENT[h]) : [];
|
|
897
|
+
const caiInStore = hiddenEls.includes(caiEl);
|
|
898
|
+
const mainInStore = at.length > 0 && (HIDDEN[store] || []).slice(0, 1).map((h) => STEM_ELEMENT[h]).includes(caiEl);
|
|
899
|
+
|
|
900
|
+
const label = (ks) => ks.map((k) => ({ year: '年', month: '月', day: '日', hour: '时' }[k])).join('、');
|
|
901
|
+
|
|
902
|
+
let verdict = '无财库';
|
|
903
|
+
let detail = `日主${dayStem}${roles.me},财为${caiEl},${caiEl}之墓在${store};四支里没有${store},本盘不立财库`
|
|
904
|
+
+ `${openers.length ? `(${label(openers)}支见${openerBranch},但没有${store}可冲,冲不成库)` : ''}。`;
|
|
905
|
+
if (at.length) {
|
|
906
|
+
// 四库每一支都含所墓那一行的余气(戌藏丁、丑藏辛、辰藏癸、未藏乙),
|
|
907
|
+
// 所以「库里有财」几乎恒真;真正要分的是本气与余气——这才是「财星入库」的深浅。
|
|
908
|
+
const storeNote = mainInStore
|
|
909
|
+
? `(${store}藏干本气即${caiEl},正合「财星入库」)`
|
|
910
|
+
: `(${store}藏干里的${caiEl}只是余气,财星算入了库,但入得浅)`;
|
|
911
|
+
const head = `日主${dayStem}${roles.me},财为${caiEl},${caiEl}之墓在${store};`
|
|
912
|
+
+ `本盘${label(at)}支见${store},财库成立${caiInStore ? storeNote : ',库中不见财星'}。`;
|
|
913
|
+
const tail = openers.length
|
|
914
|
+
? `${label(openers)}支见${openerBranch},${store}${openerBranch}相冲,库门被冲开。`
|
|
915
|
+
: `四支里没有${openerBranch}来冲,库是闭的——要等岁运引动。`;
|
|
916
|
+
const step = (() => {
|
|
917
|
+
if (favorable && !caiWeak) return opened ? `财${caiEl}为喜用且不弱(${caiPct}%),库开则财有出路,主发。` : `财${caiEl}为喜用且不弱(${caiPct}%),但库未开,是「有财待发」,不是已经发财。`;
|
|
918
|
+
if (favorable && caiWeak) return opened ? `财${caiEl}为喜用但偏弱(${caiPct}%),库开只是流动起来,发而不厚,先补财再谈库。` : `财${caiEl}为喜用但偏弱(${caiPct}%),库又未开,宜先扶财。`;
|
|
919
|
+
if (avoidable) return opened ? `财${caiEl}为忌(${caiPct}%),开库反主破财,冲得越实越明显。` : `财${caiEl}为忌(${caiPct}%),但库未开,破财之势未启。`;
|
|
920
|
+
return opened ? `财${caiEl}在喜忌里为中性(${caiPct}%),开库只算动了财,吉凶看岁运把哪一边引起来。` : `财${caiEl}在喜忌里为中性(${caiPct}%),库未开,暂不作财库论。`;
|
|
921
|
+
})();
|
|
922
|
+
verdict = opened
|
|
923
|
+
? (favorable && !caiWeak ? '开库主发' : avoidable ? '开库反主破财' : favorable ? '开库发而不厚' : '开库,吉凶待引动')
|
|
924
|
+
: (favorable ? (caiWeak ? '库闭财弱' : '库闭待冲开') : avoidable ? '库闭未开' : '库闭,吉凶待引动');
|
|
925
|
+
detail = `${head}${tail}${step}`;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
return {
|
|
929
|
+
dayElement: roles.me,
|
|
930
|
+
caiElement: caiEl,
|
|
931
|
+
store,
|
|
932
|
+
present: at.length > 0,
|
|
933
|
+
positions: at,
|
|
934
|
+
opener: openerBranch,
|
|
935
|
+
opened,
|
|
936
|
+
openerPositions: openers,
|
|
937
|
+
caiInStore,
|
|
938
|
+
mainInStore,
|
|
939
|
+
caiPct,
|
|
940
|
+
caiWeak,
|
|
941
|
+
favorState: favorable ? '喜' : avoidable ? '忌' : '中',
|
|
942
|
+
verdict,
|
|
943
|
+
detail,
|
|
944
|
+
rule: '财库=财星(日主所克那一行)之墓在四支上;开库=库支被对冲。「开库才发」有两个前提:财为喜用、且财不弱;财为忌时开库反主破财。',
|
|
945
|
+
method: `五行之墓取木未/火戌/金丑/水辰,土取戊土长生墓位戌;问真原表作「水木日主在戌、火在丑、土在辰、金在未」,与本法五格全同。财「不弱」以全局占比 >= ${CAIKU_WEAK_PCT}% 折算,是本插件口径,非古法原数。`,
|
|
946
|
+
boundary: '只作只读标注:不改旺衰分、不改喜忌、不参与取格。另一说把辰当作「水土同宫」的土墓,则木日主财库会落在辰,本插件不取此说。',
|
|
947
|
+
};
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
// ── 三平衡(富贵层次的解读方向)────────────────────────────
|
|
951
|
+
|
|
952
|
+
// 地支阴阳:论八字时以藏干本气的阴阳定,不以奇偶定(问真《基础知识·干支上》)。
|
|
953
|
+
// 子藏癸、午藏丁、卯藏乙、酉藏辛 → 阴;亥藏壬、巳藏丙、寅藏甲、申藏庚 → 阳。
|
|
954
|
+
const BRANCH_YINYANG = {
|
|
955
|
+
子: '阴', 丑: '阴', 寅: '阳', 卯: '阴', 辰: '阳', 巳: '阳',
|
|
956
|
+
午: '阴', 未: '阴', 申: '阳', 酉: '阴', 戌: '阳', 亥: '阳',
|
|
957
|
+
};
|
|
958
|
+
const BALANCE_SPREAD_MAX = 22;
|
|
959
|
+
const BALANCE_MIN_PCT = 4;
|
|
960
|
+
const BALANCE_YINYANG_LO = 3;
|
|
961
|
+
const BALANCE_YINYANG_HI = 5;
|
|
962
|
+
const BALANCE_CLIMATE_W = 0.3;
|
|
963
|
+
|
|
964
|
+
/**
|
|
965
|
+
* 三平衡:五行平衡 / 阴阳平衡 / 寒暖燥湿平衡。
|
|
966
|
+
* @param {object} p
|
|
967
|
+
* @param {string} p.dayStem 日干
|
|
968
|
+
* @param {object} p.pillars 四柱
|
|
969
|
+
* @param {object} p.wuxing 五行分值
|
|
970
|
+
* @param {object} p.climate judgeClimate 的结果(yongshen.climate)
|
|
971
|
+
* @param {object} p.strength 旺衰结果(只用于文案)
|
|
972
|
+
*/
|
|
973
|
+
export function balanceOf({ dayStem, pillars = {}, wuxing = {}, climate = null, strength = null }) {
|
|
974
|
+
const total = Object.values(wuxing).reduce((n, v) => n + (Number(v) || 0), 0);
|
|
975
|
+
const w = (el) => Math.round((Number(wuxing[el]) || 0) * 10) / 10;
|
|
976
|
+
const pctOf = (el) => (total > 0 ? Math.round((w(el) / total) * 1000) / 10 : 0);
|
|
977
|
+
|
|
978
|
+
// ① 五行平衡:最高与最低的占比差,加上「有没有几乎缺掉的
|
|
979
|
+
const pcts = ELEMENTS.map((el) => ({ element: el, pct: pctOf(el) }));
|
|
980
|
+
const spread = Math.round((Math.max(...pcts.map((x) => x.pct)) - Math.min(...pcts.map((x) => x.pct))) * 10) / 10;
|
|
981
|
+
const lowest = pcts.slice().sort((a, b) => a.pct - b.pct)[0];
|
|
982
|
+
const highest = pcts.slice().sort((a, b) => b.pct - a.pct)[0];
|
|
983
|
+
const wuxingOk = spread <= BALANCE_SPREAD_MAX && lowest.pct >= BALANCE_MIN_PCT;
|
|
984
|
+
const wuxingDetail = wuxingOk
|
|
985
|
+
? `五行占比在 ${lowest.pct}%–${highest.pct}% 之间,极差 ${spread} 个百分点,没有明显缺项。`
|
|
986
|
+
: lowest.pct < BALANCE_MIN_PCT
|
|
987
|
+
? `${lowest.element}只有 ${lowest.pct}%,近乎缺项;${highest.element}高到 ${highest.pct}%,偏得明显。`
|
|
988
|
+
: `${highest.element}高到 ${highest.pct}%、${lowest.element}只有 ${lowest.pct}%,极差 ${spread} 个百分点,偏枯。`;
|
|
989
|
+
|
|
990
|
+
// ② 阴阳平衡:天干按奇偶,地支按藏干本气
|
|
991
|
+
const stemKeys = ['year', 'month', 'day', 'hour'].filter((k) => pillars[k] && pillars[k].stem);
|
|
992
|
+
const yStem = stemKeys.filter((k) => isYangStem(pillars[k].stem)).length;
|
|
993
|
+
const yBranch = stemKeys.filter((k) => BRANCH_YINYANG[pillars[k].branch] === '阳').length;
|
|
994
|
+
const yang = yStem + yBranch;
|
|
995
|
+
const yin = stemKeys.length * 2 - yang;
|
|
996
|
+
const yinyangOk = yang >= BALANCE_YINYANG_LO && yang <= BALANCE_YINYANG_HI;
|
|
997
|
+
const pure = yang === 0 ? '纯阴' : yang === stemKeys.length * 2 ? '纯阳' : '';
|
|
998
|
+
const yinyangDetail = pure
|
|
999
|
+
? `${pure}之局(阳 ${yang}/阴 ${yin}),课里说纯阴纯阳减贵减富。`
|
|
1000
|
+
: yinyangOk
|
|
1001
|
+
? `天干阳 ${yStem}、地支阳 ${yBranch},合计阳 ${yang}/阴 ${yin},阴阳相配。`
|
|
1002
|
+
: `天干阳 ${yStem}、地支阳 ${yBranch},合计阳 ${yang}/阴 ${yin},一边倒。`;
|
|
1003
|
+
|
|
1004
|
+
// ③ 寒暖燥湿:气候平和,或调候之物在原局有根
|
|
1005
|
+
const kind = climate && climate.kind ? climate.kind : '';
|
|
1006
|
+
const needEl = climate && climate.need && climate.need.element ? climate.need.element : '';
|
|
1007
|
+
const needW = needEl ? w(needEl) : 0;
|
|
1008
|
+
const climateOk = kind === '平和' || (!!needEl && needW >= BALANCE_CLIMATE_W);
|
|
1009
|
+
const climateDetail = !kind
|
|
1010
|
+
? '未见气候判定,本项不计。'
|
|
1011
|
+
: kind === '平和'
|
|
1012
|
+
? `气候平和(${kind}),寒暖燥湿不偏。`
|
|
1013
|
+
: needEl
|
|
1014
|
+
? climateOk
|
|
1015
|
+
? `气候偏${kind},需${needEl}调候;原局${needEl}已有 ${needW} 分,调候之物在位。`
|
|
1016
|
+
: `气候偏${kind},需${needEl}调候;原局${needEl}只有 ${needW} 分,调候之物不实。`
|
|
1017
|
+
: `气候偏${kind},但未见明确调候之物。`;
|
|
1018
|
+
|
|
1019
|
+
const hits = [wuxingOk, yinyangOk, climateOk].filter(Boolean).length;
|
|
1020
|
+
const tier = hits === 3 ? '三备' : hits === 2 ? '两备' : hits === 1 ? '一备' : '零备';
|
|
1021
|
+
const tierText = {
|
|
1022
|
+
三备: '三方面平衡全备,课里按大富大贵论方向。',
|
|
1023
|
+
两备: '三方面备了两项,课里按中富中贵论方向。',
|
|
1024
|
+
一备: '三方面只备一项,课里按小富小贵论方向。',
|
|
1025
|
+
零备: '三项都不备,课里不给富贵层次;这不等于命薄,只说明这套衡量法在这一盘上不适用。',
|
|
1026
|
+
}[tier];
|
|
1027
|
+
|
|
1028
|
+
return {
|
|
1029
|
+
wuxing: { ok: wuxingOk, spread, highest: highest.element, lowest: lowest.element, pcts, detail: wuxingDetail },
|
|
1030
|
+
yinyang: { ok: yinyangOk, yang, yin, yangStems: yStem, yangBranches: yBranch, pure, detail: yinyangDetail },
|
|
1031
|
+
climate: { ok: climateOk, kind, need: needEl || null, needWeight: needW, detail: climateDetail },
|
|
1032
|
+
hits,
|
|
1033
|
+
tier,
|
|
1034
|
+
text: `五行平衡:${wuxingOk ? '备' : '不备'}——${wuxingDetail}阴阳平衡:${yinyangOk ? '备' : '不备'}——${yinyangDetail}寒暖燥湿:${climateOk ? '备' : '不备'}——${climateDetail}${tierText}`,
|
|
1035
|
+
strengthNote: strength && strength.level ? `日主${dayStem},旺衰为${strength.level}。` : '',
|
|
1036
|
+
rule: '问真《专业知识·论八字富贵层次》:五行平衡、阴阳平衡、寒暖燥湿平衡,三方面全备为大富大贵,两备为中富中贵,一备为小富小贵。',
|
|
1037
|
+
method: `阈值是本插件的折算口径,不是古法原数:五行看最高最低占比差 <= ${BALANCE_SPREAD_MAX} 个百分点且无一项低于 ${BALANCE_MIN_PCT}%;`
|
|
1038
|
+
+ `阴阳看八位(四天干奇偶 + 四地支本气)阳数在 ${BALANCE_YINYANG_LO}–${BALANCE_YINYANG_HI} 之间;`
|
|
1039
|
+
+ `寒暖燥湿看气候为平和,或调候之物在原局有 ${BALANCE_CLIMATE_W} 分以上。`,
|
|
1040
|
+
boundary: '只作解读方向:不改旺衰分、不改喜忌、不参与取格。格局法的贵贱十式另有专章,不并入这三项。',
|
|
1041
|
+
};
|
|
1042
|
+
}
|
|
1043
|
+
|
|
852
1044
|
// ── 对外入口 ────────────────────────────────────────────────
|
|
853
1045
|
|
|
854
1046
|
/**
|
|
@@ -875,6 +1067,12 @@ export function analyzeBaziFrame({ pillars, dayStem, monthBranch, strength, wuxi
|
|
|
875
1067
|
const bingyao = bingyaoOf({ dayStem, strength, wuxing, yongshen, geju });
|
|
876
1068
|
// 闲神:只读标注
|
|
877
1069
|
const xianshen = xianshenOf({ dayStem, wuxing, pillars, yongshen });
|
|
1070
|
+
// 财库:只读标注,复用上面的喜忌
|
|
1071
|
+
const caiKu = caiKuOf({ dayStem, pillars, wuxing, yongshen });
|
|
1072
|
+
// 三平衡:只读标注,气候取用神层已判好的那一个
|
|
1073
|
+
const balance = balanceOf({
|
|
1074
|
+
dayStem, pillars, wuxing, climate: yongshen.climate || null, strength,
|
|
1075
|
+
});
|
|
878
1076
|
return {
|
|
879
1077
|
geju,
|
|
880
1078
|
primary: month,
|
|
@@ -883,6 +1081,8 @@ export function analyzeBaziFrame({ pillars, dayStem, monthBranch, strength, wuxi
|
|
|
883
1081
|
yongshen,
|
|
884
1082
|
bingyao,
|
|
885
1083
|
xianshen,
|
|
1084
|
+
caiKu,
|
|
1085
|
+
balance,
|
|
886
1086
|
patternScore,
|
|
887
1087
|
dayStem,
|
|
888
1088
|
monthBranch,
|
package/engine/hehua.js
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
// 天干五合的「合化」判定。
|
|
2
|
+
//
|
|
3
|
+
// bazi.js 的 buildRelations 在干支关系层只写「有合、化某待定」——那一层不该断言化与不化。
|
|
4
|
+
// 是否真化要过问真《基础知识·干支中》给的四条件:
|
|
5
|
+
// ① 天干紧挨(隔一位=隔合、隔两位=遥合,都不化;争合、妒合一律不化)
|
|
6
|
+
// ② 被化天干(阴干一侧)在天干上无同类(比劫)帮扶
|
|
7
|
+
// ③ 月令有引化物(月支五行或月支本气=化神五行)
|
|
8
|
+
// ④ 引化物不被克(克化神之五行不现于月干、日干,月支本气也不是它)
|
|
9
|
+
//
|
|
10
|
+
// 判完只作只读标注:不改旺衰分、不改五行权重、不改喜忌、不改 relations.stems 的文案。
|
|
11
|
+
// 反化(甲己化木、乙庚化木、丙辛化火或金、丁壬化火或水、戊癸化土或水)诸家分歧大,本插件不做。
|
|
12
|
+
|
|
13
|
+
const STEMS = ['甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸'];
|
|
14
|
+
const STEM_ELEMENT = {
|
|
15
|
+
甲: '木', 乙: '木', 丙: '火', 丁: '火', 戊: '土', 己: '土', 庚: '金', 辛: '金', 壬: '水', 癸: '水',
|
|
16
|
+
};
|
|
17
|
+
const BRANCH_ELEMENT = {
|
|
18
|
+
子: '水', 丑: '土', 寅: '木', 卯: '木', 辰: '土', 巳: '火',
|
|
19
|
+
午: '火', 未: '土', 申: '金', 酉: '金', 戌: '土', 亥: '水',
|
|
20
|
+
};
|
|
21
|
+
const OVERCOMES = { 木: '土', 土: '水', 水: '火', 火: '金', 金: '木' };
|
|
22
|
+
const HIDDEN = {
|
|
23
|
+
子: ['癸'], 丑: ['己', '癸', '辛'], 寅: ['甲', '丙', '戊'], 卯: ['乙'],
|
|
24
|
+
辰: ['戊', '乙', '癸'], 巳: ['丙', '庚', '戊'], 午: ['丁', '己'], 未: ['己', '丁', '乙'],
|
|
25
|
+
申: ['庚', '壬', '戊'], 酉: ['辛'], 戌: ['戊', '辛', '丁'], 亥: ['壬', '甲'],
|
|
26
|
+
};
|
|
27
|
+
const STEM_HE = { 甲己: '土', 乙庚: '金', 丙辛: '水', 丁壬: '木', 戊癸: '火' };
|
|
28
|
+
const KEYS = ['year', 'month', 'day', 'hour'];
|
|
29
|
+
const LABEL = { year: '年', month: '月', day: '日', hour: '时' };
|
|
30
|
+
|
|
31
|
+
const METHOD = '问真《基础知识·干支中》:五合是否真化看四条件——天干紧挨、被化天干无同类帮扶、'
|
|
32
|
+
+ '月令有引化物、引化物不被克;隔合、遥合、争合、妒合一律不化';
|
|
33
|
+
const BOUNDARY = '只作只读标注:不改旺衰分、不改五行权重、不改喜忌。'
|
|
34
|
+
+ '争合=两阳干争一阴干,妒合=两阴干争一阳干,问真说这两者「实际指的就是合绊」,故判不化。';
|
|
35
|
+
|
|
36
|
+
const isYangStem = (stem) => STEMS.indexOf(stem) % 2 === 0;
|
|
37
|
+
const heOf = (a, b) => STEM_HE[a + b] || STEM_HE[b + a] || null;
|
|
38
|
+
const elOf = (stem) => STEM_ELEMENT[stem] || '';
|
|
39
|
+
/** 克某五行的那一行 */
|
|
40
|
+
const keOf = (element) => Object.keys(OVERCOMES).find((el) => OVERCOMES[el] === element) || '';
|
|
41
|
+
/** 月支本气所属五行 */
|
|
42
|
+
const mainElOf = (branch) => elOf((HIDDEN[branch] || [])[0] || '');
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 判四柱天干的五合化与不化。
|
|
46
|
+
* @param {object} pillars 四柱(bazi.js 的 pillar 对象;用到 stem 与 branch)
|
|
47
|
+
* @param {string} monthBranch 月支(省略时取 pillars.month.branch)
|
|
48
|
+
* @param {string} dayStem 日干(省略时取 pillars.day.stem)
|
|
49
|
+
* @param {string[]} keys 参与判定的柱;时辰未知时传 ['year','month','day']
|
|
50
|
+
*/
|
|
51
|
+
export function judgeHehua(pillars, monthBranch, dayStem, keys = KEYS) {
|
|
52
|
+
const slots = (Array.isArray(keys) ? keys : KEYS)
|
|
53
|
+
.filter((k) => pillars && pillars[k] && pillars[k].stem && pillars[k].branch)
|
|
54
|
+
.map((k) => ({ key: k, label: LABEL[k] || k, stem: pillars[k].stem, branch: pillars[k].branch }));
|
|
55
|
+
const mb = monthBranch || (pillars && pillars.month && pillars.month.branch) || '';
|
|
56
|
+
const ds = dayStem || (pillars && pillars.day && pillars.day.stem) || '';
|
|
57
|
+
|
|
58
|
+
const notes = [
|
|
59
|
+
'反化(甲己化木、乙庚化木、丙辛化火或金、丁壬化火或水、戊癸化土或水)是近代易人的演绎,诸家分歧大,本插件不做。',
|
|
60
|
+
'日元参与合化时,即使化成功仍以原五行论:问真说「五行的本质属性不会转变,只不过表现形式可能会发生变化」。',
|
|
61
|
+
'天干五合未必以日元为主——年月干合化成功同样算数(问真所举己酉造就是年月干合)。',
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
if (slots.length < 2) {
|
|
65
|
+
return {
|
|
66
|
+
items: [], transformed: [], text: '天干不足两柱,五合无从判起。', method: METHOD, boundary: BOUNDARY, notes,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const monthEl = BRANCH_ELEMENT[mb] || '';
|
|
71
|
+
const monthMain = mainElOf(mb);
|
|
72
|
+
const items = [];
|
|
73
|
+
|
|
74
|
+
for (let i = 0; i < slots.length; i++) {
|
|
75
|
+
for (let j = i + 1; j < slots.length; j++) {
|
|
76
|
+
const a = slots[i];
|
|
77
|
+
const b = slots[j];
|
|
78
|
+
if (a.stem === b.stem) continue;
|
|
79
|
+
const hua = heOf(a.stem, b.stem);
|
|
80
|
+
if (!hua) continue;
|
|
81
|
+
|
|
82
|
+
const gap = j - i - 1;
|
|
83
|
+
const closeness = gap === 0 ? '紧挨' : gap === 1 ? '隔合' : '遥合';
|
|
84
|
+
const yin = isYangStem(a.stem) ? b : a;
|
|
85
|
+
const yang = isYangStem(a.stem) ? a : b;
|
|
86
|
+
const others = slots.filter((s) => s !== a && s !== b);
|
|
87
|
+
|
|
88
|
+
// 争合 / 妒合:第三干与这一对里的某一干另成五合
|
|
89
|
+
let conflict = null;
|
|
90
|
+
let conflictStem = '';
|
|
91
|
+
for (const s of others) {
|
|
92
|
+
if (!heOf(s.stem, a.stem) && !heOf(s.stem, b.stem)) continue;
|
|
93
|
+
conflict = isYangStem(s.stem) ? '争合' : '妒合';
|
|
94
|
+
conflictStem = s.stem;
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ② 被化天干(阴干一侧)无同类帮扶。
|
|
99
|
+
// 只算「同类(比劫)」,不算印:问真的唯一完整例「己酉 甲戌 壬戌 丁未」里,
|
|
100
|
+
// 被化的己土有丁火为印(火生土)却仍判化成功——把印计进生扶会与它自己的例子冲突。
|
|
101
|
+
const sameKind = others.filter((s) => elOf(s.stem) === elOf(yin.stem));
|
|
102
|
+
|
|
103
|
+
// ④ 引化物不被克:问真原文点明「月干/日干透出」与「月支本气」两处。
|
|
104
|
+
const keEl = keOf(hua);
|
|
105
|
+
const keMajor = others.filter((s) => elOf(s.stem) === keEl && (s.key === 'month' || s.key === 'day'));
|
|
106
|
+
const keMinor = others.filter((s) => elOf(s.stem) === keEl && s.key !== 'month' && s.key !== 'day');
|
|
107
|
+
const keMonth = !!keEl && monthMain === keEl;
|
|
108
|
+
|
|
109
|
+
const conditions = {
|
|
110
|
+
adjacent: gap === 0,
|
|
111
|
+
noConflict: !conflict,
|
|
112
|
+
unrescued: sameKind.length === 0,
|
|
113
|
+
monthLead: (monthEl && monthEl === hua) || (monthMain && monthMain === hua) || false,
|
|
114
|
+
leadUnchecked: keMajor.length === 0 && !keMonth,
|
|
115
|
+
};
|
|
116
|
+
const ok = conditions.adjacent && conditions.noConflict && conditions.unrescued
|
|
117
|
+
&& conditions.monthLead && conditions.leadUnchecked;
|
|
118
|
+
|
|
119
|
+
const missing = [];
|
|
120
|
+
if (!conditions.adjacent) missing.push(closeness === '隔合' ? '相隔一位(隔合)' : '相隔两位(遥合)');
|
|
121
|
+
if (!conditions.noConflict) {
|
|
122
|
+
missing.push(`${conflict}(另有${conflictStem}与${conflict === '争合' ? '同一阴干' : '同一阳干'}成合)`);
|
|
123
|
+
}
|
|
124
|
+
if (!conditions.unrescued) missing.push(`被化干${yin.stem}在天干有同类${sameKind.map((s) => s.stem).join('、')}帮扶`);
|
|
125
|
+
if (!conditions.monthLead) missing.push(`月令${mb}(${monthEl || '—'})不是化神${hua}`);
|
|
126
|
+
if (!conditions.leadUnchecked) {
|
|
127
|
+
const who = [
|
|
128
|
+
...keMajor.map((s) => `${s.stem}(${s.label}干)`),
|
|
129
|
+
keMonth ? `月支${mb}本气${keEl}` : '',
|
|
130
|
+
].filter(Boolean);
|
|
131
|
+
missing.push(`引化物${hua}被${keEl}克:${who.join('、')}`);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const status = ok ? '化成功'
|
|
135
|
+
: !conditions.adjacent ? `${closeness}不化`
|
|
136
|
+
: !conditions.noConflict ? `${conflict}不化`
|
|
137
|
+
: '合绊不化';
|
|
138
|
+
|
|
139
|
+
const pair = `${a.stem}${b.stem}`;
|
|
140
|
+
const positionText = `${a.label}干${a.stem}与${b.label}干${b.stem}`;
|
|
141
|
+
const leadText = monthEl === monthMain || !monthMain
|
|
142
|
+
? `月令${mb}为${monthEl}`
|
|
143
|
+
: `月令${mb}为${monthEl}、本气${monthMain}`;
|
|
144
|
+
const evidence = ok
|
|
145
|
+
? `${positionText}紧挨,成${pair}合化${hua};${leadText},正好引化;`
|
|
146
|
+
+ `被化干${yin.stem}${elOf(yin.stem)}在天干无同类帮扶;克${hua}的${keEl}不在月干与日干,月支本气也不是它。`
|
|
147
|
+
: `${positionText}成${pair}合,但${missing.join(';')},只作合绊,不论化。`;
|
|
148
|
+
|
|
149
|
+
items.push({
|
|
150
|
+
pair,
|
|
151
|
+
huaElement: hua,
|
|
152
|
+
positions: `${a.key}-${b.key}`,
|
|
153
|
+
positionText,
|
|
154
|
+
closeness,
|
|
155
|
+
distance: gap,
|
|
156
|
+
yinStem: yin.stem,
|
|
157
|
+
yangStem: yang.stem,
|
|
158
|
+
conflict,
|
|
159
|
+
conflictStem: conflictStem || null,
|
|
160
|
+
conditions,
|
|
161
|
+
status,
|
|
162
|
+
ok,
|
|
163
|
+
dayMasterInvolved: !!ds && (a.stem === ds || b.stem === ds),
|
|
164
|
+
evidence,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const transformed = items.filter((x) => x.ok).map((x) => `${x.pair}化${x.huaElement}`);
|
|
170
|
+
const lines = items.map((x) => `【${x.status}】${x.evidence}`);
|
|
171
|
+
if (items.some((x) => x.ok && x.dayMasterInvolved)) {
|
|
172
|
+
lines.push('日元参与的那一组即使化成功,五行属性仍按原干论,只表现形式变。');
|
|
173
|
+
}
|
|
174
|
+
// 克化神之五行只在年干/时干出现时不挡化,但要写明——离得远,力道打折
|
|
175
|
+
for (const x of items) {
|
|
176
|
+
if (!x.ok) continue;
|
|
177
|
+
const keEl = keOf(x.huaElement);
|
|
178
|
+
const far = slots.filter((s) => elOf(s.stem) === keEl && x.positions.split('-').indexOf(s.key) < 0
|
|
179
|
+
&& s.key !== 'month' && s.key !== 'day');
|
|
180
|
+
if (far.length) lines.push(`${x.pair}化${x.huaElement}:克化神的${keEl}只在${far.map((s) => `${s.label}干`).join('、')},被化神隔开,不挡化。`);
|
|
181
|
+
}
|
|
182
|
+
const text = items.length ? lines.join('\n') : '四柱天干未见五合。';
|
|
183
|
+
|
|
184
|
+
return { items, transformed, text, method: METHOD, boundary: BOUNDARY, notes };
|
|
185
|
+
}
|
package/engine/interpret.js
CHANGED
|
@@ -547,6 +547,29 @@ function baziInterpret(r) {
|
|
|
547
547
|
+ `边界:暗合与上面的「地支关系」(三合、三会、六合、六冲、刑、害)是两条线,本插件不把它们合并计分;`
|
|
548
548
|
+ `${r.relations.anhe.length === 1 ? '本盘只出现一对,按课里口径可以直接忽略。' : `本盘共 ${r.relations.anhe.length} 对,可作取象参考,但仍不折旺衰。`}`,
|
|
549
549
|
}] : []),
|
|
550
|
+
// 五合化与不化:上面「天干关系」只写「化某待定」,这一节才拿四条件去判。
|
|
551
|
+
// 判完仍然不改旺衰与喜忌——所以把「不改什么」写进节里,别让人当成合化后重排。
|
|
552
|
+
...(r.relations && r.relations.hehua && Array.isArray(r.relations.hehua.items) && r.relations.hehua.items.length ? [{
|
|
553
|
+
key: 'hehua', label: '合化',
|
|
554
|
+
text: `${r.relations.hehua.text}\n`
|
|
555
|
+
+ `口径:${r.relations.hehua.method}\n`
|
|
556
|
+
+ `边界:${r.relations.hehua.boundary}\n`
|
|
557
|
+
+ (r.relations.hehua.notes || []).map((n) => `· ${n}`).join('\n'),
|
|
558
|
+
}] : []),
|
|
559
|
+
// 财库:库在四支、冲开与否、财是喜是忌——三件事一起才有结论
|
|
560
|
+
...(frame.caiKu ? [{
|
|
561
|
+
key: 'caiku', label: '财库',
|
|
562
|
+
text: `【${frame.caiKu.verdict}】${frame.caiKu.detail}\n`
|
|
563
|
+
+ `口径:${frame.caiKu.rule}${frame.caiKu.method}\n`
|
|
564
|
+
+ `边界:${frame.caiKu.boundary}`,
|
|
565
|
+
}] : []),
|
|
566
|
+
// 三平衡:只给富贵层次的「解读方向」,不反改旺衰与喜忌
|
|
567
|
+
...(frame.balance ? [{
|
|
568
|
+
key: 'balance', label: '三平衡',
|
|
569
|
+
text: `【${frame.balance.tier}】${frame.balance.text}\n`
|
|
570
|
+
+ `口径:${frame.balance.rule}${frame.balance.method}\n`
|
|
571
|
+
+ `边界:${frame.balance.boundary}`,
|
|
572
|
+
}] : []),
|
|
550
573
|
(() => {
|
|
551
574
|
const ss = r.shensha;
|
|
552
575
|
const cols = { year: '年', month: '月', day: '日', hour: '时' };
|
package/engine/plain-summary.js
CHANGED
|
@@ -114,9 +114,20 @@ function baziSummary(r) {
|
|
|
114
114
|
: cl.label === '燥热' ? '火土偏燥,像久旱的地,需要水和湿气来松一松'
|
|
115
115
|
: '寒暖相对均衡,没有极端的偏枯';
|
|
116
116
|
const needEl = (cl.need && cl.need.element) || favor[0] || '';
|
|
117
|
+
// 财库:库在不在、开没开、财是喜是忌——把三件事压成一句人话,接在总纲末尾
|
|
118
|
+
const ck = (r.frame && r.frame.caiKu) || null;
|
|
119
|
+
const caiKuLine = (() => {
|
|
120
|
+
if (!ck) return '';
|
|
121
|
+
if (!ck.present) return '财这一路没有立库,赚多少看明面上的财星与行运,不靠「开库」这一说。';
|
|
122
|
+
if (ck.opened && ck.verdict === '开库主发') return `财有库(${ck.store}),而且库门被${ck.opener}冲开了:钱是能进来的,关键在于你肯不肯把它存住。`;
|
|
123
|
+
if (ck.opened && ck.verdict === '开库反主破财') return `财有库(${ck.store})也被冲开了,但这一行在你这盘上是忌:动得越多漏得越快,稳比冲重要。`;
|
|
124
|
+
if (ck.opened) return `财有库(${ck.store}),库门也开了,但财本身不算厚:有得有失,别指望一次翻身。`;
|
|
125
|
+
return `财有库(${ck.store}),门还关着:不是没有,是要等对的时间或对的选择把它引出来。`;
|
|
126
|
+
})();
|
|
117
127
|
const lead = `${dm.stem || ''}${dm.element || ''}日主,生在${season}${month.branch || ''}月:${climateWord}。`
|
|
118
128
|
+ `${needEl ? `最需要的是${needEl}${cl.need && cl.need.why ? `——${cl.need.why}` : ''}。` : ''}`
|
|
119
|
-
+ `整体${r.strength ? r.strength.level : '中和'},不是极旺也不是极弱,所以${r.strength && r.strength.level === '身弱' ? '很多事要靠外部条件配合,硬扛不如借力' : '撑得住,关键是别把力气用在错的地方'}
|
|
129
|
+
+ `整体${r.strength ? r.strength.level : '中和'},不是极旺也不是极弱,所以${r.strength && r.strength.level === '身弱' ? '很多事要靠外部条件配合,硬扛不如借力' : '撑得住,关键是别把力气用在错的地方'}。`
|
|
130
|
+
+ caiKuLine;
|
|
120
131
|
|
|
121
132
|
// ── 底色:十神权重前两位 ──
|
|
122
133
|
const top2 = topGods.slice(0, 2).map(([k]) => k);
|
|
@@ -171,6 +182,17 @@ function baziSummary(r) {
|
|
|
171
182
|
if (avoid.length) advice.push(`少把自己放在${avoid.slice(0, 2).join('、')}过重的环境里——不是不能碰,是别长期待在那种氛围中。`);
|
|
172
183
|
if (top2.includes('印')) advice.push('给「想」设个时限:一件事想超过十分钟还没结论,就先做一个最小动作,用行动换信息。');
|
|
173
184
|
if (gejuNames.includes('伤官见官')) advice.push('把标准用在事情上,不要用在人身上;对人提要求之前,先说清你需要什么。');
|
|
185
|
+
// 三平衡:只作「往哪个方向补」的一句话,不给富贵层次的下断语(层次见解析层的三平衡节)
|
|
186
|
+
const bal = (r.frame && r.frame.balance) || null;
|
|
187
|
+
if (bal) {
|
|
188
|
+
const gaps = [];
|
|
189
|
+
if (!bal.wuxing.ok) gaps.push(`五行偏在${bal.wuxing.highest}、缺在${bal.wuxing.lowest}`);
|
|
190
|
+
if (!bal.yinyang.ok) gaps.push(bal.yinyang.pure ? `${bal.yinyang.pure}之局` : `阴阳一边倒(阳 ${bal.yinyang.yang}/阴 ${bal.yinyang.yin})`);
|
|
191
|
+
if (!bal.climate.ok) gaps.push(`寒暖燥湿没调匀(${bal.climate.kind})`);
|
|
192
|
+
advice.push(gaps.length
|
|
193
|
+
? `结构上${gaps.join('、')}:不必去「补命」,把这几处当作长期要照看的方向就行。`
|
|
194
|
+
: '五行、阴阳、寒暖燥湿三方面都还匀:这种盘最忌讳的是为了「更好」而硬改节奏,稳住就是优势。');
|
|
195
|
+
}
|
|
174
196
|
|
|
175
197
|
return {
|
|
176
198
|
system: 'bazi',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-metaphysics",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.67.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "命理排盘(玄学 xuanxue)for DeepSeek Harness: nineteen systems and eleven quick references (almanac, solar–lunar conversion, …), with climate adjustment (tiaohou), the 120 Qiongtong Baojian entries, 1,062-char name library with per-character pinyin, Kangxi stroke counts, five-grid (五格/三才) analysis and mechanical phonetics checks, a 78-card tarot library on the Rider-Waite-Smith base (per-card English name, image description, core meaning and astrological correspondence, cross-checked against three published sources; court cards carry no zodiac by design and the chart says so), classical quotes (Ziping Zhenquan / Di Tian Sui / San Ming Tong Hui), hexagram body relations (六冲/六合/伏吟/反吟/化进神/化退神) plus yongshen placement (用神落位) with month/day strength (月建日辰旺衰) and whole-hexagram per-line strength (全卦逐爻旺衰) and response-time clues (应期线索:逢值/逢冲/逢合 + 月建五态快慢) for liuyao, plus an MBTI-style 16-type questionnaire and exact dayun handover dates (交运日) with annual suiyun hints (岁运并临/伏吟反吟), palace conditions (击刑/入墓), month states (旺相休囚死) and stem–palace relations (天盘干与宫生克) for qimen, flying four-transformations with chained flights (四化飞星串连), three-way-four-corner composite flights (三方四正复合飞化), switchable leap-month policy (闰月按日切分/整月归次月/整月归本月) eleven school switches (亮度/庚干四化/天马/天空/截空旬空/魁钺/天伤天使/长生/晚子时/身主/杂曜全表) for ziwei, the last one opting in to a 61-star minor-star (杂曜) table where each of the twelve extra stars carries its placement verse and the palace it landed in (verses accepted only when at least two independent published editions give the same table, homonymous stars never merged), caliber diffs for bazi/ziwei/qimen (same inputs, one switch, root-field changes), shadow-chart IDs (same normalized params → same ID; version bumps auto-diff chart fields), step-by-step deduction traces (liuyao najia→liuqin→shiying→fushen→strength; bazi strength score and pattern/yongshen; ziwei pattern conditions), and a bundled offline single-file page (命理排盘.html), a panel-to-chat handoff that asks the Harness about a finished chart, per-tab lazy engine chunks so the first-screen client bundle stays under 100KB gzip, and a public verification report (128 classical hexagram cases, 312 Zi Wei charts × 34 patterns, 12 dayun handover cases) generated from the same source that gates CI.",
|
|
6
6
|
"keywords": [
|