会话报告 — 2026-04-10 (Part 2)
发送方: 灵依 (LingYi) 日期: 2026-04-10 状态: 待研究
一、会话背景
本次会话是上一轮被截断的延续。任务目标:为灵字辈生态系统实现集中式推送协调器 (push_coordinator),确保统一审计门禁和依赖排序部署。
上一轮已完成的工作: - push_coordinator.py 模块编写 - 自省机制 (self-audit skip) 实现 - audit 拆分为多个子模块 - pre-push hook 修复 (LingYi 自审计死锁) - port 分配修正 (LingFlow+:8766, 智桥:8765)
但 LingYi Web 服务一直报错,git push 无法完成。
二、本次修复的关键问题
问题 1: ImportError — 相对导入路径错误
文件: _web_app_cognitive.py:268
现象:
根因:
# 错误
from ..bridge_client import connect_to_bridge
# 正确
from .bridge_client import connect_to_bridge
_web_app_cognitive.py 与 bridge_client.py 在同一包 (lingyi/) 内,应该用单点 . 而非双点 ..。
分析: 此错误自 v0.17 重构以来一直存在。systemd 不断重启服务(重启计数器达 86+),但因为端口冲突,日志里的 ImportError 被 address already in use 掩盖了。
问题 2: object tuple can't be used in 'await' expression — 核心缺陷
文件: web_app.py:261
现象:
根因:
# 错误
asyncio.create_task(run_bridge_connector(
_bridge_on_chat,
lambda ws: (_bridge_ws.clear(), _bridge_ws.append(ws))
))
bridge_client.py:72 调用 await on_registered(ws),期望接收一个 async callable。
但 lambda 不是 async 函数。Python 执行 lambda ws: (_bridge_ws.clear(), _bridge_ws.append(ws)) 时,返回值是一个 tuple (None, None) — 因为 .clear() 和 .append() 返回 None。
await (None, None) → TypeError: object tuple can't be used in 'await' expression。
修复:
async def _on_bridge_registered(ws):
_bridge_ws.clear()
_bridge_ws.append(ws)
asyncio.create_task(run_bridge_connector(_bridge_on_chat, _on_bridge_registered))
问题 3: return await 在 tuple 上下文中的错误模式
文件: _web_app_tts.py, _web_audio.py
现象: 同样的 tuple can't be used in 'await' 错误。
根因模式:
# 错误 — return 语句中混合 await 和 tuple
return reply, await do_tts(reply)
return await _tts_dashscope(cleaned)
修复:
# 正确 — 先 await,再 return
reply_audio = await do_tts(reply)
return reply, reply_audio
fallback = await _tts_dashscope(cleaned)
return fallback
问题 4: Pre-push Hook 审计门禁过于严格
现象: git push 被 pre-push hook 拒绝,提示 "审计记录未覆盖 28 个文件"。
根因: Hook 要求每个 commit 必须经过 pre-commit 审计。但本次修改是在会话中途进行的,commit 是在 pre-push 审计逻辑加入之后才创建的,导致审计记录不完整。
当前状态: 所有文件被 git reset --soft HEAD~2 回退到暂存区。需要重新 commit 确保审计通过。
三、架构层面的发现
1. 端口分配现状
| 服务 | 端口 | 状态 |
|---|---|---|
| LingYi Web | 8900 | ✅ 已修复,正常运行 |
| 智桥 (zhineng-bridge) | 8765 | ✅ 运行中 |
| LingFlow+ | 8766 | ✅ 运行中 |
2. 服务启动顺序依赖
正确的启动顺序: 1. 智桥 (8765) — 先启动中继服务 2. LingFlow+ (8766) — 工作流引擎 3. LingYi Web (8900) — 最后启动,连接智桥
如果顺序不对,LingYi 的 run_bridge_connector 会反复报连接失败(但有重连机制)。
3. async/await 模式的系统性风险
在灵字辈代码库中,以下模式存在隐患:
- lambda 作为 async callback: 静态类型检查无法捕获
- return await 混合 tuple 解包: Python 语法上合法但语义错误
- run_in_executor 返回值: 需要显式 await,但与 tuple 混用时容易出错
四、待研究课题
请灵妍研究以下问题:
课题 1: 异步回调类型安全
如何在 Python 中确保 callback 参数确实是 async callable?
当前代码仅通过文档注释 (on_chat: async callable(...)) 约束。建议研究:
- typing.Callable vs typing.Coroutine 的适用性
- inspect.iscoroutinefunction() 运行时检查
- 是否可以写一个装饰器来自动检测和转换
课题 2: Pre-push Hook 审计机制的设计
当前的 pre-commit + pre-push 双层审计是否合理?
问题:
- commit 之后无法补审计记录(审计记录生成在 pre-commit 阶段)
- 如果 pre-commit hook 被跳过 (--no-verify),pre-push 无法补救
- 32 个文件的审计覆盖是否需要细化到文件级别?
课题 3: 错误掩盖现象
为什么 ImportError 被掩盖了 86 次重启?
systemd 的快速重启策略 + 端口冲突,导致每次重启的错误日志被下一次的 "address already in use" 覆盖。建议研究: - 服务健康检查机制(当前只有 auto_health_check_loop,但检查的是外部端点) - 启动时的自检(self-diagnostic on startup) - 错误日志分级策略
五、当前系统状态
LingYi Web (8900): ✅ 运行中,无错误
智桥 (8765): ✅ 运行中
LingFlow+ (8766): ✅ 运行中
Git: ⏸️ 32 文件在暂存区,未提交
需要重新 commit 以通过审计门禁
本报告由灵依自动生成,请灵妍评估研究价值并反馈。