diff --git a/CHANGELOG.md b/CHANGELOG.md index 261de770..41189935 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # 印度占星 Skill 更新日志 +## 2026-09-09 — 生时校正对照卡按候选分钟算经历和时段,交付旁白不再被裁成一句 + +生时校正给出范围后,对照卡上的经历吻合和未来时段按引擎里全部候选分钟来算,不再只算引擎分数最高的三个。卡片上的三列是后验可能性最高的三个分钟;某一列还没算出来时写灰字「这一分钟还没对照」,不会再出现「强相关 0 · 有关联 0 · 弱关联 0」,也不会把「没算」说成「未来一年没有明显的窗口」。 + +三列里相同的性格句只出现在卡片顶部一次,例如「三个时间的事业盘都在巨蟹座:…」。每列改成时间、相对可能性、有差别的性格句,再加上两行人话:经历对照(「8 件经历里 7 件对得上,最不合的是 2024 年 5 月那段感情」)和下一个值得留意的时段;没有窗就写「未来一年没有明显的时段」。列内不再有小标题。 + +交付轮助手正文在可以收口时最多留三句(范围、经历与吻合率、边界句),中间采集轮仍只留一句复述。 + +右侧当前盘面改成北印度菱形图,宫位表收进折叠;换升时刻默认折起来,摘要写「换升时刻 · N 个」。Skill 版本不变。 + + ## 2026-09-09 — 点「更像这个」后三列对照卡留在原处 生时校正点「更像这个」之后,三列对照卡不再整张消失。被点的列先显示「正在采用…」,成功后变成「已采用」,其它列仍可改选。下面那句「已采用 HH:MM,新建对话即按这个时间排盘。」跟卡片同一条左边线,不再单独贴到屏幕左边。Skill 版本不变。 @@ -16,6 +27,7 @@ 从首页点「深入看今日」时,按「时运」计算,不再被改成「综合」。正文按三节写:今日趋势、适合推进 / 需要避开、一个行动。某一节没写出字会再试一次;分段写作时不能再调排盘工具。思考区按整句过滤,不会再出现缺词英文或 `run-jyotish-` 残段。空回答仍然不扣点。Skill 版本不变。 + ## 2026-09-09 — 婚恋激活句按心动 / 成对 / 领证出,网页咨询接上当前大小运 网页咨询路径现在用当前大运/小运喂给婚恋三层,不再拿出生时大运空转。没有领证命中时,激活句只写观察、并标明不等于领证;没有事件类命中时不再写「关键期」。小运缺失时大运名不再拼 `Unknown`。Skill 版本不变。 diff --git a/docs/BUG_HISTORY.md b/docs/BUG_HISTORY.md index 65285451..11434e1e 100644 --- a/docs/BUG_HISTORY.md +++ b/docs/BUG_HISTORY.md @@ -9263,10 +9263,10 @@ - 用户现象:区间卡每个候选分钟一行。与代表分钟 D9/D10 相同的行右侧是空的;代表分钟预先标成「排盘用」,用户觉得是直接出一个时间,而不是在几个分钟里对照后选择。 - 触发条件:访谈收口出区间交付卡;范围内有两个以上候选分钟。 - 根因:BUG-595 把交付做成「点一行即采用」,右侧只写与代表分钟的分盘差异。产品决定改成并排对照:每列写该分钟自己的相对可能性、性格处事、经历吻合和未来一年窗口。 -- 修复:卡片改成一行至多三列,按后验概率排序、按精确 HH:MM 去重。每列由服务端写相对可能性、D9/D10/月宿性格处事、经历强/中/弱计数与最不吻合一件(年-月+领域)、往后 12 个月 1–2 个窗或固定句「未来一年没有明显的窗口」。按钮「更像这个」走现有 accept RPC,选择不计分。同一次 compare 增加 `event_dasha_ledger_by_time` 与 `prospective_windows_by_time`。不预标「排盘用」。Skill 只改 `references/candidate-comparison.md`,bump 10.0.18。 +- 修复:卡片改成一行至多三列,按后验概率排序、按精确 HH:MM 去重。每列由服务端写相对可能性、D9/D10/月宿性格处事、经历对照与未来时段。按钮「更像这个」走现有 accept RPC,选择不计分。同一次 compare 增加 `event_dasha_ledger_by_time` 与 `prospective_windows_by_time`。不预标「排盘用」。Skill 只改 `references/candidate-comparison.md`,bump 10.0.18。列键必须覆盖引擎候选全集,见 BUG-614;用户可见句不再写「强相关 / 有关联 / 弱关联」,见 BUG-614 卡片减法。 - 验证:`frontend/tests/rectification-range-delivery-20260907.test.ts` 三列 DOM、「更像这个」、无「排盘用」;`frontend/tests/rectification-delivery-ui-simplify-20260908.test.ts` 三句旁白仍不含「排盘用」;`frontend/tests/agent-voice-copy-contract.test.ts` 锁新文案;`tests/test_rectification_v5_services.py::test_compare_returns_ledger_and_windows_by_candidate_time` 三分钟各一份 ledger/窗口。 -- 防复发:交付卡必须是列对照而不是逐行空差异;列文案必须来自服务端类型表与 ledger/窗口映射,不得让模型写。超过三列时必须出现「还有 N 个分钟可能性更低,已并入范围」。没有窗口时必须写固定句,不得空白。 -- 相关记录:BUG-595、BUG-583、BUG-568 +- 防复发:交付卡必须是列对照而不是逐行空差异;列文案必须来自服务端类型表与 ledger/窗口映射,不得让模型写。超过三列时必须出现「还有 N 个分钟可能性更低,已并入范围」。`by_time` 缺键必须是「这一分钟还没对照」,不得回退成 0 或「没有窗口」。没有窗口时写「未来一年没有明显的时段」。 +- 相关记录:BUG-595、BUG-583、BUG-568、BUG-614 - 复发自:BUG-595(逐行卡上线后用户看不出为何要选另一分钟) - 修复版本:待发布 @@ -9409,8 +9409,8 @@ - 根因:方法句渲在气泡;旁白拼接 `explainScoreMovement`;证据轮只靠提示词,模型仍写三句加评价。 - 修复:气泡不再渲染 `vargaSentence`,展开的活动时间线保留。点选旁白只有「已记录,范围没变。」或「已记录,范围收到 / 变为 A–B。」证据轮超过两句只留首句,并去掉「很有帮助 / 很有价值 / 很有分量 / 特别有用」。 - 验证:`frontend/tests/rectification-varga-style-copy.test.ts`、`frontend/tests/rectification-answer-choice.test.ts`、`frontend/tests/rectification-v9-agent.test.ts`、`frontend/tests/rectification-collect-prompt.test.ts`、`frontend/tests/agent-voice-copy-contract.test.ts`(机器词表含「领先」「落后」)。 -- 防复发:用户可见旁白不得出现「领先」「落后」。证据轮落库不得含价值评价四词。方法句不得回到气泡正文。 -- 相关记录:BUG-545、BUG-585 +- 防复发:用户可见旁白不得出现「领先」「落后」。证据轮落库不得含价值评价四词。方法句不得回到气泡正文。仍有下一问的 evidence 轮超过两句只留首句;`persistNextInterviewIfIdle` 返回 `terminalNote` 的交付轮保留 ≤3 句(BUG-615)。 +- 相关记录:BUG-545、BUG-585、BUG-615 - 复发自:无 - 修复版本:`aa7ccb30` @@ -9526,6 +9526,38 @@ - 复发自:无 - 修复版本:待发布 +## BUG-614 | 三列卡把「还没对照」显示成 0 和没有窗口 + +- 状态:resolved +- 首次发现:2026-09-09 +- 最近更新:2026-09-09 +- 影响面:`scripts/rectification/refinement_packet.py`(`column_times_for_compare`)、`frontend/src/lib/rectification-agentic/v9/divergence-panel.ts`、`rectification-range-delivery.tsx`、`user-copy.ts` +- 用户现象:区间卡第 2、3 列写「强相关 0 · 有关联 0 · 弱关联 0」,三列都写「未来一年没有明显的窗口」;相同性格句每列重复一遍。 +- 触发条件:推断层后验前三与引擎分数前三不是同一组分钟;客户端按列时间查 `event_dasha_ledger_by_time` / `prospective_windows_by_time` 找不到键。 +- 根因:`column_times_for_compare` 只取引擎分数前三,卡片列按后验前三投影。缺键时投影把空表当成 0 次吻合、把缺窗口当成「没有窗」。 +- 修复:`columns` 改为引擎 `candidate_times` 去重全集(上限 9)。客户端缺键写 `fit: null` / `windows: null`,灰字「这一分钟还没对照」,不得回退成 0。经历对照改成「N 件里 M 件对得上」;无窗写「未来一年没有明显的时段」。三列共有的性格句只出现在卡顶一次。 +- 验证:`tests/test_rectification_v5_services.py::test_compare_ledgers_cover_all_engine_candidate_times`;`frontend/tests/rectification-range-delivery-20260907.test.ts` 后验前三与引擎前三不同时 `fit` 非 null,缺键 DOM 出现「这一分钟还没对照」、不出现 `0 · 0 · 0`。 +- 防复发:`set(ledgers) == set(candidate_times)`;用户可见文案禁用「强相关 / 有关联 / 弱关联」;列内不得再出现 `

