Skip to content

feat(goals): 每日维护自动复核内部目标与可能重复补判(G 线,G-C1) - #142

Merged
leafliber merged 7 commits into
mainfrom
feat/goal-auto-review
Nov 12, 2026
Merged

leafliber merged 7 commits into
mainfrom
feat/goal-auto-review

Conversation

@leafliber

@leafliber leafliber commented Nov 11, 2026 •

Copy link
Copy Markdown
Member

概要

全自动阶段 G 线(规格 G,DECISIONS 2026-11-10「全自动阶段计划」与 2026-11-11 条目;设计 15.3—15.5):

  • G1:每日维护按明确依据自动完成或放弃学习产生的内部普通目标。
  • G2:每日维护补判“可能重复”的目标对。
  • 两个开关 goal_auto_review_enabled、goal_duplicate_auto_judge_enabled 默认关闭,新库和旧库都不开。
  • 目标页、维护报告和设置页的界面,以及确定性计分的评测工具 evals/goal_review_eval/。

本 PR 不调用真实模型,不改 D6 提示词、冻结语料、设计文档和 DECISIONS.md。第二轮按规划者审查意见修改,见文末“第二轮修改”。

实现

  • 迁移 039(039_goal_auto_review.sql)新增:

    • goal_auto_reviews:G1 判断记录,带指纹唯一约束。
    • goal_auto_review_evidence:自动关闭所依据的候选消息,供消息清理保护。
    • goal_duplicate_judgments:G2 判断记录,带指纹;自动合并另存 merge_record_json,以及 undone_at、undone_by。
    • goals.auto_review_after_message_id:重开时记录的消息水位。

    迁移不写设置,也不改任何现有数据。

  • G1:

    • 提示词 goal_review_auto_v1.md(SHA-256 318545babb070ce20e8dc3a8d264050383ac1ac65525e6160e7e3e8812405c04),走 chat 用途,purpose 为 goal_auto_review,用 json_chat,含一次 JSON 修正。
    • 材料与第 3 节核对见 goals.auto_review_material、_review_check、apply_goal_review。核对失败时保持未结束并记固定原因:decision_open、invalid_output、content_rejection、evidence_empty、evidence_outside_material、evidence_only_sources、evidence_missing、evidence_not_after_creation、evidence_sender_not_involved、evidence_kind_not_allowed。
    • 关闭时沿用状态变更的提醒处理,写目标快照(动作 auto_review,原因 auto_completed 或 auto_abandoned),操作记录的 actor 为 maintenance。
  • G2:

    • 把 Goals.review 中的材料组装抽成 dedup_review_material,判断和陈旧检查抽成 dedup_review_judge、dedup_review_decision、dedup_review_stale。创建时复核和维护 G2 都调用这几个函数,因此 goal_dedup_probe 在 60 秒预算下测到的就是维护路径的判断。
    • 有测试锁定:两条路径都调用 dedup_review_material,G2 发给模型的内容等于它的输出,系统提示是 D6。
    • 每对预算 60 秒,走 goal_dedup_judge 用途。
  • 维护:目标阶段的确定性项目做完后,依次执行 G2 和 G1。

    • 开关在接受维护请求时固定(settings_json.goal_auto),执行时当前设置也必须开启。
    • 模型调用都在事务外;每项在一个短写事务里核对修订号,并写结果、快照、报告项和带游标的计数。
    • 失败(超时、429、暂停、每日上限)不记指纹,下次再试;用途不可用时本轮提前停止。
  • 管理接口:

    • POST /admin/api/goals/{id}/reopen:重开每日维护自动关闭的目标。
    • POST /admin/api/goal-duplicate-judgments/{id}/undo:撤销自动合并。
    • GET /admin/api/goal-auto-actions:分页列出自动处理记录。
    • 目标详情增加 auto_review 和 auto_closed,列表增加 auto_closed,都只在管理端。宿主 /api/v1 的字段不变,有测试锁定。
  • 界面:

    • 目标详情有“每日维护自动复核”,显示依据消息,可重开或撤销合并。
    • 目标页有可展开的“每日维护自动处理的目标”,展开前不发请求,可重开或撤销合并。
    • 维护报告有“目标自动复核”分区(计数含“预算用尽”),可直接重开或撤销合并,另有“目标复核保持不变”分组。
    • 设置页“目标与提醒”新增两个开关;Operations.tsx 补了新操作的中文名。构建产物已提交。

第二轮修改(规划者审查 4393c10)

  1. 目标自己的来源不能当依据:合格依据只能来自候选消息。goal_sources(包括合并时继承来的)一律不算,即使晚于创建时间,这种情况记 evidence_only_sources。提示词里来源的表述改为“目标的出处,不是完成或放弃的依据,与时间无关”。
    • 测试 test_sources_inherited_by_a_merge_are_not_evidence_even_when_later(拦截+通过)、test_own_source_is_never_evidence_but_a_later_candidate_alongside_it_is。
    • 时间和发送者两条代码核对,另用伪造材料做双向测试:test_code_checks_reject_early_and_uninvolved_evidence_even_in_a_crafted_material。
  2. G2 遵守宿主令牌范围:组材料、陈旧检查和合并都按宿主目标的 host_scope_json 处理。一对中有宿主目标、而另一方所在入口不在该令牌范围内时,不调用模型、不合并,撤销标记并记 host_scope_not_merged。
    • 测试 test_host_goal_is_never_merged_outside_its_token_scope 走审查给的自然流程:I2 并入 I 后产生 (I,H),验证 H 不会被并入范围外的 I。
    • 对照测试 test_host_goal_merges_when_the_partner_is_inside_its_scope。
  3. 每日 token 上限:
    • G1 每次调用前按整理的做法检查 health.check('chat','learning')。G2 调用前检查 goal_dedup_judge 用途,这个用途本身就受上限约束。
    • 达到上限即停止本轮,不发请求、不记指纹、不写失败项。
    • 测试 test_daily_token_limit_stops_g1_without_requests_or_fingerprints、test_daily_token_limit_also_stops_g2,都覆盖上限用尽和未用尽两种情况。
  4. 合并保留重开水位:_merge 让存续目标取双方 auto_review_after_message_id 的较大值。
    • 测试 test_merge_keeps_the_reopen_watermark:G1 关闭 X,管理员重开 X,G2 把 X 并入 Y,同一次维护里 G1 不能用旧依据关闭 Y。另以没有水位的情况作对照。
  5. 中断续跑计数累加:计数和游标写在 progress_json.goal_auto,与每项结果同事务提交;续跑从游标继续并累加,报告里不显示游标。
    • 测试 test_report_counts_accumulate_across_an_interrupted_run。
  6. 候选消息不再挤掉最新的撤回:最多 30 条中固定保留发送者合格的最新 10 条,其余按规格顺序补足。指纹改用发送者合格的最新消息 ID,不只看材料内的最大 ID。
    • 测试 test_newest_qualified_messages_are_kept_when_priority_messages_fill_the_material:高优先级消息已满 30 条时,另一入口、不含关键词的“还没弄完”仍进入材料,新的合格消息会触发重判。
    • 测试 test_priority_order_still_fills_beyond_the_newest_ten。

