Files
LWLT-AIBOT/findings.md
2026-08-25 10:33:29 +08:00

19 KiB
Raw Blame History

当前关键发现

2026-08-24 — ERP 异常状态链接刷新加固(已完成)

  • 用户描述的是插件长时间待机后的偶发 ERP 未连接告警;当前源码已有 chrome.alarms 待机保活,但 runErpSessionKeepalive() 在 session_expired/failed 后只写入 erpKeepaliveState,没有恢复动作。
  • 当前保活默认首次约 1 分钟、之后每 5 分钟;只查找现有 https://lwlt.hisy.cc/* 标签页,执行主世界带 Cookie 的只读 GET /System/Mainlt.asp,执行中跳过,不新开标签、不刷新页面、不写 ERP。
  • findExistingErpTabForKeepalive() 会拒绝非完整加载或非 allowlisted origin;因此长待机后页面已被导航到登录/异常路径、页面注入链路失效或标签页状态异常时,保活只能报告 skipped/failed/session_expired,不能自愈。
  • readErpSessionStatus()、business-bridge.js 和 popup 已能展示最近保活状态;平台/业务 operation、Schema 与 Skill 不承载此宿主维护能力,当前活动约束来自 mappings/lifecycle.mapping.json。
  • 本轮拟保持 fail-closed:仅在无活动 ERP 执行、自动化与保活开关开启且已存在 allowlisted ERP 标签页时,执行受控同源 Mainlt 导航/刷新后再次只读探测;不自动打开新标签、不重交任务、不跨越 ERP 写入边界。
  • 已实现 performErpLinkRecovery() 与单飞请求锁:异常时对现有 ERP 标签页执行 chrome.tabs.reload(..., { bypassCache: true }),等待加载完成,再复用只读 probe;2 分钟冷却内最多一次,执行中二次检查并跳过。
  • readErpSessionStatus() 在登录/权限页面或页面注入异常时异步触发恢复,不阻塞平台 PING;桥接和平台状态新增 session_ready、恢复状态、恢复次数和最近恢复时间。平台在会话异常/恢复中保持告警并阻止新的任务下发,恢复失败要求人工确认,不自动重交。
  • lifecycle mapping、插件 README、popup 文案和 tools/erp-session-keepalive.test.mjs 已同步;定向保活回归 4/4、生命周期契约 47/47、相关 JS 语法检查通过。
  • 扩展已递增到 0.5.140;dist/ltjt-order-assistant-0.5.140.zip 已通过 unzip -t,SHA-256 为 5d2eceb77a337849bd20bc3e03dea4c86b617c789dd196b8a47bbb33c0da0338;0.5.139 已归档到 archive/releases/2026-08-24/。
  • 完整门禁最终通过:check:repo 9/9、check、串行 test:control-plane 66/66、test:legacy 214/214、build、git diff --check;未进行真实 ERP 写入、任务重试、外部发送、重启或部署。

2026-08-22 — 取消产品/客户来源地强制匹配

  • 用户日志中的阻断发生在 shared_child_order_create 的浏览器只读阶段,唯一失败项为 product_customer_source_region:产品关键字识别出“贵阳”,客户来源信息未命中;客户、OP、销售和领队候选本身均已唯一,且 no_erp_write=true。
  • 当前 Schema 没有要求产品与客户来源地相同;强制关系来自插件 inpage.js、team-batch-inpage.js 的运行时来源地兼容门禁,以及客户候选的产品来源地消歧 fallback。
  • 活动规则已收敛为:产品和客户分别进行 ERP 唯一解析;客户关键词在精确/唯一包含失败后仍可用客户自身来源词做唯一 fallback,但该 fallback 不读取产品;产品/客户来源地不一致不阻断 DoInfoJH、DoInfoJHs 或 DoInfoSPs。
  • 已移除来源地兼容函数和跨产品/客户候选消歧;保留产品候选唯一、客户候选唯一、人员/领队校验、写入前门禁、明确 ERP 回执及 fresh requery。source-region.js 仅保留客户侧候选辅助接口。
  • 扩展已递增到 0.5.139,平台最低版本、生命周期 mapping、运行时版本断言、业务页、mapping、夹具和说明同步;dist/ltjt-order-assistant-0.5.139.zip SHA-256 为 d3ad25b6c22f5269a2fa713441f3b2aebf4cbcf3dff96bdafcef15d29d810353。
  • 上一版 0.5.138 已保存在 archive/releases/2026-08-22/;本轮未重试用户任务、未写入 ERP、未重启、未部署、未向外部渠道发送消息。

2026-08-20 — ERP 会话待机保活实现

  • 现有插件已有执行期间的 MV3 worker/page keepalive,但没有空闲时的 ERP 会话请求;lwlt-confirmation Skill 明确“定时和外发”不属于业务 action,因此本次只修改插件宿主维护逻辑,不扩展 operation、Schema 或 Skill 输入契约。
  • 安全实现采用 chrome.alarms,默认首次约 1 分钟、之后每 5 分钟触发;只查找现存且 allowlisted 的 https://lwlt.hisy.cc/* 标签页,不自动新开标签、不调用 tabs.reload()。
  • 页面侧通过主世界 fetch('/System/Mainlt.asp', { method: 'GET', credentials: 'include', cache: 'no-store' }) 发送轻量只读请求;检查最终 URL、HTTP 状态和登录/权限页面特征,结果写入本地状态并通过插件面板展示。
  • 当 ERP 自动化或单独保活开关关闭、执行中任务存在、没有已加载 ERP 标签页或权限不可用时,保活跳过/失败且不触碰业务写入;浏览器或操作系统休眠会延迟 alarm,不能保证休眠期间持续请求。
  • 扩展已递增到 0.5.138,同步 manifest.json、平台最低版本、生命周期 mapping、页面运行时版本和定向回归;版本化 ZIP SHA-256 为 751dfe6022d61c7388c602089c703b88a9bfeebf67f81edacea1555545d7bcd0。

2026-08-19 — AgentBus 无状态消息但任务成功(诊断进行中)

  • 已确认本轮是只读诊断;工作区存在大量既有未提交改动,不能回退或覆盖。
  • 当前尚未取得该次成功任务的任务 ID、渠道 ID 或运行时发送日志;先以当前契约、源码、测试和已有控制面证据定位确定性条件。
  • 待核对:任务状态事件生成、回复路由是否持久化、AgentBus 渠道是否启用/握手、accepted/processing/result 是否进入 durable outbox,以及失败/重试语义。
  • 登记表列出的 agent设计规范/businesses/confirmation_export.md 当前不存在;已转用行为注册表、lwlt-confirmation Skill、AgentBus 回复契约和源码作为活动规则来源。
  • 当前 control-plane/README.md 明确用户侧只持久化发送一次 task.progress(status=accepted) 和一次 task.result;不会发送“解析完成/等待确认/进入 ERP”的中间进度,因此“processing”不是当前 AgentBus 对外消息。
  • lwlt-confirmation Skill 与标准 operation Schema 只描述业务解析/执行事实,不承诺定时或主动外发;lifecycle.mapping.json 的 scheduled=false/sent=false 属于业务附件外发字段,不能单独证明 AgentBus 回执已发送或未发送。
  • AgentBus 回复契约明确用户侧预期是“受理通知 + 最终返回通知”,但执行阶段、页面打开、提交中和回查等中间状态只进入平台生命周期/审计;因此本次“没有处理消息”首先是契约预期与实现定义不一致,仍需查清 accepted/result 为何也未达渠道。
  • 生产数据库渠道走 durable delivery:AgentBusListener.processInboundTask() 将 channel_id、入站 frame 路由和 accepted payload 一起交给 TaskService.ingestMessage();只有这些路由字段存在时,事务才插入 agentbus_deliveries(delivery_kind='accepted')。
  • durable 模式下不会直接发送 accepted;listener 每秒/session.ready 后 flush outbox。只有 accepted delivery 已标记 delivered,且任务进入终态,才会创建 delivery_kind='result';因此 accepted 没投递成功时,result 会被有意延后,而任务本身仍可继续完成。
  • 手工操作台/API 任务没有 AgentBus channel_id/agentBusRoute,recordAgentBusAcceptedDelivery() 会直接跳过;该任务可以成功,但不会生成任何 AgentBus delivery。判断“任务来自 AgentBus”必须看 tasks.source='agentbus'、tasks.channel_id 和入站回执行。
  • listener 只有在 agentBusEnabled、渠道 enabled=true、全局 WebSocket URL/渠道 key/bot address 可用并收到 session.ready 后才会发送;连接断开会把 sending 释放回 pending,失败按退避重试。当前源码测试覆盖 legacy 直发和数据库渠道 durable accepted/result 两种路径。
  • tasks.source 仅允许 manual/agentbus,tasks.channel_id 可为空;agentbus_deliveries 对 accepted/result 做唯一约束,默认 pending,失败会重试。数据库设计本身允许“任务已成功但 delivery 未送达”的中间状态。
  • TaskService 的执行结果路径只更新任务、写 task_events/通用 outbox_events 并发出内部 events;AgentBus result 不是在任务成功事务内直接发送,而由 listener 的 durable flush 后置生成。因此仅看到控制面“任务成功”日志,不等于看到 outbound_durable_delivery_sent。
  • 最终诊断:processing 缺失是设计行为;accepted/result 同时缺失则不是“ERP 任务成功”能够覆盖的成功条件,优先检查该任务是否为 source=agentbus 且绑定 channel_id,再检查对应 accepted/result delivery 是否存在及其 pending/failed/delivered 状态。没有任务 ID 和任务时段日志,无法在“手工任务无路由”与“AgentBus delivery 未投递”之间做历史唯一归因。
  • 当前只读 /health/ready 探针返回数据库/schema 正常,4 个启用渠道均 connected=true、session_ready=true;未执行外部发送、任务重试、重启或部署。
  • 现场日志已捕获用户刚发的成功任务 TASK-20260819102429-R13bn8w:入站 frame 为 wechat-task-c6540dcf293678ec2d76dfeb#1,控制面先发送 accepted(delivery 4d447c5b-1012-437c-9e00-2854429a91d3),后发送 completed result(delivery e4b3db12-abc2-49b8-b97f-a1674fe876a8),两条均有 outbound_durable_delivery_sent。
  • 同一 result frame 之后收到 AgentBus server 的 accepted-177 与 delivered-178 确认帧;日志没有 outbound_durable_delivery_failed、socket_error 或 socket_close 与该任务相邻。因此“控制面未给 AgentBus 返回”已被排除;“delivered”只能证明 AgentBus WebSocket/网关接收,不证明微信客户端已经渲染。
  • 该任务的 processing 仍不会发送,这是契约设计;本次 accepted/result 已实际发送却用户不可见,剩余故障域是 AgentBus 网关到微信适配器/会话的下游路由、事件类型渲染或会话展示。

2026-08-19 — confirmation_export Chrome host 权限阻断

  • 两份用户粘贴日志内容结构相同但任务编号/时间不同;外部 Agent SSE 正常完成,标准 operation 校验通过,action 为 confirmation_export,文件类型为 xingyou-confirm。
  • 两次都在插件浏览器执行阶段阻断,错误完全一致:Cannot access contents of the page. Extension manifest must request permission to access the respective host.;agent_returned=true、plugin_dispatch_started=true、erp_write_started=false、no_erp_write=true,没有 ERP 写入或导出源回执。
  • 当前扩展 manifest.json 已递增到 0.5.137,仍只允许登记的 https://lwlt.hisy.cc/*;background.js 用同一固定 origin 查找/打开 ERP tab,随后通过 chrome.scripting.executeScript 注入页面脚本。
  • runPageAction() 的业务动作执行使用主框架;resolveOperationInErp() 也使用主框架,但前置/只读探针路径有 allFrames=true 调用。Chrome 原始错误没有在源码中硬编码,说明需要区分固定 ERP host、重定向 host 和受限 frame 三种触发条件。
  • 对固定 ERP URL 的外部只读 HEAD/重定向探测因连接超时未得到网络证据;不读取秘密配置,不重试外部业务任务。
  • 修复已在后台增加 chrome.permissions.contains host 前检、tab origin 复核、同源导航竞态的一次安全重试和结构化权限错误;平台桥接状态现在展示 ERP 页面权限,并在权限不可用时阻止新的自动 handoff。
  • 定向验证已通过:扩展/平台语法检查、operation plan 40/40、生命周期契约 47/47;check:repo 9/9 通过,0.5.137 ZIP 与源码逐文件一致。

2026-08-18 — visitor-list XLSX 转换失败日志

  • 用户提供的运行记录中,外部 Agent 解析完成并进入插件只读阶段;没有 ERP 写入。
  • 最终阻断原因为 artifact_delivery_failed:visitor_xlsx_conversion_failed:conversion_failed:游客信息已读取,但移动端 .xlsx 派生文件生成失败。
  • 系统按 fail-closed 规则没有把原始 HTML-in-XLS .xls 回传 AgentBus,因此不能把前面的 confirmed 自动化事件当作最终成功;最终任务状态是 blocked。
  • 当前需要继续核对转换器的输入路径、LibreOffice 调用/退出码、输出发现与 XLSX ZIP/magic 校验;在得到根因前不执行 ERP 重试。
  • 已用当前 bundled soffice 对脱敏 HTML-in-XLS fixture 复现:输入被识别为 Writer/Web document,执行 xlsx:Calc MS Excel 2007 XML 时退出信号为 SIGABRT,stderr 为 Unspecified Application Error;输出目录仅有锁文件和临时文件,没有有效 XLSX。该崩溃是当前 conversion_failed 的直接根因候选。

2026-08-18 — 散拼母团创建写后回查假阴性修复

  • 用户已人工确认本次 2027 年三个母团实际创建成功;本次错误因此确定为写后回查假阴性,而非 ERP 创建失败。
  • ERP 成功响应完整返回 3 个团号,精确回查却全部为 parent_group_not_found;最终错误为 erp_result_uncertain,系统未自动重试。
  • 当前 createSplitParentLive() 仅在 groupNumbers.length < dates.length 或启用事实探针时调用 reconcileSplitParentByRequest()。本次 3 个返回团号等于 3 个日期,导致精确回查全部失败时仍跳过按日期兜底。
  • 精确回查调用 searchMainPage() 时只设置日期范围与团号,没有显式清空客户、产品、游客/领队和状态筛选;列表复用现有文档,因此残留筛选可能隐藏已创建行。
  • 修复范围已确认:清空非目标筛选、有限延迟只读重试、任一精确团号未命中即触发按日期兜底;不得再次提交创建请求,持续缺失或歧义仍保持不确定态。
  • 当前实现使用 0/750/2000ms 三次精确只读查询;每次查询都设置日期与团号,并清空客户、产品、游客/领队和状态筛选。
  • 恢复判定现在同时检查保存响应、团号数量、精确回查完整性和事实探针;任一条件需要恢复时调用现有逐日期唯一匹配。回查行合并会让成功的日期兜底结果覆盖先前空结果,但不会覆盖歧义或缺失门禁。
  • 定向测试已通过:split-plan-reconciliation 14/14;生命周期静态门禁 1/1。测试确认首次全空、第二次可见可收敛,持续缺失会耗尽有限预算并保持未确认,且 createSplitParentLive() 仍只有一次 captureAjaxSubmit() 保存捕获调用。
  • 扩展已递增到 0.5.135,当前 ZIP SHA-256 为 9f49f5529083cb1cc497bfc52c56d0142076394c034552fcdd77e34e70ce7f14;旧 0.5.134 已进入日期归档。
  • 完整验证中,本次回查相关代码、legacy 214/214、类型检查、构建、仓库与发布物门禁均通过。控制面唯一失败来自任务开始前已有的游客 XLSX 并行改动:convertDocumentToXlsx() 期待 .xlsx,测试假 soffice 仍只生成 team.pdf;本轮未改动该策略或测试。

2026-08-18 — visitor-list AgentBus XLSX 交付

  • 用户日志中的源文件为 LW-260816Z-A Visitor.xls,源大小 9,377 字节,源 MIME 为 application/vnd.ms-excel; Charset=UTF-8,并带有独立 SHA-256。
  • 历史 ERP 实时采集记录确认 /System/Business/orders_Visitor.asp 的响应虽然声明 application/vnd.ms-excel,但首字节是 HTML 文档头,属于 HTML-in-XLS wrapper,不是标准 BIFF/OLE .xls。
  • 桌面 Excel 会兼容解析这种 HTML 表格;手机 Office/微信通常同时检查扩展名与文件签名,遇到“.xls 文件名 + HTML 内容”会提示格式不支持。这与用户“电脑能开、手机和微信打不开”的现象一致。
  • 插件 chrome-extension/ltjt-order-assistant/inpage.js 用 response.arrayBuffer() 读取 ERP 响应,再计算 SHA-256/base64;没有文本转码或重写。
  • 控制面 prepareExecutionArtifacts() 对 visitor-list 直接沿用源字节、源文件名和源 MIME;OSS 写入设置 attachment disposition 并保留 MIME。当前证据不支持平台或微信链路把文件内容损坏,问题边界在 ERP 源格式。
  • 仅把扩展名改成 .xlsx 或只改 MIME 不能修复;要在手机/微信打开,必须生成真实 .xlsx(保留表格语义)或 PDF。
  • 用户已确认双文件方案:原始 .xls 仅作为平台源归档,真实 .xlsx 作为移动端/AgentBus 交付文件;其他类型仍按 PDF 规则处理。
  • convertDocumentToXlsx() 识别 HTML-in-XLS,调用 LibreOffice Calc MS Excel 2007 XML,校验 ZIP/XLSX magic;转换失败返回 source_fallback,任务层对 visitor-list fail-closed,不把原始 XLS 发送给 AgentBus。
  • 游客导出报告现在同时记录 source_artifact_count=1、derived_artifact_count=1、xlsx_count=1 和 delivered_artifact_count=2;原始 artifact 标记 artifact_role=source_archive、agentbus_visible=false,XLSX 标记 artifact_role=mobile_delivery、agentbus_visible=true。
  • reply-contract.ts 和 agentbus.ts 均过滤 agentbus_visible=false,因此用户回执文本、普通附件元数据、直连与耐久 AgentBus outbox 都只暴露 XLSX。
  • 已用 artifact-tool 导入并检查真实 XLSX:工作表单元格可读取,渲染预览正常,文件头为 ZIP/XLSX;验证使用 LibreOffice 实际转换路径而非仅改扩展名。
  • 本轮复现进一步确认:同一 HTML 内容临时文件名为 .xls 时,LibreOffice 将其识别为 Calc document 并成功生成 6KB 有效 XLSX;临时文件名为 .html 时则识别为 Writer/Web document 并 SIGABRT。修复已将 HTML 源临时扩展名固定为 .xls,并让回归测试断言该导入路径。
  • 修复后的完整门禁全部通过:check:repo 9/9、类型检查、控制面 66/66、legacy 214/214、build、git diff --check;面板已重启,新 PID 24717 监听 127.0.0.1:8786,live/ready 与 4 个 AgentBus 渠道均正常。

已完成的相关交付

  • confirmation_export 已按类型交付:visitor-list 源 XLS 归档并生成真实 XLSX,AgentBus/微信只返回 XLSX;其余类型 PDF;转换失败回退源文件。
  • 已同步控制面、Skill、输出契约、Schema、mapping、插件提示、测试、版本化 Skill/扩展包、运营 DOCX 和发布清单。
  • 散拼子单导出二次查询已移除固定“收客中”过滤,仍保留母团/子单/ddid/tid 唯一核验。
  • 上一轮验证全部通过:check:repo 9/9、check、控制面 61/61、legacy 208/208、build、git diff --check;Skill 官方校验和 DOCX 15 页渲染检查通过。

约束与证据边界

  • 当前证据是脱敏的响应摘要(路径、状态、MIME、长度、内容特征、哈希),未保存真实游客资料或完整源文件;不能在本地对用户这一个 9,377 字节样本再运行 file/移动端实测。
  • 未读取或输出秘密配置;未执行 ERP 写入、重试、重启、部署或外部发送。
  • 压缩前完整 findings 已冻结到 visitor 移动端诊断前 findings;更早历史事实仍在同目录日期归档中。