`「经历对照 / 往后 12 个月」。 +- 相关记录:BUG-597、BUG-615、`TASK-rectification-compare-card-polish-20260909.md` +- 复发自:BUG-597(三列对照的 by_time 只覆盖引擎前三) +- 修复版本:待发布 + +## BUG-615 | 交付旁白被证据轮裁句裁成一句 + +- 状态:resolved +- 首次发现:2026-09-09 +- 最近更新:2026-09-09 +- 影响面:`frontend/src/lib/rectification-agentic/v9/collect-prompt.ts`、`agent-run.ts` +- 用户现象:交付轮助手正文只剩「校正到这里可以收口了。」一类单句,BUG-595 定的三句(范围、经历与吻合率、边界句)被裁掉。 +- 触发条件:访谈收口出区间卡;该轮 `action === "evidence"`,模型写了三句以上。 +- 根因:BUG-606 的 `trimEvidenceTurnBody`(超过两句只留首句)对所有 evidence 轮生效。交付也走 evidence 轮。 +- 修复:先跑 `persistNextInterviewIfIdle`。仍有下一问时继续裁到一句;该函数返回 `terminalNote` 时保留 ≤3 句。裁剪不得发生在 idle 之前,否则交付四句会先被裁掉。裁完与流式正文不同时发 `answer.delta replace`,气泡跟落库同一段。 +- 验证:`frontend/tests/rectification-v9-agent.test.ts` 交付轮模型写四句 → 落库三句;普通证据轮三句 → 一句。`frontend/tests/rectification-collect-prompt.test.ts` 锁 `trimSpokenTurnForInterview`。 +- 防复发:`agent-run` 必须在 idle 之后调用 `trimSpokenTurnForInterview(answerText, interviewIdle?.terminalNote === true)`。不得把交付轮重新裁成一句。 +- 相关记录:BUG-606、BUG-595、BUG-614、`TASK-rectification-compare-card-polish-20260909.md` +- 复发自:BUG-606(证据轮裁句没有把交付轮排除) +- 修复版本:待发布 + ## BUG-618 | 采集题「没有 / 记不清」浮在输入框上方,离问题太远 - 状态:resolved diff --git a/docs/tasks/PROGRESS-rectification-compare-card-polish-20260909.md b/docs/tasks/PROGRESS-rectification-compare-card-polish-20260909.md new file mode 100644 index 00000000..a66654a7 --- /dev/null +++ b/docs/tasks/PROGRESS-rectification-compare-card-polish-20260909.md @@ -0,0 +1,52 @@ +# PROGRESS · 三列对比卡修正与减法(BUG-614/615,2026-09-09) + +工作树:`.worktrees/rectification-compare-card-polish-20260909` +分支:`codex/rectification-compare-card-polish-20260909` +任务书:`docs/tasks/TASK-rectification-compare-card-polish-20260909.md` +基线:任务书写 `origin/staging` @ `365ad799`;本 worktree 按开工时的 `origin/staging` `3005e36d`(任务书本身)切出。合入前 rebase 到当时的 `origin/staging`(含 `17b36f3a` 咨询 BUG-612/613、`584a56bd` 报告图布局 brief、`ca921c3f` 采集按钮/时间轴/已采用列,BUG-618~620)。已采用列继续 `disabled={busy || adopted}`,不把 BUG-618 冲掉。 + +本单状态:**待验收**。合入 staging 时更新落点 SHA。 + +预检:本机已跑 `python3 scripts/pre_work_check.py --remote-timeout 8 --command-timeout 45`(含 `diagnose_external_engine_adapters.py --json`),远端可见性 `verified`。前端用 worktree 里指向主仓的 `frontend/node_modules` 符号链接。 + +未改:采用 RPC、各道门槛、`SCORE_DELTA`、四选项合同、时间轴、Skill 版本 / `references/conversation-strategy.md`。 + +## 做了什么 + +- **BUG-614** `column_times_for_compare(..., limit=9)` 覆盖引擎 `candidate_times` 去重全集。客户端 `lookupByTime` 缺键 → `fit: null` / `windows: null`,灰字「这一分钟还没对照」,不再把空表渲染成 `0 · 0 · 0`。 +- **BUG-615** `trimSpokenTurnForInterview` 在 `persistNextInterviewIfIdle` **之后**执行:仍有下一问裁到一句;`terminalNote` 保留 ≤3 句。不得在 `streamAttempt` 里先裁。裁完若与流式正文不同,再发一条 `answer.delta` `replace`,气泡与落库一致。 +- **卡片减法** 两列及以上共有性格句提到卡顶并改写成「两个/三个时间的…都在…」;列内 `fit_line` / `window_line`;无 `