对规划者决定的落实:

  • 调用上限:G1 100、G2 50 保持常量,超出时计入 budget_exhausted,界面显示为“预算用尽”。测试 test_call_cap_reports_budget_exhausted_and_the_rest_waits。
  • 撤销自动合并:只针对每日维护的自动合并。合并时在 merge_record_json 中记下存续目标的截止时间、提前量和重开水位,以及来源、涉及人、承诺记忆、依据标注、重定向、可能重复关系和待取提醒的 ID,不存正文。
    • 撤销时核对存续目标的修订号,合并后被修改过就返回 409。
    • 撤销内容:
      • 恢复被并入目标(清空 merged_into,被挪走的待取提醒退回,提醒文字按它自己的正文恢复);
      • 存续目标退回合并前的字段和关系;
      • 删除合并时新建的可能重复关系,恢复原来的关系;
      • 重新安排两边的提醒计划;
      • 这一对记为驳回,以后不再自动合并。
    • 接口沿用管理员会话、CSRF,并写 admin_operations(goal_merge_undo)和目标快照(merge_undo)。
    • 测试:
      • 服务层:test_undo_restores_both_goals_and_never_merges_the_pair_again、test_undo_refuses_when_the_survivor_changed_after_the_merge、test_only_automatic_merges_can_be_undone、test_undo_returns_moved_reminders_to_the_restored_goal、test_undo_removes_relations_the_merge_copied_and_restores_watermarks。
      • 接口:test_undo_auto_merge_endpoint_lists_state_and_requires_csrf。
      • 前端:三个用例。
  • 依据消息保护:memory_ops.message_references 新增一处检查:goal_auto_review_evidence 中关闭依据的候选消息不被 30 天消息清理删除,依据记录存在且目标存在时一直保护。这是 memory_ops.py 中唯一的改动。只读模型给出的、未用于关闭的引用不受保护。测试 test_closure_evidence_is_protected_from_message_retention,用真实的消息清理验证一条被保护、一条被清理。
  • 操作记录页:在 Operations.tsx 补了新操作名的中文显示,只改标签映射。

第三轮修改(规划者复审 0085ea8)

  1. G1 不再每天全部重判,超上限的目标不会一直轮不到:
    • “我”的消息只在这个目标的对话里算候选,也只在这里影响指纹,即目标所在入口,以及涉及的人发过言的入口。涉及的人自己的消息仍按可见范围取。
    • 处理顺序改为最久未复核优先:从未复核的最先,其余按本次运行之前最后一次判断的时间升序。本次运行自己的判断不参与排序,续跑时游标按(时间, ID)继续。
    • 测试 test_role_messages_in_unrelated_entries_do_not_cause_daily_rejudgment:按 probe_rejudge 的场景每天只在无关入口加一条 self_output,不再重判;在本入口回复就会重判。
    • 测试 test_role_messages_count_where_the_goal_people_speak:涉及的人发过言的群里,我的回复算候选;无关入口的不算。
    • 测试 test_call_cap_leftover_goal_is_first_in_line_next_time:三个目标、上限 2,第三个在下一次维护中被复核,之后按最久未复核轮换。
  2. G2 宿主范围只拦一个方向:只有宿主目标作为被并入的一方、要并进它令牌范围外的目标时才拦,这时不调用模型、不合并,保留可能重复标记,记 kept/host_scope_not_merged,按指纹不再重复处理。内部目标并进宿主目标照创建时规则调用模型。
    • 测试 test_internal_goal_merges_into_an_earlier_scoped_host_goal_as_at_creation:按 probe_scope_block 的场景,正常判断并合并进宿主目标。
    • 测试 test_host_goal_is_never_merged_outside_its_token_scope:反方向被拦,标记保留,第二次维护不再处理。
  3. 撤销合并不取消存续目标自己的提醒:合并后发布的待取提醒,只取消因合并带来的字段而产生的那些,即截止时间不同,或者早于自己提前量、而自己的提醒时刻还没到的;后一种情况由新计划按时重发。
    • 测试 test_undo_keeps_the_survivors_own_reminders_and_cancels_merged_ones:按 probe_undo_reminder,存续目标自己的临近提醒撤销后仍待取;因被并入目标的截止时间而发布的提醒被取消。
  4. 本轮 G2 刚合并的存续目标,G1 本轮跳过:计入 merged_this_run,下一次维护再复核。
    • 测试 test_goal_merged_into_this_run_is_reviewed_next_run。
    • test_merge_keeps_the_reopen_watermark 相应改为在第二次维护中验证。
  5. 依据保护只保护合格依据:只保护逐条通过核对的合格依据,一同被引用的不合格消息不保护。管理员重开时解除这次关闭的保护。
    • 测试 test_reopen_releases_evidence_and_unqualified_co_citations_are_never_protected:一同引用的 event 消息不受保护;重开后依据消息被真实的消息清理删除,目标来源仍按原规则保留。

本轮没有改迁移和提示词,前端只补了报告标签。

第四轮修改(规划者复审 d1e08b4)

  1. 宿主范围拦截算上已被吸收的宿主目标:较晚一方本身,以及 merged_into 链最终指向它的任一宿主目标,只要有一个的令牌范围不允许写对方入口,就按“被拦”处理:保留标记,记 kept/host_scope_not_merged,不调用模型。

    • 创建时复核没有共用这段判断,所以只修了 G2。创建时路径依靠待判目标自身的范围筛候选,并在 _merge 里核对写权限,没有检查已被吸收进待判目标的宿主目标。新目标在创建复核完成前就吸收别的目标的情况很少见,但理论上仍有这个问题,见已知限制。
    • 测试 test_absorbed_host_goal_blocks_a_merge_out_of_its_scope(probe_scope_redirect 的场景):H 并入 S 后,S 不会被并进范围外的 P;宿主访问 H 时得到 GoalMerged,指向 S,并能在范围内更新 S。
    • 对照测试 test_absorbed_host_goal_allows_a_merge_inside_its_scope。
  2. 撤销合并时被并入目标的提醒还回去:合并期间在存续目标名下发布的提醒按截止时间分三种处理:

    • 等于存续目标还原后的截止时间:保留(只有被合并带来的更早提前量提前发出、且自己的提醒时刻未到时取消)。
    • 等于被并入目标自身的截止时间:改回被并入目标名下,并按它的正文更新,不论是否已取走。
    • 两者都不是的待取提醒:取消。

    两边截止时间相同时,提醒留在存续目标,被并入目标按自己的计划重排,不补发已过的时点。

    • 测试 test_undo_returns_reminders_of_the_merged_goals_own_deadline(probe_round3 末段):A 无截止、B 有截止,合并后在 A 名下发出的临近提醒撤销后回到 B,仍待取;不属于任何一方的提醒被取消;B 只重排剩余的到期计划。
    • 测试 test_undo_keeps_reminders_on_the_survivor_when_both_deadlines_match。
    • test_undo_keeps_the_survivors_own_reminders_and_cancels_merged_ones 改为断言因被并入目标截止时间发出的提醒回到被并入目标。
  3. “涉及的人发过言的入口”只算目标创建之后:仍受本次维护的消息上界限制。

    • 测试 test_people_speaking_in_a_group_only_before_creation_do_not_widen_the_conversation:只在创建前于群里发过言时,群里我的发言不进候选、不改变指纹;涉及的人在创建后到群里发言,群里我的发言才算候选。
  4. 性能:加了 messages(sender_subject_id, entry_id, id) 索引(写在迁移 039 中),tests/test_media_retention.py 的 039 撤销步骤相应删除这个索引。

    • 改前用 EXPLAIN QUERY PLAN 看,候选查询和入口子查询都是 SEARCH m USING INTEGER PRIMARY KEY (rowid>? AND rowid<?),等于逐条扫描本次范围内的全部消息。
    • 改后(库里未跑 ANALYZE,与产品一致):
      • 候选查询的“涉及的人”一支用 messages_sender_entry (sender_subject_id=?);
      • “我”一支用 (sender_subject_id=? AND entry_id=? AND id>? AND id<?);
      • 入口子查询用 (sender_subject_id=?);
      • goal_sources 用覆盖索引。
    • 产品代码不运行 ANALYZE。

第五轮修改(规划者复审 080b618)

