Files
LWLT-AIBOT/archive/project-history/2026-08-25/findings-pre-compression-ai-parser-evaluation.md
T

167 lines
35 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.
# 当前关键发现
## 2026-08-25 — AI 解析环节可替代性评估(进行中)
- 当前公开架构已把 AI 边界压缩到“业务语义、字段抽取和归一化”;ERP 查询、内部引用生成、候选唯一解析、执行门禁、写入、写后回查和成功声明均不属于 AI。这意味着本次真正待评估的是自然语言到解析态 operation,而不是整条业务自动化链路。
- Skill 中的必填、枚举、日期、互斥、默认值和确认规则原则上都能编译或重写为确定性程序;但“规则可编码”与“开放自然语言中的意图、实体、指代、缺失和歧义可由同一套确定性程序可靠识别”是两个不同命题。
- 活动业务注册表覆盖新建、修改、名单、五类安排、取消/恢复和文件导出等多类 action;其执行能力和真实验证等级并不一致,因此替代判断必须按 action 与字段拆分,不能用某个规则简单的 action 推导整个 AI 环节。
- 行为注册表明确要求容忍少量错别字、常见简称、非标准首行、正文中出现行为名称和自然表达,并在多目标冲突时追问;这部分不是 ERP 算法,而是开放输入的意图路由与语境判断。若改成纯程序,必须选择“收窄为结构化表单/命令”或为这些变体承担持续词典、语法与冲突消解维护。
- 用户不提供 `tid/ddid/行 ID` 等内部引用,仍由宿主/插件确定性注入;产品、客户、领队等 ERP 实体也由插件进行唯一解析。这进一步缩小了 AI 需要承担的实体链接范围。
- 五个活动 Skill 均以短主文件配合输入/operation/output 契约;`lwlt-newbooking` 另有独立归一化规则。规则已经被显式拆分,便于逐条迁入程序校验,但仍需从契约文本核对哪些条目依赖自然语言语境。
- `lwlt-newbooking` 的输出边界高度结构化:四选一 action、最小必填、日期/人数/房型/别名归一化、固定 `formal`/`dry_run` 和三态结果。这些约束适合由程序做最终裁决;模型价值主要位于从首行与正文识别事实、容忍表达差异和最小追问。
- `lwlt-updating` 要求保留用户明确提出的“全部业务目标”,包括当前尚未自动执行的多类字段,并区分“完整人数组合”与“仅修改某一类别”、目标总数与增减量。若仍接受开放聊天,这类“说了什么/没说什么/修饰哪个字段”的语义边界比固定表单解析更难用有限规则穷尽;若改用字段化 UI,则可以程序化。
- `lwlt-arrangement` 的 action 与字段集合有限,日期/数量/资源搜索词也适合程序校验;候选组合文本的模糊匹配、联动字段和默认首条选择已经明确交给业务系统。因此在采用标准模板或表单时,这一 Skill 是最适合优先做无 AI 解析试点的类别之一;保留自由聊天时仍要处理“新增安排”与“安排变更”、日期角色和备注边界。
- `lwlt-lifecycle` 中名单的 13 列、完整性、序号、重复项和覆盖确认都天然适合确定性程序;订单候选检索和补充校验也已在插件侧。剩余模型职责主要是识别名单/取消/恢复意图、从混合正文中分离检索字段与表格,以及理解补充/覆盖的会话语义。
- `lwlt-confirmation` 是最窄的解析面:固定 action、有限文件类型别名、“全部”展开和接机牌姓名条件追问,绝大多数可由词典 + Schema + 表单程序实现;AI 的边际价值主要是兼容非标准文件名称及混合自然表达。
- 单一 Agent Prompt 明确把“结合完整正文和上下文”“容忍错别字/简称/自然表达”“补充上一轮资料而不重复格式”“多个业务目标冲突时阻断”设为产品能力。这些要求正是纯确定性解析器最难维持等价覆盖的部分;若愿意取消这些体验、强制选择 action 并填写字段,AI 可以被完全移除,但这是交互契约变更而非单纯技术替换。
- 新建业务的活动输入本身已有高度规范的“字段名:值”模板;在模板遵从度高的流量上,action 路由、必填校验、下一次发生日补年、日期范围、人数和房型表达都可用确定性 parser 实现。当前宿主甚至已对无年份新建日期做了确定性二次归一化,说明规则迁出 AI 在实践中已有先例。
- 新建契约仍保留稀疏人数对象、姓名与人数“领队”消歧、客户原文与纠错后搜索名双轨等语义细节;这些可编码,但必须用针对真实表达的语法/词典与回归集覆盖,不能只把 Markdown 条款逐句翻译成 if/else 就假定等价。
- 修改契约允许 `prices.*` 等开放 target、最多 32 个动作,并要求所有明确目标原样保留,即使下游暂不能执行。这提高了纯 parser 的长期维护面:每出现新字段表达或复合句式,都需同步词典、语法、Schema 映射和测试;表单路线则可把这部分成本转为 UI 字段维护。
- 五类 Skill 的运营契约现在都提供固定首行、固定字段标签和明确值格式。若把“必须使用模板或表单”设为新输入契约,解析层可用 label parser + 类型转换 + Schema 校验完全替代 AI;此结论对模板内输入成立,不代表对当前允许的任意自然表达成立。
- 安排与导出契约的枚举、必填条件和条件追问是有限状态机问题;名单 TSV 是表格解析问题。它们具备低风险的确定性 fast path。修改类的自由目标段和一条消息多目标拆分则应作为最晚迁移或继续交给受约束模型的部分。
- 多处契约强调“只输出用户明确提供的字段”“原文未明确对象类型时不要猜”“旧上下文的过时必填不得触发追问”。这些负向语义条件很重要:纯规则系统不只要识别正向关键词,还要正确处理否定、缺省、旧上下文污染和字段作用域。
- 四个新增业务页都明确分成“用户事实 → Skill 归一化 → ERP 派生/结果”三层;客户/产品 ID、联动默认值、团号、人员、保存回执和回查已全部在确定性层。AI 不是业务正确性的最终裁决者,而是把用户事实填进受限 operation 的前端翻译器。
- 业务页也揭示一个重要成本差异:AI 层字段虽少,ERP 执行层包含页面联动、候选唯一性、提交安全门与 fresh requery,复杂度和风险明显更高。移除 AI 只会改变输入翻译,不会显著简化这些核心 ERP 适配代码或真实验证负担。
- 现有模板已有足够强的机器可读结构,因此可设计“确定性优先”:严格模板/表单直接编译为 operation;只有非标准表达、跨轮补充或规则 parser 置信不足时进入 AI。该方案能降低调用量,同时保持现有自然语言兼容。
- 项目已有独立的 `agent_parse_result`、`agent_operation` 与更完整的 `standard_system_operation` Schema,以及页面级表单 Schema/mapping。无论是否保留 AI,Schema 校验都应继续作为确定性信任边界;替代 AI 不等于取消契约或直接让文本驱动 ERP。
- 解析态 Schema 将 AI 输出限制为 16 个 action、固定 `formal`/`dry_run`、封闭 `data` 属性和 action-specific 必填/互斥条件;解析信封也只有 passed/needs_input/blocked 三态。这证明 AI 后端接口本身完全可以由任何确定性编译器实现,模型不是协议所必需。
- Schema 只能证明结构合法,不能证明文本语义被正确理解。例如它无法单凭 JSON 证明用户是否“明确”提供某字段、复合人数是否被正确拆分、日期角色是否选对、否定句是否被尊重或问题是否真的是最小追问。因此“现有 Schema 校验通过”不能作为纯规则与 AI 语义等价的充分证据。
- `agent_parse_needs_input` 允许开放的 `captured_facts` 和自然语言 questions/reply;若采用无 AI 方案,最好把澄清也收敛为由缺失字段表驱动的固定问题,避免重新引入难审计的自由文本状态机。
- 执行态 Schema 比解析态多出 ERP 派生字段、运行证据和兼容/测试 action;lifecycle mapping 又定义唯一解析、fresh current values、写前门禁、明确成功响应与 fresh requery。AI 输出必须经过这些确定性阶段才能执行,现有架构已经正确地把概率模型放在低信任区。
- lifecycle mapping 的内容量和条件复杂度远高于五个 Skill 的字段提取规则,表明“业务规则”并不都在 Skill 中:真正决定能否安全执行的规则已在程序、Schema 和 mapping。即便完全移除 AI,插件/控制面绝大多数复杂度、测试与真实 ERP 验证仍然保留。
- 因此替代 AI 的主要收益应按解析调用成本、延迟、可用性、数据出域和输出稳定性衡量;不能把它包装成重写整个业务流程或显著降低 ERP 适配维护量。主要新增成本则是自然语言 parser/表单、词典、会话状态与长期回归维护。
- 当前 `external-agent-client.mjs` 不是单纯模型调用:它已有本地结果归一化、无年份日期处理、解析态/执行态 operation 验证、SSE/超时/重试/会话恢复和 canonical operation 输入识别。说明系统已经采用“AI 提议 + 程序校验/修复”的混合形态,并存在结构化 operation 绕过语义模型的代码入口,需要进一步核对其实际边界。
- 该客户端约 3,236 行、对应测试约 1,672 行;移除外部 AI 可以删除或隔离一部分网络/SSE/重试复杂度,但本地规范化、Schema 验证、任务状态和安全门仍必须保留。替代工程不是简单删除一个 API 调用。
- 已确认原始输入若本身是合法 operation JSON,系统会完全绕过外部 Agent,使用本地 execution validator 后进入 `canonical_json` 模式;通过时标记 `canonical-json-v1`。因此“业务系统直接产生结构化 operation”在当前架构中不是理论可能,而是已有正式代码路径。
- 普通文本路径仍依赖外部会话、SSE、超时、重试、恢复和一次契约修复;服务未配置或响应不确定时 fail-closed。用本地确定性 parser 覆盖标准模板可直接消除这些请求的外部可用性、延迟与契约修复风险。
- 宿主已经在模型返回后确定性重做无年份新建日期归一化,并专门拦截过时的“安排其他/备案”追问。这是强证据:关键业务规则不应只信任 Skill/模型,适合继续迁入程序;但这些后置修正仍没有替代最前面的自由文本语义识别。
- `validateAgentOperation()` 已用程序实现 action-specific 字段白名单、必填、日期范围、人数/房型、名单 13 列、更新值类型/重复 target、安排条件、导出类型和接机牌姓名等大量 Skill 条款。换言之,当前多数“规则”已经同时存在于程序 validator 中;AI 主要负责从文本提出候选 operation,而非独占规则执行。
- 当前本地非 AI 入口只识别完整 JSON operation,没有发现可把固定 Markdown 模板直接解析为 operation 的生产 parser。故现状下移除外部 AI 后,普通文本输入会失去解析能力;必须新增 label/form parser,或要求上游直接提交 JSON/表单,不能仅靠现有 validator 替代。
- 稳定 fixture 主体是标准模板,但明确要求把“独立团批 量下单”、行为行不在首行、乃至没有行为名称而只有“请批量安排这个独立团的多个发团日期”识别为同一 action。这是当前产品契约中纯 label parser 不覆盖的代表性长尾。
- 仓库内目前看到的是设计 fixture 和契约测试,而不是经过脱敏标注的真实生产输入分布;因此无法仅凭源码客观断言“实际 95% 都是模板”或给出准确替代率。任何比例结论必须通过历史任务脱敏抽样或双跑 shadow evaluation 获取,不能凭观感。
- `samples/` 只有两个结构化 operation 示例,且是较早的 test/dry-run 执行态形状,不包含可用于评估自然语言 parser 的原始文本—标准答案对。现有样例不能支持比较 AI 与规则 parser 的语义准确率。
- 解析客户端测试主要用预构造 JSON/SSE 响应验证传输、契约、日期后置归一化和门禁;“18 条路由”测试也是直接构造 operation 再过 validator/plugin front gate。它没有把同一批真实自然语言同时交给 AI 与规则 parser 比对,因此现有全绿测试不代表自然语言解析准确率已被测量。
- 这也意味着当前 AI 本身的语义质量同样没有被仓库中的离线 gold corpus 量化。客观决策不应把“AI 已使用一段时间”当作质量证据,也不应把“规则看起来完整”当作替代证据;两者都应接受同一套标注样本评测。
- 控制面通过可注入的 `ExternalParser.parse(...)` 接口使用解析器,参数已经包含 rawText、taskId、turnNo、sessionId、history 和 signal;技术上可替换为本地 parser 或路由器,不需要改写 ERP 执行链。现有 UI/日志中的“AI 正在拆解”文案和外部 session 表则需要兼容或重命名。
- 消息路由已经用确定性前缀表 + NFKC/去空格判断“新任务还是上一任务补充”,说明有限路由规则确实有效;但它只检查首个非空行和已登记前缀,并不承担行为在正文、错别字或无指令自然句的完整 action 识别。
- 多轮补充不是外部模型独有,但替代实现必须保留同一任务的已捕获字段、缺失字段、当前轮覆盖规则和新任务切分;只做无状态正则会在续问场景产生功能倒退。
- `ExternalParser` 接口本身只约束 `parse()` 和可选 `checkConnection()`,解析结果进入同一 passed/needs_input/blocked 状态机;替换耦合较低。真正需要清理的是 `agent_sessions`、`agent_returned`、`aiServiceConnected` 和“AI 正在拆解”这类命名/观测语义,而不是任务或 ERP 契约。
- 结构化 parser 与 AI parser 可以并存于同一接口:控制面无需知道结果来自模型、模板编译器还是人工表单。推荐把 provenance 改为中性的 `parser_kind/parser_version`,保留审计和回滚能力。
- 运营总模板明确要求“第一行一个业务指令、第二行起一行一个字段”,覆盖 18 个运营入口;若这才是强制产品契约,则所有入口都具备程序化基础,其中修改类可通过动态字段表单或受限 DSL 处理。此时外部 AI 对合规输入的必要性很低。
- 但 Agent Prompt/行为注册表又把错别字、非标准位置、自然表达和跨轮自由补充定义为应支持能力。仓库当前同时存在“严格模板入口”和“宽松自然语言兼容”两套承诺;评估结论必须明确:完全移除 AI 只能在收窄输入契约或新建足够成熟的 NLP parser 后成立。
- 活动运营模板仍写有“产品来源地与客户来源必须兼容”,而较新的活动业务页、mapping 和 findings 已明确取消该跨字段强制门禁。这暴露了文字规则多点同步的漂移风险。把可执行规则集中到程序/Schema 会改善一致性,但输入说明、词典和程序仍需生成式同步与契约测试,不能仅靠一次性改写。
- 解析链记录逐任务 timeline、event_count 和 contract_repair_count,但当前活动源码未见 token/费用或聚合解析延迟、成功率、人工纠正率指标。没有这些基线,暂时无法客观计算“移除 AI 可节省多少成本/时间”;应先补观测再做 ROI 决策。
- 平台 README 再次确认外部 Agent 模块只把原始指令转成解析态 JSON,管理员确认、插件、ERP 提交与回查完全在其范围外。替换该模块的爆炸半径可控,但收益同样局限在解析阶段。
- 当前工作区干净;本轮只更新 planning 文件,不改业务实现、不调用外部 Agent、不触发 ERP 或外发,并按用户要求不使用子智能体。
## 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](archive/project-history/2026-08-18/findings-pre-compression-visitor-mobile-diagnosis.md);更早历史事实仍在同目录日期归档中。