Files
Jyotisha/docs/tasks/PROGRESS-consult-upstream-functional-v2-20261002.md
T

17 KiB
Raw Blame History

PROGRESS · 上游功能吉凶 v2 收尾:生时校正算法身份、普通对话 golden、第四轮残留、第五轮回测(2026-10-02)

  • 执行方式:产品负责人要求子代理直接执行(Claude 子代理);无单独任务书,决策记录见下。只 commit、未 push。
  • 分支 / worktree:codex/consult-upstream-functional-v2-20261002 / .worktrees/consult-upstream-functional-v2-20261002
  • 基线:57782aea(Claude/PM 按产品授权移植上游功能吉凶 profile v2、Pancha 自合修正、瑜伽引擎读同一吉凶表;父提交 f8579466 = 事业单分支合入 origin/staging)
  • BUG 编号:开工核对 origin/staging 与各 worktree 最大号 BUG-1179;本单 BUG-1180~1182,更新 BUG-1158(→ resolved)、BUG-1165(复发指向 1182)、BUG-1176(第五轮)。
  • 上一单:docs/tasks/TASK-consult-career-yoga-functional-20261002.md / PROGRESS-consult-career-yoga-functional-20261002.md。

决策记录

  • D1 功能吉凶采用上游 profile v2(产品 2026-10-02 授权,PM 已在 57782aea 移植):bphs_ch34_general_with_sign_exceptions_v2。推翻上一单第二次决策「吉 / 凶 / 中性分组不变」与 T1 分支逐格对照表方案。v5 77 例评测(PM 实测,命令 python3 scripts/research/holdout_v5_baseline.py --dataset v5 --out-dir <dir>):先验头名 ±10/30/60 0.1818/0.0779/0.0649 → 0.1818/0.0909/0.0779;六题回放 0.6364/0.4935/0.2597 → 0.6364/0.4935/0.3117;线上区间回放 0.6753/0.4935/0.3247 → 0.6623/0.5584/0.4026;覆盖 0.987/0.987/0.974 → 0.987/0.987/0.987。产品接受(一格 −1.3 pp)。
  • D2 生时校正算法身份升到 scoring-10(本会话按先例决定,见 T1)。
  • D3 第四轮残留本轮修(产品批准):事业落宫不翻成幕后、父母反向安慰、逆行禁句、两处请求;只改单一定义处的规则文字,不对模型输出做正则后处理。

T1 生时校正打分合同(BUG-1181)

要不要升版本:要

  • 先例:TASK-rectification-engine-convergence-20260901 硬红线 3「打分语义变化必须 bump ALGORITHM_VERSION」;跨午夜修复按此 7 → 8 → 9(BUG-981~985,PROGRESS-rectification-cross-midnight-20260920.md)。BUG-621 的教训是「升版本后历史必须还能打开」,BUG-984 已把版本不一致的历史结果做成只读 + 「重新比较」。
  • 事实:功能吉凶分组经 active_rectification_event_engine.py 的 *_functional_benefic_auxiliary / *_functional_malefic_auxiliary 规则进入事件矩阵。同一输入(记忆化测试的公开虚构请求)候选 12:00 的分数 8.6274 → 8.4977;跨午夜虚构 golden 23:59 的分数 0.7893 → 0.9213。
  • 不升的后果:cachedEngineScoreIsReusable 按算法身份 + 证据指纹决定能否复用,证据未变的历史 Case 会把旧分组的分数当当前结果。
  • 结论:升到 rectification-v5-matrix-scoring-10;策略版本 rectification-candidate-policy-v3、输入合同 v5、Skill 版本都不变;历史结果不重标。

升版本时发现的第二个问题

前端五处、数据库一处用字面量 === "rectification-v5-matrix-scoring-9" 判断「这是带日期窗合同的结果」(engine-client.ts score / diagnostics 的 dated、tool-service.ts 候选行解析与 legacy 段选择、score-persist.ts 是否先补日期窗、rectification-candidate-result.ts、validate_dated_rectification_candidate)。直接升到 10 会让新结果按旧的同日结果解析(跨午夜候选丢日期),数据库守卫对 scoring-10 失效。处理:按代数判断(≥ 9)。

改动

位置 改动
scripts/rectification/scoring_service.py ALGORITHM_VERSION → rectification-v5-matrix-scoring-10(注释写明原因)
frontend/src/lib/rectification-agentic/core/candidate-window.ts 新增 FIRST_DATED_SCORING_GENERATION = 9、isDatedScoringAlgorithmVersion()
engine-client.ts / tool-service.ts / score-persist.ts / rectification-candidate-result.ts 五处字面量改用上面的函数;v9EngineVersion() 缺省串 → scoring-10
frontend/supabase/migrations/20261002010000_rectification_dated_algorithm_generation.sql 只 create or replace validate_dated_rectification_candidate,守卫改 `~ '^rectification-v5-matrix-scoring-(9
tests/golden/rectification_engine_memoization_v2.json 用测试文件自带的 write_golden 由真实引擎写出(scoring-10,source_commit = 57782aea);v1(scoring-8)原样保留并以 sha256 钉住
frontend/tests/fixtures/rectification-midnight-date-anchor.delivery.scoring-10.native.json python3 scripts/research/midnight_date_anchor_regression.py --baseline <本 worktree> --output <scratch> --golden --golden-path …:真实引擎,虚构资料;同机独立进程 A/B 3 例 × 7 字段逐位相等。scoring-9 的旧 golden 保留不动

校正研究记录重新冻结(ERR-110 / ERR-114)

只改 ALGORITHM_VERSION 一行就让 test_rectification_validation_integrity_gate.py 等 8 项失败:scoring_service.py 在冻结身份 PRODUCTION_FILES 里。反过来,57782aea 改的 functional_benefics.py 不在清单里,分数变了门禁却没红(记 ERR-114)。按 09-29 BUG-1088 先例(56b51e21)处理:

步骤 内容
清单 sealed_holdout_rerun.py PRODUCTION_FILES 补 scripts/functional_benefics.py;新增 test_functional_roles_are_part_of_the_production_identity(并进快速门 bridge)
新标签 两个脚本的 FREEZE / REPORT 指向 *_functional_v2_2026_10_02;IDENTITY_FORBIDDEN_PREFIXES 加两个新前缀
冻结后重放(PYTHONHASHSEED=0) sealed_holdout_rerun.py --freeze 后重放 20 例:与 09-29 逐条相同(top-1 0.45 / top-3 0.5 / MAE 6.45,影子 fact ranker 不读功能吉凶);reported_offset_sweep.py --freeze 后重放 900 例(6 分 12 秒):230 例变化,窗口内平均头名 ±15/30/60 不变(0.0636 / 0.06 / 0.05),交付覆盖 0.9864 / 0.99 / 1.0 → 0.9955 / 0.9967 / 1.0,平均分钟误差 10.02 / 16.88 / 26.96 → 10.31 / 16.72 / 25.71
合同 references/rectification_sealed_holdout.v1.json:current_tree_scorer 的 extended_identity / source_report / metrics、current_tree_fixed_protocol_rerun、current_tree_reported_offset_replay 换成新记录;09-29 记录挪到 previous(superseded_reason 写明);status: not_ready、六个发布键不变;旧报告与冻结文件逐字节保留

这些记录是「已曝光、不可用于调参」的敏感性研究,不是发布指标,确认门照旧关闭。

改动的既有断言(原值 / 新值 / 原因)

文件 · 测试 原值 新值 原因
tests/test_sealed_holdout_contract_freshness.py IDENTITY_FORBIDDEN_PREFIXES 到 quality_wording_2026_09_29 加 functional_v2_2026_10_02 两个前缀 新冻结标签(与 09-29 同法)
frontend/tests/rectification-confirmation-gate.test.ts 当前重跑报告路径(两处) …sealed_holdout_rerun_quality_wording_2026_09_29.json …sealed_holdout_rerun_functional_v2_2026_10_02.json 同上;第一次快速门里 npm 多出这 1 项失败才发现(406d81b8 先例),改后 npm 全量与基线同名
tests/test_rectification_engine_memoization.py 对比目标 v1 golden(scoring-8)+ 投影 scoring-9 新增字段 v2 golden(scoring-10)直接比;新增「v1 冻结且已不是当前」测试 分数变了,v1 不能再当当前;按「历史 golden 不改写、新增版本文件」处理
tests/test_dasha_transition_proximity_cross_midnight.py == "…scoring-9" == "…scoring-10" BUG-1181
tests/test_rectification_relative_support.py "…scoring-9" "…scoring-10" BUG-1181
frontend/tests/rectification-engine-version-cross-midnight.test.ts LIVE_CURRENT = scoring-9,scoring-9 dated golden 兼作「当前」 LIVE_CURRENT = scoring-10;scoring-9 golden 记为 DATED_HISTORICAL;新增「scoring-9 缓存在 scoring-10 下不可复用」 BUG-1181
frontend/tests/rectification-midnight-date-anchor.test.ts 跨午夜贯穿 只跑 scoring-9 golden scoring-9 与 scoring-10 两份都跑 证明新代仍按日期窗解析
frontend/tests/database-adopted-birth-date.test.ts 只验 scoring-9 去掉日期合同被拒 另验 scoring-10 / 11 被拒、scoring-8 仍按旧同日结果返回空 迁移守卫

验证

  • 记忆化文件 22 项全过;write_golden 再写一次,candidate_scores / decision_receipt 相同,只有未参与比较的特征哈希不同(BUG-733 / 985 的已知跨进程浮点差,测试本就不比)。
  • 红绿:把 isDatedScoringAlgorithmVersion 临时改回字面量 scoring-9,scoring-10 跨午夜贯穿测试即红;去掉迁移文件,database-adopted-birth-date 2 项即红;57782aea^ 的旧代码跑同一记忆化请求得 8.6274,新代码 8.4977。
  • 数据库(本机 PostgreSQL 17 + docker 替身,方法见记忆「local-postgres-without-docker」):npm run test:db 全量 80 项,基线 57782aea 一次性 worktree 与本分支都是 74 过 / 6 败,失败名单逐条相同(env validator、个人报告 RLS、会话标题 updated_at、admin 身份、staging 备份、stdin 大 SQL——替身不支持 pg_dump / 部署脚本等)。
  • 历史打开(BUG-621 教训):rectification-*.test.ts + skill-registry*.test.ts 1,872 项 0 失败(含 BUG-621 按会话用绑定 Skill 打开、BUG-984 版本不一致只读 + 「重新比较」、历史回执原样读取);新增用例:真实 scoring-9 结果在 scoring-10 下 read_only = true、can_recompare = true、候选仍带日期,在 scoring-9 下不只读。
  • 部署侧待办(不在本会话):核实 staging / 生产没有设置 RECTIFICATION_ENGINE_VERSION / RECTIFICATION_ALGORITHM_VERSION(deploy/、.gitea/ 里没有);迁移随部署自动应用;真机走一遍「打开一条旧校正 → 只读 → 重新比较」。

T2 普通对话 golden 与功能吉凶断言(BUG-1158)

  • PYTHONHASHSEED=0 JYOTISH_API_CHART_CACHE_TTL_SECONDS=0 跑 capture_consult_evidence_card_golden.py、capture_consult_biography_backtest_golden.py,各两次逐字节相同;diff 只在功能吉凶字段(分组、profile、role_basis、lagna_lord 等新字段、Technique Audit 的 key_functional_*)。瑜伽字段无变化。
  • 九位名人分组变化:乔布斯(处女)木星中→凶、太阳凶→中;奥巴马(摩羯)月亮中→凶;泰勒、琵雅芙(天蝎)太阳中→吉、火星吉→中、金星凶→中;嘉兰(双子)木星中→凶;卡罗(狮子)月亮凶→中;齐达内(金牛)太阳中→吉、火星凶→中、金星吉→凶;梦露、布什(巨蟹)不变。
  • Python:全量跑过,功能吉凶相关测试(mcp strict 系列、consumer context、report parity、active rectification 等)没有新失败(见门禁)。pyjhora / oracle 测试的失败都在基线名单里。
  • 前端改动的断言:consult-card-affliction-data-20261001.test.ts 乔布斯父亲代表星太阳 原值 malefic / 新值 neutral / 原因:v2 只管 12 宫的星不自动判凶(三栏写在测试注释)。
  • 新增 frontend/tests/consult-upstream-functional-v2-20261002.test.ts:12 份 golden 的 profile、泰勒(天蝎)与乔布斯(处女)卡上分组。

T3 第四轮残留

项 查到的原因 改动
a 事业 9/18「不是站台式 / 往深处做」(BUG-1176) 规则说了「不断定公众 / 幕后」,但没点名 A10 / AL / 太阳 / 10 宫主落 4、6、8、12 宫这类读法本身就是在下类型结论 CAREER_FIELD_ASK_RULE 加一句:这些落宫只说阻力或代价(要经手、要绕路、来得晚),不翻成「不在台前」「不在台面上」「不靠曝光」「幕后」「不是站台式」「往深处做」,也不把落宫翻成行业
b 梦露 ×2 / 琵雅芙 ×1 母亲「在管、在安排、近」(BUG-1182) 卡上没有解读性文字;系统提示三处示例把「4 宫主落 10 宫」配成「母亲的注意力在你的前途上 / 离你近、上心」,梦露盘 4 宫主正落 10 宫;AFFLICTION_RANGE_RULE 只禁安慰词,不禁拿宫主落宫 / 宫内吉星描写人物行为,也不管行动建议 AFFLICTION_RANGE_RULE 加「不拿宫主落哪一宫、宫里有吉星去描写这个人对你做什么……行动建议也不写给他打电话、去问他」;三处示例括号写明「母亲这条线没有受冲」
c 禁句 1(琵雅芙健康「逆行 → 拖出来」) 通用读法只写「逆行不等于反复、打回来」 改为「也不等于拖得久、拖出来,推论里不拿逆行当理由(依据里可以列)」
c 三份两处请求 AFFLICTION_RANGE_RULE 要「这一段末尾」问,和事业段末那一问叠加 加「问过之后别的段落不再另问」

改动的既有断言:consult-no-presupposition-20261001.test.ts AFFLICTION_RANGE_TEXT(原值:止于「全篇这类请求最多一处。」/ 新值:加上面两句 / 原因:BUG-1182)与是非题例正则(原值 /不是。(4 宫主落 10 宫)…/ / 新值 /不是。(母亲这条线没有受冲;4 宫主落 10 宫)…/);consultation-voice-contract.test.ts 父母例与是非题例两处(同上,三栏在注释)。frontend/docs/VOICE.md 同步(不揣测、§7 ③、§8、示例一节、对照表两行)。

回测脚本 consult-biography-backtest.mts:--correction-domain 支持逗号分隔多个领域,--correction / --correction-texts 支持 领域:名人 写法,一次跑完父母纠正与事业追问。

T4 第五轮回测

详表见 docs/testing/consult-affliction-backtest-20261001.md「改动后(第五轮)」。key 只从环境变量读,没有写入文件、日志或提交;模型输出在 scratch/consult-biography-backtest/round5-20261002/(gitignore)。

通过线 第四轮 第五轮 达到
事业行业 / 类型与生平冲突 ≤ 1 / 18 9 / 18 5 / 18 否
事业段末问一句 ≥ 16 / 18 18 / 18 17 / 18 是
严重冲突 ≤ 5 / 72 12 / 72 5 / 72(全在事业;父母 3 → 0) 是(压线)
对照组严重误报 0 0 0 是
对照组轻度误报 ≤ 2 3 4 否
禁句 0 1 0 是
每份只问一次 3 份两处 72 / 72 一处 是

追问:父母纠正 8 / 8、事业追问 6 / 6。未达的两项见测试文档「读出来的东西(第五轮)」:事业剩下的是同义词逃逸(「不靠场面」「不是一阵热闹」),对照组轻度误报是把「迹象」写成一句现实结论,交产品决定下一步(建议方向写在测试文档)。

门禁

项 基线(57782aea 一次性 worktree) 本分支
tsc --noEmit — 0 错
npm run lint — 0 error / 126 warning
npm test(Node 22) 4,911 项:pass 4,846 / fail 24 / cancelled 0 / skip 41 4,921 项:pass 4,856 / fail 24 / cancelled 0 / skip 41;失败名单逐条同名(都是需要 Docker / PostgreSQL / 部署环境的套件)
npm run test:db(本机 PG17 替身) 80:74 过 / 6 败 80:74 过 / 6 败,名单相同
next build / ○ Static / ○ Static
首屏 gzip(预渲染 index.html 引用的 32 个 /_next/ 资源 gzip-9 求和,同法实测) 635,351 B 635,380 B(+0.005%)
Python 全量(pytest tests -n 6) 67 项失败(f8579466 基线名单;57782aea 只多出 8 项记忆化失败) 62 项失败,全部在基线名单内、新增 0;记忆化 8 项转绿;另有 5 项 prashna 研究测试转绿,与本单无关(工作树里 4 个 references/oracle/prashna_* 文件开工前已被改写,见下)
快速门 run_quality_gate.py --profile quick(系统 python3 + Node 22) — pytest 1,043 passed / 1 skipped;门内 npm test 4,921 项 fail 24,名单与基线同名;门禁总状态因这 24 项环境失败为 failed(与上一单相同)

环境:frontend/node_modules 用硬链接拷贝(cp -al),未提交。工作树里 references/oracle/prashna_*_2026_07_20.json 四个文件开工前就是已修改状态(来源不明,疑为别的测试运行改写),本单未提交。一次性基线 worktree .worktrees/tmp-base-57782aea-20261002 用完删除。

提交

codex/consult-upstream-functional-v2-20261002(未 push):3733b978(BUG-1181 算法身份、日期窗代数判断、迁移、记忆化 golden v2、研究记录重新冻结)、3a40d422(BUG-1180 回归测试)、7806c72f(普通对话 golden、第四轮残留规则、回测脚本)、dae2b99f(确认门测试读新冻结报告)及本文档提交。