撤销自动合并时,不再改动任何已有提醒记录的 goal_id 或正文,以免宿主游标已越过的记录被改挂后再也拉不到:

  • 已取走的提醒:保持原样。
  • 属于被并入目标 B 的待取提醒:包括截止时间等于 B 自身截止时间的,以及合并前原属 B、被合并挪走的(规划者已接受这处扩展)。取消这些记录;如果 B 按自己的提前量计算的临近时刻已过,为 B 新建一条立即可取的提醒(新 id),还没到就交给 B 的新计划按时发。
  • 存续目标一侧:规则不变。
  • 测试:
    • test_undo_never_rewrites_existing_reminders_and_b_gets_exactly_one_on_time[未取走/已取走],即 probe_undo_dup 的两个场景。未取走时原记录保持在存续目标名下并取消,B 在自己的临近时刻得到唯一一条待取提醒;已取走时那条记录的 goal_id、正文和状态都不变。
    • test_undo_reissues_immediately_when_bs_own_warning_time_has_passed:B 的临近时刻已过时,撤销即新建一条。
    • 另有三个旧测试改为断言原记录取消、B 得到新 id 的提醒。

第六轮修改(规划者复审 9f90290)

第五轮的逐例修补仍有两个边界会丢提醒:合并时保留的提醒被宿主取走后撤销,A 的同阶段提醒被恢复而 B 丢了提醒;两边截止时间相同时 B 丢了临近提醒(probe_undo_round5)。撤销时的提醒处理因此改为一条简单规则,宁可多发一次,不丢:

  • 不动已有记录:已有提醒记录一律不改挂、不改正文,已取消的不再恢复为待取,已取走的不动。
  • 取消两边待取提醒:在撤销的同一事务里,取消存续目标 A 和被并入目标 B 名下当前所有待取的提醒。
  • 按当前阶段补发:两边都先取消旧计划,再按还原后的字段重排,各自按当前所处阶段补发至多一条新提醒(新 id):
    • 临近时刻已过、尚未到截止:补一条临近提醒;
    • 已过截止:一律补一条。过期提醒开启时沿用过期文案和次日计划;关闭时补一条“目标已到期”提醒,不排次日计划(第七轮,见 probe_undo_round6);
    • 临近时刻未到:不补,交给新计划。
  • 第五轮中“恢复为待取”和“按分支判断是否补发”的代码已删除。
  • 测试:用共同的断言检查以下几点:已有记录的 goal_id 和正文不变,相关的待取提醒都被取消、没有记录被恢复,每个目标至多新建一条,两个目标都不丢当前阶段的提醒。
    • probe_undo_round5 两段:test_undo_round5_after_the_kept_reminder_was_taken_both_goals_get_their_stage(同时验证宿主游标之后能拉到两个目标的新提醒)、test_undo_round5_equal_deadlines_merged_before_the_warning;
    • probe_undo_dup 两个场景:test_undo_never_rewrites_existing_reminders_and_b_gets_exactly_one_on_time[未取走/已取走]、test_undo_reissues_immediately_when_bs_own_warning_time_has_passed;
    • probe_round3 末段:test_undo_round3_reminder_fired_under_a_for_bs_deadline;
    • 另有 test_undo_reissues_the_current_stage_for_both_goals_of_each_merge、test_undo_with_equal_deadlines_reissues_for_both、test_undo_past_the_deadline_issues_one_overdue_reminder_unless_turned_off、test_undo_past_the_deadline_respects_turned_off_overdue_reminders(过期提醒关闭时补“已到期”提醒、不排次日计划),以及 test_undo_round6_survivor_past_its_deadline_gets_its_stage_either_way[关闭/开启](probe_undo_round6 两种设置)。

评测工具

uv run python evals/goal_review_eval/run.py --corpus <JSON> --out <仓库外目录>,默认语料为冻结的 goal_review_v1.json。

  • 运行方式:每例使用隔离数据库和固定时钟,原样写入数据,走真实的维护目标阶段,只开 G1。
  • 标签隔离:expected、reason、category 在写入前剔除,有测试锁定,也检查请求中不出现标注文字。
  • 计分:全部确定性,包括误关闭(含完成与放弃方向相反)、宿主或管理员目标被关闭数、识别率、按类别明细和 gates。
  • 有效性:call_counts 统计超时、429、截断、无效调用和执行错误,报告给出 valid。出现超时、429 或复核失败时停止,整次无效。
  • 假模式:--fake 用 MockTransport,不读模型配置,不访问网络。
  • G2 测量:用现有 goal_dedup_probe --method D6(默认预算 60 秒)。

