Files
Jyotisha/docs/tasks/TASK-upstream-sync-20260903.md
T

298 lines
42 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 任务书 · 上游研究仓同步与三项新能力接入(2026-09-03)
基线:`origin/staging` @ `591ffd21`。上游研究仓 `732642856/yinduzhanxing` 目标提交 `a6f47abd2c9b7c6baa911ea00c971e1ec902380c`2026-09-03`main`)。本地干净检出在 `/workspace/yinduzhanxing`origin 与策略文件一致,`git status` 干净)。
## 现状实证
1. **快照落后 20 天、629 个提交。** `references/upstream/yinduzhanxing/source-manifest.json` 锁在 `5db72537`2026-08-14)。上游到 `a6f47abd` 之间:references 1040 文件、docs 539、scripts 707(约 640 个是新研究脚本)、tests 750。上游自己的 9 月总结(`docs/research/september_2026_execution_log.md`)写明"本地代码工作已关闭,剩余全部是外部证据准入阻塞,不允许任何真相/运行时/发布/预测层升级"。**这批不是能力大升级,是研究台账为主。**
2. **导入器只覆盖 SKILL.md。** `references/cross_project_contract/sync_policy.v2.json`:唯一字节镜像是上游 `SKILL.md``references/upstream/yinduzhanxing/SKILL.md`;六个"语义合并"文件(`SKILL.md``AGENTS.md``references/strict-workflow-router.md``scripts/unified_consultation_orchestrator.py``scripts/report_orchestrator.py``scripts/jyotish_api_server.py`)导入器只列不写;其余引擎代码不在策略范围内。
3. **引擎是分叉,不是镜像。** 本仓 `scripts/` + `jyotish_vedic/` + `mcp_server.py` 共 389 个 Python 文件:242 个与快照 `5db72537` 逐字节一致,92 个有商业改动,55 个本仓独有。上游 HEAD 另有 736 个本仓没有的 Python 文件。因此引擎同步只能做**三方合并**(base = 上游 `5db72537`ours = 本仓,theirs = 上游 `a6f47abd`)。
4. **三方合并干跑结果**`git merge-file -p ours base theirs`,冲突块数):
| 文件 | ours 改动行 | theirs 改动行 | 冲突块 |
| --- | ---: | ---: | ---: |
| `scripts/jyotish_api_server.py` | 8283 | 3383 | 36 |
| `scripts/jyotish_engine.py` | 3649 | 10924 | 25 |
| `scripts/unified_consultation_orchestrator.py` | 553 | 753 | 18 |
| `mcp_server.py` | 655 | 625 | 11 |
| `scripts/active_rectification_questions.py` | 197 | 160 | 7 |
| `scripts/ashtottari_dasha.py` | 264 | 134 | 5 |
| `scripts/active_rectification_events.py` | 204 | 101 | 5 |
| `scripts/domain_calculation_service.py` | 410 | 20 | 5 |
| `references/technique_registry.json` | 3084(仅格式,内容与快照一致) | 966 | 5 |
| `scripts/narayana_dasha.py` | 486 | 269 | 4 |
| `scripts/run_quality_gate.py` | 132 | 54 | 4 |
| `scripts/kp_system.py` | 205 | 145 | 3 |
| `scripts/varga.py` / `tajika.py` / `report_orchestrator.py` | 35 / 324 / 108 | 43 / 88 / 28 | 各 1 |
| `scripts/jaimini.py` / `muhurta.py` / `western_timing_engine.py` / `solar_return.py` | 1 / 2 / 0 / 54 | 137 / 1618 / 230 / 84 | **0** |
`jyotish_engine.py` 的 25 处冲突集中在本仓商业改动过的同一批函数:`_build_ai_prompt_pack``compute_chart_data``cmd_chart``cmd_dasha``cmd_shadbala``cmd_tajika``_calc_actionable_context``_add_chart_args``_ayanamsa_display_name``main`
5. **上游真正涉及业务能力的变化**(按本仓产品是否用到排序):
- `references/strict-workflow-router.md`:新增 `health-timing-strict` 路由(D1/D6/D8/D30Narayana 交叉核对,输出必须分**压力窗 / 事件风险窗 / 恢复支持窗**三段,非医疗边界),`wealth-timing-strict` 改名 `finance-timing-strict` 并保留旧别名。上游编排器 `route_surface_contract` 已把 `wealth-timing-strict` 作为 `finance` 的别名。
- `references/technique_registry.json`:91 → 116 项。新增 25 项全是 `western_*``western_profection``covered`,其余 `guarded`)、`classical_*`(全 `guarded`)、`ziwei_*``comparison-only``covered`)。
- Ashtottari 解冻:`blocked_rule_source_conflict``selected_rule_family_parameter_sensitive`,可执行但未验证,只对规则族 `rahu_from_lagna_lord_kendra_trikona_plus_paksha_daynight` 适用;`scripts/ashtottari_dasha.py``SKILL.md` 同步改动。
- VedAstro:官方 MCP 端点 `tools/call` 持续返回 `Invalid or Outdated Call`,上游把默认外部对标通路切到 REST 桥 `scripts/vedastro_rest_bridge.py``https://api.vedastro.org/api/Calculate`horoscope / dasa 两个子命令实测 `Status: Pass`,免费层 5 次/分钟)。本仓 `scripts/vedastro_gateway.py``OFFICIAL_ENDPOINT` 本来就是 REST 根地址,但本仓 `scripts/vedastro_official_mcp_bridge.py` 仍被 `vedastro_parity_matrix.py` 使用。
- `scripts/jyotish_engine.py``pl9-export` 子命令(`build_pl9_style_export_packet(full_reading)` + `render_pl9_markdown`,格式 json / markdown / pdf / authority`--pack` 选包),术语规范改为 `professional_report_reference``docs/architecture/professional_report_reference_contract_v1.md`),markdown 导出带引擎边界声明(上游 `7a2793cb`)。与咨询链路直接相关的改动落在 `_build_ai_prompt_pack`7 块)、`cmd_full_reading`10 块)、`cmd_varga_full`4 块)、`cmd_dasha`4 块)、`_build_career/finance/relationship_narrative_payload`,以及新增的 `_build_pratyantar_timeline``_build_birth_time_sensitivity``_build_planetary_friendship_snapshot``_build_three_year_predictive_ephemeris_pack``_build_module_execution_audit`
- `scripts/muhurta.py` +1600 行择日能力(Panchaka、Tarabala/Chandrabala、Siddha Yoga、Durmuhurtha 窗口、择日盘 dosha 与取消权重);`jaimini.py``narayana_dasha.py``kp_system.py``western_timing_engine.py``tajika.py``solar_return.py``varga.py` 各有修改。
- `mcp_server.py` 新增 `get_pl9_expert_reader_report``get_pl9_full_report_authority``route_jyotish_question`;编排器新增专家判断影子层(`build_expert_judgment_shadow_input` 等)与 `route_surface_contract`
- 新增两个子 skill`skills/financial-astrology`(市场占星)、上游版 `skills/jyotish-birth-time-rectification`
6. **本仓相关现状**
- 咨询链路的 `health` 路由**已经存在**`scripts/unified_consultation_orchestrator.py` `_ROUTE_DEFINITIONS["health"]`D1/D6/D8/D30,输出段 `non_medical_pattern / pressure_factors / protective_factors / verification_questions`),前端 `frontend/src/lib/consultation-methodology.ts` 已把 `health` 映射到 `health-timing-strict`。差距在于:输出合同不是上游的三窗结构;`focus_techniques` 缺 Narayana / Transit / 功能吉凶;证据包无 health 专属必需段;**个人报告主题枚举没有 health**(`frontend/src/lib/personal-report-route-core.ts:37` 只有 career / marriage / wealth / timing / general);引擎没有 health 叙事种子生成器。
- 前端 `wealth` 主题硬编码 `wealth-timing-strict`,本仓编排器没有 finance 别名。
- 导入器 dry-run 在主检出直接被拒:`{"status": "rejected", "reason": "target_must_be_clean"}`(根目录有未跟踪的 TASK 文件)。必须在干净 worktree 里跑。
## 根因
上游是研究仓,日更数十个提交;本仓是分叉后带商业改动的产品仓,两者没有共同 git 历史。导入策略 v2 设计时只解决了"真相层"(SKILL.md)的镜像与审计,没有给引擎代码定同步办法,于是 20 天没有同步,再往后只会更难合。
## 决策记录(产品负责人 2026-09-03 授权)
- **(a)** 推进上游快照到 `a6f47abd`,按策略 v2 镜像 SKILL.md、语义合并六个文件、整体接收 116 项注册表并由商业覆盖层定状态。
- **(b)** 引擎代码做三方合并(基线 `5db72537`),商业改动优先,只取对产品路径有意义或纯新增的上游改动。
- **(c)** 三项新能力**全部要做**:health 路由对齐上游三窗合同并进入个人报告主题;VedAstro 外部对标切到 REST 桥;`pl9-export` 专业报告导出接进个人报告产品。
- **(d) 校正解冻(2026-09-03 用户决定)**:撤销"校正冻结新行为直到走查清零"对本任务书的限制,但只解冻到任务 7 列出的三项(自适应选题、岁差/交点模式按请求传递、不确定出生时间的报告敏感度节)。校正打分算法(V5 score service、POLICY v3、matrix-scoring-7)、采用/停止规则(BUG-463 / BUG-503 口径)、会话面交互本轮**仍不动**。解冻后欠着的浏览器走查(`docs/testing/`)必须在任务 7 合入后重新跑一遍。
- **授权不包括**:接收上游约 640 个研究脚本、150 万行证据台账、750 个研究测试、两份 PDF、`skills/financial-astrology`、上游版校正 skill;修改岁差默认值(保持 Raman,见 `TASK-repo-hygiene-20260903.md`);放松写作 agent 输入隔离;改数据库结构;改 `.gitea/workflows/**`
- **注册表新增 25 项的商业状态默认规则**:凡网页路径(`/api/consultation_workflow`)没有实际执行的,覆盖层一律 `research_only_blocked`;只有 `scripts/full_technique_invocation_matrix.py` 证明会执行的才可写 `partial``reference_only`。不得因上游写 `covered` 就进确定性结论。
## 三个产品面的覆盖对照
| 产品面 | 上游相关变化 | 本任务书落点 |
| --- | --- | --- |
| 普通聊天(`/api/consultation_workflow` → 折叠技法审计表) | finance 别名、health 三窗、Ashtottari 状态、`_build_technique_audit_table` / `_build_module_execution_audit`、叙事种子 `timing_narrative``planetary_friendship` 模块 | 任务 1(覆盖层与路由文档)、任务 2(引擎合并)、任务 3(health)、**任务 6(把新字段接到响应与前端)** |
| 生时校正(`/api/rectification/*``/api/active_rectification_events*`、前端 birth-time-journey | `3bb90620` 自适应选题器(含答案泄漏)、`dbb9804a` 亲属事件域 + 岁差/交点按请求传递、`d5b83c71` `compare_candidate_minutes` + 事件域注册表、`_build_birth_time_sensitivity` + 四个 `flexible_birth_time_*` 模块、便携版 skill v2.0.0 | **任务 7**(只取选题器、岁差/交点传递、报告敏感度节三项);其余不取,理由见硬红线 3 |
| 报告生成(个人报告管线、报告中心) | health 主题、`pl9-export`、解读模板注册表 +145 行、`timing_narrative` / `pratyantar_dasha_timeline` / `planetary_friendship` 可作解读性事实 | 任务 1(模板注册表)、任务 3(health 主题)、任务 5(专业导出)、任务 6(新字段进 bundle) |
## 硬红线
1. **方向单向。** 只从 `/workspace/yinduzhanxing` 读,不得向其写入、提交或推送;不得改 `sync_policy.v2.json` 的方向、受保护路径与最小保护集。
2. **受保护路径不接收上游内容**`skills/jyotish-birth-time-rectification/**``skills/jyotish-vedic-astrology/**`(只能新增版本目录,不能改既有版本)、根 `SKILL.md`(只允许语义合并本任务书列出的三段)、`frontend/**``deploy/**``.gitea/**``references/oracle/commercial_skill_truth_overlay.v1.json`(只允许按决策记录新增条目)。
3. **校正只按任务 7 的范围动。** 上游自快照以来对校正的改动共四个提交,逐个核过:
- `3bb90620`08-31)新增 `_known_case_regression_hint`:对 `1993-04-17` 出生时间读作者本人的已知案例标定文件,把 `14:49` 当回归目标并在分钟排名里 +5 分。**这就是已定性的答案泄漏,一行都不得进入本仓**;同一提交里按 `sensitivity_count` 排分钟的 `minute_rankings` 也不取(比本仓 V5 打分弱)。该提交里的 `active_rectification_selector.py``factual_reliability`、把 `scan_candidate_times` 挂进 `_candidate_scan` 是可取部分,见任务 7a。
- `dbb9804a`08-18)亲属事件域(parent / sibling / spouse_family)与分盘扩到 D3/D7/D12:本仓 `family` 域已含 D12/D7/D3,分盘列表 `[2,3,4,5,7,9,10,12,24,30]` 是超集,不取;该提交里 `ayanamsa` / `node_mode` 从请求读取的模式取,见任务 7b。
- `d5b83c71`08-27`compare_candidate_minutes` 固定分钟微比较:本仓 V5 score service、`minute_rectification_pairwise_v3.py``minute_candidate_discriminability.py``build_stability_diagnostics` 已覆盖且更强,不取。`references/rectification_evidence_contract_v1.json` 事件域注册表是治理数据,本仓 `rectification_technique_contract.py` 已是代码化合同且不含 D60/D40/D45,规则等价,不取,PROGRESS 记一句。
- `a9058663`08-31)便携版校正 skill v2.0.0:与本仓 v10.0.14 服务器权威 Case 模型不同源,受保护路径,不取。
- `_build_birth_time_sensitivity` + `flexible_birth_time_profile / report_support / full_report_projection / report_section`(四模块 761 行,测试 440 行,除被守护的 1993 分段表外无数据文件依赖):取,见任务 7c,但窗口来源必须改为本仓校正案例的可信区间,不用上游固定 ±1 分钟。
校正的打分算法、阈值、采用/停止规则、`frontend/src/lib/rectification-agentic/v9/**` 的会话状态机本轮不动;`minute_rectification_*` / `dynamic_rectification_*` 不合并上游(上游没有对应文件)。
4. **咨询响应契约不得变形。** `/api/consultation_workflow` 响应里前端已读取的键路径与类型(任务 0 的 golden 快照)改后必须逐一存在且类型一致;上游改动只允许**新增**键,不得改名、删键、改形状。`frontend/tests` 里的契约测试与 `tests/test_api_server_growth_contract.py` 等 Python 契约测试必须绿,不得改断言来迁就(除非断言锁的就是本轮要改的注册表计数或 README 徽章,改动处注明原值原因并在 PROGRESS 单列)。
5. **合并冲突的裁决规则**:商业侧函数体优先;上游改动仅在(i)纯新增函数/子命令且其 import 在本仓可解析,或(ii)修的是计算正确性且本仓同函数无商业改动时才取。任何 import 了本仓不存在模块的上游代码块一律不取,不得为了让它跑而顺手拖入研究脚本。每处冲突的取舍写进 PROGRESS 的冲突表。
6. **隐私与体积**:不得引入 `.pdf`、私有出生资料、PL9 参考报告原文、`review-only` 全量 payload`scripts/public_release_privacy_scan.py``scripts/commercial_privacy_artifact_scan.py` 必须过。fixture 一律用虚构 smoke 出生数据。
7. **不得新增模型调用。** 任务 5 的专业报告导出是确定性引擎产物,不经过写作 agent,不计费为报告生成。
8. 推 staging 前 `./node_modules/.bin/tsc --noEmit` 必须通过(不要用 `npx tsc`);`scripts/**``references/**` 都在 `deploy/gated-paths.txt` 内,每次推送都会跑完整门禁并部署 staging,推之前本地先跑 `run_quality_gate.py --profile quick`
9. 不得自行提升 `main`,不得改 workflow。
让步顺序:数据与隐私不泄漏 > 方向与受保护路径不越界 > 咨询契约与校正不回归 > 真相层同步完整 > 引擎代码合并覆盖面 > 三项新能力 > 代码整洁。
## 开工前置
```bash
git fetch origin --prune
git worktree add -b codex/upstream-sync-20260903 \
../.worktrees/upstream-sync-20260903 origin/staging
cd ../.worktrees/upstream-sync-20260903
.venv/bin/python scripts/pre_work_check.py --remote-timeout 8 --command-timeout 45
git -C /workspace/yinduzhanxing status --short --branch # 必须干净且在 a6f47abd
git -C /workspace/yinduzhanxing rev-parse HEAD
```
`docs/research/yinduzhanxing_one_way_import_2026_08_06.md``docs/research/pr0_upstream_governance_baseline_2026_08_14.md``docs/research/pre_work_error_ledger.md``frontend/AGENTS.md`;在 `docs/BUG_HISTORY.md` 检索 "上游 / import / merge / 契约 / varga 形状"。
**先读这几个文件再动手**
- `scripts/import_yinduzhanxing.py` —— git 模式要求、manifest 生成、`--test-run` 记录
- `references/cross_project_contract/sync_policy.v2.json``references/cross_project_contract/imports/commit-5db72537….json` —— 上次 manifest 的字段
- `scripts/unified_consultation_orchestrator.py` —— `_ROUTE_DEFINITIONS``_DOMAIN_PROFILE_SECTIONS`、health 路由
- `scripts/jyotish_api_server.py` `_compute_consultation_workflow`(约 4319 行起)、`_compute_full_reading_for_thematic``skip_full_reading_for_thematic`
- `scripts/jyotish_engine.py` `_build_ai_prompt_pack``cmd_full_reading``compute_chart_data``main`
- `frontend/src/lib/personal-report-generation.ts``report-theme-evidence-plan.ts``personal-report-route-core.ts``consultation-methodology.ts`
- 上游:`docs/architecture/professional_report_reference_contract_v1.md``docs/research/vedastro_rest_bridge_default_decision_2026_09_01.md``docs/research/ashtottari_primary_text_verification_2026_09_01.md``references/strict-workflow-router.md` §7
**与 `TASK-repo-hygiene-20260903.md` 的并行规则(2026-09-03 补)**:整备任务书正在另一执行方手上,两份任务书有共同文件——`scripts/jyotish_api_server.py`(整备改岁差字面量 `:2853` `:4017` `:7030` `:7086`;本任务书任务 2 对全文件三方合并)、`scripts/run_quality_gate.py`(整备任务 1 改发布门;本任务书任务 2 合并上游改动)、`references/technique_registry.json``tests/test_capability_evidence_pool.py`(整备任务 2 加 `experimental_variant` 白名单断言;本任务书任务 1 换成 116 项注册表,必须满足该断言)、根 `SKILL.md` / `pyproject.toml` / `README.md`(整备任务 3 改仓库地址;本任务书任务 1 加三段与徽章计数)、`frontend/src/lib/personal-report-generation.ts``birth-time-journey-*.ts`(整备 0.c 贯通岁差;本任务书任务 3 / 6 / 7 改同文件)。因此:
- **现在就可以并行开工的**:任务 0(导入器、golden、冲突表,只写 `references/cross_project_contract/imports/``references/upstream/``tests/golden/`、新测试文件)和任务 4(VedAstro,文件集与整备无交集)。两者在 `codex/upstream-sync-20260903` 上做,基线取当时的 `origin/staging`
- **必须等整备任务 0–3 合入 staging 后再开的**:任务 1、2,以及其后的 3 / 5 / 6 / 7。开工前 `git rebase origin/staging`,任务 2 的三方合并以 rebase 后的文件为 ours,不得在旧基线上合完再解冲突。任务 0 的 golden 只记键路径与类型,整备改的是岁差取值与标签,golden 不需要重采;但任务 2 完成后按任务 0 的要求重采一次。
- 整备任务书里"校正引擎按 Raman 校准的阈值与 golden 本轮不动"的约束继续有效,本任务书 7b 在它之后。
**串行顺序**:任务 0 → 1 → 2 在分支 `codex/upstream-sync-20260903` 上完成并验收后合入 staging;任务 3 / 4 / 5 / 6 / 7 在其上另开 `codex/upstream-capabilities-20260903`,任务 6 先于任务 3 与 7c 做(两者都沿用任务 6 打通的透传路径),7b 排在 `TASK-repo-hygiene-20260903.md` 之后,其余可并行但推送串行。任务 4 不依赖任务 2,如需提前可单独分支。
---
## 任务 0(P0,门控)· 快照推进与咨询契约 golden
### 做法
1. 在干净 worktree 里跑导入器 git 模式:
```bash
.venv/bin/python scripts/import_yinduzhanxing.py \
--source /workspace/yinduzhanxing --source-mode git \
--policy references/cross_project_contract/sync_policy.v2.json \
--dry-run --output artifacts/yinduzhanxing-import-plan.json
```
审阅 semantic_merge 行后再 `--apply`manifest 只允许进入 `references/cross_project_contract/imports/`,同步更新 `references/upstream/yinduzhanxing/source-manifest.json` 与 `import-plan.json`。
2. **咨询契约 golden**:用虚构 smoke 出生数据,起本地 Python API,按前端实际请求(career / marriage / wealth / timing / health 各一次,`skip_full_reading_for_thematic` 两种取值各跑一次)调用 `/api/consultation_workflow`、`/api/chart`、`/api/varga_full`、`/api/daily_guidance`、`/api/synastry`,把响应**键路径 + 类型**(不记值)写成 fixture 存 `tests/golden/`(沿用 `tests/run_golden_cases.py` 的形式),加一条测试 `tests/test_consultation_contract_golden.py`:合并后重新采集,键路径集合只允许是超集。
3. 把三方合并干跑的冲突表(本任务书"现状实证 4")复核一遍写进 PROGRESS,作为任务 2 的工作清单。
### 验收
- `references/cross_project_contract/imports/commit-a6f47abd….json` 存在,`source_mode=git``source_commit` 为 40 位全哈希,`source_tree_sha256` 与 manifest 一致;`references/upstream/yinduzhanxing/SKILL.md` 的 sha256 等于上游 HEAD 的 SKILL.md。
- golden fixture 无隐私(出生数据为虚构 smoke),测试在改前基线上绿。
- `tests/test_import_yinduzhanxing.py` 绿。
---
## 任务 1P0)· 真相层同步
### 做法
1. `references/strict-workflow-router.md`:语义合并上游 §5 更名(`finance-timing-strict`,保留 `wealth-timing-strict` 别名)、§7 `health-timing-strict` 全文、Level 2 分盘清单加 D6/D8/D30;章节号顺延。`references/quick-reference-guide.md` 同步 finance 别名。**不要**逐字覆盖,本仓两文件有商业改动。
2. `references/technique_registry.json`:接收上游 116 项内容(保持本仓的 JSON 格式化方式,不要把 3084 行格式 diff 反向带回去)。`references/oracle/commercial_skill_truth_overlay.v1.json` 为 25 个新项按决策记录逐条加 `technique_id / status / claim_boundary`Ashtottari 加一条:`status=partial``claim_boundary` 注明规则族限制与 "unverified",且 `selected_rule_family_parameter_sensitive` 不得进确定性结论。
3. 根 `SKILL.md`(商业入口)只加三段:Ashtottari 状态与适用族;`professional_report_reference` 术语规则(对外首选该名,`PL9` 只作旧代号);VedAstro 官方 MCP 故障与 REST 桥为默认对标通路。其余上游 SKILL.md 改动只通过镜像快照体现。
4. 技法计数变化会打红 `tests/test_readme_badges.py` 与 README 徽章:徽章改为注册表实际新值,测试断言同步,改动处注明原值。
5. skill 发布包:`skills/jyotish-vedic-astrology/versions/` 下**新增**一个版本目录(版本号由 `scripts/skill_release_manifest.py` 与 `pyproject.toml` 现有规则决定,例如 `6.9.15`),不改 `6.9.14``scripts/skill_release_package.py` dry-run 通过。
6. 检查 `scripts/full_technique_invocation_matrix.py` 与 `scripts/audit_capabilities.py` 对 116 项注册表的输出:新项在网页路径上应显示为未执行/阻塞,不得出现"executed"。
### 验收
- `.venv/bin/python -m pytest tests/test_readme_badges.py tests/test_skill_hard_constraints.py tests/test_capability_evidence_pool.py tests/test_import_yinduzhanxing.py`:除 `test_capability_evidence_pool` 中基线已红的 `experimental_variant` 一条外全绿;若上游新项让它多红,必须修注册表数据而不是改测试。
- `run_quality_gate.py --profile quick` 绿。
- PROGRESS 给出 25 项新技法的覆盖层状态表。
---
## 任务 2(P0)· 引擎代码三方合并
### 做法
按下列顺序逐文件 `git merge-file`,每个文件合并后立刻跑该文件对应的本仓测试:
1. **零冲突文件**`scripts/jaimini.py`、`scripts/muhurta.py`、`scripts/western_timing_engine.py`、`scripts/solar_return.py`。先检查它们新增的 import 是否都在本仓;缺的模块若是纯计算模块(无外部证据文件依赖)可一并带入并注明来源提交,否则删掉该 import 所属功能。上游对应测试(`tests/test_muhurta*.py`、`test_jaimini*.py` 等)本仓已有的版本一并更新。
2. **低冲突计算模块**`varga.py`、`tajika.py`、`tajika_kernel.py`、`kp_system.py`、`narayana_dasha.py`、`ashtottari_dasha.py`、`gulika.py`、`ayanamsa_utils.py`、`domain_calculation_service.py`、`run_quality_gate.py`、`report_orchestrator.py`、`report_pack_contract.py`。按硬红线 5 裁决。`run_quality_gate.py` 的 `RELEASE_CRITICAL_UNTRACKED_PATHS` 与门禁范围不得被上游改窄。
3. **高冲突入口文件**`unified_consultation_orchestrator.py`(取 `route_surface_contract` 与 finance 别名、health 路由的 `focus_techniques` 与 `evidence_packet_required_sections`;专家判断影子层只在其依赖模块可解析时取)、`mcp_server.py`(取三个新工具,前提是 `pl9-export` 已可运行)、`jyotish_api_server.py`(保留本仓全部商业路由;上游 nadi leaf assistant 路由不取)、`jyotish_engine.py``_build_ai_prompt_pack` / `cmd_full_reading` / `cmd_varga_full` / `cmd_dasha` / 叙事种子生成器 / `pl9-export` 相关函数按硬红线 5 取;`cmd_classical_*` / `cmd_nadi_*` 全部不取;`main` 中对应子命令注册不取)。
4. 校正相关文件按硬红线 3 跳过。
5. **引擎运行时读取的数据文件,按下面规则处理**(2026-09-03 核实:批 B 计算模块 muhurta / jaimini / narayana_dasha / ashtottari_dasha / varga / western_timing_engine / solar_return 不读任何数据文件;`yoga_rules.json`、`saham_rules.json`、`assets/**` 本仓与上游逐字节一致;算法不依赖上游证据台账):
- **必须带入**(引擎运行时无守护地读取、内容是状态/合同元数据、无隐私):`scripts/kp_system.py` `kp_maturity_profile()` 读的四个文件 `references/oracle/kp_exact_cusp_closure_dashboard_2026_08_22.json`、`kp_exact_cusp_mainline_status_2026_08_22.json`、`kp_12_cusp_numeric_oracle_readiness_2026_07_23.json`、`kp_real_event_replay_gate_2026_07_30.json`。不带入则合并后 KP 分析路径直接抛异常。带入前逐个打开确认无出生资料。
- **应同步的产品面内容**(非研究台账):`references/interpretation_template_registry.json`(上游 +145 行,报告生产者索引它)、`references/ai-reading-workflow-prompt.md`、`references/mandatory-verification-gate-protocol.md`,走语义合并。
- **不带入、靠守护降级**:`_event_replay_contract` 读的 `references/oracle/1993_birth_time_candidate_segment_table_2026_08_23.json`(上游作者本人出生案例,隐私,代码已 try/except)、`_build_timing_boundary_attribution` / `_profile_aware_benchmark_appendix` / `_load_rectification_evidence_contract` 读的状态文件(均已守护,缺失时该段显示 blocked / unavailable,这是保守方向,可接受)。PROGRESS 记录哪些段因此为 blocked。
- **随研究子命令一起不取**:`references/nadi_low_risk_rule_pack_draft.json`、`references/real_case_calibration/classical_doctrine_loci_manifest_2026_08_28.json`、`references/chat_safety_audit_manifest.json`。
- 通用规则:合并后 `grep` 引擎入口文件里所有 `references/` / `docs/` 路径字面量与 `Path(...) / 'references'` 拼接,逐一核对本地存在性;不存在且无守护的,要么按上面带入,要么加守护返回 `blocked`,不得让缺文件变成运行时异常。
5. 合并完成后重新采集任务 0 的 golden,跑契约测试;用虚构数据实跑一次 `python scripts/jyotish_engine.py full-reading` 与 `/api/consultation_workflow`career / wealth / health 三题),确认 `modules` 里没有新增 `status=failed` 的模块。
### 验收
- PROGRESS 冲突表:每个冲突块一行(文件、函数、取 ours / theirs / 手工合成、理由)。
- 任务 0 的 golden 测试绿(键路径超集);`frontend` `tsc` 0 错、`npm test` fail 数不高于基线;`run_quality_gate.py` 完整 profile 绿;`tests/test_api_server_growth_contract.py`、`tests/test_commercial_domain_calculation_contract.py` 绿。
- 本地全量 `pytest` 红测清单与 `TASK-repo-hygiene-20260903.md` 记录的基线逐条比对,新增红项为 0,或每一项都有归因。
- staging 部署后 `GET /api/health` 的 `deployment.gitCommit` 等于合并提交;`/api/consultation_workflow` 用 smoke 数据实测三题正常。
---
## 任务 3(P1)· health 路由对齐上游三窗合同并进入个人报告
### 做法
1. **编排器**`_ROUTE_DEFINITIONS["health"]` 的 `focus_techniques` 对齐上游(D6/D8/D30/Dasha/Narayana Dasha/Shadbala/Transit/Functional Benefic-Malefic);`_DOMAIN_PROFILE_SECTIONS["health"]` 改为上游三窗结构:`pressure_windows`、`event_risk_windows`、`recovery_support_windows`、`non_medical_boundary`、`verification_questions`(旧四段的内容映射进新段,不丢);新增 `evidence_packet_required_sections(route)`(本仓没有,取上游实现),health 路由追加 D6 / D8 / D30 / narayana_dasha / functional_benefic_malefic / transit / non_medical_boundary。
2. **引擎**`_build_ai_prompt_pack` 为 health 主题产出叙事种子(对齐 `_build_career_narrative_payload` 的结构:headline / strengths / risks / boundaries),来源限于 D6/D8/D30 宫位与主星、6/8/12 宫主 Dasha 激活、Shadbala 相关行星。`boundaries` 固定包含非医疗声明。
3. **前端咨询链**`consultation-methodology.ts` health 条目保留 `health-timing-strict`wealth 条目加 `finance-timing-strict` 为主名、`wealth-timing-strict` 为别名,与编排器 `route_surface_contract` 对齐;Technique Audit Table 折叠展示对 health 新段生效。
4. **个人报告**`personal-report-route-core.ts` 主题枚举加 `health``report-theme-evidence-plan.ts` 为 health 定最低证据组(D1 + D6 + D8 + D30 + VimshottariTransit 为可选加分项,参照 `TASK-report-blocked-repairs-20260902.md` 的 fail-closed 口径);`personal-report-generation.ts` 的 `interpretiveFacts` / `themeNarrativeSeeds` allowlist 加 health 种子;writer 的 per-theme 静态知识包(`TASK-report-skill-parity-20260901.md` 任务 3 的机制)新增 health 包,≤3000 字符,禁路径与内部名词,且开头写明非医疗边界;报告中心的主题选择器加 health;计费口径与其他主题一致(不新增计费项)。
5. `docs/BUG_HISTORY.md` 不需要新条目,除非实施中发现既有 health 路由缺陷。
### 验收
- smoke 数据实跑 `/api/consultation_workflow` health 题:响应 `strict_workflow_contracts` 显示 health 路由,三窗段齐全,D6/D8/D30 在 `available_layers` 里为 executed`Transit` 无则为 blocked 而非缺席。
- 个人报告含 health 主题时:确定性管线(假 writer)到 `PIPELINE-READY`health claim card 的 conclusion 为真实内容且含非医疗声明;`assertionLevel` 防升级规则未改。
- 前端 `tsc` 0 错;`frontend/tests/consultation-methodology.test.ts`、`consultation-agentic-runtime.test.ts`、报告相关测试绿。
---
## 任务 4P1)· VedAstro 外部对标切到 REST 桥
### 做法
1. 引入 `scripts/vedastro_rest_bridge.py`(上游 `a6f47abd` 版本),去掉其内置的 yn-1993 默认出生参数(本仓不得携带真实出生资料,默认改为虚构 smoke 数据或必填)。
2. `scripts/vedastro_gateway.py`:官方通路的健康判定改为对 `/api/Calculate` 的实际 `Status: Pass``official_verified` / `official_blocked` / `local_fallback` 三态语义不变;免费层 5 次/分钟写进 gateway 的限流参数与 `/api/vedastro_gateway/status` 输出。
3. `scripts/vedastro_parity_matrix.py` 与其他调用 `vedastro_official_mcp_bridge.py` 的路径改为走 REST 桥;MCP 桥保留文件与测试,标注"仅协议探测",不再是默认通路。`match` 合盘子命令上游尚未实现,本仓合盘对标继续标 `official_blocked`,不得伪造。
4. 更新 `docs/engine/README.md`(或本仓 VedAstro 文档所在处)与 `scripts/diagnose_vedastro_mode.py` 的说明。
### 验收
- 无网络时 `tests/test_vedastro_*.py` 全绿(REST 桥测试用录制响应,不打真网)。
- 有网络时手工跑一次 REST 桥 horoscope 子命令(虚构数据),PROGRESS 记录 `Status` 与耗时;命中限流时 gateway 降级 `official_blocked` 而不是报错。
- `/api/vedastro_gateway/status` 显示当前通路为 REST 与限流配置。
---
## 任务 5(P1)· 专业报告导出接进个人报告产品
### 做法
1. **引擎**:确保任务 2 已带入 `build_pl9_style_export_packet`、`render_pl9_markdown`、`cmd_pl9_export` 及其依赖;上游 `--format authority` 与 `--archive-dir` 不需要,可不接;markdown 输出保留上游的引擎边界声明段。所有对外文案与新代码标识用 `professional_report_reference`,旧 `pl9_*` 标识只在兼容处保留。
2. **API**`scripts/jyotish_api_server.py` 新增 `POST /api/professional_report_reference`(入参与 `/api/consultation_workflow` 相同的出生参数 + `format ∈ {json, markdown}` + `packs`),走 `api_heavy_compute_gate`,复用 `_compute_full_reading_for_thematic` 的缓存/复用逻辑,不重复算全盘;响应不含 raw full-reading(上游 `--include-raw` 语义在这里关闭)。
3. **前端**:报告中心(`personal-report-center.tsx`)在已 ready 的报告上增加"专业参考版(导出)"入口,调用上述 API 生成 markdown 并按既有导出方式交付(下载或页内查看,沿用报告中心现有导出交互,不新做组件);导出不经写作 agent、不计费为报告生成、不写 `personal_report_sections`。入口对未 ready 报告不显示。
4. **不做**:把导出内容喂给写作 agent、把导出存进数据库、PDF 格式(上游 pdf 依赖另行评估)。
### 验收
- smoke 数据 `python scripts/jyotish_engine.py pl9-export --format markdown` 与 `/api/professional_report_reference` 都能产出;markdown 含引擎边界声明;输出中不出现文件路径、内部模块名。
- 隐私扫描通过;仓库内没有任何 PL9 参考报告原文。
- 前端入口只对 ready 报告出现,`tsc` 0 错,报告中心测试绿;导出一次不产生任何模型调用(telemetry 计数为 0)。
---
## 任务 6(P1)· 把合并进来的引擎新字段接到聊天与报告
任务 2 只是把上游代码合进引擎;`/api/consultation_workflow` 的 `ai_prompt_pack` 是 `scripts/jyotish_api_server.py` 自己的精简版 `_build_chart_prompt_pack`,前端的报告提取层又是 allowlist 制,**不做这一步,聊天和报告什么都不会变**。
### 做法
1. **响应侧(只新增键)**:在 `_compute_consultation_workflow` / `_build_chart_prompt_pack` 里新增并透传:`timing_narrative`(上游 `_build_timing_narrative_payload(modules)`,结构对齐既有 career / relationship / finance 种子)、`modules.planetary_friendship`(上游 `_build_planetary_friendship_snapshot`)、`module_execution_audit`(上游 `_build_module_execution_audit`)、`pratyantar_dasha_timeline`(上游在 `cmd_dasha` 里挂的,需要在 workflow 的 dasha 子周期里同样挂上)。上游 `response_envelope` 键是纯附加,透传或忽略都可以,不得据此改既有键。任务 0 的 golden 重新采集后必须是超集。
2. **聊天侧**:折叠技法审计表新增 `planetary_friendship` 与 `module_execution_audit` 派生的行(executed / blocked / not_applicable 三态照旧);Ashtottari 行按任务 1 覆盖层的 `partial` 显示为"参数敏感、未验证",不得显示 executed 为确定性;finance / wealth 别名在审计表与路由展示一致。`_build_chart_prompt_pack` 里给聊天模型的证据快照加 `timing_narrative`,长度上限与既有种子一致。
3. **报告侧**`personal-report-generation.ts` 的 `interpretiveFacts` allowlist 加 `planetary_friendship`(只取友敌等级表,不取自由文本)与 `pratyantar_dasha_timeline`(只取当前与下一段的边界日期),`themeNarrativeSeeds` 加 `timing_narrative`timing 主题);沿用 `filterReportEvidenceBundleForSection` 按主题裁剪;净化、长度上限、hash 覆盖与 `TASK-report-skill-parity-20260901.md` 的规则一致。timing 主题 claim card 的 conclusion 可以引用 pratyantar 边界。
4. 成本:报告每章 `inputTokens` 改前改后对照写进 PROGRESS,p50 超过改前 1.3 倍必须停下摆数据(这轮只是增补字段,不应接近报告对齐那轮的 2 倍线)。
### 验收
- golden 超集测试绿;前端 `tsc` 0 错;聊天与报告相关测试绿。
- smoke 数据实跑一次聊天(timing 题)与一份 personal_full 报告:审计表出现新行且三态正确;timing 章节的 claim card 含 pratyantar 边界日期;bundle hash 稳定(同输入两次一致)。
- 每章 `inputTokens` 对照表在 PROGRESS 里。
---
## 任务 7(P1)· 校正:自适应选题、岁差按请求传递、报告出生时间敏感度节
### 7a · 自适应选题器(P1)
- 引入上游 `scripts/active_rectification_selector.py``select_next_questions`:按可区分答案跨度、事实可靠度、作答成本、域多样性、剩余候选数、**分钟相关度**打分选题)与其测试 `tests/test_active_rectification_selector.py`。分钟相关度是核心价值:只优先问"其敏感层在剩余候选分钟窗口内真的会变"的题,直接针对本仓已知的"题库分不开相邻 top-2"问题。
- `scripts/active_rectification_questions.py`:按上游给题库加 `factual_reliability`、`positive_cluster` / `negative_cluster``_candidate_scan` 挂 `scan_candidate_times` 的 `minute_scan``build_questionnaire` / `score_answers` 返回 `selection` / `next_round_selection`**新增键**`next_round_questions` 等旧键保留)。**不引入** `_known_case_regression_hint`、`regression_hint`、`minute_rankings`、`minute_focus`。
- 本仓 `scan_candidate_times` 只返回各分盘上升星座;选题器的 `_minute_feature_value` 需要更细特征。按上游改法给扫描行**新增** `d1_longitude` 与完整上升对象(旧字段不动),并把分盘列表里的 D1 去掉。
- 前端 `birth-time-journey-engine-model.ts` / `birth-time-journey-turn.ts`:自适应轮的 `nextQuestion` 改为优先取服务端 `next_round_selection.selected_questions[0]`,服务端没给时回退现有逻辑。基线轮不变。
- 验收:`tests/test_active_rectification_questions.py`(按上游 +64 行的断言更新,但删掉与 regression_hint 相关的用例)与选题器测试绿;`npx tsx --test tests/rectification-*.test.ts` fail=0 且用例数不少于基线 62 个文件;用本仓虚构 smoke 案例跑一次完整问答,PROGRESS 附"每轮所选题 + 其分钟相关度"表,证明选题确实随候选窗口变化;V5 打分输出对同一答案集逐字节不变(选题只改顺序,不改分数)。
### 7b · 岁差与交点模式按请求传递(P1,与 `TASK-repo-hygiene-20260903.md` 串行)
- `scripts/active_rectification_event_engine.py``AYANAMSA` / `NODE_MODE` 全局常量三处)、`active_rectification_questions.py`、`candidate_time_sensitivity_scan.py`(本仓签名无 `ayanamsa`):改为 `request.get("ayanamsa", DEFAULT_AYANAMSA_NAME)` / `request.get("node_mode", ...)`,默认值不变(Raman)。`/api/rectification/*` 与 `/api/active_rectification_*` 的请求体接受这两个键并写进回执。
- 顺序:仓库整备任务书的任务 0 已规定"校正引擎按 Raman 校准的阈值与 golden 本轮不动,只确认 lahiri 下不崩"。本项在其之后做:整备任务书交付 `resolveAyanamsa(profile)` 后,校正前端把它传给 Python。若整备任务书尚未合入,本项只做 Python 侧并保持默认值,前端传参留到整备任务书合入后补一个小提交。
- 验收:默认请求(不带 ayanamsa)的 V5 输出逐字节不变;带 `ayanamsa=lahiri` 的请求回执里 `ayanamsa` 为 `lahiri` 且计算确实按 Lahiri(用 smoke 案例对比上升度数);`tests/test_active_rectification_api.py` 及本仓 38 个 Python 校正测试绿。
### 7c · 不确定出生时间的报告敏感度节(P2,依赖任务 2 与任务 6)
- 引入上游四个 `flexible_birth_time_*` 模块与测试;`_build_birth_time_sensitivity` 里读 1993 分段表的 `_load_1993_candidate_segment_table` 与 `candidate_segment_table` 一并删掉,`candidate_micro_compare` 段不要。窗口来源改为:报告请求带的出生时间精度真值(`BIRTH_TIME_ACCURACY``TASK-consultation-birth-accuracy-20260901.md` 已贯通)为 `confirmed` 时**不生成**本节;为 `provisional` / `approximate` 时窗口取校正案例已采用的可信区间(案例不存在时用精度等级对应的固定宽度,宽度表写进代码常量并在 PROGRESS 说明),上限 15 个候选分钟,超出则只取区间两端与代表分钟。
- 产物:`consultation_workflow` 响应新增 `birth_time_sensitivity`schema 沿用上游 `jyotish.report_birth_time_sensitivity.v1``status ∈ {not_applicable, candidate_window_only}`),个人报告 bundle 新增对应的解读性事实(哪些主题结论在窗口内稳定、哪些敏感),报告附录多一节"出生时间敏感度",正文各章在该主题被标为敏感时加一句边界提示。writer 输入隔离与 schema 规则沿用。
- 验收:`confirmed` 案例的报告与改前逐字节一致(bundle hash 不变);`provisional` 案例的报告附录出现敏感度节,且每个"敏感"判断能追溯到窗口内至少一个分钟的层变化;引擎侧 `python scripts/jyotish_engine.py full-reading` 带窗口参数不依赖任何 references 数据文件;前端 `tsc` 0 错,报告测试绿。
### 任务 7 通用红线
- 仓库内不得出现任何真实出生案例;任务 7 全部 fixture 用虚构 smoke 数据。合并前 `grep -rn "1993-04-17\|14:49" scripts tests frontend/src` 必须为空(或只命中与该日期无关的既有测试数据,逐条说明)。
- `ALGORITHM_VERSION` / `POLICY` 常量不变;若任何 golden 变化,说明是新增键还是数值变化,数值变化即视为越界。
- 合入后重跑 `docs/testing/` 里校正的浏览器走查清单,结果写 PROGRESS;走不了的写环境缺口。
---
## BUG 编号起点
开工时核对 `docs/BUG_HISTORY.md` 最大号;截至本任务书为 **BUG-510**,新条目从 **BUG-511** 起。
## 回报格式
`docs/tasks/PROGRESS-upstream-sync-20260903.md`(任务 02)与 `docs/tasks/PROGRESS-upstream-capabilities-20260903.md`(任务 3–7):每个任务写做了什么、测试数字、冲突表、偏离与原因、环境缺口;并在 `docs/tasks/README.md` 状态板改状态。