Files
reader/TODO.md
T
root 590d050218 keyword cleanup: v2 engine, alias rule layer, LLM semantic suggestions
- build_review_bundle.py: 新增 _compute_percentile/_compute_growth,
  候选池从固定阈值改为百分位排名 + 增速因子 (v2 policy)
- term_cleanup_policy.json: 升级 v2 schema
- generate_term_cleanup_suggestions.py: 新增 _prepare_alias_suggestions,
  规则层输出 alias (大小写/单复数/分词变体)
- generate_term_cleanup_semantic_suggestions.py: 新增 LLM 语义建议脚本
  (DeepSeek API, 产出 semantic alias/stopword/promote)
- SKILL.md: 更新为 5 Phase 工作流程
- 首轮清洗 apply: interest 54, aliases 17组, stopwords 17个
- docs/design/keyword-cleanup-flow-overview.md: 流程文档
- plans/: 引擎设计方案
2026-05-14 17:17:49 +08:00

14 KiB
Raw Blame History

TODO - Reader MCP 正式化

本文件用于架构与 Codex 协作同步。

规则:

  • TODO = 未开始
  • DOING = 正在进行
  • DONE = 已完成
  • 每次只允许一个最高优先级主任务处于 DOING

0. 协作约束

开始编码前必须阅读:

  1. README.md
  2. docs/README.md
  3. docs/openclaw/README.md
  4. docs/openclaw/openclaw-handoff.md
  5. docs/openclaw/openclaw-orchestration-flow.md
  6. plans/README.md
  7. plans/reader-mcp-architecture-design.md
  8. plans/reader-mcp-implementation-plan.md
  9. 本文件
  10. plans/issues/2026-04-06-reader-digest-sigterm.md

1. 当前主任务

[DONE][P0] 建立 run-state 运行态基础设施

目标:

  • 给 freshrss pipeline 引入正式 run state
  • 即使失败或中断,也能留下明确运行真相

要求:

  • 新增 RunState / StageState / ArtifactRecord 模型
  • 在 outputs/freshrss/rerun/<run_id>/run-state.json 持久化
  • 至少覆盖以下 stages:
    • fetch_feed
    • extract_articles
    • generate_summaries
    • apply_filters
    • build_delivery_payload
    • write_run_report
  • 失败时写入失败阶段与错误摘要
  • 不破坏现有输出目录兼容性

建议文件:

  • src/summary_mcp/runtime/state_models.py
  • src/summary_mcp/runtime/run_store.py
  • src/summary_mcp/workflows/...

完成标准:

  • 跑一次 pipeline 后,无论成功失败,都存在 run-state.json
  • 文件中可看出当前/最后阶段、整体状态、关键 artifacts

进展备注:

  • 2026-04-07:架构设计文档已建立;开始进入实现阶段。
  • 2026-04-07:已新增 runtime 包骨架,落地 RunState / StageState / ArtifactRecord 与文件存储接口。
  • 2026-04-07:已将 run-state.json 接入 freshrss 主流程,按阶段持续写入状态与关键 artifacts。
  • 2026-04-07:已完成成功/失败路径自检,确认 run-state.json 在两类路径下都保留且不改变既有对外返回字段。

2. 后续任务队列

[DONE][P1] 增加 MCP 状态查询接口 get_run_status

目标:

  • 可通过 MCP 查询 run 状态

要求:

  • 输入 run_id
  • 返回 status / current_stage / completed_stages / failed_stage / artifacts / recovery

完成情况:

  • 已通过 MCP 暴露 get_run_status
  • 优先读取 run-state.json;对无 run-state.json 的历史 run 兼容基于现有 run 目录与 run-report.json 推断状态
  • 返回补充了 progress / output_dir / state_source,便于 OpenClaw 稳定消费且不必手拼路径

改动文件:

  • src/summary_mcp/runtime/query_service.py
  • src/summary_mcp/runtime/run_store.py
  • src/summary_mcp/runtime/__init__.py
  • src/summary_mcp/server.py

遗留风险:

  • 历史 run 若缺少 run-state.json,其阶段状态只能基于现有目录与 run-report.json 做保守推断

[DONE][P1] 增加 MCP 查询接口 list_runs

目标:

  • 查看近期 runs

要求:

  • 支持按 workflow / status / latest_n 过滤

完成情况:

  • 已通过 MCP 暴露 list_runs
  • 支持按 workflow / status / latest_n 过滤近期 runs
  • 返回 run_id、status、progress、recovery、output_dir 与 state_source

改动文件:

  • src/summary_mcp/runtime/query_service.py
  • src/summary_mcp/runtime/__init__.py
  • src/summary_mcp/server.py

遗留风险:

  • 当前按文件系统扫描 outputs/freshrss/rerun/ 聚合,规模继续增大时可能需要再评估缓存或索引,但本阶段先保持文件系统真相

[DONE][P1] 增加 MCP 查询接口 list_run_artifacts

目标:

  • 统一列出 run 下 artifact

完成情况:

  • 已通过 MCP 暴露 list_run_artifacts
  • 对新 run 优先返回 run-state.json 已注册 artifacts,并补充 run 目录扫描发现的标准产物
  • 对历史 run 直接基于现有 run 目录发现标准产物,保持兼容

改动文件:

  • src/summary_mcp/runtime/query_service.py
  • src/summary_mcp/runtime/__init__.py
  • src/summary_mcp/server.py

遗留风险:

  • 当前仅补充扫描固定的一组标准产物;未注册且不在标准集合内的调试文件不会进入稳定 artifact 列表

[DONE][P1] 增加 MCP 结果读取接口 get_delivery_payload

目标:

  • 按 run_id 读取 delivery payload

完成情况:

  • 已通过 MCP 暴露 get_delivery_payload
  • 查询优先复用 run-state.json 已注册 artifacts,其次回退标准产物路径、run-report.json 引用和 run 目录扫描
  • 返回补充了 artifact、payload_schema_version、generated_at、delivery_date、candidate_count、stats,并保留完整 payload

改动文件:

  • src/summary_mcp/runtime/query_service.py
  • src/summary_mcp/server.py
  • src/summary_mcp/runtime/__init__.py

遗留风险:

  • 历史 run 的 payload 若既未注册也不在标准路径下,只能依赖 run-report.json 引用或目录扫描做兼容发现

[DONE][P1] 增加 MCP 结果读取接口 get_run_report

目标:

  • 按 run_id 读取 run report

完成情况:

  • 已通过 MCP 暴露 get_run_report
  • 查询优先复用 run-state.json 已注册 artifacts,其次回退标准产物路径、历史 run-report.json 固定位置和 run 目录扫描
  • 返回补充了 artifact、核心计数摘要、规范化后的关键产物路径与 keyword_index,并保留完整 report

改动文件:

  • src/summary_mcp/runtime/query_service.py
  • src/summary_mcp/runtime/__init__.py
  • src/summary_mcp/server.py

遗留风险:

  • 历史 run 的 run-report.json 内嵌路径仍保留原始绝对路径于 report 字段,当前仅在顶层摘要字段做规范化,避免改变历史文件真相

[DONE][P2] 设计并实现 resume_run

目标:

  • 基于 run-state.json 和现有中间产物继续执行

说明:

  • 先做最小可用恢复
  • 暂不追求任意 stage 任意重入
  • 设计约束已补充到 plans/resume-run-minimal-design.md
  • 第一版只支持 freshrss workflow 且仅支持有 run-state.json 的 run
  • 第一版仅考虑从最近可恢复点继续;fetch_feed / extract_articles 暂不支持恢复

进展备注:

  • 2026-04-07:已完成 resume_run minimal design 与现有 runtime/workflow/server 代码对齐分析,开始实现最小恢复链路。
  • 2026-04-07:已完成 resume_run 最小实现编码,新增 runtime 恢复服务并接入 MCP server;当前进入设计对齐与本地自检。
  • 2026-04-07:已完成 resume_run 架构对齐与本地自检;已验证 write_run_report 可恢复,且 extract_articles 会被明确拒绝恢复。
  • 2026-04-14:已补 inspect_resume_plan、artifact-first 恢复判定,以及生产模式下稳定 summary-batch / candidate-batch artifacts;当前 resume 的剩余主问题不再是恢复点判断,而是同步执行模型仍可能让 OpenClaw 恢复阶段超时。

[DONE][P1] 把 resume_run 升级为最小真异步 job

目标:

  • 解决 resume_run 在 OpenClaw → MCP 同步链路里仍可能超时的问题
  • 让恢复也具备“启动 / 轮询 / 读取结果”的正式控制面

要求:

  • 新增最小异步接口:
    • start_resume_job
    • get_resume_job_status
    • get_resume_job_result
  • 状态目录固定落到:
    • outputs/freshrss/resume_jobs/<job_id>/
  • 至少包含:
    • run-state.json
    • input.json
    • result.json(成功时)
    • job-report.json
  • 启动前必须先走 inspect_resume_plan
  • 业务执行继续复用现有 resume_service,不要重写恢复主逻辑
  • resume_run 保留为同步 debug / fallback 路径,但不再作为 OpenClaw 的默认恢复入口

完成标准:

  • 可恢复 run 上,start_resume_job 能成功返回 job_id
  • get_resume_job_status 能稳定反映恢复 job 生命周期
  • get_resume_job_result 能稳定返回 run_id、resume_from_stage、最终状态与关键产物路径
  • 恢复耗时超过单次 MCP 同步窗口时,OpenClaw 仍不会因为同步调用挂住

进展备注:

  • 2026-04-14:已落地 src/summary_mcp/runtime/resume_jobs.py 与 scripts/run_resume_job.py,新增 start_resume_job / get_resume_job_status / get_resume_job_result
  • 2026-04-14:启动前会先走 inspect_resume_plan;不可恢复 run 会在 job 输入校验阶段直接失败,不进入后台恢复执行
  • 2026-04-14:后台执行复用现有 _resume_freshrss_run(...),没有重写恢复主逻辑
  • 2026-04-14:已完成本地 synthetic 验证:write_run_report 恢复可通过 start -> poll -> result 闭环成功收敛

[DONE][P1] 单篇总结改为最小真异步 job

目标:

  • 解决 generate_article_summaries 在 OpenClaw → MCP 同步链路里易 timeout 的问题
  • 将单篇总结正式升级为可启动、可轮询、可读取结果的异步 job

要求:

  • 新增最小异步接口:
    • start_article_summary_job
    • get_article_summary_job_status
    • get_article_summary_job_result
  • 状态目录固定落到:
    • outputs/freshrss/article_summary_jobs/<job_id>/
  • 至少包含:
    • run-state.json
    • input.json
    • result.json(成功时)
    • job-report.json
  • 执行模型优先使用后台子进程,不使用线程
  • 业务逻辑继续复用 summarize_selected_articles(...),不要重写正文总结核心逻辑
  • 对 OpenClaw / reader-digest-flow 而言,异步 job 成功后应可继续接 IMA 沉淀闭环

当前进展:

  • 2026-04-10:已完成方案文档 plans/article-summary-async-job-plan.md
  • 2026-04-10:已落地最小代码骨架:
    • src/summary_mcp/runtime/article_summary_jobs.py
    • scripts/run_article_summary_job.py
    • src/summary_mcp/server.py 已新增 3 个 async job tools
  • 2026-04-10:已用真实 extracted 文件验证最小异步链路可跑通,job 能成功进入 running → success,并可读回结果
  • 2026-04-10:已补 README / OpenClaw handoff 文档,并对外统一为 start_article_summary_job / get_article_summary_job_status / get_article_summary_job_result
  • 2026-04-10:已完成聚焦自检:
    • MCP tool 注册名校验通过
    • stubbed async job 成功路径通过
    • stubbed async job 失败路径通过,error_summary 与 job-report.json 可回读

下一步:

  • 将 reader-digest-flow 正式默认路径切到 async job
  • 用真实 LLM 配置再做一次非 stub 的服务端冒烟验证

[DOING][P0] FreshRSS 主日报 run 改为最小真异步 job

目标:

  • 解决 run_freshrss_openclaw_pipeline 在正式生产链路里仍为同步 MCP 调用、易超时的问题
  • 将 FreshRSS 主日报启动路径升级为可启动、可轮询、可读取结果的异步 job

要求:

  • 新增最小异步接口:
    • start_freshrss_pipeline_job
    • get_freshrss_pipeline_job_status
    • get_freshrss_pipeline_job_result
  • 状态目录固定落到:
    • outputs/freshrss/pipeline_jobs/<job_id>/
  • 至少包含:
    • run-state.json
    • input.json
    • result.json(成功时)
    • job-report.json
  • 执行模型优先使用后台子进程,不使用线程
  • 主业务逻辑继续复用 run_freshrss_pipeline(...),不要重写日报核心逻辑
  • job 成功后结果中必须带回 run_id 与关键产物路径
  • README / handoff / OpenClaw 生产建议路径需要同步改成 async start path

当前进展:

  • 2026-04-11:问题定位完成,确认之前异步化的是 article-summary,不是主日报 run
  • 2026-04-11:已新增方案文档 plans/freshrss-pipeline-async-job-plan.md

下一步:

  • 复用 article-summary job runtime 骨架实现主日报 async job
  • 新增后台 runner 脚本
  • 暴露 3 个 MCP tools
  • 用真实 MCP 冒烟验证 start -> status -> result

[TODO][P2] 评估 rerun_stage 是否值得进入第一阶段

目标:

  • 在 resume_run 之后评估是否继续增加更细粒度补跑能力

[TODO][P2] 调整 run_freshrss_openclaw_pipeline 内部实现以复用 runtime

目标:

  • 保持外部兼容
  • 内部不再是黑箱长函数

[DONE][P1] interest/watch 候选引擎从固定阈值改为百分位排名 + 增速因子

目标:

  • 解决固定阈值(total_count>=3)不随数据量自适应的问题
  • 引入趋势信号(growth 因子),识别近期集中爆发的词
  • 支持 7 天、41 天、200 天数据量下取同样的 top 5%/5%-20% 而不需调阈值

要求:

  • build_review_bundle.py:新增 percentile 和 growth 计算函数;候选池从固定阈值改为百分位 + 增速
  • configs/term_cleanup_policy.json:升级为 v2 schema,percentile/growth 替代绝对阈值
  • 不改 generate_term_cleanup_suggestions.py 和 apply_term_suggestions.py
  • 全量跑一次对比新旧产出,确认差异合理

方案文档:plans/keyword-cleanup-interest-watch-engine-improvement.md


[DONE][P3] 更新 README / handoff / docs,明确 MCP 为正式入口

目标:

  • 把生产建议从 CLI 迁移到 MCP
  • CLI 明确降级为 debug / fallback

完成情况:

  • 已更新 README.md,补齐 reader 作为正式 MCP workflow service 的当前能力边界、推荐调用路径、已支持 tools 与最小 resume_run 范围
  • 已更新 docs/openclaw/openclaw-handoff.md,明确 OpenClaw 应优先通过 MCP 读取 run 状态与结果,不再自己拼接 reader 输出路径

改动文件:

  • README.md
  • docs/openclaw/openclaw-handoff.md

遗留风险:

  • 当前仍无独立 get_digest_brief tool;若下游确实需要该产物,仍应先通过 list_run_artifacts / get_run_report 发现,而不是写死路径

3. 记录区

已完成记录

  • 2026-04-07:新增架构设计文档 plans/reader-mcp-architecture-design.md
  • 2026-04-07:新增实施计划文档 plans/reader-mcp-implementation-plan.md
  • 2026-04-07:完成 freshrss pipeline 的 run-state 基础设施,新增 runtime 包并覆盖关键 stages 状态持久化。
  • 2026-04-14:已补 OpenClaw 文档导航、历史归档、design/notes/plans 导航,并统一当前正式口径为 async job 编排入口。

风险提醒

  • 不要在第一阶段引入复杂任务队列
  • 不要让 CLI 和 MCP 背后变成两套独立逻辑
  • 若实现偏离架构,先更新 plans/ 再改代码