保守选择与偏离

  1. 重开水位:重开后只把更新的消息当候选,否则同一依据会在第二天把目标再次关上。合并时取较大水位,见上面第 4 条。
  2. 吸收过宿主或管理员目标的内部目标不进入 G1。
  3. 候选消息的可见范围:只取可见范围不窄于目标的入口里的消息。
  4. 不保存模型文字理由:只保存判断、依据 ID 和固定原因。
  5. G2 合并条件:只有创建时规则会合并到这一对中较早的一方时才合并。在这个条件下含管理员目标时撤销标记;仍有歧义时保留标记(same_ambiguous)。
  6. G2 的跳过条件:目标去重判断关闭时不运行;任一方仍有创建时去重任务时跳过该对。询问对也会处理。
  7. 开关只在显式保存过才写入运行设置。
  8. G1 无效输出或内容拒绝:记指纹、保持未结束。
  9. 评测只写入 now 之前的消息。
  10. 报告阶段名仍为“目标依据复核”。
  11. tests/test_media_retention.py:补了撤销 039 的一步,规划者已接受。
  12. 设置测试:设置接口 goals 分区多两个键,相应更新了三个设置测试的期望值。

已知限制

  • 撤销会因后续修改失效:存续目标在合并后有任何修订(包括管理员编辑)时,撤销返回 409,与整理撤销的口径一致。
  • 撤销可能多发一条提醒:撤销时取消两边的待取提醒,再按当前阶段各补发至多一条。宿主可能因此对同一阶段多收到一条,这是规划者接受的代价。已取走的提醒不改动。
  • 看不到维护开始后的消息:写回只核对修订号,维护开始后才到的消息本次看不到,靠管理员重开兜底。
  • G2 指纹偏严:G2 指纹包含全部已观察目标的修订号,uncertain 的一对会被多判。
  • 大群里每日重判仍可能接近上限:涉及的人在大群里天天发言时,每天仍可能有新的合格消息,重判可能接近上限。
  • 撤回仍可能被挤掉:合格消息很多时,较早的撤回仍可能在固定保留的最新 10 条之外被挤掉。
  • 创建时复核没检查已吸收的宿主目标:创建时复核没有“已吸收宿主目标被带出范围”的检查(G2 已修),规划者另行安排后续任务。
  • 用旧 head 建的开发库需要重建:迁移 039 在本 PR 内改写过,用旧 head 打开过的开发或测试库需要重建,不影响任何正式数据。

测试(head d5f3f0c)

  • 定向测试:目标、合并、去重、评测、media_retention 相关,共 227 个,全部通过。
  • Python 3.13 全量:5952 个测试,5951 个通过;唯一失败的是已知的 test_persona_streaming.py::test_future_deadline_closes_stream_worker_and_preserves_shared_client(它在未改动的 origin/main 上同样失败,与本 PR 无关,规划者另行处理)。
  • Python 3.12 全量(uv run --locked --isolated --python 3.12 pytest):5951 个通过,失败的只有同一个用例。
  • 前端:第四到第六轮没有改动,第二、三轮的 npm test(478 个)和 build 结果仍然有效。
  • uv build:通过。
  • 迁移 039 的 SHA-256:33c66256c0b9b060545e3f6b036580b187f7699bf683c99e7849cb6174e131e9。提示词的 SHA-256:318545babb070ce20e8dc3a8d264050383ac1ac65525e6160e7e3e8812405c04。这两轮都没有改动。

各轮修改对应的新测试见上面各轮的修改说明。

本 PR 不调用真实模型。真实评测和隐藏集由规划者安排。

