来源:用户,2026-09-11 会话。
现在从syb同步商品信息后需要过滤掉一些商品,不入库,规则如下:去掉variationSku字段包含"-"和"#"的商品,去掉包含以下文字的商品:CVC短袖220斤 / 180克純棉圓領短袖 / 拼色純棉短袖 / 300斤牛奶絲圓領 / 印花大學T / 印花帽T
先排除"-"和"#",再排除包含后面字符串的。这样就能够排除大部分,不需要的。
空 variationSku不过滤。
只读查询线上库 goauto(13010 行 syb_product,7586 张货运单,2026-08-20 ~ 2026-09-11)。
goauto
syb_product
规则1 命中分布
#
-
命中样本全部是「档口-供应商#货号」格式:新寮-雅伊阁大码女装#301、广达-爆款大码女装#9018、山湖-金顺大码女装#2797#(&13)。 未命中样本是自有编码:PDD0582、my238、le171、D256437。
新寮-雅伊阁大码女装#301
广达-爆款大码女装#9018
山湖-金顺大码女装#2797#(&13)
PDD0582
my238
le171
D256437
结论:该规则的语义是排除线下档口直供、保留可走 PDD 采购的商品,65% 被过滤是预期结果。
[必须] 按 OR 实现。AND 只命中 6386,会漏掉 DD#004、300斤牛奶絲圓領#A057 等 2118 行。
[必须]
DD#004
300斤牛奶絲圓領#A057
规则2 命中分布
[必须] 六条关键词只匹配 variationSku,不匹配 productTitle(标题实测 0 命中)。
variationSku
productTitle
[必须] 六条在当前数据上净增 0,全部已被规则1 覆盖。规则2 的价值是前瞻兜底:档口若改用不含 # 的编码,由它接住。因此必须可配置且可观测命中数。
拼色純棉短袖 当前 0 命中(拼色、純棉短袖 单独查亦为 0),仍写入初始数据。
拼色純棉短袖
拼色
純棉短袖
保留集核验:过滤后 4506 行非空值无档口格式残留。1(295 行)与 引流款(9 行)经抽查为正常商品的人工编码,非脏数据。空 variationSku 2724 行分布在正常启用店铺且持续产生至今,按用户确认保留。
1
引流款
server/app/goauto/sybimport/sync.go 明细循环,紧接既有店铺白名单检查之后、applyStockDetail 之前。沿用该处既有的按明细行 continue 模式(docs/12-syb-erp-interface.md:一张货运单可含多个商品,过滤粒度是明细行而非整单)。
server/app/goauto/sybimport/sync.go
applyStockDetail
continue
docs/12-syb-erp-interface.md
variationSku 含 - 或 # 即跳过。不做成配置——它是「什么叫档口货」的业务定义,不是参数;做成可开关的配置反而有被误关、导致 65% 无效数据涌入的风险。
新增 syb_product_filter,形态对齐既有 syb_shop(同为「SYB 同步按名单过滤 + 管理页维护」):
syb_product_filter
syb_shop
keyword
normalized_keyword
enabled
last_hit_at
last_hit_count
note
软删除沿用 SYBShop 的 DeletedAt + DeletedFlag 哨兵写法(唯一索引与可空 deleted_at 共存)。
SYBShop
DeletedAt
DeletedFlag
deleted_at
归一化复用 sybshop.Normalize(去首尾空格、全角折半角、字母小写)。用户清单前三条带尾随空格,CVC 可能为全角或小写,三者均需要。[必须] 不做简繁转换,SYB 数据为繁体,保持原样。
sybshop.Normalize
CVC
API 路由照 sybshop/router.go:GET 与写操作分开注册,写操作加 middleware.RequireRoleKey("admin")(go-admin 按 API 路径授权,不分开无法表达「配置仅管理员,其他角色只读」)。
sybshop/router.go
middleware.RequireRoleKey("admin")
管理页 web/src/views/goauto/syb-product-filters,菜单与 syb-shops 同组。
web/src/views/goauto/syb-product-filters
syb-shops
[必须] 两条规则命中数分别记入 SyncReport,不得合并成单一「过滤总数」。
SyncReport
理由:规则2 今日净增 0。只有分开计数,才能在它由 0 变为非 0 时立刻看出档口已改编码格式。合并统计会使规则1 是否失效不可观测。
[必须] 新增管理页属于新页面,按 AGENTS.md「工单与设计证据双门禁」需先有可审阅原型并经用户确认,才能编写该页生产代码。 服务端过滤逻辑、表结构与 API 不受此门禁阻塞,可先行实施。
可并行:与 #241 / #242 无代码重叠,可并行。
server/
sybimport
models
migrations
web/
android/
CVC
cvc
.\scripts\verify.ps1 -Component all
harness.py sync
docs/08-agent-api-contract.md
syb-product-filters
[必须] 按 AGENTS.md,先修改线上 Wiki 页面并回读 revision,再运行一次 sync 与一次 sync --check 提交镜像;不得直接编辑本地镜像反向覆盖。
sync
sync --check
用户确认:- 与 # 也在同一管理页配置。
原范围「规则1:代码判据 / 不做成配置」作废,替换为下述设计。原「不把规则1 做成配置」一条从非目标中移除。
syb_product_filter 增加 kind 列,取值 char | keyword,两类规则共用一张表与一套 API:
kind
char
[必须] API 必须在服务端拒绝对 kind=char 行的新增与删除,不得只靠前端隐藏按钮。
kind=char
理由:档口编码的判据就是这两个字符。允许自由增删等于把业务定义交给误操作;判据本身需要变更(例如档口改用 / 或 @)属于需要评估的范围变化,应走新建工单,不应是一次点击。
/
@
停用结构判据会使大量档口明细恢复入库(依本单核验:# 对应 8498 行,- 对应 6392 行)。前端必须弹出二次确认,文案示例:
停用「#」后,SYB 同步将不再过滤含 # 的档口商品。按最近一次同步数据估算,约 8498 条明细会恢复入库。确认停用?
[必须] 文案中的条数取自该行实时的 last_hit_count,不得写死。写死的数字在数据变化后会给出错误警告。
kind=keyword 的启停不需要二次确认(影响面为 0 行)。
kind=keyword
kind=char 行的启停必须记录操作人与时间。关键词改错影响 0 行,结构判据改错影响约 65% 明细,两者审计要求不同。kind=keyword 沿用 updated_at 即可。
updated_at
sybimport/sync.go 的过滤逻辑由写死判据改为查表:先应用全部启用的 kind=char 行(任一命中即跳过),再应用启用的 kind=keyword 行。执行顺序与统计口径不变,两类命中数仍须分别记入 SyncReport。
sybimport/sync.go
原型需相应重做,覆盖:结构过滤分段(两条 char 行、无增删按钮)、停用二次确认弹窗。旧版原型(screen 10001/10002/10003/10004/10240)作废,以重做后的版本为准。
6aa3a707191a826306a7fe21
10001
对应 AGENTS.md「新组件记录正常、空、加载、失败、禁用和权限边界」六项,已全部覆盖。
复用 web/src/views/goauto/syb-shops/index.vue 的现有规范:inline 搜索栏(主按钮 + 搜索 + 只看启用 + 重置)、顶部 el-alert 提示条、summary 行、el-table border stripe + 操作列 fixed=right、底部 pagination + scope-note、非管理员 tooltip 说明。
web/src/views/goauto/syb-shops/index.vue
关键词匹配 variationSku,不匹配商品标题。
本规则在「-、# 结构过滤」之后执行,命中数为结构过滤未覆盖的部分。
该关键词已存在(归一化后与「CVC短袖220斤」相同)
还没有配置过滤关键词。结构过滤(variationSku 含 - 或 #)仍然生效,本页只影响额外的关键词过滤。
当前账号只有查看权限。新增、编辑、启用、停用和删除关键词需要管理员操作。
停用或删除只影响后续同步,已经入库的商品明细不会被删除。
示例数据使用本单线上核验结论:6 条关键词命中数均为 0(已被结构过滤覆盖),其中 5 条启用、1 条停用。
由 Codex(gpt-5.6-sol)依据本单方案制作,主 Agent 复核。复核发现并已修正三项:
muted:
—
10240
首轮曾以 gpt-6-astra 派发,返回 Selected model is at capacity,未产生任何改动,改用 gpt-5.6-sol 重跑。
gpt-6-astra
Selected model is at capacity
gpt-5.6-sol
未导出 HTML(用户未要求),未修改仓库文件,未提交 Git。
[必须] 本原型经用户确认前,不得编写管理页生产代码。服务端过滤逻辑、syb_product_filter 表结构与 API 不受此门禁阻塞,可先行实施。
用户于 2026-09-11 确认:「原型通过」。旧版五屏证据(2026-09-11 早前提交的 screen 10001/10002/10003/10004/10240 版本)作废,以本条为准。
lastUUID 10309
isPublic = true
覆盖 AGENTS.md「新组件记录正常、空、加载、失败、禁用和权限边界」六项。
结构过滤(不可增删,仅可停用)
这两个字符是识别档口商品的判据,命中即不入库。需要变更判据请另行建单评估。
2026-09-11 14:06 admin 启用
确认停用结构过滤「#」?
约 8498 条明细会恢复入库
条数取自该规则最近一次同步的命中数,会随数据变化。
在结构过滤之后执行,命中数为结构过滤未覆盖的部分。
示例数据为本单线上核验结论:# 命中 8498、- 命中 6392;6 条关键词命中均为 0(已被结构过滤覆盖),5 启用 1 停用。
设计证据门禁已解除,管理页生产代码可开始编写。
首轮由 Codex 制作四屏;主 Agent 复核修正三项(样式类名 muted: 被当作可见文案、备注空值渲染为字面「(空)」、缺加载态)。本轮结构过滤分段与二次确认弹窗由主 Agent 使用 QuantUX MCP 完成——两次派发 Codex 均返回 Selected model is at capacity(gpt-6-astra、gpt-5.6-sol),零改动。
过程中主 Agent 误用 apply_changes(替换语义而非合并)导致 5 个 screen 的 name/start/children 被清空,已用改动前 dump 重建并校验 children 合计 295 = widgets 295。
apply_changes
children 合计 295 = widgets 295
用户 2026-09-11 在本地真实环境测试后确认验收通过。已合并 main 并推送:7992903..c24e8a4。
7992903..c24e8a4
652bf30
20f59b6
78df997
cad9f6d
503b3cb
40a254d
c24e8a4
初版 go test -p 1 ./... 33 个包全绿、pnpm build:prod 成功,但带着以下四个缺陷;其中三个只有在真实 MySQL 上跑迁移才会暴露。
go test -p 1 ./...
pnpm build:prod
Match
(char, keyword bool)
HitCounter
UpdateHits
migrations.Migrate
cmd/migrate
迁移后仍缺少表:syb_product_filter
access.GoAutoModules()
sys_menu
sys_migration
ReconcilePurchaserPermissions
type:text
Error 1170
size:200
go build ./...
pnpm lint
python dev_scripts/harness.py check --strict
印花大學T
印花大學t
结构过滤不可新增
结构过滤不可删除
cvc短袖220斤
realworld_test.go
上寮-琪琪尚雅网批#2604##(&15)
migrate
新执行 1 个,跳过 42 个
admin
purchaser
Update
先改线上 Wiki 并回读 revision,再同步镜像:
SYB-ERP-Interface-Contract
f1792b7f
Android-Agent-API-Contract
38869285
用户 2026-09-11 明确验收通过。关闭本工单。
No dependencies set.
The note is not visible to the blocked user.
原始需求
来源:用户,2026-09-11 会话。
线上数据核验(2026-09-11)
只读查询线上库
goauto(13010 行syb_product,7586 张货运单,2026-08-20 ~ 2026-09-11)。规则1 命中分布
#-命中样本全部是「档口-供应商#货号」格式:
新寮-雅伊阁大码女装#301、广达-爆款大码女装#9018、山湖-金顺大码女装#2797#(&13)。未命中样本是自有编码:
PDD0582、my238、le171、D256437。结论:该规则的语义是排除线下档口直供、保留可走 PDD 采购的商品,65% 被过滤是预期结果。
[必须]按 OR 实现。AND 只命中 6386,会漏掉DD#004、300斤牛奶絲圓領#A057等 2118 行。规则2 命中分布
[必须]六条关键词只匹配variationSku,不匹配productTitle(标题实测 0 命中)。[必须]六条在当前数据上净增 0,全部已被规则1 覆盖。规则2 的价值是前瞻兜底:档口若改用不含#的编码,由它接住。因此必须可配置且可观测命中数。拼色純棉短袖当前 0 命中(拼色、純棉短袖单独查亦为 0),仍写入初始数据。保留集核验:过滤后 4506 行非空值无档口格式残留。
1(295 行)与引流款(9 行)经抽查为正常商品的人工编码,非脏数据。空variationSku2724 行分布在正常启用店铺且持续产生至今,按用户确认保留。方案
过滤位置
server/app/goauto/sybimport/sync.go明细循环,紧接既有店铺白名单检查之后、applyStockDetail之前。沿用该处既有的按明细行continue模式(docs/12-syb-erp-interface.md:一张货运单可含多个商品,过滤粒度是明细行而非整单)。规则1:代码判据
variationSku含-或#即跳过。不做成配置——它是「什么叫档口货」的业务定义,不是参数;做成可开关的配置反而有被误关、导致 65% 无效数据涌入的风险。规则2:独立表 + 管理页
新增
syb_product_filter,形态对齐既有syb_shop(同为「SYB 同步按名单过滤 + 管理页维护」):keywordnormalized_keywordenabledlast_hit_at/last_hit_countnote软删除沿用
SYBShop的DeletedAt+DeletedFlag哨兵写法(唯一索引与可空deleted_at共存)。归一化复用
sybshop.Normalize(去首尾空格、全角折半角、字母小写)。用户清单前三条带尾随空格,CVC可能为全角或小写,三者均需要。[必须]不做简繁转换,SYB 数据为繁体,保持原样。API 路由照
sybshop/router.go:GET 与写操作分开注册,写操作加middleware.RequireRoleKey("admin")(go-admin 按 API 路径授权,不分开无法表达「配置仅管理员,其他角色只读」)。管理页
web/src/views/goauto/syb-product-filters,菜单与syb-shops同组。统计
[必须]两条规则命中数分别记入SyncReport,不得合并成单一「过滤总数」。理由:规则2 今日净增 0。只有分开计数,才能在它由 0 变为非 0 时立刻看出档口已改编码格式。合并统计会使规则1 是否失效不可观测。
非目标
variationSkuproductTitle前置依赖
[必须]新增管理页属于新页面,按 AGENTS.md「工单与设计证据双门禁」需先有可审阅原型并经用户确认,才能编写该页生产代码。 服务端过滤逻辑、表结构与 API 不受此门禁阻塞,可先行实施。可并行:与 #241 / #242 无代码重叠,可并行。
子项目影响
server/:sybimport(过滤 + 统计)、models(新表)、新增 filter 包(API)、migrationsweb/:新增管理页android/:无验收
variationSku含-或#的明细不入库variationSku正常入库验证
sybimport过滤与统计单元测试(含 OR 而非 AND 的回归用例:DD#004、300斤牛奶絲圓領#A057必须被过滤)CVC、小写cvc归一为同一键;繁体不被转换.\scripts\verify.ps1 -Component all风险
SyncReport命中数与本单核验数据(8504/13010)量级一致,不一致须停止排查。文档影响
docs/12-syb-erp-interface.md:新增同步过滤规则章节(长期业务规则,需先改线上 Wiki 再harness.py sync)docs/08-agent-api-contract.md:新增syb-product-filters接口(同上)[必须]按 AGENTS.md,先修改线上 Wiki 页面并回读 revision,再运行一次sync与一次sync --check提交镜像;不得直接编辑本地镜像反向覆盖。2026-09-11 范围变更:结构判据改为可配置(仅开关)
用户确认:
-与#也在同一管理页配置。变更内容
原范围「规则1:代码判据 / 不做成配置」作废,替换为下述设计。原「不把规则1 做成配置」一条从非目标中移除。
syb_product_filter增加kind列,取值char|keyword,两类规则共用一张表与一套 API:char-、#两条,随迁移写入keyword[必须]API 必须在服务端拒绝对kind=char行的新增与删除,不得只靠前端隐藏按钮。理由:档口编码的判据就是这两个字符。允许自由增删等于把业务定义交给误操作;判据本身需要变更(例如档口改用
/或@)属于需要评估的范围变化,应走新建工单,不应是一次点击。[必须]停用kind=char需二次确认停用结构判据会使大量档口明细恢复入库(依本单核验:
#对应 8498 行,-对应 6392 行)。前端必须弹出二次确认,文案示例:[必须]文案中的条数取自该行实时的last_hit_count,不得写死。写死的数字在数据变化后会给出错误警告。kind=keyword的启停不需要二次确认(影响面为 0 行)。[必须]变更审计kind=char行的启停必须记录操作人与时间。关键词改错影响 0 行,结构判据改错影响约 65% 明细,两者审计要求不同。kind=keyword沿用updated_at即可。过滤实现相应调整
sybimport/sync.go的过滤逻辑由写死判据改为查表:先应用全部启用的kind=char行(任一命中即跳过),再应用启用的kind=keyword行。执行顺序与统计口径不变,两类命中数仍须分别记入SyncReport。验收补充
kind=char行无法通过 API 新增或删除(前端隐藏 + 服务端拒绝,二者都要测)kind=char弹出二次确认,且提示条数与该行last_hit_count一致#后,含#的明细恢复入库;重新启用后恢复过滤kind=char的启停操作可查到操作人与时间风险补充
设计证据
原型需相应重做,覆盖:结构过滤分段(两条 char 行、无增删按钮)、停用二次确认弹窗。旧版原型(screen 10001/10002/10003/10004/10240)作废,以重做后的版本为准。
设计证据(原型,待确认)
6aa3a707191a826306a7fe2110001覆盖范围
对应 AGENTS.md「新组件记录正常、空、加载、失败、禁用和权限边界」六项,已全部覆盖。
设计基准
复用
web/src/views/goauto/syb-shops/index.vue的现有规范:inline 搜索栏(主按钮 + 搜索 + 只看启用 + 重置)、顶部 el-alert 提示条、summary 行、el-table border stripe + 操作列 fixed=right、底部 pagination + scope-note、非管理员 tooltip 说明。界面上固定下来的关键文案
关键词匹配 variationSku,不匹配商品标题。本规则在「-、# 结构过滤」之后执行,命中数为结构过滤未覆盖的部分。该关键词已存在(归一化后与「CVC短袖220斤」相同)还没有配置过滤关键词。结构过滤(variationSku 含 - 或 #)仍然生效,本页只影响额外的关键词过滤。当前账号只有查看权限。新增、编辑、启用、停用和删除关键词需要管理员操作。停用或删除只影响后续同步,已经入库的商品明细不会被删除。示例数据使用本单线上核验结论:6 条关键词命中数均为 0(已被结构过滤覆盖),其中 5 条启用、1 条停用。
制作与复核
由 Codex(gpt-5.6-sol)依据本单方案制作,主 Agent 复核。复核发现并已修正三项:
muted:当作可见文案渲染 —— 已去掉前缀—10240首轮曾以
gpt-6-astra派发,返回Selected model is at capacity,未产生任何改动,改用gpt-5.6-sol重跑。未导出 HTML(用户未要求),未修改仓库文件,未提交 Git。
门禁状态
[必须]本原型经用户确认前,不得编写管理页生产代码。服务端过滤逻辑、syb_product_filter表结构与 API 不受此门禁阻塞,可先行实施。设计证据(原型,已确认)
用户于 2026-09-11 确认:「原型通过」。旧版五屏证据(2026-09-11 早前提交的 screen 10001/10002/10003/10004/10240 版本)作废,以本条为准。
6aa3a707191a826306a7fe2110001lastUUID 10309;QuantUX 无独立 revision 号isPublic = true(为便于审阅开启,原型不含个人数据或凭据)覆盖范围
覆盖 AGENTS.md「新组件记录正常、空、加载、失败、禁用和权限边界」六项。
界面固定下来的关键约束
结构过滤(不可增删,仅可停用);说明:这两个字符是识别档口商品的判据,命中即不入库。需要变更判据请另行建单评估。kind=char两行操作列为不可点击的灰字「不可删除」,无任何增删控件(服务端仍须独立拒绝,见验收第 8 条)2026-09-11 14:06 admin 启用),对应审计要求确认停用结构过滤「#」?+约 8498 条明细会恢复入库+ 小字条数取自该规则最近一次同步的命中数,会随数据变化。(对应「不得写死」)关键词匹配 variationSku,不匹配商品标题。在结构过滤之后执行,命中数为结构过滤未覆盖的部分。示例数据为本单线上核验结论:
#命中 8498、-命中 6392;6 条关键词命中均为 0(已被结构过滤覆盖),5 启用 1 停用。门禁
设计证据门禁已解除,管理页生产代码可开始编写。
制作说明
首轮由 Codex 制作四屏;主 Agent 复核修正三项(样式类名
muted:被当作可见文案、备注空值渲染为字面「(空)」、缺加载态)。本轮结构过滤分段与二次确认弹窗由主 Agent 使用 QuantUX MCP 完成——两次派发 Codex 均返回Selected model is at capacity(gpt-6-astra、gpt-5.6-sol),零改动。过程中主 Agent 误用
apply_changes(替换语义而非合并)导致 5 个 screen 的 name/start/children 被清空,已用改动前 dump 重建并校验children 合计 295 = widgets 295。实施完成并验收通过(2026-09-11)
用户 2026-09-11 在本地真实环境测试后确认验收通过。已合并 main 并推送:
7992903..c24e8a4。提交
652bf3020f59b6last_hit_count按类汇总而非按行78df997variationSku样本补回归测试cad9f6d503b3cb40a254dc24e8a4复核发现并修复的四个缺陷
初版
go test -p 1 ./...33 个包全绿、pnpm build:prod成功,但带着以下四个缺陷;其中三个只有在真实 MySQL 上跑迁移才会暴露。last_hit_count按kind写同一个汇总值。Match只返回(char, keyword bool),无法归因到具体规则。停用确认弹窗引用该值,会对#和-提示同一个数字——按线上数据其中一个会偏差约 2100 行。改为Match返回命中的规则,新增HitCounter按规则 id 累加,UpdateHits写每条自己的数,未命中写 0(避免上一轮的旧数字留存)。migrations.Migrate的 AutoMigrate 列表,对已有数据库无效。由cmd/migrate的迁移后建表检查捕获:迁移后仍缺少表:syb_product_filter。access.GoAutoModules()注册不产生sys_menu行;菜单由首次建菜单的版本迁移写入,该版本已记录在sys_migration中不再执行,启动时的ReconcilePurchaserPermissions只对齐 Casbin API 矩阵。结果是表、接口、路由都在,但无法从菜单进入。keyword/normalized_keyword声明为type:text,MySQL 拒绝无前缀长度的 BLOB/TEXT 进入键定义(Error 1170)。改为size:200(对齐SYBShop的做法)。SQLite 接受文本列入索引,所以整套单元测试无法发现。验证
go build ./...通过;go test -p 1 ./...33 个包全绿(合并后在 main 上重跑确认)pnpm lint本单文件 0 error;pnpm build:prod成功python dev_scripts/harness.py check --strict通过;sync --check通过goauto库,迁移前已完整备份):迁移应用成功,syb_product_filter8 行(2 结构 + 6 关键词),繁体保留(印花大學T→印花大學t,只降大小写),sys_menu菜单行创建于 采采管理 组下char新增 403结构过滤不可新增;char删除 403结构过滤不可删除;重复关键词 409该关键词已存在(归一化后与「CVC短袖220斤」相同);全角加空格cvc短袖220斤被判为重复realworld_test.go):新寮-雅伊阁大码女装#301、广达-爆款大码女装#9018、DD#004、300斤牛奶絲圓領#A057、上寮-琪琪尚雅网批#2604##(&15)被过滤;PDD0582、my238、le171、1、引流款、空值 保留;两条结构规则记录到不同的命中数migrate,输出新执行 1 个,跳过 42 个,行恢复且admin、purchaser两角色均绑定未验证
SyncReport的两类命中数与本单核验量级(8504 / 13010)一致,不一致须停止排查。与已确认原型的偏离
Update方法。影响有限(删除后重加等效),未处理,如需补应另建工单。文档影响(已完成)
先改线上 Wiki 并回读 revision,再同步镜像:
SYB-ERP-Interface-Contract→ revisionf1792b7f(镜像docs/12-syb-erp-interface.md)Android-Agent-API-Contract→ revision38869285(镜像docs/08-agent-api-contract.md)验收结论
用户 2026-09-11 明确验收通过。关闭本工单。