dsh-metaphysics 0.59.0 → 0.60.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 +154 -5
- package/README.md +15 -0
- package/client.almanac.js +65 -61
- package/client.bazi.js +111 -107
- package/client.chenggu.js +65 -61
- package/client.convert.js +65 -61
- package/client.daliuren.js +120 -116
- package/client.fengshui.js +67 -63
- package/client.hepan.js +111 -107
- package/client.js +421 -327
- package/client.liuyao.js +120 -116
- package/client.mbti.js +64 -60
- package/client.name.js +70 -66
- package/client.numerology.js +68 -64
- package/client.qimen.js +121 -117
- package/client.star.js +68 -64
- package/client.tarot.js +118 -114
- package/client.trend.js +112 -108
- package/client.xiaoliuren.js +79 -75
- package/client.zeri.js +64 -60
- package/client.ziwei.js +113 -109
- package/engine/bazi.js +800 -740
- package/engine/calendar.js +8 -2
- package/engine/diff.js +3 -0
- package/engine/dst.js +28 -1
- package/engine/geju.js +548 -547
- package/engine/handle.js +6 -2
- package/engine/index.js +154 -19
- package/engine/interpret.js +4 -1
- package/engine/limits.js +5 -0
- package/engine/lunar.js +10 -11
- package/engine/plain-summary.js +604 -0
- package/engine/random.js +9 -1
- package/engine/rectify.js +26 -4
- package/engine/trend.js +32 -20
- package/engine/zeri.js +25 -9
- package/engine/ziwei.js +5 -2
- package/index.js +34 -12
- package/package.json +13 -4
- package//345/221/275/347/220/206/346/216/222/347/233/230.html +2887 -1391
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,112 @@
|
|
|
1
|
-
## 0.
|
|
1
|
+
## 0.60.0(2026-11-02,待发布)
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
> 本版主题:从「算得对」推进到「用得顺」。新增**我的命盘**(本机档案)与**复制提问**两条日常路径,并把历算、输入守卫、异步竞态、发布闸门里查出来的问题逐条修掉。新增能力不改变既有排盘口径;同一输入、同一 asOf 仍产出同一张盘。
|
|
4
|
+
|
|
5
|
+
- **我的命盘:一次录入,下次点卡出盘**(`src/panel-kit.js`、`src/app.js`、`src/web-ui.js`):
|
|
6
|
+
- 面板与离线单页共用一套实现与同一个存储键 `dsh-metaphysics/profiles-v1`:存的是出生日期、时刻、性别、出生地这些**输入**,不是结果;只落本机,不上传。
|
|
7
|
+
- 卡片照市面排盘 App 的命盘列表:一张卡一个人,点卡直接出盘;改名、置顶、删除收在卡片右上角,悬停或键盘聚焦才出现,触屏常驻。置顶在前,其余按最近排过排序;最多 24 张,超出时淘汰最久没排的那张。
|
|
8
|
+
- 档案来自 localStorage,按外部输入对待:逐字段验一遍,日期要真过日历,坏条目整条丢弃,不把 `undefined` 渲染进卡片;同 id 只留第一条。
|
|
9
|
+
- 删除点两次才算;改名会把原称呼读回输入框,改完点「更新这张档案」覆盖原档,创建时间、使用次数与置顶状态不变。
|
|
10
|
+
- 写入失败不再假装成功:`profilesPut` 报失败,删除/置顶/记次数也回滚到存储里的真实状态;浏览器完全没有 localStorage 时同样按失败回报——否则卡片从界面消失、下次进来又复活。
|
|
11
|
+
- 旧版本或手改存储留下的「有日期没时刻」卡不再拿表单里现成的时刻顶上(那会排成另一个人),而是提示先补时刻;这种卡也不算「排过一次」。
|
|
12
|
+
- 称呼框是裸 DOM:面板重绘与单页重绘都先把已输入的字存起来,翻置顶、切视图不会把称呼抹掉。
|
|
13
|
+
|
|
14
|
+
- **复制提问:把盘面和问题整理成一段话,交给任意 AI**(`engine/followup.js`、`engine/bridge.js`、`src/app.js`、`src/web-ui.js`):
|
|
15
|
+
- 追问框优先于「所问之事」:只读主问题时,命盘类没有这个输入框,复制出去的「所问」会永远是默认开场句。
|
|
16
|
+
- 包里带上面板已算好的开场结论(直答/说人话),别的模型开场沿用同一口径;盘面摘要与回答骨架一并带上。
|
|
17
|
+
- 打包失败时按钮给出「暂无可复制内容」并自动复原,不再毫无反应;切方向 / 重绘结果时追问框里已经输入的字保留。
|
|
18
|
+
|
|
19
|
+
- **输入守卫:坏参数不再静默变成另一张盘**(`engine/index.js`、`index.js`、`engine/handle.js`):
|
|
20
|
+
- 经度统一整形并校验:数字串转数字;非有限值或超出 −180…180 报 `E_RANGE`,不再走到真太阳时里炸成裸异常,也不再静默少一次修正。
|
|
21
|
+
- 地址、问题、revise、ask、姓名等自由文本设长度上限——这些串会整段进句柄,不设限等于允许一次调用把结果撑到几百 KB。
|
|
22
|
+
- `datetime` 的秒位真正校验;`asOf` 的小时与分钟必须在范围内,非法值不再被折回另一天。
|
|
23
|
+
- 句柄增量拒绝 `__proto__` / `constructor` / `prototype` 键,避免改掉结果对象的原型。
|
|
24
|
+
- 联网解析失败不写缓存:不会连着六小时把「解析失败」当成答案;风水不再请求出生地解析(经度对盘面没有影响,发给第三方是纯外泄)。
|
|
25
|
+
- `detail` 只接受 `full` / `lean`,写了别的值不再被当成缺省静默放过。
|
|
26
|
+
|
|
27
|
+
- **历算修正**(`engine/calendar.js`、`engine/lunar.js`、`engine/dst.js`、`engine/ziwei.js`、`engine/trend.js`、`engine/random.js`、`engine/rectify.js`、`engine/zeri.js`):
|
|
28
|
+
- `jdToParts` 的分钟进位会让 23:59:45 塌回「当日 00:00」,日柱退一天;改为先归到整秒再向下取整分,拆出的那一天永远就是这一刻所在的那一天。
|
|
29
|
+
- 农历的节气时刻被移了两次时(净偏移约 −12 分),节气落在午夜前后十几分钟内会少算一天,置闰整月错位;修正后 1917 年由「闰三」回到真历表「闰二」、1922 年由「闰六」回到「闰五」。
|
|
30
|
+
- 夏令时换表日给出明确说明:起算日 02:00–03:00 的钟面读数在当年不存在,终止日 01:00–02:00 同一读数对应两个真实时刻——按哪种读法折算写进提示。
|
|
31
|
+
- 紫微流年改用调用方的 `asOf` 作基准年,同一句柄跨年不再排出不同的流年表;人生 K 线按交运年份切段,与虚岁轴对齐,不再整条线提前一年。
|
|
32
|
+
- 随机种子把高位与小数位折进状态:相差 2^32 的种子(如隔 49.7 天的毫秒时间戳)不再摇出同一卦。
|
|
33
|
+
- 生时校正的事件限 200 条、年份限 1600–2400、候选时辰去重后最多 24 个;择日事项错误统一带 `E_INPUT`,`days` 的数字串会被规范化,越界或非数字一律报错,不再静默改成 30 天。
|
|
34
|
+
|
|
35
|
+
- **输出档位与上下文**(`engine/index.js`、`index.js`、`engine/handle.js`):
|
|
36
|
+
- 新增 `detail: "lean"`:只给结论、所问方向那一条与三张表,长论述与「规则·出处」折成一行指针(省约一半文本);盘面、句柄与解析对象不变,影子盘与口径对照也不会把档位当成盘面差异。
|
|
37
|
+
- 工具 schema 把梅花与小六壬的 `mode` 合并进同一个字段并写明三组取值,避免同名字段被后定义覆盖。
|
|
38
|
+
|
|
39
|
+
- **客户端稳定性**(`src/engine-lazy.js`、`src/app.js`):
|
|
40
|
+
- 分块在途请求去重:并发打开两个体系共享同一次下载;失败也清掉在途记录,一次网络抖动不会把分块永久钉在「正在加载」。
|
|
41
|
+
- 面板连续排盘 / 连点 tab 时用序号丢弃过期结果:旧请求不再覆盖新盘,也不再在 await 之后把 tab 拨回去。
|
|
42
|
+
|
|
43
|
+
- **闸门与发布**(`tools/`):
|
|
44
|
+
- `check-html-sinks` 重写:逐插值判定,补上四类旧版漏检(裸变量赋值、一个 `esc(` 救全条、`insertAdjacentHTML` 的第二个实参、`dangerouslySetInnerHTML`),并带可自证的漏检用例。
|
|
45
|
+
- 发布脚本不再 `git add -A`:按目录白名单与扩展名逐路径暂存,点开头的运行痕迹不收,重命名记录正确跳过来源路径。
|
|
46
|
+
- 新增凭据扫描、对拍报告新鲜度校验、分块体积预算(单块 gzip ≤260KB、18 块合计 ≤2.75MB)。
|
|
47
|
+
- `npm test` 现有 147 个测试文件 / 7139 条断言;新测试覆盖档案存储、分块预算、客户端竞态、细节档位、DST 歧义、输入守卫、HTML 注入面、凭据闸。新增断言均通过「把旧实现改回去必须变红」的反向验证。
|
|
48
|
+
|
|
49
|
+
- **真机回归**:`e2e-dom` 137 项、`e2e-panel` 89 项全过,覆盖档案存入/回填/改名/置顶/两次删除/缺时刻拦截、复制提问的所问与开场结论、切方向后追问框保留、深色与窄屏布局、全程无 JS 报错。
|
|
50
|
+
|
|
51
|
+
## 0.59.1(2026-11-02,已发布)
|
|
52
|
+
|
|
53
|
+
> 已发布:npm `dsh-metaphysics@0.59.1`,shasum `43817f74d114121bbbe947c91abc10a825a287b9`,94 个文件。
|
|
54
|
+
|
|
55
|
+
> 本版主题:把「先说结论」从八字/紫微推到全部九个体系,并且堵住三个会让第一屏**说错话**的坑。不新增断法,不改算法;改的是「第一屏能不能读、说的是不是真的」。
|
|
56
|
+
|
|
57
|
+
- **九个体系都有第一屏了**(`engine/plain-summary.js`、`engine/index.js`、`src/panel-kit.js`):
|
|
58
|
+
- 之前只有八字与紫微在盘面上方给一段人话;六爻、梅花、六壬、奇门、塔罗、合盘、走势七个体系点开就是一整屏术语。
|
|
59
|
+
- 现在每个体系一个 `xxxSummary`,统一返回 `{title,chips,lead,sections,advice,caveat,footer}`;`plainSummary()` 分派,`compute()` 统一挂在 `r.brief` 上(生成失败只记 `briefError`,绝不拖垮排盘)。面板侧收成一个 `pp.briefHTML(r)`,九个盘面都只写一行前缀,不再各自判一次、也不会漏一个。
|
|
60
|
+
- 各体系讲各自的结构:六爻讲世应/用神/月日/卦体,梅花讲体用,六壬讲三传(起手—转折—落点),奇门讲日干宫与时干宫的门星神,塔罗逐张给位置义,合盘讲日主关系/夫妻宫/五行互补,走势讲「这一步的基调、最亮最闷、怎么用」。
|
|
61
|
+
- 证据:`test/plain-summary.test.mjs` 从 63 条扩到 149 条。新增一组「七体系×五项」:给得出、字段里不许漏 `undefined`、每段有实质、至少一条可做的事、结尾写明不是断语、问事的要回显用户那句话。渲染侧另测九个盘面:方框在最前、只渲染一次、带免责尾句、结果无 `undefined`。
|
|
62
|
+
|
|
63
|
+
- **六爻停在「综合」:没有用神也给第一屏,并说清为什么**(`engine/plain-summary.js`):
|
|
64
|
+
- 问题:用神由「询问方向」定,而方向默认是「综合」。默认状态下卡片一片空白——恰好是大多数第一次点开六爻的人看到的样子。
|
|
65
|
+
- 改法:走「世应版」——只讲与问题无关的世爻、应爻、卦体(六冲/六合/伏吟/反吟)与动爻,并在补充说明里写明「不是算不出来,是取用神要先知道问什么」,第一条建议就是让用户补选方向。选定方向后自动切回用神版,两种版本不会同时出现。
|
|
66
|
+
- 顺带修一句措辞:动爻原来写「4、5、6 爻动」,会被读成「六个爻都在动」;改成「第 4、5、6 爻动」,标签里的「3 爻动」是数量。
|
|
67
|
+
|
|
68
|
+
- **修:选「财运/学业」时,建议那一段是空的**(`engine/plain-summary.js`):命盘的「询问方向」是 wealth/career/love/health/study/travel/general 七档,问事提示的六类是 career/love/business/action/day/other,两套键只有两个重合。不转这一道,「财运」取不到现实核对清单。新增 `DIR2KIND` 映射(财运→生意、学业→工作、健康→其他、出行→推进)。
|
|
69
|
+
|
|
70
|
+
- **修:合盘标签渲染成 `undefinedundefined × undefinedundefined`**(`engine/plain-summary.js`):合盘结果里 `dayMaster` 是「丁火」这样一整串,不是 `{stem,element}` 对象——两种写法现在都接住。
|
|
71
|
+
|
|
72
|
+
- **修:紫微同一段里既说「成」又说「破」**(`engine/plain-summary.js`):被判冲破的格局原先同时出现在「结构上成的是…」与「被冲破的格局有…」两句里,读的人只会觉得自相矛盾。被冲破的一律不计入「成」,措辞也从「被判为被冲破」改成「冲不等于毁,说的是它不如完好时那么顶用」。
|
|
6
73
|
|
|
7
|
-
|
|
74
|
+
- **修:奇门宫位写「6宫」**(`engine/plain-summary.js`):读奇门的人认的是乾宫、巽宫,不是阿拉伯数字。宫名从 `PALACE_FIELD` 释义里取,并补上方位(乾宫(西北));中宫仍按寄宫说明。
|
|
75
|
+
|
|
76
|
+
- **修:塔罗的「关节牌」取得随机**(`engine/plain-summary.js`):原来取「第一张逆位」,同一副牌换个抽牌顺序结论就换位置。改成取「现在/现况/核心/建议」那一张,没有就取中间一张;标签里也去掉重复的「3 张」。
|
|
77
|
+
|
|
78
|
+
- **走势不再读挂钟**(`engine/trend.js`、`engine/index.js`、`engine/plain-summary.js`、`src/core.js`、`src/app.js`、`src/web-ui.js`):
|
|
79
|
+
- 原来 `trendSummary` 用 `new Date().getFullYear()` 找「你现在在哪一步」,过了元旦同一条线会自己改口,也过不了 `check-patterns` 的时间约定。
|
|
80
|
+
- 改成:`buildTrend` 接受 `nowYear`,`compute` 从 `asOf` 取年,写进 `meta.nowYear`;引擎侧一律不读挂钟。界面(面板与离线页)用 `Core.todayStamp()` 传当天,内嵌在八字页里的 K 线也带上。没给 `asOf` 时不假装知道现在,改说「没给当前日期,所以不标现在在第几步」。
|
|
81
|
+
- 顺带多给一句有用的:「走到这一步的第 N 年,再过 M 年换下一步」。
|
|
82
|
+
|
|
83
|
+
- **修(最严重的一条):新增模块漏进分块构建,八个体系的产物里静默变成 `briefError`**(`tools/build-client.mjs`):
|
|
84
|
+
- `plain-summary` 只挂在八字/紫微的栈上。另外八个分块(六爻、奇门、六壬、塔罗、黄历、择日、称骨、起名…)里 `plainSummary` 是 `undefined`,`compute` 一调就抛,被 try/catch 收进 `briefError`——源码测试全绿,打包后第一屏直接消失。这正是 0.59.0 记过的同一个坑(`limits` 那次)。
|
|
85
|
+
- 改法:抽出 `BRIEF` 组,所有会调 `compute` 的分块都带上。`chunks.test.mjs` 的 19 体系逐字节比对当场抓到(报压缩名 `Fe is not a function`)。
|
|
86
|
+
|
|
87
|
+
- **修:八字页会同时出现两个「先说结论」**(`src/panel-kit.js`、`src/app.js`、`src/web-ui.js`):K 线随八字页渲染时也带上了自己的人话方框,两个方框抢第一屏。`trendHTML(r, { brief:false })` 用于内嵌,单独看走势时仍然保留。
|
|
88
|
+
|
|
89
|
+
- **口径对照不把「人话总结」当盘面差异**(`engine/diff.js`):`brief` 是从盘面派生的叙述,换一档口径必然改写;不剔掉的话,奇门晚子时那一项会从「1 处差异」变成 3 处。
|
|
90
|
+
|
|
91
|
+
- **时辰未知:八字三柱模式,紫微/合盘阻断,趋势降级**(`engine/bazi.js`、`engine/index.js`、`src/app.js`、`src/web-ui.js`、`tools/build-html.mjs`):
|
|
92
|
+
- 问题:没填时刻就按页面默认时刻排盘,时柱、紫微命宫、起运日照常出现——**看起来像算过,实际是拿占位值算的**。这比算错更糟:错得看不出来。
|
|
93
|
+
- 做法:`buildBazi` 接受 `hourUnknown`,内部仍按「正午」跑完整条管线(大运、旺衰要有个基准),但对外把不该被当成已知的东西全部收回——`pillars.hour = null`、命宫/身宫置空(依赖生时支)、输入回显不带钟点、`civilText`/`trueSolarText` 只留日期、大运与交运去掉时刻并标 `precision: 'day'`、五行不含时柱重算、只落在时柱上的神煞整条去掉。**全文不出现 `12:00`**,内部只用语义标记 `provisionalHour: 'noon'`。
|
|
94
|
+
- 下游分三类处理:紫微(命宫由生月+生时支定,时支未知整盘不成立)与合盘(夫妻宫、大运依赖时支)→ `HOUR_UNKNOWN` 阻断并给一句可执行引导;趋势 → 降级,顶层带 `hourPrecision: 'day'` 且首行写明「起运按日估算」。
|
|
95
|
+
- 摘要第一行固定句:「时柱按正午暂算,涉及时柱的结论仅供参考」——用户先看到「这不是一张完整盘」,才不会被下面的时柱/命宫误导。
|
|
96
|
+
- 界面:八字与人生 K 线的时间框旁多一个「时辰未知」勾选(勾上即收起时刻框),面板与独立页同一套行为;紫微/合盘不提供这个勾选,因为给了等于诱导出一个假盘。
|
|
97
|
+
- 证据:`test/hour-unknown.test.mjs` 47 条。三条硬断言——全文(JSON + 渲染文本 + 摘要)不得出现 `12:00`;时柱及依赖项必须为空且不得写成已知;提示必须是摘要第一行(无出生地、远期 ΔT 精度提示都不得把它挤到第二行);工具 schema 必须暴露 `hourUnknown`;面板 `pp-warn` 必须逐字含固定句。另有五条守下游:紫微/合盘必须抛 `HOUR_UNKNOWN`、趋势必须带按日标记、默认路径逐字节不变。
|
|
98
|
+
|
|
99
|
+
- **修:无地址时固定提示被挤到第二行**(`engine/index.js`、`test/hour-unknown.test.mjs`):地警告与 ΔT 精度提示也在往摘要最前插——固定句先插、后警告再插,「时柱按正午暂算…」就被压到第二行(命中精度提示时第三行)。改为最后再插固定句,并补「无出生地」「2150 远期盘」两条断言:现在无论有没有地址、精度如何,首行都是它。
|
|
100
|
+
|
|
101
|
+
- **补:工具 schema 也支持 `hourUnknown`**(`index.js`、`test/hour-unknown.test.mjs`):原先只有面板与离线页能勾三柱,`metaphysics_chart` 的 schema 里没这个参数,Agent 要不到。补上布尔参数与说明(八字三柱、趋势按日、紫微/合盘阻断),并加断言防回退。
|
|
102
|
+
|
|
103
|
+
- **面板三柱提示改用固定句**(`src/panel-kit.js`):`pp-warn` 文案统一为「时柱暂缺:只排年/月/日三柱,起运与交运按日估算。时柱按正午暂算,涉及时柱的结论仅供参考。」,与摘要首行逐字一致(有断言)。
|
|
104
|
+
- **证据与门禁**:`test:ci` 138 文件全过,断言基线 6737 条(0.59.0 为 6620);真机回归 `e2e-dom` 103 项、`e2e-panel` 43 项(含「方框只渲染一次」);`stress` 200 盘 14 项(p95 2ms、堆增长 +0.46MB)。
|
|
105
|
+
|
|
106
|
+
## 0.59.0(2026-11-01,已发布)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
> 已发布:npm `dsh-metaphysics@0.59.0`,shasum `4712088541c06b112792c9249fe64d0dbe0dd38d`,93 个文件。
|
|
8
110
|
|
|
9
111
|
> 本版主题:把「算得更准」这条路主动停下,改走「不骗人」。三件事——知识标签不再冒充「已验证」、分歧按「本盘涉及」分组、新增「本插件不回答什么」清单。都不碰算法:0.58.0 的应期回测已经说明,51.7% 对 29.6% 的随机基线,靠调规则优先级补不上来;能补上来的是「别让用户以为它比实际更可靠」。
|
|
10
112
|
|
|
@@ -34,6 +136,28 @@
|
|
|
34
136
|
- 新增能力边界 `liuyao-liuyue`:不推演流月推进后的二次变化。依据是一条实占反例(用神伏藏、本可靠日辰冲开,进入下月建后一冲解掉原月建对制它之爻的合,制者复起,出伏失败),这类跨月推演还没做,所以应期只能作「该留意哪几支」。
|
|
35
137
|
- 证据:`test/yingqi.test.mjs` 28 条(+3)。新增两条是防回归的关键——「规则顺序照原文罗列」把 15 个 id 的顺序钉死,改排序必须给原文依据;「同时命中按原文次序取主规则」用「入墓 5 < 月破 7」的用例验证排序真的生效。另修正两个旧用例的日辰(原来取辰,正好是水墓,会把「入墓」拉进来抢主位,测的就不是月破/旬空了)。
|
|
36
138
|
|
|
139
|
+
- **真机回归:用本机浏览器把 19 个 tab 逐个点一遍**(`tools/e2e-dom.mjs`、`package.json`):
|
|
140
|
+
- 补的是最后一层:冒烟测试跑在 node 里,测得到引擎与渲染函数,测不到事件绑定、表单显隐、勾选后的重渲染、深链落地。这一层用 Chrome 真开页面点。
|
|
141
|
+
- 19 个 tab 各查:切得到、有主按钮、能出结果、结果无脏串、**全程无 JS 报错**(监听 `pageerror` 与 `console.error`)。共 103 项断言。
|
|
142
|
+
- 另测三条只有真浏览器能测的:① 八字勾「时辰未知」后,结果里必须出现「时柱暂缺」且不含 `12:00`;② 深链 `#mp=…` 直接打开能自动落地出结果;③ 深色主题下扫描全页文字对比度(含渐变背景取平均色)、390px 窄屏无横向溢出且能出结果。
|
|
143
|
+
- 用 `playwright-core` + 本机已装的 Chrome/Edge,**不下载浏览器**;找不到浏览器时打印跳过并返回 0,不会把 CI 弄红。
|
|
144
|
+
- 过程中修掉两处**误报**(不是产品问题,但值得记):渐变背景只读 `backgroundColor` 会拿到透明、把「浅底深字」判成同色;父容器(`button.tool`)的文字都在子节点里,拿父容器的 `color` 算对比度必然误判——改成只看「直接含文字节点的元素」且渐变取平均色。
|
|
145
|
+
|
|
146
|
+
- **全体系稳定性复查:新增冒烟 + 修掉 K 线 id 不稳定**(`test/smoke-all.test.mjs`、`tools/smoke-all.mjs`、`src/panel-kit.js`):
|
|
147
|
+
- 为什么加:单测各自盯一块,但整页能出结果的路径有几十条,一条崩就是白屏——上次「时辰未知」崩在 `p.stemTenGod`,引擎 6253 条断言全绿、页面全崩。这次把 19 个 tab 的 36 个用例逐个跑「排盘 → 渲染 → 文本 → 解析」四条链,共 300 条断言。
|
|
148
|
+
- 每项查五件事:不抛异常;成品里不留 `undefined / NaN / null / [object Object]`;**同一张盘渲染两次必须字节一致**;关键结构词在(四柱/命宫/值符/世爻/宜忌…);无 `<script>` 与事件属性。
|
|
149
|
+
- 另外覆盖:边界日期(1900/1929 时区切换、2024-02-29、2100)、立春前后年柱必须换、晚子时开关必须改日柱、三柱盘与完整盘的年月日柱必须一致、10 条参数错误路径必须给「带错误码的中文提示」、句柄往返、八字×紫微交叉、40 个随机日期采样、以及**交付物自身**——把单页里的 4 段内联脚本各过一遍编译器(产物语法坏了,跑源码的单测永远发现不了)。
|
|
150
|
+
- **修掉一个真 bug**:人生 K 线的 `clipPath` id 原来用全局自增(`klineSeq`),导致同一张盘两次渲染出不同 id——截图对拍、快照测试永远对不上。改成盘面内容的短哈希(FNV-1a):不同盘不同 id,同盘永远同 id。
|
|
151
|
+
- 用法:`npm run smoke`(也进 `test:ci`,断言数进基线)。
|
|
152
|
+
|
|
153
|
+
- **盘面顶部「先说结论」:一段人话总结**(`engine/plain-summary.js`、`engine/index.js`、`src/panel-kit.js`):
|
|
154
|
+
- 起因:排完盘先给的是四柱表和一堆术语,普通人第一屏读不动——就算下面写了解析,也读不到第二屏。要的是「先给一段能看懂的话,再给依据」。
|
|
155
|
+
- 内容:一个方框,四件事——总纲(日主+生月+冷暖+最需要什么)、你的底色(十神权重前两位翻成人话)、感情这件事(配偶星落在哪、配偶宫坐什么、有没有破冲合)、最容易卡住的地方;末尾给 2–4 条可以立刻做的事,再加一句补充说明与「不是断语」的尾句。
|
|
156
|
+
- 硬规矩:**只做「结构 → 人话」的翻译,不下吉凶断语**。「官杀混」可以说成「你容易遇到两种类型的人」,不能说成「你婚姻不好」。同一张盘每次生成的文字逐字相同(有断言钉死确定性)。
|
|
157
|
+
- 八字与紫微都有:紫微那版讲命宫主星、身宫落宫、夫妻宫与格局(格局只描述形状,不作吉凶判词)。
|
|
158
|
+
- 位置:方框在盘面之前、每份结果只渲染一次;对话侧 `renderText` 也把这段放在最前(`【先说结论】`),模型照它复述就不会一开口是术语表。
|
|
159
|
+
- 证据:`test/plain-summary.test.mjs` 38 条。含确定性(两次生成 JSON 全等)、不越界(不许出现「一定会/必然/注定/肯定会」)、时辰未知时必须在补充说明里讲清「只有六个字、约七成信息」、男命取财星不套女命说法、渲染顺序(方框 index < 盘面 index)。
|
|
160
|
+
|
|
37
161
|
- **面板一键「复制问事提示」**(`src/panel-kit.js`、`src/web-ui.js`、`src/app.js`、`src/core.js`、`engine/index.js`、`tools/build-client.mjs`):
|
|
38
162
|
- 六爻 / 梅花 / 大六壬 / 奇门 / 塔罗五个体系的结果页,问题行下方出现「复制问事提示」按钮:点一下,当前盘面 + 所问之事打包成一段完整提示,粘到任何对话里都能用。`core.js` 加 `kindOfDirection` 把命盘的七向(财运/事业/感情…)映射到问事的六类(business/career/love…)。
|
|
39
163
|
- 命盘类(八字 / 紫微 / 合盘 / 趋势 / 起名 / 风水 / 称骨 / 星座 / 数字 / 人格)不渲染这个按钮——它们回答的是「这个人是什么结构」,不是「这件事成不成」,给了按钮就是诱导误用。小六壬结果是单行落宫、没有解析报告,按钮也不在它那边,提示走命令行。
|
|
@@ -73,8 +197,33 @@
|
|
|
73
197
|
|
|
74
198
|
> 下列两条是 0.58.0 之后、本版之前的工作,随本版一并发布。再往下的 C3 对话桥替代 / §5.8 自动发布加固 / push-tag 三条的详细记录属 0.58.0,保留于此备查。
|
|
75
199
|
|
|
200
|
+
## 0.58.0(2026-11-01,已发布)
|
|
201
|
+
|
|
202
|
+
> 本版主题:把「盘送不进对话」这条路补成三条不依赖宿主的通道(C3),顺手让自动发布可观测、可自愈,再把引文里两句长期误署的话改回原书。
|
|
203
|
+
>
|
|
204
|
+
> 包含:C3 对话桥替代(深链 / 复制 / 结构化参数)、§5.8 自动发布加固、B6 通行说复核、B6 通根透干复核(误署纠正)、B6 第五批(大六壬 3 条)、C4-a 三方合盘、C4-b 择日候选日比较、C4-c 同盘多口径并排、D1+ 首屏耗时回显、A1+ 推导链出处、D4 发布回滚、自检修复(见下)。
|
|
205
|
+
|
|
76
206
|
## 未发布
|
|
77
207
|
|
|
208
|
+
- **凭据扫描进约定闸:token 形态的字符串提交不进去**(`tools/check-patterns.mjs`):
|
|
209
|
+
- 起因:npm / GitHub 的发布凭据存在 `<用户目录>/.dsh/metaphysics-autopublish.json`,只从环境变量喂给 `tools/release.mjs`;它一旦被贴进对话、写进文档或提交到仓库,撤回版本也撤不回已推送的历史。
|
|
210
|
+
- 新增第 8 条规则:全仓(跳过 `node_modules` / `.git` / `.workbuddy`)扫 `npm_xxx`、`gh[pousr]_xxx`、`github_pat_xxx`、PEM 私钥头。**命中只打印「文件:行」与原因,绝不回显匹配到的内容**——检查本身不能变成泄露通道。
|
|
211
|
+
- 自检:往仓库根放一个 `npm_` + 40 位的假串,闸门退出码 1 并指出 `_leak-probe.js:1`;删掉后恢复通过。当前 299 个文件无命中。
|
|
212
|
+
|
|
213
|
+
- **面板(宿主侧栏)真机回归:补上最后一层没测过的 UI,并抓到一个三柱盘必崩的 bug**(`tools/e2e-panel.mjs`、`src/app.js`、`package.json`):
|
|
214
|
+
- 缺口在哪:单页 E2E 跑的是 `src/web-ui.js`,面板跑的是 `src/app.js`——两条渲染链只有 `panel-kit` 共用。面板自己的状态(勾选联动、本地历史、深链落地、首屏卡片)此前只有静态字符串断言,等于没跑过。
|
|
215
|
+
- 怎么测:真 Chrome + **真 React 18**,配一个最小宿主——假 `slots` 注册表(`register` / `inject` / `spec`)、假 `ctx.effect`、`assemble()` 打出的全量 client(含引擎),本机 http 起服务(`file://` 下 localStorage 会抛 SecurityError)。把 `PanelIcon` 画进侧栏、主面板画进 `#main`,然后照用户顺序点:切体系 → 排盘 → 勾「时辰未知」→ 起卦 → 切深色 → 缩到 520px → 带 `#mp=` 深链重开。43 项断言。
|
|
216
|
+
- **抓到的真 bug**:`HISTORY_LABEL` 对 `pillars` 逐项取 `.ganzhi`,时柱为 `null` 时抛 `Cannot read properties of null`——表现是「三柱盘一点排盘就报错」,而引擎 6620 条断言全绿(那段代码在面板里,不在引擎里)。已修:过滤空柱,并在文案末尾写「(时柱暂缺)」,别让历史条目看起来像四柱。
|
|
217
|
+
- 顺带验了面板独有的几处:勾选后时刻框被禁用、排过的盘进 `localStorage` 并出现在「最近用过」、连点 10 次不崩也不膨胀、深色下选中卡片对比度 8.13:1、520px 容器无横向溢出、深链把面板切到对应体系并带回问题。
|
|
218
|
+
- `test/hour-unknown.test.mjs` 补 6 条把 `HISTORY_LABEL` 的逻辑本身钉住(从 `app.js` 取出函数独立求值,不依赖浏览器),免得下次又只有真机才暴露。
|
|
219
|
+
- 用法:`npm run e2e:panel`(没有 Chrome/Edge 时打印跳过并返回 0);`npm run e2e` 现在同时跑单页与面板两层。
|
|
220
|
+
|
|
221
|
+
- **连续 200 次压测:不崩、不漂、不涨、不串**(`test/stress.test.mjs`、`package.json`):
|
|
222
|
+
- 冒烟测「每条路能走通」,压测测「一直走会不会变形」。200 份**不同日期**的输入(八字/紫微/六爻/奇门轮转,逼缓存真的淘汰),预热 20 次后再跑。
|
|
223
|
+
- 四条断言:① 200 次零抛错、结果里没有 NaN/undefined/[object Object];② 同一份输入在压测前后**逐字节一致**(抓隐藏计数器、缓存污染);③ 日历三个 LRU 都不超上限,且确实踩到过上限(`termInstant 899/4096`、`termYear 32/32`、`termWindow 8/8`——踩不到说明压测没打中热点);④ 后 50 次不比前 50 次慢(0.5ms vs 0.8ms),p95 ≤40ms。
|
|
224
|
+
- 内存单独起一个 `--expose-gc` 子进程量:强制 GC 后堆增长 **+0.44MB**(9.55 → 10.00MB)。同进程量只会量到未回收的垃圾,是噪声不是泄漏。
|
|
225
|
+
- 实测:200 次共 127ms,平均 0.61ms/次。用法 `npm run stress`。
|
|
226
|
+
|
|
78
227
|
- **B1 六爻应期:样本不再等用户,改从《增删卜易》里取;规则层落地,命中率公开且不好看**(`engine/yingqi.js`、`tools/gen-zengshan-cases.mjs`、`tools/backtest-yingqi.mjs`、`test/fixtures/zengshan-cases.json`、`test/yingqi.test.mjs`):
|
|
79
228
|
- 为什么不等用户给卦例。应期对拍要「月建日辰 + 完整六爻 + 断语 + 应期口径 + 实际应验」五样齐,这类样本在《增删卜易》里本来就是成批的(野鹤老人自己拿实占卦例成书)。本地已缓存全书 12.4 万字,170 处「X月Y日占」起式,够用,且不必麻烦用户现编。
|
|
80
229
|
- 收录标准四条全过才收:起式能定位月建日辰;六爻能按行解析;**解析出的六亲/地支/五行与引擎纳甲逐爻一致**(这一条同时充当解析正确性校验——纳甲+六亲由卦宫五行唯一决定,六爻全对基本等于卦没错);断语点名用神(「寅木官星持世」「未土父母動化進神」「財爻持世」「世爻寅木」「X为用神」五种句式);应验句里有可解析的年月日。结果 **29 条收录 / 141 条排除**,每条排除都写了理由(`excluded`),不静默丢弃。变卦名按「原文缩写还原成候选,候选唯一才核」处理(写「之兌」即兑为泽、写「之夬」即泽天夬,「大」这种可指大过/大壮的当未能核验),避免拿缩写误判。
|
package/README.md
CHANGED
|
@@ -238,11 +238,22 @@ dsh plugin install ./dsh-metaphysics-0.17.0.tgz
|
|
|
238
238
|
|
|
239
239
|
`docs/象与数-要义导读.md` 是把这三层讲成人话的一篇长文:数是坐标系、象是关系、辞是名字;纳甲为什么必须存在、十神与宫位各自站在哪、为什么「同一个用神伏藏」能读出相反的结论、以及**怎么用三个问题判断一句断语是不是在裸奔**。不教断命,只帮你把事情分清楚:哪些算得准、哪些可商量、哪些只能自己决定。
|
|
240
240
|
|
|
241
|
+
## 先说结论
|
|
242
|
+
|
|
243
|
+
排完盘,**最上方**是一段人话总结(方框):这张盘/这一卦大致在说什么、关键落点在哪、最容易卡住的地方,再加几条可以立刻做的事。它在盘面之前——先给结论,再用下面的盘面作依据;反过来大多数人读不到第二屏。
|
|
244
|
+
|
|
245
|
+
九个体系都有这一屏:八字(底色/感情/卡点)、紫微(命身/夫妻宫/被冲破的格局)、六爻(世爻/用神/成不成看哪里)、梅花(体用与过程结果)、六壬(起手—转折—落点)、奇门(你的宫与事的宫、门星神)、塔罗(逐张位置义)、合盘(日主关系/夫妻宫/五行互补)、人生 K 线(这一步的基调、最亮与最闷、怎么用)。
|
|
246
|
+
|
|
247
|
+
其中两条是特意做的「不许糊弄」:六爻若「询问方向」还停在综合,取不到用神,它不会硬给一个结论,而是改读世应与卦体,并把「为什么没有结论、该补哪一步」写在方框里;走势若没拿到当前日期(`asOf`),它不猜「你现在几岁」,直接说明不标当前位置。
|
|
248
|
+
|
|
249
|
+
这段只做「结构 → 人话」的翻译,不下吉凶断语:可以写「你容易遇到两种类型的人」,不会写「你婚姻不好」。同一张盘每次生成的文字完全一致(引擎不读挂钟,当前时间由界面传入);时辰未知时它会先说明「只据六字、约七成信息」。
|
|
250
|
+
|
|
241
251
|
## 精度与口径
|
|
242
252
|
|
|
243
253
|
- **节气**:VSOP87B 截断级数(105 项)+ 岁差 + 章动 + 光行差;与日本国立天文台《暦要項》对拍,2024/2025 共 48 个节气最大偏差 **0.6 分钟**;出生时刻距「节」不足 20 分钟时会提示复核。**1929-01-01 之前按北京地方平时(UTC+7.7611)**推算,之后按东八区——与农历共用同一套换算,避免 14 分钟错位
|
|
244
254
|
- **农历**:定朔(Meeus 第 49 章,误差约 1 分钟)+ 冬至所在月为十一月 + 无中气置闰
|
|
245
255
|
- **真太阳时**:经度差 + 均时差;内置 34 个省会 + 200 个地级市坐标(±0.2°),地址更细时可开「联网精确到区县」(Nominatim)。**单盘与合盘用的是同一套修正**(合盘双方各按自己出生地算)。只按经度修正,**未含历史时区与夏令时**:海外出生请先把当地钟表时间换算成东八区标准时再输入;没给经度时摘要首行会出 ⚠
|
|
256
|
+
- **时辰未知**:不知道出生时刻时勾「时辰未知」,八字只排年/月/日三柱,时柱不给、命宫身宫不排、起运与交运降到按日(`dayun.precision: 'day'`),摘要第一行固定写「时柱按正午暂算,涉及时柱的结论仅供参考」;工具侧传 `hourUnknown: true` 等价(八字 / 趋势可用)。**紫微与合盘会直接报 `HOUR_UNKNOWN`**:这两套离开生时支就不成立,硬排出来只是看着像盘。全文不出现 `12:00` 这类占位钟点。
|
|
246
257
|
- **晚子时**:八字/大六壬默认 23:00 后换日,奇门默认归当日;`lateZi` 与 `lateZiHourMode` 是同一个开关的两个名字。各体系摘要都会写明本次采用的口径,不改默认值、不偷偷改盘
|
|
247
258
|
- **口径对照**:`caliberCompare` 只做「当前口径 → 另一档」的逐字段比对,根因按柱 / 命宫 / 局数 / 起运归类,`total` 是变化字段数、不是分数;没有根因时写明「无单一根因」(如真太阳时只改起运时刻)。紫微的 12 组含十类流派开关(亮度 / 庚干四化 / 天马 / 天空 / 截空旬空 / 魁钺 / 天伤天使 / 长生 / 晚子时 / 身主),平铺参数与 `schools` 嵌套都能读;取局流派、晚子时归日、闰月政策与流派回显属于口径回显,不计入差异;「其他」是尚未归类的派生字段,不隐藏也不折算。每行另给 `views`:八字(日柱 / 时柱 / 旺衰 / 格局 / 喜用 / 起运)、紫微(命宫 / 身宫支 / 五行局 / 身主 / 起大限)、奇门(日柱 / 局数 / 值符 / 值使)的两列并排,只列变化项,摘要里写成「并排:日柱 丙辰 → 乙卯」,面板与独立页画成表格。对照会按开关数多排盘(工具里由 `diff: true` 显式开启)
|
|
248
259
|
- **八字五合**:干支关系只标「有合」,摘要写「戊癸合(化火待定)」;是否真化另看月令、化神与争合妒合,不在关系层直接断「合化火」
|
|
@@ -309,6 +320,10 @@ npm run build:verification # 重建 docs/verification.html 与 README 徽章(
|
|
|
309
320
|
# 存到别处:node tools/build-html.mjs --out "D:\某处\命理排盘.html"
|
|
310
321
|
npm test # 顺序跑完 test/ 下全部 *.test.mjs 并汇总
|
|
311
322
|
npm run test:ci # 构建 + 产物自检 + 回归 + 断言基线 + 测试自检 + HTML 注入面 + 工程约定(CI 跑的就是这条)
|
|
323
|
+
npm run smoke # 全体系冒烟:19 个 tab × 关键选项 × 边界日期,看「排盘→渲染→文本」三条链有没有崩
|
|
324
|
+
npm run stress # 压测:连续排 200 次(不同日期),查不崩、不漂、缓存不涨、体系不串
|
|
325
|
+
npm run e2e # 真机回归:单页 19 个 tab + 宿主面板,各点一遍(无浏览器时自动跳过)
|
|
326
|
+
npm run e2e:panel # 只跑面板那层:真 Chrome + 真 React + 假宿主槽位,43 项
|
|
312
327
|
npm run test:baseline # 断言数确实要减少时,显式重建基线
|
|
313
328
|
npm run check:html # 单独跑 HTML 注入面扫描
|
|
314
329
|
npm run check:patterns # 单独跑工程约定检查
|