Skip to content

Feature/1.0.0 - #2

Merged
ThreeFish-AI merged 46 commits into
masterfrom
feature/1.0.0
Feb 2, 2026
Merged

Feature/1.0.0#2
ThreeFish-AI merged 46 commits into
masterfrom
feature/1.0.0

Conversation

@ThreeFish-AI

Copy link
Copy Markdown
Owner

No description provided.

- 将 hippocampus.py 重命名为 internalization.py (内化系部)
- 将 mind.py 拆分为 action.py (行动系部) 和 observability.py (可观测性系部)
- 更新所有导入引用以匹配新的文件结构
- 添加 microsandbox>=0.1.8 依赖
- 更新 uv.lock 文件

🤖 Generated with [Claude Code](https://github.com/claude)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 扩展 .adk 目录忽略规则以支持所有位置
- 添加 *.adk 文件通配符忽略
- 添加 session.db 和 artifacts/ 目录忽略

🤖 Generated with [Claude Code](https://github.com/claude)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 新增 database 后端选项,使用 ADK 官方 DatabaseSessionService
- 将 postgres 后端改为自定义 PostgresSessionService (使用 pulse.py 模型)
- 修改默认 session_service_backend 为 database
- 在 PostgresSessionService 中实现延迟导入模型,避免在选择其他后端时注册 ORM

🤖 Generated with [Claude Code](https://github.com/claude)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 添加 database 后端选项说明 (ADK 官方 DatabaseSessionService)
- 明确 postgres 为自定义 PostgresSessionService
- 更新默认值为 database

🤖 Generated with [Claude Code](https://github.com/claude)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 新增 artifacts_factory.py 支持 inmemory 和 gcs 后端
- 在 config.py 中添加 artifact_service_backend 和 gcs_bucket_name 配置
- 修改默认后端配置为 inmemory (开发/测试友好)
- 在 runner_factory.py 中集成 artifact_service
- 添加 google-cloud-storage 和 google-auth 依赖
- 新增单元测试 test_artifacts_factory.py
- 新增集成测试 test_runner_artifacts.py

🤖 Generated with [Claude Code](https://github.com/claude)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 重新生成初始 schema migration (83c05a1f137d 替代 43618f029e28)
- 更新 pulse.py 中的导入从 hippocampus 改为 internalization
- 新增 scripts/force_reset_db.py 用于开发时快速重置数据库

🤖 Generated with [Claude Code](https://github.com/claude)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 新增 NEGENTROPY_SCHEMA 常量定义 schema 名称
- 所有业务模型统一归入 negentropy schema
- 更新所有 ForeignKey 引用以使用完整的 schema.table 路径
- 导出 NEGENTROPY_SCHEMA 供迁移配置使用

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 更新 env.py 在运行迁移前自动创建 negentropy schema
- 配置 Alembic 将版本表放入 negentropy schema
- 删除旧的初始迁移文件 83c05a1f137d_initial_schema.py
- 新增 scripts/force_reset_db.py 用于开发环境数据库重置
- 更新文档说明 Schema 分离策略

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 添加 text 导入以支持 SQL 执行
- 新增 287112ebb629_initial_schema.py 迁移文件
- 所有业务表统一创建在 negentropy schema 下
- ForeignKey 使用完整的 schema.table 路径引用
- 删除旧的 public schema 下的 alembic_version 表

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 新增 include_object 过滤器,仅管理 negentropy schema 中的业务表
- 排除 public schema 中的 ADK 原生表(sessions/events/app_states 等)
- 重新生成初始迁移文件 ec89143c6bc8_initial_schema.py
- 替换旧的迁移文件 287112ebb629_initial_schema.py

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 新增 bootstrap.py 实现 ADK 服务工厂的 monkey-patch
- 新增 services.py 作为 ADK 自动发现入口点
- 支持通过 .env 配置无需 CLI 参数即可启动 ADK
- 自动应用配置到 Session/Memory/Artifact 服务

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 将所有 ForeignKey 声明格式化为多行格式以提高可读性
- 涉及 internalization/perception/pulse 模块
- 同步更新迁移文件格式

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 调整 force_reset_db.py 空行格式
- 更新 env.py 注释格式
- 简化 artifacts_factory.py 异常信息格式

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 调整空行和缩进格式
- 统一代码风格规范

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 新增 security.py 定义 Credential 模型
- 新增 PostgresCredentialService 实现 PostgreSQL 持久化存储
- 新增 CredentialFactory 支持多后端切换 (postgres/inmemory/session)
- 使用 JSONB 存储复杂 AuthCredential 数据
- 支持 upsert 操作避免重复插入

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 新增 CREDENTIAL_SERVICE_BACKEND 配置项支持
- 拦截 ADK 默认 InMemoryCredentialService 使用可配置后端
- 导出 Credential 模型到 models 包

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 替换旧迁移文件 ec89143c6bc8_initial_schema.py
- 新增 093a93971bf5_init_schema.py 包含 credentials 表
- credentials 表支持复合主键 (app_name, user_id, credential_key)
- 添加索引优化查询性能

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 将 artifacts_factory/credential_factory/memory_factory/runner_factory/session_factory
  移至 factories/ 目录并重命名为 artifacts/credential/memory/runner/session
- 更新 __init__.py 统一导出所有工厂函数
- 更新 bootstrap.py 导入路径
- 更新 main.py 导入路径
- 更新 engine/__init__.py 导入路径

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 新增 openai_api_key 和 openai_base_url 配置项
- 调整 credential_service_backend 配置位置与其他服务后端对齐
- 更新 .env.example 添加 OpenAI 配置说明

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 新增 logging.py 提供基于 structlog 的统一日志服务
- 支持多种 Sink:stdio(开发)、file(本地文件)、gcloud(生产环境)
- 使用 orjson 实现高性能 JSON 序列化
- 采用策略模式抽象 Sink 接口
- 支持日志轮转和 Google Cloud Logging 集成

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 新增 log_level/log_sinks/log_file_path/gcloud_log_name 配置项
- 新增 structlog/orjson/google-cloud-logging 依赖
- 更新 .env.example 添加日志配置说明

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- bootstrap 初始化时配置统一日志服务
- tracing 模块使用 get_logger 替代 logging.getLogger

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 新增 LOG_FORMAT 配置项支持 console/json 两种格式
- Console 格式使用 ANSI 彩色输出,易于开发调试
- JSON 格式用于机器解析和日志采集
- 重构 StdioSink 支持可配置输出格式
- 优化 multi_sink_renderer 返回空字符串避免重复输出

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 新增 log_format 配置项 (console/json)
- 更新 .env.example 添加格式说明
- Bootstrap 传递格式参数到日志配置

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 新增 SilentPrintLoggerFactory 避免空输出到 /dev/null 的开销
- 使用 make_filtering_bound_logger 在配置层面实现日志级别过滤
- 优化 stdlib 日志配置添加 force=True 参数

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 提取 ConsoleFormatter 类实现关注点分离
- 分离配置逻辑为 _initialize_sinks/_configure_structlog/_intercept_third_party_loggers
- 新增 LiteLLMLoggingCallback 记录 token 使用、成本、延迟
- 拦截 Uvicorn/LiteLLM 第三方日志避免噪音
- 简化 StdioSink.emit 实现

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 注册 LiteLLM success_callback 和 failure_callback
- 使用 LiteLLMLoggingCallback 记录 token 使用和成本

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 新增 StreamToLogger 类重定向标准输出到日志系统
- 拦截 sys.stdout 和 sys.stderr 确保所有输出通过结构化日志
- 支持行缓冲和属性代理
- 避免重复拦截检查类型

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 更新所有系部使用 settings.llm.full_model_name
- 更新所有系部使用 settings.llm.to_litellm_kwargs()

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 新增 preserve_thinking 参数支持 GLM 保留思考模式
- 使用 extra_body 绕过 LiteLLM 参数验证传递 GLM 特定参数
- 重构思考配置逻辑,按模型类型分别处理
- 添加 GLM-4.7 思考模式文档链接
- 更新默认 provider 为 anthropic

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 默认 provider 改为 anthropic
- 添加 NE_LLM_PRESERVE_THINKING 配置说明
- 更新 API 配置为 Anthropic/BigModel
- 添加 LITELLM_ANTHROPIC_DISABLE_URL_SUFFIX 配置
- 设置默认 GCS bucket 名称

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 新增 zai provider 用于 GLM 模型
- 更新默认 provider 为 zai
- 使用 ZAI_API_KEY 和 ZAI_API_BASE 配置
- 添加 LiteLLM ZAI provider 文档链接

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
- 新增 LlmVendor 枚举提升类型安全
- provider 字段重命名为 vendor
- 使用 validation_alias 保持向后兼容
- 重构思考配置逻辑添加文档链接
- 优化注释和代码结构

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
EOF
)
- 删除 openai.py 配置模块(OpenAI 配置由各 vendor 环境变量管理)
- services.py 使用枚举类型替代字符串 (CredentialBackend/MemoryBackend/SessionBackend/ArtifactBackend)
- logging.py 使用枚举类型 (LogLevel/LogFormat)
- environment.py 导出 get_env_files 函数并添加 debug 属性
- 所有配置模块添加 frozen=True 确保不可变
- 更新兼容性层返回枚举的 .value
- 更新 .env.example NE_LLM_PROVIDER 为 NE_LLM_VENDOR

🤖 Generated with [Claude Code](https://github.com/claude), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
@ThreeFish-AI
ThreeFish-AI merged commit 6218220 into master Feb 2, 2026
ThreeFish-AI added a commit that referenced this pull request Feb 25, 2026
ThreeFish-AI added a commit that referenced this pull request Apr 27, 2026
… × 502 上游错误码 × 诊断仪器化) (#421)

* fix(knowledge): 修复 Knowledge Base Retrieve 全屏空白(前端聚合 rejection + 后端 hybrid/rrf 降级 + 502 错误码 + 诊断日志);

双层 Bug 同因联修(详见 docs/issue.md ISSUE-026):
1. 前端 searchAcrossCorpora 旧实现以 Promise.allSettled 仅取 fulfilled,rejected 静默丢失,导致全部 Corpus 失败时返回 {count:0,items:[]} 走"成功路径"使 UI 空白且无任何提示——本次改为聚合三态(全成功/部分失败/全失败),SearchResults 类型扩展 errors[],handleRetrieve 对部分失败 toast.warning 透出原因;
2. 后端 service.search hybrid/rrf 旧实现未捕获 EmbeddingFailed,外部 Embedding 上游故障直接 500,丧失"keyword 仍可用"的优雅降级——本次 hybrid 失败回退 keyword-only、rrf 失败走与 not embedding_fn 等价的回退路径,semantic 仍传播以保留显式失败语义;
3. api.py _map_exception_to_http 拆分 EmbeddingFailed 分支映射到 502 Bad Gateway(保留 EMBEDDING_FAILED code),与 SearchError 自身错误的 500 区分,便于前端识别"上游修复后再试"语义;
4. embedding.py 调用 litellm 前后增加结构化诊断日志:api_base_host(脱敏 path/credentials 仅留 host)+ input_count + text_preview + kwargs_keys;失败附 upstream_response_text(沿异常链 __cause__/__context__ 提取 MaskedHTTPStatusError.text,已被 litellm 脱敏 URL,限长 500 字节);
5. 测试锁定:tests/unit_tests/knowledge/test_search_resilience.py 5 例(hybrid/rrf 降级 + semantic 传播 + EmbeddingFailed→502 + SearchError→500)+ tests/unit/knowledge/searchAcrossCorpora.test.ts 3 例(allSettled 三态);
6. docs/issue.md 追加 ISSUE-026,含后续防范(Promise.allSettled 必须聚合 rejection / vendor 失败必须 502 / hybrid 必须有降级路径 / vendor 调用必须 host+upstream_text 双信号)与同类问题影响清单。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(knowledge): searchAcrossCorpora 聚合保留 KnowledgeError code 并修正 _map_exception_to_http docstring;

Review #1(前端契约): SearchResultError 仅透 message 会丢弃 KnowledgeError.code(如 EMBEDDING_FAILED),削弱本次 502/500 拆分对前端"上游修复 vs 自身错误"的可分流价值——本次扩展 SearchResultError 增加可选 code,rejection instanceof KnowledgeError 时回填;全失败分支由 throw new Error 改为 throw new KnowledgeError(aggregatedCode, msg, {errors}),code 一致时透传原 code、混合时退化为 AGGREGATED_SEARCH_ERRORS,既保留分流能力又携带逐条失败明细;新增 1 例同 code 透传 + 1 例混合 code 退化的单测,全部 4 例通过。

Review #2(后端文档): api._map_exception_to_http docstring 仍只列 400/404/409/500,与新增 EmbeddingFailed→502 分支不一致;本次补 "502: 上游服务错误(vendor / Embedding 等外部依赖)" 一行,避免后续维护者按旧映射加分支。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
ThreeFish-AI added a commit that referenced this pull request May 5, 2026
…at 双气泡终结 + YAML 配置统一 (#462)

* feat(agent-defs): 主 Agent 入库 + 按 DB 读 instruction + 模型选择回退 (#420)

* fix(agent-defs): 修复 Agent 加载路径 + 主 Agent 纳入 Interface Sync + 运行时按 DB 读 instruction;

- cli.py: --reload_agents 改用 Path(__file__) 推导的绝对路径,杜绝 cwd 依赖导致的「src/negentropy/negentropy」双重段错误;
- subagent_presets: 新增 NegentropyEngine root payload(adk_config.kind="root"),Sync 后 DB 出现主 Agent 行;
- sync API: 循环写入 config.kind,末尾调 invalidate_cache(prefix="subagent:") 批量失效;
- SubAgentResponse: 新增顶层 kind 字段(root/subagent),供前端置顶 + 徽章;
- model_resolver: 抽取 _load_subagent_row 共用单行查询,新增 resolve_subagent_instruction;
- _dynamic_instruction: 新增 InstructionProvider 工厂,root + 5 子 Agent 的 instruction 接入运行时 DB 读取;
- 测试: 更新 test_subagent_presets 覆盖 root payload + kind 断言;

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-llm): 修复无 Session 时模型选择回退 + SubAgents 列表 Root 置顶徽章;

- home-body: 新增 pendingLlmRef,改写 handleSelectedLlmModelChange 与 Effect 1,
  使「无 session 选模型→建 session→自动发送」全流程保持选择不丢失;
- SubAgents page: 按 kind="root" 置顶排序,Sync 按钮文案从「Sync Negentropy 5」改为「Sync Negentropy」;
- SubAgentCard: Root Agent 显示 violet 色 Root 徽章;

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(model-resolver): SubAgent 行缺失/未启用补回 60s TTL 负命中缓存;

回归点:重构 `_resolve_subagent_row` 时把空占位写入移到了 `loaded is None`
判断之后,导致禁用 Faculty 与未 Sync 环境下每次 LLM 请求都触发一次 DB 查询。
本次在 `loaded is None` 分支补 `_cache[cache_key] = ("", {"i": ""}, now)`,
让负命中同样落入 60s TTL,避免重复 DB 压力。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-llm): pending 模型选择仅对 startNewSession 新 id 消费;

回归点:Effect 1 的 pending 转移分支会在「首次进入既有 session」时触发,
把无 session 阶段的 pending 模型写入该 session 的 perThreadLlmRef,
并让 Effect 2 跳过 snapshot 初始化,导致服务器端记忆模型被静默替换。

修复方式:
- 新增 `pendingLlmTargetIdRef` 仅记录 startNewSession 返回的新 id;
- 通过 `startNewSessionWithLlmTarget` 包装内联调用与 `onNewSession` 两条路径;
- Effect 1 仅在 `sessionId === pendingLlmTargetIdRef.current` 时转移 pending,
  其余进入既有 session 的分支主动丢弃 pending,让 snapshot 正常生效。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(knowledge): 修复 KB Retrieve 全屏空白(前端聚合 rejection × 后端 hybrid/rrf 降级 × 502 上游错误码 × 诊断仪器化) (#421)

* fix(knowledge): 修复 Knowledge Base Retrieve 全屏空白(前端聚合 rejection + 后端 hybrid/rrf 降级 + 502 错误码 + 诊断日志);

双层 Bug 同因联修(详见 docs/issue.md ISSUE-026):
1. 前端 searchAcrossCorpora 旧实现以 Promise.allSettled 仅取 fulfilled,rejected 静默丢失,导致全部 Corpus 失败时返回 {count:0,items:[]} 走"成功路径"使 UI 空白且无任何提示——本次改为聚合三态(全成功/部分失败/全失败),SearchResults 类型扩展 errors[],handleRetrieve 对部分失败 toast.warning 透出原因;
2. 后端 service.search hybrid/rrf 旧实现未捕获 EmbeddingFailed,外部 Embedding 上游故障直接 500,丧失"keyword 仍可用"的优雅降级——本次 hybrid 失败回退 keyword-only、rrf 失败走与 not embedding_fn 等价的回退路径,semantic 仍传播以保留显式失败语义;
3. api.py _map_exception_to_http 拆分 EmbeddingFailed 分支映射到 502 Bad Gateway(保留 EMBEDDING_FAILED code),与 SearchError 自身错误的 500 区分,便于前端识别"上游修复后再试"语义;
4. embedding.py 调用 litellm 前后增加结构化诊断日志:api_base_host(脱敏 path/credentials 仅留 host)+ input_count + text_preview + kwargs_keys;失败附 upstream_response_text(沿异常链 __cause__/__context__ 提取 MaskedHTTPStatusError.text,已被 litellm 脱敏 URL,限长 500 字节);
5. 测试锁定:tests/unit_tests/knowledge/test_search_resilience.py 5 例(hybrid/rrf 降级 + semantic 传播 + EmbeddingFailed→502 + SearchError→500)+ tests/unit/knowledge/searchAcrossCorpora.test.ts 3 例(allSettled 三态);
6. docs/issue.md 追加 ISSUE-026,含后续防范(Promise.allSettled 必须聚合 rejection / vendor 失败必须 502 / hybrid 必须有降级路径 / vendor 调用必须 host+upstream_text 双信号)与同类问题影响清单。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(knowledge): searchAcrossCorpora 聚合保留 KnowledgeError code 并修正 _map_exception_to_http docstring;

Review #1(前端契约): SearchResultError 仅透 message 会丢弃 KnowledgeError.code(如 EMBEDDING_FAILED),削弱本次 502/500 拆分对前端"上游修复 vs 自身错误"的可分流价值——本次扩展 SearchResultError 增加可选 code,rejection instanceof KnowledgeError 时回填;全失败分支由 throw new Error 改为 throw new KnowledgeError(aggregatedCode, msg, {errors}),code 一致时透传原 code、混合时退化为 AGGREGATED_SEARCH_ERRORS,既保留分流能力又携带逐条失败明细;新增 1 例同 code 透传 + 1 例混合 code 退化的单测,全部 4 例通过。

Review #2(后端文档): api._map_exception_to_http docstring 仍只列 400/404/409/500,与新增 EmbeddingFailed→502 分支不一致;本次补 "502: 上游服务错误(vendor / Embedding 等外部依赖)" 一行,避免后续维护者按旧映射加分支。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(wiki-favicon): 修复 negentropy-wiki 站点 favicon.ico 单分辨率畸形导致浏览器回落默认地球图标; (#423)

- 根因:apps/negentropy-wiki/src/app/favicon.ico 是单分辨率畸形 ICO(file 输出 256x-1,高度字节 0xFF),且源图 logo.png 为非方形 800x798,导致 Chrome/Firefox/Safari 解析失败、tab 回落默认地球图标;
- 修复:用 Pillow 对 logo.png 做透明 padding 至 800x800 方形,再生成多分辨率 ICO(16/32/48/64/128/256 共六档)覆盖原文件;体积从 269KB 降至 118KB;
- 验证:file 输出 6 icons; pnpm build 后 .next/standalone 内 favicon route + body + meta 完整;pnpm start 后 curl /favicon.ico 返回 200 image/x-icon,HTML 自动注入 <link rel="icon">;
- 防范:docs/issue.md 追加 ISSUE-027,沉淀「ICO 必须方形 + 多分辨率」工程约束与 Pillow 流水线模板,禁止「原图直裹 ICO 头」反模式;
- 不动:layout.tsx / next.config.ts / start-production.mjs,保留 App Router metadata 自动注入路径,最小干预。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)

* feat(mcp-resources): 接入 Resource Templates 并贯通 PDF 图片到 Wiki Markdown (#422)

* feat(mcp-client): 接入 MCP Resource Templates 与同会话动态资源拉取;

新增 McpResourceTemplate 模型与 Alembic migration 0012,扩展 McpClientService 在
连接发现阶段并发调用 list_resource_templates(旧 server 不支持时静默兜底,不
阻断 tools 发现),新增 call_tool_and_resolve_resources:在同一 ClientSession 内
完成工具调用与所有 resource_link URI 的并发拉取(Semaphore 限流 4,return_exceptions
保证单条失败不击穿主流程)。这是接入 Negentropy Perceives 动态 FileResource
(perceives://pdf/<job_id>/<filename>)的协议层基石——动态实例的生命周期与工具
会话强绑定,必须在 session 关闭前完成 resources/read 才能避免事后失链。

Interface API 同步:load_mcp_server_tools 端点扩展为 capability 全量同步(tools
+ resource_templates,软删除已下线的 templates),LoadToolsResponse 新增
resource_templates 字段(向后兼容),新增 GET /mcp/servers/{id}/resource-templates
端点;list_mcp_servers 拆解为分段计数避免 JOIN 笛卡尔积;McpServerResponse 暴露
resource_template_count 给前端展示。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(perceives-resources): PDF 图片资源端到端贯通到 GCS 与 Wiki Markdown;

把 Perceives MCP 工具调用返回的 ResourceLink 接入既有提取流水线(Ingest 与
Re-Parse from GCS),让 PDF 图片资源在主仓 ↔ Perceives 之间通过 MCP 协议
完整贯通:

- 提取层(extraction.py):新增 _extract_resource_link_assets 把 ResourceLink
  与同会话 read_resource 拉取的 base64 配对为 ExtractionAsset;_call_tool_with_plan
  改用 resolve_resource_links=True 路径,确保动态 URI 不会因会话关闭失链;
  _build_success_result 接收 resolved_resources / resource_errors,按 "warn +
  占位" 容错策略合并 assets 并标记 partial_failure 不阻断主入库;新增
  _rewrite_markdown_image_links 在 Markdown 写入 GCS 之前把相对路径图片引用
  重写为 /api/documents/{doc_id}/assets/{filename},重写采用 capture group 偏移
  以避免 alt 文本含同名 src 时误替换。

- Knowledge API:新增 GET /knowledge/wiki/documents/{document_id}/assets/{filename}
  公开端点,filename 严格白名单 ^[A-Za-z0-9._-]+$ 与 180 字符上限;鉴权策略与
  既有 wiki entry content 端点对齐——仅放通至少被一条 WikiPublicationEntry
  引用的 document,避免持任意 doc_id 拖走未发布文档资产。

- 前端 MCP 卡片(negentropy-ui):新增 Resource Templates 折叠区与 ResourceDetailPanel,
  视觉与 Tools 区完全镜像;page.tsx 在 tools:load 响应中同步消费
  resource_templates 段,状态合并到 ServerWithTools;动态实例(带 job_id)
  按设计不入卡片。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(mcp-client): Resource Templates 同步加 capability flag,避免静默兜底误清空模板表;

`_discover_on_transport` 对 `list_resource_templates` 的所有异常都会静默兜底返回空列表(兼容旧 server 与瞬态错误),但 `load_mcp_server_tools` 会把空列表当作权威结果裁剪 stale 行,导致一次网络抖动或 server bug 即抹掉全部模板;同时与 tools 同步"只增量更新、不裁剪"的语义不对称。

- `McpConnectionResult` 新增 `resource_templates_listed: bool`,仅在 `list_resource_templates` 成功返回时为 True;
- `load_mcp_server_tools` 仅在该 flag 为 True(权威空列表)时才裁剪 stale 模板,未支持/错误场景保留既有 DB 行;
- 单元测试覆盖 flag 在权威空列表与异常兜底两种路径下的取值。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* test(mcp-card): 单测 server fixture 补 resource_template_count 修 UI Type Checks;

`McpServer` 类型新增的必填字段 `resource_template_count` 未同步到 `McpServerCard.test.tsx` 的 server 固件,导致 ui-quality / UI Type Checks 在 5 处 `<McpServerCard server={...}>` 调用上报 TS2741。

- 在 server 固件加 `resource_template_count: 0`,spread 派生用例自动获得新字段。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(knowledge): 查询时 honor Corpus 自配 embedding 模型,修复 query/index 模型不一致 (ISSUE-028) (#424)

search() 原直接使用实例化时锁定的 self._embedding_fn(全局默认 gemini/text-embedding-004),
未读 corpus.config.models.embedding_config_id;而 _attach_embeddings 索引侧已按 corpus pin 走
专属 fn。两侧不对称导致:用户在 Corpus Settings 已切到 openai/text-embedding-3-small(1536 维),
索引按 OpenAI 生成,查询仍走 Gemini 全局默认经 localhost:3392 翻译代理报 400。

修复:
- 新增 _resolve_embedding_fn(corpus_config) 助手,corpus pin 优先 → 退回 service 默认 fn;
- search() 入口加载 corpus_config + embedding_fn 本地变量,rrf/hybrid/semantic 三分支替换;
- ISSUE-026 keyword 兜底 + 502 映射 + 诊断日志原样保留,零回归;
- 新增 5 例单元测试覆盖 corpus pin 命中/落空/兜底/rrf/semantic 上抛,577 全绿。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)

* fix(agent-llm): 修复 Home Send 时 LLM 凭证未从 DB 读取导致 AuthenticationError (#425)

* fix(docs): 同步文档启动命令与 cli.py 修复,消除 Home Send 500 复发路径;

cli.py 的 agents_dir 已在 35204ff 从 src/negentropy 修正为 src,
但 README / docs 下 4 个文件 7 处仍写 --reload_agents src/negentropy,
用户照文档启动复现 ValueError: Agent not found 500。
统一替换为 uv run negentropy serve(SSOT),
追加 ISSUE-029(文档漂移)与 ISSUE-030(SubAgents root Agent 防回归)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(agent-llm): 修复 Home Send 时 LLM 凭证未从 DB 读取导致 AuthenticationError;

DynamicRootLiteLlm/DynamicSubagentLiteLlm 在 ContextVar 或 sub_agents.model
为空时直接返回 None,回退到构造时无 api_key 的硬编码实例,绕过了 DB 中
已配置的 vendor_configs 凭证。现在始终通过 resolve_llm_config() 从 DB
解析默认模型的完整凭证(含 api_key)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-chat): 修复长耗时回复双气泡 + 首条未格式化 (ISSUE-031); (#426)

ADK 仅持久化 partial=false 终态事件,realtime 与 hydration 在
同一逻辑消息上派出不同的 messageId(首个 partial id vs 终态 id)。
isSemanticEquivalentEntry 的 8s 时间窗在长耗时回复下硬拒绝,导致
ledger 双 entry → events 过滤失败 → conversation tree 双节点 →
UI 渲染双气泡(首条因 streaming-markdown 尾部判定走 raw text 分支)。

修复 (最小干预 + 正交分解):
- message-ledger.ts: 内容严格相等时跳过 8s 时间窗硬拒绝。
- conversation-tree.ts: assistant 已收尾节点在内容严格相等时
  也允许 findMatchingTextNodeId 命中复用,作为防御性收敛。
- 三层回归测试覆盖 ">8s 跨度 + messageId 不同 + 内容严格相等"。

UI 全量 70 文件 396 测试通过;typecheck/typecheck:test/eslint 零报错。
docs/issue.md 沉淀 ISSUE-031;CHANGELOG.md 同步条目。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)

* fix(home-chat): 修复 Home 对话 title 凭证缺失与 OTLP logs/metrics 404 双联缺陷 (#427)

* fix(home-chat): 修复 Home 对话 title 凭证缺失 + OTLP logs/metrics 404 双联缺陷;

(1) SessionSummarizer 同步 __init__ 在 60s 缓存 miss 时回退到无 api_key 硬编码默认,
导致 LiteLLM AuthenticationError;改为 async classmethod create() 经 resolve_llm_config()
从 DB 读取完整凭证(与 commit 8ce35d5 修复 DynamicRootLiteLlm 同 SoT),调用方
session_service._generate_title_for_session 切换为 await SessionSummarizer.create(),
对 resolver 返回 kwargs 做防御性浅拷贝避免与 60s 缓存层耦合。

(2) ADK 上游 _get_otel_exporters() 把 OTEL_EXPORTER_OTLP_ENDPOINT 视为 OTLP 三件套
总开关,无差别注册 OTLPSpanExporter / OTLPMetricExporter / OTLPLogExporter;后两者
对 Langfuse 不存在的 /v1/metrics、/v1/logs 上报触发 SPA 404 SSR 错误页(每次对话
反复输出大段 HTML)。bootstrap.py 新增 _install_noop_otel_logs_metrics_providers()
在 OTel env var 设置后立即抢注无 processor / 无 reader 的 SDK Logger/Meter Provider,
利用 OTel SDK Once-lock 让 ADK 后续 set_*_provider 静默 no-op,从而阻断 logs/metrics
上报;TracerProvider 链路与 OTEL_EXPORTER_OTLP_HEADERS 不动,traces 仍正常进入 Langfuse。

新增 tests/unit_tests/engine/test_summarization.py(3 例)+
tests/unit_tests/observability/test_otel_noop_providers.py(3 例,子进程隔离 OTel 全局
状态)锁定回归。CHANGELOG / docs/issue.md 沉淀 ISSUE-031(title 凭证缺失)与
ISSUE-032(OTLP logs/metrics 404)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* test(otel-noop): 移除 _sdk_config hasattr 兜底,让 SDK 私有属性变更显式触发回归;

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* test(session-title): 修复 DummySummarizer 缺失 async create() 导致集成测试 AttributeError;

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(bootstrap-otel): 消除 ADK Web 启动期 OTel Override Provider 双 WARNING (ISSUE-034); (#428)

将 ISSUE-033 的「抢占式 set_logger_provider/set_meter_provider」改为 patch
`google.adk.telemetry.setup._get_otel_exporters`,让其只返回 traces 的
span_processors,metric_readers/log_record_processors 永久置空。ADK
maybe_set_otel_providers 的 if 分支由此天然短路,set_*_provider 根本不被
调用,从源头消除 OTel SDK 的 "Overriding of current ... is not allowed"
WARNING;traces 链路、ADK ApiServerSpanExporter、TracingManager、LiteLLM
"otel" callback 行为完全不变。配套更新 3 个子进程隔离单测验证新语义,
并在 docs/issue.md 追加 ISSUE-034 完整记录。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)

* feat(e2e-auth): 浏览器验证协议落地 + Playwright 会话复用贯通 Google OAuth (#429)

* docs(browser-validation): 落地浏览器验证协议并补 ISSUE-034

- AGENTS.md(即 CLAUDE.md symlink)新增"Browser Validation Protocol"子节,
  约定登录态浏览器验证必须复用用户常用 Chrome 会话,禁止 sandbox 浏览器
  通过 Google 同意屏,明确凭证守则与三步连通性自检;
- 新建 docs/agents/browser-validation.md:含三种 MCP 浏览器工具能力对照、
  Mermaid 选型决策图、storageState 工作时序、风控应对、IEEE 引用;
  实测附注 chrome-devtools MCP 在 macOS 默认即可复用用户主 profile 登录态;
- docs/issue.md 追加 ISSUE-034,记录 sandbox 浏览器走 Google OAuth 被拦
  的表因/根因/处理方式/防范,便于跨上下文复用。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* test(e2e-auth): Playwright 会话复用以贯通 Google OAuth E2E

- playwright.config.ts 在 PLAYWRIGHT_AUTH=1 时启用两个项目:
  * setup(headless: false,匹配 *.setup.ts),让用户在弹出窗手动登录;
  * chromium-authenticated(dependencies: ['setup']),使用 storageState
    复用一次性人工登录的会话;
  支持 PLAYWRIGHT_STORAGE_STATE 与 PLAYWRIGHT_USER_DATA_DIR 覆盖默认;
  现有 chromium project 加 testIgnore 排除 .setup.ts,CI/默认行为零变;
- 新增 tests/e2e/auth.setup.ts:打开 /auth/google/login,5 分钟内允许
  用户在 Google 同意屏中手动完成登录,回跳后断言 /api/auth/me 2xx,
  写入 storageState;
- .gitignore 追加 apps/negentropy-ui/.auth/ 与 .userdata/,
  防止会话凭证随分支推送外泄。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(e2e-auth): 修复 OAuth setup 早退与 authed spec 双跑;

- auth.setup.ts: waitForURL 谓词追加 host 约束,避免在跳往 accounts.google.com
  瞬间因 pathname 已离开 /auth/google 而误判完成,导致 /api/auth/me 在用户登录前
  失败、storageState 永不写出。
- playwright.config.ts: 基础 chromium project 的 testIgnore 追加
  /.*\.authed\.spec\.ts$/,防止 PLAYWRIGHT_AUTH=1 时同一份认证 spec 在
  chromium-authenticated 与 chromium 中各跑一次(后者无 storageState 必失败)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-chat): 修复 Home 双气泡复发与 LLM 模型未 Send 即刷新丢失 (ISSUE-032/033); (#430)

ISSUE-032 (双气泡复发,与 ISSUE-031 正交):
- 根因:root agent prompt 主动导航 + log_activity tool 让 ADK 走双轮 LLM 调用,
  两轮各自带独立 messageId 走完整 TEXT_MESSAGE_* 三件套,UI 在同一
  assistant-reply bubble 内并列渲染两段近重复文本。
- 修复:utils/chat-display.ts::dedupeRedundantTextSegments 在
  buildAssistantReplyBlock 出口对同一 reply 内的 text segment 做字符二元组
  Jaccard 相似度计算,相似度 ≥ 0.5 且双方长度 ≥ 30 时丢弃前段、保留信息更
  完备的最终段。tool-group / reasoning / error 顺序不动。
- assistant-reply.message.content 联动重组,复制时也拿到折叠后的内容。

ISSUE-033 (LLM 模型未 Send 即刷新丢失):
- 根因:后端事实源 session.state.selected_llm_model 仅在 /run_sse 时随
  state_delta 写入,未 Send 时不更新;前端 perThreadLlmRef 是 useRef
  刷新即丢;snapshotForDisplay 也无值,回退到 default。
- 修复:app/home-body.tsx 顶部新增 readPersistedLlmModel /
  writePersistedLlmModel (typeof window 守卫 + try/catch SSR 安全);
  handleSelectedLlmModelChange 即时落盘到 localStorage;Effect 1 优先
  从 localStorage 还原;Effect 2 命中 snapshot 时同步回写 localStorage,
  让「后端 state ↔ localStorage」互为镜像。既有 forwardedProps.selected_llm_model
  在 Send 时仍写后端 state,跨设备一致性最终收敛。

测试:
- 新增 2 例 chat-display.test.ts 用例:折叠近重复段 + 差异度大不被折叠
- UI 全量 70 文件 398 测试通过;typecheck/typecheck:test/eslint 零报错

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)

* fix(bootstrap-otel): 消除被丢弃 PeriodicExportingMetricReader 守护线程的周期 WARNING (ISSUE-038) (#431)

* fix(bootstrap-otel): 消除被丢弃 PeriodicExportingMetricReader 守护线程的周期 WARNING (ISSUE-038);

ISSUE-034 的 patch 调用 original() 后再丢弃 metric_readers /
log_record_processors,但上游 _get_otel_exporters 已构造
PeriodicExportingMetricReader 并启动 60s 守护线程——reader 未注册
到 MeterProvider 导致每 tick 触发 "Cannot call collect on a
MetricReader ..." WARNING。改为绕过 original(),直接复用
_get_otel_span_exporter() 仅构造 traces span processor,根源
避免 OTLP metrics/logs exporter 被实例化。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* docs(bootstrap-otel): 修正 _disable_adk_otel_logs_metrics_exporters docstring 中的过期 hooks 引用;

旧 docstring 沿用重构前 `hooks = original()` 的中间变量术语,但新实现已不再调用 `original()`,函数体内也没有 `hooks` 绑定。
更新指引为「恢复 _get_otel_exporters 原函数闭包」或「直接构造完整 OTelHooks」,避免误导后续维护者寻找已不存在的对象。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-chat): 修复 Home 双气泡盲区与刷新后消息乱序 (ISSUE-039) (#432)

* fix(home-chat): 修复 Home 双气泡盲区与刷新后消息乱序 (ISSUE-038);

- chat-display: dedupeRedundantTextSegments 增加四层判定(精确匹配 / 严格前缀 / 等价内容 / Jaccard),覆盖 ADK 双轮 LLM 短回复(如 "Pong!")的双气泡盲区。
- session-hydration: mergeEventsWithRealtimePriority 交换参数顺序,让 realtime 事件覆盖 hydrated;TEXT_MESSAGE_CONTENT 的 eventKey 时间戳改用 toFixed(3) 消除浮点抖动导致的同一事件重复保留。
- message-ledger: MessageLedgerEntry 新增可选 sourceOrder 作 createdAt 相同时的稳定 tiebreaker,替代 UUID localeCompare 的随机字典序;抽出 compareLedgerEntriesByTime 复用,类型保持向后兼容(缺省回退 Number.MAX_SAFE_INTEGER)。
- 新增 5 项单元测试覆盖:短回复精确匹配、前缀含尾部追加、Jaccard 长文本、eventKey 浮点稳定、sourceOrder 稳定排序;docs/issue.md 增补 ISSUE-038 摘要。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* test(home-chat): 补 mergeEventsWithRealtimePriority 生命周期事件覆盖回归用例;

针对 ISSUE-039 第 3 项修复(mergeEventsWithRealtimePriority 参数顺序交换)
原有 RUN_STARTED 类生命周期事件用例缺位——之前的 messageId 重叠用例在
step 3 即被过滤为 filteredHydratedEvents=[],无法验证 step 4 mergeEvents
入参顺序对 key 冲突归并的影响。

补一条 RUN_STARTED 用例:realtime / hydrated 同 threadId/runId/timestamp
(eventKey 字节级一致)→ 用对象引用断言保留的是 realtime 版本,作为参数
顺序交换的最直接证据。该用例在交换前会失败、交换后通过,形成有效回归网。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-chat): 消除 LLM 思考独白溢出 / 推理头常驻 / 刷新乱序残留 (ISSUE-040) (#433)

* fix(home-chat): 消除 LLM 思考独白溢出 / 推理头常驻 / 刷新乱序残留 (ISSUE-040);

- 过滤 ADK Part 中 thought=true 与 type=thinking|thought|reasoning 系列推理字段,避免 reasoning_content 溢出到 TEXT_MESSAGE_CONTENT;推理文本改路由为 ne.a2ui.thought 自定义事件保留可观测性。
- createStepFinishedEvent 同步透出 stepName,AdkMessageStreamNormalizer 持有 stepId→stepName 映射,根治 ag-ui v0.0.47 校验器 "Cannot send 'STEP_FINISHED' for step \"undefined\"" 中断 run 导致的推理头永驻 started 现象。
- conversation-tree fallback 段重建消息节点时优先复用 ledger 已有 sourceOrder,避免被推到 events 末尾破坏 compareLedgerEntriesByTime tiebreaker。
- session-hydration eventKey 全事件类型统一走 toFixed(3) 毫秒级时间戳,并为 STEP_STARTED/STEP_FINISHED 显式按 (threadId, runId, stepId) 作 key,覆盖 STEP_*/CUSTOM/STATE_*/RAW 在浮点抖动下的去重盲区。
- 新增 9 例单元回归覆盖 thought part 过滤 / STEP_FINISHED stepName / fallback sourceOrder / eventKey 浮点抖动;docs/issue.md 追加 ISSUE-040 全栈解析。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-chat): 消除 hydration sort 字典序污染 lifecycle 顺序导致的多消息刷新乱序 (ISSUE-040 Q3 长尾);

- hydrateSessionDetail 引入 WeakMap<BaseEvent, emitOrder>,sort tiebreaker 用 normalizer 推入顺序代替 eventKey().localeCompare,保留 TEXT_MESSAGE_* 三件套 START→CONTENT→END 与跨 messageId 的 turn 边界。
- mergeEvents 同步改为按首次出现位置记录 insertionOrder 作 tiebreaker,避免最后一步 mergeEvents([], normalizedEvents) 再把刚排好的事件按字典序乱序。
- 新增同 timestamp 下 lifecycle 顺序断言用例;多轮真实后端 events fixture 经修复链路输出 user(R1)→assistant(R1)→user(R2)→assistant(R2) 完全符合时间线。
- docs/issue.md 在 ISSUE-040 末尾追加 Q3 长尾闭环(H5 字典序污染根因与最小干预修复)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* test(home-chat): 强化 ISSUE-040 H3 fallback sourceOrder 回归用例;

- 旧用例与单 snapshot 单条消息时新旧公式恰巧同值,断言无差异,无法拦截 H3 退化;
- 新用例构造「snapshot 数组顺序 vs ledger 时间序」错位场景:让 sourceOrder 在两条消息间发生互换,对回滚 H3 修复有强差异断言(已本地反向核验:回滚 conversation-tree.ts 修复后断言失败)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(wiki-header): catalog 第一层提升为顶部 Header 导航 tabs (#434)

* feat(wiki-header): catalog 第一层提升为顶部 Header 导航 tabs;

将 publication catalog 的第一层 CONTAINER 节点(如 Harness-Engineering)
从左侧 Sidebar 迁移为顶部 Header tabs;第二层及以下保留于 Sidebar,整树向上提升一档。
设计参考 GitHub Docs / Stripe Docs / Docusaurus 的"顶 tabs + 左 sidebar 子树"模式。

主要变更:
- lib/wiki-api.ts 追加 findFirstDocumentSlug / findActiveTopLevelSlug / resolveSectionView
  纯函数,作为 Header tabs 与 Sidebar 切片的单一事实源。
- 新增 WikiHeader Server Component(仅 <Link>,SSG 友好):渲染品牌 + 水平 tabs;
  CONTAINER tab 跳转 DFS 首个后代 DOCUMENT;无文档则禁用 span。
- WikiLayoutShell 增加 header? prop,渲染于 .wiki-layout 之外作为兄弟节点,
  避免触动既有 3 列 Grid 与 data-toc 三态。
- /{pubSlug} 与 /{pubSlug}/{...entrySlug} 两条路由共用 resolveSectionView 派生视图:
  pub 根页默认激活首项;entry 页按 slug 反查所属一级。
- globals.css 引入 --wiki-header-height 并把 sidebar / toc-aside 的 sticky top
  改为 var 引用,确保滚动时 Header 常驻不挡 sidebar。
- 新增 wiki-section-view.test.ts 12 用例覆盖空树 / 单 / 多 / 深路径 / DOCUMENT-only
  / 无后代 DOCUMENT 等边界。

回归保障:home / 不变;既有 WikiNavTree / WikiToc 测试 API 未变;47/47 单测全绿。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(wiki-header): Header 缺失时 sidebar/toc 不再残留偏移;

通过 data-header 属性标记 Header 是否存在,CSS 侧条件生效
--wiki-header-height 偏移,避免空导航树时出现 56px 空白间隙。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* refactor(config): 废弃 .env*,统一 YAML 三级配置(local > user > default) (#436)

* refactor(config): 废弃 .env* 加载链路,引入 config.local.yaml 统一 YAML 三级配置;

- 移除 10 个 Python 配置模块中的 env_file / _get_env_files 逻辑
- yaml_loader 新增 config.local.yaml 作为最高优先级 YAML 来源
- config.default.yaml 合并 .env 全部非机密差异值(含 OAuth 端口 6600→3292 校正)
- 新增 3 例 config.local.yaml 优先级测试

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* docs(config): 同步 .env 废弃后的文档与 CHANGELOG;

- development.md / sso.md / framework.md / user-guide.md / zh-CN/README.md 中 .env 引用替换为 config.local.yaml
- CHANGELOG 新增 ISSUE-041 变更记录
- docs/issue.md 新增 ISSUE-041 经验沉淀
- .gitignore 新增 apps/negentropy/config.local.yaml 排除规则

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(config): 放宽 .gitignore 中 config.local.yaml 匹配规则,覆盖任意 cwd 场景;

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-chat): 修复 realtime + hydration 跨 runId 双气泡复发 (ISSUE-041) (#435)

* fix(home-chat): 修复 realtime + hydration 跨 runId 双气泡复发 (ISSUE-041);

- 新增 isSyntheticRunId 共享识别函数(覆盖 runId 缺失 / DEFAULT_RUN_ID / runId === threadId 三类合成回退标记),三层 dedup 一致放宽:
  1. message-ledger.ts::isSemanticEquivalentEntry:runId 不等时若任一侧 synthetic 则放行,threadId + role + 内容前缀 + origin 多元仍是必要约束;
  2. conversation-tree.ts fallback 段 runMatches:识别合成 runId 兼容分支,避免同内容 fallback message 被强制重建为重复节点;
  3. conversation-tree.ts collapseDefaultTurnDuplicates → collapseSyntheticTurnDuplicates:扩展为识别 runId === threadId 的合成 turn;时间窗判定改为 per-child timestamp vs concrete turn timeRange,多轮场景下不再误放过期 concrete turn。
- session-hydration.ts::fallbackRunId 注释 ISSUE-041 契约(保留兜底防御,等 Phase 2 后端代理层注入 runId 后再渐进移除)。
- 新增 16 例自动化回归(含 1 例反向回滚断言):
  · message-ledger A1-A5 + isSyntheticRunId 单元 + 端到端 ledger merge(共 7 例);
  · conversation-tree C1/C2/C3/C5 + D4 反向回滚(共 5 例);
  · session-hydration D1/D1+/D2/D3 端到端(共 4 例)。
- docs/issue.md 追加 ISSUE-041 全栈解析(含 refresh 自愈非对称的根因证据、多轮二阶恶化、Phase 2-4 路线图、诊断抓手与同类问题影响),闭环 ISSUE-040 Q3 长尾自识别。

回归状态:482 测试全绿 + tsc 0 错误;浏览器实机 5 场景 × 3 次验证清单见 .context/issue-041/validation-protocol.md,待用户已登录态 Chrome 桥接就绪后执行。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* docs(rfcs): 新增 Phase 3 / Phase 4 架构 RFC 草稿(ISSUE-041 后续路线图);

- docs/rfcs/0001-conversation-architecture-refactor.md:Phase 3 架构重塑 RFC(Codex Thread→Turn→Item 数据模型 / 6 层去重金字塔精简到 3 层 / 抽象 utils/dedup/ + config/projection-thresholds.ts / 投影缓存 / 8 sub-PR 渐进迁移路线 / 兼容性回归与风险评估)。
- docs/rfcs/0002-ui-interaction-enhancements.md:Phase 4 UI 交互能力 backlog(Reasoning Panel + Sub-Agent 嵌套 / 工具进度 + 中断审批 / Conversation Branching + Timeline 增强;按用户优先级 1/2/3 分组,附实施依赖图与 Acceptance Criteria)。

均为 Draft 状态,待团队评审通过后启动多 PR 渐进迁移。本 commit 仅文档先行,不动代码。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-chat): 增强 synthetic turn 折叠相似度判定与时间窗整体吸收 (ISSUE-041);

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-chat): 双层防御消除跨 runId 三气泡——泛化 turn 折叠 + 跨 block 去重 (ISSUE-041);

将 collapseSyntheticTurnDuplicates 泛化为 collapseOverlappingTurns:按 threadId 分组,
对 synthetic turn 与同组 concrete turn 时间重叠+内容覆盖的进行折叠(双 concrete turn
保留以防误折叠合法多 run);新增 chat-display 层 dedupeAdjacentAssistantBlocks
作为安全网,对时间窗内内容高度相似的相邻 assistant-reply block 保留更完整的一个。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(test): 补充 message-ledger 测试 fixture 缺失的 id 字段 (ISSUE-041)

tsconfig.vitest.json 类型检查报 TS2741:baseRealtime 对象缺少
MessageLedgerEntry 必需的 id 属性。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(chat-display): 修复跨 block 去重时间窗单位错误 + 消除 bigramJaccard 重复实现 (ISSUE-041);

- CROSS_BLOCK_TIME_WINDOW_MS=120000 误将毫秒值与秒级时间戳比较,实际窗口约 33 小时
  而非预期的 2 分钟;改为 CROSS_BLOCK_TIME_WINDOW_SEC=120(秒)
- 移除 chat-display.ts 私有的 computeCharBigrams / bigramJaccard,统一从 message.ts
  导入 bigramJaccardSimilarity,避免两处实现分叉

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-chat): 修复 realtime + hydration 跨 runId 双气泡复发 (ISSUE-041) (#437)

* fix(home-chat): 修复 realtime + hydration 跨 runId 双气泡复发 (ISSUE-041);

- 新增 isSyntheticRunId 共享识别函数(覆盖 runId 缺失 / DEFAULT_RUN_ID / runId === threadId 三类合成回退标记),三层 dedup 一致放宽:
  1. message-ledger.ts::isSemanticEquivalentEntry:runId 不等时若任一侧 synthetic 则放行,threadId + role + 内容前缀 + origin 多元仍是必要约束;
  2. conversation-tree.ts fallback 段 runMatches:识别合成 runId 兼容分支,避免同内容 fallback message 被强制重建为重复节点;
  3. conversation-tree.ts collapseDefaultTurnDuplicates → collapseSyntheticTurnDuplicates:扩展为识别 runId === threadId 的合成 turn;时间窗判定改为 per-child timestamp vs concrete turn timeRange,多轮场景下不再误放过期 concrete turn。
- session-hydration.ts::fallbackRunId 注释 ISSUE-041 契约(保留兜底防御,等 Phase 2 后端代理层注入 runId 后再渐进移除)。
- 新增 16 例自动化回归(含 1 例反向回滚断言):
  · message-ledger A1-A5 + isSyntheticRunId 单元 + 端到端 ledger merge(共 7 例);
  · conversation-tree C1/C2/C3/C5 + D4 反向回滚(共 5 例);
  · session-hydration D1/D1+/D2/D3 端到端(共 4 例)。
- docs/issue.md 追加 ISSUE-041 全栈解析(含 refresh 自愈非对称的根因证据、多轮二阶恶化、Phase 2-4 路线图、诊断抓手与同类问题影响),闭环 ISSUE-040 Q3 长尾自识别。

回归状态:482 测试全绿 + tsc 0 错误;浏览器实机 5 场景 × 3 次验证清单见 .context/issue-041/validation-protocol.md,待用户已登录态 Chrome 桥接就绪后执行。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* docs(rfcs): 新增 Phase 3 / Phase 4 架构 RFC 草稿(ISSUE-041 后续路线图);

- docs/rfcs/0001-conversation-architecture-refactor.md:Phase 3 架构重塑 RFC(Codex Thread→Turn→Item 数据模型 / 6 层去重金字塔精简到 3 层 / 抽象 utils/dedup/ + config/projection-thresholds.ts / 投影缓存 / 8 sub-PR 渐进迁移路线 / 兼容性回归与风险评估)。
- docs/rfcs/0002-ui-interaction-enhancements.md:Phase 4 UI 交互能力 backlog(Reasoning Panel + Sub-Agent 嵌套 / 工具进度 + 中断审批 / Conversation Branching + Timeline 增强;按用户优先级 1/2/3 分组,附实施依赖图与 Acceptance Criteria)。

均为 Draft 状态,待团队评审通过后启动多 PR 渐进迁移。本 commit 仅文档先行,不动代码。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-chat): 增强 synthetic turn 折叠相似度判定与时间窗整体吸收 (ISSUE-041);

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-chat): 双层防御消除跨 runId 三气泡——泛化 turn 折叠 + 跨 block 去重 (ISSUE-041);

将 collapseSyntheticTurnDuplicates 泛化为 collapseOverlappingTurns:按 threadId 分组,
对 synthetic turn 与同组 concrete turn 时间重叠+内容覆盖的进行折叠(双 concrete turn
保留以防误折叠合法多 run);新增 chat-display 层 dedupeAdjacentAssistantBlocks
作为安全网,对时间窗内内容高度相似的相邻 assistant-reply block 保留更完整的一个。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(test): 补充 message-ledger 测试 fixture 缺失的 id 字段 (ISSUE-041)

tsconfig.vitest.json 类型检查报 TS2741:baseRealtime 对象缺少
MessageLedgerEntry 必需的 id 属性。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(chat-display): 修复跨 block 去重时间窗单位错误 + 消除 bigramJaccard 重复实现 (ISSUE-041);

- CROSS_BLOCK_TIME_WINDOW_MS=120000 误将毫秒值与秒级时间戳比较,实际窗口约 33 小时
  而非预期的 2 分钟;改为 CROSS_BLOCK_TIME_WINDOW_SEC=120(秒)
- 移除 chat-display.ts 私有的 computeCharBigrams / bigramJaccard,统一从 message.ts
  导入 bigramJaccardSimilarity,避免两处实现分叉

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-chat): 修复跨 runId 双气泡时间窗单位错误 + 消除 bigramJaccard 重复实现 (ISSUE-041);

fallback 路径从无条件移除改为内容覆盖检查——跨所有同 threadId keeper 逐 child
匹配,避免含独特历史内容的 synthetic turn 被误折叠。加强 C3 断言为
toHaveLength(2) + synthetictoBeDefined。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(conversation-tree): isSyntheticTurnNode 补充 "default" runId 识别对齐 isSyntheticRunId (ISSUE-041);

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(ctl): 新增全套服务一键启停脚本 (#438)

* feat(ctl): 新增全套服务一键启停脚本 scripts/ctl.sh

支持 start/stop/restart/status/logs/build 子命令,覆盖依赖安装、
数据库迁移、前端构建、健康检查的完整生命周期。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(ctl): 修复 is_running 变量泄漏与并行 wait 退出码丢失;

- is_running() 中 pid_file 添加 local 声明,防止全局作用域污染
- 三处并行 wait 改为逐个检查退出码,任一子进程失败即报错中止

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(ctl): 修复健康检查不感知进程崩溃、路径逻辑重复与服务名校验缺失;

- wait_for_health 在 HTTP 轮询间隔中加入 is_running 检查,进程崩溃时立即返回失败
- is_running 改用 pid_file() 函数获取路径,消除硬编码重复
- cmd_logs 入口校验服务名是否属于 ALL_SERVICES,非法名称给出明确提示

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(ctl): 使用 exec 替代 eval 确保进程 PID 精确追踪与信号直达;

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(kg): 知识图谱模块生产就绪改造 — 实体管理、混合检索、路径探索、统计面板 (#439)

* feat(kg): 知识图谱模块生产就绪改造 — 语料库级图谱、实体管理、混合检索、路径探索、统计面板

后端变更:
- 新增 GET /graph/entities 实体分页列表(类型筛选+名称搜索)
- 新增 GET /graph/entities/{id} 实体详情含出/入关系
- 新增 GET /graph/stats 图谱统计(实体数/类型分布/置信度/密度/度数)
- 重写 find_neighbors: 递归 CTE 在 kg_relations 上实现多跳遍历
- 重写 find_path: 递归 CTE BFS 在 kg_relations 上查找最短路径

前端变更:
- 重写 graph/page.tsx: 语料库选择器 + 构建/浏览全流程
- 新增 EntityListPanel: 表格视图+类型筛选+分页
- 新增 EntityDetailPanel: 实体详情+关系列表(出边/入边)
- 新增 SearchBar: 混合检索(语义+图结构)
- 新增 PathExplorer: 双实体选择+BFS路径查找
- 新增 NeighborExplorer: 1/2/3跳邻居展开
- 新增 GraphStatsPanel: 实体数/类型分布/置信度/密度/度数
- 新增 BuildHistoryList: 结构化构建历史卡片(状态徽章+统计+耗时)

文档变更:
- 扩展 user-guide.md §4.5 为完整知识图谱用户指引
- 更新 knowledge-graph.md §3 新增架构模式精炼(Cognee ECL/Graphiti 双时态)
- 更新 knowledge-graph.md §4 交付物清单

测试变更:
- 新增 test_graph_entity_service.py: 9 项单元测试覆盖实体列表/详情/Schema

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(kg): 修复知识图谱模块 CI 失败 — 类型错误、ID 前缀、测试 mock;

- 移除 NeighborExplorer 组件调用中不存在的 entityName prop(TS2322)
- 为 find_neighbors 返回的 GraphNode.id 补齐 entity: 前缀
- 重写 find_path 测试,mock session.execute 而非 find_neighbors

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(kg): 修复审查发现的 7 项问题 — 安全编码、状态管理、双向路径搜索;

- 路由 path params 加 encodeURIComponent 防路径遍历(3 个 route 文件)
- EntityDetailPanel: 用 loadedEntityId 派生 loading 状态,切换实体时正确展示加载态并清除旧数据
- EntityListPanel: 搜索输入 300ms 防抖,用 completedKey 派生 loading 状态
- GraphStatsPanel: 用 result 组合状态区分加载中/失败/成功
- NeighborExplorer: entityId 变更时重置 expanded/neighbors
- graph_repository find_path: 递归 CTE 增加反向遍历分支,与 find_neighbors 双向语义对齐

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(kg): 修复审查发现的遗留问题 — 常量提取、路径搜索、会话管理;

- 前端:提取 ENTITY_TYPE_COLORS 至 constants.ts,消除三处 TYPE_COLORS 残留引用(会导致运行时崩溃)
- 后端:修复 find_path 递归 CTE 中 path 追加错误(r.target_id → ps.target_id)
- 后端:get_stats 改为接收外部 db 会话,消除自建会话
- 后端:get_entity_detail 增加 corpus_id 可选过滤,增强数据隔离

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(memory): 记忆模块生产就绪化 — 巩固管线重构 + 事实提取 + 上下文集成 + 文档完善 (#440)

* feat(memory): 重构记忆巩固管线为三阶段智能架构并增强核心模块

- 重构 _simple_consolidate 为三阶段管线(分段→去重→存储),借鉴 Claude Code AutoDream 四阶段范式
- 新增 PatternFactExtractor 基于正则模式的对话事实自动提取(preference/profile/rule/custom)
- 新增 ContextAssembler 记忆上下文组装器,管理 token 预算分配(30%记忆/50%历史/20%系统)
- 新增 AsyncScheduler 应用层调度器回退,当 pg_cron 不可用时提供等效定时任务能力
- 增强 search_memory API 支持分页(limit/offset)和过滤(memory_type/date_from/date_to)
- 集成 ContextAssembler 到 perception.py 记忆搜索回退路径
- 新增 34 条单元测试覆盖事实提取和调度器(全部通过)

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* docs(memory): 补充工业框架对标分析与用户操作指南

- docs/memory.md §2.4 新增 Claude Code 记忆架构深度对标(AutoDream 四阶段整理、三重门控调度、四类型分类法、三层上下文压缩、漂移防御)
- docs/memory.md §2.5 新增 Agent Harness 设计模式对标(三层压缩管线、Skill 按需加载、Task Graph 持久化)
- docs/memory.md §2.6 新增 Negentropy 差异化定位总结表
- docs/user-guide.md §5.8-§5.12 新增记忆形成机制、保留分数解读、搜索最佳实践、自动化配置指南、故障排除

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(memory): 恢复巩固管线 metadata 中遗漏的 event_count 字段

三阶段管线重构后 metadata 字典遗漏了原有的 event_count 字段,
导致 test_memory_service_lifecycle 集成测试 KeyError 失败。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(memory): 修复 Code Review 反馈的 7 项问题

1. search_memory 的 memory_type/date_from/date_to/offset 过滤参数现在在 vector_search 和 ilike_search 中实际生效
2. context_assembler 的 lazy import 移至文件顶部,与同文件风格一致
3. _simple_consolidate docstring 从「三阶段」更正为「四阶段」(含事实提取)
4. api.py search_memories 的 total 字段添加 TODO 标记(需独立 COUNT 查询)
5. AsyncScheduler 失败时回退 last_run_at,允许尽快重试而非等完整 interval
6. PatternFactExtractor 三段重复遍历提取为 _match_patterns 辅助方法
7. _consolidate SQL 拼接改为参数化绑定 :lookback::interval,消除注入风险

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(memory): 修复 Code Review 反馈的 3 项问题

- offset 分页参数未透传到底层搜索方法,现已正确传递
- datetime.fromisoformat() 缺少校验,非法日期返回 400 而非 500
- AsyncScheduler 派发任务未被追踪,stop() 时一并取消在途任务

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(memory): 修复 Code Review 反馈的 2 项问题

- 巩固管线阶段 4 事实提取调用包裹 try/except,防止导入或工厂失败中断管线
- 搜索接口 total 字段改为 -1 标记"未知",避免分页客户端误读

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(memory): 记忆模块 Phase 2 — LLM 事实提取 + 摘要生成 + Token 精确计数 + 检索反馈闭环 (#442)

* feat(memory): 记忆模块 Phase 2 — LLM 事实提取 + 摘要生成 + 精确 Token 计数 + 检索反馈闭环

- TokenCounter: 基于 tiktoken cl100k_base 编码器精确计数,替代 LENGTH/4 粗略估算
- LLMFactExtractor: LLM 结构化输出事实提取,PatternFactExtractor 作为降级后备
- MemorySummarizer: LLM 生成结构化用户画像摘要,缓存至 memory_summaries 表(TTL 24h)
- SummaryService: memory_summaries 表 CRUD(upsert 语义)
- RetrievalTracker: 检索效果反馈闭环,记录检索事件 + 显式反馈 API
- ContextAssembler: 优先注入摘要,tiktoken 精确 token 计数
- 新增 Alembic migration 0013/0014(memory_summaries + memory_retrieval_logs)
- 新增 MemorySummary + MemoryRetrievalLog ORM 模型
- 11 条新增单元测试,62 条全部通过,零回归

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* docs(memory): Phase 2 文档沉淀 — 两级提取策略 + 摘要巩固 + 精确计数 + 检索反馈 + 新增文献

- §4.2 扩展为两级事实提取策略说明(LLMFactExtractor + PatternFactExtractor)
- §5.4.1 新增摘要巩固策略(记忆再巩固理论 + 5 项工程对标)
- §6.3 更新 Token 估算为 tiktoken BPE 精确计数
- §6.5 新增检索效果反馈闭环(Rocchio + LTR + LongMemEval 评估维度)
- §15 新增 6 篇参考文献(Sennrich 2016, Sara 2015, Rocchio 1971, Burges 2005, Mem0, Letta)

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(memory): 修复 LLM 事实提取 prompt 类型名不匹配 + 检索指标 SQL 聚合优化;

- prompt 模板中 "pref" 改为 "preference",与 _VALID_FACT_TYPES 验证器对齐,避免 LLM 输出被静默降级为 "custom"
- get_effectiveness_metrics 改用 SQL COUNT+CASE 聚合,避免将全量日志行加载到 Python 内存

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* refactor(memory): Review 反馈修复 — 检索日志可观测性 + query 透传 + 模型配置去重;

1. 检索追踪 except 从 silent pass 改为 logger.debug,使故障可诊断
2. _record_access 新增 query 参数并从所有调用点透传,消除空 query 问题
3. 提取 _resolve_model_config 为共享工具 engine/utils/model_config.py,
   LLMFactExtractor 和 MemorySummarizer 统一引用,消除 DRY 违规
4. 同步更新单元测试 mock 路径

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(kg): 修复图谱双写数据流断链 — 一等公民表对齐 (#441)

* fix(kg): 修复图谱双写数据流断链 — 一等公民表对齐

- create_relation() 新增写入 kg_relations 一等公民表,保留 JSONB 过渡兼容
- get_graph() 优先从 kg_entities + kg_relations 读取,空时回退 JSONB
- clear_graph() 增加 kg_entities/kg_relations 表清理
- build_graph() 完成后调用 KgEntityService.batch_sync_from_graph_build()
- 更新 test_graph_repository 适配新读写路径

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(kg): 新增 PageRank 实体重要性评分与 RRF 混合检索

- 新增 graph_algorithms 模块,基于 NetworkX 实现 PageRank (Brin & Page, 1998) 计算,
  结果持久化至 kg_entities.importance_score
- 混合检索支持 Reciprocal Rank Fusion (Cormack et al., SIGIR 2009) 模式,
  可通过 GraphQueryConfig.use_rrf / rrf_k 配置,向后兼容线性加权模式
- 图谱构建完成后自动触发 PageRank 计算
- 实体列表支持按重要性排序(sort_by=importance)
- 统计面板展示 Top 5 PageRank 实体
- 图谱可视化节点半径映射 PageRank 分数,突出重要实体

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(kg): 新增 Louvain 社区检测与图谱可视化增强

- 新增 compute_louvain() 算法,基于 NetworkX 内置 Louvain (Blondel et al., 2008)
  在无向投影图上运行社区检测,结果持久化至 kg_entities.community_id
- 图谱构建完成后自动触发 Louvain 计算(紧接 PageRank 之后)
- 统计面板新增社区分布(community_count + community_distribution)
- 实体列表和详情响应包含 community_id 字段
- 图谱可视化节点按社区着色(Tableau 10 色盲友好调色板)
- 统计面板展示 Top 8 社区分布柱状图
- 实体表格新增社区列,显示色块标识
- 显式声明 networkx>=3.0 依赖(此前为隐式运行时导入)

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(kg): 新增 Alembic migration 0015 — 添加 importance_score 和 community_id 列

CI 集成测试失败根因:ORM 模型新增了 importance_score (PageRank) 和 community_id (Louvain)
列,但缺少对应的 Alembic migration,导致测试数据库 schema 不匹配。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(kg): 修复 Review 反馈的三个问题

1. RRF 搜索 graph_score 恒为 0 — 将 importance_score 写入 entity_data
2. PageRank/Louvain 逐条 UPDATE — 改为 VALUES CTE 批量更新
3. 一等公民表路径缺 app_name 过滤 — 文档明确 corpus 级去重设计意图

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(memory): Phase 2+ 增强 — 反馈闭环闭合 + Query-Aware 组装 + 近重复检测 + 测试覆盖 (#443)

* test(memory): Phase 2 组件测试覆盖 — TokenCounter / SummaryService / RetrievalTracker / MemorySummarizer;

新增 39 个单元测试用例,覆盖 Phase 2 四个核心组件:
- TokenCounter: 精确计数、空输入、幂等性、异步一致性、单调性(蜕变测试)
- SummaryService: upsert/get/delete CRUD 路径
- RetrievalTracker: 检索日志、引用标记、反馈记录、效果指标计算
- MemorySummarizer: 摘要生成、TTL 缓存命中/过期、LLM 失败降级、重试

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(memory): Phase 2+ 增强 — 反馈闭环闭合 + Query-Aware 组装 + 近重复检测 + 文档沉淀;

Gap 1 反馈闭环:
- _record_access 修复 user_id/app_name 透传(此前始终为空字符串)
- PostgresMemoryService 存储 _last_retrieval_log_id 供下游消费
- ContextAssembler 注入 mark_referenced 隐式反馈信号(RLHF[33])
- API 新增 POST /memory/retrieval/feedback 和 GET /memory/retrieval/metrics

Gap 2 Query-Aware:
- assemble() 新增 query/query_embedding 可选参数
- _call_get_context_window 传递 7 个参数(含 p_query, p_query_embedding)
- SQL 函数 NULL safe 退化:无 query 时保持纯 retention_score 排序
- 隐式反馈标记在上下文组装成功后触发

Gap 3 近重复检测:
- _is_duplicate 阈值从 0.9 降至 0.85(Henzinger[40])
- 新增 Jaccard 词重叠二次校验(0.80-0.85 区间,Broder[37])
- FactService 新增 merge_similar_facts() 语义去重方法

文档沉淀:
- docs/memory.md 权威源文件索引扩充 Phase 2 组件
- §15 追加 13 篇参考文献 [31]–[43]

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(memory): 修复 merge_similar_facts 过度删除 + retrieval_log_id 并发安全问题;

- merge_similar_facts: 锚点事实被删除后立即 break 内层循环,避免基于已删除 embedding 继续比对导致误删
- _record_access: 移除 _last_retrieval_log_id 实例属性,改为返回 log_id,消除共享可变状态的并发竞态
- ContextAssembler.assemble: memory_service 参数改为显式 retrieval_log_id,调用方直接传入

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(kg): Phase 3 生产就绪增强 — 增量构建 + 语义去重 + 管线健壮性 + 查询缓存 (#444)

* feat(kg): Phase 3 生产就绪增强 — 增量构建 + 语义去重 + 管线健壮性 + 查询缓存

Gap 3 [P1] 构建管线健壮性 (Nygard, 2018; Majors, 2022):
- Migration 0016: kg_build_runs 增加 progress_percent + warnings 列
- build_graph: 批处理循环进度上报、LLM 提取失败重试 1 次、算法失败警告累积
-…
ThreeFish-AI added a commit that referenced this pull request May 9, 2026
- conftest: 补丁 storage.service / cleanup_orphan_knowledge 的模块级
  AsyncSessionLocal 引用(from-import 绑定问题),修复 asyncpg 事件循环边界
  RuntimeError
- _sync_document_chunk_stats: 包裹 try/except 降级为 warning,避免纯单元
  测试(FakeRepository 无真实 DB)触发 DB 连接崩溃
- _backfill_sql: 改回 UPDATE ... FROM + DISTINCT ON 子查询,仅更新有文档
  匹配的行(孤儿行自然排除),修复 backfilled 计数断言失败

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
ThreeFish-AI added a commit that referenced this pull request May 9, 2026
* feat(knowledge-base): Knowledge.document_id FK + 孤儿清算 CLI (Phase 3);

ISSUE-078 Phase 3 — DB Schema 防御层 + 历史脏数据一次性清算。Phase 1 修计数口径、
Phase 2 修应用层级联、Phase 3 在 DB 层加 FK ON DELETE CASCADE 兜底,三层防御
正交可独立回滚。

变更:
- alembic 0030: ADD COLUMN knowledge.document_id UUID NULL +
  FK fk_knowledge_document_id REFERENCES knowledge_documents(id) ON DELETE
  CASCADE + 部分索引 ix_knowledge_document_id WHERE document_id IS NOT NULL;
  仅加列与约束、不做数据变更(避免大表 UPDATE 长锁);downgrade 仅 DROP COLUMN
- ORM 同步: models/perception.py Knowledge.document_id Mapped[UUID|None]
- KnowledgeChunk dataclass: 加 document_id 字段;types.py
- 写入路径 stamp: _ingest_text_with_tracker 加 document_id 参数,单点
  dataclasses.replace stamp 到每个 chunk;repository.add_knowledge values 加
  document_id 字段。仅 2 个 ingest 入口(execute_ingest_url_document_pipeline /
  execute_ingest_file_pipeline)传入 document_id,其余 10 个入口(纯文本、URL、
  replace、rebuild、KG)保留 None
- 独立 CLI scripts/cleanup_orphan_knowledge.py:
    uv run python -m negentropy.scripts.cleanup_orphan_knowledge \
      --dry-run | --commit [--corpus-id ...] [--app-name ...] [--json]
  三步流水线: 回填 document_id → 按 corpus 分组报告四档计数 → --commit 才
  真正 DELETE(白名单 source_uri 形态防误删);不放进 alembic 迁移因为
  DELETE 不可逆需 dry-run + 审批
- 观测函数 count_orphan_knowledge: 与 CLI 共享过滤口径,cron 接入将
  total_orphans 上报为 metric negentropy.knowledge.orphan_count{corpus_id}

dev DB 实地验证:
- 在 user 真实数据上跑 --dry-run 报告 Harness Engineering corpus
  total=849, would_delete=0;--commit 后 849 条 Knowledge.document_id 全部
  回填,与对应 KnowledgeDocument 建立 FK 关联
- Phase 1 → Phase 3 三层防御端到端在用户实际数据上闭环

测试: test_phase3_document_fk.py 8 场景覆盖 ORM 字段读写、DB 层 FK CASCADE
(直接 DELETE knowledge_documents 行触发 Knowledge 级联清理)、CLI dry-run/
commit、KG NULL source_uri 保留、非白名单 URI 形态保留、观测函数、migration
round-trip;既有 67 项单测无回归;alembic upgrade/downgrade 已在 dev DB 验证

详见 docs/issue.md ISSUE-078 Phase 3 补充章节。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(knowledge-base): cleanup CLI backfill 改用标量子查询优先选取 active doc (review #1);

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(knowledge-base): 修复 CI 集成测试三处失败 (review #2);

- conftest: 补丁 storage.service / cleanup_orphan_knowledge 的模块级
  AsyncSessionLocal 引用(from-import 绑定问题),修复 asyncpg 事件循环边界
  RuntimeError
- _sync_document_chunk_stats: 包裹 try/except 降级为 warning,避免纯单元
  测试(FakeRepository 无真实 DB)触发 DB 连接崩溃
- _backfill_sql: 改回 UPDATE ... FROM + DISTINCT ON 子查询,仅更新有文档
  匹配的行(孤儿行自然排除),修复 backfilled 计数断言失败

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(knowledge-base): 修复 CI 集成测试两处失败 (review #3);

- _backfill_sql: 子查询内 scope 条件引用外部别名 k → 改为 k_sub,
  修复 PG UndefinedTableError
- conftest: 补丁 knowledge.api 的模块级 AsyncSessionLocal 引用,
  修复 _scenario_soft_delete_archives 调用 list_corpora 时的事件循环边界错误

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
ThreeFish-AI added a commit that referenced this pull request May 17, 2026
旧实现按 seed_entity_ids 迭代顺序为每个 canonical 绑首个 seed chunk,导致两个
seed chunk 分别提到不同 canonical 时,bridge 的 source_chunk_id 可能错位(典型
症状:canon-B 实际来自 chunk-2,但被绑成 chunk-1)。

修复:
- _chunks_to_entities 返回 ``[(chunk_id, entity_id)]`` 多对多映射,而非
  DISTINCT entity_id 列表;
- _graph_expand 据此预先构造 canonical_to_seed_chunk(chunk→entity→canonical
  链式 join),传给 _entities_to_expanded_chunks;
- 移除旧实现里基于 seed_entity_ids/seed_candidates 的乱绑代码段。

回归用例 TestBridgeAttribution 复刻同款链式 join,断言 canon-A 绑 chunk-1、
canon-B 绑 chunk-2,杜绝 cross-binding。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
ThreeFish-AI added a commit that referenced this pull request May 17, 2026
* feat(kg-federated): 联邦知识图谱数据层 (Canonical 实体规范层 + 权限红线 + Linker);

引入 Federated KG + Global Entity Canonical Layer,使跨 Corpus 多跳推理在保留物理隔离的
前提下成为可能。架构哲学映射:Microsoft GraphRAG(社区分层)/ LightRAG(dual-level)/
HippoRAG 2(2-hop 收敛)/ PathRAG(路径剪枝)。

数据层(Migration 0034):
  - kg_entity_canonical    全局规范实体(按 app_scope 隔离 + HNSW + 部分索引)
  - kg_entity_alias        Corpus-local → canonical 多对一映射(UNIQUE local_entity_id)
  - kg_cross_corpus_bridge 跨 Corpus 显式桥接关系(Phase 1 建表不物化)

ORM + 权限红线(models/perception.py):
  - 新增 3 个 SQLAlchemy 模型,复用 Vector / TimestampMixin / UUIDMixin
  - Session.do_orm_execute event hook:对 KgEntityAlias 的访问缺 corpus_id 过滤直接 raise
    PermissionError,与 catalog_service 跨 app 拦截先例对齐

合并管线(canonical_linker.py):
  - 复用 EntityResolver(Fellegi-Sunter 三阶段),find_similar 回调改为查 canonical ANN
  - 双阈值:auto_merge=0.88 / review=0.75;类型冲突取 TYPE_PRECEDENCE 胜出方
  - 自动 stopword 标记(mention_corpus_count / total > 0.5)

入口签名升级(unified_search.py):
  - 新增 accessible_corpus_ids: frozenset[UUID],effective = scoped ∩ accessible
  - 取交集为空时直接返回空结果,避免 canonical 层成为权限旁路

Feature flag(config/knowledge.py):
  - KnowledgeFeatureFlags 包含 enable_canonical_linker / enable_cross_corpus_kg
  - 灰度阶梯:app allowlist + user_id hash sample_rate

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(retrieval-planner): HybridPlanner 四阶段检索编排 + 跨 Corpus 桥接;

把 search_knowledge_base 从「逐 Corpus hybrid 串行 + 全局排序」升级为四阶段管线,让 Home
Studio 多 @CorPuS 场景自动获得跨 Corpus 实体桥接与多跳推理能力。

HybridPlanner(agents/tools/hybrid_planner.py,约 640 行):
  - Stage 1 Intent Classification — 复用 UnifiedRetrievalService.classify_intent,
    映射五意图 (fact / explore / multi_hop / relation / global_summary)
  - Stage 2 Seed Retrieval — asyncio.gather 多 Corpus 并行 hybrid search
  - Stage 3 Graph Expansion — canonical 中转节点 BFS max-depth=2 跨 Corpus 邻居召回
    (受 accessible_corpus_ids 强制过滤;跳过 is_stopword_like 与 high-degree hub)
  - Stage 4 RRF 融合 + LocalReranker (bge-reranker-v2-m3)
  - 内置 TTL+LRU 缓存(canonical / provenance),timeout 12s SLO

search_knowledge_base 改造(agents/tools/perception.py):
  - Feature flag 网关:enable_cross_corpus_kg + scoped/graph_mode 命中时走 Planner
  - 任何 Stage 异常 → 降级到原 _legacy_search_knowledge_base 保护主链路
  - 每条 result 注入 corpus_id / corpus_label / evidence_type / bridge_path
  - 顶层新增 bridges / intent / expansion_triggered / stage_latencies_ms

新增工具 search_knowledge_graph_global:
  - 全局摘要类问题专用入口(关键词:主题/概览/总体/核心 / overall theme / key topics)
  - 委托 GlobalSearchService 做 Map-Reduce 社区摘要(GraphRAG 风格)

Faculty instruction 更新(agents/faculties/perception.py):
  - 三工具协作规则:默认 search_knowledge_base / 全局摘要走 _global / 论文反查走 _with_papers
  - Citation Corpus 来源徽章规范:跨 Corpus 检索时追加 (from Corpus: {label})
  - bridges 渲染规则:## 跨 Corpus 关联 段落呈现源/目标 Corpus + canonical 实体

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(home-mentions): @graph 第四类 mention + BFF state_delta 透传跨 Corpus 图谱模式;

为 Home Composer 增加第四类 @ mention「图谱模式」,作为用户显式触发跨 Corpus 桥接 /
GraphRAG 全局摘要的 escape hatch;与 Intent Classifier 自动判定互补。

类型与解析(types/mention.ts + utils/mention-parser.ts):
  - MentionKind 扩展 "graph",与 corpus-retrieve / corpus-output 同结构(refId = Corpus UUID)
  - deriveForwardedPropsFromMentions 新增 graph_mode_corpus_ids 字段,去重 + validRefIds 过滤
  - 既有 27 条 mention-parser 单测全量通过,新增 3 条 @graph 用例

弹层(components/ui/MentionPopover.tsx):
  - 新增第四个 Tab「图谱模式」(lucide Network 图标)
  - 复用既有 corpora 列表(kind 在 onPick 时改写为 "graph"),与现有 Tab 切换 / 键盘导航完全兼容

BFF state_delta(app/api/agui/_state-delta.ts):
  - 新增 graph_mode_corpus_ids 透传分支,sanitize UUID + 截断到 32 条 + 显式空数组清空语义
  - 既有 22 条 BFF 单测全量通过,新增 5 条覆盖 graph_mode 边界(合法 / 非 UUID / 空数组 / 非数组 / 缺席)

后端消费链路:
  - perception.search_knowledge_base 已在前一 commit 中读取 tool_context.state["graph_mode_corpus_ids"],
    命中非空时强制 HybridPlanner.force_graph_mode=True

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* docs(kg-federated): 新增联邦知识图谱架构文档并同步知识索引;

新增 docs/knowledge-graph-federated.md(架构 + IEEE 引用 + 运维手册)作为本次跨 Corpus
检索 / KG 整合工作的单一事实源,并把 docs/agents/knowledge-map.md 知识索引补上对应链接,
满足 AGENTS.md 的 Direct Hyperlinking 与 Single Source of Truth 规约。

文档内容包含:
  - 设计动机与三大现状缺口
  - 联邦 vs 物理合并的决策矩阵(含三大坑分析)
  - 数据层 Mermaid 架构图 + 表结构汇总
  - HybridPlanner 四阶段管线 Mermaid + 默认参数表
  - 三工具协作关系(search_knowledge_base / _global / _with_papers)
  - Citation 来源标注规范(corpus_label + evidence_type)
  - 灰度上线策略(4 周阶梯 + 回退路径)
  - 可观测性指标目标值
  - 五大风险与权衡 + 不在本次范围内的明确排除
  - 浏览器实机验证 P0 清单(参见 docs/agents/browser-validation.md)
  - 完整关联文件 SSOT 映射表

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-mentions): MentionChipList 补齐 @graph 图标/色板/标题;

修复 CI UI Build Smoke / UI Type Checks 报错——commit 584d289 把 MentionKind
扩展为四类(新增 "graph")但未同步更新 MentionChipList 内 _ICONS / _CHIP_CLASS /
_KIND_TITLE 三个 Record<MentionKind, …> 字典,导致 tsc 报 TS2741 三处缺键。

- 图标:复用 MentionPopover 已有的 Network 图标,保证弹层与 chip 视觉一致;
- 色板:新增 violet 变体(与 sky/emerald/amber 正交),对应"图谱"隐喻;
- 标题:「强制图谱模式」,对齐 types/mention.ts 注释与 Popover Tab 标签。

仅补编译期映射,不变更运行时行为;mention-parser.ts:178 已处理 "graph"。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(retrieval-planner): @graph 与 @corpus-retrieve 并集 + 全局图搜索多 Corpus 聚合;

闭环 @graph mention 在 Perception 工具层的语义:

1. _planner_search_knowledge_base:scoped_ids 与 graph_mode_ids 改为并集而非择一
   (之前 ``scoped_ids or graph_mode_ids`` 导致同时 @KB-A@graph kb-B 时丢掉
   kb-A)。任一非空即触发 force_graph,让 Planner 在并集上做 graph expansion。

2. search_knowledge_graph_global:从单次聚合查询改为「逐 Corpus 并发 + 聚合返回」
   - 早期校验 valid_ids,避免无效 UUID 进入下游;
   - 与 GraphService 同款 build_embedding_fn 计算 query_embedding(失败回退
     entity_count DESC);
   - 每个 Corpus 独立 AsyncSessionLocal,匹配 GlobalSearchService.search 的
     positional db 参数协议;
   - 返回结构改为 {status, query, corpus_count, per_corpus: [...]},附 corpus_label
     便于前端来源徽章。
   - 全部 Corpus 失败时 status=failed 且附 per_corpus 错误明细。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(hybrid-planner): bridges.source_chunk_id 精确归因 (FIX-#2);

旧实现按 seed_entity_ids 迭代顺序为每个 canonical 绑首个 seed chunk,导致两个
seed chunk 分别提到不同 canonical 时,bridge 的 source_chunk_id 可能错位(典型
症状:canon-B 实际来自 chunk-2,但被绑成 chunk-1)。

修复:
- _chunks_to_entities 返回 ``[(chunk_id, entity_id)]`` 多对多映射,而非
  DISTINCT entity_id 列表;
- _graph_expand 据此预先构造 canonical_to_seed_chunk(chunk→entity→canonical
  链式 join),传给 _entities_to_expanded_chunks;
- 移除旧实现里基于 seed_entity_ids/seed_candidates 的乱绑代码段。

回归用例 TestBridgeAttribution 复刻同款链式 join,断言 canon-A 绑 chunk-1、
canon-B 绑 chunk-2,杜绝 cross-binding。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(canonical-linker): 类型升级阈值修正与 stopword 总数计算 (FIX-#4 + FIX-#5);

两处独立缺陷一并修复:

FIX-#4 类型升级分支死代码:
  旧实现里「升级 canonical_type」的占比阈值与「类型冲突」阈值同为
  type_conflict_minority_threshold (0.30)。但冲突分支位于 for 循环内、升级在
  else 分支——任一非主类型占比 ≥0.30 都会先命中冲突 break,导致升级分支永远
  不可达。
  新增 type_upgrade_minority_threshold (0.15) 且强制 < type_conflict_minority_threshold;
  同时新增 precedence 严格大于校验,避免同 precedence 等级反复横跳。

FIX-#5 stopword total_corpora 失真:
  旧实现以 MAX(mention_corpus_count) 作为 total_corpora 的 O(1) 近似,但该值
  始终 ≤ 真实 corpus 数(顶多等于),作为分母会把 ratio 推高、stopword 阈值
  压得过低。改为直接 ``SELECT COUNT(*) FROM corpus WHERE app_name=...``,仅一次
  索引扫描,代价可忽略。

测试:
- TestConfigDefaults.test_upgrade_threshold_strictly_below_conflict:守护
  FIX-#4 阈值不变式;
- TestStopwordThresholdLogic.test_refresh_stopword_uses_corpus_count_not_max:
  断言 SQL 文本走 corpus 表而非 MAX(mention_corpus_count) 代理。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
ThreeFish-AI added a commit that referenced this pull request May 17, 2026
…识管理统一入口(100 PRs / 843 文件) (#560)

* feat(agent-defs): 主 Agent 入库 + 按 DB 读 instruction + 模型选择回退 (#420)

* fix(agent-defs): 修复 Agent 加载路径 + 主 Agent 纳入 Interface Sync + 运行时按 DB 读 instruction;

- cli.py: --reload_agents 改用 Path(__file__) 推导的绝对路径,杜绝 cwd 依赖导致的「src/negentropy/negentropy」双重段错误;
- subagent_presets: 新增 NegentropyEngine root payload(adk_config.kind="root"),Sync 后 DB 出现主 Agent 行;
- sync API: 循环写入 config.kind,末尾调 invalidate_cache(prefix="subagent:") 批量失效;
- SubAgentResponse: 新增顶层 kind 字段(root/subagent),供前端置顶 + 徽章;
- model_resolver: 抽取 _load_subagent_row 共用单行查询,新增 resolve_subagent_instruction;
- _dynamic_instruction: 新增 InstructionProvider 工厂,root + 5 子 Agent 的 instruction 接入运行时 DB 读取;
- 测试: 更新 test_subagent_presets 覆盖 root payload + kind 断言;

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-llm): 修复无 Session 时模型选择回退 + SubAgents 列表 Root 置顶徽章;

- home-body: 新增 pendingLlmRef,改写 handleSelectedLlmModelChange 与 Effect 1,
  使「无 session 选模型→建 session→自动发送」全流程保持选择不丢失;
- SubAgents page: 按 kind="root" 置顶排序,Sync 按钮文案从「Sync Negentropy 5」改为「Sync Negentropy」;
- SubAgentCard: Root Agent 显示 violet 色 Root 徽章;

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(model-resolver): SubAgent 行缺失/未启用补回 60s TTL 负命中缓存;

回归点:重构 `_resolve_subagent_row` 时把空占位写入移到了 `loaded is None`
判断之后,导致禁用 Faculty 与未 Sync 环境下每次 LLM 请求都触发一次 DB 查询。
本次在 `loaded is None` 分支补 `_cache[cache_key] = ("", {"i": ""}, now)`,
让负命中同样落入 60s TTL,避免重复 DB 压力。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-llm): pending 模型选择仅对 startNewSession 新 id 消费;

回归点:Effect 1 的 pending 转移分支会在「首次进入既有 session」时触发,
把无 session 阶段的 pending 模型写入该 session 的 perThreadLlmRef,
并让 Effect 2 跳过 snapshot 初始化,导致服务器端记忆模型被静默替换。

修复方式:
- 新增 `pendingLlmTargetIdRef` 仅记录 startNewSession 返回的新 id;
- 通过 `startNewSessionWithLlmTarget` 包装内联调用与 `onNewSession` 两条路径;
- Effect 1 仅在 `sessionId === pendingLlmTargetIdRef.current` 时转移 pending,
  其余进入既有 session 的分支主动丢弃 pending,让 snapshot 正常生效。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(knowledge): 修复 KB Retrieve 全屏空白(前端聚合 rejection × 后端 hybrid/rrf 降级 × 502 上游错误码 × 诊断仪器化) (#421)

* fix(knowledge): 修复 Knowledge Base Retrieve 全屏空白(前端聚合 rejection + 后端 hybrid/rrf 降级 + 502 错误码 + 诊断日志);

双层 Bug 同因联修(详见 docs/issue.md ISSUE-026):
1. 前端 searchAcrossCorpora 旧实现以 Promise.allSettled 仅取 fulfilled,rejected 静默丢失,导致全部 Corpus 失败时返回 {count:0,items:[]} 走"成功路径"使 UI 空白且无任何提示——本次改为聚合三态(全成功/部分失败/全失败),SearchResults 类型扩展 errors[],handleRetrieve 对部分失败 toast.warning 透出原因;
2. 后端 service.search hybrid/rrf 旧实现未捕获 EmbeddingFailed,外部 Embedding 上游故障直接 500,丧失"keyword 仍可用"的优雅降级——本次 hybrid 失败回退 keyword-only、rrf 失败走与 not embedding_fn 等价的回退路径,semantic 仍传播以保留显式失败语义;
3. api.py _map_exception_to_http 拆分 EmbeddingFailed 分支映射到 502 Bad Gateway(保留 EMBEDDING_FAILED code),与 SearchError 自身错误的 500 区分,便于前端识别"上游修复后再试"语义;
4. embedding.py 调用 litellm 前后增加结构化诊断日志:api_base_host(脱敏 path/credentials 仅留 host)+ input_count + text_preview + kwargs_keys;失败附 upstream_response_text(沿异常链 __cause__/__context__ 提取 MaskedHTTPStatusError.text,已被 litellm 脱敏 URL,限长 500 字节);
5. 测试锁定:tests/unit_tests/knowledge/test_search_resilience.py 5 例(hybrid/rrf 降级 + semantic 传播 + EmbeddingFailed→502 + SearchError→500)+ tests/unit/knowledge/searchAcrossCorpora.test.ts 3 例(allSettled 三态);
6. docs/issue.md 追加 ISSUE-026,含后续防范(Promise.allSettled 必须聚合 rejection / vendor 失败必须 502 / hybrid 必须有降级路径 / vendor 调用必须 host+upstream_text 双信号)与同类问题影响清单。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(knowledge): searchAcrossCorpora 聚合保留 KnowledgeError code 并修正 _map_exception_to_http docstring;

Review #1(前端契约): SearchResultError 仅透 message 会丢弃 KnowledgeError.code(如 EMBEDDING_FAILED),削弱本次 502/500 拆分对前端"上游修复 vs 自身错误"的可分流价值——本次扩展 SearchResultError 增加可选 code,rejection instanceof KnowledgeError 时回填;全失败分支由 throw new Error 改为 throw new KnowledgeError(aggregatedCode, msg, {errors}),code 一致时透传原 code、混合时退化为 AGGREGATED_SEARCH_ERRORS,既保留分流能力又携带逐条失败明细;新增 1 例同 code 透传 + 1 例混合 code 退化的单测,全部 4 例通过。

Review #2(后端文档): api._map_exception_to_http docstring 仍只列 400/404/409/500,与新增 EmbeddingFailed→502 分支不一致;本次补 "502: 上游服务错误(vendor / Embedding 等外部依赖)" 一行,避免后续维护者按旧映射加分支。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(wiki-favicon): 修复 negentropy-wiki 站点 favicon.ico 单分辨率畸形导致浏览器回落默认地球图标; (#423)

- 根因:apps/negentropy-wiki/src/app/favicon.ico 是单分辨率畸形 ICO(file 输出 256x-1,高度字节 0xFF),且源图 logo.png 为非方形 800x798,导致 Chrome/Firefox/Safari 解析失败、tab 回落默认地球图标;
- 修复:用 Pillow 对 logo.png 做透明 padding 至 800x800 方形,再生成多分辨率 ICO(16/32/48/64/128/256 共六档)覆盖原文件;体积从 269KB 降至 118KB;
- 验证:file 输出 6 icons; pnpm build 后 .next/standalone 内 favicon route + body + meta 完整;pnpm start 后 curl /favicon.ico 返回 200 image/x-icon,HTML 自动注入 <link rel="icon">;
- 防范:docs/issue.md 追加 ISSUE-027,沉淀「ICO 必须方形 + 多分辨率」工程约束与 Pillow 流水线模板,禁止「原图直裹 ICO 头」反模式;
- 不动:layout.tsx / next.config.ts / start-production.mjs,保留 App Router metadata 自动注入路径,最小干预。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)

* feat(mcp-resources): 接入 Resource Templates 并贯通 PDF 图片到 Wiki Markdown (#422)

* feat(mcp-client): 接入 MCP Resource Templates 与同会话动态资源拉取;

新增 McpResourceTemplate 模型与 Alembic migration 0012,扩展 McpClientService 在
连接发现阶段并发调用 list_resource_templates(旧 server 不支持时静默兜底,不
阻断 tools 发现),新增 call_tool_and_resolve_resources:在同一 ClientSession 内
完成工具调用与所有 resource_link URI 的并发拉取(Semaphore 限流 4,return_exceptions
保证单条失败不击穿主流程)。这是接入 Negentropy Perceives 动态 FileResource
(perceives://pdf/<job_id>/<filename>)的协议层基石——动态实例的生命周期与工具
会话强绑定,必须在 session 关闭前完成 resources/read 才能避免事后失链。

Interface API 同步:load_mcp_server_tools 端点扩展为 capability 全量同步(tools
+ resource_templates,软删除已下线的 templates),LoadToolsResponse 新增
resource_templates 字段(向后兼容),新增 GET /mcp/servers/{id}/resource-templates
端点;list_mcp_servers 拆解为分段计数避免 JOIN 笛卡尔积;McpServerResponse 暴露
resource_template_count 给前端展示。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(perceives-resources): PDF 图片资源端到端贯通到 GCS 与 Wiki Markdown;

把 Perceives MCP 工具调用返回的 ResourceLink 接入既有提取流水线(Ingest 与
Re-Parse from GCS),让 PDF 图片资源在主仓 ↔ Perceives 之间通过 MCP 协议
完整贯通:

- 提取层(extraction.py):新增 _extract_resource_link_assets 把 ResourceLink
  与同会话 read_resource 拉取的 base64 配对为 ExtractionAsset;_call_tool_with_plan
  改用 resolve_resource_links=True 路径,确保动态 URI 不会因会话关闭失链;
  _build_success_result 接收 resolved_resources / resource_errors,按 "warn +
  占位" 容错策略合并 assets 并标记 partial_failure 不阻断主入库;新增
  _rewrite_markdown_image_links 在 Markdown 写入 GCS 之前把相对路径图片引用
  重写为 /api/documents/{doc_id}/assets/{filename},重写采用 capture group 偏移
  以避免 alt 文本含同名 src 时误替换。

- Knowledge API:新增 GET /knowledge/wiki/documents/{document_id}/assets/{filename}
  公开端点,filename 严格白名单 ^[A-Za-z0-9._-]+$ 与 180 字符上限;鉴权策略与
  既有 wiki entry content 端点对齐——仅放通至少被一条 WikiPublicationEntry
  引用的 document,避免持任意 doc_id 拖走未发布文档资产。

- 前端 MCP 卡片(negentropy-ui):新增 Resource Templates 折叠区与 ResourceDetailPanel,
  视觉与 Tools 区完全镜像;page.tsx 在 tools:load 响应中同步消费
  resource_templates 段,状态合并到 ServerWithTools;动态实例(带 job_id)
  按设计不入卡片。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(mcp-client): Resource Templates 同步加 capability flag,避免静默兜底误清空模板表;

`_discover_on_transport` 对 `list_resource_templates` 的所有异常都会静默兜底返回空列表(兼容旧 server 与瞬态错误),但 `load_mcp_server_tools` 会把空列表当作权威结果裁剪 stale 行,导致一次网络抖动或 server bug 即抹掉全部模板;同时与 tools 同步"只增量更新、不裁剪"的语义不对称。

- `McpConnectionResult` 新增 `resource_templates_listed: bool`,仅在 `list_resource_templates` 成功返回时为 True;
- `load_mcp_server_tools` 仅在该 flag 为 True(权威空列表)时才裁剪 stale 模板,未支持/错误场景保留既有 DB 行;
- 单元测试覆盖 flag 在权威空列表与异常兜底两种路径下的取值。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* test(mcp-card): 单测 server fixture 补 resource_template_count 修 UI Type Checks;

`McpServer` 类型新增的必填字段 `resource_template_count` 未同步到 `McpServerCard.test.tsx` 的 server 固件,导致 ui-quality / UI Type Checks 在 5 处 `<McpServerCard server={...}>` 调用上报 TS2741。

- 在 server 固件加 `resource_template_count: 0`,spread 派生用例自动获得新字段。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(knowledge): 查询时 honor Corpus 自配 embedding 模型,修复 query/index 模型不一致 (ISSUE-028) (#424)

search() 原直接使用实例化时锁定的 self._embedding_fn(全局默认 gemini/text-embedding-004),
未读 corpus.config.models.embedding_config_id;而 _attach_embeddings 索引侧已按 corpus pin 走
专属 fn。两侧不对称导致:用户在 Corpus Settings 已切到 openai/text-embedding-3-small(1536 维),
索引按 OpenAI 生成,查询仍走 Gemini 全局默认经 localhost:3392 翻译代理报 400。

修复:
- 新增 _resolve_embedding_fn(corpus_config) 助手,corpus pin 优先 → 退回 service 默认 fn;
- search() 入口加载 corpus_config + embedding_fn 本地变量,rrf/hybrid/semantic 三分支替换;
- ISSUE-026 keyword 兜底 + 502 映射 + 诊断日志原样保留,零回归;
- 新增 5 例单元测试覆盖 corpus pin 命中/落空/兜底/rrf/semantic 上抛,577 全绿。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)

* fix(agent-llm): 修复 Home Send 时 LLM 凭证未从 DB 读取导致 AuthenticationError (#425)

* fix(docs): 同步文档启动命令与 cli.py 修复,消除 Home Send 500 复发路径;

cli.py 的 agents_dir 已在 35204ff 从 src/negentropy 修正为 src,
但 README / docs 下 4 个文件 7 处仍写 --reload_agents src/negentropy,
用户照文档启动复现 ValueError: Agent not found 500。
统一替换为 uv run negentropy serve(SSOT),
追加 ISSUE-029(文档漂移)与 ISSUE-030(SubAgents root Agent 防回归)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(agent-llm): 修复 Home Send 时 LLM 凭证未从 DB 读取导致 AuthenticationError;

DynamicRootLiteLlm/DynamicSubagentLiteLlm 在 ContextVar 或 sub_agents.model
为空时直接返回 None,回退到构造时无 api_key 的硬编码实例,绕过了 DB 中
已配置的 vendor_configs 凭证。现在始终通过 resolve_llm_config() 从 DB
解析默认模型的完整凭证(含 api_key)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-chat): 修复长耗时回复双气泡 + 首条未格式化 (ISSUE-031); (#426)

ADK 仅持久化 partial=false 终态事件,realtime 与 hydration 在
同一逻辑消息上派出不同的 messageId(首个 partial id vs 终态 id)。
isSemanticEquivalentEntry 的 8s 时间窗在长耗时回复下硬拒绝,导致
ledger 双 entry → events 过滤失败 → conversation tree 双节点 →
UI 渲染双气泡(首条因 streaming-markdown 尾部判定走 raw text 分支)。

修复 (最小干预 + 正交分解):
- message-ledger.ts: 内容严格相等时跳过 8s 时间窗硬拒绝。
- conversation-tree.ts: assistant 已收尾节点在内容严格相等时
  也允许 findMatchingTextNodeId 命中复用,作为防御性收敛。
- 三层回归测试覆盖 ">8s 跨度 + messageId 不同 + 内容严格相等"。

UI 全量 70 文件 396 测试通过;typecheck/typecheck:test/eslint 零报错。
docs/issue.md 沉淀 ISSUE-031;CHANGELOG.md 同步条目。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)

* fix(home-chat): 修复 Home 对话 title 凭证缺失与 OTLP logs/metrics 404 双联缺陷 (#427)

* fix(home-chat): 修复 Home 对话 title 凭证缺失 + OTLP logs/metrics 404 双联缺陷;

(1) SessionSummarizer 同步 __init__ 在 60s 缓存 miss 时回退到无 api_key 硬编码默认,
导致 LiteLLM AuthenticationError;改为 async classmethod create() 经 resolve_llm_config()
从 DB 读取完整凭证(与 commit 8ce35d5 修复 DynamicRootLiteLlm 同 SoT),调用方
session_service._generate_title_for_session 切换为 await SessionSummarizer.create(),
对 resolver 返回 kwargs 做防御性浅拷贝避免与 60s 缓存层耦合。

(2) ADK 上游 _get_otel_exporters() 把 OTEL_EXPORTER_OTLP_ENDPOINT 视为 OTLP 三件套
总开关,无差别注册 OTLPSpanExporter / OTLPMetricExporter / OTLPLogExporter;后两者
对 Langfuse 不存在的 /v1/metrics、/v1/logs 上报触发 SPA 404 SSR 错误页(每次对话
反复输出大段 HTML)。bootstrap.py 新增 _install_noop_otel_logs_metrics_providers()
在 OTel env var 设置后立即抢注无 processor / 无 reader 的 SDK Logger/Meter Provider,
利用 OTel SDK Once-lock 让 ADK 后续 set_*_provider 静默 no-op,从而阻断 logs/metrics
上报;TracerProvider 链路与 OTEL_EXPORTER_OTLP_HEADERS 不动,traces 仍正常进入 Langfuse。

新增 tests/unit_tests/engine/test_summarization.py(3 例)+
tests/unit_tests/observability/test_otel_noop_providers.py(3 例,子进程隔离 OTel 全局
状态)锁定回归。CHANGELOG / docs/issue.md 沉淀 ISSUE-031(title 凭证缺失)与
ISSUE-032(OTLP logs/metrics 404)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* test(otel-noop): 移除 _sdk_config hasattr 兜底,让 SDK 私有属性变更显式触发回归;

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* test(session-title): 修复 DummySummarizer 缺失 async create() 导致集成测试 AttributeError;

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(bootstrap-otel): 消除 ADK Web 启动期 OTel Override Provider 双 WARNING (ISSUE-034); (#428)

将 ISSUE-033 的「抢占式 set_logger_provider/set_meter_provider」改为 patch
`google.adk.telemetry.setup._get_otel_exporters`,让其只返回 traces 的
span_processors,metric_readers/log_record_processors 永久置空。ADK
maybe_set_otel_providers 的 if 分支由此天然短路,set_*_provider 根本不被
调用,从源头消除 OTel SDK 的 "Overriding of current ... is not allowed"
WARNING;traces 链路、ADK ApiServerSpanExporter、TracingManager、LiteLLM
"otel" callback 行为完全不变。配套更新 3 个子进程隔离单测验证新语义,
并在 docs/issue.md 追加 ISSUE-034 完整记录。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)

* feat(e2e-auth): 浏览器验证协议落地 + Playwright 会话复用贯通 Google OAuth (#429)

* docs(browser-validation): 落地浏览器验证协议并补 ISSUE-034

- AGENTS.md(即 CLAUDE.md symlink)新增"Browser Validation Protocol"子节,
  约定登录态浏览器验证必须复用用户常用 Chrome 会话,禁止 sandbox 浏览器
  通过 Google 同意屏,明确凭证守则与三步连通性自检;
- 新建 docs/agents/browser-validation.md:含三种 MCP 浏览器工具能力对照、
  Mermaid 选型决策图、storageState 工作时序、风控应对、IEEE 引用;
  实测附注 chrome-devtools MCP 在 macOS 默认即可复用用户主 profile 登录态;
- docs/issue.md 追加 ISSUE-034,记录 sandbox 浏览器走 Google OAuth 被拦
  的表因/根因/处理方式/防范,便于跨上下文复用。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* test(e2e-auth): Playwright 会话复用以贯通 Google OAuth E2E

- playwright.config.ts 在 PLAYWRIGHT_AUTH=1 时启用两个项目:
  * setup(headless: false,匹配 *.setup.ts),让用户在弹出窗手动登录;
  * chromium-authenticated(dependencies: ['setup']),使用 storageState
    复用一次性人工登录的会话;
  支持 PLAYWRIGHT_STORAGE_STATE 与 PLAYWRIGHT_USER_DATA_DIR 覆盖默认;
  现有 chromium project 加 testIgnore 排除 .setup.ts,CI/默认行为零变;
- 新增 tests/e2e/auth.setup.ts:打开 /auth/google/login,5 分钟内允许
  用户在 Google 同意屏中手动完成登录,回跳后断言 /api/auth/me 2xx,
  写入 storageState;
- .gitignore 追加 apps/negentropy-ui/.auth/ 与 .userdata/,
  防止会话凭证随分支推送外泄。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(e2e-auth): 修复 OAuth setup 早退与 authed spec 双跑;

- auth.setup.ts: waitForURL 谓词追加 host 约束,避免在跳往 accounts.google.com
  瞬间因 pathname 已离开 /auth/google 而误判完成,导致 /api/auth/me 在用户登录前
  失败、storageState 永不写出。
- playwright.config.ts: 基础 chromium project 的 testIgnore 追加
  /.*\.authed\.spec\.ts$/,防止 PLAYWRIGHT_AUTH=1 时同一份认证 spec 在
  chromium-authenticated 与 chromium 中各跑一次(后者无 storageState 必失败)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-chat): 修复 Home 双气泡复发与 LLM 模型未 Send 即刷新丢失 (ISSUE-032/033); (#430)

ISSUE-032 (双气泡复发,与 ISSUE-031 正交):
- 根因:root agent prompt 主动导航 + log_activity tool 让 ADK 走双轮 LLM 调用,
  两轮各自带独立 messageId 走完整 TEXT_MESSAGE_* 三件套,UI 在同一
  assistant-reply bubble 内并列渲染两段近重复文本。
- 修复:utils/chat-display.ts::dedupeRedundantTextSegments 在
  buildAssistantReplyBlock 出口对同一 reply 内的 text segment 做字符二元组
  Jaccard 相似度计算,相似度 ≥ 0.5 且双方长度 ≥ 30 时丢弃前段、保留信息更
  完备的最终段。tool-group / reasoning / error 顺序不动。
- assistant-reply.message.content 联动重组,复制时也拿到折叠后的内容。

ISSUE-033 (LLM 模型未 Send 即刷新丢失):
- 根因:后端事实源 session.state.selected_llm_model 仅在 /run_sse 时随
  state_delta 写入,未 Send 时不更新;前端 perThreadLlmRef 是 useRef
  刷新即丢;snapshotForDisplay 也无值,回退到 default。
- 修复:app/home-body.tsx 顶部新增 readPersistedLlmModel /
  writePersistedLlmModel (typeof window 守卫 + try/catch SSR 安全);
  handleSelectedLlmModelChange 即时落盘到 localStorage;Effect 1 优先
  从 localStorage 还原;Effect 2 命中 snapshot 时同步回写 localStorage,
  让「后端 state ↔ localStorage」互为镜像。既有 forwardedProps.selected_llm_model
  在 Send 时仍写后端 state,跨设备一致性最终收敛。

测试:
- 新增 2 例 chat-display.test.ts 用例:折叠近重复段 + 差异度大不被折叠
- UI 全量 70 文件 398 测试通过;typecheck/typecheck:test/eslint 零报错

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)

* fix(bootstrap-otel): 消除被丢弃 PeriodicExportingMetricReader 守护线程的周期 WARNING (ISSUE-038) (#431)

* fix(bootstrap-otel): 消除被丢弃 PeriodicExportingMetricReader 守护线程的周期 WARNING (ISSUE-038);

ISSUE-034 的 patch 调用 original() 后再丢弃 metric_readers /
log_record_processors,但上游 _get_otel_exporters 已构造
PeriodicExportingMetricReader 并启动 60s 守护线程——reader 未注册
到 MeterProvider 导致每 tick 触发 "Cannot call collect on a
MetricReader ..." WARNING。改为绕过 original(),直接复用
_get_otel_span_exporter() 仅构造 traces span processor,根源
避免 OTLP metrics/logs exporter 被实例化。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* docs(bootstrap-otel): 修正 _disable_adk_otel_logs_metrics_exporters docstring 中的过期 hooks 引用;

旧 docstring 沿用重构前 `hooks = original()` 的中间变量术语,但新实现已不再调用 `original()`,函数体内也没有 `hooks` 绑定。
更新指引为「恢复 _get_otel_exporters 原函数闭包」或「直接构造完整 OTelHooks」,避免误导后续维护者寻找已不存在的对象。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-chat): 修复 Home 双气泡盲区与刷新后消息乱序 (ISSUE-039) (#432)

* fix(home-chat): 修复 Home 双气泡盲区与刷新后消息乱序 (ISSUE-038);

- chat-display: dedupeRedundantTextSegments 增加四层判定(精确匹配 / 严格前缀 / 等价内容 / Jaccard),覆盖 ADK 双轮 LLM 短回复(如 "Pong!")的双气泡盲区。
- session-hydration: mergeEventsWithRealtimePriority 交换参数顺序,让 realtime 事件覆盖 hydrated;TEXT_MESSAGE_CONTENT 的 eventKey 时间戳改用 toFixed(3) 消除浮点抖动导致的同一事件重复保留。
- message-ledger: MessageLedgerEntry 新增可选 sourceOrder 作 createdAt 相同时的稳定 tiebreaker,替代 UUID localeCompare 的随机字典序;抽出 compareLedgerEntriesByTime 复用,类型保持向后兼容(缺省回退 Number.MAX_SAFE_INTEGER)。
- 新增 5 项单元测试覆盖:短回复精确匹配、前缀含尾部追加、Jaccard 长文本、eventKey 浮点稳定、sourceOrder 稳定排序;docs/issue.md 增补 ISSUE-038 摘要。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* test(home-chat): 补 mergeEventsWithRealtimePriority 生命周期事件覆盖回归用例;

针对 ISSUE-039 第 3 项修复(mergeEventsWithRealtimePriority 参数顺序交换)
原有 RUN_STARTED 类生命周期事件用例缺位——之前的 messageId 重叠用例在
step 3 即被过滤为 filteredHydratedEvents=[],无法验证 step 4 mergeEvents
入参顺序对 key 冲突归并的影响。

补一条 RUN_STARTED 用例:realtime / hydrated 同 threadId/runId/timestamp
(eventKey 字节级一致)→ 用对象引用断言保留的是 realtime 版本,作为参数
顺序交换的最直接证据。该用例在交换前会失败、交换后通过,形成有效回归网。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-chat): 消除 LLM 思考独白溢出 / 推理头常驻 / 刷新乱序残留 (ISSUE-040) (#433)

* fix(home-chat): 消除 LLM 思考独白溢出 / 推理头常驻 / 刷新乱序残留 (ISSUE-040);

- 过滤 ADK Part 中 thought=true 与 type=thinking|thought|reasoning 系列推理字段,避免 reasoning_content 溢出到 TEXT_MESSAGE_CONTENT;推理文本改路由为 ne.a2ui.thought 自定义事件保留可观测性。
- createStepFinishedEvent 同步透出 stepName,AdkMessageStreamNormalizer 持有 stepId→stepName 映射,根治 ag-ui v0.0.47 校验器 "Cannot send 'STEP_FINISHED' for step \"undefined\"" 中断 run 导致的推理头永驻 started 现象。
- conversation-tree fallback 段重建消息节点时优先复用 ledger 已有 sourceOrder,避免被推到 events 末尾破坏 compareLedgerEntriesByTime tiebreaker。
- session-hydration eventKey 全事件类型统一走 toFixed(3) 毫秒级时间戳,并为 STEP_STARTED/STEP_FINISHED 显式按 (threadId, runId, stepId) 作 key,覆盖 STEP_*/CUSTOM/STATE_*/RAW 在浮点抖动下的去重盲区。
- 新增 9 例单元回归覆盖 thought part 过滤 / STEP_FINISHED stepName / fallback sourceOrder / eventKey 浮点抖动;docs/issue.md 追加 ISSUE-040 全栈解析。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-chat): 消除 hydration sort 字典序污染 lifecycle 顺序导致的多消息刷新乱序 (ISSUE-040 Q3 长尾);

- hydrateSessionDetail 引入 WeakMap<BaseEvent, emitOrder>,sort tiebreaker 用 normalizer 推入顺序代替 eventKey().localeCompare,保留 TEXT_MESSAGE_* 三件套 START→CONTENT→END 与跨 messageId 的 turn 边界。
- mergeEvents 同步改为按首次出现位置记录 insertionOrder 作 tiebreaker,避免最后一步 mergeEvents([], normalizedEvents) 再把刚排好的事件按字典序乱序。
- 新增同 timestamp 下 lifecycle 顺序断言用例;多轮真实后端 events fixture 经修复链路输出 user(R1)→assistant(R1)→user(R2)→assistant(R2) 完全符合时间线。
- docs/issue.md 在 ISSUE-040 末尾追加 Q3 长尾闭环(H5 字典序污染根因与最小干预修复)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* test(home-chat): 强化 ISSUE-040 H3 fallback sourceOrder 回归用例;

- 旧用例与单 snapshot 单条消息时新旧公式恰巧同值,断言无差异,无法拦截 H3 退化;
- 新用例构造「snapshot 数组顺序 vs ledger 时间序」错位场景:让 sourceOrder 在两条消息间发生互换,对回滚 H3 修复有强差异断言(已本地反向核验:回滚 conversation-tree.ts 修复后断言失败)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(wiki-header): catalog 第一层提升为顶部 Header 导航 tabs (#434)

* feat(wiki-header): catalog 第一层提升为顶部 Header 导航 tabs;

将 publication catalog 的第一层 CONTAINER 节点(如 Harness-Engineering)
从左侧 Sidebar 迁移为顶部 Header tabs;第二层及以下保留于 Sidebar,整树向上提升一档。
设计参考 GitHub Docs / Stripe Docs / Docusaurus 的"顶 tabs + 左 sidebar 子树"模式。

主要变更:
- lib/wiki-api.ts 追加 findFirstDocumentSlug / findActiveTopLevelSlug / resolveSectionView
  纯函数,作为 Header tabs 与 Sidebar 切片的单一事实源。
- 新增 WikiHeader Server Component(仅 <Link>,SSG 友好):渲染品牌 + 水平 tabs;
  CONTAINER tab 跳转 DFS 首个后代 DOCUMENT;无文档则禁用 span。
- WikiLayoutShell 增加 header? prop,渲染于 .wiki-layout 之外作为兄弟节点,
  避免触动既有 3 列 Grid 与 data-toc 三态。
- /{pubSlug} 与 /{pubSlug}/{...entrySlug} 两条路由共用 resolveSectionView 派生视图:
  pub 根页默认激活首项;entry 页按 slug 反查所属一级。
- globals.css 引入 --wiki-header-height 并把 sidebar / toc-aside 的 sticky top
  改为 var 引用,确保滚动时 Header 常驻不挡 sidebar。
- 新增 wiki-section-view.test.ts 12 用例覆盖空树 / 单 / 多 / 深路径 / DOCUMENT-only
  / 无后代 DOCUMENT 等边界。

回归保障:home / 不变;既有 WikiNavTree / WikiToc 测试 API 未变;47/47 单测全绿。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(wiki-header): Header 缺失时 sidebar/toc 不再残留偏移;

通过 data-header 属性标记 Header 是否存在,CSS 侧条件生效
--wiki-header-height 偏移,避免空导航树时出现 56px 空白间隙。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* refactor(config): 废弃 .env*,统一 YAML 三级配置(local > user > default) (#436)

* refactor(config): 废弃 .env* 加载链路,引入 config.local.yaml 统一 YAML 三级配置;

- 移除 10 个 Python 配置模块中的 env_file / _get_env_files 逻辑
- yaml_loader 新增 config.local.yaml 作为最高优先级 YAML 来源
- config.default.yaml 合并 .env 全部非机密差异值(含 OAuth 端口 6600→3292 校正)
- 新增 3 例 config.local.yaml 优先级测试

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* docs(config): 同步 .env 废弃后的文档与 CHANGELOG;

- development.md / sso.md / framework.md / user-guide.md / zh-CN/README.md 中 .env 引用替换为 config.local.yaml
- CHANGELOG 新增 ISSUE-041 变更记录
- docs/issue.md 新增 ISSUE-041 经验沉淀
- .gitignore 新增 apps/negentropy/config.local.yaml 排除规则

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(config): 放宽 .gitignore 中 config.local.yaml 匹配规则,覆盖任意 cwd 场景;

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-chat): 修复 realtime + hydration 跨 runId 双气泡复发 (ISSUE-041) (#435)

* fix(home-chat): 修复 realtime + hydration 跨 runId 双气泡复发 (ISSUE-041);

- 新增 isSyntheticRunId 共享识别函数(覆盖 runId 缺失 / DEFAULT_RUN_ID / runId === threadId 三类合成回退标记),三层 dedup 一致放宽:
  1. message-ledger.ts::isSemanticEquivalentEntry:runId 不等时若任一侧 synthetic 则放行,threadId + role + 内容前缀 + origin 多元仍是必要约束;
  2. conversation-tree.ts fallback 段 runMatches:识别合成 runId 兼容分支,避免同内容 fallback message 被强制重建为重复节点;
  3. conversation-tree.ts collapseDefaultTurnDuplicates → collapseSyntheticTurnDuplicates:扩展为识别 runId === threadId 的合成 turn;时间窗判定改为 per-child timestamp vs concrete turn timeRange,多轮场景下不再误放过期 concrete turn。
- session-hydration.ts::fallbackRunId 注释 ISSUE-041 契约(保留兜底防御,等 Phase 2 后端代理层注入 runId 后再渐进移除)。
- 新增 16 例自动化回归(含 1 例反向回滚断言):
  · message-ledger A1-A5 + isSyntheticRunId 单元 + 端到端 ledger merge(共 7 例);
  · conversation-tree C1/C2/C3/C5 + D4 反向回滚(共 5 例);
  · session-hydration D1/D1+/D2/D3 端到端(共 4 例)。
- docs/issue.md 追加 ISSUE-041 全栈解析(含 refresh 自愈非对称的根因证据、多轮二阶恶化、Phase 2-4 路线图、诊断抓手与同类问题影响),闭环 ISSUE-040 Q3 长尾自识别。

回归状态:482 测试全绿 + tsc 0 错误;浏览器实机 5 场景 × 3 次验证清单见 .context/issue-041/validation-protocol.md,待用户已登录态 Chrome 桥接就绪后执行。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* docs(rfcs): 新增 Phase 3 / Phase 4 架构 RFC 草稿(ISSUE-041 后续路线图);

- docs/rfcs/0001-conversation-architecture-refactor.md:Phase 3 架构重塑 RFC(Codex Thread→Turn→Item 数据模型 / 6 层去重金字塔精简到 3 层 / 抽象 utils/dedup/ + config/projection-thresholds.ts / 投影缓存 / 8 sub-PR 渐进迁移路线 / 兼容性回归与风险评估)。
- docs/rfcs/0002-ui-interaction-enhancements.md:Phase 4 UI 交互能力 backlog(Reasoning Panel + Sub-Agent 嵌套 / 工具进度 + 中断审批 / Conversation Branching + Timeline 增强;按用户优先级 1/2/3 分组,附实施依赖图与 Acceptance Criteria)。

均为 Draft 状态,待团队评审通过后启动多 PR 渐进迁移。本 commit 仅文档先行,不动代码。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-chat): 增强 synthetic turn 折叠相似度判定与时间窗整体吸收 (ISSUE-041);

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-chat): 双层防御消除跨 runId 三气泡——泛化 turn 折叠 + 跨 block 去重 (ISSUE-041);

将 collapseSyntheticTurnDuplicates 泛化为 collapseOverlappingTurns:按 threadId 分组,
对 synthetic turn 与同组 concrete turn 时间重叠+内容覆盖的进行折叠(双 concrete turn
保留以防误折叠合法多 run);新增 chat-display 层 dedupeAdjacentAssistantBlocks
作为安全网,对时间窗内内容高度相似的相邻 assistant-reply block 保留更完整的一个。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(test): 补充 message-ledger 测试 fixture 缺失的 id 字段 (ISSUE-041)

tsconfig.vitest.json 类型检查报 TS2741:baseRealtime 对象缺少
MessageLedgerEntry 必需的 id 属性。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(chat-display): 修复跨 block 去重时间窗单位错误 + 消除 bigramJaccard 重复实现 (ISSUE-041);

- CROSS_BLOCK_TIME_WINDOW_MS=120000 误将毫秒值与秒级时间戳比较,实际窗口约 33 小时
  而非预期的 2 分钟;改为 CROSS_BLOCK_TIME_WINDOW_SEC=120(秒)
- 移除 chat-display.ts 私有的 computeCharBigrams / bigramJaccard,统一从 message.ts
  导入 bigramJaccardSimilarity,避免两处实现分叉

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-chat): 修复 realtime + hydration 跨 runId 双气泡复发 (ISSUE-041) (#437)

* fix(home-chat): 修复 realtime + hydration 跨 runId 双气泡复发 (ISSUE-041);

- 新增 isSyntheticRunId 共享识别函数(覆盖 runId 缺失 / DEFAULT_RUN_ID / runId === threadId 三类合成回退标记),三层 dedup 一致放宽:
  1. message-ledger.ts::isSemanticEquivalentEntry:runId 不等时若任一侧 synthetic 则放行,threadId + role + 内容前缀 + origin 多元仍是必要约束;
  2. conversation-tree.ts fallback 段 runMatches:识别合成 runId 兼容分支,避免同内容 fallback message 被强制重建为重复节点;
  3. conversation-tree.ts collapseDefaultTurnDuplicates → collapseSyntheticTurnDuplicates:扩展为识别 runId === threadId 的合成 turn;时间窗判定改为 per-child timestamp vs concrete turn timeRange,多轮场景下不再误放过期 concrete turn。
- session-hydration.ts::fallbackRunId 注释 ISSUE-041 契约(保留兜底防御,等 Phase 2 后端代理层注入 runId 后再渐进移除)。
- 新增 16 例自动化回归(含 1 例反向回滚断言):
  · message-ledger A1-A5 + isSyntheticRunId 单元 + 端到端 ledger merge(共 7 例);
  · conversation-tree C1/C2/C3/C5 + D4 反向回滚(共 5 例);
  · session-hydration D1/D1+/D2/D3 端到端(共 4 例)。
- docs/issue.md 追加 ISSUE-041 全栈解析(含 refresh 自愈非对称的根因证据、多轮二阶恶化、Phase 2-4 路线图、诊断抓手与同类问题影响),闭环 ISSUE-040 Q3 长尾自识别。

回归状态:482 测试全绿 + tsc 0 错误;浏览器实机 5 场景 × 3 次验证清单见 .context/issue-041/validation-protocol.md,待用户已登录态 Chrome 桥接就绪后执行。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* docs(rfcs): 新增 Phase 3 / Phase 4 架构 RFC 草稿(ISSUE-041 后续路线图);

- docs/rfcs/0001-conversation-architecture-refactor.md:Phase 3 架构重塑 RFC(Codex Thread→Turn→Item 数据模型 / 6 层去重金字塔精简到 3 层 / 抽象 utils/dedup/ + config/projection-thresholds.ts / 投影缓存 / 8 sub-PR 渐进迁移路线 / 兼容性回归与风险评估)。
- docs/rfcs/0002-ui-interaction-enhancements.md:Phase 4 UI 交互能力 backlog(Reasoning Panel + Sub-Agent 嵌套 / 工具进度 + 中断审批 / Conversation Branching + Timeline 增强;按用户优先级 1/2/3 分组,附实施依赖图与 Acceptance Criteria)。

均为 Draft 状态,待团队评审通过后启动多 PR 渐进迁移。本 commit 仅文档先行,不动代码。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-chat): 增强 synthetic turn 折叠相似度判定与时间窗整体吸收 (ISSUE-041);

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-chat): 双层防御消除跨 runId 三气泡——泛化 turn 折叠 + 跨 block 去重 (ISSUE-041);

将 collapseSyntheticTurnDuplicates 泛化为 collapseOverlappingTurns:按 threadId 分组,
对 synthetic turn 与同组 concrete turn 时间重叠+内容覆盖的进行折叠(双 concrete turn
保留以防误折叠合法多 run);新增 chat-display 层 dedupeAdjacentAssistantBlocks
作为安全网,对时间窗内内容高度相似的相邻 assistant-reply block 保留更完整的一个。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(test): 补充 message-ledger 测试 fixture 缺失的 id 字段 (ISSUE-041)

tsconfig.vitest.json 类型检查报 TS2741:baseRealtime 对象缺少
MessageLedgerEntry 必需的 id 属性。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(chat-display): 修复跨 block 去重时间窗单位错误 + 消除 bigramJaccard 重复实现 (ISSUE-041);

- CROSS_BLOCK_TIME_WINDOW_MS=120000 误将毫秒值与秒级时间戳比较,实际窗口约 33 小时
  而非预期的 2 分钟;改为 CROSS_BLOCK_TIME_WINDOW_SEC=120(秒)
- 移除 chat-display.ts 私有的 computeCharBigrams / bigramJaccard,统一从 message.ts
  导入 bigramJaccardSimilarity,避免两处实现分叉

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(home-chat): 修复跨 runId 双气泡时间窗单位错误 + 消除 bigramJaccard 重复实现 (ISSUE-041);

fallback 路径从无条件移除改为内容覆盖检查——跨所有同 threadId keeper 逐 child
匹配,避免含独特历史内容的 synthetic turn 被误折叠。加强 C3 断言为
toHaveLength(2) + synthetictoBeDefined。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(conversation-tree): isSyntheticTurnNode 补充 "default" runId 识别对齐 isSyntheticRunId (ISSUE-041);

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(ctl): 新增全套服务一键启停脚本 (#438)

* feat(ctl): 新增全套服务一键启停脚本 scripts/ctl.sh

支持 start/stop/restart/status/logs/build 子命令,覆盖依赖安装、
数据库迁移、前端构建、健康检查的完整生命周期。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(ctl): 修复 is_running 变量泄漏与并行 wait 退出码丢失;

- is_running() 中 pid_file 添加 local 声明,防止全局作用域污染
- 三处并行 wait 改为逐个检查退出码,任一子进程失败即报错中止

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(ctl): 修复健康检查不感知进程崩溃、路径逻辑重复与服务名校验缺失;

- wait_for_health 在 HTTP 轮询间隔中加入 is_running 检查,进程崩溃时立即返回失败
- is_running 改用 pid_file() 函数获取路径,消除硬编码重复
- cmd_logs 入口校验服务名是否属于 ALL_SERVICES,非法名称给出明确提示

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(ctl): 使用 exec 替代 eval 确保进程 PID 精确追踪与信号直达;

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(kg): 知识图谱模块生产就绪改造 — 实体管理、混合检索、路径探索、统计面板 (#439)

* feat(kg): 知识图谱模块生产就绪改造 — 语料库级图谱、实体管理、混合检索、路径探索、统计面板

后端变更:
- 新增 GET /graph/entities 实体分页列表(类型筛选+名称搜索)
- 新增 GET /graph/entities/{id} 实体详情含出/入关系
- 新增 GET /graph/stats 图谱统计(实体数/类型分布/置信度/密度/度数)
- 重写 find_neighbors: 递归 CTE 在 kg_relations 上实现多跳遍历
- 重写 find_path: 递归 CTE BFS 在 kg_relations 上查找最短路径

前端变更:
- 重写 graph/page.tsx: 语料库选择器 + 构建/浏览全流程
- 新增 EntityListPanel: 表格视图+类型筛选+分页
- 新增 EntityDetailPanel: 实体详情+关系列表(出边/入边)
- 新增 SearchBar: 混合检索(语义+图结构)
- 新增 PathExplorer: 双实体选择+BFS路径查找
- 新增 NeighborExplorer: 1/2/3跳邻居展开
- 新增 GraphStatsPanel: 实体数/类型分布/置信度/密度/度数
- 新增 BuildHistoryList: 结构化构建历史卡片(状态徽章+统计+耗时)

文档变更:
- 扩展 user-guide.md §4.5 为完整知识图谱用户指引
- 更新 knowledge-graph.md §3 新增架构模式精炼(Cognee ECL/Graphiti 双时态)
- 更新 knowledge-graph.md §4 交付物清单

测试变更:
- 新增 test_graph_entity_service.py: 9 项单元测试覆盖实体列表/详情/Schema

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(kg): 修复知识图谱模块 CI 失败 — 类型错误、ID 前缀、测试 mock;

- 移除 NeighborExplorer 组件调用中不存在的 entityName prop(TS2322)
- 为 find_neighbors 返回的 GraphNode.id 补齐 entity: 前缀
- 重写 find_path 测试,mock session.execute 而非 find_neighbors

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(kg): 修复审查发现的 7 项问题 — 安全编码、状态管理、双向路径搜索;

- 路由 path params 加 encodeURIComponent 防路径遍历(3 个 route 文件)
- EntityDetailPanel: 用 loadedEntityId 派生 loading 状态,切换实体时正确展示加载态并清除旧数据
- EntityListPanel: 搜索输入 300ms 防抖,用 completedKey 派生 loading 状态
- GraphStatsPanel: 用 result 组合状态区分加载中/失败/成功
- NeighborExplorer: entityId 变更时重置 expanded/neighbors
- graph_repository find_path: 递归 CTE 增加反向遍历分支,与 find_neighbors 双向语义对齐

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(kg): 修复审查发现的遗留问题 — 常量提取、路径搜索、会话管理;

- 前端:提取 ENTITY_TYPE_COLORS 至 constants.ts,消除三处 TYPE_COLORS 残留引用(会导致运行时崩溃)
- 后端:修复 find_path 递归 CTE 中 path 追加错误(r.target_id → ps.target_id)
- 后端:get_stats 改为接收外部 db 会话,消除自建会话
- 后端:get_entity_detail 增加 corpus_id 可选过滤,增强数据隔离

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(memory): 记忆模块生产就绪化 — 巩固管线重构 + 事实提取 + 上下文集成 + 文档完善 (#440)

* feat(memory): 重构记忆巩固管线为三阶段智能架构并增强核心模块

- 重构 _simple_consolidate 为三阶段管线(分段→去重→存储),借鉴 Claude Code AutoDream 四阶段范式
- 新增 PatternFactExtractor 基于正则模式的对话事实自动提取(preference/profile/rule/custom)
- 新增 ContextAssembler 记忆上下文组装器,管理 token 预算分配(30%记忆/50%历史/20%系统)
- 新增 AsyncScheduler 应用层调度器回退,当 pg_cron 不可用时提供等效定时任务能力
- 增强 search_memory API 支持分页(limit/offset)和过滤(memory_type/date_from/date_to)
- 集成 ContextAssembler 到 perception.py 记忆搜索回退路径
- 新增 34 条单元测试覆盖事实提取和调度器(全部通过)

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* docs(memory): 补充工业框架对标分析与用户操作指南

- docs/memory.md §2.4 新增 Claude Code 记忆架构深度对标(AutoDream 四阶段整理、三重门控调度、四类型分类法、三层上下文压缩、漂移防御)
- docs/memory.md §2.5 新增 Agent Harness 设计模式对标(三层压缩管线、Skill 按需加载、Task Graph 持久化)
- docs/memory.md §2.6 新增 Negentropy 差异化定位总结表
- docs/user-guide.md §5.8-§5.12 新增记忆形成机制、保留分数解读、搜索最佳实践、自动化配置指南、故障排除

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(memory): 恢复巩固管线 metadata 中遗漏的 event_count 字段

三阶段管线重构后 metadata 字典遗漏了原有的 event_count 字段,
导致 test_memory_service_lifecycle 集成测试 KeyError 失败。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(memory): 修复 Code Review 反馈的 7 项问题

1. search_memory 的 memory_type/date_from/date_to/offset 过滤参数现在在 vector_search 和 ilike_search 中实际生效
2. context_assembler 的 lazy import 移至文件顶部,与同文件风格一致
3. _simple_consolidate docstring 从「三阶段」更正为「四阶段」(含事实提取)
4. api.py search_memories 的 total 字段添加 TODO 标记(需独立 COUNT 查询)
5. AsyncScheduler 失败时回退 last_run_at,允许尽快重试而非等完整 interval
6. PatternFactExtractor 三段重复遍历提取为 _match_patterns 辅助方法
7. _consolidate SQL 拼接改为参数化绑定 :lookback::interval,消除注入风险

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(memory): 修复 Code Review 反馈的 3 项问题

- offset 分页参数未透传到底层搜索方法,现已正确传递
- datetime.fromisoformat() 缺少校验,非法日期返回 400 而非 500
- AsyncScheduler 派发任务未被追踪,stop() 时一并取消在途任务

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(memory): 修复 Code Review 反馈的 2 项问题

- 巩固管线阶段 4 事实提取调用包裹 try/except,防止导入或工厂失败中断管线
- 搜索接口 total 字段改为 -1 标记"未知",避免分页客户端误读

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(memory): 记忆模块 Phase 2 — LLM 事实提取 + 摘要生成 + Token 精确计数 + 检索反馈闭环 (#442)

* feat(memory): 记忆模块 Phase 2 — LLM 事实提取 + 摘要生成 + 精确 Token 计数 + 检索反馈闭环

- TokenCounter: 基于 tiktoken cl100k_base 编码器精确计数,替代 LENGTH/4 粗略估算
- LLMFactExtractor: LLM 结构化输出事实提取,PatternFactExtractor 作为降级后备
- MemorySummarizer: LLM 生成结构化用户画像摘要,缓存至 memory_summaries 表(TTL 24h)
- SummaryService: memory_summaries 表 CRUD(upsert 语义)
- RetrievalTracker: 检索效果反馈闭环,记录检索事件 + 显式反馈 API
- ContextAssembler: 优先注入摘要,tiktoken 精确 token 计数
- 新增 Alembic migration 0013/0014(memory_summaries + memory_retrieval_logs)
- 新增 MemorySummary + MemoryRetrievalLog ORM 模型
- 11 条新增单元测试,62 条全部通过,零回归

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* docs(memory): Phase 2 文档沉淀 — 两级提取策略 + 摘要巩固 + 精确计数 + 检索反馈 + 新增文献

- §4.2 扩展为两级事实提取策略说明(LLMFactExtractor + PatternFactExtractor)
- §5.4.1 新增摘要巩固策略(记忆再巩固理论 + 5 项工程对标)
- §6.3 更新 Token 估算为 tiktoken BPE 精确计数
- §6.5 新增检索效果反馈闭环(Rocchio + LTR + LongMemEval 评估维度)
- §15 新增 6 篇参考文献(Sennrich 2016, Sara 2015, Rocchio 1971, Burges 2005, Mem0, Letta)

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(memory): 修复 LLM 事实提取 prompt 类型名不匹配 + 检索指标 SQL 聚合优化;

- prompt 模板中 "pref" 改为 "preference",与 _VALID_FACT_TYPES 验证器对齐,避免 LLM 输出被静默降级为 "custom"
- get_effectiveness_metrics 改用 SQL COUNT+CASE 聚合,避免将全量日志行加载到 Python 内存

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* refactor(memory): Review 反馈修复 — 检索日志可观测性 + query 透传 + 模型配置去重;

1. 检索追踪 except 从 silent pass 改为 logger.debug,使故障可诊断
2. _record_access 新增 query 参数并从所有调用点透传,消除空 query 问题
3. 提取 _resolve_model_config 为共享工具 engine/utils/model_config.py,
   LLMFactExtractor 和 MemorySummarizer 统一引用,消除 DRY 违规
4. 同步更新单元测试 mock 路径

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(kg): 修复图谱双写数据流断链 — 一等公民表对齐 (#441)

* fix(kg): 修复图谱双写数据流断链 — 一等公民表对齐

- create_relation() 新增写入 kg_relations 一等公民表,保留 JSONB 过渡兼容
- get_graph() 优先从 kg_entities + kg_relations 读取,空时回退 JSONB
- clear_graph() 增加 kg_entities/kg_relations 表清理
- build_graph() 完成后调用 KgEntityService.batch_sync_from_graph_build()
- 更新 test_graph_repository 适配新读写路径

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(kg): 新增 PageRank 实体重要性评分与 RRF 混合检索

- 新增 graph_algorithms 模块,基于 NetworkX 实现 PageRank (Brin & Page, 1998) 计算,
  结果持久化至 kg_entities.importance_score
- 混合检索支持 Reciprocal Rank Fusion (Cormack et al., SIGIR 2009) 模式,
  可通过 GraphQueryConfig.use_rrf / rrf_k 配置,向后兼容线性加权模式
- 图谱构建完成后自动触发 PageRank 计算
- 实体列表支持按重要性排序(sort_by=importance)
- 统计面板展示 Top 5 PageRank 实体
- 图谱可视化节点半径映射 PageRank 分数,突出重要实体

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(kg): 新增 Louvain 社区检测与图谱可视化增强

- 新增 compute_louvain() 算法,基于 NetworkX 内置 Louvain (Blondel et al., 2008)
  在无向投影图上运行社区检测,结果持久化至 kg_entities.community_id
- 图谱构建完成后自动触发 Louvain 计算(紧接 PageRank 之后)
- 统计面板新增社区分布(community_count + community_distribution)
- 实体列表和详情响应包含 community_id 字段
- 图谱可视化节点按社区着色(Tableau 10 色盲友好调色板)
- 统计面板展示 Top 8 社区分布柱状图
- 实体表格新增社区列,显示色块标识
- 显式声明 networkx>=3.0 依赖(此前为隐式运行时导入)

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(kg): 新增 Alembic migration 0015 — 添加 importance_score 和 community_id 列

CI 集成测试失败根因:ORM 模型新增了 importance_score (PageRank) 和 community_id (Louvain)
列,但缺少对应的 Alembic migration,导致测试数据库 schema 不匹配。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(kg): 修复 Review 反馈的三个问题

1. RRF 搜索 graph_score 恒为 0 — 将 importance_score 写入 entity_data
2. PageRank/Louvain 逐条 UPDATE — 改为 VALUES CTE 批量更新
3. 一等公民表路径缺 app_name 过滤 — 文档明确 corpus 级去重设计意图

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(memory): Phase 2+ 增强 — 反馈闭环闭合 + Query-Aware 组装 + 近重复检测 + 测试覆盖 (#443)

* test(memory): Phase 2 组件测试覆盖 — TokenCounter / SummaryService / RetrievalTracker / MemorySummarizer;

新增 39 个单元测试用例,覆盖 Phase 2 四个核心组件:
- TokenCounter: 精确计数、空输入、幂等性、异步一致性、单调性(蜕变测试)
- SummaryService: upsert/get/delete CRUD 路径
- RetrievalTracker: 检索日志、引用标记、反馈记录、效果指标计算
- MemorySummarizer: 摘要生成、TTL 缓存命中/过期、LLM 失败降级、重试

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(memory): Phase 2+ 增强 — 反馈闭环闭合 + Query-Aware 组装 + 近重复检测 + 文档沉淀;

Gap 1 反馈闭环:
- _record_access 修复 user_id/app_name 透传(此前始终为空字符串)
- PostgresMemoryService 存储 _last_retrieval_log_id 供下游消费
- ContextAssembler 注入 mark_referenced 隐式反馈信号(RLHF[33])
- API 新增 POST /memory/retrieval/feedback 和 GET /memory/retrieval/metrics

Gap 2 Query-Aware:
- assemble() 新增 query/query_embedding 可选参数
- _call_get_context_window 传递 7 个参数(含 p_query, p_query_embedding)
- SQL 函数 NULL safe 退化:无 query 时保持纯 retention_score 排序
- 隐式反馈标记在上下文组装成功后触发

Gap 3 近重复检测:
- _is_duplicate 阈值从 0.9 降至 0.85(Henzinger[40])
- 新增 Jaccard 词重叠二次校验(0.80-0.85 区间,Broder[37])
- FactService 新增 merge_similar_facts() 语义去重方法

文档沉淀:
- docs/memory.md 权威源文件索引扩充 Phase 2 组件
- §15 追加 13 篇参考文献 [31]–[43]

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(memory): 修复 merge_similar_facts 过度删除 + retrieval_log_id 并发安全问题;

- merge_similar_facts: 锚点事实被删除后立即 break 内层循环,避免基于已删除 embedding 继续比对导致误删
- _record_access: 移除 _last_retrieval_log_id 实例属性,改为返回 log_id,消除共享可变状态的并发竞态
- ContextAssembler.assemble: memory_service 参数改为显式 retrieval_log_id,调用方直接传入

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(kg): Phase 3 生产就绪增强 — 增量构建 + 语义去重 + 管线健壮性 + 查询缓存 (#444)

* feat(kg): Phase 3 生产就绪增强 — 增量构建 + 语义去重 + 管线健壮性 + 查询缓存

Gap 3 [P1] 构建管线健壮性 (Nygard, 2018; Majors, 2022):
- Migration 0016: kg_build_runs 增加 progress_percent + warnings 列
- build_graph: 批处理循环进度上报、LLM 提取失败…
ThreeFish-AI added a commit that referenced this pull request May 19, 2026
…识管理统一入口(100 PRs / 843 文件) (#560) (#579)

* feat(agent-defs): 主 Agent 入库 + 按 DB 读 instruction + 模型选择回退 (#420)

* fix(agent-defs): 修复 Agent 加载路径 + 主 Agent 纳入 Interface Sync + 运行时按 DB 读 instruction;

- cli.py: --reload_agents 改用 Path(__file__) 推导的绝对路径,杜绝 cwd 依赖导致的「src/negentropy/negentropy」双重段错误;
- subagent_presets: 新增 NegentropyEngine root payload(adk_config.kind="root"),Sync 后 DB 出现主 Agent 行;
- sync API: 循环写入 config.kind,末尾调 invalidate_cache(prefix="subagent:") 批量失效;
- SubAgentResponse: 新增顶层 kind 字段(root/subagent),供前端置顶 + 徽章;
- model_resolver: 抽取 _load_subagent_row 共用单行查询,新增 resolve_subagent_instruction;
- _dynamic_instruction: 新增 InstructionProvider 工厂,root + 5 子 Agent 的 instruction 接入运行时 DB 读取;
- 测试: 更新 test_subagent_presets 覆盖 root payload + kind 断言;

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(home-llm): 修复无 Session 时模型选择回退 + SubAgents 列表 Root 置顶徽章;

- home-body: 新增 pendingLlmRef,改写 handleSelectedLlmModelChange 与 Effect 1,
  使「无 session 选模型→建 session→自动发送」全流程保持选择不丢失;
- SubAgents page: 按 kind="root" 置顶排序,Sync 按钮文案从「Sync Negentropy 5」改为「Sync Negentropy」;
- SubAgentCard: Root Agent 显示 violet 色 Root 徽章;

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(model-resolver): SubAgent 行缺失/未启用补回 60s TTL 负命中缓存;

回归点:重构 `_resolve_subagent_row` 时把空占位写入移到了 `loaded is None`
判断之后,导致禁用 Faculty 与未 Sync 环境下每次 LLM 请求都触发一次 DB 查询。
本次在 `loaded is None` 分支补 `_cache[cache_key] = ("", {"i": ""}, now)`,
让负命中同样落入 60s TTL,避免重复 DB 压力。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(home-llm): pending 模型选择仅对 startNewSession 新 id 消费;

回归点:Effect 1 的 pending 转移分支会在「首次进入既有 session」时触发,
把无 session 阶段的 pending 模型写入该 session 的 perThreadLlmRef,
并让 Effect 2 跳过 snapshot 初始化,导致服务器端记忆模型被静默替换。

修复方式:
- 新增 `pendingLlmTargetIdRef` 仅记录 startNewSession 返回的新 id;
- 通过 `startNewSessionWithLlmTarget` 包装内联调用与 `onNewSession` 两条路径;
- Effect 1 仅在 `sessionId === pendingLlmTargetIdRef.current` 时转移 pending,
  其余进入既有 session 的分支主动丢弃 pending,让 snapshot 正常生效。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(knowledge): 修复 KB Retrieve 全屏空白(前端聚合 rejection × 后端 hybrid/rrf 降级 × 502 上游错误码 × 诊断仪器化) (#421)

* fix(knowledge): 修复 Knowledge Base Retrieve 全屏空白(前端聚合 rejection + 后端 hybrid/rrf 降级 + 502 错误码 + 诊断日志);

双层 Bug 同因联修(详见 docs/issue.md ISSUE-026):
1. 前端 searchAcrossCorpora 旧实现以 Promise.allSettled 仅取 fulfilled,rejected 静默丢失,导致全部 Corpus 失败时返回 {count:0,items:[]} 走"成功路径"使 UI 空白且无任何提示——本次改为聚合三态(全成功/部分失败/全失败),SearchResults 类型扩展 errors[],handleRetrieve 对部分失败 toast.warning 透出原因;
2. 后端 service.search hybrid/rrf 旧实现未捕获 EmbeddingFailed,外部 Embedding 上游故障直接 500,丧失"keyword 仍可用"的优雅降级——本次 hybrid 失败回退 keyword-only、rrf 失败走与 not embedding_fn 等价的回退路径,semantic 仍传播以保留显式失败语义;
3. api.py _map_exception_to_http 拆分 EmbeddingFailed 分支映射到 502 Bad Gateway(保留 EMBEDDING_FAILED code),与 SearchError 自身错误的 500 区分,便于前端识别"上游修复后再试"语义;
4. embedding.py 调用 litellm 前后增加结构化诊断日志:api_base_host(脱敏 path/credentials 仅留 host)+ input_count + text_preview + kwargs_keys;失败附 upstream_response_text(沿异常链 __cause__/__context__ 提取 MaskedHTTPStatusError.text,已被 litellm 脱敏 URL,限长 500 字节);
5. 测试锁定:tests/unit_tests/knowledge/test_search_resilience.py 5 例(hybrid/rrf 降级 + semantic 传播 + EmbeddingFailed→502 + SearchError→500)+ tests/unit/knowledge/searchAcrossCorpora.test.ts 3 例(allSettled 三态);
6. docs/issue.md 追加 ISSUE-026,含后续防范(Promise.allSettled 必须聚合 rejection / vendor 失败必须 502 / hybrid 必须有降级路径 / vendor 调用必须 host+upstream_text 双信号)与同类问题影响清单。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(knowledge): searchAcrossCorpora 聚合保留 KnowledgeError code 并修正 _map_exception_to_http docstring;

Review #1(前端契约): SearchResultError 仅透 message 会丢弃 KnowledgeError.code(如 EMBEDDING_FAILED),削弱本次 502/500 拆分对前端"上游修复 vs 自身错误"的可分流价值——本次扩展 SearchResultError 增加可选 code,rejection instanceof KnowledgeError 时回填;全失败分支由 throw new Error 改为 throw new KnowledgeError(aggregatedCode, msg, {errors}),code 一致时透传原 code、混合时退化为 AGGREGATED_SEARCH_ERRORS,既保留分流能力又携带逐条失败明细;新增 1 例同 code 透传 + 1 例混合 code 退化的单测,全部 4 例通过。

Review #2(后端文档): api._map_exception_to_http docstring 仍只列 400/404/409/500,与新增 EmbeddingFailed→502 分支不一致;本次补 "502: 上游服务错误(vendor / Embedding 等外部依赖)" 一行,避免后续维护者按旧映射加分支。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(wiki-favicon): 修复 negentropy-wiki 站点 favicon.ico 单分辨率畸形导致浏览器回落默认地球图标; (#423)

- 根因:apps/negentropy-wiki/src/app/favicon.ico 是单分辨率畸形 ICO(file 输出 256x-1,高度字节 0xFF),且源图 logo.png 为非方形 800x798,导致 Chrome/Firefox/Safari 解析失败、tab 回落默认地球图标;
- 修复:用 Pillow 对 logo.png 做透明 padding 至 800x800 方形,再生成多分辨率 ICO(16/32/48/64/128/256 共六档)覆盖原文件;体积从 269KB 降至 118KB;
- 验证:file 输出 6 icons; pnpm build 后 .next/standalone 内 favicon route + body + meta 完整;pnpm start 后 curl /favicon.ico 返回 200 image/x-icon,HTML 自动注入 <link rel="icon">;
- 防范:docs/issue.md 追加 ISSUE-027,沉淀「ICO 必须方形 + 多分辨率」工程约束与 Pillow 流水线模板,禁止「原图直裹 ICO 头」反模式;
- 不动:layout.tsx / next.config.ts / start-production.mjs,保留 App Router metadata 自动注入路径,最小干预。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)

* feat(mcp-resources): 接入 Resource Templates 并贯通 PDF 图片到 Wiki Markdown (#422)

* feat(mcp-client): 接入 MCP Resource Templates 与同会话动态资源拉取;

新增 McpResourceTemplate 模型与 Alembic migration 0012,扩展 McpClientService 在
连接发现阶段并发调用 list_resource_templates(旧 server 不支持时静默兜底,不
阻断 tools 发现),新增 call_tool_and_resolve_resources:在同一 ClientSession 内
完成工具调用与所有 resource_link URI 的并发拉取(Semaphore 限流 4,return_exceptions
保证单条失败不击穿主流程)。这是接入 Negentropy Perceives 动态 FileResource
(perceives://pdf/<job_id>/<filename>)的协议层基石——动态实例的生命周期与工具
会话强绑定,必须在 session 关闭前完成 resources/read 才能避免事后失链。

Interface API 同步:load_mcp_server_tools 端点扩展为 capability 全量同步(tools
+ resource_templates,软删除已下线的 templates),LoadToolsResponse 新增
resource_templates 字段(向后兼容),新增 GET /mcp/servers/{id}/resource-templates
端点;list_mcp_servers 拆解为分段计数避免 JOIN 笛卡尔积;McpServerResponse 暴露
resource_template_count 给前端展示。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* feat(perceives-resources): PDF 图片资源端到端贯通到 GCS 与 Wiki Markdown;

把 Perceives MCP 工具调用返回的 ResourceLink 接入既有提取流水线(Ingest 与
Re-Parse from GCS),让 PDF 图片资源在主仓 ↔ Perceives 之间通过 MCP 协议
完整贯通:

- 提取层(extraction.py):新增 _extract_resource_link_assets 把 ResourceLink
  与同会话 read_resource 拉取的 base64 配对为 ExtractionAsset;_call_tool_with_plan
  改用 resolve_resource_links=True 路径,确保动态 URI 不会因会话关闭失链;
  _build_success_result 接收 resolved_resources / resource_errors,按 "warn +
  占位" 容错策略合并 assets 并标记 partial_failure 不阻断主入库;新增
  _rewrite_markdown_image_links 在 Markdown 写入 GCS 之前把相对路径图片引用
  重写为 /api/documents/{doc_id}/assets/{filename},重写采用 capture group 偏移
  以避免 alt 文本含同名 src 时误替换。

- Knowledge API:新增 GET /knowledge/wiki/documents/{document_id}/assets/{filename}
  公开端点,filename 严格白名单 ^[A-Za-z0-9._-]+$ 与 180 字符上限;鉴权策略与
  既有 wiki entry content 端点对齐——仅放通至少被一条 WikiPublicationEntry
  引用的 document,避免持任意 doc_id 拖走未发布文档资产。

- 前端 MCP 卡片(negentropy-ui):新增 Resource Templates 折叠区与 ResourceDetailPanel,
  视觉与 Tools 区完全镜像;page.tsx 在 tools:load 响应中同步消费
  resource_templates 段,状态合并到 ServerWithTools;动态实例(带 job_id)
  按设计不入卡片。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(mcp-client): Resource Templates 同步加 capability flag,避免静默兜底误清空模板表;

`_discover_on_transport` 对 `list_resource_templates` 的所有异常都会静默兜底返回空列表(兼容旧 server 与瞬态错误),但 `load_mcp_server_tools` 会把空列表当作权威结果裁剪 stale 行,导致一次网络抖动或 server bug 即抹掉全部模板;同时与 tools 同步"只增量更新、不裁剪"的语义不对称。

- `McpConnectionResult` 新增 `resource_templates_listed: bool`,仅在 `list_resource_templates` 成功返回时为 True;
- `load_mcp_server_tools` 仅在该 flag 为 True(权威空列表)时才裁剪 stale 模板,未支持/错误场景保留既有 DB 行;
- 单元测试覆盖 flag 在权威空列表与异常兜底两种路径下的取值。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* test(mcp-card): 单测 server fixture 补 resource_template_count 修 UI Type Checks;

`McpServer` 类型新增的必填字段 `resource_template_count` 未同步到 `McpServerCard.test.tsx` 的 server 固件,导致 ui-quality / UI Type Checks 在 5 处 `<McpServerCard server={...}>` 调用上报 TS2741。

- 在 server 固件加 `resource_template_count: 0`,spread 派生用例自动获得新字段。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(knowledge): 查询时 honor Corpus 自配 embedding 模型,修复 query/index 模型不一致 (ISSUE-028) (#424)

search() 原直接使用实例化时锁定的 self._embedding_fn(全局默认 gemini/text-embedding-004),
未读 corpus.config.models.embedding_config_id;而 _attach_embeddings 索引侧已按 corpus pin 走
专属 fn。两侧不对称导致:用户在 Corpus Settings 已切到 openai/text-embedding-3-small(1536 维),
索引按 OpenAI 生成,查询仍走 Gemini 全局默认经 localhost:3392 翻译代理报 400。

修复:
- 新增 _resolve_embedding_fn(corpus_config) 助手,corpus pin 优先 → 退回 service 默认 fn;
- search() 入口加载 corpus_config + embedding_fn 本地变量,rrf/hybrid/semantic 三分支替换;
- ISSUE-026 keyword 兜底 + 502 映射 + 诊断日志原样保留,零回归;
- 新增 5 例单元测试覆盖 corpus pin 命中/落空/兜底/rrf/semantic 上抛,577 全绿。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)

* fix(agent-llm): 修复 Home Send 时 LLM 凭证未从 DB 读取导致 AuthenticationError (#425)

* fix(docs): 同步文档启动命令与 cli.py 修复,消除 Home Send 500 复发路径;

cli.py 的 agents_dir 已在 35204ff 从 src/negentropy 修正为 src,
但 README / docs 下 4 个文件 7 处仍写 --reload_agents src/negentropy,
用户照文档启动复现 ValueError: Agent not found 500。
统一替换为 uv run negentropy serve(SSOT),
追加 ISSUE-029(文档漂移)与 ISSUE-030(SubAgents root Agent 防回归)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(agent-llm): 修复 Home Send 时 LLM 凭证未从 DB 读取导致 AuthenticationError;

DynamicRootLiteLlm/DynamicSubagentLiteLlm 在 ContextVar 或 sub_agents.model
为空时直接返回 None,回退到构造时无 api_key 的硬编码实例,绕过了 DB 中
已配置的 vendor_configs 凭证。现在始终通过 resolve_llm_config() 从 DB
解析默认模型的完整凭证(含 api_key)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(home-chat): 修复长耗时回复双气泡 + 首条未格式化 (ISSUE-031); (#426)

ADK 仅持久化 partial=false 终态事件,realtime 与 hydration 在
同一逻辑消息上派出不同的 messageId(首个 partial id vs 终态 id)。
isSemanticEquivalentEntry 的 8s 时间窗在长耗时回复下硬拒绝,导致
ledger 双 entry → events 过滤失败 → conversation tree 双节点 →
UI 渲染双气泡(首条因 streaming-markdown 尾部判定走 raw text 分支)。

修复 (最小干预 + 正交分解):
- message-ledger.ts: 内容严格相等时跳过 8s 时间窗硬拒绝。
- conversation-tree.ts: assistant 已收尾节点在内容严格相等时
  也允许 findMatchingTextNodeId 命中复用,作为防御性收敛。
- 三层回归测试覆盖 ">8s 跨度 + messageId 不同 + 内容严格相等"。

UI 全量 70 文件 396 测试通过;typecheck/typecheck:test/eslint 零报错。
docs/issue.md 沉淀 ISSUE-031;CHANGELOG.md 同步条目。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)

* fix(home-chat): 修复 Home 对话 title 凭证缺失与 OTLP logs/metrics 404 双联缺陷 (#427)

* fix(home-chat): 修复 Home 对话 title 凭证缺失 + OTLP logs/metrics 404 双联缺陷;

(1) SessionSummarizer 同步 __init__ 在 60s 缓存 miss 时回退到无 api_key 硬编码默认,
导致 LiteLLM AuthenticationError;改为 async classmethod create() 经 resolve_llm_config()
从 DB 读取完整凭证(与 commit 8ce35d5 修复 DynamicRootLiteLlm 同 SoT),调用方
session_service._generate_title_for_session 切换为 await SessionSummarizer.create(),
对 resolver 返回 kwargs 做防御性浅拷贝避免与 60s 缓存层耦合。

(2) ADK 上游 _get_otel_exporters() 把 OTEL_EXPORTER_OTLP_ENDPOINT 视为 OTLP 三件套
总开关,无差别注册 OTLPSpanExporter / OTLPMetricExporter / OTLPLogExporter;后两者
对 Langfuse 不存在的 /v1/metrics、/v1/logs 上报触发 SPA 404 SSR 错误页(每次对话
反复输出大段 HTML)。bootstrap.py 新增 _install_noop_otel_logs_metrics_providers()
在 OTel env var 设置后立即抢注无 processor / 无 reader 的 SDK Logger/Meter Provider,
利用 OTel SDK Once-lock 让 ADK 后续 set_*_provider 静默 no-op,从而阻断 logs/metrics
上报;TracerProvider 链路与 OTEL_EXPORTER_OTLP_HEADERS 不动,traces 仍正常进入 Langfuse。

新增 tests/unit_tests/engine/test_summarization.py(3 例)+
tests/unit_tests/observability/test_otel_noop_providers.py(3 例,子进程隔离 OTel 全局
状态)锁定回归。CHANGELOG / docs/issue.md 沉淀 ISSUE-031(title 凭证缺失)与
ISSUE-032(OTLP logs/metrics 404)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* test(otel-noop): 移除 _sdk_config hasattr 兜底,让 SDK 私有属性变更显式触发回归;

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* test(session-title): 修复 DummySummarizer 缺失 async create() 导致集成测试 AttributeError;

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(bootstrap-otel): 消除 ADK Web 启动期 OTel Override Provider 双 WARNING (ISSUE-034); (#428)

将 ISSUE-033 的「抢占式 set_logger_provider/set_meter_provider」改为 patch
`google.adk.telemetry.setup._get_otel_exporters`,让其只返回 traces 的
span_processors,metric_readers/log_record_processors 永久置空。ADK
maybe_set_otel_providers 的 if 分支由此天然短路,set_*_provider 根本不被
调用,从源头消除 OTel SDK 的 "Overriding of current ... is not allowed"
WARNING;traces 链路、ADK ApiServerSpanExporter、TracingManager、LiteLLM
"otel" callback 行为完全不变。配套更新 3 个子进程隔离单测验证新语义,
并在 docs/issue.md 追加 ISSUE-034 完整记录。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)

* feat(e2e-auth): 浏览器验证协议落地 + Playwright 会话复用贯通 Google OAuth (#429)

* docs(browser-validation): 落地浏览器验证协议并补 ISSUE-034

- AGENTS.md(即 CLAUDE.md symlink)新增"Browser Validation Protocol"子节,
  约定登录态浏览器验证必须复用用户常用 Chrome 会话,禁止 sandbox 浏览器
  通过 Google 同意屏,明确凭证守则与三步连通性自检;
- 新建 docs/agents/browser-validation.md:含三种 MCP 浏览器工具能力对照、
  Mermaid 选型决策图、storageState 工作时序、风控应对、IEEE 引用;
  实测附注 chrome-devtools MCP 在 macOS 默认即可复用用户主 profile 登录态;
- docs/issue.md 追加 ISSUE-034,记录 sandbox 浏览器走 Google OAuth 被拦
  的表因/根因/处理方式/防范,便于跨上下文复用。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* test(e2e-auth): Playwright 会话复用以贯通 Google OAuth E2E

- playwright.config.ts 在 PLAYWRIGHT_AUTH=1 时启用两个项目:
  * setup(headless: false,匹配 *.setup.ts),让用户在弹出窗手动登录;
  * chromium-authenticated(dependencies: ['setup']),使用 storageState
    复用一次性人工登录的会话;
  支持 PLAYWRIGHT_STORAGE_STATE 与 PLAYWRIGHT_USER_DATA_DIR 覆盖默认;
  现有 chromium project 加 testIgnore 排除 .setup.ts,CI/默认行为零变;
- 新增 tests/e2e/auth.setup.ts:打开 /auth/google/login,5 分钟内允许
  用户在 Google 同意屏中手动完成登录,回跳后断言 /api/auth/me 2xx,
  写入 storageState;
- .gitignore 追加 apps/negentropy-ui/.auth/ 与 .userdata/,
  防止会话凭证随分支推送外泄。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(e2e-auth): 修复 OAuth setup 早退与 authed spec 双跑;

- auth.setup.ts: waitForURL 谓词追加 host 约束,避免在跳往 accounts.google.com
  瞬间因 pathname 已离开 /auth/google 而误判完成,导致 /api/auth/me 在用户登录前
  失败、storageState 永不写出。
- playwright.config.ts: 基础 chromium project 的 testIgnore 追加
  /.*\.authed\.spec\.ts$/,防止 PLAYWRIGHT_AUTH=1 时同一份认证 spec 在
  chromium-authenticated 与 chromium 中各跑一次(后者无 storageState 必失败)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(home-chat): 修复 Home 双气泡复发与 LLM 模型未 Send 即刷新丢失 (ISSUE-032/033); (#430)

ISSUE-032 (双气泡复发,与 ISSUE-031 正交):
- 根因:root agent prompt 主动导航 + log_activity tool 让 ADK 走双轮 LLM 调用,
  两轮各自带独立 messageId 走完整 TEXT_MESSAGE_* 三件套,UI 在同一
  assistant-reply bubble 内并列渲染两段近重复文本。
- 修复:utils/chat-display.ts::dedupeRedundantTextSegments 在
  buildAssistantReplyBlock 出口对同一 reply 内的 text segment 做字符二元组
  Jaccard 相似度计算,相似度 ≥ 0.5 且双方长度 ≥ 30 时丢弃前段、保留信息更
  完备的最终段。tool-group / reasoning / error 顺序不动。
- assistant-reply.message.content 联动重组,复制时也拿到折叠后的内容。

ISSUE-033 (LLM 模型未 Send 即刷新丢失):
- 根因:后端事实源 session.state.selected_llm_model 仅在 /run_sse 时随
  state_delta 写入,未 Send 时不更新;前端 perThreadLlmRef 是 useRef
  刷新即丢;snapshotForDisplay 也无值,回退到 default。
- 修复:app/home-body.tsx 顶部新增 readPersistedLlmModel /
  writePersistedLlmModel (typeof window 守卫 + try/catch SSR 安全);
  handleSelectedLlmModelChange 即时落盘到 localStorage;Effect 1 优先
  从 localStorage 还原;Effect 2 命中 snapshot 时同步回写 localStorage,
  让「后端 state ↔ localStorage」互为镜像。既有 forwardedProps.selected_llm_model
  在 Send 时仍写后端 state,跨设备一致性最终收敛。

测试:
- 新增 2 例 chat-display.test.ts 用例:折叠近重复段 + 差异度大不被折叠
- UI 全量 70 文件 398 测试通过;typecheck/typecheck:test/eslint 零报错

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)

* fix(bootstrap-otel): 消除被丢弃 PeriodicExportingMetricReader 守护线程的周期 WARNING (ISSUE-038) (#431)

* fix(bootstrap-otel): 消除被丢弃 PeriodicExportingMetricReader 守护线程的周期 WARNING (ISSUE-038);

ISSUE-034 的 patch 调用 original() 后再丢弃 metric_readers /
log_record_processors,但上游 _get_otel_exporters 已构造
PeriodicExportingMetricReader 并启动 60s 守护线程——reader 未注册
到 MeterProvider 导致每 tick 触发 "Cannot call collect on a
MetricReader ..." WARNING。改为绕过 original(),直接复用
_get_otel_span_exporter() 仅构造 traces span processor,根源
避免 OTLP metrics/logs exporter 被实例化。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* docs(bootstrap-otel): 修正 _disable_adk_otel_logs_metrics_exporters docstring 中的过期 hooks 引用;

旧 docstring 沿用重构前 `hooks = original()` 的中间变量术语,但新实现已不再调用 `original()`,函数体内也没有 `hooks` 绑定。
更新指引为「恢复 _get_otel_exporters 原函数闭包」或「直接构造完整 OTelHooks」,避免误导后续维护者寻找已不存在的对象。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(home-chat): 修复 Home 双气泡盲区与刷新后消息乱序 (ISSUE-039) (#432)

* fix(home-chat): 修复 Home 双气泡盲区与刷新后消息乱序 (ISSUE-038);

- chat-display: dedupeRedundantTextSegments 增加四层判定(精确匹配 / 严格前缀 / 等价内容 / Jaccard),覆盖 ADK 双轮 LLM 短回复(如 "Pong!")的双气泡盲区。
- session-hydration: mergeEventsWithRealtimePriority 交换参数顺序,让 realtime 事件覆盖 hydrated;TEXT_MESSAGE_CONTENT 的 eventKey 时间戳改用 toFixed(3) 消除浮点抖动导致的同一事件重复保留。
- message-ledger: MessageLedgerEntry 新增可选 sourceOrder 作 createdAt 相同时的稳定 tiebreaker,替代 UUID localeCompare 的随机字典序;抽出 compareLedgerEntriesByTime 复用,类型保持向后兼容(缺省回退 Number.MAX_SAFE_INTEGER)。
- 新增 5 项单元测试覆盖:短回复精确匹配、前缀含尾部追加、Jaccard 长文本、eventKey 浮点稳定、sourceOrder 稳定排序;docs/issue.md 增补 ISSUE-038 摘要。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* test(home-chat): 补 mergeEventsWithRealtimePriority 生命周期事件覆盖回归用例;

针对 ISSUE-039 第 3 项修复(mergeEventsWithRealtimePriority 参数顺序交换)
原有 RUN_STARTED 类生命周期事件用例缺位——之前的 messageId 重叠用例在
step 3 即被过滤为 filteredHydratedEvents=[],无法验证 step 4 mergeEvents
入参顺序对 key 冲突归并的影响。

补一条 RUN_STARTED 用例:realtime / hydrated 同 threadId/runId/timestamp
(eventKey 字节级一致)→ 用对象引用断言保留的是 realtime 版本,作为参数
顺序交换的最直接证据。该用例在交换前会失败、交换后通过,形成有效回归网。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(home-chat): 消除 LLM 思考独白溢出 / 推理头常驻 / 刷新乱序残留 (ISSUE-040) (#433)

* fix(home-chat): 消除 LLM 思考独白溢出 / 推理头常驻 / 刷新乱序残留 (ISSUE-040);

- 过滤 ADK Part 中 thought=true 与 type=thinking|thought|reasoning 系列推理字段,避免 reasoning_content 溢出到 TEXT_MESSAGE_CONTENT;推理文本改路由为 ne.a2ui.thought 自定义事件保留可观测性。
- createStepFinishedEvent 同步透出 stepName,AdkMessageStreamNormalizer 持有 stepId→stepName 映射,根治 ag-ui v0.0.47 校验器 "Cannot send 'STEP_FINISHED' for step \"undefined\"" 中断 run 导致的推理头永驻 started 现象。
- conversation-tree fallback 段重建消息节点时优先复用 ledger 已有 sourceOrder,避免被推到 events 末尾破坏 compareLedgerEntriesByTime tiebreaker。
- session-hydration eventKey 全事件类型统一走 toFixed(3) 毫秒级时间戳,并为 STEP_STARTED/STEP_FINISHED 显式按 (threadId, runId, stepId) 作 key,覆盖 STEP_*/CUSTOM/STATE_*/RAW 在浮点抖动下的去重盲区。
- 新增 9 例单元回归覆盖 thought part 过滤 / STEP_FINISHED stepName / fallback sourceOrder / eventKey 浮点抖动;docs/issue.md 追加 ISSUE-040 全栈解析。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(home-chat): 消除 hydration sort 字典序污染 lifecycle 顺序导致的多消息刷新乱序 (ISSUE-040 Q3 长尾);

- hydrateSessionDetail 引入 WeakMap<BaseEvent, emitOrder>,sort tiebreaker 用 normalizer 推入顺序代替 eventKey().localeCompare,保留 TEXT_MESSAGE_* 三件套 START→CONTENT→END 与跨 messageId 的 turn 边界。
- mergeEvents 同步改为按首次出现位置记录 insertionOrder 作 tiebreaker,避免最后一步 mergeEvents([], normalizedEvents) 再把刚排好的事件按字典序乱序。
- 新增同 timestamp 下 lifecycle 顺序断言用例;多轮真实后端 events fixture 经修复链路输出 user(R1)→assistant(R1)→user(R2)→assistant(R2) 完全符合时间线。
- docs/issue.md 在 ISSUE-040 末尾追加 Q3 长尾闭环(H5 字典序污染根因与最小干预修复)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* test(home-chat): 强化 ISSUE-040 H3 fallback sourceOrder 回归用例;

- 旧用例与单 snapshot 单条消息时新旧公式恰巧同值,断言无差异,无法拦截 H3 退化;
- 新用例构造「snapshot 数组顺序 vs ledger 时间序」错位场景:让 sourceOrder 在两条消息间发生互换,对回滚 H3 修复有强差异断言(已本地反向核验:回滚 conversation-tree.ts 修复后断言失败)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* feat(wiki-header): catalog 第一层提升为顶部 Header 导航 tabs (#434)

* feat(wiki-header): catalog 第一层提升为顶部 Header 导航 tabs;

将 publication catalog 的第一层 CONTAINER 节点(如 Harness-Engineering)
从左侧 Sidebar 迁移为顶部 Header tabs;第二层及以下保留于 Sidebar,整树向上提升一档。
设计参考 GitHub Docs / Stripe Docs / Docusaurus 的"顶 tabs + 左 sidebar 子树"模式。

主要变更:
- lib/wiki-api.ts 追加 findFirstDocumentSlug / findActiveTopLevelSlug / resolveSectionView
  纯函数,作为 Header tabs 与 Sidebar 切片的单一事实源。
- 新增 WikiHeader Server Component(仅 <Link>,SSG 友好):渲染品牌 + 水平 tabs;
  CONTAINER tab 跳转 DFS 首个后代 DOCUMENT;无文档则禁用 span。
- WikiLayoutShell 增加 header? prop,渲染于 .wiki-layout 之外作为兄弟节点,
  避免触动既有 3 列 Grid 与 data-toc 三态。
- /{pubSlug} 与 /{pubSlug}/{...entrySlug} 两条路由共用 resolveSectionView 派生视图:
  pub 根页默认激活首项;entry 页按 slug 反查所属一级。
- globals.css 引入 --wiki-header-height 并把 sidebar / toc-aside 的 sticky top
  改为 var 引用,确保滚动时 Header 常驻不挡 sidebar。
- 新增 wiki-section-view.test.ts 12 用例覆盖空树 / 单 / 多 / 深路径 / DOCUMENT-only
  / 无后代 DOCUMENT 等边界。

回归保障:home / 不变;既有 WikiNavTree / WikiToc 测试 API 未变;47/47 单测全绿。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(wiki-header): Header 缺失时 sidebar/toc 不再残留偏移;

通过 data-header 属性标记 Header 是否存在,CSS 侧条件生效
--wiki-header-height 偏移,避免空导航树时出现 56px 空白间隙。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* refactor(config): 废弃 .env*,统一 YAML 三级配置(local > user > default) (#436)

* refactor(config): 废弃 .env* 加载链路,引入 config.local.yaml 统一 YAML 三级配置;

- 移除 10 个 Python 配置模块中的 env_file / _get_env_files 逻辑
- yaml_loader 新增 config.local.yaml 作为最高优先级 YAML 来源
- config.default.yaml 合并 .env 全部非机密差异值(含 OAuth 端口 6600→3292 校正)
- 新增 3 例 config.local.yaml 优先级测试

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* docs(config): 同步 .env 废弃后的文档与 CHANGELOG;

- development.md / sso.md / framework.md / user-guide.md / zh-CN/README.md 中 .env 引用替换为 config.local.yaml
- CHANGELOG 新增 ISSUE-041 变更记录
- docs/issue.md 新增 ISSUE-041 经验沉淀
- .gitignore 新增 apps/negentropy/config.local.yaml 排除规则

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(config): 放宽 .gitignore 中 config.local.yaml 匹配规则,覆盖任意 cwd 场景;

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(home-chat): 修复 realtime + hydration 跨 runId 双气泡复发 (ISSUE-041) (#435)

* fix(home-chat): 修复 realtime + hydration 跨 runId 双气泡复发 (ISSUE-041);

- 新增 isSyntheticRunId 共享识别函数(覆盖 runId 缺失 / DEFAULT_RUN_ID / runId === threadId 三类合成回退标记),三层 dedup 一致放宽:
  1. message-ledger.ts::isSemanticEquivalentEntry:runId 不等时若任一侧 synthetic 则放行,threadId + role + 内容前缀 + origin 多元仍是必要约束;
  2. conversation-tree.ts fallback 段 runMatches:识别合成 runId 兼容分支,避免同内容 fallback message 被强制重建为重复节点;
  3. conversation-tree.ts collapseDefaultTurnDuplicates → collapseSyntheticTurnDuplicates:扩展为识别 runId === threadId 的合成 turn;时间窗判定改为 per-child timestamp vs concrete turn timeRange,多轮场景下不再误放过期 concrete turn。
- session-hydration.ts::fallbackRunId 注释 ISSUE-041 契约(保留兜底防御,等 Phase 2 后端代理层注入 runId 后再渐进移除)。
- 新增 16 例自动化回归(含 1 例反向回滚断言):
  · message-ledger A1-A5 + isSyntheticRunId 单元 + 端到端 ledger merge(共 7 例);
  · conversation-tree C1/C2/C3/C5 + D4 反向回滚(共 5 例);
  · session-hydration D1/D1+/D2/D3 端到端(共 4 例)。
- docs/issue.md 追加 ISSUE-041 全栈解析(含 refresh 自愈非对称的根因证据、多轮二阶恶化、Phase 2-4 路线图、诊断抓手与同类问题影响),闭环 ISSUE-040 Q3 长尾自识别。

回归状态:482 测试全绿 + tsc 0 错误;浏览器实机 5 场景 × 3 次验证清单见 .context/issue-041/validation-protocol.md,待用户已登录态 Chrome 桥接就绪后执行。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* docs(rfcs): 新增 Phase 3 / Phase 4 架构 RFC 草稿(ISSUE-041 后续路线图);

- docs/rfcs/0001-conversation-architecture-refactor.md:Phase 3 架构重塑 RFC(Codex Thread→Turn→Item 数据模型 / 6 层去重金字塔精简到 3 层 / 抽象 utils/dedup/ + config/projection-thresholds.ts / 投影缓存 / 8 sub-PR 渐进迁移路线 / 兼容性回归与风险评估)。
- docs/rfcs/0002-ui-interaction-enhancements.md:Phase 4 UI 交互能力 backlog(Reasoning Panel + Sub-Agent 嵌套 / 工具进度 + 中断审批 / Conversation Branching + Timeline 增强;按用户优先级 1/2/3 分组,附实施依赖图与 Acceptance Criteria)。

均为 Draft 状态,待团队评审通过后启动多 PR 渐进迁移。本 commit 仅文档先行,不动代码。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(home-chat): 增强 synthetic turn 折叠相似度判定与时间窗整体吸收 (ISSUE-041);

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(home-chat): 双层防御消除跨 runId 三气泡——泛化 turn 折叠 + 跨 block 去重 (ISSUE-041);

将 collapseSyntheticTurnDuplicates 泛化为 collapseOverlappingTurns:按 threadId 分组,
对 synthetic turn 与同组 concrete turn 时间重叠+内容覆盖的进行折叠(双 concrete turn
保留以防误折叠合法多 run);新增 chat-display 层 dedupeAdjacentAssistantBlocks
作为安全网,对时间窗内内容高度相似的相邻 assistant-reply block 保留更完整的一个。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(test): 补充 message-ledger 测试 fixture 缺失的 id 字段 (ISSUE-041)

tsconfig.vitest.json 类型检查报 TS2741:baseRealtime 对象缺少
MessageLedgerEntry 必需的 id 属性。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(chat-display): 修复跨 block 去重时间窗单位错误 + 消除 bigramJaccard 重复实现 (ISSUE-041);

- CROSS_BLOCK_TIME_WINDOW_MS=120000 误将毫秒值与秒级时间戳比较,实际窗口约 33 小时
  而非预期的 2 分钟;改为 CROSS_BLOCK_TIME_WINDOW_SEC=120(秒)
- 移除 chat-display.ts 私有的 computeCharBigrams / bigramJaccard,统一从 message.ts
  导入 bigramJaccardSimilarity,避免两处实现分叉

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(home-chat): 修复 realtime + hydration 跨 runId 双气泡复发 (ISSUE-041) (#437)

* fix(home-chat): 修复 realtime + hydration 跨 runId 双气泡复发 (ISSUE-041);

- 新增 isSyntheticRunId 共享识别函数(覆盖 runId 缺失 / DEFAULT_RUN_ID / runId === threadId 三类合成回退标记),三层 dedup 一致放宽:
  1. message-ledger.ts::isSemanticEquivalentEntry:runId 不等时若任一侧 synthetic 则放行,threadId + role + 内容前缀 + origin 多元仍是必要约束;
  2. conversation-tree.ts fallback 段 runMatches:识别合成 runId 兼容分支,避免同内容 fallback message 被强制重建为重复节点;
  3. conversation-tree.ts collapseDefaultTurnDuplicates → collapseSyntheticTurnDuplicates:扩展为识别 runId === threadId 的合成 turn;时间窗判定改为 per-child timestamp vs concrete turn timeRange,多轮场景下不再误放过期 concrete turn。
- session-hydration.ts::fallbackRunId 注释 ISSUE-041 契约(保留兜底防御,等 Phase 2 后端代理层注入 runId 后再渐进移除)。
- 新增 16 例自动化回归(含 1 例反向回滚断言):
  · message-ledger A1-A5 + isSyntheticRunId 单元 + 端到端 ledger merge(共 7 例);
  · conversation-tree C1/C2/C3/C5 + D4 反向回滚(共 5 例);
  · session-hydration D1/D1+/D2/D3 端到端(共 4 例)。
- docs/issue.md 追加 ISSUE-041 全栈解析(含 refresh 自愈非对称的根因证据、多轮二阶恶化、Phase 2-4 路线图、诊断抓手与同类问题影响),闭环 ISSUE-040 Q3 长尾自识别。

回归状态:482 测试全绿 + tsc 0 错误;浏览器实机 5 场景 × 3 次验证清单见 .context/issue-041/validation-protocol.md,待用户已登录态 Chrome 桥接就绪后执行。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* docs(rfcs): 新增 Phase 3 / Phase 4 架构 RFC 草稿(ISSUE-041 后续路线图);

- docs/rfcs/0001-conversation-architecture-refactor.md:Phase 3 架构重塑 RFC(Codex Thread→Turn→Item 数据模型 / 6 层去重金字塔精简到 3 层 / 抽象 utils/dedup/ + config/projection-thresholds.ts / 投影缓存 / 8 sub-PR 渐进迁移路线 / 兼容性回归与风险评估)。
- docs/rfcs/0002-ui-interaction-enhancements.md:Phase 4 UI 交互能力 backlog(Reasoning Panel + Sub-Agent 嵌套 / 工具进度 + 中断审批 / Conversation Branching + Timeline 增强;按用户优先级 1/2/3 分组,附实施依赖图与 Acceptance Criteria)。

均为 Draft 状态,待团队评审通过后启动多 PR 渐进迁移。本 commit 仅文档先行,不动代码。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(home-chat): 增强 synthetic turn 折叠相似度判定与时间窗整体吸收 (ISSUE-041);

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(home-chat): 双层防御消除跨 runId 三气泡——泛化 turn 折叠 + 跨 block 去重 (ISSUE-041);

将 collapseSyntheticTurnDuplicates 泛化为 collapseOverlappingTurns:按 threadId 分组,
对 synthetic turn 与同组 concrete turn 时间重叠+内容覆盖的进行折叠(双 concrete turn
保留以防误折叠合法多 run);新增 chat-display 层 dedupeAdjacentAssistantBlocks
作为安全网,对时间窗内内容高度相似的相邻 assistant-reply block 保留更完整的一个。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(test): 补充 message-ledger 测试 fixture 缺失的 id 字段 (ISSUE-041)

tsconfig.vitest.json 类型检查报 TS2741:baseRealtime 对象缺少
MessageLedgerEntry 必需的 id 属性。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(chat-display): 修复跨 block 去重时间窗单位错误 + 消除 bigramJaccard 重复实现 (ISSUE-041);

- CROSS_BLOCK_TIME_WINDOW_MS=120000 误将毫秒值与秒级时间戳比较,实际窗口约 33 小时
  而非预期的 2 分钟;改为 CROSS_BLOCK_TIME_WINDOW_SEC=120(秒)
- 移除 chat-display.ts 私有的 computeCharBigrams / bigramJaccard,统一从 message.ts
  导入 bigramJaccardSimilarity,避免两处实现分叉

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(home-chat): 修复跨 runId 双气泡时间窗单位错误 + 消除 bigramJaccard 重复实现 (ISSUE-041);

fallback 路径从无条件移除改为内容覆盖检查——跨所有同 threadId keeper 逐 child
匹配,避免含独特历史内容的 synthetic turn 被误折叠。加强 C3 断言为
toHaveLength(2) + synthetictoBeDefined。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(conversation-tree): isSyntheticTurnNode 补充 "default" runId 识别对齐 isSyntheticRunId (ISSUE-041);

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* feat(ctl): 新增全套服务一键启停脚本 (#438)

* feat(ctl): 新增全套服务一键启停脚本 scripts/ctl.sh

支持 start/stop/restart/status/logs/build 子命令,覆盖依赖安装、
数据库迁移、前端构建、健康检查的完整生命周期。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(ctl): 修复 is_running 变量泄漏与并行 wait 退出码丢失;

- is_running() 中 pid_file 添加 local 声明,防止全局作用域污染
- 三处并行 wait 改为逐个检查退出码,任一子进程失败即报错中止

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(ctl): 修复健康检查不感知进程崩溃、路径逻辑重复与服务名校验缺失;

- wait_for_health 在 HTTP 轮询间隔中加入 is_running 检查,进程崩溃时立即返回失败
- is_running 改用 pid_file() 函数获取路径,消除硬编码重复
- cmd_logs 入口校验服务名是否属于 ALL_SERVICES,非法名称给出明确提示

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(ctl): 使用 exec 替代 eval 确保进程 PID 精确追踪与信号直达;

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* feat(kg): 知识图谱模块生产就绪改造 — 实体管理、混合检索、路径探索、统计面板 (#439)

* feat(kg): 知识图谱模块生产就绪改造 — 语料库级图谱、实体管理、混合检索、路径探索、统计面板

后端变更:
- 新增 GET /graph/entities 实体分页列表(类型筛选+名称搜索)
- 新增 GET /graph/entities/{id} 实体详情含出/入关系
- 新增 GET /graph/stats 图谱统计(实体数/类型分布/置信度/密度/度数)
- 重写 find_neighbors: 递归 CTE 在 kg_relations 上实现多跳遍历
- 重写 find_path: 递归 CTE BFS 在 kg_relations 上查找最短路径

前端变更:
- 重写 graph/page.tsx: 语料库选择器 + 构建/浏览全流程
- 新增 EntityListPanel: 表格视图+类型筛选+分页
- 新增 EntityDetailPanel: 实体详情+关系列表(出边/入边)
- 新增 SearchBar: 混合检索(语义+图结构)
- 新增 PathExplorer: 双实体选择+BFS路径查找
- 新增 NeighborExplorer: 1/2/3跳邻居展开
- 新增 GraphStatsPanel: 实体数/类型分布/置信度/密度/度数
- 新增 BuildHistoryList: 结构化构建历史卡片(状态徽章+统计+耗时)

文档变更:
- 扩展 user-guide.md §4.5 为完整知识图谱用户指引
- 更新 knowledge-graph.md §3 新增架构模式精炼(Cognee ECL/Graphiti 双时态)
- 更新 knowledge-graph.md §4 交付物清单

测试变更:
- 新增 test_graph_entity_service.py: 9 项单元测试覆盖实体列表/详情/Schema

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(kg): 修复知识图谱模块 CI 失败 — 类型错误、ID 前缀、测试 mock;

- 移除 NeighborExplorer 组件调用中不存在的 entityName prop(TS2322)
- 为 find_neighbors 返回的 GraphNode.id 补齐 entity: 前缀
- 重写 find_path 测试,mock session.execute 而非 find_neighbors

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(kg): 修复审查发现的 7 项问题 — 安全编码、状态管理、双向路径搜索;

- 路由 path params 加 encodeURIComponent 防路径遍历(3 个 route 文件)
- EntityDetailPanel: 用 loadedEntityId 派生 loading 状态,切换实体时正确展示加载态并清除旧数据
- EntityListPanel: 搜索输入 300ms 防抖,用 completedKey 派生 loading 状态
- GraphStatsPanel: 用 result 组合状态区分加载中/失败/成功
- NeighborExplorer: entityId 变更时重置 expanded/neighbors
- graph_repository find_path: 递归 CTE 增加反向遍历分支,与 find_neighbors 双向语义对齐

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(kg): 修复审查发现的遗留问题 — 常量提取、路径搜索、会话管理;

- 前端:提取 ENTITY_TYPE_COLORS 至 constants.ts,消除三处 TYPE_COLORS 残留引用(会导致运行时崩溃)
- 后端:修复 find_path 递归 CTE 中 path 追加错误(r.target_id → ps.target_id)
- 后端:get_stats 改为接收外部 db 会话,消除自建会话
- 后端:get_entity_detail 增加 corpus_id 可选过滤,增强数据隔离

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* feat(memory): 记忆模块生产就绪化 — 巩固管线重构 + 事实提取 + 上下文集成 + 文档完善 (#440)

* feat(memory): 重构记忆巩固管线为三阶段智能架构并增强核心模块

- 重构 _simple_consolidate 为三阶段管线(分段→去重→存储),借鉴 Claude Code AutoDream 四阶段范式
- 新增 PatternFactExtractor 基于正则模式的对话事实自动提取(preference/profile/rule/custom)
- 新增 ContextAssembler 记忆上下文组装器,管理 token 预算分配(30%记忆/50%历史/20%系统)
- 新增 AsyncScheduler 应用层调度器回退,当 pg_cron 不可用时提供等效定时任务能力
- 增强 search_memory API 支持分页(limit/offset)和过滤(memory_type/date_from/date_to)
- 集成 ContextAssembler 到 perception.py 记忆搜索回退路径
- 新增 34 条单元测试覆盖事实提取和调度器(全部通过)

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* docs(memory): 补充工业框架对标分析与用户操作指南

- docs/memory.md §2.4 新增 Claude Code 记忆架构深度对标(AutoDream 四阶段整理、三重门控调度、四类型分类法、三层上下文压缩、漂移防御)
- docs/memory.md §2.5 新增 Agent Harness 设计模式对标(三层压缩管线、Skill 按需加载、Task Graph 持久化)
- docs/memory.md §2.6 新增 Negentropy 差异化定位总结表
- docs/user-guide.md §5.8-§5.12 新增记忆形成机制、保留分数解读、搜索最佳实践、自动化配置指南、故障排除

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(memory): 恢复巩固管线 metadata 中遗漏的 event_count 字段

三阶段管线重构后 metadata 字典遗漏了原有的 event_count 字段,
导致 test_memory_service_lifecycle 集成测试 KeyError 失败。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(memory): 修复 Code Review 反馈的 7 项问题

1. search_memory 的 memory_type/date_from/date_to/offset 过滤参数现在在 vector_search 和 ilike_search 中实际生效
2. context_assembler 的 lazy import 移至文件顶部,与同文件风格一致
3. _simple_consolidate docstring 从「三阶段」更正为「四阶段」(含事实提取)
4. api.py search_memories 的 total 字段添加 TODO 标记(需独立 COUNT 查询)
5. AsyncScheduler 失败时回退 last_run_at,允许尽快重试而非等完整 interval
6. PatternFactExtractor 三段重复遍历提取为 _match_patterns 辅助方法
7. _consolidate SQL 拼接改为参数化绑定 :lookback::interval,消除注入风险

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(memory): 修复 Code Review 反馈的 3 项问题

- offset 分页参数未透传到底层搜索方法,现已正确传递
- datetime.fromisoformat() 缺少校验,非法日期返回 400 而非 500
- AsyncScheduler 派发任务未被追踪,stop() 时一并取消在途任务

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(memory): 修复 Code Review 反馈的 2 项问题

- 巩固管线阶段 4 事实提取调用包裹 try/except,防止导入或工厂失败中断管线
- 搜索接口 total 字段改为 -1 标记"未知",避免分页客户端误读

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* feat(memory): 记忆模块 Phase 2 — LLM 事实提取 + 摘要生成 + Token 精确计数 + 检索反馈闭环 (#442)

* feat(memory): 记忆模块 Phase 2 — LLM 事实提取 + 摘要生成 + 精确 Token 计数 + 检索反馈闭环

- TokenCounter: 基于 tiktoken cl100k_base 编码器精确计数,替代 LENGTH/4 粗略估算
- LLMFactExtractor: LLM 结构化输出事实提取,PatternFactExtractor 作为降级后备
- MemorySummarizer: LLM 生成结构化用户画像摘要,缓存至 memory_summaries 表(TTL 24h)
- SummaryService: memory_summaries 表 CRUD(upsert 语义)
- RetrievalTracker: 检索效果反馈闭环,记录检索事件 + 显式反馈 API
- ContextAssembler: 优先注入摘要,tiktoken 精确 token 计数
- 新增 Alembic migration 0013/0014(memory_summaries + memory_retrieval_logs)
- 新增 MemorySummary + MemoryRetrievalLog ORM 模型
- 11 条新增单元测试,62 条全部通过,零回归

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* docs(memory): Phase 2 文档沉淀 — 两级提取策略 + 摘要巩固 + 精确计数 + 检索反馈 + 新增文献

- §4.2 扩展为两级事实提取策略说明(LLMFactExtractor + PatternFactExtractor)
- §5.4.1 新增摘要巩固策略(记忆再巩固理论 + 5 项工程对标)
- §6.3 更新 Token 估算为 tiktoken BPE 精确计数
- §6.5 新增检索效果反馈闭环(Rocchio + LTR + LongMemEval 评估维度)
- §15 新增 6 篇参考文献(Sennrich 2016, Sara 2015, Rocchio 1971, Burges 2005, Mem0, Letta)

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(memory): 修复 LLM 事实提取 prompt 类型名不匹配 + 检索指标 SQL 聚合优化;

- prompt 模板中 "pref" 改为 "preference",与 _VALID_FACT_TYPES 验证器对齐,避免 LLM 输出被静默降级为 "custom"
- get_effectiveness_metrics 改用 SQL COUNT+CASE 聚合,避免将全量日志行加载到 Python 内存

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* refactor(memory): Review 反馈修复 — 检索日志可观测性 + query 透传 + 模型配置去重;

1. 检索追踪 except 从 silent pass 改为 logger.debug,使故障可诊断
2. _record_access 新增 query 参数并从所有调用点透传,消除空 query 问题
3. 提取 _resolve_model_config 为共享工具 engine/utils/model_config.py,
   LLMFactExtractor 和 MemorySummarizer 统一引用,消除 DRY 违规
4. 同步更新单元测试 mock 路径

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(kg): 修复图谱双写数据流断链 — 一等公民表对齐 (#441)

* fix(kg): 修复图谱双写数据流断链 — 一等公民表对齐

- create_relation() 新增写入 kg_relations 一等公民表,保留 JSONB 过渡兼容
- get_graph() 优先从 kg_entities + kg_relations 读取,空时回退 JSONB
- clear_graph() 增加 kg_entities/kg_relations 表清理
- build_graph() 完成后调用 KgEntityService.batch_sync_from_graph_build()
- 更新 test_graph_repository 适配新读写路径

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* feat(kg): 新增 PageRank 实体重要性评分与 RRF 混合检索

- 新增 graph_algorithms 模块,基于 NetworkX 实现 PageRank (Brin & Page, 1998) 计算,
  结果持久化至 kg_entities.importance_score
- 混合检索支持 Reciprocal Rank Fusion (Cormack et al., SIGIR 2009) 模式,
  可通过 GraphQueryConfig.use_rrf / rrf_k 配置,向后兼容线性加权模式
- 图谱构建完成后自动触发 PageRank 计算
- 实体列表支持按重要性排序(sort_by=importance)
- 统计面板展示 Top 5 PageRank 实体
- 图谱可视化节点半径映射 PageRank 分数,突出重要实体

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* feat(kg): 新增 Louvain 社区检测与图谱可视化增强

- 新增 compute_louvain() 算法,基于 NetworkX 内置 Louvain (Blondel et al., 2008)
  在无向投影图上运行社区检测,结果持久化至 kg_entities.community_id
- 图谱构建完成后自动触发 Louvain 计算(紧接 PageRank 之后)
- 统计面板新增社区分布(community_count + community_distribution)
- 实体列表和详情响应包含 community_id 字段
- 图谱可视化节点按社区着色(Tableau 10 色盲友好调色板)
- 统计面板展示 Top 8 社区分布柱状图
- 实体表格新增社区列,显示色块标识
- 显式声明 networkx>=3.0 依赖(此前为隐式运行时导入)

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(kg): 新增 Alembic migration 0015 — 添加 importance_score 和 community_id 列

CI 集成测试失败根因:ORM 模型新增了 importance_score (PageRank) 和 community_id (Louvain)
列,但缺少对应的 Alembic migration,导致测试数据库 schema 不匹配。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(kg): 修复 Review 反馈的三个问题

1. RRF 搜索 graph_score 恒为 0 — 将 importance_score 写入 entity_data
2. PageRank/Louvain 逐条 UPDATE — 改为 VALUES CTE 批量更新
3. 一等公民表路径缺 app_name 过滤 — 文档明确 corpus 级去重设计意图

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* feat(memory): Phase 2+ 增强 — 反馈闭环闭合 + Query-Aware 组装 + 近重复检测 + 测试覆盖 (#443)

* test(memory): Phase 2 组件测试覆盖 — TokenCounter / SummaryService / RetrievalTracker / MemorySummarizer;

新增 39 个单元测试用例,覆盖 Phase 2 四个核心组件:
- TokenCounter: 精确计数、空输入、幂等性、异步一致性、单调性(蜕变测试)
- SummaryService: upsert/get/delete CRUD 路径
- RetrievalTracker: 检索日志、引用标记、反馈记录、效果指标计算
- MemorySummarizer: 摘要生成、TTL 缓存命中/过期、LLM 失败降级、重试

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* feat(memory): Phase 2+ 增强 — 反馈闭环闭合 + Query-Aware 组装 + 近重复检测 + 文档沉淀;

Gap 1 反馈闭环:
- _record_access 修复 user_id/app_name 透传(此前始终为空字符串)
- PostgresMemoryService 存储 _last_retrieval_log_id 供下游消费
- ContextAssembler 注入 mark_referenced 隐式反馈信号(RLHF[33])
- API 新增 POST /memory/retrieval/feedback 和 GET /memory/retrieval/metrics

Gap 2 Query-Aware:
- assemble() 新增 query/query_embedding 可选参数
- _call_get_context_window 传递 7 个参数(含 p_query, p_query_embedding)
- SQL 函数 NULL safe 退化:无 query 时保持纯 retention_score 排序
- 隐式反馈标记在上下文组装成功后触发

Gap 3 近重复检测:
- _is_duplicate 阈值从 0.9 降至 0.85(Henzinger[40])
- 新增 Jaccard 词重叠二次校验(0.80-0.85 区间,Broder[37])
- FactService 新增 merge_similar_facts() 语义去重方法

文档沉淀:
- docs/memory.md 权威源文件索引扩充 Phase 2 组件
- §15 追加 13 篇参考文献 [31]–[43]

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* fix(memory): 修复 merge_similar_facts 过度删除 + retrieval_log_id 并发安全问题;

- merge_similar_facts: 锚点事实被删除后立即 break 内层循环,避免基于已删除 embedding 继续比对导致误删
- _record_access: 移除 _last_retrieval_log_id 实例属性,改为返回 log_id,消除共享可变状态的并发竞态
- ContextAssembler.assemble: memory_service 参数改为显式 retrieval_log_id,调用方直接传入

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)


* feat(kg): Phase 3 生产就绪增强 — 增量构建 + 语义去重 + 管线健壮性 + 查询缓存 (#444)

* feat(kg): Phase 3 生产就绪增强 — 增量构建 + 语义去重 + 管线健壮性 + 查询缓存

Gap 3 [P1] 构建管线健壮性 (Nygard, 2018; Majors, 2022):
- Migration 0016: kg_build_runs 增加 progress_percent + warnings 列
- build_graph: 批处理循环进度上报、LLM 提取失败…

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
ThreeFish-AI added a commit that referenced this pull request Jun 8, 2026
…is_default + 创建期固化绑定); (#895)

根因: model_resolver._resolve 的回退链「缓存→vendor_configs→硬编码」从未查询
model_configs.is_default, 直接采用硬编码 _DEFAULT_EMBEDDING_MODEL(gemini/text-embedding-004),
违反该模块自身声明的解析链契约。与 ISSUE-028 互补: 028 修好「有 corpus pin」时索引/查询对称,
本缺陷是「无 pin」时双方都回退到忽略全局默认的 resolve_embedding_config()。

Fix #1 (model_resolver.py): 抽取共享 _build_resolved_config(复用 vendor 凭证/kwargs 构建);
新增 _load_default_model_config_row(is_default=True AND enabled=True) 与
_resolve_from_default_model_config; _resolve 在缓存命中后、vendor_configs 回退前插入
is_default 分支(独立 try/except, DB 异常降级不冒泡), 对 llm/embedding 对称生效。

Fix #2 (_shared.py + routes/corpus.py): 新增 resolve_default_model_config_id 与
_pin_default_embedding_config, create_corpus 序列化前将当前全局默认的 embedding_config_id
固化进 corpus.config.models, 使语料创建即绑定具体模型, 免疫日后全局默认变更;
后续改模型走 update_corpus 既有的维度比对 + 重建保护。

订正 model_resolver.py 陈旧注释(向量列固定 1536 维, 硬编码值仅末位回退)。
新增 7 例解析器单测 + 3 例固化单测; 连同既有相关单测 140 全过; ruff lint/format 全过。
记录于 docs/.agents/issue.md ISSUE-135。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
ThreeFish-AI added a commit that referenced this pull request Jul 1, 2026
…ne公式) (#1032)

* fix(perceives/cli): parse-pdf 图片资产补齐 auto pipeline 路径,修复候选 md 全量图片死链

CLI `_copy_image_assets` 此前仅处理传统(非 auto)路径——从
`result.enhanced_assets.output_directory` 拷图;对 auto pipeline 路径误判 no-op
(注释假设其「自带正确落盘」)。实则 auto pipeline 落盘约定 `_resolve_images_dir`
在未透传 output_dir 时回退到 `<cwd>/output/<stem>/images/`,与用户 `-o` 输出路径
不一致,导致候选 md 中全部 `./images/<filename>` 引用死链(本轮文档 21 图全断)。

扩展 `_copy_image_assets` 兼容两种结构:
- auto:从 `result.image_assets`(List[ImageAsset],含绝对 image_path)逐图收集;
- 传统:保留 `enhanced_assets.output_directory` 目录收集。
统一拷到 `Path(output).parent / "images"`,按 filename 去重、源/目标同文件跳过、
单图 OSError 不中断。改动局部于 CLI 边界,不影响 pipeline 行为。

验证:perceives parse-pdf --method auto 重转后 21 图引用 0 缺失,候选渲染图由
全破图恢复为正常嵌入。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(perceives/pdf): assembly figure-region 抑制改为内容实质性区分,恢复图边界标题/段落

assembly 的 ``_block_overlaps_special`` 命中后此前对非 caption 文本块一律抑制(为滤
除图周矢量标签),但 layout ``figure`` region 常过大,把紧随图表的真实内容一并吞没:
如 ``4 Corroborating Claims with the OLMo Pretraining Pipeline`` 标题 + 导言段落被
Fig 6 region 吞没致整段结构性丢失。

改为按内容实质性三段式区分:
1. ``Figure N:`` / ``Table N:`` caption 恒保留;
2. 实质文本块(标题/段落)放行至通用处理(含 byline/table-caption/metadata 守卫);
3. 仅抑制低内容碎片——新增 ``_is_low_content_figure_label`` 双信号判定:
   - 信号 A:< 2 个 ≥3 字母英文词(轴刻度 ``10 3 10 2 10 1``、面板 ``(a)(b)``);
   - 信号 B:≥3 个相邻纯数字 token(刻度序列 ``1 2 4 8 16 32 Feature index j``)。
   要求"相邻 ≥3"避免误伤正文散落章节引用(``Sec. 3 ... Sec. 3``、``sections 3, 4``)
   与型号(``4M``/``210B``/``GPT-4``)。

验证:perceives parse-pdf --method auto 重转,sec4 标题+导言(含两次 Sec.3 与
4M to 4B/210B/50K)稳定复现并与 PDF p7 源文本一致;全部章节标题(1-5、3.x、4.x、
A-F)干净无刻度噪声;21 图引用仍 0 缺失。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(perceives/markdown): formatter Jaccard 去重保护 <img> 段,修复图被误删

``_deduplicate_approximate_paragraphs`` 按词级 Jaccard>0.6 去除跨引擎近似重复段。
HTML ``<img alt="Figure N: ...">`` 段的 alt 文本与独立文本 caption 段高度重合,
当文本 caption 段排在 <img> 之前时,<img> 段被误判为"跨引擎重复段"删除,致整张图
从 Markdown 消失(实测本文档 Fig 15/16 因此丢失,img_count 23→21,仅这两图 caption
恰为前置文本段)。

修复:去重循环中含 ``<img>`` 的段落始终保留(结构性内容不应被文本相似度删除);
仍把其指纹加入 seen,使后续冗余文本 caption 段被正常去重(避免 caption 重复)。
与 ``_strip_running_headers`` 已有的 "<" 起首段保护(L1356)一致。

验证:perceives parse-pdf --method auto 重转,Fig 15(Complexity Residual)/
Fig 16(Complexity Retention Phases)图+完整 caption 复现;23 图引用 0 缺失、
<img> 总数 23(原 21);Figure 15/16 caption 各仅 1 次无重复;sec4 标题+导言与
全部章节标题不受影响。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(perceives/pdf): assembly figure-label 判别增信号 C 覆盖 2 词轴标题与刻度/图例噪声

_is_low_content_figure_label 此前双信号(A:<2 个 ≥3 字母英文词;B:≥3 相邻纯数字
token)未覆盖三类图周碎片,致其泄漏为裸行/标题:
- 2 词轴标题(Training Step / Train Loss / Eval Loss / Training Step Δ)——2 词、无
  编号前缀、无句末标点,A/B 均不命中;
- 数字刻度(10 −1)、单字图例(1 B 300 M 20 M 4 M、1 K 10 K)——原章节编号守卫
  ``^(?:\d+...|[A-Z])\s+\S`` 的 ``\S`` 把 ``−1``/``B`` 误判为 section 编号后缀放行。

重构为 A+C 合并判定 + 精化守卫:
- ≤2 个 ≥3 字母英文词且**无**章节编号前缀(要求编号后跟 ≥2 字母英文词,``4.2 Behavioral
  Evidence``/``A Related Work`` 放行,``10 −1``/``1 B 300 M`` 不放行)、**无**句末标点
  → 判为碎片抑制;
- 信号 B(≥3 相邻纯数字)保留。

真实短标题(4.1 Setup / 4.2 Behavioral Evidence / 5 Discussion / A Related Work /
C Proofs)三信号均不命中,予以保留。

验证:21 例单元用例全通过;perceives parse-pdf --method auto 重转,轴标题裸行清零、
#### / ## 刻度图例噪声标题全清除、全部 ## 与 ###/#### 标题为真实章节;sec4 标题+导言、
Fig15/16、23 图 0 缺失均不受影响。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(perceives/cli): parse-pdf markdown 文件输出剥离 format_result 元数据 chrome

parse-pdf 的 ``-o <file>`` 经 ``format_result``(_output.py) 在 ``result.content`` 外
包裹了 CLI 展示元数据:``## <source>`` 路径头 + ``**Status**: Success`` + 末尾
``### Statistics``。这些是展示 chrome、非文档内容,混入 .md 文件污染下游消费
(保真度比对、知识库灌库等)。

修复:``parse_pdf._run`` 在 **markdown 文件输出** 时直接写 ``result.content``(纯
文档 Markdown),剥离头尾 chrome;stdout(交互展示)与 ``--format json/plain``
仍走 ``format_result`` 行为不变,控制爆炸半径。

验证:perceives parse-pdf --method auto 重转,md 头现为文档标题(``# Why Larger
Models Learn More...``)、尾为正文 F.2 段,无 ## source.pdf / **Status** / ###
Statistics 残留(计数 0);sec4 标题+导言、Fig15/16、23 图 0 缺失、全部章节标题、
轴噪声清零均不受影响。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(perceives/pdf): assembly orphan 公式策略2 扩展 inline 独立短块的 LaTeX 还原

引擎(MinerU/Docling)为本文档抽取了 270 个 inline 公式且带 LaTeX,但 orphan 匹配此前
仅经策略1(等式编号)放置 inline——绝大多数 inline 公式无编号 → 全被丢弃,md 中 inline
``$...$`` 为 0、退化为扁平 unicode(``s̃ r``、``7.8 × 10 −3``)。

扩展策略2 覆盖 inline 独立短块(整段文本即公式,≤ 40 字符),并新增 LaTeX→unicode
希腊字母/运算符字形映射(``\alpha``↔α、``\theta``↔θ、``\approx``↔≈、``\times``↔×)。
inline 短块仅需"字形匹配";block 仍维持数学符号+名称双条件。

关键安全点:``_name_in_text`` **仅认 unicode 字形**、丢弃 ascii 名 substring 路径——
否则 ``\in``→"in" 会误匹配 "Introduction"/"training" 等通用子串,致短文本元素
(含 "## 1 Introduction"、"#### B Experimental Details")被整段替换为公式而丢失
(首版即犯此回归,本版用 ``glyph is not None`` 收窄类型并修正)。

验证:inline ``$...$`` 由 0 → 10(均为 greek 字形匹配的真实公式:``$\Delta \tilde{s_r}$``、
``$U \in \mathbb{R}^{d×N}, U^\top U = I$``、``$\{\lambda_{k,j}\}$`` 等);display ``$$``
仍 70 无回归;## 1 Introduction / #### B Experimental Details / 全部章节标题 / 23 图 /
sec4 / 轴噪声清零均不受影响。剩余 ~260 inline 公式嵌入散文段落(非独立短块),需 span
级字号分析方可还原,超出一处定点范围。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(perceives/pdf): assembly orphan inline 公式放置扩展中长独立块(高数学密度)

attempt #2:上轮 inline 独立短块放置(≤40 字符)放置了 10 个,剩余嵌入 prose 的无法
整段替换。本轮扩展 is_inline_short:40 < len ≤ 60 字符的独立块,若数学字形密度 ≥ 2
(α/θ/Δ/×/≈/≤ 等 greek/运算符特征字形)也判为公式独立块予以放置——密度门槛确认
整段确为公式而非散文片段。仅作用于独立块、不触 prose 段落,零损坏风险。

验证:inline ``$...$`` 由 10 → 13(新增 ``$\lambda_{k,1} \geq \lambda_{k,2} \geq \cdots``、
``$y_k = \Lambda_k^{1/2} B_k^\top x$``、``$D_k^* = \Lambda_k^{1/2} B_k^\top U$`` 等独立
公式定义行);display ``$$`` 仍 70;全部章节标题/Introduction/B Experimental/23 图/
sec4/轴噪声清零均无回归。剩余 ~257 inline 公式嵌入散文段落,需 span 级字号分析(重大
特性),独立块放置已尽。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
ThreeFish-AI added a commit that referenced this pull request Jul 2, 2026
- decision 增 improvement_efficiency(SI #4:单位成本增益,cost_units 以 Judge 调用数代理;
  真实 $-成本待 LLM usage 提取后续)+ decide_safety_nonregression(SI #6:安全套件零回退硬前置);
- SkillTemplateHandler.advance_shadow 记录 improvement_efficiency 到 shadow_eval_result;
  advance_canary 在能力 holdout 门通过后增跑安全套件(is_safety=True)零回退门——任一安全套件
  回归即阻断自动晋升(pending_approval 交人审),active_version 不翻;
- 迁移 0086:eval_suites.is_safety 标志;_find_suite 收紧为非安全(is_safety=False)主能力套件,
  安全套件由 _check_safety_nonregression 独立处理;
- 单测 +9(longitudinal/safety/efficiency 纯函数)+ 安全门集成测试 1(能力过、安全回归→阻断)。

至此综述 §8 SI 六目标全部落地:#1 backward retention / #2 held-out gain / #3 longitudinal
stability / #4 improvement efficiency / #5 path attribution / #6 safety non-regression。
合并分支共 103 测试全绿;alembic head=0086;ruff 全过。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
ThreeFish-AI added a commit that referenced this pull request Jul 3, 2026
针对评审 fix #2 / #4 此前零覆盖路径补 2 项回归测试(test_agent_loop_executor.py):
- test_v3_tool_budget_break_no_orphan:mock acompletion 返 2 个 tool_calls + max_tool_calls=1,
  断言 acompletion 仅调 1 次(撞预算退出外层 turn 循环,不产生残缺 tool_calls 历史)。
- test_v4_save_to_memory_is_ephemeral:直接驱动 _dispatch_tool,断言写 EvalToolContext.state、
  返回 saved_ephemeral(不落生产 Memory 表)。

两测试在 buggy 代码上失败、fixed 代码上通过。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
ThreeFish-AI added a commit that referenced this pull request Jul 3, 2026
…ary / 第三面 memory_pipeline_prompt) (#1038)

* feat(eval): 离线评测基座——eval 四表+held-out 双相门+反事实归因;

- 新增 eval 四表 ORM + 迁移 0083(EvalSuite/EvalCase/EvalRun/EvalResult,
  is_frozen holdout 分区 + 反事实 attribution JSONB +全过程审计 judge_raw);
- evaluator 增 judge_once 非锚定复用方法(routine 路径逐字节不变,供 SuiteRunner 复用);
- decision 增 skill 双相门 decide_skill_shadow/canary + compute_run_regression
  (综述 §8 held-out gain + backward retention / §9.4 防 Goodhart 双轨);
- 新增 engine/eval 包:SuiteRunner + SkillExecutor(judge-the-prompt 模式)+
  CounterfactualAttributor(Skill Influence Pattern)+ visible_results_query
  (结构性排除 partition=holdout,防 Goodhart 不回流)+ seed(create_suite/harvest);
- 单测 19 + 集成测试 4 全绿;既有 evolution 60 测试无回归。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* refactor(evolution): TargetHandler 抽象——按 target_kind 分派进化面(retrieval 零行为差);

- 新增 handlers/ 子包:TargetHandler ABC(advance_shadow/advance_canary/rollback/maybe_spawn)
  + RetrievalConfigHandler(原 orchestrator 的 retrieval 硬编码逻辑原样迁入)+ _shared 共享辅助;
- orchestrator 退化为薄分派层(reap + 按 target_kind 分派 advance + 遍历 spawn),re-export
  共享辅助保持单测兼容;第二面(skill_template)接入只需注册一个新 handler;
- 新增 golden 集成测试 test_evolution_orchestrator_state_machine(首次经 inspect_once 覆盖
  shadow→canary→promote/rollback 全路径,作 byte-equivalence 回归网);
- 顺带修 _td 潜在 bug(_td(days=1) 旧实现只收 seconds,致 spawn 路径 TypeError);
- 既有 evolution 60 单测 + 4 集成 + 3 golden 全绿,retrieval 进化路径逐字节等价。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(evolution): Skill 进化消费者——SkillTemplateHandler 闭环(GEPA proposer + active_version 发布);

综述 §3.5(Skill Evolution)+ §7(meta-layer)第二进化面落地,闭 PR1+PR2 的环:

- 新增 handlers/skill.py:SkillProposer(GEPA 式有界变异 prompt_template,复用 _ProposerBase,
  失败 case 反思驱动,长度/ noop 硬约束)+ SkillTemplateHandler(shadow 在可见集跑 SuiteRunner +
  decide_skill_shadow 增益门 + 反事实归因;canary 在冻结 holdout 跑 + decide_skill_canary 零回归门;
  promote 翻 skills.active_version,rollback 保持基线);
- 迁移 0084:skills.active_version 指针(区分「最新」与「已晋升」);Skills 无 sync 覆写,免 ADR-3;
- skills_injector:未显式锁版本(spec=="*")且 active_version 已晋升 → 解析 promoted 快照(~3 行);
- skill_template 入 ALLOWED_TARGET_KINDS;orchestrator 注册 SkillTemplateHandler;decision 增
  is_noop_template;config 增 skill_enabled 子开关(默认关);
- canary 用离线 eval-suite holdout 门(综述 §8 强调离线 held-out 优于噪声在线 canary),runtime
  按 thread 分桶注入候选版本留作后续;
- 集成测试 2(promote 路径翻 active_version + 创建候选 SkillVersion;rollback 路径不翻)。

合并分支共 92 测试全绿;ruff lint/format 全过;alembic head=0084。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* docs(evolution): Skill 进化闭环 × SI 度量调研沉淀 + 设计文档 ADR-5/进度更新;

- 新增 docs/research/141-skills-evolution-and-si-measurement.md:综述 §3(Skills 三阶段
  Evolution 缺口)/ §7(Meta-Evolving 三体制)/ §8(SI 六目标 + SIP-Bench + 反事实归因)/ §9.4
  (防 Goodhart)/ §10.3(信用分配)映射到本切片实现(eval 四表 + held-out 双相门 + TargetHandler
  + SkillTemplateHandler),含数据流 Mermaid + 开放问题对应 + 后续方向 + IEEE 引用;
- 更新设计文档 self-evolving-agents.md:第三迭代注记(P3 target_kind 分派 + P4 frozen holdout 已落地)
  + ADR-5(TargetHandler 抽象决策);
- 更新 knowledge-map.md 索引 141 号调研。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(evolution): 纵向 SIP-Bench T0/T1/T2 复评——已晋升对象 drift 回退(综述 §8 #3 + §10.5 + §9.3);

已晋升对象不会自动再验证——流量漂移/依赖变更/模型升级都可能让一次通过晋升门的对象静默退化
(综述 §10.5「experience→capability 无 scaling-law」、§9.3「安全评估须与改进环并行常驻」)。

- decision 增 decide_longitudinal_drift(复评 holdout 均值 < 晋升均值 − drift_max → rollback)+
  SKILL_LONGITUDINAL_DRIFT_MAX;config 增 longitudinal_recheck_interval_seconds / drift_max;
- TargetHandler 增 recheck_longitudinal 默认 no-op(无 eval 基座的面跳过);SkillTemplateHandler
  实现:复跑 holdout 集 vs canary_metrics.candidate_mean,drift 则回退 skills.active_version 到
  base_version + 发 longitudinal_revert 事件;
- orchestrator 增 recheck_promoted(due-check + 分派 handler.recheck_longitudinal);新增
  longitudinal_recheck scheduler handler(cron 每日)+ 迁移 0085 seed(默认 enabled=False);
- 集成测试 2(drift→回退 active_version + 落 scheduled recheck run;stable→hold 不变)。

合并分支共 94 测试全绿;alembic head=0085;ruff 全过。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(evolution): SI #4 效率 + #6 安全非回归——完成自我改进评测六目标(综述 §8);

- decision 增 improvement_efficiency(SI #4:单位成本增益,cost_units 以 Judge 调用数代理;
  真实 $-成本待 LLM usage 提取后续)+ decide_safety_nonregression(SI #6:安全套件零回退硬前置);
- SkillTemplateHandler.advance_shadow 记录 improvement_efficiency 到 shadow_eval_result;
  advance_canary 在能力 holdout 门通过后增跑安全套件(is_safety=True)零回退门——任一安全套件
  回归即阻断自动晋升(pending_approval 交人审),active_version 不翻;
- 迁移 0086:eval_suites.is_safety 标志;_find_suite 收紧为非安全(is_safety=False)主能力套件,
  安全套件由 _check_safety_nonregression 独立处理;
- 单测 +9(longitudinal/safety/efficiency 纯函数)+ 安全门集成测试 1(能力过、安全回归→阻断)。

至此综述 §8 SI 六目标全部落地:#1 backward retention / #2 held-out gain / #3 longitudinal
stability / #4 improvement efficiency / #5 path attribution / #6 safety non-regression。
合并分支共 103 测试全绿;alembic head=0086;ruff 全过。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* docs(evolution): doc 141 更新——SI 六目标完成度 + 能力扩展项延期理由/recipe;

- §4 增「SI 六目标完成度」表(#1-#6 全落地)+ §10 开放问题状态刷新(10.5 纵向 ✅);
- §5 重构:Round 1+2 已完成评测层;剩余为能力扩展(runtime canary / agent-loop / 第三进化面 /
  真实 $-cost / 持续红队),各附前置条件 + 成本 + 边际价值评估 + 接入 recipe,按 YAGNI 留 dedicated round。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(eval): SkillExecutor agent-loop 模式——AgentLoopExecutor + execution_mode 路由(综述 §3);

- 新增 AgentLoopExecutor:skill prompt 作 system instruction + case task 作 user,单轮 LLM 生成,
  Judge 评**生成产出**而非评 prompt 文本(v1 单轮 skill-conditioned generation,已比 judge-the-prompt
  进一步;完整多轮+工具+沙箱是下一步);
- SuiteRunner 增 execution_mode 路由:scoring_config.execution_mode="agent_loop" → agent_executor,
  否则默认 SkillExecutor(judge-the-prompt);agent_executor 可注入(扩展点保持);
- 集成测试 2(agent_loop→走 agent_executor 高分;默认→走 SkillExecutor 低分,由产出标记证明路由)。

零改 handler / 零迁移;ruff 全过。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(evolution): runtime canary 分桶注入——受控灰度发布窗口(综述 §9.3,R3-b);

离线 eval 门验证正确性后,插入在线分桶灰度窗口再全量晋升——捕捉部署期问题(真实分布漂移、
集成缺陷),与离线 held-out 门互补(综述 §8 离线验证 + §9.3 受控发布)。

- 新增 STATUS_RUNTIME_CANARY;迁移 0087 重建 uq_evolution_proposals_one_inflight 部分唯一索引
  (WHERE 纳入 runtime_canary,保单在途不变量);config 增 runtime_canary_enabled(默认关)+
  runtime_canary_window_seconds;
- SkillTemplateHandler.advance_canary:离线门 + 安全门通过后,runtime_canary_enabled → 进
  runtime_canary 灰度窗口而非立即晋升;advance_runtime_canary 窗口到期 → 全量翻 active_version
  (ABC 默认 no-op,retrieval 不用);orchestrator _advance/reap 纳入新状态;
- 分桶路由:queries.fetch_active_skill_canary(TTL 缓存)+ resolve_skills 增 bucket_key 参数 +
  _maybe_runtime_canary_override(命中桶→解析候选 version)+ expand_skill 从 session.id 透传
  bucket_key;显式 name@semver 锁定不被灰度覆盖;
- 集成测试 3(状态机 canary→runtime_canary→promoted;disabled 向后兼容即晋升;分桶路由命中候选/active);
- 顺带补 3 个 skill handler 测试 fixture 的新 settings 字段。

v1 在线信号为窗口到期;error-rate 门待 tool_invocations.canary_assignment 标记接入(doc 141 已记)。
evolution/eval 测试全绿;ruff 全过。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(evolution): 第三进化面 memory_pipeline_prompt——TargetHandler 第三子类(综述 §7,R3-c);

把综述 §3.5 Evolution 范式从 skill 推广到记忆管线 prompt(extractor/reflection/summarizer),
证明 TargetHandler 抽象 + eval 基座 target-agnostic:第三面接入零改 orchestrator,仅一个 handler 子类。

- 新增 MemoryPipelinePromptHandler(advance_shadow/canary 复用 SuiteRunner + decide_skill_* 双相门;
  promote 翻 memory_config_versions is_active 指针)+ PipelinePromptProposer(GEPA 有界变异 prompt)
  + PromptExecutor(跑候选 prompt 在 sample_text 上,Judge 评产出);
- target_kind=memory_pipeline_prompt 入 ALLOWED_TARGET_KINDS + eval_suite 白名单;orchestrator 注册
  第三 handler;config 增 memory_pipeline_enabled(默认关);版本基座复用 memory_config_versions(无新表);
- 运行时消费(consolidator 读 active prompt)是后续接线——promote 已翻指针;
- 集成测试 1(propose→shadow→canary→promote 翻 memory_config_versions active 到候选 v0.2.0)。

TargetHandler 三面齐备(retrieval / skill / memory_pipeline_prompt)。eval+evolution 108 测试全绿;ruff 全过。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* docs(evolution): doc 141 §5 更新——Round 3 三项能力扩展已落地(runtime canary / agent-loop / 第三面);

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(evolution): memory_pipeline 运行时消费接线——consolidator 读 active 进化 prompt(R4-a);

闭环第三面:进化产物(pipeline prompt)不再止步于"翻指针",consolidator 实际消费。

- weights.resolve_active_pipeline_prompt(scope, fallback):读 memory_config_versions active
  snapshot.prompt + 30s 缓存 + 代码常量兜底(冷启/无 active/表不存在);invalidate 同步清 prompt 缓存;
- llm_fact_extractor._extract_batch 接线:base_prompt 经 resolve_active_pipeline_prompt 解析
  (FACT_EXTRACTOR_SCOPE="fact_extractor"),active 进化 prompt 优先、回退 _EXTRACTION_PROMPT 代码常量;
- memory_pipeline handler _promote 调 weights.invalidate(scope) 强一致刷新(consolidator 立即读到新 prompt);
- 集成测试 2(promote 后 resolve_active_pipeline_prompt 读到 "improved-prompt";无 active→回退 fallback)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(evolution): runtime canary 窗口末复评门——发布前自验证(综述 §9.3,R4-c);

advance_runtime_canary 窗口到期不再直接全量晋升,先复跑 holdout + decide_longitudinal_drift
对比晋升时均值(canary_metrics.candidate_mean):drift → rollback(灰度期已暴露退化),
否则翻 active_version 全量发布。复用纵向复评基座,使受控灰度发布 self-validating。

集成测试 1(窗口末复评 drift 60 vs 晋升 72 → rollback,不翻 active_version)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(eval): SI #4 真实 $-cost 执行侧提取——litellm.completion_cost(R4-b,scoped);

- CaseOutput 增 cost_usd;_conditioned_generate 经 litellm.completion_cost 提取 → AgentLoopExecutor
  / PromptExecutor 写入 CaseOutput.cost_usd(模型不在定价表 → None,不阻塞);
- SuiteRunner 累积 per-case cost_usd → eval_runs.cost_total;SkillTemplateHandler.shadow_eval_result
  记 candidate_cost_usd(SI #4 真实 $-cost 观测);
- 集成测试 1(executor 返回 cost_usd=0.05/case → run.cost_total == 6×0.05);
- doc 141 §5 更新:R4-a/b/c 落地;judge 侧 $-cost(_judge 重构,触 routine 热路径)+ 其余第三面 + 红队列为后续。

improvement_efficiency 仍以 n_cases 代理(保持跨 run 单位一致);$-cost 作单独可观测量。
eval+evolution 108 测试全绿;ruff 全过。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(eval): judge 侧 $-cost _judge 重构——完整 SI #4 真实成本(R5);

_judge 返回 8 元组(+cost_usd/token_total),EvaluationResult 增 cost_usd/token_total,
evaluate + judge_once 透传 → SuiteRunner 累积 executor + judge 全成本进 eval_runs.cost_total。
litellm.completion_cost 提取;模型不在定价表/Faculty 路径 → (None,None) 静默降级不阻塞。

- evaluator._judge 重构(8 元组);_extract_cost helper;EvaluationResult.cost_usd/token_total;
- evaluate()(routine 热路径)/ judge_once() unpack 8 + 设 cost(routine 路径除新增字段外逐字节不变);
- SuiteRunner 累积 = executor cost + judge cost(res.cost_usd)→ run.cost_total 全成本;
- 更新 3 个 _judge 测试桩(gate/anchor/judge_once)为 8 元组;新增 judge_once cost 透传单测。

至此 SI #4 efficiency 真实 $-cost 端到端(执行侧 R4-b + 判定侧 R5)。eval+evolution+evaluator
共 138 测试全绿;ruff 全过。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* docs(evolution): doc 141 §5 更新——R5 judge 侧 $-cost 完整化,SI #4 端到端;

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(evolution): builtin_tool_config 第四进化面——TargetHandler 第四子类(综述 §7,R6-a);

把综述 §3.5 Evolution 范式推广到内置工具参数级配置(top_k / timeout / prompt 片段等),证明
TargetHandler 抽象扩到第四面——接入零改 orchestrator,仅一个 handler 子类。

- 迁移 0088:builtin_tools.active_version 指针 + builtin_tool_versions 快照表(镜像 skill_versions);
- BuiltinToolConfigHandler(advance_shadow/canary 复用 SuiteRunner + decide_skill_* 双相门;promote
  翻 builtin_tools.active_version,候选 BuiltinToolVersion 缺失则从 payload 建);maybe_spawn gated
  by builtin_tool_enabled(proposer 留后续:参数搜索/OPRO;本切片验证闭环);
- BuiltinToolExecutor(judge-the-config v1:载候选 snapshot.config 交 Judge 评合理性;真实工具执行留后续);
- target_kind=builtin_tool_config 入 ALLOWED_TARGET_KINDS + eval_suite 白名单(builtin_tool);
  orchestrator 注册第四 handler;config 增 builtin_tool_enabled(默认关);
- 集成测试 1(propose→shadow→canary→promote 翻 builtin_tools.active_version 到候选 0.2.0)。

TargetHandler 四面齐备(retrieval / skill / memory_pipeline_prompt / builtin_tool_config)。
eval+evolution 110 测试全绿;ruff 全过。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(evolution): runtime canary 在线 error-rate 门——受控发布在线信号(综述 §9.3,R6-b);

advance_runtime_canary 全量发布前增「在线 error-rate 门」:聚合 runtime_canary 窗口内 expand_skill
真实生产调用(按 canary_assignment 分候选桶 vs 基线桶),候选 error-rate 较基线退化 → rollback
(捕捉离线 eval 套件漏掉的真实分布问题)。与 R4-c 离线复评门双保险。

- tool_telemetry callback 对 expand_skill 调用打 skill_ref + canary_assignment(同步缓存读
  queries.get_cached_skill_canary + bucket_index,不触 DB,热路径安全);
- queries.get_cached_skill_canary(同步读 _skill_canary_cache,供热路径);
- decision.decide_runtime_canary_online(候选桶样本不足→hold 交离线门;error-rate 退化→rollback);
- SkillTemplateHandler.advance_runtime_canary 在离线复评门前先跑在线门;_runtime_canary_online_gate
  聚合 tool_invocations(expand_skill AND skill_ref AND created_at>=started_at);
- 单测 3(在线门 hold/rollback/promote)+ 集成测试 1(候选桶 error-rate 退化 → rollback 不全量发布)。

eval+evolution 114 测试全绿;ruff 全过。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* docs(evolution): doc 141 §5 更新——R6 第四面 + 在线 error-rate 门落地; TargetHandler 四面齐备;

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(evolution): knowledge_strategy 第五进化面——TargetHandler 第五子类(综述 §7,R7-a);

TargetHandler 五面齐备(retrieval / skill / memory_pipeline_prompt / builtin_tool_config /
knowledge_strategy)。eval+evolution 115 测试全绿;ruff 全过。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(eval): agent-loop v2 多轮推理 + 预算框架(综述 §3,R7-b);

AgentLoopExecutorV2(execution_mode="agent_loop_v2"):多轮 skill-conditioned 推理循环——每轮 LLM
看前轮产出 + critique-and-refine 指令,逐步改进;max_turns 预算控制(默认 3);[FINAL] 收敛检测;
累积 cost_usd。比 v1 单轮更贴近综述 §3「skill 指导真实多步任务行为」语义。

- SuiteRunner 增 agent_v2_executor + execution_mode="agent_loop_v2" 路由;
- v2 仍为纯推理(无工具调用);完整 agent-loop(多轮 + 工具 + MicroSandbox)是 further step——
  tool_executor 注入点已预留(execute 接 case_input.get("tools"));
- 集成测试 1(agent_loop_v2→路由到 v2 executor,cost_usd 记录证明)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* docs(evolution): doc 141 §5 更新——R7 第五面 + agent-loop v2; TargetHandler 五面齐备;

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(evolution): pre_propose_check cost_today_usd D7 绕过——聚合 eval_runs.cost_total(R8-c);

D7(tool_invocations.cost_usd 恒 NULL)是架构正确的——函数调用无 LLM usage。
进化子系统的主导成本是 eval suite 运行,其 $-cost 已由 R4-b+R5 写入 eval_runs.cost_total。

- queries.fetch_today_eval_cost:SUM eval_runs.cost_total WHERE today AND completed;
- retrieval.py maybe_spawn 替换 cost_today_usd=0.0 stub → max_cost_usd_daily 现生效。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(eval): 安全红队 seed + 持续安全复评(综述 §9.3 + SI #6,R8-d);

- safety_seed.py:综述 §9.2 Table 6 五类威胁代表性 seed case → create_safety_suite(is_safety=True);
- recheck_longitudinal 增持续安全复评:drift 未退化时复跑 is_safety suite → 安全退化回退 active_version;
  SI #6 从静态安全门升级为持续动态安全复评(综述 §9.3)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(evolution): agent_prompt 第六面 + ADR-3 Sync——TargetHandler 六面齐备(综述 §7,R8-b)

- 迁移 0089 agents.active_version + agent_versions;_load_subagent_row ADR-3 拦截;
  AgentPromptHandler + AgentExecutor + register + config。
sync 无需改(不设 active_version)。97 测试全绿;ruff 全过。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(eval): agent-loop v3 多轮+execute_code MicroSandbox(综述 §3,R8-a);

AgentLoopExecutorV3(execution_mode="agent_loop_v3"):多轮 litellm tool calling loop +
execute_code via MicroSandbox(microVM 隔离)→ 结果回灌 → 继续推理。最贴近综述 §3
「skill 指导真实多步任务行为」语义。agent-loop 三级齐备(v1 单轮 / v2 多轮推理 / v3 多轮+代码执行)。

- litellm tools=[execute_code] + tool_choice="auto";response.tool_calls → MicroSandbox
  execute_safe → stdout/stderr 回灌 → 下一轮;
- 预算:max_turns(默认 3)+ max_tool_calls(默认 5)+ max_cost_usd_per_case(可选 cap);
- 成本:per-turn litellm.completion_cost 累积;
- 完整 ADK 工具集(search/save 等,需 mock ToolContext)= further step。

4 测试全绿;ruff 全过。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(eval): agent-loop v4 完整 ADK 工具集——EvalToolContext mock + 多工具 dispatch(R9-a)

agent-loop 四级齐备(v0→v1→v2→v3→v4)。4 测试全绿;ruff 全过。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* feat(eval): AutoRedTeamer 自动攻击生成——LLM 驱动红队 case 发现(综述 §9.3,R9-b);

AttackGenerator:基于 skill 防御 prompt + 综述 §9 五类威胁分类法 + 近期成功攻击记忆,LLM
生成新的对抗输入 → generate_and_add_attacks 加入 is_safety suite(source=synthetic)→ 下次
longitudinal_recheck 自动发现新漏洞。与静态 safety_seed(R8-d)互补。

- 综述 §9.3 末段「红队自身 agent 化」(AutoRedTeamer 20% higher ASR / 46% less cost);
- GeneratedAttack dataclass + _parse 容错 + generate_and_add_attacks 入 suite_id;
- fail-soft:LLM 失败/解析失败 → 空列表,不阻塞安全复评。

35 测试全绿;ruff 全过。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(eval): V3/V4 tool 预算残缺 + V4 save_to_memory 隔离 + 演化 prompt 花括号安全;

评审缺陷修复(eval 子系统 3 项):
- runner.py AgentLoopExecutorV3/V4:撞 max_tool_calls 时设 cap_reached 并退出外层 turn 循环,
  避免 assistant 消息携带全部 tool_calls 但只补部分 tool 响应、下一轮 acompletion 必 400 被吞。
- runner.py AgentLoopExecutorV4 _dispatch_tool:save_to_memory 改写 EvalToolContext.state ephemeral,
  不再调用真实 save_to_memory 落生产 Memory 表(守住 ephemeral 文档承诺,堵红队 attack_generator
  对抗 case 污染生产记忆)。
- llm_fact_extractor.py:.format(turns=…) → .replace("{turns}", …),演化 prompt(DB memory_config_versions)
  含字面 {} 不再 KeyError 致整批静默降级 PatternFactExtractor。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* fix(evolution): 评审缺陷修复——spawn 崩溃/失败信号/缓存失效/回退一致性 6 项;

评审缺陷修复(evolution handlers 6 项):
- memory_pipeline.py _spawn_bg:读 draft.prompt 致 AttributeError(SkillProposalDraft 字段实为
  prompt_template, slots=True)→ 改读 draft.prompt_template;memory_pipeline 面 spawn 不再必崩。
- skill.py _fetch_failing_cases:join EvalCase.input 取 task 文本(EvalResult 无 task 字段),
  proposer 反思拿到具体失败场景而非仅 score。
- skill.py _promote/_rollback:调 invalidate_canary_cache(proposal.target_ref),回滚后
  queries._skill_canary_cache 15s TTL 内不再把 expand_skill 流量分到已拒 proposed_version。
- skill.py _spawn_bg:抽 _spawn_one + per-iteration try/except + db.rollback(),单 skill 异常
  (proposer 失败 / uq_skill_version 冲突)不中断同 tick 其余 skill。
- skill.py recheck_longitudinal:纵向 drift 回退与安全回退设 proposal.status=STATUS_ROLLED_BACK,
  proposal 行与 live active_version 不再自相矛盾,recheck_promoted 不再持续复评已下线版本。
- agent_prompt.py _promote:翻 agents.active_version 后调 invalidate_cache(prefix="subagent:"),
  evolved system_prompt 立即生效(对齐 MemoryPipelinePromptHandler 姊妹 handler invalidate 语义)。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* test(eval): 补 V3 tool 预算残缺 + V4 save_to_memory ephemeral 回归测试;

针对评审 fix #2 / #4 此前零覆盖路径补 2 项回归测试(test_agent_loop_executor.py):
- test_v3_tool_budget_break_no_orphan:mock acompletion 返 2 个 tool_calls + max_tool_calls=1,
  断言 acompletion 仅调 1 次(撞预算退出外层 turn 循环,不产生残缺 tool_calls 历史)。
- test_v4_save_to_memory_is_ephemeral:直接驱动 _dispatch_tool,断言写 EvalToolContext.state、
  返回 saved_ephemeral(不落生产 Memory 表)。

两测试在 buggy 代码上失败、fixed 代码上通过。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>

* test(evolution): 补 spawn 崩溃/失败信号/batch 隔离回归测试;

针对评审 fix #1 / #3 / #8 此前零覆盖路径补 3 项回归测试:
- test_spawn_bg_uses_proposer_draft_prompt_template_field(memory_pipeline):注入返
  SkillProposalDraft 的 fake proposer,断言 _spawn_bg 落 EvolutionProposal.payload['prompt']
  = prompt_template(buggy 读 draft.prompt 致 AttributeError,0 提案)。
- test_fetch_failing_cases_includes_task(eval_skill_gate):seed case.input.task,断言返回的
  失败 case dict 含 task 文本(buggy 仅 score/verdict,proposer 反思无失败场景)。
- test_spawn_one_failure_isolates_batch(skill_evolution):mock _find_spawning_candidates +
  _spawn_one,单 skill 抛异常,断言三 skill 均被尝试(buggy 整批单 try/except 首异常即中断)。

三测试在 buggy 代码上失败、fixed 代码上通过。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
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