Files
zhuyongxin e4f37cb9e6 fix(knowledge): 修复循环依赖 + 归档 session-dedup-knowledge-map + 记录 ISS-002
- KnowledgeIndexService: 域级生成从 @PostConstruct 移到 @EventListener(ApplicationReadyEvent),解决 KnowledgeIndexService ↔ KnowledgeDomainService 循环依赖
- devflow 归档: evidence.md + acceptance.md(含运行验证结果)
- devflow/index.md: session-dedup-knowledge-map 状态改为 archived
- openspec .archive-ready 标记
- mvp/issues/ISS-002: Executor 无约束重复调用 lookup_knowledge
2026-07-01 14:26:59 +08:00

3.0 KiB
Raw Permalink Blame History

Evidence: session-dedup-knowledge-map

E1: ThreadLocal 在多 Agent 路径是否安全

问题:SessionContextHolder 基于 ThreadLocal,多 Agent 异步路径可能导致 sessionId 丢失。

证据:

  • AsyncConfig 只启用 @EnableAsync,无 TaskDecorator
  • SupervisorAgent.invoke() 是同步阻塞调用,工具调用与主线程同线程
  • 当前路径下 ThreadLocal 安全

结论:当前同步路径安全。未来引入异步扩展时需补 TaskDecorator 传递 ThreadLocal。


E2: 6 个文档是否全部有 category 字段

问题:域聚合依赖 category 字段分组,需确认现有文档是否都有值。

证据:

  • 全部 6 个文档均有 category 字段:api(1)、domain(1)、infrastructure(3)、troubleshooting(1)

结论:现有文档无需修补,category 覆盖率 100%。


E3: 去重 key 设计

问题:用什么字段唯一标识一个文档用于去重。

证据:

  • KnowledgeEntry.filePath 在 L0 索引内唯一
  • L1 向量索引的 _source 字段也是 filePath
  • 上传时 saveToLocal() 生成 knowledge_base/{category}/{fileName} 路径

结论:统一用 filePath 作去重 key,L0 和 L1 一致。


E4: Planner prompt token 增量是否可接受

问题:knowledge map YAML 注入 Planner prompt 会增加固定 token 开销。

证据:

  • 当前 planner prompt 21 行
  • 注入 knowledge map 约增加 200-400 字符(6 个文档场景)
  • 相比 Planner 整体 prompt + 历史消息,增量占比 < 5%

结论:可接受,不构成性能瓶颈。


E5: EvaluationService.tool_call_count 影响

问题:去重后 tool_call_count 降低,是否影响 EvaluationService 评分逻辑。

证据:

  • EvaluationService 使用 tool_call_count 作为评分因子
  • 去重导致重复调用被过滤,tool_call_count 下降
  • 这是修复效果(消除了无意义的重复调用),不是回归

结论:EvaluationService 评分规则无需改动。下降的 tool_call_count 反映了真实效率提升。


P1: 手写 JSON 解析器脆弱性

问题:KnowledgeIndexService.extractJsonValue / extractJsonArray 在遇到含逗号、引号的自然语言字段时会截断。

证据:

  • whenToRetrieve 字段由 LLM 生成,内容为自然语言(含逗号、分号等标点)
  • 手写解析器以 " 和 , 作分隔符,自然语言中的标点会导致提前截断
  • Jackson ObjectMapper.readValue(metadata, Frontmatter.class) 是项目已有依赖

结论:全量替换为 Jackson,影响范围仅 KnowledgeIndexService.parseDocumentToEntry(),行为更健壮。


P2: LookupResult 去重提示字段

问题:去重命中时如何向 LLM 返回"不要重试"的信号。

证据:

  • 复用 primary.content 语义不清,LLM 可能理解为正常检索结果
  • 独立 message 字段 + found=false 语义明确,LLM 能理解"已检索过"不再重试

结论:LookupResult 新增 String message 字段,去重时填入提示文本。