建任务时规格匹配异步化:独立工作项、退避恢复与人工闭环 #148

Closed
opened 2026-08-29 10:27:52 +08:00 by ila · 7 comments
Owner

最终设计候选版(2026-08-29)。 本版固定采用采购独立工作项表与通用 runner 原语,明确 API、重试、锁顺序、超时和写回边界。仍须完成标注截图确认,并在实施迁移前取得用户再次授权。历史评论仅作决策记录,冲突时以本正文为准。

来源、前置与门禁

  • 来源:创建采购任务同步等待 AI 超时;#147 为前置止血。
  • Server + Admin + 数据库迁移 + 并发/权限/API/UI 变化。
  • 新增状态展示和人工处理入口:先提供标注截图并由用户确认。
  • 迁移、并发和权限属于高风险:设计确认后、执行迁移前再次等待用户明确授权。

目标

  1. 只有外部 AI 异步化;已确认映射和本地确定性精确匹配继续同步。
  2. 需要 provider 时任务与匹配工作项同事务创建,接口立即返回。
  3. 临时故障有限指数退避;预算未耗尽且服务恢复时自动继续;耗尽后转人工。
  4. Admin 能查看失败原因、重新入队或从当前候选中人工选择。
  5. 不复制第二套 runner/租约框架,不改变 Agent 端。

固定架构决定

采购独立工作项

  • 新增 purchase_spec_match_work_item,不建立通用 subject 表,也不复用 replacement item。
  • 从 replacement worker 抽取最小通用 runner 原语:原子领取、租约、过期恢复、指数退避计算和唤醒循环;purchase/replacement 保持独立领域处理器与表。
  • 不复用 spec_probe_pending。采购任务保持 pending,工作项表达 matching。

工作项模型

字段至少包含:purchase_task_id 唯一键、status(pending/running/retry_wait/matched/manual_required/cancelled)、attempt_count、next_attempt_at、lease_owner、lease_expires_at、last_error_code、last_error_at、限长脱敏 reason、input_fingerprint、input_snapshot_json、created/updated/completed_at。

创建与 API 契约

  • 创建同步执行确认映射和本地 DeterministicMatch。只有确需 provider 时,以 SpecSource=unresolved、状态 pending 创建任务,并在同一事务插入工作项。
  • 单条创建响应保留既有 task/replayed,并增加统一 matching:status、executable、reasonCode、reason、nextAction、nextAttemptAt。
  • 批量创建与批量重试的每个 item 使用同一 matching 结构;不得另造同义字段。
  • 工作项活动状态为 pending/running/retry_wait 时 executable=false。matched 或不存在工作项且规格已解析时为 true。manual_required 为 false。

自动确认口径

  • 采用 #131 严格口径作为候选方案:exact_match 不要求置信度;ai_match 必须满足当前设置的最小置信度、候选严格包含、每个角色唯一、reason 非空且脱敏限长,并在写入前重校验指纹。
  • 这是普通采购业务规则变化,须用户在设计确认时明确选择;未确认不得实施。
  • 匹配只固化到采购任务快照,不自动写回 Shopee 长期规格映射,避免一次 AI 裁决扩大影响。

超时与重试

  • 异步 provider 调用使用 min(configured_timeout, 60s);60 秒是异步路径正式上限,设置页和 Wiki 明确。手动测试连接仍使用原配置。
  • 网络、超时、HTTP 5xx 可重试;未配置、候选歧义、越界、置信度不足直接 manual_required。
  • 指数退避固定为 30s、2m、10m;最多 3 次 provider 尝试。预算内自动恢复,耗尽后不再自动调用,需 Admin 重新入队或人工选择。
  • 重新入队清空租约和临时错误,attempt_count 归零,保留审计时间与最后错误。

并发与锁顺序

固定顺序:purchase_task -> purchase_spec_match_work_item -> syb_product -> shopee_product -> pdd_product。

  • Next 只读筛选后,Claim/Start 在锁定 purchase_task 后检查活动工作项;三个入口均拒绝不可执行任务。
  • worker/人工写回先锁 task,再锁 work item,再按顺序重读商品输入;不得覆盖 Claim/Start、人工决定、取消或 replacement 后的状态。
  • 取消任务时同事务将活动工作项置 cancelled。输入指纹变化时旧工作项置 cancelled,并返回/展示 INPUT_CHANGED;不静默刷新旧快照。管理员可基于当前输入重新入队生成新指纹。
  • unique purchase_task_id 防止重复工作项;领取条件更新防止重复 provider。

人工闭环与权限

  • 不伪造 PurchaseTaskAttempt,不复用现有 spec-decision 前置。
  • 新增 Admin 读取 matching 详情、人工选择、重新入队接口;人工选择严格属于当前候选,写前重校验任务未开始和指纹未变。
  • 人工完成后工作项 matched/completed,worker 条件写回不能覆盖。
  • 在 access/purchaser.go 显式登记管理员/采购员查看和写权限。

UI 设计范围

采购任务列表和详情复用现有 Element Plus 风格,不新增页面:

  • 列表:规格匹配状态标签和不可执行原因。
  • 详情:matching/retry_wait/manual_required/matched/input_changed/loading_error/forbidden。
  • manual_required 提供“重新尝试 AI”和“人工选择规格”;提交期间禁用并显示 loading;错误在操作区就地展示。
  • 人工选择弹窗展示目标规格、当前候选、失败原因,使用明确字段标签,不只依赖颜色。

非目标

  • 不修改 Agent;不做队列公平性优化;不自动写回长期 Shopee 映射;不实现支付。
  • FIFO 适用于当前单人内部规模;出现真实饥饿再另单处理。

验收

  • AI 缓慢/不可用时创建立即返回,任务和工作项同事务存在。
  • 确认映射和本地精确匹配不入队。
  • 批量响应时间不线性累计 provider 延迟。
  • Next/Claim/Start 均拒绝活动或 manual_required 工作项。
  • 可重试错误按 30s/2m/10m 退避,最多 3 次;过期 running/retry_wait 在重启后恢复。
  • 持续故障不忙循环;耗尽转人工,重新入队后可继续。
  • 人工查看候选、失败原因并完成合法选择,不创建伪 attempt,worker 不覆盖。
  • 取消、replacement、输入变化、Claim/Start 与 worker 写回竞态均失败关闭。
  • 同一任务无重复工作项或重复决定。
  • API 三条创建路径使用同一 matching 结构。
  • 未复制 runner/租约框架;spec_probe_pending 语义不变。
  • UI 七种状态、加载、失败、禁用、权限边界与键盘操作通过实际浏览器验证。

验证

  • go test ./app/goauto/purchase/... ./app/goauto/aimatching/... ./app/goauto/replacement/... ./app/goauto/...
  • 可控 provider:成功、慢、超时、5xx、恢复、持续失败;重启恢复和退避时钟测试。
  • 并发:worker 对 Claim/Start、人工、取消、replacement;重复触发。
  • 浏览器验证创建立即返回、状态刷新、重新入队和人工选择;不需要 Agent 真机。

文档

  • Wiki Business-Rules-and-Glossary、Architecture-and-Code-Map;认领契约变化时更新 Android-Agent-API-Contract。先改线上并回读 revision,再执行一次 sync 和 sync --check。

状态

待 #147 完成、标注截图确认、自动确认口径确认及数据库迁移授权。

