Skip to content

automation: 组合情报「无实质变化」判定有 3 个误判口子,另有 1 处过严(#134 遗留) #185

Open

Description

@kbkb628

背景:#134(补齐组合情报"无实质变化"运行路径)已合并。审查时发现判定逻辑存在方向相反的偏差,建议单独跟进。

会把「有变化」误判成「无变化」(风险方向)

  1. NaN 不落 failure:packages/shared/src/automation/runner.ts:112 对 priceMovePct 只查 === undefined,脏数据产生的 NaN 不落 failure,而 NaN >= 阈值 为 false(runner.ts:295-299)→ 被计成 no_material_update。
  2. 探针异常静默降级:runner.ts:273-292 的 calendarProbe/diff 探针异常时静默降级为"无信号",所以 failures.length === 0 并不等于"确实没有事件"。
  3. 新鲜度判断缺失:Quote.timestamp 未参与判断,scopeSnapshot.sourceFetchedAt(packages/core/src/automation.ts:40-47)只写不读 → 无法区分"新取的旧数据"。

反方向:过于严格

failures 把通知失败/研究失败也算进去(runner.ts:122,130),于是一次 OS 通知失败就会让整轮变成 incomplete,新路径在生产可能长期走不到,日报的 quiet 段会静默丢符号。

测试缺口

本 PR 新增的两个 catch(runner.ts:101-106 evaluation failed、208-211 scope unavailable)、NaN priceMovePct、以及"通知失败 → incomplete"都没有测试;RuleCard 只测了 no_material_update,没测 material_update/incomplete。

建议

  • priceMovePct 用 Number.isFinite 判定;
  • 探针异常至少留一条 failure 或单独的 degraded 标记,让"无信号"和"探测失败"可区分;
  • 考虑把通知/研究失败从"决定 material 与否"的 failures 里拆出来,避免 noisy 通知把整轮降级。

Activity

  1. xiaodu55 commented on Sep 23, 2026

    @xiaodu55
    Contributor

    /claim

  2. github-actions commented on Sep 23, 2026

    @github-actions

    @xiaodu55 已认领该 Issue,并已自动设为 Assignee。提交 PR 时请在描述中写 Closes #185。

  3. xiaodu55 commented on Sep 24, 2026

    @xiaodu55
    Contributor

    #185 第 3 点(新鲜度语义)设计提议——#188 已收口前两个误判口子和过严问题,本条单独讨论,定案后我再提实现 PR。

    现状:runner.ts 的 fetchQuote 只取 result.data,把 ProviderResult.provenance(含 stale: boolean 和 fetchedAt)直接丢弃;scopeSnapshot.sourceFetchedAt 也是只写不读。所以"新取到的旧数据"目前在判定里完全不可见。

    一个关键观察:provider 层其实已经有 staleness 判定——provenance.stale 由 Provider/Router 自己的口径维护,runner 不必自造"多旧算旧"的墙钟阈值。方案据此分两条:

    • 方案 1(fail-closed,推荐起点):provenance.stale === true 的 quote 记为评估类 failure({{symbol}}: quote stale,沿用 fix(automation): 收紧无实质变化判定的三个误判口子,投递失败不再降级整轮运行 #188 的 evaluationFailures 机制 → 整轮 incomplete,绝不当"无变化");portfolio scope 的 sourceFetchedAt 超过规则执行时刻一个可配置上限(如 24h)→ scope failure。阈值集中放常量并在 PR 里给出取值依据。
    • 方案 2(仅可见性):AutomationRun 增加可选 staleQuotes: string[] / degraded: boolean,stale 数据照常参与判定但留下可观察痕迹,不改变 outcome;等产品定调后再收紧为方案 1。

    想请维护者拍板两点:① 用 provider 的 provenance.stale 口径,还是 runner 自定墙钟阈值?② stale 时 fail-closed(方案 1)还是先只做可见性(方案 2)?定了我就提实现 PR。

  4. github-actions commented on Oct 18, 2026

    @github-actions

    @xiaodu55 这个 Issue 已认领超过 7 天,目前没有发现关联的 open PR,也没有看到最近 7 天的进度更新。

    如果仍在推进,请在 3 天内 留一条简短进度说明(包括正在等待的前置依赖也可以);如果已经有 PR,请贴出链接。若 3 天内没有回应,认领会自动释放,方便其他贡献者接手。

  5. removed
    claimedClaimed by a contributor and currently in progress
    on Oct 21, 2026
  6. github-actions commented on Oct 21, 2026

    @github-actions

    @xiaodu55 在提醒后 3 天内没有进度回应,且仍未发现关联的 open PR;本次认领已自动释放。Issue 保持开放,可以重新认领。

  7. 2Zest commented on Oct 26, 2026

    @2Zest

    我想接手第 3 点“新鲜度语义”的后续,但不重复 #188 已合入的 NaN、探针异常和投递失败修复。

    当前实现会丢弃 ProviderResult.provenance.stale,而 scopeSnapshot.sourceFetchedAt 只写不读;因此“新获取的陈旧数据”可能被当作无实质变化。请维护者确认采用哪种产品口径:

    1. stale === true 或超出允许时限时,整轮标记为 incomplete;
    2. 保留现有判定结果,但记录 degraded/staleQuotes 供 UI 与追踪展示。

    确认后我会只实现选定策略,补充 stale quote、过期 scope、正常新鲜数据的回归测试,并附完整验证报告。

  8. helsome commented on Oct 26, 2026

    @helsome
    Owner

    @2Zest 可以按方案 1 推进第 3 点的新鲜度语义,范围不包含 #188 已合入的修复。

    口径确认:

    • 关键行情或持仓范围证据已过期时,整轮标记为 incomplete,不能据此得出“无实质变化”。降级标记可以补充说明原因,但不能替代这个判定。
    • 行情沿用 Provider/Router 的 provenance.stale 口径,runner 不另造统一的墙钟阈值。正常的数据源延迟、休市日与真正过期的数据需要区分。
    • 持仓范围的 sourceFetchedAt 单独定义时效规则,并说明依据;不要直接统一套用 24 小时。

    请补充 stale quote、过期 scope、正常新鲜数据和休市边界的回归测试,并在 PR 中附验证报告。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions