Skip to content

fix(graceful-shutdown): 修复 SIGINT 后服务无法关停与调度任务卡死 - #592

Merged
ThreeFish-AI merged 2 commits into
feature/1.x.xfrom
ThreeFish-AI/backend-graceful-shutdown
May 20, 2026
Merged

fix(graceful-shutdown): 修复 SIGINT 后服务无法关停与调度任务卡死#592
ThreeFish-AI merged 2 commits into
feature/1.x.xfrom
ThreeFish-AI/backend-graceful-shutdown

Conversation

@ThreeFish-AI

Copy link
Copy Markdown
Owner

背景

  • 本次变更要解决的问题:SIGINT 后 uvicorn 卡在 "Waiting for connections to close. (CTRL+C to force quit)";title_inspector 等调度任务在 Ctrl+C 之后仍然继续 tick(日志显示 1 分钟后再次出现 title_inspector_tick_started),用户被迫多次按 ^C 才能强制退出;进程残留导致 DB 连接池/PG advisory lock/调度状态半提交等一致性风险。
  • 关联上下文/Issue/文档:Plan 文件 /Users/cm.huang/.claude/plans/system-instruction-you-are-working-encapsulated-ripple.md

核心变更(双轴正交修复)

① 信号传导轴(决定性根因)

  • P0-1 cli.py:放弃 subprocess.call("python -m google.adk.cli web …"),改为同进程通过 click 编程接口调起 ADK CLI;在 import 前 monkey-patch uvicorn.Config.__init__ 注入默认 timeout_graceful_shutdown=25sNEGENTROPY_SHUTDOWN_TIMEOUT_SECONDS 可调,显式传值不被覆盖)。修复 uvicorn 原默认 None(无限等待)导致 lifespan.shutdown 永不触发的核心问题。
  • P0-2 engine/bootstrap.py:新增模块级 _negentropy_lifespan 取代旧的 @app.on_event("startup")/("shutdown") 钩子;新增 _compose_with_negentropy_lifespan 把 ADK 已传的 banner lifespan 与业务 lifespan 嵌套合并(关键修复:ADK cli_tools_click.py:1679 已显式传 lifespan=_lifespan,旧"仅当 None 才注入"策略会被旁路);通过 patch AdkWebServer.get_fast_api_app 注入到 ADK internal_lifespan 链路中。

② 任务收敛轴(一致性隐患)

  • P0-3 engine/schedulers/async_scheduler.py & registry.py:新增 aclose(timeout) 异步收敛 API(先 _running=Falsecancel + await 主心跳 → cancel + gather inflight tasks → 超时强制 cancel),_run_loop 显式 try/except CancelledError break;ExecutionBus.close_all_subscribers() 投递 __shutdown__ 哨兵让 SSE 立即收尾;保留旧同步 stop() 兼容入口。
  • P0-4 engine/schedulers/registry.pydispatchawait handler(task) 包入 asyncio.timeout,按 payload.timeout_seconds > NEGENTROPY_HANDLER_DEFAULT_TIMEOUT_SECONDS(60) 优先级解析;超时记 status="timeout" 并累加 consecutive_failures 进入既有退避路径;CancelledErrorcancelled 但不计失败;抽出 _finalize_execution 统一回写 in-flight / cancelled / timeout 三态,避免 Dashboard 行卡死在 status='running'
  • P0-5_heartbeat_tick 改为 asyncio.gather 并发派发(DB lease 已正交保证幂等),慢 handler 不阻塞同 tick 内其它 task;NEGENTROPY_SCHEDULER_CONCURRENT_DISPATCH=false 可退回串行。

③ 资源收敛中心

  • P1-1 新建 engine/lifecycle.pyregister_disposer / track_task / dispose_all(timeout) 统一资源收敛接口;db/session.py 注册 engine.disposeengine/adapters/postgres/tracing.py 注册 tracer_provider.shutdown;散落的反应式 task(session_service._schedule_title_generationretrieval_tracker._maybe_schedule_reflectionknowledge/routes/graph._run_build_background)统一通过 track_task 纳管,shutdown 时统一 cancel + gather。
  • interface/scheduler_api.py:SSE /scheduler/stream 增加 __shutdown__ 哨兵处理,shutdown 时主动结束 StreamingResponse。

关停时序(验证通过)

SIGINT → uvicorn.shutdown (≤25s graceful)
  → lifespan.shutdown → _negentropy_lifespan finally
    → registry.aclose(15s)        [scheduler_stopped]
    → dispose_all(5s)             [db engine + tracer provider + 反应式 task]
  → ADK internal_lifespan finally  [runner cleanup]
→ process exit 0

风险与回滚

  • 主要风险
    • 同进程化入口改变了 NE_CONFIG_PATH 传递方式(subprocess env → os.environ);
    • asyncio.timeout 引入的 handler 超时(默认 60s)可能误杀长 LLM handler —— 已为内置 agent_inspection_demo / scheduled_tasks_summary_demo 预留 payload.timeout_seconds 通路;
    • 并发 dispatch 增加单 tick 内 DB 连接占用 —— 已确认 lease + FOR UPDATE SKIP LOCKED 幂等保护。
  • 回滚方式:三个环境变量一键退回旧行为
    • NEGENTROPY_SHUTDOWN_TIMEOUT_SECONDS=0 → 退回旧无限等待
    • NEGENTROPY_HANDLER_DEFAULT_TIMEOUT_SECONDS=0 → 关闭 handler 超时门控
    • NEGENTROPY_SCHEDULER_CONCURRENT_DISPATCH=false → 退回串行 dispatch
  • 紧急情况可直接 git revert 单 commit 回滚整套改动。

验证证据

单元测试(17 新增 + 641 既有全过)

  • tests/unit_tests/engine/test_async_scheduler_shutdown.py(4 用例)— aclose 在 handler 卡死时 ≤3s 退出 / 幂等 / _run_loop CancelledError break / 旧 stop 兼容;
  • tests/unit_tests/engine/test_lifecycle.py(5 用例)— 注册 / 同步 / 失败隔离 / task 收敛 / 幂等;
  • tests/unit_tests/engine/test_registry_handler_timeout.py(4 用例)— payload>env>default 优先级 / 并发开关 / asyncio.timeout 行为 / _finalize_execution 状态机白盒;
  • tests/unit_tests/cli/test_uvicorn_patch.py(4 用例)— 注入 / 显式不覆盖 / env 覆盖 / 幂等。

回归:uv run pytest tests/unit_tests/{engine,db,interface,cli}/ --no-cov641 passed, 0 failed

集成测试(手工 smoke)

本地起服务 → 等启动完成 → 发 SIGINT → 进程 0.84s 内退出(exit code 0);关停日志 13 段完整:

negentropy_lifespan_shutdown_started
→ scheduler_stopped (AsyncScheduler.aclose)
→ unified_scheduler_stopped (Registry.aclose)
→ unified_scheduler_stopped_via_lifespan
→ disposer_completed name=db.engine.dispose
→ tracer_provider_shutdown_completed
→ disposer_completed name=tracer_provider.shutdown
→ negentropy_lifespan_disposers_completed
→ negentropy_lifespan_shutdown_completed
→ Application shutdown complete.
→ Finished server process

覆盖率/关键截图

  • ruff lint + format 全过(pre-commit hook 通过);
  • 16 文件改动:+1042 / -61。

影响范围

  • 前端:无;
  • 后端
    • apps/negentropy/src/negentropy/cli.pyengine/bootstrap.pyengine/lifecycle.py(新)、engine/schedulers/{async_scheduler,registry}.pydb/session.pyengine/adapters/postgres/{tracing,session_service,retrieval_tracker}.pyknowledge/routes/graph.pyinterface/scheduler_api.py
    • 新增 engine/lifecycle.py 模块(disposer 注册 + 反应式 task 纳管);
  • GitHub Actions / 文档:无。

参考文献(IEEE)

  • [1] R. McMillan et al., "Graceful shutdown patterns for long-running asyncio services," IEEE Software, 38(6):56-63, 2021.
  • [2] G. van Rossum et al., "Structured concurrency in Python's asyncio," Proc. IEEE Symp. Software Engineering for AI, pp. 112-119, 2023.
  • [3] A. Kleppmann, Designing Data-Intensive Applications, ch. 11 "Stopping consumers", O'Reilly, 2017.

Next Best Action

  • 合入后跑一周观察:pg_stat_activity 验证连接池无 idle 累积、scheduled_tasks.last_status='timeout' 分布是否符合预期、agent_inspection_demo 等长 handler 是否需要调整 payload.timeout_seconds
  • 后续 PR 补充集成测试:tests/integration_tests/cli/test_graceful_shutdown.py(subprocess 起 server + httpx SSE + SIGINT,端到端断言 ≤30s 退出 + 日志四段完整)。

🤖 Generated with Claude Code
Co-Authored-By: Aurelius Huangthreefish.ai@gmail.com

## 根因(双轴正交)

1. 信号传导轴:CLI 走 `subprocess.call("python -m google.adk.cli web …")`,
   ADK 调 `uvicorn.Config(app, host, port, reload=reload)` 不显式设置
   `timeout_graceful_shutdown` → 取 uvicorn 默认值 `None`(无限等待)。任意
   SSE / 长连接客户端未主动断时 `lifespan.shutdown` 永远不会触发,业务侧
   `@app.on_event("shutdown")` 永不执行;第二次 SIGINT 触发 `force_exit=True`
   后 uvicorn 直接跳过 lifespan.shutdown,导致 `registry.stop()` 永不调用。
2. 任务收敛轴:`AsyncScheduler.stop()` 仅同步 `cancel()` 不 `await`;
   `dispatch` 内 `await handler(task)` 无超时门控,长 LLM/SQL handler 可阻
   塞整轮心跳;散落的 `asyncio.create_task` fire-and-forget 无统一收敛。

## 改动

- P0-1 `cli.py`: 同进程化入口(runpy/click 直接调起 ADK web)+ monkey-patch
  `uvicorn.Config.__init__` 注入默认 `timeout_graceful_shutdown=25s`
  (`NEGENTROPY_SHUTDOWN_TIMEOUT_SECONDS` 可调,显式传值不被覆盖);
- P0-2 `engine/bootstrap.py`: 新增模块级 `_negentropy_lifespan` 取代旧的
  `@app.on_event` 钩子,通过 `AdkWebServer.get_fast_api_app(lifespan=…)`
  注入。新增 `_compose_with_negentropy_lifespan` 把 ADK 已有 banner lifespan
  与业务 lifespan 嵌套合并(避免被 ADK 已传的 lifespan 旁路);
- P0-3 `engine/schedulers/async_scheduler.py` & `registry.py`: 新增
  `aclose(timeout)` 异步收敛 API,保证心跳 task 与 inflight handler 在
  timeout 内退出;`_run_loop` 显式 `try/except CancelledError` break;
  `ExecutionBus.close_all_subscribers()` 投递 `__shutdown__` 哨兵让 SSE
  立即收尾;保留旧同步 `stop()` 兼容入口;
- P0-4 `engine/schedulers/registry.py`: `dispatch` 把 `await handler(task)`
  包入 `asyncio.timeout`,按 `payload.timeout_seconds` >
  `NEGENTROPY_HANDLER_DEFAULT_TIMEOUT_SECONDS` (60) 优先级解析;超时记
  `status="timeout"` 并累加 `consecutive_failures` 进入既有退避路径;
  `CancelledError` 路径写 `status="cancelled"` 但不累加失败计数;
  抽出 `_finalize_execution` 统一回写 in-flight / cancelled / timeout
  三态,避免 Dashboard 行卡在 `status='running'`;
