- ai_op_queue: staging table for AI write ops (draft|confirmed|executed|failed|cancelled)
- ProposeWriteTool.proposeUpdate(entity, record, field, newValue): self-resolves the entity master table (excludes viw_* report views), resolves field via 字段字典, locates the unique record + old value, stages a DRAFT to ai_op_queue — DOES NOT execute; returns a proposal
- ErpClient.updateForm: executes via ERP addUpdateDelBusinessData with the frontend-compatible payload {data:[{sTable,name:master,column:[{handleType:update,sId,field:value}]}]}
- OpController: deterministic (non-LLM) POST /op/{id}/confirm (executes + writes back status) / cancel / GET pending
- AgentChatController.onToolExecuted: on proposeUpdate, attach conversation + push write_proposal SSE
- chat.html: confirm/cancel card + result echo
- system prompt: proposeUpdate flow; never claim a write is done before confirm
Verified end-to-end: '把必胜客简称改成必胜客中国' -> proposal card -> confirm -> ERP update -> DB changed; cancel -> DB unchanged. Nothing executes without explicit user confirm.