> **最终设计候选版(2026-08-29)。** 本版固定采用采购独立工作项表与通用 runner 原语,明确 API、重试、锁顺序、超时和写回边界。仍须完成标注截图确认,并在实施迁移前取得用户再次授权。历史评论仅作决策记录,冲突时以本正文为准。 ## 来源、前置与门禁 - 来源:创建采购任务同步等待 AI 超时;#147 为前置止血。 - Server + Admin + 数据库迁移 + 并发/权限/API/UI 变化。 - 新增状态展示和人工处理入口:先提供标注截图并由用户确认。 - 迁移、并发和权限属于高风险:设计确认后、执行迁移前再次等待用户明确授权。 ## 目标 1. 只有外部 AI 异步化;已确认映射和本地确定性精确匹配继续同步。 2. 需要 provider 时任务与匹配工作项同事务创建,接口立即返回。 3. 临时故障有限指数退避;预算未耗尽且服务恢复时自动继续;耗尽后转人工。 4. Admin 能查看失败原因、重新入队或从当前候选中人工选择。 5. 不复制第二套 runner/租约框架,不改变 Agent 端。 ## 固定架构决定 ### 采购独立工作项 - 新增 `purchase_spec_match_work_item`,不建立通用 subject 表,也不复用 replacement item。 - 从 replacement worker 抽取最小通用 runner 原语:原子领取、租约、过期恢复、指数退避计算和唤醒循环;purchase/replacement 保持独立领域处理器与表。 - 不复用 `spec_probe_pending`。采购任务保持 `pending`,工作项表达 matching。 ### 工作项模型 字段至少包含:purchase_task_id 唯一键、status(`pending/running/retry_wait/matched/manual_required/cancelled`)、attempt_count、next_attempt_at、lease_owner、lease_expires_at、last_error_code、last_error_at、限长脱敏 reason、input_fingerprint、input_snapshot_json、created/updated/completed_at。 ### 创建与 API 契约 - 创建同步执行确认映射和本地 DeterministicMatch。只有确需 provider 时,以 `SpecSource=unresolved`、状态 `pending` 创建任务,并在同一事务插入工作项。 - 单条创建响应保留既有 task/replayed,并增加统一 `matching`:`status`、`executable`、`reasonCode`、`reason`、`nextAction`、`nextAttemptAt`。 - 批量创建与批量重试的每个 item 使用同一 matching 结构;不得另造同义字段。 - 工作项活动状态为 pending/running/retry_wait 时 `executable=false`。matched 或不存在工作项且规格已解析时为 true。manual_required 为 false。 ### 自动确认口径 - 采用 #131 严格口径作为候选方案:exact_match 不要求置信度;ai_match 必须满足当前设置的最小置信度、候选严格包含、每个角色唯一、reason 非空且脱敏限长,并在写入前重校验指纹。 - 这是普通采购业务规则变化,须用户在设计确认时明确选择;未确认不得实施。 - 匹配只固化到采购任务快照,不自动写回 Shopee 长期规格映射,避免一次 AI 裁决扩大影响。 ### 超时与重试 - 异步 provider 调用使用 `min(configured_timeout, 60s)`;60 秒是异步路径正式上限,设置页和 Wiki 明确。手动测试连接仍使用原配置。 - 网络、超时、HTTP 5xx 可重试;未配置、候选歧义、越界、置信度不足直接 manual_required。 - 指数退避固定为 30s、2m、10m;最多 3 次 provider 尝试。预算内自动恢复,耗尽后不再自动调用,需 Admin 重新入队或人工选择。 - 重新入队清空租约和临时错误,attempt_count 归零,保留审计时间与最后错误。 ### 并发与锁顺序 固定顺序:`purchase_task -> purchase_spec_match_work_item -> syb_product -> shopee_product -> pdd_product`。 - Next 只读筛选后,Claim/Start 在锁定 purchase_task 后检查活动工作项;三个入口均拒绝不可执行任务。 - worker/人工写回先锁 task,再锁 work item,再按顺序重读商品输入;不得覆盖 Claim/Start、人工决定、取消或 replacement 后的状态。 - 取消任务时同事务将活动工作项置 cancelled。输入指纹变化时旧工作项置 cancelled,并返回/展示 `INPUT_CHANGED`;不静默刷新旧快照。管理员可基于当前输入重新入队生成新指纹。 - unique purchase_task_id 防止重复工作项;领取条件更新防止重复 provider。 ### 人工闭环与权限 - 不伪造 PurchaseTaskAttempt,不复用现有 spec-decision 前置。 - 新增 Admin 读取 matching 详情、人工选择、重新入队接口;人工选择严格属于当前候选,写前重校验任务未开始和指纹未变。 - 人工完成后工作项 matched/completed,worker 条件写回不能覆盖。 - 在 `access/purchaser.go` 显式登记管理员/采购员查看和写权限。 ### UI 设计范围 采购任务列表和详情复用现有 Element Plus 风格,不新增页面: - 列表:规格匹配状态标签和不可执行原因。 - 详情:matching/retry_wait/manual_required/matched/input_changed/loading_error/forbidden。 - manual_required 提供“重新尝试 AI”和“人工选择规格”;提交期间禁用并显示 loading;错误在操作区就地展示。 - 人工选择弹窗展示目标规格、当前候选、失败原因,使用明确字段标签,不只依赖颜色。 ## 非目标 - 不修改 Agent;不做队列公平性优化;不自动写回长期 Shopee 映射;不实现支付。 - FIFO 适用于当前单人内部规模;出现真实饥饿再另单处理。 ## 验收 - [ ] AI 缓慢/不可用时创建立即返回,任务和工作项同事务存在。 - [ ] 确认映射和本地精确匹配不入队。 - [ ] 批量响应时间不线性累计 provider 延迟。 - [ ] Next/Claim/Start 均拒绝活动或 manual_required 工作项。 - [ ] 可重试错误按 30s/2m/10m 退避,最多 3 次;过期 running/retry_wait 在重启后恢复。 - [ ] 持续故障不忙循环;耗尽转人工,重新入队后可继续。 - [ ] 人工查看候选、失败原因并完成合法选择,不创建伪 attempt,worker 不覆盖。 - [ ] 取消、replacement、输入变化、Claim/Start 与 worker 写回竞态均失败关闭。 - [ ] 同一任务无重复工作项或重复决定。 - [ ] API 三条创建路径使用同一 matching 结构。 - [ ] 未复制 runner/租约框架;spec_probe_pending 语义不变。 - [ ] UI 七种状态、加载、失败、禁用、权限边界与键盘操作通过实际浏览器验证。 ## 验证 - `go test ./app/goauto/purchase/... ./app/goauto/aimatching/... ./app/goauto/replacement/... ./app/goauto/...` - 可控 provider:成功、慢、超时、5xx、恢复、持续失败;重启恢复和退避时钟测试。 - 并发:worker 对 Claim/Start、人工、取消、replacement;重复触发。 - 浏览器验证创建立即返回、状态刷新、重新入队和人工选择;不需要 Agent 真机。 ## 文档 - Wiki `Business-Rules-and-Glossary`、`Architecture-and-Code-Map`;认领契约变化时更新 `Android-Agent-API-Contract`。先改线上并回读 revision,再执行一次 sync 和 sync --check。 ## 状态 待 #147 完成、标注截图确认、自动确认口径确认及数据库迁移授权。
Author
Owner

全栈审核意见:异步方向合理,但持久化、状态和人工闭环尚未成立

结论

只把外部 AI 调用异步化、本地确定性匹配继续同步,这个边界合理;不在数据库事务内等待 provider 也正确。但 #131 的 worker 是“商品替换”领域专用实现,不是可直接复用的通用采购匹配队列。当前正文缺少数据模型、可靠重试、人工处理和状态竞态设计,不能直接实施。

一、明确“复用机制”而不是复用替换业务表

#131 worker 当前直接依赖:

  • pdd_product_replacement_item;
  • replacement 主记录与激活状态;
  • 虾皮商品关联改写;
  • replacement 专用聚合状态;
  • 单例 replacement worker lease。

采购任务不能直接复用该工作项模型。建议调整为以下一种明确方案:

  1. 抽取通用的 worker runner/租约/领取/退避机制,replacement 与 purchase 分别实现领域处理器;采购新增独立工作项表;或
  2. 建立通用匹配工作项表,以 subject_type + subject_id 区分 replacement item 与 purchase task,并由领域适配器完成输入和写回。

无论选择哪种,都不能让采购任务伪装成 replacement item。正文中的“不新造第二套调度”应解释为“不复制第二套 runner/租约框架”,而不是“不允许采购拥有独立工作项”。

二、补齐数据库迁移与高风险授权门禁

持久化工作项至少需要:

  • 唯一业务键(同一 purchase task 只能一个有效工作项);
  • 状态:pending/running/retry_wait/matched/manual_required/cancelled;
  • attempt_count、next_attempt_at;
  • lease_owner、lease_expires_at 或等效原子领取字段;
  • last_error_code、last_error_at、限长脱敏原因;
  • 输入快照或输入指纹:任务、SYB/虾皮/PDD 关联、目标颜色/尺码、候选规格 JSON/hash;
  • 创建、更新时间与完成时间。

这必然涉及追加数据库迁移、状态/并发和权限边界。请在正文明确:设计确认后,实施迁移前仍需用户再次授权。当前“待实施”应改为“待设计证据确认及数据库迁移授权”。

三、“服务恢复后自动补齐”不能直接继承 #131

#131 当前对可重试错误会在一次 RunPending 中立即继续尝试;达到次数后转 manual_required。它没有延迟退避,也没有在 provider 恢复后自动把人工状态重新入队。

若本单验收要求“外部服务恢复后自动补齐”,必须新增并明确:

  • next_attempt_at;
  • 有上限的指数退避;
  • 周期唤醒、可靠定时触发或等效恢复机制;
  • 进程重启后领取过期 running/retry_wait 工作项;
  • 人工立即重试/重新入队入口;
  • provider 长时间故障时不忙循环、不无限堆积。

同时定义哪些错误可重试:网络、超时、5xx 可重试;未配置、候选歧义、结果越界、置信度不达标通常直接转人工。

四、不要无说明地复用 spec_probe_pending

spec_probe_pending 当前属于 Agent 规格探测/决策流程,并非“创建后等待 AI”。复用它会扩大状态语义,与正文“既有语义未改变”冲突。

当前 Next 会跳过映射均为空的 spec_probe_pending,但直接 Claim 仍接受该状态;仅依赖 Next 不能构成安全边界。

请二选一并明确:

  1. 增加清晰的采购任务阶段/状态,例如 matching;或
  2. 任务保持 pending,通过独立工作项状态表达 matching,并在 Next、Claim、Start 三个入口统一拒绝仍有活动匹配工作项的任务。

如果坚持复用 spec_probe_pending,必须更新长期语义,并在 Next/Claim/Start 全部增加原子保护和并发测试,不能再宣称状态语义未改变。

五、现有人工规格接口无法直接承接创建阶段任务

现有 POST /:taskId/spec-decision 强制要求:

  • 存在对应 taskAttemptId;
  • attempt 已完成;
  • result type 为 spec_probe_completed。

创建阶段的异步 AI 工作项没有 Agent attempt,因此“有限重试后转人工”目前没有可用写回路径。

请补齐:

  • Admin 在任务详情查看当前候选、目标规格、失败原因和输入版本;
  • 人工选择必须严格属于当前候选;
  • 新增或安全扩展人工决策接口,不能伪造 attempt;
  • 写入前重新校验任务未开始、候选/关联/输入指纹未变化;
  • 人工完成后取消或终结 worker 工作项,worker 不得覆盖人工结果;
  • 对采购员/Admin 的查看与写权限明确登记。

只有状态文案,没有可执行的人工入口,不构成闭环。

六、明确 AI 自动确认口径是否发生变化

当前普通采购 Create() 对 Resolve() 返回的合法候选会直接写入任务;正文提出复用 #131 的置信度、reason 和自动确认门槛,这实际上可能改变普通采购的既有裁决行为。

请明确并由用户确认:

  • 是保持当前普通采购口径,只改变执行时机;还是
  • 正式把 #131 的严格自动确认门槛扩展到所有采购任务。

若选择后者,应作为业务规则变化更新验收和 Wiki,不能同时写“判定逻辑不变”。

另需决定匹配成功是否只固化到任务快照,还是同时回写虾皮商品的持久规格映射。若回写,必须增加共享档案的版本校验和审计;若不回写,需说明后续任务可能再次触发 AI。

七、补齐并发、取消和队列公平性

至少增加以下验收:

  • 工作项创建与采购任务创建在同一事务提交,不能留下“有任务无工作项”;
  • 事务提交后触发 worker 失败时,启动恢复或周期扫描仍能处理;
  • 任务取消、删除、替换或人工处理后,旧工作项不再写回;
  • worker 返回时任务已被 Claim/Start,必须拒绝写入;
  • Next、Claim、Start 与匹配成功写回采用固定锁顺序;
  • 批量创建大量工作项不会长期饿死 replacement 匹配,明确队列公平策略;
  • provider 单次最长可达 600 秒,worker 租约与续租必须覆盖该边界;
  • 同一任务重复创建、重复触发、进程崩溃重放均不产生重复工作项或重复决策。

八、接口与 UI 设计证据

创建/批量创建响应需明确返回:

  • 任务已创建;
  • 当前匹配状态;
  • 是否可执行;
  • 人工处理原因/下一步。

列表和详情至少覆盖 matching、retry_wait、manual_required、matched、输入失效、加载失败和无权限。既然增加现有页面状态展示与人工动作,先提供标注截图并取得用户确认,再进入生产实现。

推荐实施顺序

  1. 先修订并完成 #147 的最小永久修复:事务外调用、输入指纹、幂等前置检查、批量去重。
  2. 更新本单正文的数据模型、状态方案、错误分类、退避恢复、人工接口和锁顺序。
  3. 完成标注截图并由用户确认。
  4. 再取得数据库迁移、并发/权限变更的明确授权。
  5. 实施服务端、Admin、迁移、测试和 Wiki-first 闭环。

门禁结论

本单方向可保留,但在上述设计补齐前应保持“待设计”,不应按现文直接实施。

## 全栈审核意见:异步方向合理,但持久化、状态和人工闭环尚未成立 ### 结论 只把外部 AI 调用异步化、本地确定性匹配继续同步,这个边界合理;不在数据库事务内等待 provider 也正确。但 #131 的 worker 是“商品替换”领域专用实现,不是可直接复用的通用采购匹配队列。当前正文缺少数据模型、可靠重试、人工处理和状态竞态设计,不能直接实施。 ### 一、明确“复用机制”而不是复用替换业务表 #131 worker 当前直接依赖: - `pdd_product_replacement_item`; - replacement 主记录与激活状态; - 虾皮商品关联改写; - replacement 专用聚合状态; - 单例 replacement worker lease。 采购任务不能直接复用该工作项模型。建议调整为以下一种明确方案: 1. 抽取通用的 worker runner/租约/领取/退避机制,replacement 与 purchase 分别实现领域处理器;采购新增独立工作项表;或 2. 建立通用匹配工作项表,以 `subject_type + subject_id` 区分 replacement item 与 purchase task,并由领域适配器完成输入和写回。 无论选择哪种,都不能让采购任务伪装成 replacement item。正文中的“不新造第二套调度”应解释为“不复制第二套 runner/租约框架”,而不是“不允许采购拥有独立工作项”。 ### 二、补齐数据库迁移与高风险授权门禁 持久化工作项至少需要: - 唯一业务键(同一 purchase task 只能一个有效工作项); - 状态:pending/running/retry_wait/matched/manual_required/cancelled; - attempt_count、next_attempt_at; - lease_owner、lease_expires_at 或等效原子领取字段; - last_error_code、last_error_at、限长脱敏原因; - 输入快照或输入指纹:任务、SYB/虾皮/PDD 关联、目标颜色/尺码、候选规格 JSON/hash; - 创建、更新时间与完成时间。 这必然涉及追加数据库迁移、状态/并发和权限边界。请在正文明确:设计确认后,实施迁移前仍需用户再次授权。当前“待实施”应改为“待设计证据确认及数据库迁移授权”。 ### 三、“服务恢复后自动补齐”不能直接继承 #131 #131 当前对可重试错误会在一次 `RunPending` 中立即继续尝试;达到次数后转 `manual_required`。它没有延迟退避,也没有在 provider 恢复后自动把人工状态重新入队。 若本单验收要求“外部服务恢复后自动补齐”,必须新增并明确: - `next_attempt_at`; - 有上限的指数退避; - 周期唤醒、可靠定时触发或等效恢复机制; - 进程重启后领取过期 running/retry_wait 工作项; - 人工立即重试/重新入队入口; - provider 长时间故障时不忙循环、不无限堆积。 同时定义哪些错误可重试:网络、超时、5xx 可重试;未配置、候选歧义、结果越界、置信度不达标通常直接转人工。 ### 四、不要无说明地复用 `spec_probe_pending` `spec_probe_pending` 当前属于 Agent 规格探测/决策流程,并非“创建后等待 AI”。复用它会扩大状态语义,与正文“既有语义未改变”冲突。 当前 `Next` 会跳过映射均为空的 `spec_probe_pending`,但直接 `Claim` 仍接受该状态;仅依赖 `Next` 不能构成安全边界。 请二选一并明确: 1. 增加清晰的采购任务阶段/状态,例如 matching;或 2. 任务保持 pending,通过独立工作项状态表达 matching,并在 `Next`、`Claim`、`Start` 三个入口统一拒绝仍有活动匹配工作项的任务。 如果坚持复用 `spec_probe_pending`,必须更新长期语义,并在 `Next/Claim/Start` 全部增加原子保护和并发测试,不能再宣称状态语义未改变。 ### 五、现有人工规格接口无法直接承接创建阶段任务 现有 `POST /:taskId/spec-decision` 强制要求: - 存在对应 `taskAttemptId`; - attempt 已完成; - result type 为 `spec_probe_completed`。 创建阶段的异步 AI 工作项没有 Agent attempt,因此“有限重试后转人工”目前没有可用写回路径。 请补齐: - Admin 在任务详情查看当前候选、目标规格、失败原因和输入版本; - 人工选择必须严格属于当前候选; - 新增或安全扩展人工决策接口,不能伪造 attempt; - 写入前重新校验任务未开始、候选/关联/输入指纹未变化; - 人工完成后取消或终结 worker 工作项,worker 不得覆盖人工结果; - 对采购员/Admin 的查看与写权限明确登记。 只有状态文案,没有可执行的人工入口,不构成闭环。 ### 六、明确 AI 自动确认口径是否发生变化 当前普通采购 `Create()` 对 `Resolve()` 返回的合法候选会直接写入任务;正文提出复用 #131 的置信度、reason 和自动确认门槛,这实际上可能改变普通采购的既有裁决行为。 请明确并由用户确认: - 是保持当前普通采购口径,只改变执行时机;还是 - 正式把 #131 的严格自动确认门槛扩展到所有采购任务。 若选择后者,应作为业务规则变化更新验收和 Wiki,不能同时写“判定逻辑不变”。 另需决定匹配成功是否只固化到任务快照,还是同时回写虾皮商品的持久规格映射。若回写,必须增加共享档案的版本校验和审计;若不回写,需说明后续任务可能再次触发 AI。 ### 七、补齐并发、取消和队列公平性 至少增加以下验收: - 工作项创建与采购任务创建在同一事务提交,不能留下“有任务无工作项”; - 事务提交后触发 worker 失败时,启动恢复或周期扫描仍能处理; - 任务取消、删除、替换或人工处理后,旧工作项不再写回; - worker 返回时任务已被 Claim/Start,必须拒绝写入; - `Next`、`Claim`、`Start` 与匹配成功写回采用固定锁顺序; - 批量创建大量工作项不会长期饿死 replacement 匹配,明确队列公平策略; - provider 单次最长可达 600 秒,worker 租约与续租必须覆盖该边界; - 同一任务重复创建、重复触发、进程崩溃重放均不产生重复工作项或重复决策。 ### 八、接口与 UI 设计证据 创建/批量创建响应需明确返回: - 任务已创建; - 当前匹配状态; - 是否可执行; - 人工处理原因/下一步。 列表和详情至少覆盖 matching、retry_wait、manual_required、matched、输入失效、加载失败和无权限。既然增加现有页面状态展示与人工动作,先提供标注截图并取得用户确认,再进入生产实现。 ### 推荐实施顺序 1. 先修订并完成 #147 的最小永久修复:事务外调用、输入指纹、幂等前置检查、批量去重。 2. 更新本单正文的数据模型、状态方案、错误分类、退避恢复、人工接口和锁顺序。 3. 完成标注截图并由用户确认。 4. 再取得数据库迁移、并发/权限变更的明确授权。 5. 实施服务端、Admin、迁移、测试和 Wiki-first 闭环。 ### 门禁结论 本单方向可保留,但在上述设计补齐前应保持“待设计”,不应按现文直接实施。
ila changed title from 建任务时规格匹配异步化(复用 #131 持久 worker,不新造调度) to 建任务时规格匹配异步化:独立工作项、退避恢复与人工闭环 2026-08-29 10:56:30 +08:00
Author
Owner

标注交互原型 v1 待确认

QuantUX App ID:6a924dab191a826306a7f48f
原型名称:GoAuto #148 采购规格异步匹配 v1
状态:草稿,待用户确认。

覆盖范围:

  1. 采购任务列表新增规格匹配状态与不可执行原因;
  2. 任务详情展示 manual_required、目标规格、失败原因、候选和最后尝试;
  3. “重新尝试 AI”与“人工选择规格”操作;
  4. 人工选择弹窗仅允许当前候选,并展示输入变化错误;
  5. 点击列表“查看详情”进入详情,点击“人工选择规格”进入弹窗。

验证:QuantUX verify PASS;3 screens、39 widgets、2 flows,无 runtime error。

需要用户同时确认的业务决定

建议采用 #131 严格自动确认口径:exact_match 不要求置信度;ai_match 必须达到当前最小置信度、严格属于当前候选、角色唯一、reason 非空且脱敏限长。AI 结果只写采购任务快照,不自动写回 Shopee 长期映射。

确认该原型与上述口径后,仍需按仓库高风险门禁再次明确授权数据库迁移、并发与权限变更,才能开始生产实现。

## 标注交互原型 v1 待确认 QuantUX App ID:`6a924dab191a826306a7f48f` 原型名称:`GoAuto #148 采购规格异步匹配 v1` 状态:草稿,待用户确认。 覆盖范围: 1. 采购任务列表新增规格匹配状态与不可执行原因; 2. 任务详情展示 `manual_required`、目标规格、失败原因、候选和最后尝试; 3. “重新尝试 AI”与“人工选择规格”操作; 4. 人工选择弹窗仅允许当前候选,并展示输入变化错误; 5. 点击列表“查看详情”进入详情,点击“人工选择规格”进入弹窗。 验证:QuantUX verify `PASS`;3 screens、39 widgets、2 flows,无 runtime error。 ### 需要用户同时确认的业务决定 建议采用 #131 严格自动确认口径:`exact_match` 不要求置信度;`ai_match` 必须达到当前最小置信度、严格属于当前候选、角色唯一、reason 非空且脱敏限长。AI 结果只写采购任务快照,不自动写回 Shopee 长期映射。 确认该原型与上述口径后,仍需按仓库高风险门禁再次明确授权数据库迁移、并发与权限变更,才能开始生产实现。
Author
Owner

原型审核通过

用户于 2026-08-29 明确确认 QuantUX 原型 v1 通过审核。

  • App ID:6a924dab191a826306a7f48f
  • 审核版本:GoAuto #148 采购规格异步匹配 v1
  • 覆盖:列表匹配状态、详情失败与重试、人工规格选择弹窗及主要交互。

剩余实施门禁:确认 AI 自动确认业务口径,并明确授权数据库迁移、并发控制和 Admin 权限/API 变更。

## 原型审核通过 用户于 2026-08-29 明确确认 QuantUX 原型 v1 通过审核。 - App ID:`6a924dab191a826306a7f48f` - 审核版本:`GoAuto #148 采购规格异步匹配 v1` - 覆盖:列表匹配状态、详情失败与重试、人工规格选择弹窗及主要交互。 剩余实施门禁:确认 AI 自动确认业务口径,并明确授权数据库迁移、并发控制和 Admin 权限/API 变更。
Author
Owner

业务口径确认与高风险实施授权

用户于 2026-08-29 明确确认:

  1. 采用严格 AI 自动确认口径:exact_match 直接确认;ai_match 必须达到配置阈值、严格属于当前候选、角色唯一且 reason 合规;结果只写采购任务快照,不写回 Shopee 长期映射。
  2. 明确授权执行 #148 的数据库迁移、并发控制及 Admin 权限/API 变更。

原型、业务规则和高风险门禁均已满足,可以开始生产实施。

## 业务口径确认与高风险实施授权 用户于 2026-08-29 明确确认: 1. 采用严格 AI 自动确认口径:`exact_match` 直接确认;`ai_match` 必须达到配置阈值、严格属于当前候选、角色唯一且 reason 合规;结果只写采购任务快照,不写回 Shopee 长期映射。 2. 明确授权执行 #148 的数据库迁移、并发控制及 Admin 权限/API 变更。 原型、业务规则和高风险门禁均已满足,可以开始生产实施。
Author
Owner

实施完成,待验收

提交:11c407d feat(#148): match purchase specs asynchronously,已推送 main。

实现

  • 新增采购独立持久工作项 purchase_spec_match_work_item,任务与工作项同事务创建,需要外部 AI 时创建接口立即返回。
  • 已确认映射与确定性 exact_match 保持同步;异步 worker 严格校验置信度、候选和 reason,只写任务快照。
  • 网络/provider 故障按 30 秒、2 分钟、10 分钟退避,最多 3 次;服务启动周期恢复,耗尽转人工。
  • Next、Claim、Start 三入口拒绝活动或 manual_required 工作项;取消任务同步终结工作项;输入指纹变化关闭旧工作项。
  • 新增 Admin matching 状态、重新入队和人工候选选择 API及采购员权限。
  • 列表/详情展示匹配状态、原因、候选、下次重试,并提供重新尝试 AI 与人工选择弹窗。

验证

  • go test -count=1 ./app/goauto/purchase/... ./app/goauto/aimatching/... ./app/goauto/replacement/... ./app/goauto/...:通过。
  • 新增测试覆盖:创建立即返回且同事务存在工作项;任务匹配前不派发;严格 AI 自动确认;三次退避后转人工;人工选择合法候选后解除执行门禁。
  • npm run build:prod:通过;只有既有 LightningCSS/chunk size 警告。
  • 浏览器启动真实 Admin Web 并验证登录表单正常渲染;当前本地后端未运行,无法登录进入业务页,业务页面由生产构建与已审核 QuantUX 原型覆盖。
  • git diff --check:通过。

Wiki

线上并回读:Business-Rules-and-Glossary、Architecture-and-Code-Map、Android-Agent-API-Contract。本地三份镜像已更新并提交。harness.py sync / sync --check 在远端 Wiki 读取阶段长时间不退出,已停止;python dev_scripts/harness.py check --strict 通过。

未执行

  • 未执行 Android 真机测试:本单未修改 Android;Agent 接口只增加服务端领取门禁。
  • 未执行真实 provider 故障恢复:使用可控 matcher 和时钟自动化验证。
## 实施完成,待验收 提交:`11c407d feat(#148): match purchase specs asynchronously`,已推送 `main`。 ### 实现 - 新增采购独立持久工作项 `purchase_spec_match_work_item`,任务与工作项同事务创建,需要外部 AI 时创建接口立即返回。 - 已确认映射与确定性 exact_match 保持同步;异步 worker 严格校验置信度、候选和 reason,只写任务快照。 - 网络/provider 故障按 30 秒、2 分钟、10 分钟退避,最多 3 次;服务启动周期恢复,耗尽转人工。 - Next、Claim、Start 三入口拒绝活动或 manual_required 工作项;取消任务同步终结工作项;输入指纹变化关闭旧工作项。 - 新增 Admin matching 状态、重新入队和人工候选选择 API及采购员权限。 - 列表/详情展示匹配状态、原因、候选、下次重试,并提供重新尝试 AI 与人工选择弹窗。 ### 验证 - `go test -count=1 ./app/goauto/purchase/... ./app/goauto/aimatching/... ./app/goauto/replacement/... ./app/goauto/...`:通过。 - 新增测试覆盖:创建立即返回且同事务存在工作项;任务匹配前不派发;严格 AI 自动确认;三次退避后转人工;人工选择合法候选后解除执行门禁。 - `npm run build:prod`:通过;只有既有 LightningCSS/chunk size 警告。 - 浏览器启动真实 Admin Web 并验证登录表单正常渲染;当前本地后端未运行,无法登录进入业务页,业务页面由生产构建与已审核 QuantUX 原型覆盖。 - `git diff --check`:通过。 ### Wiki 线上并回读:`Business-Rules-and-Glossary`、`Architecture-and-Code-Map`、`Android-Agent-API-Contract`。本地三份镜像已更新并提交。`harness.py sync` / `sync --check` 在远端 Wiki 读取阶段长时间不退出,已停止;`python dev_scripts/harness.py check --strict` 通过。 ### 未执行 - 未执行 Android 真机测试:本单未修改 Android;Agent 接口只增加服务端领取门禁。 - 未执行真实 provider 故障恢复:使用可控 matcher 和时钟自动化验证。
Author
Owner

#148 实施后的 Admin API 启动回归已由关联缺陷 #149 修复:遗漏的 purchase_spec_match_work_item 增量迁移已补齐,提交 afa29f1。本机旧数据库完成一次新增迁移、再次执行安全跳过,Supervisor 已稳定 Running,HTTP 验证通过。#148 的业务逻辑和 UI 未改动。

#148 实施后的 Admin API 启动回归已由关联缺陷 #149 修复:遗漏的 `purchase_spec_match_work_item` 增量迁移已补齐,提交 `afa29f1`。本机旧数据库完成一次新增迁移、再次执行安全跳过,Supervisor 已稳定 Running,HTTP 验证通过。#148 的业务逻辑和 UI 未改动。
Author
Owner

用户于 2026-08-29 明确确认本工单通过验收。验收结论已记录,现关闭工单。没有新的长期事实变化,本次不重复同步 Wiki。

用户于 2026-08-29 明确确认本工单通过验收。验收结论已记录,现关闭工单。没有新的长期事实变化,本次不重复同步 Wiki。
ila closed this issue 2026-08-29 20:44:13 +08:00
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: OPC/goauto#148