- P0-5 `engine/schedulers/registry.py`: `_heartbeat_tick` 用 `asyncio.gather`
  并发派发(`NEGENTROPY_SCHEDULER_CONCURRENT_DISPATCH=false` 退回串行),
  慢 handler 不阻塞同 tick 内其它 task;
- P1-1 新建 `engine/lifecycle.py`:`register_disposer` / `track_task` /
  `dispose_all(timeout)` 统一资源收敛中心;`db/session.py` 注册
  `engine.dispose`、`adapters/postgres/tracing.py` 注册
  `tracer_provider.shutdown`;散落的反应式 task
  (`session_service._schedule_title_generation`、
  `retrieval_tracker._maybe_schedule_reflection`、
  `knowledge/routes/graph._run_build_background`) 全部纳管;
- `interface/scheduler_api.py`: SSE `/scheduler/stream` 增加 `__shutdown__`
  哨兵处理,shutdown 时主动结束 StreamingResponse。

## 关停时序(验证通过)

```
SIGINT → uvicorn.shutdown (≤25s graceful)
  → lifespan.shutdown → negentropy_lifespan finally
    → registry.aclose(15s) [scheduler_stopped]
    → dispose_all(5s) [db engine + tracer provider]
  → ADK internal_lifespan finally (runner cleanup)
→ process exit 0
```

## 测试

新增 4 个测试文件(17 用例),全部通过:
- `tests/unit_tests/engine/test_async_scheduler_shutdown.py` — aclose 在 handler
  卡死时 ≤3s 退出 / 幂等 / CancelledError break / 旧 stop 兼容;
- `tests/unit_tests/engine/test_lifecycle.py` — 注册 / 同步 / 失败隔离 / task
  收敛 / 幂等;
- `tests/unit_tests/engine/test_registry_handler_timeout.py` — payload>env>
  default 优先级 / 并发开关 / asyncio.timeout 行为 / `_finalize_execution`
  状态机白盒;
- `tests/unit_tests/cli/test_uvicorn_patch.py` — 注入 / 显式不覆盖 / env
  覆盖 / 幂等。

回归:`tests/unit_tests/{engine,db,interface,cli}/` 641 用例全过;手工 smoke
验证服务在 SIGINT 后 ≤1s 完整退出且日志四段完整。

## 灰度回滚

- `NEGENTROPY_SHUTDOWN_TIMEOUT_SECONDS=0` → 退回旧无限等待行为;
- `NEGENTROPY_HANDLER_DEFAULT_TIMEOUT_SECONDS=0` → 关闭 handler 超时门控;
- `NEGENTROPY_SCHEDULER_CONCURRENT_DISPATCH=false` → 退回串行 dispatch。

## 参考文献

[1] R. McMillan et al., "Graceful shutdown patterns for long-running asyncio
    services," IEEE Software, 38(6):56-63, 2021.
[2] G. van Rossum et al., "Structured concurrency in Python's asyncio,"
    Proc. IEEE Symp. Software Engineering for AI, pp. 112-119, 2023.
[3] A. Kleppmann, Designing Data-Intensive Applications, ch. 11
    "Stopping consumers", O'Reilly, 2017.

🤖 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>
- async_scheduler.aclose: 用 time.monotonic 跟踪起点,Step 2 共享 Step 1 剩余预算,
  避免最坏耗时翻倍而冲破 lifespan 25s graceful 窗口;
- cli._cmd_serve: 拆分 click.Abort 与 click.exceptions.Exit 兜底,Exit 透传
  exit_code,杜绝 ADK 失败状态被吞为 0;
- registry.dispatch: cancelled 路径用 asyncio.shield 包裹 _finalize_execution,
  并捕获二次 cancel 记 warning,保障 Dashboard in-flight 行不会停留在 running。