- G1:学习产生的内部普通目标按明确依据自动完成或放弃;新提示词 goal_review_auto_v1(chat 用途),
  代码核对依据在材料内、晚于创建、来自涉及的人或“我”、类型可用,修订号不变才关闭;
  指纹(目标修订号+材料内最新消息 ID)去重,失败下次再试,自动关闭可重开。
- G2:可能重复对用与创建时复核共用的 dedup_review_material 和 D6 提示词补判,每对 60 秒;
  same 合并到较早一条(管理员目标不合并,撤销标记),different 撤销标记,uncertain 保留并记指纹。
- 迁移 039:goal_auto_reviews、goal_duplicate_judgments、goals.auto_review_after_message_id。
- 开关 goal_auto_review_enabled、goal_duplicate_auto_judge_enabled 默认关闭。
- 目标页、维护报告、设置页界面与构建产物;evals/goal_review_eval 确定性计分。
- G1 目标自己的来源(含合并继承的)不算依据,记 evidence_only_sources;提示词来源表述改为与时间无关。
- G2 按宿主目标的令牌范围组材料与合并;跨范围的一对不调用模型、不合并,撤销标记(host_scope_not_merged)。
- G1/G2 调用前检查用途暂停与每日 token 上限,达到即停止本轮、不记指纹。
- _merge 让存续目标取双方较大的重开水位。
- 维护计数与游标同事务写入,中断续跑累加;超出调用上限记 budget_exhausted。
- 候选固定保留最新 10 条合格消息,指纹用合格的最新消息 ID。
- 自动合并可撤销(POST /admin/api/goal-duplicate-judgments/{id}/undo),存续目标合并后被改则 409;撤销后该对驳回。
- 关闭依据消息写入 goal_auto_review_evidence,memory_ops.message_references 据此保护其不被消息清理删除。
- 界面:撤销合并、预算用尽、操作记录中文名;构建产物。
- G1 候选与指纹中“我”的消息只取目标所在入口和涉及的人发过言的入口;按最久未复核优先处理,上限截断的目标下次排前。
- G2 只拦宿主目标被并入其令牌范围外的目标:不调用模型、不合并,保留标记(kept/host_scope_not_merged);内部目标并入宿主目标照创建时规则判断。
- 撤销自动合并只取消因合并带来的字段而发布的待取提醒,存续目标自己的提醒保留。
- 本次维护里 G2 刚合并的存续目标,G1 留到下一次维护(merged_this_run)。
- 依据保护只保护逐条通过核对的合格依据;管理员重开时解除这次关闭的保护。
- G2 范围拦截检查较晚一方及所有已并入它的宿主目标;只修 G2,创建时复核未共用该判断。
- 撤销合并:等于被并入目标自身截止时间的提醒改回其名下并按其正文更新;属于存续目标的保留;其余待取提醒取消。
- G1 中“涉及的人发过言的入口”只算目标创建之后。
- 迁移 039 增加 messages(sender_subject_id,entry_id,id) 索引;test_media_retention 的 039 撤销同步删除该索引。
- 已取走的提醒保持原样;存续目标一侧规则不变。
- 截止时间等于被并入目标自身截止时间、或合并前原属被并入目标的待取提醒:取消该记录;被并入目标按自身提前量的临近时刻已过则新建一条立即可取的提醒(新 ID),未到则由其新计划按时发出。
- 已有提醒记录不改挂、不改正文、不恢复,已取走的不动。
- 取消存续目标与被并入目标名下全部待取提醒,两边按还原后的字段重排;临近时刻已过且未到截止补一条临近提醒,已过截止按过期提醒设置补一条,未到不补。
- 删除恢复为待取与按分支补发的代码,更新测试并补 probe_undo_round5、probe_undo_dup、probe_round3 场景。
@leafliber
leafliber merged commit dc816fb into main Nov 12, 2026
1 check passed
@leafliber
leafliber deleted the feat/goal-auto-review branch November 12, 2026 01:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant