这份文档用于把 TrendRadar Rust 在首版闭合后的后续拓展工作,整理成一份可连续执行、可审查、可验证的实施清单。
它不替代下面这些基线文档,而是建立在它们之上:
本文件覆盖首版内核稳定后的三类工作:
- v1.2 范围内的性能优化与能力补齐
- v1.x 范围内的工程交付增强
- v2.0 之后的生态扩展预研与落地顺序
本文件默认不要求一次性完成所有任务,而是要求后续执行时按“单任务闭环”推进。
- 每次只执行一个任务编号,避免把多个功能混成一个大改动。
- 执行前先确认受影响 crate、测试入口和文档同步点。
- 执行中优先保持
app为薄编排层,不把业务规则塞回app。 - 执行完成前至少运行一条相关验证命令,不能只写代码不验证。
- 若任务改变 crate 边界、CLI 参数、验证命令或配置契约,必须同步更新 README 和对应文档。
- 若任务仍处于设计分歧阶段,只允许补文档、fixture、测试骨架,不直接扩实现。
当前仓库已经结束“迁移收尾”口径,后续执行统一按两轮推进:
- 第 1 轮:
v2.0.0-beta,目标是“对外可用化” - 第 2 轮:
v2.1.0,目标是“真实生态接入”
第 1 轮只做下面 5 项:
D1部署标准化D2对外展示与交付文档B3热榜平台扩展B1通知渠道扩展D3长稳运行验证
第 2 轮只做下面 3 项:
C1真实远程对象存储C2真实 AI ProviderC3MCP 协议补强
下面这些内容不纳入当前两轮执行:
P3AI 翻译- 更大范围分发生态(如 Homebrew、更多安装入口)
- 全量通知矩阵与所有历史兼容层
当前增量主线按下面顺序推进:
D1部署标准化D2对外展示与交付文档B3热榜平台扩展B1通知渠道扩展D3长稳运行验证C1真实远程对象存储C2真实 AI ProviderC3MCP 协议补强
其中:
A1~A4已完成,不再作为当前主线阻塞项B2/B4/B5已在当前仓库口径下完成,不再单独拆轮执行
- 状态:
done - 目标:把当前“本地 CLI 可运行”推进到“官方部署入口明确、文档可执行、首次安装可跑通”。
- 主要范围:
Dockerfile、deploy/、README.md、docs/deployment.md - 关键输出:
- 官方
Dockerfile - 官方
docker-composeone-shot 运行入口 - 二进制部署的
systemd service/timer样例 - 首次部署文档与最小可运行配置模板
- 建议步骤:
- 先固定 one-shot 运行模型,不把容器误包装成常驻 Web 服务
- 统一
--config/--db挂载路径,避免和自动发现逻辑冲突 - 使用
--dry-run补部署自检路径 - 验证命令:
docker build -t trendradar:local .docker run --rm trendradar:local --versiondocker run --rm -v "$PWD/deploy/runtime/config.json:/config/config.json:ro" trendradar:local --config /config/config.json --dry-runcargo test --workspace- 完成标准:
- 新机器可按文档完成本地或容器启动
- Docker 与二进制部署入口均有可复制样例
- 文档中的命令与当前 CLI 行为一致
- 当前实现:
- 已补
Dockerfile、deploy/docker-compose.yml、deploy/systemd/trendradar.service、deploy/systemd/trendradar.timer - 已补
deploy/examples/config.rss.json最小示例配置与docs/deployment.md - 当前 Docker 入口使用本机 release binary 打包,优先保证 one-shot 部署路径可验证
- 验证结果:
cargo build --release -p trendradar-appdocker run --rm trendradar:local --versiondocker run --rm -v "$PWD/deploy/runtime/config.json:/config/config.json:ro" trendradar:local --config /config/config.json --dry-run
- 状态:
done - 目标:把“对外可展示的数据”收敛成一页文档,避免继续依赖内部迁移术语。
- 主要范围:
README.md、docs/、开发日志 - 关键输出:
- 平台支持、通知支持、性能对比、部署方式、运行稳定性口径
- Rust / Python 对比表
- 明确“不支持 / 暂未纳入”的边界列表
- 完成标准:
- 外部读者不需要翻开发日志即可理解产品现状
- README 首页能直接链接这份文档
- 当前实现:
- 已补
docs/public-capability-overview.md - 已补
docs/runtime-stability.md README.md已新增这两份文档入口- 当前文档已显式收口平台、通知、性能、部署与当前边界
- 状态:
done - 目标:把“测试通过”补成“可长期运行”的证据。
- 主要范围:
tests/、docs/、部署样例 - 关键输出:
- 至少一份连续运行验证记录
- 慢源 / 失败源 / 空输入恢复报告
- 资源占用与退出码观察结果
- 完成标准:
- 形成一份可引用的运行稳定性报告
- 能对外说明适合怎样的运行频率和部署方式
- 当前实现:
- 已复用根级系统测试中的慢源 / 失败源恢复、多轮重复执行一致性、大输入稳定性与多格式一致性证据
- 已补
docs/runtime-stability.md,把这些验证入口收口为部署前检查说明 - 当前验证结果:
cargo test --workspace- 当前工作区总数:
238 tests passed
- 状态:
done - 目标:建立 Rust 版当前性能基线,替代“体感更快”的模糊判断。
- 主要范围:
crates/app、crates/fetch、crates/analyze、crates/storage、crates/report - 关键输出:
- 新增 benchmark 入口,至少覆盖 fixture pipeline 和 HTTP smoke pipeline
- 记录各阶段耗时:fetch、filter、analyze、store、report
- 在文档中留下可复现的运行命令和基线结果
- 建议步骤:
- 引入
criterion或等价 benchmark 方案 - 先对 fixture pipeline 建稳定 benchmark,避免网络噪声
- 再补单次 HTTP smoke benchmark,并明确其仅作趋势参考
- 在
docs/roadmap.md或本文件追加基线结果 - 验证命令:
cargo test --workspacecargo clippy --workspace --all-targets --all-features -- -D warningscargo bench --workspace- 完成标准:
- 仓库内存在稳定 benchmark 入口
- 至少有一份基线结果被写入文档
- 后续优化任务都能引用同一基线
- 当前实现:
- benchmark 入口:
cargo bench --package trendradar-app --bench pipeline_bench - 基线覆盖:fixture pipeline total、fetch/analyze/storage/report 四个阶段
- 当前备注:本轮先建立 Rust 内部基线;Python 对比模板已单独整理到
docs/benchmark-python-baseline.md,真实对比值留待后续补充 - 首次基线记录:
pipeline_total/fixture_pipeline_minimal:194.20 µs ~ 207.51 µspipeline_stage/fetch_fixture_sources:9.0537 µs ~ 9.4556 µspipeline_stage/analyze_filter_rank_group:1.1192 µs ~ 1.1954 µspipeline_stage/storage_in_memory_roundtrip:99.968 µs ~ 108.28 µspipeline_stage/report_render_all_formats:30.268 µs ~ 31.643 µs- 历史备注:
- 首轮曾记录
pipeline_total/http_pipeline_smoke:1.8386 ms ~ 1.9952 ms - 在并发抓取改造后,该 benchmark 的 mock HTTP 夹具稳定性不足,已从默认 benchmark 套件移除
- 状态:
done - 目标:避免 pipeline 在 push 阶段无条件生成
json/html/table/markdown四份报告。 - 主要范围:
crates/app、crates/report - 关键输出:
- pipeline 只渲染 CLI 或调用方实际请求的输出格式
both仍保持 JSON + HTML 双输出语义- 建议步骤:
- 在
app层引入显式输出目标枚举,而不是用原始字符串在main.rs分支 - 将输出目标传入 pipeline
- 将
PipelineResult调整为按需携带输出,而不是固定四字段全填 - 补齐
json/html/both/table/markdown行为测试 - 验证命令:
cargo test --workspacecargo clippy --workspace --all-targets --all-features -- -D warnings- 完成标准:
- 单一输出模式下只生成对应报告
- 现有 CLI 行为不回退
- 相关系统测试和二进制测试仍通过
- 当前实现:
app已新增OutputMode,CLI 输出模式通过显式枚举传入 pipeline- 旧
run_fixture_pipeline()/run_config_pipeline()保持兼容,默认走OutputMode::All - 新增
crates/app/tests/output_mode.rs,覆盖json/html/both/table/markdown五种输出模式
- 状态:
done - 目标:把逐条插入改为事务批量写入,减少 I/O 和 SQLite 提交开销。
- 主要范围:
crates/storage、crates/app - 关键输出:
NewsRepository或 SQLite 实现支持批量写入接口- 保持去重与
rank = MIN(existing, incoming)语义不变 - 建议步骤:
- 在
storagecrate 增加批量写入 API - 使用事务包裹整批写入
- 保留现有单条写入接口,避免不必要破坏
- 增加“大批量输入 + 重复标题 + 多来源”测试
- 验证命令:
cargo test --workspacecargo clippy --workspace --all-targets --all-features -- -D warnings- 完成标准:
- 批量写入路径已接入 pipeline
- 去重和排序行为与当前一致
- benchmark 能显示存储阶段耗时下降
- 当前实现:
NewsRepository已增加默认save_news_batch(),SqliteNewsRepository使用单事务批量写入apppipeline 已切到批量写入路径,不再逐条执行 SQL- 优化结果:
pipeline_stage/storage_in_memory_roundtrip:75.258 µs ~ 84.820 µs- 对 A1 初始基线提升约
15.6% ~ 25.3% pipeline_total/fixture_pipeline_minimal:147.17 µs ~ 166.30 µs
- 状态:
done - 目标:缩短多源抓取总耗时,避免串行抓取按最慢总和累积。
- 主要范围:
crates/app、crates/fetch - 关键输出:
- 多个 fetcher 可并发执行
resilient=true/false的错误语义保持不变- 建议步骤:
- 先采用最小侵入方案并发包装现有 blocking fetcher
- 保持 fixture pipeline 和 HTTP pipeline 的公共行为一致
- 为并发模式补错误传播、空输入、部分成功样例
- 若后续决定全链路 async,此任务只先做过渡实现,不提前重写全仓
- 验证命令:
cargo test --workspacecargo clippy --workspace --all-targets --all-features -- -D warnings- 完成标准:
- 多源抓取可并发
- 错误与日志语义不回退
- benchmark 能显示 fetch 阶段总耗时下降
- 当前实现:
Fetchertrait 已显式要求Send + Syncapp的 HTTP/生产抓取路径改为作用域线程并发执行,并按原始 fetcher 顺序收集结果- fixture pipeline 仍保持串行,避免本地测试/基准被线程调度开销放大
resilient=false仍传播错误,resilient=true仍记录警告并跳过失败源- 新增
collect_items_fetches_sources_concurrently与resilient_collection_keeps_successful_items两条内部测试 - 当前备注:
- 由于 mock HTTP benchmark 夹具在并发场景下稳定性不足,本轮使用并发行为测试而不是 HTTP benchmark 作为收口证据
- 状态:
done - 目标:在现有
Notifiertrait 基础上补齐核心通知渠道,并建立可继续扩展的 sink 模型。 - 主要范围:
crates/notification、crates/config、crates/app - 关键输出:
- 新增各平台 notifier 实现
- 配置结构支持多通知渠道
- 默认
ConsoleNotifier回退语义不变 - 建议步骤:
- 先统一通知配置模型,再分别实现各平台 payload 适配
- 每个平台都用 mock server 做成功与失败测试
app只负责构建 notifiers 和发送,不负责编码各平台字段- 同步更新
docs/module-map.md和通知相关实现文档 - 验证命令:
cargo test --workspacecargo clippy --workspace --all-targets --all-features -- -D warnings- 完成标准:
- 至少支持飞书、钉钉、企业微信三种通知
- 通知失败仍为旁路警告,不中断主 pipeline
- 至少一份配置样例文档可复用
- 当前实现:
NotificationConfig已扩展feishu_webhook_url、dingtalk_webhook_url、wecom_webhook_url- 第 1 轮继续补齐
discord_webhook_url与ntfy_topic_url notificationcrate 已新增FeishuNotifier、DingTalkNotifier、WeComNotifier、DiscordNotifier、NtfyNotifierbuild_notifiers()工厂函数现支持同时构建多渠道通知器,且无外部渠道时仍默认回退到ConsoleNotifierapp仍只负责把配置映射到 notifier 工厂,不包含渠道 payload 细节- 验证结果:
cargo test -p trendradar-notificationcargo test --workspacecargo clippy --workspace --all-targets --all-features -- -D warnings
- 状态:
done - 目标:支持工作日/周末区分与冷却周期,不破坏现有时间窗口语义。
- 主要范围:
crates/schedule、crates/config、crates/app - 关键输出:
- 调度配置支持 weekday/weekend 和 cooldown 规则
- 时区与跨午夜场景下的决策保持可验证
- 建议步骤:
- 先补契约与 fixture,再补实现
- 新规则全部落在
schedulecrate,app只消费决策结果 - 补齐错误路径:非法天数、非法冷却值、窗口叠加冲突
- 同步更新
docs/contracts/schedule.md - 验证命令:
cargo test --workspacecargo clippy --workspace --all-targets --all-features -- -D warnings- 完成标准:
- 新调度规则通过 crate 级和系统级样例验证
app未吸收额外调度业务规则- 当前进展:
- 已新增
weekday/weekend覆盖规则,继续保持“纯配置 + 显式时间上下文”模型 ScheduleContext已扩展is_weekend/current_time/last_success_atcooldown_minutes已进入ScheduleConfig,app通过本地 sidecar 状态文件显式提供last_success_atschedule仍保持纯逻辑,不直接读取文件系统或系统时间
- 状态:
done - 目标:在现有
HotlistParser扩展点上继续补齐头条、百度、澎湃、财联社等平台。 - 主要范围:
crates/fetch、crates/config、fixtures、系统测试 - 关键输出:
- 新 parser 实现
- 新 fixture 与配置样例
- 平台选择逻辑继续通过工厂函数路由
- 建议步骤:
- 每次只新增 1 到 2 个平台
- 每个平台都先补 fixture,再补 parser,再接配置测试
- 不修改
HttpHotlistFetcher主体职责,保持开闭原则 - 验证命令:
cargo test --workspacecargo clippy --workspace --all-targets --all-features -- -D warnings- 完成标准:
- 新平台可以独立解析并通过系统测试
- 不影响已有
generic/weibo/zhihu/bilibili行为 - 当前实现:
fetch已新增ToutiaoHotlistParser、BaiduHotlistParser、PengpaiHotlistParser、ClsHotlistParserhotlist_parser_for()已支持toutiao、baidu、pengpai、cls,并兼容thepaper、cls-hot别名路由- 第 1 轮继续把
GenericHotlistParser扩展为兼容newsnow的{"items":[...]}包装响应,并把douyin、wallstreetcn-hot、ifeng、tieba纳入显式支持 - 已新增
fixtures/system/config/hotlist-multi-platform-http.json作为多平台 HTTP 配置样例 crates/app/tests/wave4_http_pipeline.rs已补多平台source_type路由测试,验证app -> fetch parser factory -> HTTP pipeline闭环- 验证结果:
cargo test -p trendradar-fetchcargo test -p trendradar-app --test wave4_http_pipelinecargo check --workspace --all-targets
- 状态:
done - 目标:统一 CLI 退出码,便于脚本调用和运维诊断。
- 主要范围:
crates/app - 关键输出:
- 明确配置错误、网络错误、存储错误、未知错误的退出码
- README 与文档中写清退出码语义
- 建议步骤:
- 先列出当前错误来源与归类边界
- 在
main.rs做统一映射,不把退出码分散在各 crate - 为二进制 smoke test 增加失败码断言
- 验证命令:
cargo test --workspacecargo clippy --workspace --all-targets --all-features -- -D warnings- 完成标准:
- CLI 退出码稳定可预测
- 文档与测试同步
- 当前实现:
crates/app/src/main.rs已新增集中式退出码分类,统一映射配置、网络、存储与未知错误crates/app/tests/binary_smoke.rs已补配置错误与存储错误退出码断言main.rs内部单测已补网络错误、存储错误、未知错误的分类断言README.md已新增 CLI 退出码表,明确0/1/2/3/4语义- 验证结果:
cargo test -p trendradar-app --test binary_smokecargo test -p trendradar-appcargo check --workspace --all-targets
- 状态:
done - 目标:补齐
install.sh、cargo install说明和后续 Homebrew 入口。 - 主要范围:仓库根目录、README、CI/release 文档
- 关键输出:
- 最小安装脚本
- README 安装章节
- release 产物下载说明
- 建议步骤:
- 先交付
install.sh与 README 使用说明 - 再视需要补 Homebrew formula
- 明确平台差异和校验方式
- 验证命令:
./scripts/check_environment.shcargo test --workspace- 完成标准:
- 新用户按 README 能完成安装和首次运行
- 当前实现:
- 仓库根目录已新增
install.sh,支持 Linux x86_64 与 macOS arm64 的 GitHub Releases 安装 README.md已新增安装章节,覆盖 release 安装脚本、源码cargo install --path crates/app --locked和 Windows 手动下载说明scripts/bootstrap.sh已同步当前rust-toolchain.toml的1.94.1版本,避免环境准备脚本与活文档脱节- Homebrew formula 继续留作后续按需补充,不阻塞当前安装闭环
- 验证结果:
bash -n ./install.sh./install.sh --help./scripts/check_environment.shcargo test --workspace
- 状态:
done - 目标:在不破坏本地 SQLite 默认路径的前提下,补齐 S3/OSS adapter。
- 前置条件:A3 已完成,
NewsRepository边界稳定。 - 主要范围:
crates/storage、crates/config - 关键输出:
- 远程存储实现
- 配置开关与失败回退语义
- 远程存储测试策略
- 完成标准:
- 本地与远程后端可切换
- 本地路径仍是默认实现
- 当前进展:
config已新增storage.backend与远程对象存储配置app当前已支持storage.backend = "s3" + provider = "s3" | "aws-s3" | "oss" | "aliyun-oss"的真实对象存储路由,并保留provider = "mock-s3"的文件系统原型用于本地验证- 已新增远程对象布局契约文档、fixture 和系统测试骨架,用于先固定 key 布局与读取顺序
storage已新增基于 OpenDAL 的OpendalObjectStoreNewsRepository,并保留MockRemoteNewsRepository与FileObjectStoreNewsRepository作为仓储语义和本地布局验证入口- 当前最小闭环已形成;后续增强主要落在凭证治理、provider 细项兼容与更完整回归矩阵
- 状态:
done - 目标:基于内核输出增加摘要、主题分析、标签抽取等能力。
- 前置条件:A1 已完成,性能基线明确;B1-B3 至少完成一项,避免输入模型频繁变化。
- 主要范围:新增独立 crate 或独立模块,不直接污染核心 pipeline
- 关键输出:
- 明确 AI 输入输出契约
- prompt / provider / timeout / retry 策略
- 与报告层的集成点
- 完成标准:
- AI 能力为可选旁路,不阻塞核心抓取与存储链路
- 当前进展:
- 已新增独立
trendradar-aicrate,提供AnalysisProvidertrait、mockprovider、最小openai-compatibleprovider 和 Markdown 渲染 config.ai_analysis已新增最小配置字段,并补model/base_url/api_key/api_key_envapp已可在开启配置后生成ai_analysis_markdown,provider 不可用时只 warn + skip- 更多真实 provider、timeout/retry 精细控制和输出格式扩展仍待后续补齐
- 状态:
done - 目标:将稳定的 Rust 内核能力以工具接口形式暴露。
- 前置条件:C2 可选;核心内核 API 稳定。
- 主要范围:独立服务入口、工具协议层、文档
- 关键输出:
- 工具列表与权限边界
- 查询类工具优先,写操作延后
- 与 CLI 路径分离的服务入口
- 完成标准:
- MCP 服务不复用 CLI 输出作为协议层
- 工具契约可单独测试
- 当前进展:
- 已新增独立
trendradar-mcpcrate 和trendradar-mcp二进制 - 当前提供
tools/list和查询类tools/call - 已支持
storage.list_news、report.render_json、ai.analyze三个查询工具 - 当前更接近最小查询型工具服务,后续可继续向完整 MCP 协议兼容层收口
后续每次执行某个任务时,建议按下面顺序推进:
- 选定任务编号,例如
A2。 - 列出本次只改哪些 crate、哪些文件类型、哪些文档。
- 先补或确认 fixture / contract / 测试样例。
- 再补实现。
- 跑最小必要验证命令。
- 更新本文件中对应任务的状态与结果备注。
- 如有必要,补一篇
docs/dev-journal/日志记录关键决策。
任务状态统一使用下面四种文本值:
todo:尚未开始in-progress:已开始但未形成可验证闭环blocked:存在外部依赖或设计阻塞done:代码、测试、文档和验证已闭环
如果后续要从这份文档直接开工,建议第一批按下面顺序执行:
- A1 性能基线与 Benchmark
- A2 报告按需渲染
- A3 SQLite 批量写入
- B1 通知渠道扩展
原因:
- A1 先提供量化依据,后续优化不会失焦。
- A2 和 A3 都是低风险、直接释放 Rust 运行优势的任务。
- B1 是最容易快速补齐用户侧价值差距的能力。