`;禁用「强相关 / 有关联 / 弱关联」。 +- **右栏** `VedicChartSvg` 北印星盘;宫位表与换升时刻默认 `
`(summary「换升时刻 · N 个」);显示层并入同一折叠。换分钟只高亮变化宫,无动画。 + +## 三栏 + +| 用例 | 原值 | 新值 | 理由 | +| --- | --- | --- | --- | +| 引擎 5 个候选、卡片后验前三与引擎前三不同 | 后验列查不到键 → `0 · 0 · 0` / 「没有窗口」 | `by_time` 含全部候选分钟;列 `fit`/`windows` 有数 | 决策 1:按引擎候选集算,不是按卡片前三 | +| `by_time` 缺某一列的键 | 空数组当 0、当没有窗 | `fit === null`,DOM「这一分钟还没对照」 | 没算 ≠ 没有 | +| 三列 D10 同在巨蟹 | 三列各写一遍 | 卡顶一句「三个时间的事业盘都在巨蟹座:…」 | 相同句只写一次 | +| 交付轮模型写 4 句 | BUG-606 裁成 1 句 | `terminalNote` 时留 3 句 | 决策 2;BUG-595 三句口径 | +| 普通证据轮 3 句 | 1 句 | 仍 1 句 | BUG-606 采集轮不变 | +| 右栏本命 | 宫位表常驻 | 北印星盘 + 宫位表折叠 | 读屏仍可打开表 | +| 右栏换升时刻 | 逐分钟常驻列表 | 默认折叠「换升时刻 · N 个」 | 时间轴已表达同一件事 | + +## 测试 + +- `frontend` `./node_modules/.bin/tsc --noEmit`:exit 0 +- `npm run lint`:0 error / 107 warning(仓库既有 warning,无新增 error) +- 任务书切片 `tsx --test tests/rectification-*.test.ts tests/agent-voice-copy-contract.test.ts`(排除 database):**1063 passed / 0 failed** +- 本单针对性:`rectification-v9-agent.test.ts` 交付 4→3 句、证据 3→1 句;`rectification-range-delivery-20260907.test.ts` 后验前三有 `fit`、缺键「还没对照」;`rectification-board-model.test.ts` 北印星盘 + 换升默认折叠 +- `.venv/bin/python -m pytest tests/test_rectification_v5_services.py::RectificationV5ServicesTest::test_compare_ledgers_cover_all_engine_candidate_times` 与 `test_compare_returns_ledger_and_windows_by_candidate_time`:**2 passed**。同文件 `test_block_scan_seven_events_finishes_within_fifteen_seconds` 本机 41s 超 15s 预算,与本单无关(既有壁钟断言,见 BUG-570 P2) +- 浏览器真人走查:无登录态,未见真实交付卡/右栏像素 + +## 偏离 + +1. 任务书基线 `365ad799`;worktree 从已推任务书的 `3005e36d` 切出。未把后续 staging 提交 rebase 进来。 +2. 代表分钟缺 `by_time` 键时,经历 ledger 仍可回退到该分钟自己的 `eventDashaLedger`(不是填 0);窗口没有回退。缺键列只要 `windows == null` 仍显示「还没对照」。 +3. 单列不把性格句提到卡顶(任务书写的是三列共有)。 +4. 浏览器真人走查:本会话无登录态,未见真实交付卡/右栏像素。合同测试覆盖 DOM 字符串,不把它们写成已经看见真实会话。 +5. 裁句后补一条 `answer.delta replace`。任务书只要求 idle 之后裁句;不补这条的话流式气泡会停在未裁正文。 + +## 环境缺口 + +无登录态、无生产/staging 走查。不把合同测试写成已经看见真实像素。 diff --git a/docs/tasks/README.md b/docs/tasks/README.md index 4aac237c..5f202c64 100644 --- a/docs/tasks/README.md +++ b/docs/tasks/README.md @@ -87,7 +87,7 @@ | `TASK-rectification-timeline-fix-20260909.md` | `PROGRESS-rectification-timeline-fix-20260909.md` | 时间轴修复单:宽度读数改含两端分钟数(与 BUG-593 报告/卡片一致);标记改读推断层候选全集,被淘汰分钟留在原地变空心(客户端投影只含 active,DESIGN §10 描述在真实数据下画不出) | 已验收通过 | `92e3d5e7`(BUG-602~603) | | `TASK-rectification-conversation-economy-20260909.md` | `PROGRESS-rectification-conversation-economy-20260909.md` | 对照竞品后产品拍板三条:开场三句讲做法 + 一次收多件(推翻 opening brief「不要一次说完/不举例」与 SKILL L52);采集题「没有 / 记不清」按钮(不做示例骨架条);每轮只留一句(方法句进活动记录、点选旁白去领先落后、证据轮正文一句复述 + 服务端裁剪);Skill 10.0.19 | 已验收通过(2 条 P3 备注) | `aa7ccb30` + `1453fb16`(BUG-604~606,Skill 10.0.19) | | `TASK-consultation-daily-empty-answer-20260909.md` | `PROGRESS-consultation-daily-empty-answer-20260909.md` | 首页「深入看今日」计算完成却 `empty_answer`:入口定的 `timing` 被模型改成 `general`(`canonicalDomainPlan` 以模型为准),分段写作标题与今日格式错位,分段 `maxSteps=1` 且工具仍可调 → 模型在分段里再调工具、零正文;思考流按 chunk 过滤漏出缺词英文 | 待验收 | `codex/consultation-daily-empty-answer-20260909`(BUG-612~613);走查 `docs/testing/consultation-daily-empty-answer-20260909.md` | -| `TASK-rectification-compare-card-polish-20260909.md` | `PROGRESS-rectification-compare-card-polish-20260909.md` | 三列卡两列经历对照 0、三列无未来窗:引擎按引擎前三算 by_time,卡片按推断前三查表,键不匹配(BUG-614);交付旁白被 BUG-606 裁成一句(BUG-615);设计减法:相同性格句只写一次、经历对照说人话、删小标题、右栏本命宫位改北印星盘、换升时刻默认折叠 | 待执行 | `codex/rectification-compare-card-polish-20260909`(BUG-614~615) | +| `TASK-rectification-compare-card-polish-20260909.md` | `PROGRESS-rectification-compare-card-polish-20260909.md` | 三列卡两列经历对照 0、三列无未来窗:引擎按引擎前三算 by_time,卡片按推断前三查表,键不匹配(BUG-614);交付旁白被 BUG-606 裁成一句(BUG-615);设计减法:相同性格句只写一次、经历对照说人话、删小标题、右栏本命宫位改北印星盘、换升时刻默认折叠 | 待验收 | `codex/rectification-compare-card-polish-20260909`(BUG-614~615) | ### 聊天主链路与首页 diff --git a/docs/testing/rectification-scenarios-20260907.md b/docs/testing/rectification-scenarios-20260907.md index a7b5c2eb..fb405c09 100644 --- a/docs/testing/rectification-scenarios-20260907.md +++ b/docs/testing/rectification-scenarios-20260907.md @@ -84,12 +84,13 @@ 期望: -- 交付轮只见一张卡:范围、对照了 N 件经历、至多三列并排(相对可能性、性格处事、经历对照、往后 12 个月、「更像这个」)、底部边界句 -- 点「更像这个」即采用;卡片留在原处,被点的列显示「正在采用…」再变成「已采用」,其它列仍可点改选 +- 交付轮只见一张卡:范围、对照了 N 件经历、至多三列并排。相同性格句只出现在卡顶一次。每列是时间、相对可能性、有差别的性格句、人话经历对照(「N 件里 M 件对得上」)、下一个时段或「未来一年没有明显的时段」、「更像这个」;底部边界句。列内没有小标题。 +- 某一列还没对照时只见灰字「这一分钟还没对照」,不见「强相关 0 · 有关联 0 · 弱关联 0」,也不把「没算」写成「没有窗口」 +- 点「更像这个」即采用;卡片留在原处,被点的列显示「正在采用…」再变成「已采用」并禁用,其它列仍可点改选 - 采用后的收尾句跟卡片同一列,不要单独贴左,也不要出现在输入框上方 - 卡片下方「查看验证报告」默认收起,打开后是真正的表格 - 助手正文只有三句(范围、经历与吻合率、边界句),不含「排盘用」「方法1」或 Technique Audit -- 不见「相对支持度」「当前推荐」「采用此时间」「按这个范围用」「再补一件经历」「都不像」「说不好」 +- 不见「相对支持度」「当前推荐」「采用此时间」「按这个范围用」「再补一件经历」「都不像」「说不好」「强相关」「有关联」「弱关联」 - 输入框上方没有「先这样,先看当前范围」,也没有采用后状态条 ## 6. 七领域问完后下一问必须是职业题或直接出区间卡 diff --git a/frontend/DESIGN.md b/frontend/DESIGN.md index 8eefe836..dc6b7ac7 100644 --- a/frontend/DESIGN.md +++ b/frontend/DESIGN.md @@ -475,7 +475,7 @@ or user IDs. Agent 的 live 标记只有 `InlineSpinner` 一种。曾经并存的 canvas 小球(`thinking-orbs`)已移除,不得再引入第二种 live 标记。 -校正面的所有等待复用行内等待:进入前的 hydration 在揭幕之前完成,进入后唯一的等待形态是时间线 live 行(含「正在准备下一个问题…」这一条独立 live 行)。区间交付卡只挂在最新那条采用旁白下面,不得留在更早的采集/区分题下;采集题还没答完时不出卡。卡上至多三列并排,点「更像这个」即采用该列分钟,按钮显示「正在采用…」或「已采用」。采用过程中整张卡留在原处,不得因 `busy` 卸掉。采用后前事核对结束走 `verified_idle`:一行收尾文案跟在卡片下面、与助手列对齐,没有 live 行、没有重载、没有采用状态条。 +校正面的所有等待复用行内等待:进入前的 hydration 在揭幕之前完成,进入后唯一的等待形态是时间线 live 行(含「正在准备下一个问题…」这一条独立 live 行)。区间交付卡只挂在最新那条采用旁白下面,不得留在更早的采集/区分题下;采集题还没答完时不出卡。卡上至多三列并排,相同性格句只写一次,点「更像这个」即采用该列分钟,按钮显示「正在采用…」或「已采用」。采用过程中整张卡留在原处,不得因 `busy` 卸掉。采用后前事核对结束走 `verified_idle`:一行收尾文案跟在卡片下面、与助手列对齐,没有 live 行、没有重载、没有采用状态条。卡片与右栏细则见 §11、§12。 首页只揭幕一次。揭幕前的加载屏分两阶段:先取账户、模型目录与会话列表,再并行取当前会话消息、推荐问题、今日星语与校正入口摘要,并预热校正分包;全部就绪或 4 秒预算到期(`BOOTSTRAP_PREPARE_TIMEOUT_MS`)才揭幕。揭幕后不得再出现任何阻塞等待或组件级 spinner:推荐问题未到显示安全默认问题,今日星语未到显示静态文案「今天的星语还没写出来。」(不带 `aria-busy`),校正卡用无摘要文案,内容到达后静默替换。切换到消息尚未缓存的会话时消息区留白并只给 `sr-only` 文案,不转圈;揭幕后按侧栏顺序后台预取最近 5 条会话(`SESSION_PREFETCH_COUNT`)让常见切换零等待。轨道环消失后不得再换一套动效继续等。 @@ -523,7 +523,7 @@ Admin 的 antd `` 是独立设计系统,不在此表。 | 范围变化句 | 服务端已写进落库助手消息,BUG-588 防复发要求它在那里;条上再写=同句同屏两次 | | 「仍在范围内 N / 已排除 N」计数与图例 | 实心=在内、空心=已排除,答完第一题即自明;图例是过度提示的典型形态 | | 阶段标签(时段 / 分钟) | `block_scan` / `minute` 是后台词汇,贴近 BUG-043 红线 | -| 「已对照 N 件经历」 | 归交付卡,那里每列已带经历对照计数 | +| 「已对照 N 件经历」 | 归交付卡;卡上是人话「N 件里 M 件对得上」,不是计数条 | | 「时间轴只读」注脚 | 在解释一个不存在的东西;没有元素看起来可点,就不需要声明不可点 | | 预计剩余时间、定时器插值动画 | 与报告进度条同一条原则:不得演出后端没做的动作 | @@ -535,3 +535,23 @@ Admin 的 antd `` 是独立设计系统,不在此表。 - 跨午夜的窗口(`late_night` 是 23:00–03:59,末端早于始端)按次日展开,轴保持单调。 - 条上不得出现 `rectification-step-state` 类名(BUG-575 防复发)。 +## 11. 区间交付卡 + +交付对象是区间里并排的候选分钟,不是支持度数字,也不是逐行空差异。 + +**相同的句子只写一次。** 两列或三列共有的 D9 / D10 / 月宿性格句提到卡片顶部(「三个时间的事业盘都在巨蟹座:做事以照顾人为主」)。列内只留有差别的句子;某列没有差别句就不显示性格块,不写「同上」。单列不提升共享句。 + +每列 = 时间 + 相对可能性 + 至多三行 + 「更像这个」。列内不再有 `

