# 项目文件治理计划 ## 当前会话任务:AgentBus 渠道独立根路径与 404 修复 - **状态:** 已完成;重复兼容记录清理和 listener 状态竞态修复均已加载运行。 - **问题事实:** 当前 `control-plane/src/server.ts` 和 `.build/control-plane/src/server.js` 已包含 `/api/channels`;此前的 404 是旧进程未加载路由。默认渠道改名后旧进程曾补建重复兼容渠道;随后 listener 重载又暴露出“内部重载被写成已停用”的异步状态竞态。 - **本轮边界:** 新增独立 `/channels` 管理页和页面路由;数据接口继续使用 `/api/channels`,渠道数据仍按当前管理员所属组织隔离;重复兼容记录只停用/隐藏,不物理删除。 ### 实施清单 - [x] 将 AgentBus 渠道面板从 AI 工作台移到独立 `/channels` 根路径。 - [x] 增加 `/channels` 静态页面路由、导航激活态和缓存版本号。 - [x] 保留 `/api/channels` CRUD/轮换接口并补充页面/路由契约测试。 - [x] 完成全量验证并记录旧进程需要重启后才能加载新路由。 - [x] 经用户授权重启控制面,验证 `/api/channels` 返回鉴权响应、`/channels` 返回 200、AgentBus session ready。 - [x] 在独立渠道目录中增加“维护名称”,默认兼容渠道也可改名。 - [x] 防止默认兼容渠道改名后重启生成重复渠道,并在启动时停用已产生的重复兼容记录。 - [x] 修复渠道重载时把内部 `stop` 异步写成“已停用”的竞态;重载只写连接中/已连接,真正停用仍由管理员操作或服务关闭触发。 - [x] 修复启动阶段同一渠道状态写入乱序;按渠道串行化 `connecting` → `connected` 状态落库。 - [x] 经用户授权重启控制面,验证王徐明、阿虹两个 listener 均 `enabled=true`、`connected=true`、`session_ready=true`。 ## 当前会话任务:多 AgentBus 用户渠道与插件串行队列 - **状态:** 已完成;用户已确认方案并授权开始实施。 - **目标:** 支持多个 AgentBus 来源/外部用户渠道,每个渠道独立保存 AgentBus key;插件/ERP 浏览器自动化同一组织同一时间只执行一个任务。 - **安全边界:** 不读取或输出真实密钥;不执行 ERP 写入、生产部署或外部业务发送;本轮服务重启已获用户明确授权并完成。 ## 已确认决策 1. **队列范围:** 同一组织的 ERP 浏览器自动化全局单槽;其他任务在服务端持久化 FIFO,按 `created_at,id` 排队。 2. **渠道边界:** 每个外部用户渠道拥有独立 AgentBus listener/WebSocket 连接和独立 key;渠道身份不创建后台登录账号,由管理员管理。 3. **可靠性:** 入站路由、受理通知和最终回执使用持久化 outbox;断线、进程重启或排队期间可重试,不因内存超时误报。 4. **配置:** WebSocket URL、client type、重连参数使用全局环境配置;渠道独立加密保存 key,可覆盖 bot address;旧的全局 token/bot 配置保留兼容。 5. **生命周期:** 渠道支持启用/禁用和 key 轮换,不做物理删除;禁用不清理已有任务和待发送回执。 6. **范围排除:** 不实现具体微信协议,不改变 Agent/Skill operation Schema,不做渠道级自动化策略。 ## 实施阶段 - [x] 读取项目记忆、业务登记表、相关 Skill/Schema/mapping/实现,并确认工作区脏改动需保留。 - [x] 新增 migration 012:`user_channels`、`tasks.channel_id`、`agentbus_deliveries`。 - [x] 新增渠道服务和 `AgentBusManager`:加密 key、CRUD/轮换、每渠道 listener、运行状态。 - [x] 接入 durable AgentBus:按渠道幂等、受理 outbox、终态回执 outbox、断线释放租约、重连补发。 - [x] 接入控制面 API 与操作台渠道管理;key 不回显。 - [x] 接入组织级 FIFO ERP claim、排队信息和平台自动派发单任务防护。 - [x] 同步配置示例、控制面文档、测试夹具及契约断言。 - [x] 完成计划压缩后的仓库卫生、全量测试、构建和差异检查。 ## 关键实现位置 - `control-plane/migrations/012_agentbus_user_channels.sql` - `control-plane/src/agentbus-channels.ts` - `control-plane/src/agentbus.ts` - `control-plane/src/task-service.ts` - `control-plane/src/server.ts` - `LianSyn-platform/app.js`、`index.html`、`styles.css` - `control-plane/README.md`、`.env.example`、`.env.production.example` ## 验证记录 - 已通过:控制面测试 53/53,含 listener 启动/重载状态回归和 durable channel listener 重投回归;`build`、`git diff --check` 通过。 - `check:repo`/`test:legacy` 当前仅被既有根目录 `.DS_Store` 和 `dist/老挝联泰AI指令表-0.5.118.docx` 哈希不一致阻断;这些用户既有文件未修改。`check` 已完成且无失败输出。 - 根目录活动计划压缩前完整快照:`archive/project-history/2026-08-17/task_plan-pre-compression-agentbus-channels.md`。 ## 当前风险与收口条件 - 无可用生产 PostgreSQL/AgentBus 真实连接时,仅验证迁移文本、静态契约、单元测试和构建;不以本地模拟代替真实部署授权。 - 若全量验证发现与本轮无关的既有脏改动问题,只记录并保留,不回退用户改动。 - 所有源码验证和运行态检查已完成;清理采用停用/隐藏,不物理删除;未执行 ERP 写入、部署或外部发送。 ## 当前会话任务:插件单任务/历史任务超时自愈 - **状态:** 已完成;源码、发布包、运行态重启、历史任务收口和回归验证均已完成。 - **目标:** 插件实际领取任务后 10 分钟无最终结果自动失败;历史任务超过 30 分钟无处理进展退出活动队列,避免单条卡死任务永久阻塞组织级 ERP 槽位。 - **安全边界:** 不自动重试可能已跨过 ERP 写入边界的任务;历史任务只做失败标记和队列释放,保留回查证据;本轮未主动发起 ERP 写入。 ### 实施清单 - [x] 明确并实现单任务 10 分钟结果超时与租约释放。 - [x] 明确并实现历史任务 30 分钟维护超时与活动执行槽解耦。 - [x] 为 `no_erp_write` 与可能已写入 ERP 两类结果保留不同安全路径。 - [x] 增加控制面、插件和队列回归测试,覆盖幂等、断线和重复清理。 - [x] 完成插件构建/版本同步及可恢复运行态清理;运行态检查未发现可清除任务,未删除不确定写入历史。 - [x] 修复历史维护查询的 `42P10` 错误,并立即收口 15 条超过 30 分钟的 `reconciliation_pending` 任务。 - [x] 运行项目规定的完整检查、测试和构建。 ### 交付与运行态备注 - 控制面已按用户授权优雅重启,当前进程 PID `93460`;两个 AgentBus 会话均已 `session_ready`,重启后未再出现 `error_42p10` 或回调上下文错误。 - 历史 15 条任务已自动失败并释放执行队列;当前数据库中超过 30 分钟仍处于 `reconciliation_pending` 的任务为 0 条,未删除任何回查证据。 - 当前 Chrome 运行时清理入口已执行并返回 0 个运行中超时、0 个孤儿任务、0 个被清除的当前指针;此前浏览器心跳报告扩展版本 `0.5.132` 且状态 `connected`,当前发布插件已递增到 `0.5.133`。 - 用户本次测试任务已由持久化结果记录为 `completed`,AgentBus accepted/result 均为 `delivered`;该任务自身结果记录 `write_attempted=true`,不将其误报为“未写 ERP”。 - 当前发布插件为 0.5.133,发布清单和版本化 ZIP 已同步;不确定是否已跨 ERP 写入边界的历史任务只退出活动槽,不自动重试或删除证据。 ### 已确认决策 1. 单任务 10 分钟计时从插件实际领取并开始执行起算,不从 AgentBus“已受理”或服务端排队起算。 2. 历史维护超时为 30 分钟;超时任务不自动重跑。 3. 明确未写 ERP 的任务可失败并释放执行槽;可能已写入 ERP 的任务保留回查保护,但不能永久占用新任务活动槽。 ### 错误记录 - 首次追加本阶段计划时使用了不存在的旧上下文行,补丁未应用;随后改为以文件末尾现有内容为锚点,未产生部分修改。 - 本轮首次追加团队文件回传计划时沿用了已压缩文件中的错误锚点,补丁未应用;随后改用实际文件末尾锚点,未产生部分修改。 ## 当前会话任务:团队文件源文件回传 AgentBus 来源渠道 - **状态:** 实现已完成;功能验证通过,仓库卫生仍保留用户既有阻断。 - **目标:** `confirmation_export` 任务成功取得 ERP 源文件后,将原始文件作为最终返回消息的一部分,沿任务记录的 AgentBus 来源渠道回传;现有平台附件保存与后台鉴权下载能力继续保留。 - **已确认事实:** 当前链路能读取并保存源文件,但 AgentBus 入站只使用 `payload.text`,已有记录显示带附件的入站探测被受理而最终回执没有附件。 - **已确认决策:** AgentBus 最终回执直接携带原始文件附件,同时保留现有下载地址作为兜底;需要限制消息大小、避免日志泄露,并兼容 OSS/数据库两种存储。 ### 实施阶段 - [x] 按治理规则读取项目入口、规划记忆、业务登记表及 `confirmation_export` 相关契约。 - [x] 核对 AgentBus 当前出站帧、附件模型、来源渠道路由和回归测试边界。 - [x] 定位附件“已落库但下载消失”的交付断点:后台地址需要登录且为相对路径;durable result 未投影顶层附件;当前结果文件名存在 UTF-8/Latin-1 乱码。 - [x] 实现源文件回传,并同步契约/测试/配置(direct/durable 附件、大小上限、OSS 取件、文件名修复已落源码)。 - [x] 执行项目规定的检查、测试和构建;`check`、控制面 53/53、build、`git diff --check` 通过,`check:repo`/legacy 仅受既有 `.DS_Store` 与 DOCX 哈希漂移阻断;不执行真实 ERP 写入、部署或外部发送。 ### 本轮错误记录 - 首次合并附件修复补丁因当前工作区已有 `getContent`/OSS 回传骨架,锚点与实际源码不一致,补丁未应用;随后按实际函数边界拆分为小补丁,未产生部分修改。 - 类型检查首次复跑发现 `attachmentMetadataFrame` 的新增可选参数与 `Array.map` 的索引参数不兼容;改为显式箭头回调,未产生运行时失败。 - 全量门槛首次复跑发现根 `.DS_Store`、既有发布 DOCX 哈希漂移和 `findings.md` 超限;已将完整 findings 冻结到 `archive/project-history/2026-08-17/findings-pre-compression-attachment.md` 并压缩活动 findings,`.DS_Store` 与 DOCX 保留为用户既有阻断,未修改。 - 一次跨文件补丁误以为 `getContent` 位于 `task-service.ts`,未应用且未产生部分修改;随后按实际 `artifact-store.ts` 边界拆分补丁并通过 `check`。 ## 当前会话追加:截图复核与运行态收口 - **状态:** 控制面已按用户授权重启并恢复;历史文件名兼容修复和回归已完成,未发送外部消息。 - **证据:** 截图显示 `confirmation_export` 仍只有文字回执且文件名乱码;当前控制面 PID 2545 于 21:44 启动,附件回传源码于 22:19 修改、`.build` 于 22:23 生成,运行进程未加载本次修复。 - **兼容性事实:** 已新增共享读取时文件名纠正;新旧 artifact 在成功回执、AgentBus 附件和任务元数据路径统一修复,数据库原始记录与文件字节不变。 ### 追加阶段 - [x] 将截图内容视为问题证据,未把图片中的聊天文本当成操作指令。 - [x] 只读核对源码、构建时间、控制面进程和附件读取路径。 - [x] 用户授权后重启控制面并验证 `/health/ready`、`/api/status` 均显示 AgentBus `connected=true`、`session_ready=true`。 - [x] 增加读取时的旧文件名修复并完成回归验证;控制面测试 54/54 通过。 ### 追加验证 - `check`、`build`、`git diff --check` 通过;`check:repo`/`test:legacy` 仍仅受既有 `.DS_Store` 与 DOCX 发布哈希漂移阻断。 - 控制面第二次重启后的 PID 为 `24031`,未执行 ERP 写入、部署或外部发送。 ## 当前会话追加:平台下载入口与渠道附件缺失复核 - **状态:** 控制面与平台修复已完成;外部渠道是否渲染附件仍待上游协议确认。截图显示成功文字中有文件名,但 AgentBus 渠道未出现文件对象,平台“后台附件”区域也没有下载按钮。 - **已定位的前端缺口:** `LianSyn-platform/app.js` 的 `renderTaskArtifacts()` 只从 `task.result.report.artifacts[*].download_url` 生成按钮,没有使用成功回执中的 `success_receipt.receipt.reply_attachments` 和 `important_message.attachments` 作为详情页兜底。 - **完成项:** 已核对任务详情 API 实际返回的 `result`、`success_receipt` 和附件 URL,修复平台显示链路,并用本地契约测试验证 AgentBus 直接/持久化载荷仍携带源文件内容。 ### 当前复核结果 - 已在登录态平台页面核对真实任务 `TASK-20260817144147-1MYf84I`:后台附件区域已显示 `LLW-261202A-A 客户确认书.doc` 和“下载文件”按钮,链接含该任务的 artifact ID。 - 该任务 API 详情同时返回完整 `result.report.artifacts`、`success_receipt.receipt.reply_attachments` 和 `important_message.attachments`;平台兜底修复已在页面生效。 - 控制面本地 direct/durable 契约测试曾确认旧实现会投影 `payload.attachments[*].content_base64`;更新后的微信适配器文档已提供权威 URL-only 附件协议,当前实现已切换为 HTTPS `url` 元数据。 - AgentBus 渠道实际渲染仍缺少上游可观测回执;当前不发送新的外部探测消息,保留“控制面已生成附件载荷、渠道适配器是否支持/渲染待上游确认”的边界。 ## 当前会话追加:按微信渠道适配器协议切换 URL-only 附件 - **状态:** 已完成;代码、运行配置和控制面重启均已完成,未发送真实外部文件测试。 - **协议事实:** `task.progress`/`task.result` 使用 `payload.attachments` 元数据,附件必须提供 HTTPS `url`;适配器按白名单下载并顺序发送,AgentBus 不应携带 base64。 - [x] 将 direct/durable 出站附件从 `download_url`/`content_base64` 改为 `id`、`name`、`content_type`、`size`、`inline: false`、HTTPS `url` 和可选 `sha256`。 - [x] 拒绝 HTTP、数据库后台鉴权 URL 和无可访问 URL 的外部附件,保留平台后台下载能力。 - [x] 同步 AgentBus 契约、控制面 README、环境示例和回归测试。 - [x] 运行源码检查、控制面 54/54、构建和 `git diff --check`;`check:repo`/`test:legacy` 仍仅受既有 `.DS_Store` 与 DOCX 哈希漂移阻断。 - [x] 在实际运行环境启用 OSS 配置并重启控制面;健康检查通过,重新生成团队文件任务和真实外部文件测试仍待用户安排。 ## 当前会话追加:文件获取统一转 PDF - **状态:** 已完成;用户确认仅 `confirmation_export` 转 PDF,转换失败回退源文件。 - **已定位范围:** 当前登记的文件获取 action 为 `confirmation_export`;现有链路保存 ERP 原始文件,`converted=false`,未接入转换器。 - **已确认决策:** 转换失败时保留并回传源文件;不改变其他任务附件。 - [x] 核对 PDF 转换运行时、部署依赖、源格式和附件回传字段。 - [x] 实现平台 PDF 转换、超时/无效输出回退源文件、测试并同步容器配置。 - [x] 重建确认导出 Skill/DOCX/扩展发布物,完成仓库卫生、全量测试、构建和渲染检查。 - [x] 按用户授权重启面板并验证运行态转换器与 AgentBus 健康状态。 - **运行态:** 面板已重启;`/health/ready` 返回数据库、Schema 和 3 个 AgentBus 渠道均正常且 `session_ready=true`。 ## 当前会话追加:AgentBus 渠道状态同步修复 - **状态:** 已完成;用户确认修复并重启。 - [x] 防止旧进程停机回写覆盖新进程的 AgentBus 渠道状态。 - [x] `/api/channels` 合并实时 listener 状态,避免面板显示陈旧的“已停用”。 - [x] 增加会话 epoch 防护和回归测试;控制面 59/59、类型检查、构建通过。 - **运行态:** 当前 3 个启用渠道均为 `enabled=true`、`connected=true`、`session_ready=true`;重复兼容渠道保持管理员停用状态。