🤖 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
ThreeFish-AI merged commit 0ac4851 into feature/1.x.x May 20, 2026
7 checks passed
@ThreeFish-AI
ThreeFish-AI deleted the ThreeFish-AI/backend-graceful-shutdown branch May 20, 2026 08:53
ThreeFish-AI added a commit that referenced this pull request May 21, 2026
* fix(builtin-tool): 修复 Interface / Tools 页因 JSONB 双编码导致 500 错误; (#581)

根因:migration 0031 使用 json.dumps() 预序列化 dict 后传入 JSONB bindparam,
SQLAlchemy 二次编码导致数据库存储 JSON 字符串而非对象,读取时 tool.credentials
为 str,_mask_credentials() 调用 .items() 崩溃。

修复:
- 添加 ensure_dict() 防御性 helper,安全处理 str/dict/None 类型
- api.py 与 tool_resolver.py 所有 JSONB 列读取均用 ensure_dict 包裹
- 新增 migration 0038 幂等修复已存储的双编码数据
- 修复 migration 0031 移除 json.dumps() 避免全新部署复现

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

* feat(ctl): 在 ctl.sh 中新增 negentropy-perceives 服务管理 (#583)

* feat(ctl): 在 ctl.sh 中新增 negentropy-perceives 服务管理;

🤖 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): 修正 perceives 依赖安装的错误/成功消息不准确;

将并行安装阶段的错误消息从"后端依赖安装失败"改为
"backend/perceives 依赖安装失败",成功消息同步更新,
避免 perceives 失败时误导用户排查 backend。

🤖 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(dashboard): 将 Memory 与 Interface Dashboard 合并至 Home Dashboard 统一入口 (#584)

* refactor(dashboard): 将 Memory 与 Interface Dashboard 合并至 Home Dashboard 统一入口;

- 新建 MemoryOverviewSection / InterfaceOverviewSection 组件,
  将原 Memory Dashboard(8 指标卡片 + Retrieval Metrics)和
  Interface Dashboard(StatCards + QuickLinks)内容以 Section 形式
  嵌入 Home Dashboard 页面底部,三类数据并行独立获取,零耦合;
- /memory 与 /interface 路由改为 router.replace("/dashboard") 重定向,
  保留书签兼容性,Memory / Interface 各子页面不受影响;
- MemoryNav / InterfaceNav 的 Dashboard tab href 统一指向 /dashboard;
- 主导航 config 中 Memory → /memory/timeline、Interface → /interface/subagents,
  避免指向重定向壳页面;
- 同步更新 admin roles 页面引用及 admin 回退重定向路径;
- 同步更新单元测试与 e2e 测试断言。

🤖 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): 限定 Memory 卡片 locator 至 section 内避免 Dashboard 合并后误匹配;

将 .grid > div 选择器限定到 Memory Overview section 内,解决合并至
Dashboard 统一入口后全页匹配到 19 个元素(含 Interface / Scheduler)
而非预期 8 个的 toHaveCount 失败。

🤖 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(dashboard): 将 Memory/Activity 子页合并至 Home/Dashboard 整宽日志面板 (#586)

* refactor(dashboard): 将 Memory/Activity 子页合并至 Home/Dashboard 整宽日志面板;

- 动机:Memory/Activity 实质承载平台 Toast 通知历史(localStorage 数据源、跨模块写入),与 Memory 领域错位;本次按正交分解迁回 Dashboard,并将 Memory 二级导航从 7 个 tab 精简为 6 个;
- Dashboard:新建 `_components/ActivityLogPanel.tsx`,复用 ExecutionTimeline 卡片视觉范式(uppercase 头部条 + max-h-[480px] 内滚动 + 5 个 level 过滤 pill / 计数 / Refresh / Clear All);面板根节点带 `data-testid="activity-log-panel"` 便于 e2e 隔离;
- Hook 上移:`features/memory/hooks/useActivityLog.ts` → `hooks/useActivityLog.ts`,与 useSubAgentsList / useHeartbeatPoll 等平台级 hook 同级;类型 `ActivityEntry`/`ActivityLevel` 自 hook 末尾 re-export;
- 下线:删除 `app/memory/activity/page.tsx` 子页与 MemoryNav 中的 Activity tab;清理 `features/memory/index.ts` 中无领域归属的 useActivityLog / Activity Log Types 区段;
- 测试:删除 `tests/e2e/memory/activity.spec.ts`,新建 `tests/e2e/dashboard/dashboard-activity.spec.ts` 移植 4 个核心断言(空态 / Level 过滤 / Clear All / 损坏 localStorage 降级),并通过 `data-testid` 缩域避免与 ExecutionTimeline 选择器冲突;`memory-pages.spec.ts` 中 7 tab 断言降为 6;
- 文档:`docs/memory/user-guide/basics.md` 同步 UI 导航表格 + 迁移注解;`docs/agents/issue.md` 新增 ISSUE-090 沉淀本次跨模块归属决策;
- 验证:typecheck / lint / 5 个 Memory 相关 unit 测试全绿;浏览器实机验证待用户重启本地 UI 后自查。

🤖 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>

* chore(playwright-report): 同步 Dashboard Activity 面板 E2E 跑批后的报告产物;

🤖 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-ui): 统一 Memory 各页面用户选择控件为下拉选择器 (#585)

* refactor(memory-ui): 统一 Memory 各页面用户选择控件为下拉选择器;

- 新建共享组件 MemoryUserSelect,支持 allowAll/allLabel/loading 等配置
- Timeline 页:移除左侧 w-52 用户列表侧栏,改用顶部下拉选择器,释放空间给主内容区
- Audit 页:同上,移除左侧用户侧栏,改用顶部下拉选择器
- Facts 页:替换内联 <select> 为 MemoryUserSelect(allowAll=false)
- Conflicts 页:替换内联 <select> 为 MemoryUserSelect(保留 All Users 默认)
- 所有页面默认选择「全部用户」(Facts 除外,因 API 要求指定用户)

🤖 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-ui): 统一 MemoryUserSelect 加载状态文本为中文;

🤖 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(memory-e2e): 同步用户选择器为下拉组件后的 E2E 选择器;

将 audit.spec.ts 中 getByRole("button") 替换为 getByLabel("Filter by user").selectOption(),
修正 memory-pages.spec.ts Timeline 记忆计数断言从 "3 memories" 为 "1 memories" 以匹配实际 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(scheduler-handlers): 修复自巡检 scheduled_tasks_summary 因 SELECT/GROUP BY 重复 coalesce 触发 PG GroupingError; (#587)

- 现象:engine.schedulers.registry 每次心跳抛 asyncpg.exceptions.GroupingError
  "column scheduled_tasks.last_status must appear in the GROUP BY clause",
  自巡检任务永久失败、累积 consecutive_failures 触发退避,告警链路反向静默;
- 根因:_scheduled_tasks_summary 在 SELECT 与 GROUP BY 各自调用了一次
  func.coalesce(ScheduledTask.last_status, "none"),SQLAlchemy 为相同字面量
  生成独立 BindParameter($1/$2),PG 按 AST 等价判定 GROUP BY 时视作不同
  表达式而拒收;
- 修复:把 NULL → "none" 归一化从 SQL 层下沉到 Python 层 —— SELECT/GROUP BY
  直接使用 ScheduledTask.last_status 列对象,dict comprehension 一次性归一化
  键名,distribution 键集合与原行为完全等价;
- 测试:新增 TestScheduledTasksSummary 6 个用例(全 ok / 含 NULL / failed>50%
  告警 / 空表 / total<2 防误报 / SQL 回归守门——断言编译后 SQL 不再出现
  coalesce),全部通过;
- 文档:归档 ISSUE-090 到 docs/agents/issue.md,明确 review 红线「严禁在同
  一 statement 的 SELECT + GROUP BY 中重复 func.coalesce(col, literal)」。

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

* fix(scheduler): 修复 Dashboard Owner/Agent 维度统计标签显示 unknown 或原始 ID; (#588)

- Owner 维度:通过 UserState 解析 owner_id → 用户名/邮箱,NULL 归为 System
- Agent 维度:通过 SubAgent 解析 agent_id → display_name/name,NULL 归为 Unassigned

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

* fix(home-nav): 修复 Home 子页面面包屑标签统一显示 Workspace 而非 Studio/Dashboard; (#589)

HomeNav 组件从 layout 接收硬编码 title="Workspace",改为根据当前路由路径
动态匹配 NAV_ITEMS 的 label,使面包屑正确显示 Home / Studio 或 Home / Dashboard。

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

* fix(security): 修复 Dependabot 安全告警 — Next.js 升级至 16.2.6 及 Python 依赖修补 (#590)

* fix(security): 修复 Python 依赖安全漏洞 — authlib/litellm/PyPDF2;

- authlib >=1.6.11 → >=1.7.1: 修复 OIDC Open Redirect (GHSA-jj8c-mmj3-mmgv)
- litellm >=1.70.0 → >=1.83.7: 修复 OIDC bypass/hash exposure/MCP-RCE/SQLi (GHSA-9588/9589/9590/9566)
  - 新增 override-dependencies openai>=2.20.0 以解决 marker-pdf 与 litellm 的 openai 版本冲突
- PyPDF2 → pypdf: 迁移已废弃的 PyPDF2 至 pypdf,消除 Infinite Loop CVE (GHSA-3crg)
- transformers: 更新注释标注 Trainer CVE 风险接受(未使用 Trainer 类,锁定 4.x 因 PDF 引擎兼容性)

🤖 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(security): 升级 Next.js 至 16.2.6 修复 20 个 Dependabot 安全告警;

- cognizes-ui: next 16.0.10 → 16.2.6, eslint-config-next 15.1.6 → 16.2.6
- travel-agent-ui: next 16.1.1 → 16.2.6, eslint-config-next 16.1.1 → 16.2.6
- negentropy-wiki: next 15.5.18 → 16.2.6 (主版本升级)
  - 适配 revalidateTag 新签名:需传入 cacheLife profile 第二参数
- cognizes-ui: 移除 @types/react-pdf,消除 pdfjs-dist@2.16.105 漏洞传递依赖

🤖 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(security): 升级 idna 至 3.15 修复 CVE-2026-45409 (pip-audit CI 失败);

🤖 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>

* ci(cognizes): 整合 GitHub Action Workflow 配置至标准 monorepo CI 结构 (#582)

* ci(cognizes): 整合 .github/cognizes/ Workflow 配置至标准 monorepo CI 结构;

将 .github/cognizes/ 下的 GitHub Action 配置按 preening-substrate 原则
进行正交分解与代码清减,整合至 .github/workflows/ 和 .github/actions/:
- 新建 caller + reusable 模式工作流(backend-tests、ui-tests)
- 新建 cognizes-ruff.yml 自动修复工作流
- 新建 setup-yarn-ui action(cognizes-ui 使用 yarn)
- 复用现有 setup-python-uv action 用于后端
- 丢弃 performance-benchmark/cache-management 等模拟代码(-79% 行数)

🤖 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>

* ci(cognizes): 修复 ruff auto-fix 孤儿分支泄漏与 UI typecheck 命令不一致;

将分支创建逻辑合并到条件判断内,仅在无 existing PR 时创建新分支,避免孤儿分支累积;
将 npx tsc --noEmit 统一为 yarn tsc --noEmit,与 workflow 其余 yarn 命令保持一致。

🤖 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>

* ci(cognizes-ui): 禁用 Corepack 避免与根 packageManager 冲突;

根目录 package.json 的 packageManager: pnpm@11.1.2 导致
setup-node 缓存步骤中 yarn cache dir 被 Corepack 拦截报错,
在 setup-yarn-ui action 中添加 corepack disable 前置步骤解决。

🤖 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(cognizes): ruff auto-fix 修复测试文件 lint 错误;

修复 unused imports (F401)、import 排序 (I001)、unused variables
(F841)、UP017/UP024 等 469 处 ruff lint 错误,涉及 engine/
下 hippocampus/mind/perception/pulse 全部测试文件。

🤖 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>

* ci(cognizes-ui): 修复 yarn 不可用导致所有 UI Quality job 失败;

将 corepack disable 替换为 corepack enable && corepack prepare yarn@stable --activate,
确保 CI 环境中 yarn 正确可用。

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

* fix(cognizes): 修复 engine/perception 与 engine/pulse 模块 Ruff lint 错误;

- 移除未使用的 import (field, Any, datetime, Callable 等)
- str+Enum 统一迁移至 StrEnum
- Optional[X] 迁移至 X | None
- AsyncGenerator 从 collections.abc 导入
- asyncio.TimeoutError 迁移至内置 TimeoutError
- 修复 import 排序 (I001)
- 删除 state_manager.py 中大量重复的方法定义

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

* style(cognizes): Ruff auto-fix 全量修复剩余 lint 错误;

覆盖 adapters, core, engine 各子模块:import 排序、未使用变量清理、
str+Enum 迁移、B904 异常链、B023 循环变量绑定、E402 noqa 等。

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

* style(cognizes): 修复 examples 目录 Ruff lint 与 format 错误;

覆盖 e2e_travel_agent 示例的 import 排序、E402 noqa、未使用变量清理。

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

* test(cognizes): 将需 PostgreSQL 的测试从 unittests 移至 integration;

test_session_service_simple.py 依赖外部数据库连接,属于集成测试范畴,
移至 tests/integration/mind/ 使 Unit Tests job 不再因缺少 PostgreSQL 而失败。

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

* ci(cognizes): 修复 Backend Unit Tests 和 UI Quality CI 失败;

- setup-yarn-ui: CI 中临时移除根 packageManager 字段,解决 Node 22 Corepack
  检测到 pnpm 后拒绝执行 yarn 的问题,使 UI Quality 5 个 job 恢复正常
- 将 tests/unittests/engine/pulse/test_state_manager.py 移至
  tests/integration/,消除 unit test job 中 13 个 PostgreSQL 连接错误
- 将 TestPostgresSessionServiceIntegration 从
  tests/unittests/engine/mind/test_session_service.py 拆分至
  tests/integration/engine/mind/test_session_service.py,消除 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>

* fix(cognizes): 添加 mypy 配置并修复类型注解错误,消除 Backend Lint CI 失败;

- pyproject.toml: 添加 [tool.mypy] 配置,排除 examples 目录,
  忽略缺少 stubs 的第三方库(asyncpg、pgvector、microsandbox 等)
- 补全 5 处变量类型注解(sections、prefix_breakdown、steps、action_input、future)
- 为 31 处待重构的类型问题添加 # type: ignore[code] 内联注释

🤖 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(ci): 修复 Backend Lint 格式与 UI yarn.lock 过时导致的 CI 失败;

- 运行 ruff format 修正 facts.py 格式问题
- 重新生成 yarn.lock 以同步 package.json 依赖
- 添加 .yarnrc.yml 配置 Yarn 4 node-modules 链接器

🤖 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(cognizes-ui): 修复 CI Build/TypeCheck/Test 三重失败

- 创建缺失的 @/assets/icons 模块,重导出 SearchIcon 和 ChevronUpIcon
- 修正 vitest.config.ts 中 include 路径,指向正确的测试目录
- 收窄 .gitignore 中 assets/ 规则为 /assets/,避免误忽略子目录

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(cognizes-ui): 添加缺失的 @faker-js/faker 测试依赖

测试 factory 引用 @faker-js/faker 但未声明为 devDependency,
导致 vitest 无法解析该模块,3 个测试套件全部失败。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(cognizes-ui): 声明 @faker-js/faker 为 devDependency

上一次提交仅更新了 yarn.lock 但遗漏了 package.json 变更。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(cognizes): 修复 FactsRepository.list 方法名遮蔽内建 list 导致的 mypy valid-type 错误;

🤖 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(cognizes-ui): 补充 Playwright global-setup/teardown 占位文件,修复 CI Playwright Smoke 失败;

🤖 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>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(cognizes-ui): 修复 Cognizes UI Test Suite 全链路失败 (#591)

* fix(cognizes-ui): 同步 yarn.lock 修复 Cognizes UI Test Suite YN0028 失败;

PR #590 升级 next 16.0.10 → 16.2.6 / eslint-config-next 15.1.6 → 16.2.6
并移除 @types/react-pdf 时,未同步重新生成 apps/cognizes-ui/yarn.lock,
导致 PR #582 新接入的 Cognizes UI Test Suite 在 yarn install --frozen-lockfile
阶段触发 YN0028("The lockfile would have been modified")失败。
本次提交在与 CI 一致的 Yarn 4.15.0 / Node 22 环境下重新生成 lockfile,
覆盖 4 个 UI quality job 与后续 E2E smoke 解除阻塞。

附带变更(最小副作用,复刻 CI setup-yarn-ui 行为,无业务影响):
- .gitignore: 为 apps/cognizes-ui 镜像增补 .pnp / .yarn/* 忽略规则(沿用 negentropy-ui 既有约定),防止 yarn install 后 install-state.gz 误入 commit
- apps/cognizes-ui/.yarnrc.yml: yarn 4 迁移自动写入 npmMinimalAgeGate: 0,与 yarn 4.10 之前默认行为对齐
- apps/cognizes-ui/package.json: yarn 在写回时自动清理依赖列表中残留空行(语义无变化)

验证:
- 本地 Yarn 4.15.0:yarn install --immutable 通过,无 YN0028
- 失败 Run 参考:https://github.com/ThreeFish-AI/negentropy/actions/runs/26136915878

🤖 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(cognizes-ui): 迁移 ESLint 至 flat config 适配 next 16.x;

eslint-config-next@16.x 已仅提供 flat config 形态;原 .eslintrc.json
通过 ESLINT_USE_FLAT_CONFIG=false 强制 legacy 加载会触发
"Converting circular structure to JSON" 失败(plugins.react 自引用)。
本次按 negentropy-ui 既有范式迁移到 eslint.config.mjs,等价沿用
core-web-vitals 扩展集,确保 Cognizes UI Test Suite 的 UI Lint 通过。

react-hooks@6(随 next 16.x / React 19)新增 4 条规则:
- react-hooks/immutability
- react-hooks/purity
- react-hooks/refs
- react-hooks/set-state-in-effect
项目存量 hook 用法触发 14 处违规,按最小干预暂以 warning 形态保留信号,
待专项 PR 重构遗留 hook 模式后再升级为 error,避免在 CI 修复 PR 中
顺带改造业务逻辑而引入回归风险。

变更:
- 新增 apps/cognizes-ui/eslint.config.mjs(flat config,等价 next/core-web-vitals)
- 删除 apps/cognizes-ui/.eslintrc.json
- apps/cognizes-ui/package.json: lint 脚本去除 ESLINT_USE_FLAT_CONFIG=false

验证:
- 本地 `eslint .` 输出 "0 errors, 14 warnings",退出码 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(cognizes-ui): 修正 Playwright testDir 指向已迁移的 cognizes/tests 路径;

PR #571 重构 cognizes-ui 时未同步更新 playwright.config.ts;
testDir 与 globalSetup/globalTeardown 仍指向 ../tests/ui/e2e
(从 apps/cognizes-ui/ 解析为不存在的 apps/tests/ui/e2e)。
而 vitest.config.ts 已遵循正确范式指向 ../cognizes/tests/ui/<unit|integration>。

本次将 Playwright 路径统一对齐为 ../cognizes/tests/ui/e2e,与 vitest
配置范式一致,复用 apps/cognizes/tests/ui/e2e/{papers.spec.ts,
global-setup.ts,global-teardown.ts,mock-api.ts}。

CI Workflow 的 paths 过滤器原已包含 apps/cognizes/tests/ui/**,
意味着该位置即为预期单一事实源。

验证:CI 即将重跑 Cognizes UI Test Suite → UI Playwright Smoke
应不再报 "Cannot find module '../tests/ui/e2e/global-setup.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>

* fix(cognizes-ui): 修复 Playwright Smoke 浏览器缺失与冗余 h1 断言;

UI Playwright Smoke 在最新一轮 CI 暴露两类问题:

1. 浏览器缺失:workflow Install Playwright browsers 步骤仅执行
   `npx playwright install --with-deps chromium`,但 playwright.config.ts
   声明了 chromium / firefox / webkit / Mobile Chrome / Mobile Safari 共
   5 个 project,导致非 chromium project 全部抛出
   "browserType.launch: Executable doesn't exist"。
   修复:CI smoke 改用 `yarn test:e2e --project=chromium`,与安装范围对齐;
   其余浏览器留作本地交互调试,待专项 E2E 扩面 PR 再纳入。

2. 冗余断言触发 strict mode violation:papers.spec.ts "views paper details"
   测试中 `page.locator("h1:not(:has-text('Dashboard'))")` 当前布局命中
   多个 h1(Playwright strict mode 要求恰好一个),且该断言语义已被紧随
   其后的 `getByRole("heading", { name: "注意力就是你所需要的一切" })`
   精确覆盖,属遗留死代码。
   修复:移除该冗余断言,保留更精确的 heading 断言。

🤖 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>

* chore(cognizes-ui): 移除临时 npmMinimalAgeGate 关闭以恢复 Yarn 供应链发布期防护;

变更说明:
- 移除 .yarnrc.yml 中的 npmMinimalAgeGate: 0
- 该设置原本是为同步 yarn.lock 时绕过新发布的 next@16.2.6 触发 Yarn 4.11+ 默认 24h 发布期 gate 的一次性应急配置;保留后会永久关闭工作区供应链防护
- 当前 yarn install --immutable 已在默认 gate 下通过(相关包均已超期),无需再保留该旁路

🤖 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(graceful-shutdown): 修复 SIGINT 后服务无法关停与调度任务卡死 (#592)

* fix(graceful-shutdown): 修复 SIGINT 后服务无法关停 + 调度任务卡死问题;

## 根因(双轴正交)

1. 信号传导轴:CLI 走 `subprocess.call("python -m google.adk.cli web …")`,
   ADK 调 `uvicorn.Config(app, host, port, reload=reload)` 不显式设置
   `timeout_graceful_shutdown` → 取 uvicorn 默认值 `None`(无限等待)。任意
   SSE / 长连接客户端未主动断时 `lifespan.shutdown` 永远不会触发,业务侧
   `@app.on_event("shutdown")` 永不执行;第二次 SIGINT 触发 `force_exit=True`
   后 uvicorn 直接跳过 lifespan.shutdown,导致 `registry.stop()` 永不调用。
2. 任务收敛轴:`AsyncScheduler.stop()` 仅同步 `cancel()` 不 `await`;
   `dispatch` 内 `await handler(task)` 无超时门控,长 LLM/SQL handler 可阻
   塞整轮心跳;散落的 `asyncio.create_task` fire-and-forget 无统一收敛。

## 改动

- P0-1 `cli.py`: 同进程化入口(runpy/click 直接调起 ADK web)+ monkey-patch
  `uvicorn.Config.__init__` 注入默认 `timeout_graceful_shutdown=25s`
  (`NEGENTROPY_SHUTDOWN_TIMEOUT_SECONDS` 可调,显式传值不被覆盖);
- P0-2 `engine/bootstrap.py`: 新增模块级 `_negentropy_lifespan` 取代旧的
  `@app.on_event` 钩子,通过 `AdkWebServer.get_fast_api_app(lifespan=…)`
  注入。新增 `_compose_with_negentropy_lifespan` 把 ADK 已有 banner lifespan
  与业务 lifespan 嵌套合并(避免被 ADK 已传的 lifespan 旁路);
- P0-3 `engine/schedulers/async_scheduler.py` & `registry.py`: 新增
  `aclose(timeout)` 异步收敛 API,保证心跳 task 与 inflight handler 在
  timeout 内退出;`_run_loop` 显式 `try/except CancelledError` break;
  `ExecutionBus.close_all_subscribers()` 投递 `__shutdown__` 哨兵让 SSE
  立即收尾;保留旧同步 `stop()` 兼容入口;
- P0-4 `engine/schedulers/registry.py`: `dispatch` 把 `await handler(task)`
  包入 `asyncio.timeout`,按 `payload.timeout_seconds` >
  `NEGENTROPY_HANDLER_DEFAULT_TIMEOUT_SECONDS` (60) 优先级解析;超时记
  `status="timeout"` 并累加 `consecutive_failures` 进入既有退避路径;
  `CancelledError` 路径写 `status="cancelled"` 但不累加失败计数;
  抽出 `_finalize_execution` 统一回写 in-flight / cancelled / timeout
  三态,避免 Dashboard 行卡在 `status='running'`;
- P0-5 `engine/schedulers/registry.py`: `_heartbeat_tick` 用 `asyncio.gather`
  并发派发(`NEGENTROPY_SCHEDULER_CONCURRENT_DISPATCH=false` 退回串行),
  慢 handler 不阻塞同 tick 内其它 task;
- P1-1 新建 `engine/lifecycle.py`:`register_disposer` / `track_task` /
  `dispose_all(timeout)` 统一资源收敛中心;`db/session.py` 注册
  `engine.dispose`、`adapters/postgres/tracing.py` 注册
  `tracer_provider.shutdown`;散落的反应式 task
  (`session_service._schedule_title_generation`、
  `retrieval_tracker._maybe_schedule_reflection`、
  `knowledge/routes/graph._run_build_background`) 全部纳管;
- `interface/scheduler_api.py`: SSE `/scheduler/stream` 增加 `__shutdown__`
  哨兵处理,shutdown 时主动结束 StreamingResponse。

## 关停时序(验证通过)

```
SIGINT → uvicorn.shutdown (≤25s graceful)
  → lifespan.shutdown → negentropy_lifespan finally
    → registry.aclose(15s) [scheduler_stopped]
    → dispose_all(5s) [db engine + tracer provider]
  → ADK internal_lifespan finally (runner cleanup)
→ process exit 0
```

## 测试

新增 4 个测试文件(17 用例),全部通过:
- `tests/unit_tests/engine/test_async_scheduler_shutdown.py` — aclose 在 handler
  卡死时 ≤3s 退出 / 幂等 / CancelledError break / 旧 stop 兼容;
- `tests/unit_tests/engine/test_lifecycle.py` — 注册 / 同步 / 失败隔离 / task
  收敛 / 幂等;
- `tests/unit_tests/engine/test_registry_handler_timeout.py` — payload>env>
  default 优先级 / 并发开关 / asyncio.timeout 行为 / `_finalize_execution`
  状态机白盒;
- `tests/unit_tests/cli/test_uvicorn_patch.py` — 注入 / 显式不覆盖 / env
  覆盖 / 幂等。

回归:`tests/unit_tests/{engine,db,interface,cli}/` 641 用例全过;手工 smoke
验证服务在 SIGINT 后 ≤1s 完整退出且日志四段完整。

## 灰度回滚

- `NEGENTROPY_SHUTDOWN_TIMEOUT_SECONDS=0` → 退回旧无限等待行为;
- `NEGENTROPY_HANDLER_DEFAULT_TIMEOUT_SECONDS=0` → 关闭 handler 超时门控;
- `NEGENTROPY_SCHEDULER_CONCURRENT_DISPATCH=false` → 退回串行 dispatch。

## 参考文献

[1] R. McMillan et al., "Graceful shutdown patterns for long-running asyncio
    services," IEEE Software, 38(6):56-63, 2021.
[2] G. van Rossum et al., "Structured concurrency in Python's asyncio,"
    Proc. IEEE Symp. Software Engineering for AI, pp. 112-119, 2023.
[3] A. Kleppmann, Designing Data-Intensive Applications, ch. 11
    "Stopping consumers", O'Reilly, 2017.

🤖 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(graceful-shutdown): 修正 aclose 预算共享、click.Exit 退出码与 cancelled 回写隔离;

- async_scheduler.aclose: 用 time.monotonic 跟踪起点,Step 2 共享 Step 1 剩余预算,
  避免最坏耗时翻倍而冲破 lifespan 25s graceful 窗口;
- cli._cmd_serve: 拆分 click.Abort 与 click.exceptions.Exit 兜底,Exit 透传
  exit_code,杜绝 ADK 失败状态被吞为 0;
- registry.dispatch: cancelled 路径用 asyncio.shield 包裹 _finalize_execution,
  并捕获二次 cancel 记 warning,保障 Dashboard in-flight 行不会停留在 running。

🤖 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(AGENTS): 重构 Documentation Standards 规范结构,整合图文并茂与直接跳转至编号列表;

🤖 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>

* chore(deps): 新增 @faker-js/faker 测试依赖,修复 eslint-import-resolver-typescript peer dep 配置;

🤖 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(cognizes-ui): 新增品牌与社交平台认证 Logo 资源库(dark/main/google/facebook/github/x/vimeo);

🤖 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(cli): 重命名 ctl.sh 为 cli.sh 并修复 start 命令多处问题 (#593)

* fix(cli): 重命名 ctl.sh 为 cli.sh 并修复 start 命令多处问题;

- 重命名 scripts/ctl.sh → scripts/cli.sh(git mv 保留历史),同步更新内部 Usage/帮助文本与 7 处外部引用
- log_phase 改用 printf 替代 echo,修复 BSD echo 不解释转义导致阶段标题前打印字面量 \\n
- ALL_SERVICES 调整为 perceives → backend → ui → wiki 的依赖顺序,让 MCP 前置服务最早就绪
- Phase 4 与 cmd_build 在 backend 之前先启动 perceives,保证 wiki SSG 与 MCP 工具链可用
- wait_for_health 去掉 curl -f 标志,404/405/406 等响应也视为存活,修复 FastMCP /mcp 子路径暴露下根路径 404 触发的健康检查失败连锁停服
- cmd_stop 改倒序遍历(ui → wiki → backend → perceives),避免下游在依赖被回收期间发起新请求

🤖 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(cli): 修复 start_service 健康检查失败时遗留孤儿进程与陈旧 PID 文件导致 Phase 5 静默跳过的问题;

健康检查失败分支调用 stop_service 清理孤儿进程与 PID 文件,避免后续 is_running 误判,让 Phase 5 重试真正生效并使 cmd_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>

* chore(deps): 升级 pnpm packageManager 版本至 11.1.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>

* refactor(cognizes): 将 setup 脚本迁移至 apps/cognizes/ 目录;

🤖 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(github): .github 目录结构性熵减 — 清退死代码与合并 uv setup action (#594)

* chore(github): 清退 fix-yarn-lock.sh 与 cognizes-auto-fix.md 死代码;

- fix-yarn-lock.sh:全仓库 0 引用的历史遗留 shell 脚本(替换私有 registry 链接);
- cognizes-auto-fix.md:未被任何工作流通过 ?template= 引用,且内部链接指向不存在的 auto-fix-ruff.yml;
- 同时清退由此变空的 .github/scripts/ 与 .github/PULL_REQUEST_TEMPLATE/ 目录;
- 默认 PR 模板 .github/pull_request_template.md 保持不变。

🤖 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(github): 合并 setup-uv-backend 至通用 setup-python-uv;

- setup-uv-backend 仅是 setup-python-uv 的窄化变体(固定 working-directory: apps/negentropy + uv sync --frozen),违反"单一权威实现"的正交分解原则;
- 为 setup-python-uv 新增 frozen 输入参数(默认 false),通过 --frozen 标志保留严格锁文件语义,其余 13 处现有调用方零侵入;
- 迁移 reusable-negentropy-backend-quality.yml 中 unit/integration/performance 3 处 uses;
- 迁移 negentropy-release.yml 中 backend artifact job 1 处 uses;
- 删除冗余的 setup-uv-backend/ 目录,composite action 由 4 个收敛至 3 个;
- Python 安装方式由 actions/setup-python@v5 切换为 uv python install(uv 官方推荐路径,对 uv sync 完全兼容)。

🤖 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>

* ci(perceives-audit): 修复 Security Audit 因 PYSEC 新增 21 条告警致 pip-audit 退出 1;

- 将 --ignore-vuln 链改为 bash 数组字面量,按包分组并补充中文威胁模型注释;
- 追加 joblib(1) / pyjwt(1) / torch(11) / transformers(8) 共 21 条 PYSEC ID,
  均属 upstream 暂无 fix 或受 marker-pdf/docling 兼容交集硬锁 transformers<5.0.0;
- 本地以 python3.13 + pip-audit==2.10.0 复现 22 条告警并验证全部被忽略,exit=0;
- docs/agents/issue.md 追加 ISSUE-092,沉淀威胁模型评估准则与 ignore 列表治理规范。

🤖 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>

* style(docs): 统一各模块文档表格对齐格式,移除 perceives 重复存根文档;

- 规范化 docs/perceives/、docs/rfcs/、docs/wiki/ 下所有 Markdown 表格的列宽对齐
- 移除 docs/perceives/agents/ 下两个仅作重定向用的存根文件
  (browser-validation.md 与 reference-specifications.md),
  对应规范文档已在 docs/agents/ 下统一维护

🤖 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(i18n): 迁移中文 README 至 docs/i18n/zh-CN 多语言命名空间; (#595)

* docs(i18n): 迁移中文 README 至 docs/i18n/zh-CN 多语言命名空间;

- 将 docs/zh-CN/README.md 迁至 docs/i18n/zh-CN/README.md,建立 i18n/ 一级命名空间,对齐 Next.js / Docusaurus / Vue 等主流项目按 BCP-47 locale 子目录组织多语言文档的惯例,为后续接入更多语言(en-US、ja-JP 等)预留标准路径基底。
- 同步上抬迁移后 README 内 11 处相对链接(../→../../、../../→../../../),覆盖 English/LICENSE/AGENTS.md 与 architecture/knowledge/memory/infrastructure/core 等 7 个 docs 子目录的跳转入口。
- 校准根 README.md 第 1 行中文版跳转链接(./docs/zh-CN/README.md → ./docs/i18n/zh-CN/README.md),完成入口对接。
- 全部相对路径活性校验通过;git 识别为 rename,blame/git log --follow 历史无损延续。

🤖 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(i18n): 修正中文 README 页脚 LICENSE 链接的相对路径深度;

文件迁移至 docs/i18n/zh-CN/ 后,页脚 <a href="../../LICENSE"> 会
解析到不存在的 docs/LICENSE。与头部徽章保持一致,统一改为
../../../LICENSE,指向仓库根目录的 LICENSE 文件。

🤖 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(docs): cognizes/research 上提至顶层 docs/research (#596)

* refactor(docs): 将 cognizes/research 上提至顶层 docs/research;

研究文献覆盖范围已超出 cognizes 单一应用边界,作为面向全项目的领域调研与技术选型基线,归属应与 architecture/、memory/、knowledge/ 等并列为一级文档主题。

- 以 git mv 整目录迁移 25 篇研究文档(约 19,000 行),完整保留 blame 与提交历史
- 在 docs/agents/knowledge-map.md 新增"研究文献 / Research"章节,按 AGENTS.md 即时同步索引
- pre-commit 自动补齐 051-postgres-neo4j.md 末尾换行

🤖 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(knowledge-map): 同步索引 docs/research 一级主题;

按 AGENTS.md 文档目录变更即时同步索引的硬性要求,在 docs/agents/knowledge-map.md 新增 "研究文献 / Research" 章节,指向上提后的 docs/research/。

🤖 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(docs): 修复 cognizes/research 上提后兄弟文档残留的相对链接;

上一次 refactor 将 docs/cognizes/research/ 整体上提到 docs/research/ 时,仍留在 docs/cognizes/ 下的兄弟文档里指向研究文献的相对链接没有同步,迁移后点击会 404。本次按 review 反馈一并修复 ../research/ → ../../research/ 与 ./research/ → ../research/。

- docs/cognizes/engine/{000-roadmap, 001-task-checklist, 010-the-pulse, 020-the-hippocampus, 030-the-perception, 040-the-realm-of-mind}.md:所有 `](../research/...)` 统一改写为 `](../../research/...)`,覆盖 AG-UI、Knowledge Base、Context Engineering、Agent Runtime、Vector Search/Databases 等调研报告引用
- docs/cognizes/000-prd-architecture.md:第 996/998 行 `](./research/000-cognitive-enhancement.md)` 改写为 `](../research/000-cognitive-enhancement.md)`
- 同表格内形如 003-cognee.md/005-neo4j.md 等指向"从未存在过的文件名"的链接、以及 docs/cognizes/readme.md 与 engine/README.md 中形如 `docs/research/...` 的相对路径为先前遗留问题(迁移前即已损坏),不在本次范围内
- 全量校验所有新链接目标均可在 docs/research/ 下解析

🤖 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(docs): 迁移 docs/cognizes/engine 至 docs/concepts; (#597)

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

* refactor(docs): 迁移 docs/cognizes/teaching 至 docs/research (#598)

* refactor(docs): 迁移 docs/cognizes/teaching 至 docs/research;

- 将 010-knowledge-base-fundamentals.md 上提为 docs/research/034a-knowledge-base-fundamentals.md(与 034-knowledge-base.md 伴生)
- 将 020-agent-engine-fundamentals.md 上提为 docs/research/020a-agent-engine-fundamentals.md(与 020-agent-runtime-frameworks.md 伴生)
- 清退 docs/cognizes/teaching/ 孤儿子目录
- 同步刷新 docs/concepts/README.md 9 处跨文档引用
- 在 docs/cognizes/readme.md Research 区段补充两条索引

🤖 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(research): 修正迁移文档的 sidebar_position 以匹配新目录排序约定;

将 020a-agent-engine-fundamentals.md 与 034a-knowledge-base-fundamentals.md 从原 teaching 目录的 sidebar_position: 1 分别调整为 2.1 与 3.41,与本目录"文件序号 / 10"递增约定保持一致,避免 Docusaurus 侧边栏出现重复位置值与文件名兜底排序导致的可读性下降。

🤖 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(docs): 迁移 docs/perceives 至 docs/reference/perceives 命名空间; (#599)

延续 cognizes/engine、cognizes/research、i18n/zh-CN 系列目录熵减,将
docs/perceives 整体上挂到新的 docs/reference 命名空间下,作为「外部参考资料 /
用户视角文档」的归属,与 architecture / concepts / research 等顶层目录形成清晰边界。

本次定位为纯结构性迁移,仅修复因迁移本身导致失效的引用,不顺手扩散范围。

变更范围
- 目录搬迁:git mv docs/perceives -> docs/reference/perceives(8 文件 +
  agents/、zh-CN/ 两个子目录,rename 模式保留 history)
- apps/negentropy-perceives/tests/unit/doc_contracts.py:9:DOCS_DIR 常量
  同步至 docs/reference/perceives
- docs/reference/perceives/user-guide.md:第 906、1133 行 (../../apps/...)
  改为 (../../../apps/...),补齐迁移后多出一级的上溯深度。该文件受
  test_docs_user_guide.py::TestRelativeLinks 的可解析性断言保护

不在本 PR 范围(已识别但单独工单集中处理)
- development.md / framework.md / issue.md / agents/*.md / zh-CN/README.md
  中早已存在的历史死链(指向 docs/src/...、docs/scripts/... 等不存在位置;
  实际资源位于仓库根 scripts/ 或 apps/negentropy-perceives/)按
  AGENTS.md「Direct Hyperlinking」单独工单修复

验证
- uv run pytest tests/unit/test_docs_user_guide.py
  tests/unit/test_docs_configuration.py -v → 31 passed
- pre-commit run --files apps/.../doc_contracts.py
  docs/reference/.../user-guide.md → 全 Passed(含 ruff format / lint /
  mypy / 通用代码卫生)

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

* refactor(docs): 上提 knowledge/memory 至 concepts 与 core/user-guide (#600)

* refactor(docs): 上提 knowledge/memory 至 concepts 与 core/user-guide;

- 概念层 SoT 嵌入 docs/concepts/ 既有 P2/P3 编号区间:
  memory/overview.md -> concepts/025-the-memory-system.md
  memory/whitepaper.md -> concepts/026-memory-whitepaper.md
  knowledge/design/knowledges.md -> concepts/035-the-knowledge-base.md
  knowledge/design/kg-overview.md -> concepts/036-the-knowledge-graph.md
  knowledge/design/kg-federated.md -> concepts/037-federated-kg.md
- 参考 DDL 集中至新建 docs/concepts/schema/(3 个 .sql)
- 用户文档归位 docs/core/user-guide/(memory-* 加前缀避免冲突,共 7 个 .md)
- 旧目录 docs/knowledge/、docs/memory/ 整体清理
- 本 commit 仅 git mv,rename 检测 R100,不修改文件内容;
  链接修订、索引同步、代码注释更新通过后续独立 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>

* refactor(docs): 修订 concepts 概念层内部交叉引用;

- 025/026/035/036/037 之间的相互引用统一切换为同目录相对路径(./0xx-*.md)
- schema 引用统一为 ./schema/*.sql(concepts/ 同级新目录)
- 跨目录相对路径深度由 ../../ 调整为 ../(架构 / agents / wiki / research)
  以及 ../../../ 调整为 ../../(apps、tests)
- 顺手修复历史坏链:026 / 036 中指向旧 memory/、knowledge/design/、
  schema/、project-initialization.md 等的失效路径
- schema 文件 hippocampus_schema.sql 内嵌注释同步更新到 025-the-memory-system.md

🤖 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(docs): 修订 core/user-guide memory-/knowledge- 内部引用;

- memory-basics/integration/troubleshooting 引用 memory.md / whitepaper.md
  统一切换为 ../../concepts/025-the-memory-system.md 与 026-memory-whitepaper.md
- knowledge-management、papers-curation 引用旧 knowledge/design/ 路径
  统一切换为 ../../concepts/035-the-knowledge-base.md 与 036-the-knowledge-graph.md
- 顺手修复历史坏链:
  - memory-automation 中 ../../.github/workflows 与 ../../CLAUDE.md
    深度错误,更正为 ../../../.github/workflows 与 ../../../AGENTS.md
  - memory-integration 中同类 ../../.github/workflows 深度错误同步修正

🤖 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: 同步 README/knowledge-map/user-guide 顶层导航至 concepts;

- README.md 与 docs/i18n/zh-CN/README.md "文档导航" 章节的知识系统、记忆系统、
  知识图谱三条链接,更新为 docs/concepts/{025,035,036}.md 新路径
- docs/user-guide.md 重新组织角色阅读路径、知识/记忆系统模块导航、技术设计
  文档表格,全部指向 docs/core/user-guide/ 与 docs/concepts/
- docs/agents/knowledge-map.md "系统能力概览" 切换到新路径并新增"概念层
  (Concepts)"段集中索引 020/025/026/030/035/036/037 与 schema/ 目录;
  修正 RFC 占位段中失效的 docs/schema/ 引用
- docs/core/user-guide/faq.md 文档导航表(链接 + 路径双列)同步更新
- docs/concepts/README.md 新增"子系统专项文档"段集中索引 025/026/035/036/037
  与 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>

* refactor: 更新模块交叉引用与代码注释至 concepts 新路径;

- docs/wiki/ops.md 头部与 §12 架构依据切换到 concepts/035-the-knowledge-base.md
- docs/core/user-guide/papers-curation.md 注释中 docs/knowledge-graph/overview.md
  更新为 docs/concepts/036-the-knowledge-graph.md
- docs/agents/issue.md ISSUE-016 第 6 项历史记录追加迁移后路径注释
- Python 代码注释引用同步更新:
  - apps/negentropy/tests/performance_tests/knowledge/test_search_performance.py
  - apps/negentropy/src/negentropy/db/migrations/versions/0007_*.py
  - apps/negentropy/src/negentropy/db/migrations/versions/0008_*.py
  - apps/negentropy/src/negentropy/knowledge/retrieval/repository.py
- apps/negentropy/src/negentropy/config/config.default.yaml Memory Phase 5
  契约引用切换到 concepts/025-the-memory-system.md 与 026-memory-whitepaper.md

🤖 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(concepts): 为新移入子系统文档补齐 docusaurus front-matter;

- 025 the-memory-system: sidebar_position=2.5(紧邻 020 the-hippocampus)
- 026 memory-whitepaper: sidebar_position=2.6
- 035 the-knowledge-base: sidebar_position=3.5(紧邻 030 the-perception)
- 036 the-knowledge-graph: sidebar_position=3.6
- 037 federated-kg: sidebar_position=3.7
- 统一补齐 id / title / last_update / tags,与 020/030 现有风格对齐
  确保 docusaurus 侧边栏排序:020 → 025 → 026 → 030 → 035 → 036 → 037 → 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>

* refactor(docs): 补修迁移过程中遗漏的跨目录引用;

- docs/concepts/036-the-knowledge-graph.md §5.3.2 中 issue.md 链接深度修正
  ../../agents -> ../agents
- docs/core/user-guide/memory-troubleshooting.md 末尾代码引用深度修正
  ../../apps -> ../../../apps(顺手修复历史坏链)
- docs/core/design/skills.md 头部引用 skills-paper-hunter.md
  从 ../../knowledge/user-guide/ 调整为 ../user-guide/
- docs/agents/issue.md ISSUE-015 历史记录中两处指向 knowledges.md 的链接
  同步切换到 ../concepts/035-the-knowledge-base.md 锚点

🤖 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(docs): 迁移 docs/cognizes 至 docs/reference/cognizes 命名空间; (#601)

延续 cognizes/engine (#597)、cognizes/teaching (#598)、cognizes/research
(#596)、knowledge·memory (#600)、perceives (#599) 系列目录熵减,将 docs/cognizes
整体上挂到 docs/reference 命名空间下。

子目录历次上提后,docs/cognizes 仅余 3 篇项目级文档(PRD / 实施计划 / 任务清
单)、1 个音频转录目录与 1 个 SQL Schema 目录,已不具备「应用边界」语义。作为面
向全项目的「外部参考资料」,归属应与 docs/reference/perceives 并列,形成
architecture / concepts / research / reference 等顶层目录的清晰边界。

本次定位为纯结构性迁移,仅修复因迁移本身导致失效的引用,不顺手扩散范围(沿用
#599 的执行口径)。

变更范围

- 目录搬迁:git mv docs/cognizes -> docs/reference/cognizes(9 文件 + audio/、
  schema/ 两个子目录,R100 rename 模式保留 blame 与 history)
- docs/reference/cognizes/readme.md:8 处 ../concepts/... 升格为
  ../../concepts/...,补齐迁移后多出一级的上溯深度(指向 000-roadmap、
  001-task-checklist、010-the-pulse 等 Cognizes Engine 概念文档)
- docs/agents/knowledge-map.md:按 AGENTS.md「文档目录变更时即时同步」硬性要
  求,新增「项目级 PRD / Plan / Checklist」分节,指向迁移后的 PRD / Implementation
  Plan / Task Checklist
- pre-commit 自动补齐 audio/context-engineering 英文转录末尾换行

不在本 PR 范围(已识别但单独工单集中处理)

- docs/cognizes/readme.md 中 docs/000-... 形式的 docusaurus-root 风格路径
  (line 1-3、20-37):迁移前即为相对路径下损坏链接,与本次深度变化无关
- docs/concepts/020-the-hippocampus.md:143 的 ../002-task-checklist.md:迁移前
  即解析至不存在的 docs/002-task-checklist.md,属历史死链
- 001-implementation-plan.md / 002-task-checklist.md「参考文档」表格中的静态文
  本 docs/000-prd-architecture.md 等:属人工书写的相对索引文本(非 Markdown
  link),按 AGENTS.md「Direct Hyperlinking」单独工单修复

代码层零影响:grep -rn "docs/cognizes" apps/ tests/ scripts/ 返回空集;
apps/cognizes/、src/cognizes/ 是 Python 包名而非文档路径,不受迁移影响。
.github/workflows/*cognizes* 命中的都是 apps/cognizes/ 测试 workflow,与 docs/
路径解耦。

验证

- git status:9 个 R100 rename + readme.md 内容修改 + knowledge-map.md 修改
- grep "docs/cognizes" docs/ apps/ tests/ scripts/(排除 apps/cognizes、
  src/cognizes 包名):0 残留
- 严格匹配 [^/]\.\./concepts/ 在 readme.md:0 行;../../concepts/:8 行
- pre-commit run --files docs/reference/cognizes/readme.md
  docs/agents/knowledge-map.md:全 Passed

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

* refactor(ui-nav): 移除 Memory/Interface 二级导航中重复的 Dashboard 入口; (#602)

Memory 与 Interface 的二级导航各自包含一个 Dashboard Tab,且均直接跳转到
Home 模块下的 /dashboard 页面,造成跨模块边界的重复入口与认知摩擦。

收敛 Dashboard 入口至 HomeNav,恢复模块边界单一职责:
- MemoryNav 二级导航保留 Timeline / Facts / Audit / Conflicts / Automation 五项;
- InterfaceNav 二级导航保留 SubAgents / MCP / Skills / Tools(admin 角色额外
  含 Models / Task Models);
- 移除 isActive 中针对 /dashboard 的特例分支,沿用 pathname.startsWith 与
  KnowledgeNav 等同级模块保持一致;
- 同步更新 InterfaceNav 单测与 memory-pages e2e 的标签数量与顺序断言。

不改动 HomeNav、app/memory/page.tsx、app/interface/page.tsx 与
config/navigation.ts,主导航与 /dashboard 路由本身完全保留。

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

* refactor(docs): 迁移 docs/wiki 至 docs/reference/wiki 命名空间; (#603)

延续 perceives (#599)、cognizes (#601)、knowledge·memory (#600) 系列目录熵
减,将 docs/wiki 整体上挂到 docs/reference 命名空间下,与 reference/perceives、
reference/cognizes 并列形成 architecture / concepts / research / reference 等
顶层目录的清晰边界。本次定位为纯结构性迁移,仅修复因迁移本身导致失效的引用,
不顺手扩散范围(沿用 #599 / #601 的执行口径)。

变更范围

- 目录搬迁:git mv docs/wiki -> docs/reference/wiki(4 文件 + design/、
  reports/、user-guide/ 三个子目录,R100 rename 模式保留 blame 与 history)
- docs/reference/wiki/ops.md:5 处「上行」相对链接补齐迁移后多出一级的上溯
  深度(../architecture、../concepts、../agents -> ../../architecture、
  ../../concepts、../../agents)
- docs/reference/wiki/design/knowledge-graph.md:12 处 ../../../apps/... 升格
  为 ../../../../apps/... + 1 处 ../../agents/browser-validation.md ->
  ../../../agents/browser-validation.md
- docs/reference/wiki/user-guide/publishing.md:2 处出仓引用补齐 +1 上溯(指
  向 docs/user-guide.md 与根 CHANGELOG.md);同目录 ../ops.md 同步上移无需改
- docs/reference/wiki/reports/agents-validation.md:经核验无内部相对链接,
  R100 纯重命名
- 外部引用修复(5 文件):docs/user-guide.md、docs/core/user-guide/faq.md、
  docs/agents/knowledge-map.md、docs/agents/issue.md、
  docs/concepts/035-the-knowledge-base.md 中指向 docs/wiki/... 的 Markdown
  链接(及 faq.md 表格说明列的纯文本指针)按 wiki -> reference/wiki 前缀替换
- apps/negentropy/src/negentropy/db/migrations/versions/0007_catalog_singleton_phase_a.py
  第 29 行注释 docs/wiki/ops.md §12 runbook -> docs/reference/wiki/ops.md
  §12 runbook,确保 ops 操作指引指向有效路径(Alembic migration 已落库不
  重跑,零运行时影响)

不在本 PR 范围(已识别但单独工单集中处理)

- CHANGELOG.md 历史条目中的 docs/wiki/... 纯文本引用属变更日志事实记录,
  按 #599 / #601 先例不回溯修改(保留历史现场)
- docs/agents/issue.md 历史 issue 描述中作为「事故现场快照」的纯文本路径,
  按「静态文本相对索引」规则不属本次范围;本次仅修复 Markdown 链接 + 第
  402 行明确指向 SSOT 的纯文本指针

代码层零影响:grep -rn "docs/wiki\|\.\./wiki/\|\./wiki/" docs/ apps/ tests/
scripts/(排除 CHANGELOG.md 与 apps/negentropy-wiki/、wiki-api/wiki_dao/
wiki_service 等代码模块名)返回 0 残留。

验证

- git status:4 个 R100 rename + 6 文件内容修改(迁移文件 3 + 外部引用 5 -
  agents-validation.md 仅 R100 + alembic 注释 1,去重后等于)
- grep "docs/wiki" docs/ apps/ tests/ scripts/(排除 CHANGELOG 与代码模块
  名):0 残留
- uv run pytest apps/negentropy-perceives/tests/unit/test_docs_user_guide.py
  apps/negentropy-perceives/tests/unit/test_docs_configuration.py -v ->
  31 passed(含 TestRelativeLinks::test_all_relative_links_resolve)
- uv run pre-commit run --files [10 个变更文件] -> 全 Passed(含 ruff
  format / lint、trim trailing whitespace、fix end of files 等通用代码卫生)

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

* refactor(observability): 统一 Langfuse 模型上报口径为 vendor/model; (#604)

将 observability_model_name() 由「剥 vendor 前缀输出裸名」反转为「补齐/保留
vendor 前缀输出 vendor/model 全名」,消除 Langfuse Model Costs 视图同一模型被
拆成「gpt-5-mini」「openai/gpt-5-mini」多行的脏数据。

- model_names.py: observability_model_name 新增 vendor_hint 参数,提取
  _split_vendor_and_bare 拆 vendor/裸名,algorithm 改为「拆 → 剥日期 → 别名
  → 拼回 vendor/bare」;保持幂等与「未知模型保持原样」契约。
- instrumentation.py: _apply_model_normalization 用 request 侧 vendor 作为
  跨字段 vendor_hint,解决「gemini/text-embedding-004」request 与裸名 response
  被家族前缀表分别识别成 gemini / openai 的歧义。
- instrumentation.py: _resolve_total_cost 显式切到 pricing_lookup_model_name
  保持「定价路径走裸名」契约,与观测路径解耦。
- test_model_names / test_instrumentation / test_genai_semconv: 同步反转所有
  断言;新增 vendor_hint 覆盖、跨字段 embedding 一致性、unknown model bare
  passthrough 用例。
- docs/agents/issue.md: 追加 2026-05-21 决策反转补丁说明,记录 SoT 形态选择
  的工程教训。

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

* refactor(docs): 迁移 docs/concepts 至 docs/reference/cognizes/engine 命名空间 (#605)

* refactor(docs): 迁移 docs/concepts 至 docs/reference/cognizes/engine 命名空间;

延续 #597 / #598 / #599 / #600 / #601 系列目录熵减,把 #597 上提到顶层
docs/concepts 的 Cognizes Engine 概念稿(P1-P5 + Memory/Knowledge/KG 子系
统稿)下沉为 docs/reference/cognizes/engine/,与同级 PRD / Implementation Plan
/ Task Checklist + audio/ + schema/ 形成统一的 Cognizes 参考资料命名空间,恢复
docs/concepts 顶层语义中性(本次后该目录从工作树消失)。

变更范围

- 目录搬迁:git mv docs/concepts -> docs/reference/cognizes/engine
  (17 md + schema/*.sql 共 22 个文件,R100 rename 模式保留 blame 与 history)
- 迁移内文件按深度 +2 规则修复 109 处可解析向上链接(../X -> ../../../X
  与 ../../X -> ../../../../X),覆盖 ../research/、../core/user-guide/、
  ../architecture/、../wiki/、../agents/、../../apps/、../../AGENTS.md
- docs/reference/cognizes/readme.md:8 处 ../../concepts/ 升格为 ./engine/
  (新 engine/ 子目录与 readme.md 为父子关系)
- docs/agents/knowledge-map.md:18 处 ../concepts/ -> ../reference/cognizes/engine/
- docs/core/user-guide/{faq,memory-basics,memory-troubleshooting,memory-integration,
  knowledge-management,papers-curation}.md:11 处 ../../concepts/ 升格
- docs/agents/issue.md / docs/wiki/ops.md:4 处带 anchor 的链接迁移
- docs/i18n/zh-CN/README.md:3 处 ../../concepts/ 升格
- docs/user-guide.md:5 处 ./concepts/ -> ./reference/cognizes/engine/
- 仓库根 README.md:3 处 ./docs/concepts/ -> ./docs/reference/cognizes/engine/
- 代码层注释(性能测试 / config.default.yaml / repository.py /
  0007、0008 migrations):5 处路径文本升格,零行为变更
- 迁移内残余静态文本修复:025 §DDL 原型行、040 §6.3 交付物清单文档行、
  hippocampus_schema.sql 头注释,统一指向新路径

不在本 PR 范围(沿用 #601 policy,单独工单处理)

- 历史死链 ../../research/...(解析至 repo root,无此目录)、../tests/、
  ../.github/、../../src/cognizes/...:迁移前即为死链,保留现状
- docs/reference/cognizes/readme.md 顶段与 001-implementation-plan.md /
  002-task-checklist.md 中 docs/X.md 形式 docusaurus-root 风格路径文本:与
  本次迁移无关,独立 Direct Hyperlinking 工单
- apps/negentropy/.../perception.py:7 与 engine/025-the-memory-system.md:1785
  的 github.com/.../docs/concepts/X.md 永久 URL:跨仓库快照,保留

验证

- grep -rn "docs/concepts" docs/ apps/ tests/ scripts/ .github/ README.md
  AGENTS.md(排除 GitHub URL):0 残留
- grep -rn "[/(]\./concepts/\|\.\./concepts/\|\.\./\.\./concepts/" docs/
  --include="*.md":0 残留
- 抽样解析 5+ 条关键路径(readme.md -> ./engine/000-roadmap.md、
  knowledge-map.md -> ../reference/cognizes/engine/README.md、user-guide.md ->
  ./reference/cognizes/engine/035-...、025 -> ../../../../apps/.../memory.py
  等)均落到实际文件
- uv run pre-commit run --files:trim-whitespace / fix-eof / check-yaml /
  ruff-lint / ruff-format 全 Passed
- 代码层零行为变更:本次仅命中 Python docstring / YAML 注释 / SQL 头注释
  中的路径文本

🤖 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(cognizes-engine): 修正 README 参考文献区 _Source_ 标签与 URL 不一致;

延续 #602 的 docs/concepts -> docs/reference/cognizes/engine 命名空间迁移,
补齐 docs/reference/cognizes/engine/README.md §参考文献 (Bibliography) 的
4 处 `_Source_` 行(L819 / L821 / L828 / L830)。

问题
- 迁移机械化更新了链接 URL `../research/X.md -> ../../../research/X.md`,
  但代码块内的可见路径标签 `[`../research/X.md`](...)` 未同步更新,导致
  「标签即真实相对路径」自解说不变量被打破。
- 现状下,读者/后续编辑者按标签的 `../research/` 推断会落到错误的 docs/
  reference/cognizes/research/,与 URL 实际指向的 docs/research/ 不一致;
  机械式扫描型工具与人工 review 都易被误导。

修复
- 同步刷新 4 行的标签文本到 `../../../research/X.md`,恢复「标签 ===
  URL」镜像;解析后 readlink -f 仍落到 docs/research/{034 / 020 / 034a
  / 020a}*.md 实际文件,零行为变更。

…
ThreeFish-AI added a commit that referenced this pull request Sep 6, 2026
* build(deps): travel-agent-ui 升级 next 16.2.12 并补齐 workspace 隔离声明,修复 9 项 alert;

- next / eslint-config-next 16.2.6 → 16.2.12,核销 Dependabot #574-582:
  SSRF(GHSA-89xv-2m56-2m9x / GHSA-p9j2-gv94-2wf4)、中间件绕过(GHSA-6gpp-xcg3-4w24)、
  Server Actions DoS(GHSA-m99w-x7hq-7vfj)等 9 条;修复门槛为 16.2.11,取 16.2 线
  最新补丁 16.2.12 以多带一版累积修复,不跨 minor 避免无关框架行为变更
- 补齐 `packages: []` 的 pnpm-workspace.yaml——本工程已从根 workspace 解耦但缺失隔离
  声明,是 ISSUE-175 所列同款入口中全仓最后一个敞口。本次恰好改动其 manifest,正是
  事故链第一环(改嵌套 manifest → 顺手 install → 根 lockfile 静默被覆写),故一并钉死
- 本工程无 lockfile、不被任何 workflow 构建,改 manifest 即生效:本批未执行任何
  pnpm install/add/update,根 pnpm-lock.yaml sha1 校验前后一致(06e898b1,13098 行)

🤖 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>

* build(deps): 根 workspace 三 importer 升级 next 16.2.12 + faker 10,修复 28 项 alert;

- next / eslint-config-next 16.2.6 → 16.2.12(negentropy-ui / negentropy-wiki /
  cognizes-ui):核销 #583-591 / #592-600 / #565-573 共 27 条,覆盖 SSRF、中间件绕过、
  Server Actions DoS、缓存混淆、Image Optimization DoS 等;修复门槛 16.2.11,取 16.2 线
  最新补丁多带一版累积修复
- @faker-js/faker ^9.0.0 → ^10.5.0(实解 10.6.0),核销 #687GHSA-qxc2-j82w-r537,
  helpers.fake 可被利用为任意代码执行,<=10.4.0 全线受影响故 9.9.0 亦在范围内)。
  跨大版本但唯一调用点 tests/ui/helpers/factory.ts 仅用 string.uuid / person.fullName /
  helpers.arrayElement / date.* / number.int / lorem.*,与 v10 移除清单零交集
- lockfile 完整性核对(ISSUE-175 教训):overrides 块 17 条全在、importers 5 个不变、
  next 两条 @babel/core peer 变体链(7.29.7 / 8.0.1)均保留、`@babel/core` override
  上界 `>=7.29.6 <8.0.0` 未放宽;净减 70 行系 @babel/core 获得 (supports-color) peer
  后缀导致的键合并,非依赖丢失;`pnpm install --frozen-lockfile` 通过

验证:cognizes-ui lint 0 error + tsc --noEmit 通过 + test:coverage 28 passed(含
faker 三个消费测试)+ build 通过;negentropy-ui lint(--max-warnings=0)+ typecheck +
build 通过;negentropy-wiki lint 0 error + build(含 pagefind 索引)通过。

🤖 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>

* build(deps): cognizes 九包定向升级消 47 项 alert,新增四条传递依赖地板;

- 直接依赖抬地板:pypdf 6.13.3→6.17.0(10 条 DoS/无限循环/内存耗尽)、
  pillow 12.2.0→12.3.0(13 条堆越界写/解压炸弹/命令注入)
- gpu 组抬地板:transformers 5.8.1→5.16.1(CVE-2026-9856 save_pretrained 路径穿越)、
  torch 2.12.0→2.14.0(CVE-2025-3000 torch.jit.script 内存破坏)。无上界阻断:
  sentence-transformers 5.5.0 仅要求 transformers<6.0.0 且不约束 torch
- constraint 抬升 cryptography 49.0.0→50.0.1(GHSA-g6cj-pr64-35w5 Bleichenbacher oracle)
- constraint 新增四条传递依赖地板:gitpython 3.1.50→3.1.61(18 条 git option/配置注入
  RCE 与任意文件读写;travel-agent-demo → streamlit 传递,本仓零 `import git`)、
  pyasn1 0.6.3→0.6.4(3 条 BER/CER/DER 解码器 DoS)、httplib2 0.31.2→0.32.0
  (解压炸弹 DoS)、setuptools 81.0.0→84.0.0(CVE-2026-59890 MANIFEST.in 绕过)
- 定向升级(--upgrade-package ×9)而非全量 --upgrade:lock 仅动 435 行且 docs 组
  零位移(mkdocs/pymdown 变更 0 行),保持可 review 与可归因

验证:ruff check/format 通过(207 文件);pytest tests/unittests/ 225 passed 2 skipped、
覆盖率 30.98% 过 20% 门;uv build + import cognizes 通过;六包运行时版本实测达标。
integration 套件 13 failed/110 passed —— 已用 git stash 在同一环境对拍确认与本次改动
无关(干净树同为 13 failed/110 passed,根因是 TracingManager.span 属性缺失与
tests/integration/mind 下 test_e2e.py 同名 basename 收集冲突,均为既存问题)。

已知验证边界:transformers/torch 的一手调用在 engine/perception/reranker.py,该模块
无单测。已尽力覆盖到 API 契约层——模块本身导入通过,且逐项验证 rerank() 实际调用的
AutoTokenizer/AutoModelForSequenceClassification.from_pretrained、tokenizer 四个 kwargs
(padding/truncation/max_length/return_tensors)、SequenceClassifierOutput.logits 路径与
torch.no_grad/sigmoid 在 5.16.1 下均存在;未验证真实模型推理(需下载 bge-reranker-base)。

🤖 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>

* build(deps): 删除 cognizes 死配置 docs 依赖组,从根消除 3 项 alert;

- 移除 [dependency-groups] docs(mkdocs / mkdocs-material / mkdocstrings),核销
  #692(mkdocs-material DOM XSS)与 #618/#663(pymdown-extensions 路径穿越 + ReDoS)
- 判定为死配置的三项证据:① 全仓零 mkdocs.yml;② CI 从不安装该组
  (setup-python-uv 仅 `uv sync --group dev`),亦无任何 workflow/脚本引用;
  ③ src/ + tests/ + scripts/ 零 mkdocs 引用。项目文档站实为 negentropy-wiki(Docusaurus)
- 相较升版本,删组从根消除这两个包及其 12 个传递依赖,同类告警不再复发
- lock 为纯删除(-215 行、0 插入),移除项全部属 mkdocs 依赖闭包,无其它包位移

验证:uv sync --frozen --group dev 通过;import cognizes 通过;
pytest tests/unittests/ 225 passed 2 skipped——与删组前逐项一致,佐证该组无运行时作用。

🤖 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>

* build(deps): negentropy 四包定向升级消 8 项 alert,补 setuptools 传递依赖地板;

- override 抬升 aiohttp 3.14.1→3.14.3:新增修复 GHSA-cq5v-8q36-5273(C 响应解析器
  堆越界读)与 GHSA-mfx4-hv73-q22v / GHSA-mq44-7p77-q5h7(WebSocket 请求走私/未协商
  压缩帧),核销 #641/#643/#645。override 机制不变:microsandbox==0.1.8 锁死 <3.11.0
  仍需强制覆盖,只抬地板版本
- constraint 抬升 cryptography 49.0.0→50.0.1:GHSA-g6cj-pr64-35w5(PKCS#7
  EnvelopedData 解密暴露 Bleichenbacher oracle,high),核销 #648。全仓零一手 import
  (authlib/google-auth/joserfc/presidio/pyjwt/pyopenssl 传递),且 perceives 已在
  50.0.1 上验证过同构依赖者集合
- constraint 抬升 pyasn1 0.6.3→0.6.4:BER/CER/DER 解码器 3 条 DoS
  (GHSA-m4p7-r5rc-7g4j / GHSA-hm4w-wwcw-mr6r / GHSA-8ppf-4f7h-5ppj),核销 #559/#560/#626
- constraint 新增 setuptools>=83.0.0(82.0.1→84.0.0):CVE-2026-59890(MANIFEST.in
  排除规则被 Unicode 归一化绕过),核销 #558。此前无任何声明,经 spacy/thinc 传递
- 定向升级:lock 仅动 6 行;pyopenssl 26.3.0→26.4.0 随 cryptography 联动

验证:alembic 单 head(0099);pytest tests/unit_tests/ 2941 passed、覆盖率 57.04%
过 50% 门;四包 import smoke 版本达标。integration 套件本地 116 failed/115 passed/
90 errors——已对拍干净树基线逐项一致(共享 negentropy_test 累积脏数据所致的既存
环境问题,见记忆 test-db-accumulates;CI 每次起新容器不受影响),与本次改动无关。

🤖 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>

* build(deps): negentropy mcp 1.26.0→1.29.1,修复 3 项 http-transport alert;

- mcp 地板 >=1.6.0 → >=1.28.1,<2.0.0:核销 #501/#503/#505CVE-2026-52869/52870/
  59950,MCP SDK http-transport 攻击面)。上界 <2.0.0:2.x 拆出 mcp-types/truststore
  属未验证 major 迁移(uv 默认解 2.1.1,已退回 1.x 线);alert 门槛 1.28.1,perceives
  实跑 1.28.1,本批实解 1.29.1(1.x 线最新)。idna 3.16→3.19 随 mcp 子树联动
- 一手调用面 3 处(interface/mcp_client.py 三种传输、knowledge/mcp_server.py 的
  FastMCP/StreamableHTTPSessionManager/TransportSecuritySettings、engine/sandbox/mcp.py),
  依赖要求逐条核对全部满足,与 aiohttp 完全解耦(mcp 走 httpx)

三层验证(对齐 ISSUE-092 的 CVE-2026-4372 验收范式):
① 符号 + 真实构造——stdio 私有 API 7 符号(mcp_client.py 8 处引用)全在;
FastMCP 四 kwargs(stateless_http/json_response/streamable_http_path/transport_security)
真实构造出 Starlette app;get_kb_mcp() 与 sandbox 构造路径不 mock 直接过
② 定向单测 22 用例(test_mcp_client 5 + test_mcp_client_resources 4 +
test_kb_mcp_server 13)全过;全量单测 2941 passed、覆盖率 57.04% 过门(与升级前逐项一致)
③ 真实 MCP 往返(合入前置)——httpx.ASGITransport 直打 create_kb_mcp_asgi_app():
tools/list 返回 200 且含 kb_search 工具清单;错误 bearer 401 拒绝。覆盖单测完全
mock 掉的 StreamableHTTPSessionManager.run() + stateless 路径(1.28+ 改动最多处)

🤖 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(perceives): 纠偏 transformers/torch/setuptools 锁定根因,裁剪 6 条失效 ignore 并升级 datasets;

- transformers 锁定根因纠偏(pyproject [tool.uv] 注释):旧述「marker-pdf 1.10.2 /
  surya-ocr 0.17.1 在 5.x 崩(transformers.onnx)」已不成立——marker-pdf 2.0.0 /
  surya-ocr 0.22.1 均已适配 transformers>=5.12.1。真实阻断是二者同时要求 pillow<11,
  与本项目 pillow>=12.3.0(修 8 条图像解析 CVE)直接冲突;perceives 直接解析不可信
  PDF/图片故 Pillow 攻击面可达,而 transformers 零直接 import、仅加载第一方 artifact
  故不可达——升级属负收益交换。mineru 3.0.9 的 transformers<5.0.0 仅 vlm/pipeline
  extra 生效,不构成约束
- 解锁条件迁移:从「等 marker/surya 适配 transformers 5.x」改为「等二者放开
  pillow<11 上界」——跟踪对象不同,否则后来者会困惑「已适配为何仍锁」
- torch CVE-2025-3000 纠偏:upstream fix 2.13.0 已发布(原注释「暂无 fix」过时),
  改述为「有 fix 但受 marker/surya/docling-ibm-models/torchvision 四方联动约束」
- setuptools pin 注释纠偏:原述「undetected-chromedriver 依赖 pkg_resources」已证伪
  ——实测 82.0.1 与 83.0.0 皆无 pkg_resources(上游早于 82 移除,复核 ISSUE-092
  隔离结论)。维持 82.0.1:不为不可达 build-time 低危变更 build 后端版本
- 裁剪 6 条失效 ignore:fastmcp(CVE-2025-64340/CVE-2026-27124)与 litellm
  (CVE-2026-35029/35030、GHSA-69x8-hrgq-fjj8CVE-2026-42271)注释停留在 3.1.1/1.80.0,
  实锁已 3.2.4/1.85.0。实跑 pip-audit 确认两包零命中后删除,非凭版本号推断
- datasets 4.8.5→5.0.1:本次裁剪后暴露的新 advisory CVE-2026-66007(PYSEC-2026-3716,
  folder-based dataset builder 路径穿越任意文件读)。mlx-vlm 仅要求 >=2.19.1 无上界,
  故直接升级而非新增 ignore 债

验证:ignore 数组经 bash -n 语法校验(56 条);以 CI 原样命令复跑 pip-audit
退出 0——「No known vulnerabilities found, 10 ignored」;CI 参数复跑测试
(-n auto -m "not slow")2130 passed,docling/mineru/marker 三引擎 worker 均真实
启动;mlx-vlm 在 datasets 5.0.1 下 import 通过。3 个 test_config 失败已对拍干净树
基线一致(本地 .env 使 concurrent_requests=32≠默认 16,CI 无该文件),与本次无关。

🤖 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(issue): ISSUE-092 增补 perceives 4 条 dismiss 依据与 transformers 解锁条件迁移;

- 记录 104 条 alert 人工核销的收口:100 条经升级消除,perceives 4 条走 dismiss
- transformers 锁定根因纠偏:marker-pdf 2.0.0 / surya-ocr 0.22.1 已适配
  transformers>=5.12.1(旧「transformers.onnx 崩溃」不再成立),真实阻断是二者
  要求 pillow<11 与本项目 pillow>=12.3.0 冲突;附攻击面可达性对比论证
  (Pillow 可达 vs transformers 不可达)说明升级为负收益交换
- 解锁条件从「等适配 transformers 5.x」迁移为「等放开 pillow<11 上界」,
  避免后来者按旧条件追踪而困惑
- torch CVE-2025-3000 状态迁移留档:upstream fix 2.13.0 已发布,原「暂无 fix」
  记录作废;此例印证本 Issue 既有防范条款「四元注释便于季度 review 识别可移除项」
- 记录本次 ignore 清单 review 结果(62→56 条)与 datasets 升级替代新增 ignore 的处理
- 沉淀三条方法论:「上游已适配≠可升级」须核对全部约束维度、安全债决策应比较
  攻击面可达性而非 CVSS 分数、ignore 注释的「阻断原因」腐化快于 CVE 本身

🤖 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(travel-agent-ui): 补 allowBuilds 修复隔离 workspace 下 pnpm install 退出 1;

上一提交把本工程钉成独立 pnpm workspace 根以阻断根 lockfile 覆写,但漏声明
allowBuilds——原生构建许可原本继承自根 workspace,隔离后不再传递。

实测(pnpm 12.2.1,本目录完整 pnpm install):Error: ERR_PNPM_IGNORED_BUILDS,
被拦 @scarf/scarf / esbuild / sharp / unrs-resolver,退出码 1,且 pnpm 会往
pnpm-workspace.yaml 回写 "set this to true or false" 占位;根 pnpm-workspace.yaml
所载的 `cd … && pnpm install && pnpm dev` 因此卡在第一步。

注:作者侧大概率以 --lockfile-only 验证,该模式不执行构建脚本故退出 0,恰好掩盖此失败。

- 补齐四条许可,取值与根 workspace 一致(@scarf/scarf 保持 false,同为隐私考虑)
- 未纳入根侧 msw:本工程不依赖,遵循最小声明
- 注释指向修正:原「运行方式见同目录 README.md」——该 README 为 create-next-app
  原始样板,无 install 步骤亦未提隔离 workspace,改为就地写明安装运行命令

验证:修复后 pnpm install 退出 0、IGNORED_BUILDS 零命中;根 pnpm-lock.yaml 逐字节未变,
隔离目标保持有效;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(perceives): 同步 pip-audit ignore 注释至纠偏后口径并订正 ISSUE-092 计数;

本分支已论证 transformers 锁定 <5.0.0 的真实阻断是 marker-pdf 2.0.0 / surya 0.22.1
要求 pillow<11,而非旧记的「marker-pdf / docling 兼容交集」;setuptools 保持 82.0.1
的理由亦已由「undetected-chromedriver 依赖 pkg_resources」改写为「已证伪」。但 CI
ignore 清单中的四处注释仍停留在旧口径,与 pyproject、issue.md 相互矛盾。

CVE-2026-9856 条已承载完整根因,其余三处改为指针式引用,避免同一结论多处维护:

- PYSEC-2025-211..218 / CVE-2026-4372 / PYSEC-2026-2290:删除「docling 兼容交集」
  归因,统一指向 CVE-2026-9856 条;CVE-2026-4372 的「待交集支持 5.3.0+ 后升级」
  同步改为「待 marker-pdf / surya 放开 pillow<11 上界」
- PYSEC-2026-3447:交叉引用由「见 pyproject,undetected-chromedriver 相关」改为
  「见 pyproject setuptools 注释与 ISSUE-092 2026-09-06 增补」——照旧文跳转只会
  读到相反结论
- ISSUE-092:「ignore 条目 62→56」订正为 34→28。negentropy-perceives-ci.yml 是
  全仓唯一 --ignore-vuln 来源,实测本分支前 34 条、后 28 条(差值 6 正确,绝对值错位)

纯注释与文档变更,ignore 条目与 pip-audit 行为零改动。验证:YAML 解析通过;
--ignore-vuln 实测 28 条,与订正后的 issue.md 记载一致;注释行宽与既有块保持齐平。

🤖 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