`。经历对照由服务端拼成一行:「8 件经历里 7 件对得上,最不合的是 2024 年 5 月那段感情」。未来窗一行:「下一个值得留意的时段:2027 年 3 月前后(事业)」;算过但没有窗写「未来一年没有明显的时段」;`by_time` 缺键写灰字「这一分钟还没对照」,不得回退成 `0 · 0 · 0` 或把「没算」说成「没有窗」。用户可见文案不得出现「强相关 / 有关联 / 弱关联」。 + +卡顶保留范围与经历数;卡底边界句保留;「查看验证报告」默认收起。不预标「排盘用」。点「更像这个」走现有 accept RPC。采用过程中整张卡留在原处;已采用列按钮禁用。收尾句跟卡片同一列。 + +引擎 `event_dasha_ledger_by_time` / `prospective_windows_by_time` 的键是引擎 `candidate_times` 去重全集(上限 9),不是引擎分数前三。卡片仍只投影后验前三。 + +## 12. 校正右栏盘面 + +右栏回答「当前按哪一分钟在看盘」,不回答「选哪一分钟」。顶部不加任何新说明文字。 + +**本命宫位改北印星盘。** 用 `VedicChartSvg` 渲染代表分钟的 `house_table`。宫位表退到星盘下方的 `
`(读屏与复制仍可用)。换分钟时只高亮变化的宫(`changedHouses` / `lagnaChanged`),不做动画。星盘组件在校正面 `dynamic()` 分包里,不进首页首屏。 + +**换升时刻默认折叠。** 时间轴已常驻显示范围与候选点,右栏「换升时刻」整段默认收进 `
`,summary 为「换升时刻 · N 个」;逐分钟 LayerChips 不变。「显示层」子折叠并入同一折叠。确认门折叠、两段本命上升折叠保留原样。 + diff --git a/frontend/docs/VOICE.md b/frontend/docs/VOICE.md index c15086f3..d363f6ca 100644 --- a/frontend/docs/VOICE.md +++ b/frontend/docs/VOICE.md @@ -32,8 +32,8 @@ Jyotisha 的可见文案是产品的一部分。正确性红线(真实性、 | 当前可信区间是 05:00–05:07,代表分钟 05:00。代表分钟只是代表性候选,不是已确认的唯一出生分钟。 | 已经从最初的 30 分钟收到 05:00–05:07 这 7 分钟。代表分钟是 05:00,这只是代表性候选,不是已确认的唯一出生分钟。 | 同一边界语义,带进度,少法务腔。 | | 剩下的题分不开当前候选。更站得住的范围是 05:15,代表分钟 05:15。 | 再问下去也分不出更准的时间了。眼下更站得住的是 05:15。 | 单分钟不要把范围和代表分钟念两遍;「当前候选」是内部词。 | | 可以从下面的时间里选一个采用。 / 下面的时间可以先用着。 | 我按你说的经历认真分析过了,下面是这次的结果。 | 这是认真分析后的结果,不是随便先用着;采用仍不是确认。区间交付卡必须就在这句下面。 | -| 相对支持度 16 · 采用此时间 | 一行至多三列。每列写相对可能性、性格处事、经历对照、往后 12 个月,点「更像这个」即采用。不预标「排盘用」。 | 交付对象是区间里并排的候选分钟,不是四张卡上的支持度数字。 | -| 候选 A 预测下一次事业变动更可能在 2027 年 3 月附近。 | 每列用服务器算好的 1–2 个事件窗;没有窗就写「未来一年没有明显的窗口」。 | 窗口按候选分钟各算,模型不写。 | +| 相对支持度 16 · 采用此时间 | 一行至多三列。相同性格句只写一次。每列:相对可能性、有差别的性格句、人话经历对照、下一个时段,点「更像这个」。缺数据写灰字「这一分钟还没对照」。不预标「排盘用」。 | 交付对象是区间里并排的候选分钟,不是四张卡上的支持度数字。 | +| 候选 A 预测下一次事业变动更可能在 2027 年 3 月附近。 | 每列用服务器拼好的一行时段;没有窗就写「未来一年没有明显的时段」;没算出来写「这一分钟还没对照」。 | 窗口按候选分钟各算,模型不写。不得把「没算」说成「没有窗」。 | | 「再补一件经历」后卡片消失、输入框上方空白 | 需要补经历时继续在输入框说下一件;交付卡不再提供「再补一件经历」按钮。 | 交付卡只负责选分钟。 | | 采用后会拿盘外核对来验证。 / 已采用 04:53 · 范围 … / 改选 / 之后新建对话即按此时间排盘。 | 没有核对题:已采用 04:53,新建对话即按这个时间排盘。有核对题:前事核对到这里。之后新建对话即按已采用时间排盘;对不上随时改选。 | 采用状态在该列按钮上;整张卡留着。收尾句跟卡片同一列,不单独贴左,也不回输入框上方。 | | (采用后只念代表分钟)代表分钟是 05:12。 | 这 27 分钟里,事业方向、性格底色的判断是稳定的;婚恋(D9)会随分钟变,看盘时按范围读。这不是已确认的唯一出生分钟。 | 采用后先讲区间里什么稳、什么随分钟变;两句来自服务端,不是模型编的。 | diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css index daff8b5d..2fc49a5e 100644 --- a/frontend/src/app/globals.css +++ b/frontend/src/app/globals.css @@ -2958,6 +2958,17 @@ input:not([type="radio"]):not([type="checkbox"]):not([class^="ant-"]):not([class border-radius: 0; background: transparent; } +.rectification-board__chart { + margin: 0; + min-width: 0; +} +.rectification-board__chart .personal-report-chart-svg { + margin-top: 0; +} +.rectification-board__chart .personal-report-chart-cell.is-changed { + fill: color-mix(in srgb, var(--color-action) 14%, transparent); + stroke: var(--color-action); +} .rectification-board .technique-audit { margin-top: 0; padding-top: 0; @@ -3317,22 +3328,27 @@ input:not([type="radio"]):not([type="checkbox"]):not([class^="ant-"]):not([class } .rectification-range-delivery__likelihood, .rectification-range-delivery__block p, -.rectification-range-delivery__more { +.rectification-range-delivery__more, +.rectification-range-delivery__shared, +.rectification-range-delivery__column > p { margin: 0; color: var(--color-ink-secondary); font-size: var(--type-caption); line-height: 1.5; } +.rectification-range-delivery__shared { + display: grid; + gap: var(--space-1); + padding: 0; + list-style: none; +} +.rectification-range-delivery__muted { + color: var(--color-ink-muted, var(--color-ink-tertiary)); +} .rectification-range-delivery__block { display: grid; gap: var(--space-1); } -.rectification-range-delivery__block h3 { - margin: 0; - font-size: var(--type-overline); - font-weight: 600; - color: var(--color-ink); -} .rectification-range-delivery__accept { justify-self: stretch; min-height: 44px; diff --git a/frontend/src/components/personal-report/vedic-chart-svg.tsx b/frontend/src/components/personal-report/vedic-chart-svg.tsx index 2ef692ba..d477a754 100644 --- a/frontend/src/components/personal-report/vedic-chart-svg.tsx +++ b/frontend/src/components/personal-report/vedic-chart-svg.tsx @@ -29,6 +29,7 @@ export type VedicChartModel = NorthIndianChartModel; interface VedicChartSvgProps { chart: NorthIndianChartModel; ariaLabel: string; + highlightHouseNumbers?: ReadonlySet; } function buildRetrogradeSet(chart: NorthIndianChartModel): Set { @@ -82,7 +83,7 @@ function OccupantStack({ ); } -export function VedicChartSvg({ chart, ariaLabel }: VedicChartSvgProps) { +export function VedicChartSvg({ chart, ariaLabel, highlightHouseNumbers }: VedicChartSvgProps) { const chartId = useId().replace(/:/g, ""); const linesByHouse = new Map(); for (const house of chart.houses) { @@ -117,7 +118,7 @@ export function VedicChartSvg({ chart, ariaLabel }: VedicChartSvgProps) { {ordinal !== null && ( - +
+ +
+
+ 本命宫位表 + +
{result && } {savedStatus === "accepted" && result && result.techniqueAudit.length > 0 && ( @@ -112,8 +127,10 @@ function RectificationBoardBody({ )} {(scoringMinutes.length > 0 || displayMinutes.length > 0) && ( -
-

换升时刻

+
+ + 换升时刻 · {grouped.length} 个 + {scoringMinutes.length > 0 && (
    {scoringMinutes.map((row) => { @@ -157,7 +174,7 @@ function RectificationBoardBody({
)} -
+
)} {contrast && (
diff --git a/frontend/src/components/rectification-range-delivery.tsx b/frontend/src/components/rectification-range-delivery.tsx index 15d21bbd..c64c5e4b 100644 --- a/frontend/src/components/rectification-range-delivery.tsx +++ b/frontend/src/components/rectification-range-delivery.tsx @@ -5,13 +5,14 @@ import { RECTIFICATION_USER_COPY, REPRESENTATIVE_MINUTE_DISCLAIMER, rangeDeliveryEventCopy, - rangeDeliveryFitCopy, - rangeDeliveryWindowCopy, - rangeDeliveryWorstCopy, } from "@/lib/rectification-agentic/user-copy"; import type { RangeDeliveryProjection } from "@/lib/rectification-agentic/v9/divergence-panel"; import { RectificationVerificationReport } from "@/components/rectification-verification-report"; +function columnHasTraits(column: RangeDeliveryProjection["columns"][number]): boolean { + return Boolean(column.traits.d9 || column.traits.d10 || column.traits.nakshatra.length > 0); +} + export function RectificationRangeDelivery({ result, acceptingCandidateId, @@ -36,18 +37,25 @@ export function RectificationRangeDelivery({ : RECTIFICATION_USER_COPY.rangeDeliveryTitle; const markdown = delivery?.verification_markdown ?? result.verificationReportMarkdown; + const sharedTraits = delivery?.shared_traits ?? []; return (
{title}
+ {sharedTraits.length > 0 ? ( +
    + {sharedTraits.map((line) => ( +
  • {line}
  • + ))} +
+ ) : null}
    {columns.map((column) => { const adopted = selected === column.time; const adopting = acceptingCandidateId === column.candidate_id; - const worst = rangeDeliveryWorstCopy(column.fit.worst); - const windows = column.windows.slice(0, 2); + const missing = column.fit == null || column.windows == null; return (
  • -
    -

    {RECTIFICATION_USER_COPY.rangeDeliveryTraitsHeading}

    - {column.traits.d9 ?

    {column.traits.d9}

    : null} - {column.traits.d10 ?

    {column.traits.d10}

    : null} - {column.traits.nakshatra.map((line) => ( -

    {line}

    - ))} -
    -
    -

    {RECTIFICATION_USER_COPY.rangeDeliveryFitHeading}

    -

    {rangeDeliveryFitCopy(column.fit)}

    - {worst ?

    {worst}

    : null} -
    -
    -

    {RECTIFICATION_USER_COPY.rangeDeliveryWindowsHeading}

    - {windows.length > 0 - ? windows.map((window) => ( -

    {rangeDeliveryWindowCopy(window)}

    - )) - :

    {RECTIFICATION_USER_COPY.rangeDeliveryNoWindow}

    } -
    + {columnHasTraits(column) ? ( +
    + {column.traits.d9 ?

    {column.traits.d9}

    : null} + {column.traits.d10 ?

    {column.traits.d10}

    : null} + {column.traits.nakshatra.map((line) => ( +

    {line}

    + ))} +
    + ) : null} + {missing ? ( +

    + {RECTIFICATION_USER_COPY.rangeDeliveryNotCompared} +

    + ) : ( + <> +

    {column.fit_line}

    +

    {column.window_line}

    + + )}