Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c64733f91 | ||
|
|
853772bcea | ||
|
|
1252de3e63 |
@@ -68,3 +68,11 @@
|
||||
| 推送 / 部署 / Gitea 页面 | 没做 |
|
||||
|
||||
快速门跑的时候改写了 `references/oracle/artifacts/pending_packets/` 下 5 个模板文件。那不是本单的改动,收尾时还原,不提交。
|
||||
|
||||
## Claude 验收与补修(2026-10-04)
|
||||
|
||||
- 实测:快速门 18 行(改前约 14,000 行);`CI=true npm test` 346 行,24 条已知失败的名字和报错都列出,退出码 1;本机 Node 22 `npm test` 输出 TAP,失败名单与开工基线逐条相同;快速门子步骤失败(假命令 exit 3)时打出 ✗、末 200 行、`gate-logs/01-fake-fail.log` 和退出码;`test_run_quality_gate_output.py` 10 条通过;workflow 合同测试唯二的失败(live staging sync 两条)本来就在基线 24 条里。
|
||||
- workflow 拆成 7 步,原 7 条命令一条不少、参数不变,没有吞退出码。
|
||||
- **补修(违反红线 4)**:`run-tests.mjs` 把 `tests/*.test.ts` 原样交给 `node --test`。Node 22 会自己展开,Node 20 不会,报「Could not find tests/*.test.ts」,一条测试都不跑;本机默认的 Node 就是 v20.19.2。改为脚本自己读 `tests/` 目录,`*.test.ts` 排序后接 `*.test.tsx` 排序,与 shell 展开的顺序相同。
|
||||
- 补修后,Node 20 下 4,932 项、69 条失败,与旧写法 `tsx --test tests/*.test.ts tests/*.test.tsx` 在 Node 20 下的失败名单逐条相同(都是 Node 20 自身的旧问题)。
|
||||
- Node 22 下 4,932 项、24 条失败,名单与基线相同;`CI=true` 时 346 行。
|
||||
|
||||
@@ -421,3 +421,5 @@
|
||||
| `TASK-astrologer-rulings-batch5-20261004.md` | `PROGRESS-astrologer-rulings-batch5-20261004.md` | 占星师第六轮:Rath 双主星按 p.43(a)–(e)、罗计尊贵按 Rath Table 9(仅 Narayana 内)、子运方向 p.51 例外与书内分歧标注、Wadiyar 两对标软件特例;年主选不出时不再用 Muntha 主星顶替(对齐上游 03bea6ed);Rath 替换校正 v5 重试算(研究)(BUG 从 1223 起) | 已实现待验收(T2–T5 完成;T1 按红线停下 blocked;T6 研究分支已跑) | 分支 `codex/astrologer-rulings-batch5-20261004`(未推送;BUG-1223~1227;校正分数不变、未升版本);研究分支 `codex/narayana-rath-rectification-trial-20261004`(不合入) |
|
||||
| `TASK-astrologer-rulings-batch6-20261004.md` | `PROGRESS-astrologer-rulings-batch6-20261004.md` | 第七轮裁定(共享仓书面回复,产品采用;问 1 选 A):Rath 版双主星按 p.43 (a)–(e)(BUG-1227 解除 blocked,推翻第五批红线 2 的 Table 17 年数底线);第 5 级宫主度数只倒算计都(p.71 脚注 42);罗计旺陷 ±1 年;同宫两主比经度;BUG 从 1228 起 | 待验收 | 分支 `codex/astrologer-rulings-batch6-20261004`(BUG-1227~1229;校正分数文件未改、未升版本) |
|
||||
| `TASK-gate-log-volume-20261004.md` | `PROGRESS-gate-log-volume-20261004.md` | 门禁 validate 单步日志 4.4 万行 / 2 MB 网页打不开(run 3170):快速门只打摘要(失败给末 200 行 + 日志文件)、前端测试门禁上 dot + 失败汇总(本机仍 TAP)、拆分 validate 为 7 个 step(产品授权改 workflow,只限拆分与重定向);检查一项不少 | **已实现待验收**(BUG-1230;未推送、未部署;Gitea 各 step 页面是否打得开留待推送后由产品确认) | 分支 `codex/gate-log-volume-20261004` |
|
||||
| `TASK-consult-latency-quickwins-20261005.md` | `PROGRESS-consult-latency-quickwins-20261005.md` | 普通对话耗时两项快修:咨询链校正闸不再同步白等 VedAstro 官方快照子进程(每域约 4 s,复用顶层缓存 + 负缓存,不推翻 BUG-301);补分段计时(第 0/1 步耗时、推理 token、分类耗时进日志与 usage)。推理强度/精简说明待模型 key 另单(BUG 从 1231 起) | 待领取 | 分支 `codex/consult-latency-quickwins-20261005` |
|
||||
| `TASK-rectification-nadi-seconds-research-20261005.md` | `PROGRESS-rectification-nadi-seconds-research-20261005.md` | **「纳迪秒级校准」可证伪检验(离线)**:竞品宣传「问前事到天 → 秒级」。本仓主链只用三层小运,Sookshma / Prana 与 D150 从未进评价集;v5 真值 52/77 是整 5 分钟(秒级无真值可对)。N0 五层小运 + D150 底座(前三层与主链对账 0 差)、N1 拟合率 vs 安慰剂日期(核心)、N2 留一件预测、N3 六题后区间内再细分能否提头名、N4 岁差 / 坐标 / 时间扰动的噪声地板、N5 D150 结构层(原文比对 blocked)、N6 结论 + 对外口径草稿。规则先登记再跑;不改生产代码;不得重调 BUG-1091 已关的权重 | 待领取 | 分支 `codex/rectification-nadi-seconds-research-20261005`(BUG-1240) |
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
# TASK:普通对话耗时——外部服务不再白等 + 补分段计时 — 2026-10-05
|
||||
|
||||
## 基线
|
||||
|
||||
- 开工时 `git fetch origin --prune` 之后的最新 `origin/staging`。写本单时是 `1252de3e`,已部署。
|
||||
- 分支 `codex/consult-latency-quickwins-20261005`,工作树 `.worktrees/consult-latency-quickwins-20261005`。
|
||||
- 依据:10-04 只读审计(Claude 子代理)。测量脚本与原始数据在 Claude scratchpad `bench/`,不入库;结论摘要见下面「事故实证」。
|
||||
|
||||
## 事故实证
|
||||
|
||||
一轮普通对话(问父母、问年运)全程串行,分为:分类(thinking 关,≤3 s)→ 第 0 步(thinking 开,决定调用排盘工具)→ 引擎 `/api/consultation_workflow`(每个领域一次,最多 2 个领域)→ 第 1 步写答案(thinking 开)。
|
||||
|
||||
1. **校正闸每个领域白等 4 秒。**
|
||||
- 咨询链里的 rectification gate(`jyotish_api_server._compute_rectification_gate` → `vedastro_gateway.run_gateway_packet`)会走到 `vedastro_service_adapter` 中调用 `_try_official_capability_runner_snapshot_bundle` 的那一段(按符号定位)。它起一个子进程,撞上 `DEFAULT_TIMEOUT_SECONDS = 4`。
|
||||
- 本机装上 vedastro SDK、按产品路径(`defer_optional_external_evidence: true`)实测,每次 4.6 s,第二轮仍是 4.6 s。原因:失败结果不写缓存。
|
||||
- 同一份响应里,顶层 `vedastro_gateway` 是 `official_verified`(BUG-727 的缓存在起作用),但 `rectification.vedastro_gateway.official_closure_reason = official_raw_response_missing`。
|
||||
- 屏蔽外网时,引擎每个领域 0.75 s;这 4 s 是额外的等待。
|
||||
- **这些数字在沙箱网络下测得,生产 VPS 是否同样撞超时,须在 staging 先确认(T0)。**
|
||||
2. **看不到分段时间。**
|
||||
- 现有埋点(`[agent-observability]`、`/admin/usage`)有 `first_byte`、工具耗时、`answer.first_output`、`run.total`、总 token。
|
||||
- 没有:推理 token 数;第 0 步、第 1 步各自的耗时;分类耗时进不了 usage。
|
||||
- 推理慢的主因(答题步约 1 万推理 token、约 45 秒)因此无法在线上逐轮核对,后续「限制推理强度」「精简说明」两单也没有办法验证。
|
||||
|
||||
## 决策记录(产品负责人 2026-10-05)
|
||||
|
||||
1. 做「不白等外部服务」和「补分段计时」两项,也就是审计建议的 ③ 和 ⑤。
|
||||
2. 「限制推理强度」「精简说明」「第 0 步关 thinking」**不在本单**,等产品提供临时模型 key、跑名人回测之后另开单。
|
||||
3. **不推翻 BUG-301**:顶层前台 VedAstro 照旧调用。本单只处理咨询链里校正闸那一处注定拿不到结果的等待。
|
||||
|
||||
## 硬红线
|
||||
|
||||
1. 遵守 `jyotish_api_server.py` 的增长冻结(AGENTS §6):类方法数不增长,`JyotishAPIHandler.__new__` 伪造点不增长。改动放进 `scripts/vedastro_service_adapter.py` / `scripts/vedastro_gateway.py`,或新模块。
|
||||
2. 不改生时校正的打分:v5 77 例与改动前逐项相同;冻结身份文件(`references/rectification_sealed_holdout.v1.json` → `production_scoring_files`)原则上不动。确实要动,就按 ERR-110 重新冻结,并同步 `frontend/tests/rectification-confirmation-gate.test.ts` 的两处路径(三栏)和 `tests/test_sealed_holdout_contract_freshness.py`。
|
||||
3. 生时校正面自己调用 VedAstro 的行为(若与咨询共用同一函数)不得改变;只对咨询路径生效,或者用开关区分。改动前后,生时校正的官方证据字段要逐项相同。
|
||||
4. 埋点只记**数字和状态**(毫秒、token 数、步骤号、是否超时),不记提示词、答案正文、出生资料、用户 ID(AGENTS §8、§5.6)。
|
||||
5. 不改普通对话提示词和数据卡内容。
|
||||
6. 验收要跑 Python 全量 `pytest tests` 并与开工基线对比失败名单(BUG-1220 的教训),不能只跑快速门。
|
||||
7. 不用 `git stash`;不切换别人的工作树;开工前先 `df -h /`。
|
||||
|
||||
## 任务分解
|
||||
|
||||
### T0 staging 先确认(只读,不改代码)
|
||||
- 用 staging 的公开接口或测试账号,对一位公开名人发一次 `/api/consultation_workflow`(或经普通对话发一次),记录:
|
||||
- `rectification.vedastro_gateway.official_closure_reason`;
|
||||
- 该请求的耗时。
|
||||
- 拿不到登录态时,在进度记录里写明「T0 环境缺口」,并给产品一条可照做的检查方法:在 `/admin/usage` 或容器日志里看工具耗时是否接近「领域数 × 4 s 以上」。
|
||||
- T0 不阻断 T1。
|
||||
|
||||
### T1 校正闸不再同步白等官方快照子进程
|
||||
- 咨询路径下(以请求里已有的 `defer_optional_external_evidence` 或同等标记区分),校正闸遇到官方快照 runner 时:
|
||||
- **优先**:复用顶层 `vedastro_gateway` 已经拿到的官方结果(同一份「出生数据 + 岁差 + 交点 + UTC 日期」缓存键,BUG-727)。
|
||||
- 拿不到时,不再前台起 4 秒子进程,直接标 `official_closure_reason = deferred_in_consultation`(或同义的明确状态),不伪装成 `verified`。
|
||||
- 失败或超时的结果按同一个缓存键写入**负缓存**,有效期到当日 UTC 结束,避免同日每轮重复等待。
|
||||
- **验收**:
|
||||
- 本机装 vedastro SDK 后,按产品路径实测:每个领域的耗时从约 4.6 s 降到不超过 1.0 s(测 3 位名人 × 父母 / 年运,冷、热各两轮),数字写进进度记录;
|
||||
- 咨询响应里的 `rectification.vedastro_gateway` 状态如实;
|
||||
- 生时校正面的 VedAstro 证据字段改动前后逐项相同;
|
||||
- 新增测试:咨询路径不调用 snapshot runner 子进程(mock 断言);负缓存同日命中;跨日失效。
|
||||
|
||||
### T2 补分段计时
|
||||
- `[agent-observability]`(`frontend/src/lib/agent-observability.ts`、`stream-agent-response.ts`、普通对话 route)新增字段:
|
||||
- 分类:`classification.durationMs`(已有的话,确认它进了 usage);
|
||||
- 第 0 步、第 1 步各自的 `durationMs`、`reasoningTokens`、`outputTokens`、`inputTokens`、`cachedInputTokens`(取供应商返回的 usage;拿不到的写 null,不估算);
|
||||
- 工具调用:各领域的 `durationMs`(已有的话保持不变);
|
||||
- `answer.reasoning_ms`:第 1 步开始到第一个正文字符的时间。
|
||||
- 同样的数字写进 `/admin/usage` 记录的 metadata(**不动表结构**,只用已有的 JSON 字段;若没有可用的 JSON 字段,写进进度记录,留给另单,本单不加迁移)。
|
||||
- `/admin/usage` 页面能看到这些数字最好;需要改 UI 时只加一列或一个展开区,并同步 `frontend/DESIGN.md`。
|
||||
- **验收**:
|
||||
- 新增单元测试:给定一组模拟的步骤结果,日志 / usage metadata 的字段齐全,并且不含正文;
|
||||
- 进度记录写明产品在哪里看、每个字段的含义(一张表)。
|
||||
|
||||
### T3 记录
|
||||
- `docs/BUG_HISTORY.md`:T1、T2 各一条(T1 关联 BUG-727、BUG-301;T2 关联 10-04 审计)。
|
||||
- `CHANGELOG.md`;`docs/tasks/PROGRESS-consult-latency-quickwins-20261005.md`(T0 结果或环境缺口、T1 前后耗时表、T2 字段表);`docs/tasks/README.md` 改为「已实现待验收」。
|
||||
|
||||
## 让步顺序
|
||||
|
||||
T2 → T1 → T0 → T3。T2 风险最低且是后续两单的前置;T1 若发现生时校正与咨询共用路径、难以隔离,先交 T2,T1 写清阻塞点。
|
||||
|
||||
## 开工前置命令
|
||||
|
||||
```bash
|
||||
cd /workspace/Jyotisha && git status -sb | head -1
|
||||
git fetch origin --prune
|
||||
git worktree add -b codex/consult-latency-quickwins-20261005 .worktrees/consult-latency-quickwins-20261005 origin/staging
|
||||
df -h /
|
||||
grep -oE "BUG-1[0-9]{3}" docs/BUG_HISTORY.md | sort -u | tail -1
|
||||
python3 scripts/pre_work_check.py --remote-timeout 8 --command-timeout 45
|
||||
```
|
||||
|
||||
外部引擎改动需先读 `docs/research/pre_work_error_ledger.md`(AGENTS §9),并检索 `docs/BUG_HISTORY.md` 里的 VedAstro / BUG-301 / BUG-727 记录。
|
||||
|
||||
## 验收口径
|
||||
|
||||
- Python:快速门 + **全量 `pytest tests` 与基线对比** + 英文对照 + 隐私测试;v5 逐项相同。
|
||||
- 前端:`tsc` 0 错;lint 0 error;`npm test` 失败名单与开工基线逐条相同。
|
||||
- 不 push,由 Claude 验收后推 staging;部署后由产品在 `/admin/usage` 看一轮真实分段。
|
||||
|
||||
## BUG 编号起点
|
||||
|
||||
BUG-1231(10-05 实测最大号 BUG-1230;开工时再核对)。
|
||||
@@ -0,0 +1,167 @@
|
||||
# TASK · 「纳迪秒级校准」可证伪检验(研究单,2026-10-05)
|
||||
|
||||
## 基线
|
||||
|
||||
- `origin/staging` @ `853772bc`(写作时 head;开工时以最新 `origin/staging` 为准)。
|
||||
- 分支 `codex/rectification-nadi-seconds-research-20261005`,工作树 `.worktrees/rectification-nadi-seconds-research-20261005`。
|
||||
- **离线研究,不改生产代码**:不动 `scripts/research/sealed_holdout_rerun.py::PRODUCTION_FILES` 里的冻结文件,不动 `scripts/active_rectification_event_engine.py`、`scripts/dasha_calculator_enhanced.py`、`scripts/divisional_charts_extended.py`、任何常数,也不动 `frontend/`。研究代码只放在 `scripts/research/` 和 `tests/`,引擎函数只能 import,不能改。
|
||||
- 数据:`references/real_case_calibration/minute_rectification_holdout_v5.json`(77 例 Rodden AA 公开名人,964 件事;BUG-1090)。数据集声明的口径是 `ayanamsa = raman`、`node_mode = mean`,本单默认沿用;换口径只在 N4 里做。
|
||||
|
||||
## 先读
|
||||
|
||||
- `docs/research/rectification_scoring_research_2026_09_29.md`:打分层三条 no_benefit,42 个特征里 36–39 个是噪声。
|
||||
- `docs/research/rectification_varga_resolution_2026_09_30.md`:盘型口径;±10 六题后 D9 / D10 头段 = 真值 88% / 86%。
|
||||
- `docs/research/holdout_v5_build_2026_09_29.md`:v5 基线;六题后头名 0.64 / 0.49 / 0.26,真值在区间内 76/77、76/77、75/77。
|
||||
- `docs/research/rectification_minute_resolution_closure_2026_09_14.md` §1–§2
|
||||
|
||||
## 事故实证
|
||||
|
||||
### 起因
|
||||
|
||||
竞品 2026-10 宣传「纳迪辅助校准,符合条件时精度最高可达秒级」,验证方式是**问前事、具体到天**。产品问:我们为什么做不到。
|
||||
|
||||
Claude 2026-10-05 的判断是:秒级的盘我们能算,做不到的是**验证**。但这个判断有一个没测过的缺口,所以写本单把它补上。
|
||||
|
||||
### 物理量(Claude 用 swisseph 实算;样本为上海、1990-06-15,Lahiri)
|
||||
|
||||
| 量 | 数值 | 含义 |
|
||||
| --- | --- | --- |
|
||||
| 上升点移动速度 | 0.21–0.37°/分钟 | 这个纬度和日期,每 4 秒约走 1′ |
|
||||
| D150 一段持续多久 | 32–57 秒 | 纳迪段本身就是「不到一分钟」的量级 |
|
||||
| D60 一段持续多久 | 81–143 秒 | |
|
||||
| 出生时间差 1 秒,Vimshottari 时间轴平移 | 0.025 天(太阳大运)到 0.084 天(金星大运) | 想把一件事对准到天,出生时间就要准到约 12–40 秒 |
|
||||
| 岁差 Lahiri 与 KP 相差 | 0.097°(5.8′) | ≈ 上升点 27 秒 |
|
||||
| 出生地东西方向差 10 公里(北纬 31°) | — | ≈ 恒星时 25 秒 |
|
||||
|
||||
### 本仓现状
|
||||
|
||||
1. **主链只用到第 3 层小运**:`scripts/active_rectification_event_engine.py::_active_vimshottari` 只返回 MD / AD / PD 三层主星,`_score_event` 也只对这三层计分。第 4 层 Sookshma、第 5 层 Prana 的算法在 `scripts/dasha_calculator_enhanced.py::calculate_five_level_dasha` 里已经有,但**从来没有进过评价集**。
|
||||
2. **D150 只有等分实现**:`scripts/divisional_charts_extended.py` 中的 `calc_custom_varga(degree, 150)` 只是把每宫等分成 150 段。古典纳迪段(Chandra Kala Nadi 体系)按动 / 固 / 变宫区分顺排还是逆排,而且每段都有名称和描述文本。这两样本仓都没有。
|
||||
3. **v5 的日精度事件**:一共 244 件。43/77 例有 ≥3 件,19/77 例有 ≥5 件,4/77 例一件也没有(年精度 577 件,月精度 143 件)。
|
||||
4. **v5 的「真值出生时间」大多是取整过的**:77 例里有 **52 例的分钟数是 5 的整数倍**(:00 有 14 例,:30 有 10 例)。随机分布下只该有约 20%(约 15 例)。也就是说,**标准答案本身多数只精确到 5 分钟左右,秒级没有可对照的真值**。分钟数不是 5 的倍数的只有 25 例。
|
||||
|
||||
## 根因(为什么至今不能对外说秒级)
|
||||
|
||||
1. **没有检验过**:Sookshma / Prana 小运和 D150 这两层,是「秒级」说法唯一可能的来源,但从来没在已知出生时间的人身上测过。
|
||||
2. **「问前事对上了」这种验证分辨不出真假**:小运分 5 层,每层 9 颗主星,再乘上十几张分盘,几乎任何一秒都能找到一条解释过去某天的路径。用事件定出时间,再用同一批事件证明这个时间,是循环论证。必须有安慰剂对照和留出预测。
|
||||
3. **输入本身的误差已经比秒大**:岁差流派、出生地坐标、「出生时刻」的定义、出生证明取整,每一项都在几十秒到几分钟之间。
|
||||
|
||||
## 决策记录(产品 2026-10-05)
|
||||
|
||||
- **批准本研究单**:对竞品式的「纳迪 / 小运对日子 → 秒级」做可证伪检验。**只做研究,不做实现**。只有通过本单的「过门标准」,才另立实现单。
|
||||
- **本单不算重开 BUG-1091**:BUG-1091(打分层,closed_by_design)关的是「给已有 42 个特征重新调权重」。本单测的是**从来没进过评价集的新层**(Sookshma / Prana 小运、D150),目的是证伪,不是调参。执行方**不得**借本单去调已有特征的权重,也不得改 `DOMAIN_CONFIG` 的宫位映射。
|
||||
- **结果出来之前,产品对外不说「秒级」**。如果本单不过门,产品要的是一份对外口径草稿(见 N6),而不是功能。
|
||||
- 纳迪段的**原文描述**(Chandra Kala Nadi 各段的命运文字):仓库里没有合法来源。本单**不转录、不爬取、不让模型凭记忆生成**这类文本。按描述文字比对经历这一路记为 `blocked`,D150 只做结构层检验。
|
||||
|
||||
## 硬红线
|
||||
|
||||
1. **规则先登记再跑**:N1–N3 用到的「事件被解释」规则族、阈值和随机种子,必须先写进 `docs/research/nadi_seconds_preregistration_2026_10_05.json` 并单独 commit,然后才能第一次在 v5 上跑。PROGRESS 里写明这个 commit 的 SHA。看过结果后再改的规则,只能放进「事后」列,不能用来判过门。
|
||||
2. **真值不可见**:排序器与拟合器不得读取 `true_minute`,也不得读取出生资料里的 `time` 字段作为输入。只有评测函数可以读。新增测试要断言这一点,沿用 `truth_hidden_from_ranker` 的检查方式。
|
||||
3. **必须有安慰剂对照**:每个「对上了」的指标,都要同时报告用安慰剂日期跑出的同一指标,置换检验以「整例」为单位抽样。只报真实日期、不报安慰剂的数字,一律不算数。
|
||||
4. **不得写「秒级准确率」**:所有准确率都以「与记录时间相差 ≤1 分钟 / ≤2 分钟」为口径。取整组(52 例)和非取整组(25 例)分开列,不得合并后只报有利的一组。
|
||||
5. 生产代码零改动;`PYTHONHASHSEED=0`,所有随机数带固定种子;所有 JSON 两次复跑逐字节一致。
|
||||
6. 快速门结果与开工基线逐条一致;隐私守卫全绿;只用 v5 已有的公开名人数据,不新增人物,不访问 astro.com。
|
||||
7. 负结果完整写出。任何一格不过门,都把数字写进 PROGRESS,不得通过调阈值凑出通过。
|
||||
|
||||
## 任务分解
|
||||
|
||||
### N0 · 研究底座与真值审计
|
||||
|
||||
- 新建 `scripts/research/nadi_seconds_lib.py`:
|
||||
- 对任意候选时刻,返回 v5 每件事件当天的**五层** Vimshottari 主星(调用 `calculate_five_level_dasha` 或同一条主链的递归切分)。
|
||||
- 返回 D150 段号,两种口径:等分 `calc_custom_varga`,以及古典纳迪段排序(动宫顺排、固宫逆排、变宫从中段起排)。古典排序的出处写在代码注释里;出处不确定的写 `variant_unverified`,不得冒充定论。
|
||||
- 网格:±10 分钟窗口按 5 秒一步(241 个候选),另在记录时间 ±2 分钟内按 1 秒一步。
|
||||
- **对账**:前三层主星必须与 `_active_vimshottari` 逐例、逐事件 0 差,对账结果写进 JSON。
|
||||
- **真值审计表**:77 例的分钟数分布、取整组与非取整组名单(只列 case_id)、每例日精度事件数。
|
||||
- 验收:`tests/test_nadi_seconds_research.py` 覆盖以下几点:
|
||||
- 前三层与主链对账 0 差;
|
||||
- 五层边界首尾相接;
|
||||
- D150 段号在段边界两侧正确翻转;
|
||||
- 跨午夜正确;
|
||||
- 不读 `true_minute`;
|
||||
- 两次复跑逐字节一致。
|
||||
|
||||
### N1 · 竞品式拟合率与安慰剂(核心)
|
||||
|
||||
- **规则族**:在预登记里固定,至少包括以下两族:
|
||||
- (a) 事件当天,第 k 层小运主星 ∈ 该领域目标宫主(`DOMAIN_CONFIG` + `_house_lords`,只 import,不改),k 分别取 4 和 5;
|
||||
- (b) 第 1–5 层里有 ≥m 层命中。
|
||||
- **对每例、每个候选秒**:计算这一秒能「解释」多少件日精度事件。
|
||||
- **报三组数字**:
|
||||
- 真值分钟内各秒的拟合率;
|
||||
- 窗口内随机秒的拟合率;
|
||||
- **安慰剂日期**(每件事的日期按固定种子平移 ±30–180 天;另做一组把事件在案例之间互换)下的拟合率。
|
||||
- 过门:真值秒的拟合率高于安慰剂,整例置换检验 p < 0.05。样本只用 ≥3 件日精度事件的 43 例。
|
||||
- 验收:表格写进研究文档。另外报一个关键数:「窗口内能解释全部日精度事件的秒占多大比例」。这个比例接近 100%,就说明「问前事对上了」分辨不出真假。
|
||||
|
||||
### N2 · 留出预测(竞品验证方式的诚实版)
|
||||
|
||||
- 用 ≥4 件日精度事件的案例做留一件:用其余事件拟合出最佳秒(并列的全部保留),再看被留出的那件事在这些秒上是否被解释。
|
||||
- 对照两组:同窗口内随机秒;被留出事件换成安慰剂日期。
|
||||
- 过门:留出事件的解释率高于随机秒,整例 bootstrap 95% 置信区间不含 0。
|
||||
|
||||
### N3 · 能不能找回记录时间
|
||||
|
||||
- **N3a 单独排序**:只按纳迪层拟合排序,看头名与记录时间相差 ≤1 分钟 / ≤2 分钟的比例。对照均匀随机(±10 窗口下 ≤1 分钟约 3/21)和引擎先验头名(v5 ±10 为 0.18)。
|
||||
- **N3b 线上六题后交付区间里再细分**(这是产品真正关心的问题):沿用六题回放(`scripts/research/futile_collect_stop_replay.py` 的口径),在线上交付区间内用纳迪层排序,看头名 ≤1 分钟的命中率能否往上提。0.64 是 v5 文档里「头名」口径的数,不一定等于「≤1 分钟」口径;**先在 ≤1 分钟口径下复现线上基线,再做比较**。
|
||||
- 过门(两条都要满足):
|
||||
- N3b 头名 ≤1 分钟命中的提升,整例 bootstrap 95% 置信区间不含 0;
|
||||
- 真值仍在区间内的比例不低于 76/77。
|
||||
- 取整组和非取整组分开列;±30 / ±60 的数字只报告,不参与判定。
|
||||
|
||||
### N4 · 输入噪声地板(不论 N1–N3 结果如何都要做)
|
||||
|
||||
- 在**记录时间**上,统计每件日精度事件当天的第 4 / 第 5 层主星,以及本命 D150 段号,在下列扰动下有多少比例发生变化:
|
||||
- 岁差 Raman ↔ Lahiri ↔ KP ↔ True Chitra;
|
||||
- 出生时间 ±15 秒、±30 秒、±60 秒;
|
||||
- 出生地坐标东西方向 ±10 公里。
|
||||
- 交点 mean ↔ true 只影响罗睺 / 计都的位置,不影响 Vimshottari,单列说明即可。
|
||||
- 判定(只决定对外口径,不决定是否过门):只换一个岁差流派,第 5 层主星或 D150 段号就有 >20% 的事件 / 例子跟着变,结论就是「秒级结果跨软件不可复现」。这种情况下,即使 N1–N3 全部通过,对外文案也不得出现「秒级」。
|
||||
|
||||
### N5 · D150 结构层(低优先)
|
||||
|
||||
- 不使用文本,只测结构:本命 D150 段主星是否落在事件领域目标宫主里,以及 D150 上升星座的宫主星在事件当天的小运里是否激活。规则先登记,方法同 N1(要有安慰剂)。
|
||||
- 按描述文字比对经历这一路写 `blocked`,原因写「无合法文本来源」。
|
||||
|
||||
### N6 · 结论、对外口径与记录
|
||||
|
||||
- `docs/research/rectification_nadi_seconds_2026_10_05.md`:
|
||||
- 一句话结论表:N1–N5 各一行,写明是否过门、关键数字、安慰剂对照;
|
||||
- N4 噪声地板表;
|
||||
- 结论:通过的话,写实现单要点(改哪些模块、不改哪些模块);不通过,就 `closed_by_design`。
|
||||
- **对外口径草稿**(不论结论如何都要写,对照 `frontend/docs/VOICE.md`):三到五句,向用户说明我们的校正能做到什么精度、靠什么数据,以及为什么不说「秒级」。**不得点名竞品。**
|
||||
- 同步更新:
|
||||
- `docs/research/ACTIVE_FRONTS.md` 索引;
|
||||
- `docs/tasks/PROGRESS-rectification-nadi-seconds-research-20261005.md`;
|
||||
- `docs/BUG_HISTORY.md` 对应编号的状态;
|
||||
- `docs/tasks/README.md` 状态板这一行。
|
||||
|
||||
## 让步顺序
|
||||
|
||||
N0 > N1 > N4 > N2 > N3 > N5 > N6 里的图表。
|
||||
|
||||
- N0、N1、N4 缺一项都不能合入。
|
||||
- N2 / N3 / N5 没做的,写 `not_started`,不得写成结论。
|
||||
- 时间不够时,先砍 N5,再砍 N3 的 ±30 / ±60 列。
|
||||
|
||||
## 开工前置命令
|
||||
|
||||
```bash
|
||||
git fetch origin --prune
|
||||
git worktree add -b codex/rectification-nadi-seconds-research-20261005 .worktrees/rectification-nadi-seconds-research-20261005 origin/staging
|
||||
cd .worktrees/rectification-nadi-seconds-research-20261005
|
||||
export PYTHONHASHSEED=0
|
||||
python3 -m pytest -q tests/test_scoring_research.py tests/test_holdout_v5_schema.py tests/test_varga_resolution_research.py tests/test_rectification_validation_integrity_gate.py tests/test_repo_privacy_markers.py # 基线
|
||||
python3 scripts/research/futile_collect_stop_replay.py --help
|
||||
python3 -c "import swisseph; print(swisseph.version)"
|
||||
```
|
||||
|
||||
长任务每完成一个 N 就 commit 一次检查点,因为 09-29 有子代理被限额打断后成果没落盘的教训。研究分支只 commit,不推 staging;推送由验收方完成。
|
||||
|
||||
## BUG 编号
|
||||
|
||||
开工时核对 `docs/BUG_HISTORY.md` 当前最大号(写作时是 `BUG-1230`)。同日 `TASK-consult-latency-quickwins-20261005` 已从 BUG-1231 起编号,为避免撞号,本单预留 **BUG-1240**:「秒级 / 纳迪校准从未经过检验:Sookshma / Prana 小运与 D150 不在评价集内,真值时间多为取整值」。如果开工时 1240 已被占用,顺延到下一个空号,并在 PROGRESS 里写明。
|
||||
|
||||
执行方以 `investigating` 登记。研究结束后:通过的改为 `resolved`(另立实现单);不通过的改为 `closed_by_design`,并附上对外口径。
|
||||
|
||||
关联:BUG-560、BUG-1090、BUG-1091、BUG-1105。
|
||||
@@ -10,14 +10,22 @@
|
||||
* The process exit code is the test runner's exit code (BUG-995).
|
||||
*/
|
||||
import { spawn } from "node:child_process";
|
||||
import { mkdirSync, readFileSync } from "node:fs";
|
||||
import { mkdirSync, readFileSync, readdirSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const frontendDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
||||
const repoRoot = path.resolve(frontendDir, "..");
|
||||
const tsxCli = path.join(frontendDir, "node_modules", "tsx", "dist", "cli.mjs");
|
||||
const testGlobs = ["tests/*.test.ts", "tests/*.test.tsx"];
|
||||
// Expanded here instead of handing `tests/*.test.ts` to `node --test`: Node 20
|
||||
// does not expand test globs ("Could not find tests/*.test.ts"), while the old
|
||||
// `tsx --test tests/*.test.ts tests/*.test.tsx` script relied on the shell. Same
|
||||
// order as the shell: every *.test.ts sorted, then every *.test.tsx sorted.
|
||||
function testFiles() {
|
||||
const names = readdirSync(path.join(frontendDir, "tests"));
|
||||
const pick = (suffix) => names.filter((name) => name.endsWith(suffix)).sort().map((name) => `tests/${name}`);
|
||||
return [...pick(".test.ts"), ...pick(".test.tsx")];
|
||||
}
|
||||
const failureBlockLimit = 60;
|
||||
|
||||
function envEnabled(name) {
|
||||
@@ -193,7 +201,7 @@ function invokedDirectly() {
|
||||
async function runTests() {
|
||||
const extra = process.argv.slice(2);
|
||||
if (!gateMode()) {
|
||||
const code = await runRunner(["--test", ...testGlobs, ...extra]);
|
||||
const code = await runRunner(["--test", ...testFiles(), ...extra]);
|
||||
process.exit(code);
|
||||
}
|
||||
|
||||
@@ -208,7 +216,7 @@ async function runTests() {
|
||||
"--test-reporter=tap",
|
||||
"--test-reporter-destination",
|
||||
tapPath,
|
||||
...testGlobs,
|
||||
...testFiles(),
|
||||
...extra,
|
||||
],
|
||||
{ suppressFailedTestsTrailer: true },
|
||||
|
||||
Reference in New Issue
Block a user