# keyword-cleanup-review 建议产物补齐设计 ## 1. 背景与目标 当前仓库已经具备 keyword cleanup review 的大部分基础设施: - 已有 review bundle 构建脚本 `skills/keyword-cleanup-review/scripts/build_review_bundle.py` - 已有 term stats 与 daily term index 数据源 - 已有治理输入:`configs/term_cleanup_policy.json`、`configs/term_watchlist.json`、`configs/term_change_log.json` - 已有建议落地脚本 `scripts/apply_term_suggestions.py` 当前缺口是: > 缺少一层“把 `keyword-cleanup-bundle.json` 转成正式建议产物”的实现层。 也就是说,仓库现在能生成 review bundle,也能消费 suggestions JSON,但中间缺少稳定、可复用、可落盘的 suggestions 生成器。 本轮目标是补齐最小闭环,让仓库能够从 review bundle 稳定生成两份正式建议产物: - `outputs/term_index/review/term-cleanup-suggestions-YYYY-MM-DD.json` - `outputs/term_index/review/term-cleanup-suggestions-YYYY-MM-DD.md` 并保证 JSON 与 `skills/keyword-cleanup-review/references/suggestion-schema.md` 对齐,且能直接衔接 `scripts/apply_term_suggestions.py`。 补充口径:本方案中的 JSON 是 review / apply 之间的唯一正式建议产物;bundle 与 Markdown 主要作为运行时工作文件和临时展示层,不建议与 facts/configs 一样长期沉淀。 --- ## 2. 当前现状 ### 2.1 已有输入层 `build_review_bundle.py` 已经把以下输入聚合成单个 bundle: - `data/term_index/term_stats.json` - `data/term_index/daily/*.json` - `configs/term_aliases.json` - `configs/term_stopwords.json` - `configs/filter_context.personal.json` - `configs/term_cleanup_policy.json` - `configs/term_watchlist.json` - `configs/term_change_log.json` bundle 中已经包含: - 当前配置快照 - 最近 N 天热点词 - uncovered terms - interest review candidates - watch review candidates 这些信息已经足够支撑“保守的、可审查的” suggestions 生成。 ### 2.2 已有输出消费层 `scripts/apply_term_suggestions.py` 已经能消费 suggestions JSON,并将接受的建议写回: - `configs/term_aliases.json` - `configs/term_stopwords.json` - `configs/filter_context.personal.json` - `configs/term_watchlist.json` - `configs/term_change_log.json` 这说明落地层已存在,缺的是中间的正式建议产物生成层。 --- ## 3. 当前缺口 当前流程停在: `build_review_bundle.py` -> `keyword-cleanup-bundle.json` 但缺少: `keyword-cleanup-bundle.json` -> `term-cleanup-suggestions-YYYY-MM-DD.json/.md` 因此出现几个问题: - README / 设计文档里已经引用 suggestions 产物,但仓库内没有稳定生成脚本 - 人工审阅与后续 apply 之间没有统一的正式交付格式 - 同一份 bundle 无法稳定、幂等地重放为同名 suggestions 产物 - alias / stopword / interest / watch 四类建议缺少统一出入口 --- ## 4. 推荐最小闭环架构 推荐新增一层独立脚本: - `scripts/generate_term_cleanup_suggestions.py` 职责: - 输入:`outputs/term_index/review/keyword-cleanup-bundle.json` - 输出: - `outputs/term_index/review/term-cleanup-suggestions-YYYY-MM-DD.json` - `outputs/term_index/review/term-cleanup-suggestions-YYYY-MM-DD.md` 推荐最小数据流: 1. `build_review_bundle.py` 生成 bundle 2. `generate_term_cleanup_suggestions.py` 读取 bundle 3. 脚本基于治理 hints 生成 suggestions JSON 4. 同时渲染人类可审阅的 Markdown 5. 审阅后可用 `apply_term_suggestions.py` 选择性写回配置 本轮不引入默认 LLM 路径: - 默认实现采用确定性规则生成 - 如果未来需要 LLM 参与,应作为显式可选增强,而不是默认路径 --- ## 5. 产物设计 ### 5.1 JSON 产物 JSON 必须与 `suggestion-schema.md` 对齐,至少包含: ```json { "date": "2026-04-08", "based_on_days": 7, "alias_suggestions": [], "stopword_suggestions": [], "interest_keyword_suggestions": [ { "term": "Claude Code", "reason": "Meets the configured interest-keyword review threshold and is not yet covered." } ], "watch_terms": [ { "term": "A2A", "reason": "Falls into the configured watch-term review range and should be observed first." } ] } ``` 在不破坏兼容性的前提下,可以补充少量元数据字段,建议仅限: - `source_bundle` - `policy_schema_version` - `summary` 建议项字段口径: - `alias_suggestions[]` - `from` - `to` - `reason` - `stopword_suggestions[]` - `term` - `reason` - `interest_keyword_suggestions[]` - `term` - `reason` - 可选:`total_count`、`days_seen`、`recent_count` - `watch_terms[]` - `term` - `reason` - 可选:`total_count`、`days_seen`、`recent_count` 兼容性要求: - `apply_term_suggestions.py` 只依赖分类 bucket 与关键字段名 - 因此额外证据字段只能追加,不能替换现有字段名 ### 5.2 Markdown 产物 Markdown 推荐结构: 1. 标题与日期 2. 输入 bundle 与策略摘要 3. 当前现状摘要 - top/global 观察 - uncovered terms 概览 - 当前 watchlist / interest 覆盖情况 4. 建议摘要 - interest 建议数量 - watch 建议数量 - alias 建议数量 - stopword 建议数量 5. `interest_keyword_suggestions` 6. `watch_terms` 7. `alias_suggestions` 8. `stopword_suggestions` 9. 应用方式 - 指向生成的 JSON - 给出 `apply_term_suggestions.py` 的调用示例 这样可以保证: - 人可以直接审阅 - 机器可以直接消费同名 JSON - Markdown 与 JSON 始终一一对应 --- ## 6. 建议生成策略 ### 6.1 本轮主链路:interest / watch 本轮先实现最小可用主链路: - `interest_keyword_suggestions` - `watch_terms` 直接复用 bundle 中已有的: - `governance_hints.interest_review_candidates` - `governance_hints.watch_review_candidates` 原因: - 这些候选已经与 policy 对齐 - 这些候选已经排除了大部分已覆盖项 - 能直接与现有 apply 脚本形成闭环 ### 6.2 alias / stopword 保守处理 本轮边界明确如下: - `alias_suggestions` 先保持保守,默认可为空 - `stopword_suggestions` 先保持保守,默认可为空 - 后续如果补充更强证据或人工审查规则,再逐步增强 这样可以避免在证据不足时误伤配置。 ### 6.3 Phase 2 新方向:alias review 交给 LLM 整理 对于 alias,不再优先走程序规则匹配。 Phase 2 建议改为: - 程序继续负责准备 review 输入(term stats / daily / current aliases / stopwords / interest / watchlist) - LLM 负责整理 alias 候选 - 默认先输出人工审阅汇报,而不是直接 apply - 人工确认后,再决定是否写入 `term_aliases.json` 这样做的原因: - alias 更偏语义整理,而不是简单趋势筛选 - 与 watch / interest 相比,alias 一旦错误归并,代价更高 - 对当前低频治理场景来说,LLM + 人工确认更轻,也比在程序里持续堆复杂规则更合适 --- ## 7. 错误处理 脚本应做显式校验,并在失败时给出明确错误: ### 7.1 输入错误 - bundle 文件不存在 -> 直接失败 - bundle 不是 JSON object -> 直接失败 - 缺少关键字段(如 `days`、`governance_hints`)-> 直接失败 - 候选 bucket 结构错误 -> 直接失败 ### 7.2 输出错误 - 输出目录不存在时自动创建 - JSON / Markdown 写入失败时直接退出非 0 ### 7.3 数据去重与冲突 - 同一 term 不能同时出现在 interest 与 watch 中 - 优先级:`interest_keyword_suggestions` > `watch_terms` - 已在 bundle 当前配置中覆盖的 term 不重复输出 --- ## 8. 幂等性 本轮要求具备基础幂等性: - 同一份 bundle 多次运行,默认生成同名产物 - 同一份 bundle 多次运行,JSON 内容顺序稳定 - Markdown 内容顺序稳定 建议做法: - 优先使用 bundle 的 `generated_at` 日期作为 suggestions 文件日期 - term 排序按证据强度与 term 名稳定排序 - 不在默认输出中写入“每次运行变化”的当前时间戳 这样可以让生成器作为可重放步骤存在于 review 流程中。 --- ## 9. 与 apply_term_suggestions.py 的衔接 正式链路应变成: 1. `build_review_bundle.py` 2. `generate_term_cleanup_suggestions.py` 3. 人工审阅 Markdown 4. `apply_term_suggestions.py --suggestions ...` 衔接要求: - JSON bucket 名必须与 `apply_term_suggestions.py` 读取逻辑一致 - `date` 与 `based_on_days` 字段保留,用于 change log 回写 - 建议项中的 `reason` 直接沿用到 apply 后的 change log 这保证建议生成层不会成为孤立产物,而是正式进入 repo 治理闭环。 --- ## 10. Python 3.11 依赖处理 ### 10.1 当前现状 `build_review_bundle.py` 当前使用 `from datetime import UTC`,这要求 Python 3.11。 仓库整体 `pyproject.toml` 当前也声明 `requires-python = ">=3.11"`,因此短期内使用 `/usr/bin/python3.11` 运行是符合仓库现状的。 ### 10.2 短期建议 短期先在文档与验证命令中明确: - bundle 构建使用 `/usr/bin/python3.11` - suggestions 生成脚本也按仓库当前 3.11 基线运行 ### 10.3 中期建议 如果后续希望把 keyword cleanup 工具链下探到 Python 3.10,可做兼容改造: - 把 `datetime.UTC` 替换为 `datetime.timezone.utc` - 重新检查相关脚本是否还有其他 3.11-only 语法或库依赖 本轮不做超范围兼容重构,只在文档中把此约束说清楚。 --- ## 11. 边界与非目标 本轮明确边界: - 先实现 interest/watch 主链路 - alias/stopword 先保持保守或留待后续增强 - 不做超范围重构 - 不把 LLM 作为默认生成路径 - 不直接改 `filter_rules.json` - 不自动 apply 建议到配置 因此,本轮交付定义为: - 补齐 bundle -> suggestions 的正式实现层 - 让 review 流程可运行、可落盘、可审阅、可应用 而不是一次性做完所有高级治理逻辑。 --- ## 12. 实施建议 建议按以下小步落地: ### Phase 1(已完成) 1. 新增 `scripts/generate_term_cleanup_suggestions.py` 2. 读取 bundle 并做结构校验 3. 生成稳定排序的 interest/watch suggestions JSON 4. Markdown 改成按需生成 5. README / skill 文档补一条生成命令 6. 用 `/usr/bin/python3.11` 完整跑通 bundle -> suggestions 完成后,keyword cleanup review 的最小正式链路变为: `review bundle` -> `suggestions json` -> `apply accepted suggestions` 其中 Markdown 只是按需生成的展示层。 ### Phase 2(下一步) 1. 保持程序继续准备 review 输入 2. 引入 LLM 做 alias 候选整理 3. 默认先生成 alias review 汇报,而不是直接 apply 4. 由人工确认后再决定是否写入 `term_aliases.json` 这样 alias review 会成为一个低频治理动作,而不是主链路里的自动归一步骤。 ### Phase 3(下一步) 1. 保持程序继续准备 review 输入 2. 引入 LLM 做 stopword 候选整理 3. 默认先生成 stopword review 汇报,而不是直接 apply 4. 由人工确认后再决定是否写入 `term_stopwords.json` 这样 stopword review 会成为一个低频减噪动作,而不是主链路里的自动过滤步骤。 #### Phase 3 输入建议 建议给 LLM 的输入包括: - `data/term_index/term_stats.json` 中的高频词与 recent evidence - 最近 N 天 `data/term_index/daily/*.json` 的热点词上下文 - 当前 `configs/term_stopwords.json` - 当前 `configs/term_aliases.json` - 当前 `configs/filter_context.personal.json` 中的 `interest_keywords` - 当前 `configs/term_watchlist.json` 程序层只负责把这些输入整理成紧凑 review context,不负责直接做 stopword 决策。 #### Phase 3 输出建议 建议 LLM 默认输出一份人工审阅汇报,而不是直接写配置: - `建议加入 stopword` - 词 - 简短理由 - 证据(如 total_count / days_seen / recent_count) - `暂不建议加入 stopword` - 词 - 为什么虽然偏泛,但当前还不能杀 - `需要人工判断` - 词 - 风险点:可能是噪声,也可能仍保留有价值信号 如需结构化输出,可额外补一份 `stopword_review_candidates.json`,但该文件只作为 review 输入,不直接作为自动 apply 指令。 #### Phase 3 审阅原则 - 宁可少删,不乱杀 - 优先处理过泛、低辨识度、持续污染统计的词 - 对可能仍承载有效技术语义的词保持保守 - 默认先汇报,确认后再执行 #### Phase 3 汇报模板建议 建议 stopword review 默认按以下结构汇报给用户: 1. `建议加入 stopword` - 词 - 理由:为什么这个词对治理帮助低、噪声高 - 证据:`total_count` / `days_seen` / `recent_count` 或最近出现上下文 2. `暂不建议加入 stopword` - 词 - 理由:为什么当前不建议删掉 3. `需要人工判断` - 词 - 风险点:泛词与有效主题词之间边界不清等 推荐汇报风格: - 简短、保守、可审阅 - 先给判断,再给证据 - 不输出机器式原始 dump - 不默认承诺“已应用”,只汇报“建议” #### Phase 2 输入建议 建议给 LLM 的输入包括: - `data/term_index/term_stats.json` 中的高频词与 recent evidence - 最近 N 天 `data/term_index/daily/*.json` 的热点词上下文 - 当前 `configs/term_aliases.json` - 当前 `configs/term_stopwords.json` - 当前 `configs/filter_context.personal.json` 中的 `interest_keywords` - 当前 `configs/term_watchlist.json` 程序层只负责把这些输入整理成紧凑 review context,不负责直接做 alias 决策。 #### Phase 2 输出建议 建议 LLM 默认输出一份人工审阅汇报,而不是直接写配置: - `建议合并` - `from -> to` - 简短理由 - 证据(如 total_count / days_seen / recent_count) - `暂不建议合并` - 为什么不建议并掉 - `需要人工判断` - 语义相近但风险较高的项 如需结构化输出,可额外补一份 `alias_review_candidates.json`,但该文件只作为 review 输入,不直接作为自动 apply 指令。 #### Phase 2 审阅原则 - 宁可少提,不乱提 - 优先整理明显同义 / 同概念 / 词形差异 - 不把公司名、产品名、泛概念词强行混并 - 默认先汇报,确认后再执行 #### Phase 2 汇报模板建议 建议 alias review 默认按以下结构汇报给用户: 1. `建议合并` - `from -> to` - 理由:为什么判断为同一概念或更合适的标准词 - 证据:`total_count` / `days_seen` / `recent_count` 或最近出现上下文 2. `暂不建议合并` - 候选对 - 理由:为什么虽然相近,但当前不建议并 3. `需要人工判断` - 候选对 - 风险点:歧义、范围差异、产品名/公司名混淆等 推荐汇报风格: - 简短、保守、可审阅 - 先给判断,再给证据 - 不输出机器式原始 dump - 不默认承诺“已应用”,只汇报“建议” #### Phase 2 示例输出 建议合并: - `Claude code -> Claude Code` - 理由:明显属于同一产品名,仅是大小写写法不一致。 - 证据:`Claude Code` 在最近多日持续出现,而小写写法只是在少量上下文中作为变体出现。 - `Sub-Agent -> SubAgent` - 理由:更像词形差异,不构成新的独立概念。 - 证据:两者都围绕同一 agent 架构语境出现,且没有稳定区分语义。 暂不建议合并: - `Skills ↔ Agent Skills` - 理由:前者过泛,后者更具体,当前强行归并会损失粒度。 - `Anthropic ↔ Claude` - 理由:公司名与产品名并不等价,不应直接视为一个关键词。 需要人工判断: - `AI助手 ↔ AI Agent` - 风险点:语义可能接近,但中文表述范围更宽,是否并入需要结合你的使用语境判断。