Files
LWLT-AIBOT/archive/project-history/2026-08-17/task_plan-pre-compression-agentbus-channels.md
T

292 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 项目文件治理计划
## 当前会话任务:多 AgentBus 用户渠道与插件串行队列
- **状态:** 实施中;用户已确认整体方案。
- **用户目标:** 支持多个 AgentBus 来源/用户渠道,每个渠道可独立配置 AgentBus key,并保证插件同一时间只执行一个任务。
- **当前安全边界:** 仅做源码、契约和数据库设计梳理;未创建迁移、未改运行配置、未部署、未向 AgentBus 或 ERP 发送数据。
### 本轮阶段
- [x] 1. 读取项目记忆、检查工作区状态并按业务登记表定位通用业务契约
- [x] 2. 核对 AgentBus 认证/来源、用户模型、任务状态和插件执行链
- [x] 3. 确认渠道身份与插件队列的产品边界
- [ ] 4. 设计并实现渠道密钥、入站归属和可恢复的单插件执行槽
- [ ] 5. 同步操作台/API/文档/测试/发布边界并完成全量验证
### 当前待确认决策
| 决策 | 推荐 | 主权衡 |
|---|---|---|
| 插件串行范围 | **已确认:**同一组织/同一 ERP 浏览器会话全局一次只允许一个任务;其他用户任务保留在服务端队列,按创建时间依次领取 | 吞吐较低但不会跨用户并发写同一 ERP 会话;按用户并行会提高吞吐却无法保证当前单插件约束 |
| AgentBus key 的连接边界 | **已确认:**每个外部用户渠道对应独立 AgentBus listener/连接,独立保存 key | 多连接与重连管理更复杂,但 key 和用户边界清晰 |
| 渠道用户身份 | **已确认:**独立外部渠道身份,不创建后台登录账号;管理员统一管理 | 暂不提供渠道用户独立登录和权限视图,避免扩大现有管理员鉴权模型 |
| 最终回执可靠性 | **已确认:**入站路由和最终回执状态持久化,队列等待和进程重启不丢回执 | 增加 outbox/投递状态和重连补发逻辑,但避免用户收到假超时或因进程重启丢回执 |
### 已收敛的实施方案
1. 新增 `user_channels`(外部渠道身份、显示名、独立加密 AgentBus key、连接配置、启用/连接状态);管理员通过后台 API/页面创建、启用、禁用和轮换 key,列表不回显完整 key。
2. 控制面启动时为每个启用渠道建立独立 AgentBus listener;任务写入 `channel_id`,幂等键和会话路由按渠道隔离;Agent/Skill operation Schema 不变。
3. 新增持久化 AgentBus 入站/回执 outbox,保存 `channel_id + inbound_frame_id` 的幂等路由;先发一次受理通知,任务进入终态后发最终回执,断线/重启/排队超时后由对应渠道重连补发。
4. 插件执行 claim 在组织级事务锁下按创建时间 FIFO;存在 `queued/accepted/running` 或结果不确定的 ERP attempt 时不再创建第二个 execution,只返回排队信息。解析仍可并行,ERP 插件执行保持单槽。
5. 操作台与扩展增加排队状态/单任务防护;补充迁移、渠道 CRUD、listener、多渠道幂等/回执、FIFO claim、并发 claim 和不确定结果阻断测试,并执行项目规定的完整验证命令。
### 默认假设与排除
- 现有组织级自动化开关继续对所有 AgentBus 渠道生效,不新增渠道级自动化策略。
- WebSocket URL、client type、重连/超时等通用参数继续使用服务端环境配置;渠道独立保存 key,并允许独立 bot address 覆盖,未提供时沿用兼容默认值。
- 禁用渠道停止接收新入站帧,但已进入任务队列或待发送 outbox 的回执保留;重新启用后继续处理。删除采用禁用/归档语义,不做物理删除。
- 不实现微信等具体渠道协议,不进入 ERP,不部署、不重启生产服务,也不读取或写出任何真实 key。
### 实施记录
- [x] 用户确认开始实施
- [ ] 数据库迁移与渠道/回执服务
- [ ] 多 listener 与 durable outbox
- [ ] FIFO 插件 claim 与前端/扩展单任务防护
- [ ] 测试、文档、发布边界与完整验证
## 当前会话任务:AgentBus onboarding 更新后重新对接
- **状态:** 已完成;运行进程已按当前受保护配置重新建立 AgentBus session 并通过健康检查。
- **用户请求:** 按 `/Users/inmanx/Downloads/agentbus-bot-onboarding-bot-2076193998368161793-listener.md` 重新对接 AgentBus listener。
- **安全边界:** 仅使用文档中的连接参数;token 不写入仓库、不输出、不进入日志;不执行外部业务发送或 ERP 写入。
### 本轮阶段
- [x] 1. 读取项目记忆、检查工作区状态并审阅 onboarding 连接事实
- [x] 2. 核对当前 AgentBus listener 的握手实现与运行状态
- [x] 3. 让运行进程使用 onboarding 参数重新建立 session 并验证 ready
- [x] 4. 更新本轮发现、进度并报告可验证结果
### 本轮结论
- onboarding 中的 token 与当前受保护运行配置一致,未修改 `.env`、源码或发布物。
- listener 已重新启动并收到 `session.ready`;当前 `/health/ready` 显示 `connected=true`、`session_ready=true`,地址为 `bot:2076193998368161793:listener`。
- 已通过 onboarding 的 Invoke API 发送一条明确标记为“仅测试、不执行 ERP”的探测消息;接口返回 `202 accepted`,listener 收到并受理,随后发出受理进度和最终 `task.result`。
- 探测文本不是有效业务指令,解析服务最终返回非标准 JSON,控制面按失败契约回传错误摘要;这证明 AgentBus 收发链路正常,但不代表业务解析服务可处理任意测试文本。
- 当前进程日志中未发现新的 `channel:wechat` 入站帧;之前用户消息未进入当前 listener 的证据仍在上游渠道投递侧,而非 AgentBus WebSocket 握手。
- 用户再次发送后连续观察 20 秒,当前健康 listener 仍未收到新的微信渠道帧;当前 `/health/ready` 保持 connected/session_ready,进程未发生自动重启。
- 本轮未写入 ERP、未改变业务任务数据;探测只产生了一条非业务测试任务。
### 文件探测结论
- 已通过 Invoke API 发送 59 字节的临时 `agentbus-file-test.txt`,接口返回 `202 accepted`。
- listener 实际收到的入站 payload 包含 `attachments`;但当前 `processInboundTask` 只将 `payload.text` 交给任务服务,未把入站附件持久化或带入最终回执。
- 因此本轮验证了 AgentBus 可以承载附件字段,但尚未验证真正的渠道文件回传;当前项目的出站附件仍只来自 `confirmation_export` 执行结果中的受控附件元数据。
### 发信探测结论
- 已通过 Invoke API 发送纯文本探测;接口返回 `202 accepted`,listener 收到并受理,随后发出受理进度和最终失败回执,最终结果也收到 AgentBus `accepted`。
- 失败仅因为探测文本不是可执行业务指令,未进入 ERP;AgentBus 发信、收信和回件链路正常。
## 当前会话任务:生产 PostgreSQL / OSS 对接
- **状态:** 已完成本轮对接与验证;未执行服务部署、重启或真实 ERP 写入。
- **用户确认:** 使用干净生产 Schema,不迁移/删除旧测试数据;OSS 公共可读、仅后端可写/删;直接返回公共 URL;暂不启用自动清理。
- **远程落点:** PostgreSQL `lwlt_agent` 数据库内新建 `liansyn_prod` Schema;旧 `public` Schema 保持不变。
- **已完成:** OSS V4 provider、随机执行 UUID 对象路径、任务附件元数据、事务失败回滚清理、生产环境模板和 retention 开关。
- **已完成:** 完整仓库门槛、部署前检查、本轮证据与活动文档收口。
### 本轮阶段
- [x] 1. 探测 PostgreSQL / OSS 实际权限和 Bucket 状态
- [x] 2. 接入 OSS provider、独立数据库 Schema 和生产配置
- [x] 3. 执行远程 Schema 迁移并验证上传/公共读取/删除
- [x] 4. 完成本地测试、构建、仓库卫生和发布边界收口
## 当前会话任务:AgentBus 用户回复契约重构
- **状态:** 已完成;已确认用户端只保留受理通知和最终返回通知。
- **用户确认:** 失败时优先返回 ERP 业务反馈,没有 ERP 反馈才返回简短错误摘要;成功时按业务 action 与客户模板返回业务回执;解析完成/进入自动化 ERP 执行不对用户发送。
- **本轮重点:** 按现有五类业务能力更新成功回执契约,正式接入酒店安排中英文客户模板,并保持 AgentBus 不泄露技术细节。
### 本轮阶段
- [x] 1. 核对业务注册表、Schema、mapping 与当前 AgentBus/平台实现
- [x] 2. 形成各业务成功/失败/文件回执矩阵与酒店模板契约
- [x] 3. 实现控制面、平台/插件消息路由及回归夹具
- [x] 4. 完成仓库门槛、类型检查、控制面/遗留测试与构建验证
### 本轮决策
| 决策 | 结论 |
|---|---|
| 用户侧消息层级 | 仅发送受理通知和最终返回通知;解析完成、进入自动化执行为内部状态 |
| 失败回执 | 有明确 ERP 业务反馈时返回 ERP 反馈;否则返回简短错误摘要 |
| 成功回执 | 按 action 定义业务字段,按客户模板决定文本格式;不把通用技术消息直接作为用户回执 |
| 酒店安排成功格式 | 支持客户给定的英文/中文双格式,包含团号、入住/退房、晚数、房型/房数 |
### 本轮收敛
- `arrangement_hotel` 新增成功且字段完整时使用客户双语模板;酒店变更/清除无法套模板时返回酒店业务字段,不输出空占位符。
- 酒店双语模板的两段日期都使用同一份实际执行日期;客户名称仅在执行上下文提供时追加,不硬编码示例中的客户名。
- 文件回执只向 AgentBus 暴露文件名、类型、大小和受控下载地址;外部渠道的二进制直传仍需独立的渠道适配与鉴权转发。
- 真实 ERP 写入、部署、重启和外部发送未执行。
### 最终验证
- `node --run check:repo`:9/9。
- `node --run check`:通过。
- `node --run test:control-plane`:46/46。
- `node --run test:legacy`:201/201。
- `node --run build`:通过。
- `node --run test`:通过;`git diff --check`:通过。
### 本轮错误记录
| 错误 | 次数 | 处理 |
|---|---:|---|
| 当前 shell 没有 `npm` 命令,首次 `npm run check` 未执行 | 1 | 改用 workspace bundled Node/npm 路径后重跑;未修改源码 |
| 旧控制面/AgentBus 测试仍断言解析进度和旧成功文本 | 1 | 已确认是本轮契约预期差异,更新断言并补充酒店/业务回执测试 |
| 新增测试直接访问宽类型 `task.success_receipt` 导致 TypeScript 类型错误 | 1 | 在测试中增加最小结构断言类型;源码未回退 |
## 当前会话任务:后台附件详情视觉收口
- **状态:** 已完成源码调整、静态契约检查、控制面/遗留回归和构建验证。
- **用户确认:** 后台附件区域移除简要操作信息;有文件时只保留文件名和下载按钮,其他业务审核信息保持不变。
- **执行结果:** `confirmation_export` 不再渲染 action、目标日期、业务选择和操作明细;附件卡片隐藏文件类型/大小,仅保留文件名与鉴权下载按钮;详情面板之间不再显示无意义的横向分割线。
- **验证结果:** `check:repo` 9/9、`check`、控制面 41/41、legacy 201/201、`build` 和 `git diff --check` 通过。
## 已完成基线:团队文件后台附件交付
- **状态:** 已完成实现、控制面/遗留契约回归、DOCX 同步、版本化制品和仓库门槛;真实部署与 OSS 接入仍待单独授权。
- **用户确认:** 导出团队文件的原始字节要保存到平台后台,页面提供鉴权下载;真实上线后附件存 OSS,当前先用加密数据库存储并保留对象存储替换接口。
- **目标:** 修复“ERP 文件 HTTP 200 但后台没有文件”的假完成路径,使导出只有在附件落库成功后才可标记完成。
- **根因:** 旧 `exportConfirmationSources` 只返回来源元数据并固定 `downloaded=false`,控制面没有附件表、保存事务或下载路由。
- **执行结果:** 插件携带 base64 原始字节与 SHA-256;控制面校验大小/哈希、加密写入 `task_artifacts`、返回鉴权下载地址;保存失败显式阻断,禁止把来源读取当作交付完成。
- **验证边界:** 已完成只读源码、契约、迁移、包/源码一致性和全页 DOCX QA;未执行真实 ERP 写入、服务部署、重启或 OSS 外部写入。
## 目标
建立并落实全仓库文件治理:每类内容只有固定位置和单一权威源,保留 Planning with Files 三个项目记忆文件,分离当前源码、生成物、运行输出、验证证据与历史归档,并通过自动检查阻止后续会话再次散落或复制文件。
## 当前阶段
阶段 10:后台附件详情视觉收口
## 阶段
### 阶段 1:全仓库发现与分类
- [x] 确认用户目标和治理边界
- [x] 确认 `task_plan.md`、`findings.md`、`progress.md` 是正式项目记忆
- [x] 审计全部活动目录、根文件、引用、构建消费者及版本管理状态
- [x] 识别当前源码、生成物、运行输出、历史资料、敏感配置与无效残留
- **状态:** 已完成
### 阶段 2:制定唯一目录规范
- [x] 定义根目录允许项和各目录职责
- [x] 定义 Planning with Files 文件压缩与历史轮转规则
- [x] 定义 `dist/`、`archive/`、`reports/`、`quarantine/` 的边界
- [x] 将规则固化到项目级 `AGENTS.md` 与当前入口文档
- **状态:** 已完成
### 阶段 3:安全迁移与压缩
- [x] 保留已有未提交业务改动,不覆盖用户工作
- [x] 压缩当前规划记忆并将详细历史移入日期归档
- [x] 迁移过期文档、重复交付副本和无引用历史产物
- [x] 同步所有受影响链接、说明和制品清单
- **状态:** 已完成
### 阶段 4:自动治理
- [x] 新增仓库卫生检查
- [x] 检查禁止的根目录散落、重复制品、版本漂移、源码/包不一致和断链
- [x] 接入适当的本地验证入口
- **状态:** 已完成
### 阶段 5:验证与交付
- [x] 运行链接、Skill、Schema、构建、测试和制品完整性验证
- [x] 复核活动目录只含当前上下文
- [x] 更新规划文件并交付最终目录说明
- **状态:** 已完成
### 阶段 6:桌面历史产物收口
- [x] 按 SHA-256 区分桌面历史目录与项目 `dist/`、`archive/releases/` 的重复和唯一文件
- [x] 确认桌面历史目录没有正在打开的文件
- [x] 将 10 个仅存桌面的历史制品补录到日期化项目归档并登记哈希
- [x] 复核剩余桌面有效文件均已有项目副本
- [x] 将整个桌面历史目录可恢复地移入废纸篓
- [x] 更新归档索引、Planning 文件并完成适用验证
- **状态:** 已完成;全仓库卫生门槛仅被当前 Word 会话生成的实时锁文件暂时阻断
### 阶段 9:团队文件后台附件交付
- [x] 定位导出流程中“读取成功但未持久化文件”的根因
- [x] 增加加密数据库附件存储、任务归属校验和鉴权下载路由
- [x] 让插件上传原始字节并以大小/SHA-256 校验作为完成门槛
- [x] 同步操作台、Schema、mapping、业务模板、回归夹具和版本化插件制品
- [x] 完成控制面、遗留契约、仓库卫生、构建及 DOCX 全页渲染检查
- **状态:** 已完成当时的数据库附件实现;本轮已补齐 OSS provider 和远程基础设施验证,真实部署与真实 ERP/生产业务复测仍留待后续授权
### 阶段 10:后台附件详情视觉收口
- [x] 移除导出团队文件详情中的冗余 operation 审核摘要
- [x] 附件卡片只保留文件名和下载按钮,保留等待/链接不可用状态
- [x] 移除重要消息、审核、附件和结果面板之间的无意义横向分割线,保留卡片与日志边框
- [x] 保持其他业务审核信息、附件鉴权下载接口和任务生命周期日志不变
- **状态:** 已完成;未修改业务数据或下载接口
## 已确认决策
| 决策 | 理由 |
|---|---|
| 全仓库审计,不局限于已点名文件 | 用户要求解决跨会话长期遗留问题 |
| Planning with Files 三文件保留在项目根目录 | 它们是用户指定的正式项目管理机制 |
| 规划文件过大时做语义压缩和历史轮转,不直接删除 | 保持新会话上下文精炼,同时保留可追溯性 |
| 暂不改名 `agent设计规范/` | 目录名称本身不是重复根因,避免无收益的大规模引用迁移 |
| 先审计引用和构建消费者,再移动或归档 | 防止误伤启动、测试、发布或当前业务事实 |
| 根目录固定保留 README、AGENTS、Planning 三文件及构建配置 | 兼顾项目入口、机器约束和跨会话恢复 |
| TypeScript 构建输出迁到忽略的 `.build/` | `dist/` 只承载版本化交付物,生成代码不再混入发布目录或活动搜索 |
| `dist/` 移除无版本插件别名和松散 Prompt/示例副本 | 它们无运行/测试消费者,且已经发生模板漂移 |
| 历史 README/发布门槛先冻结原文再精简活动版本 | 保留可追溯性,同时避免旧版本流水污染当前上下文 |
| DOCX 从 Markdown 确定性重建并做全 15 页视觉 QA | 修复现有多处内容漂移和中文字体缺失,减少以后手工漏同步 |
## 审计结论
1. 当前活动目录均有明确源码、测试、部署、发布或安全隔离职责;未发现空目录或无归属根文件。
2. TypeScript 编译结果是可重建生成物;版本化插件、五个 Skill 和 DOCX 是当前交付物,由发布清单定义。
3. 活动文档只链接当前契约或日期化不可变证据;历史快照不再承担当前入口职责。
4. Planning 三文件只保留当前决策、事实和进度,详细时间线已冻结到日期归档。
## 错误记录
| 错误 | 次数 | 处理 |
|---|---:|---|
| 首次合并补丁假定 `progress.md` 标题为“进度记录” | 1 | 读取实际标题“项目进度”,改为按真实锚点分别应用补丁;首次补丁整体失败,未产生部分修改 |
| `fc-list` / `fc-match` 不在当前 PATH,无法直接枚举中文字体 | 1 | 定位 workspace dependencies 内 bundled `fc-scan` 与 fontconfig,再用 DOCX 实际渲染验证 |
| 单个补丁同时删除并新增同一路径的 README 被拒绝 | 1 | 拆成新增规则/修改配置、删除旧 README、新增新 README 三个原子补丁;失败补丁未产生部分修改 |
| 新增 DOCX 构建器的首个补丁使用了不存在的 `tools/README.md` 锚点 | 1 | 读取真实表格结构后重新应用;失败补丁未产生部分修改 |
| bundled Python 没有 `fontTools` | 1 | 改用 macOS `mdls` 和 bundled `fc-scan` 只读识别字体 |
| 默认 LibreOffice 字体配置将 DOCX 中文渲染为方框 | 3 | 使用 workspace dependencies 的 Poppler fontconfig,并将构建字体固定为 `Arial Unicode MS`;最终 15 页全部清晰 |
| 首轮仓库卫生检查发现 macOS 重建根 `.DS_Store` | 1 | 再次可恢复地移入废纸篓并保留自动阻断规则,复跑通过 |
| 归档索引检查发现两处仍链接旧维护规范 | 1 | 改为链接根 `AGENTS.md`,复跑归档索引验证 |
| 一次 `rg` 命令中的反引号导致 zsh 引号不闭合 | 1 | 改用单引号正则重新执行;未修改任何文件 |
| `pnpm run test` 内部硬编码调用缺失的 `npm` | 1 | 将聚合测试改为 Node 22 原生 `node --run`,兼容 npm/pnpm 入口后重新执行 |
| 最终 JSON 检查误用 `jq -e empty`,因无输出提前退出 | 1 | 改为 `jq empty` 后完整重跑 JSON、JS、归档、差异和目录检查 |
| 清理新生成的根 `.DS_Store` 时假定旧废纸篓治理目录仍存在 | 1 | 只读检查确认该旧目录已不存在,改用废纸篓根下新的唯一目标名;首次命令在移动前退出,无文件变化 |
| 首次直接调用 bundled `node --run check:repo` 时,脚本内子进程找不到 `node` | 1 | 为验证命令显式把 bundled Node 目录加入 `PATH` 后重跑;首次失败未修改文件 |
| 本轮 `check:repo` 首次复跑发现 `dist/.DS_Store` 与已知 Word 实时锁文件 | 1 | `.DS_Store` 可恢复移入废纸篓;Word 锁文件因当前 DOCX 仍打开而保留,关闭 Word 后再完成卫生门槛 |
## 阶段 6 实时边界
- `/Users/inmanx/Desktop/LTJT-历史版本归档` 共 68 个文件:56 个有效文件已有项目内同哈希副本,10 个历史制品仅存桌面,另有 `.DS_Store` 和 Word 锁文件两个残留。
- 10 个补录制品已通过 `SHA256SUMS` 全量校验;补录后再次扫描桌面目录,结果为 `matched=56`、`unmatched=0`、`residue=2`。
- 桌面历史目录经 `lsof` 复核无打开文件后,已整体移入 `/Users/inmanx/.Trash/LTJT-历史版本归档-20260816`;原桌面路径已不存在,废纸篓副本可恢复。
- 项目当前 DOCX 正由 Microsoft Word 打开,`dist/~$联泰AI指令表-0.5.118.docx` 是实时锁文件,本轮不得移动、读取或删除。
- 适用验证:10 个补录文件哈希全通过;`node --run check`、`test:control-plane`(37/37)、`build`、`git diff --check` 通过;`check:repo` 为 8/9、`test:legacy` 为 197/198,两个失败均是同一个 Word 实时锁文件导致 `dist/` 多出一项。
## 安全边界
- 不使用 `git reset --hard`、`git clean` 或批量回退。
- 不覆盖现有未提交业务改动。
- 不读取或输出 `.env` 中的秘密值。
- 不进入 ERP,不修改业务数据,不部署或发布。
- 所有归档移动保持可恢复,并在移动前完成精确引用审计。