一页读懂
x-order 治的是「一行数据排第几」这件事的全链路。名字里的 order 指的是排序不是订单 —— 主体是 orderNo 这个排序号字段从数据表出发,经云函数的两个排序原子、保存适配器,走到后台五种拖拽载体的整条链。一句话概括它的主张:顺序只有一个写入口,界面上不许再给第二个。
- 三态契约定「这张表该不该有排序号」:全量加载与嵌套表可选(拖拽、手工、派生排序三种都合法),分页 / 单查 / 单条禁含。这是 2026-06-19 的 V4 放宽,把「读取形态」与「排序需求」两个正交问题解耦(裁定见下方「取舍与在案裁定」)。
- 白名单定「这个实体是拖拽还是手工」:判据不看配置、不看注册表,只看
x-server下有没有{实体前缀}-order-update这个云函数目录。建了它,十颗闸同时改判。 - 服务端两个原子各管一头:新建行自动追加到末尾、重排一条 SQL 全量重写;两者都住内核母本的预设里,调用点只剩几个参数,且都配了「有这个目录就必须挂标记、标记块里必须有真调用」的闭环闸。
- 后台五种拖拽载体共用一套语义:左卡列表即时模式、行列表拖拽表格、详情页步骤编辑态、详情页内联子表、嵌套双层表。前两种拖完直接落库,后三种随保存批量提交,因此后三种多一层「重排染色」—— 让用户看得见自己动过哪些行。
- 排他是这份规范最密的一片:拖拽页不许分页、不许列头排序、不许列表形态、不许把排序号画成列 / 做成表单项 / 放进详情字段配置 / 写进前端参数类型。理由同一条 —— 任何第二个顺序来源都会与拖拽结果分叉,而分叉全部静默。
- 另有四颗与排序正交的订单钱域闸:退款中行的原子性锁、员工可见文本人话律、补记路禁幻值单号、台账值域三载体一致。它们按钱域轴治理,历史上落在本规范而非 x-api,边界与理由写在「取舍与在案裁定」。
治理边界:本规范只治排序字段与拖拽形态,不治「这张表该按什么排」「这个顺序对不对」。适用面是数据表、云函数、后台三处;小程序端一颗闸都没有(端上无重排交互,按序渲染即可,条款 ARCH-G01 写明这件事)。云函数骨架归 x-api、详情页编排归 x-detail、行列表配置归 x-curd、权限声明归 x-auth、表文档骨架归 x-data。
怎么读本页:「治理版图」的两张泳道图是主图 —— 数据链把本域的闸全部摊在七条道上,业务链讲「给一个实体加拖拽排序」时每一步哪些闸当轮咬。条款原文在条款书 .claude/rules/x-order-rule.md(写三端代码时按路径自动加载),本页的条款总表与判据总表是派生索引。本域没有同前缀 JSON 注册表 —— 拖拽白名单是目录存在性、黑话名单与状态枚举都住在判据的检测器里,改它们就是改判据。
治理版图
数据链:一个排序号从数据表到每一种拖拽载体(本域的闸全在图上)
| 跳 | 从 | 到 | 流向 | 守护 · 条款 |
|---|---|---|---|---|
| 1 | 数据表字段 · 排序号字段的三态契约 | 数据表字段 · 拖拽表把它标成系统字段 | 有排序云函数就标成系统字段 | — |
| 2 | 数据表字段 · 拖拽表把它标成系统字段 | 云函数排序原子 · 新建行:自动追加到末尾 | 用户不传,新建时由服务端补 | — |
| 3 | 云函数排序原子 · 新建行:自动追加到末尾 | 云函数排序原子 · 写入面:入参一律不收排序号 | 补的那一条是唯一写路 | — |
| 4 | 云函数排序原子 · 写入面:入参一律不收排序号 | 云函数排序原子 · 重排:预设加一条 SQL 全量重写 | 改顺序只剩排序接口这一个口 | — |
| 5 | 数据表字段 · 拖拽表把它标成系统字段 | 后台契约类型与排他面 · 前端参数类型不许带排序号 | 系统字段同样不进前端参数类型 | — |
| 6 | 云函数排序原子 · 重排:预设加一条 SQL 全量重写 | BFF 与保存适配器 · 保存适配器消费重排数组 | 批量模式在保存时调它 | — |
| 7 | 云函数排序原子 · 重排:预设加一条 SQL 全量重写 | 后台拖拽载体 · 拖拽属性两形态,出现即挂标记 | 即时模式拖完直接调它 | — |
| 8 | BFF 与保存适配器 · 保存适配器消费重排数组 | 详情页编辑态与嵌套表 · 步骤编辑态的拖拽状态字段 | 步骤的提交顺序从这里来 | — |
| 9 | BFF 与保存适配器 · 保存适配器消费重排数组 | 详情页编辑态与嵌套表 · 内联子表的重排染色 | 内联子表的重排数组从这里来 | — |
| 10 | 详情页编辑态与嵌套表 · 内联子表的重排染色 | 详情页编辑态与嵌套表 · 嵌套表外层内层各一份派生 | 同一套派生扩到双层 | — |
| 11 | 后台拖拽载体 · 拖拽属性两形态,出现即挂标记 | 后台拖拽载体 · 排他:分页、列头排序、列表形态 | 挂了拖拽就得关掉别的顺序来源 | — |
| 12 | 后台拖拽载体 · 拖拽属性两形态,出现即挂标记 | 后台契约类型与排他面 · 组件里的拖拽换算收口到一个工具 | 载体底下的换算共用一个工具 | — |
| 13 | 后台契约类型与排他面 · 前端参数类型不许带排序号 | 后台契约类型与排他面 · 列、表单、详情字段里都不许露出它 | 类型里没有,界面上也不该有 | — |
| 14 | 订单钱域(与排序正交的第二片射程) · 台账取值范围三个载体一致 | 订单钱域(与排序正交的第二片射程) · 退款中的行除转出不许再写 | 台账与状态机是同一片钱域 | — |
| 15 | 订单钱域(与排序正交的第二片射程) · 退款中的行除转出不许再写 | 订单钱域(与排序正交的第二片射程) · 员工能看见的字必须是人话 | 状态变更写进台账的那句话 | — |
| 16 | 订单钱域(与排序正交的第二片射程) · 员工能看见的字必须是人话 | 订单钱域(与排序正交的第二片射程) · 补记审计凭证只取原单号 | 同一条台账上的单号也要真 | — |
| 格子 | 数据表字段 · 排序号字段的三态契约 | 全量与嵌套可选 · 分页 / 单查 / 单条禁含 | x-order:NS-DATA-0001ARCH-A01 ARCH-A02 | |
| 格子 | 数据表字段 · 拖拽表把它标成系统字段 | 用户不可传 · 下游按它豁免入参对齐 | x-order:NS-DATA-0002ARCH-A03 | |
| 格子 | 云函数排序原子 · 新建行:自动追加到末尾 | 预设 appendNextOrderNo · 分组参数显式传 | x-order:STD-SERVER-0002x-order:NS-SERVER-0002ARCH-B03 | |
| 格子 | 云函数排序原子 · 写入面:入参一律不收排序号 | 新建与更新两个入口都堵 · repo 不留第二条轨 | x-order:NS-SERVER-0004x-order:NS-SERVER-0005x-order:NS-SERVER-0006ARCH-B04 ARCH-B05 | |
| 格子 | 云函数排序原子 · 重排:预设加一条 SQL 全量重写 | 禁逐行更新 · 标记块内必须有真调用 | x-order:STD-SERVER-0001x-order:NS-SERVER-0001x-order:NS-SERVER-0003ARCH-B01 ARCH-B02 | |
| 格子 | BFF 与保存适配器 · 保存适配器消费重排数组 | 三守卫齐了才调 · 失败必须抛出 | x-order:STD-ADMIN-0004x-order:NS-ADMIN-0012ARCH-E01 ARCH-E02 | |
| 格子 | 后台拖拽载体 · 拖拽属性两形态,出现即挂标记 | 左卡即时模式 / 行列表拖拽表格 | x-order:STD-ADMIN-0001x-order:NS-ADMIN-0002ARCH-C01 | |
| 格子 | 后台拖拽载体 · 排他:分页、列头排序、列表形态 | 同一张表不许有第二种顺序来源 | x-order:NS-ADMIN-0010x-order:NS-ADMIN-0008x-order:NS-ADMIN-0005ARCH-C02 ARCH-C03 | |
| 格子 | 后台契约类型与排他面 · 前端参数类型不许带排序号 | 实体类型豁免 · 模块任意层级 · 云函数目录名反查 | x-order:NS-ADMIN-0009ARCH-C06 | |
| 格子 | 后台契约类型与排他面 · 组件里的拖拽换算收口到一个工具 | 拖回原位 / 越界 / 新删行的边界只在一处 | x-order:NS-ADMIN-0001ARCH-C07 | |
| 格子 | 后台契约类型与排他面 · 列、表单、详情字段里都不许露出它 | 露出即可写 · 写了没反应最难查 | x-order:NS-ADMIN-0004x-order:NS-ADMIN-0006x-order:NS-ADMIN-0007ARCH-C04 ARCH-C05 | |
| 格子 | 详情页编辑态与嵌套表 · 步骤编辑态的拖拽状态字段 | 未拖过与拖过顺序未变要分得开 | x-order:STD-ADMIN-0002x-order:NS-ADMIN-0003ARCH-D01 ARCH-D04 | |
| 格子 | 详情页编辑态与嵌套表 · 内联子表的重排染色 | 新建行与已删行各走各的色 | x-order:STD-ADMIN-0003x-order:NS-ADMIN-0011ARCH-D02 | |
| 格子 | 详情页编辑态与嵌套表 · 嵌套表外层内层各一份派生 | 两层各有原始映射 · 复用已修改状态 | x-order:STD-ADMIN-0005x-order:NS-ADMIN-0013ARCH-D03 | |
| 格子 | 订单钱域(与排序正交的第二片射程) · 台账取值范围三个载体一致 | 清单 / 字段行 / 字段说明 · 锚坏即曝红 | x-order:NS-DATA-0003ARCH-F04 | |
| 格子 | 订单钱域(与排序正交的第二片射程) · 退款中的行除转出不许再写 | 写一次即把对账时钟归零 | x-order:NS-SERVER-0007ARCH-F01 | |
| 格子 | 订单钱域(与排序正交的第二片射程) · 员工能看见的字必须是人话 | 黑名单枚举制 · 诊断通道豁免 | x-order:NS-SERVER-0008ARCH-F02 | |
| 格子 | 订单钱域(与排序正交的第二片射程) · 补记审计凭证只取原单号 | 重算出的单号可能微信侧不存在 | x-order:NS-SERVER-0010ARCH-F03 | |
业务链:给一个实体加上拖拽排序,每一步当轮咬哪些闸
| 跳 | 从 | 到 | 流向 | 守护 · 条款 |
|---|---|---|---|---|
| 1 | 开发动作 · ① 先定形态:拖拽还是手工 | 开发动作 · ② 数据表加排序号并标系统字段 | 先定形态再动字段 | — |
| 2 | 开发动作 · ② 数据表加排序号并标系统字段 | 开发动作 · ③ 云函数:新建追加、入参禁传、重排原子 | 字段立住再写云函数 | — |
| 3 | 开发动作 · ③ 云函数:新建追加、入参禁传、重排原子 | 开发动作 · ④ 批量场景在保存适配器里消费重排 | 批量场景才需要适配器 | — |
| 4 | 开发动作 · ④ 批量场景在保存适配器里消费重排 | 开发动作 · ⑤ 页面挂拖拽属性与权限,关掉排他项 | 落库通了再接界面 | — |
| 5 | 开发动作 · ⑤ 页面挂拖拽属性与权限,关掉排他项 | 开发动作 · ⑥ 跑增量检测,再手验一遍拖拽 | 改完当轮就跑检测 | — |
| 6 | 开发动作 · ① 先定形态:拖拽还是手工 | 落盘产物 · x-server/…/{实体}-order-update/ | 开关落盘 | — |
| 7 | 开发动作 · ② 数据表加排序号并标系统字段 | 落盘产物 · {表}.datasource.json 与同名 .md | 落盘 | — |
| 8 | 开发动作 · ③ 云函数:新建追加、入参禁传、重排原子 | 落盘产物 · {实体}-create/repo.js 与 order-update/repo.js | 落盘 | — |
| 9 | 开发动作 · ④ 批量场景在保存适配器里消费重排 | 落盘产物 · {模块}.bff.ts 的保存适配器 | 落盘 | — |
| 10 | 开发动作 · ⑤ 页面挂拖拽属性与权限,关掉排他项 | 落盘产物 · {模块}.tsx 与 {模块}.types.ts | 落盘 | — |
| 11 | 落盘产物 · {表}.datasource.json 与同名 .md | 本域当轮咬的闸 · 数据端两颗 | 当轮咬 | — |
| 12 | 落盘产物 · {实体}-create/repo.js 与 order-update/repo.js | 本域当轮咬的闸 · 服务端模板与禁逐行 | 当轮咬 | — |
| 13 | 落盘产物 · {模块}.bff.ts 的保存适配器 | 本域当轮咬的闸 · 适配器模板与闭环 | 当轮咬 | — |
| 14 | 落盘产物 · {模块}.tsx 与 {模块}.types.ts | 本域当轮咬的闸 · 页面模板、闭环与分页排他 | 当轮咬 | — |
| 15 | 本域当轮咬的闸 · 服务端模板与禁逐行 | 同轮咬的外域闸 · 入参字段集与 repo 骨架 | 同轮还咬外域 | — |
| 16 | 本域当轮咬的闸 · 适配器模板与闭环 | 同轮咬的外域闸 · 保存适配器骨架 | 同轮还咬外域 | — |
| 17 | 本域当轮咬的闸 · 页面模板、闭环与分页排他 | 同轮咬的外域闸 · 权限声明与分页开关 | 同轮还咬外域 | — |
| 18 | 开发动作 · ⑥ 跑增量检测,再手验一遍拖拽 | 同轮咬的外域闸 · 内核与上传包等值 | 发布那一跳才咬 | — |
| 格子 | 开发动作 · ① 先定形态:拖拽还是手工 | 建不建排序云函数 · 这个决定是全链路的开关 | ARCH-B06 ARCH-G03 | |
| 格子 | 开发动作 · ② 数据表加排序号并标系统字段 | 字段名按命名规则 · .md 与 .json 一起改 | ARCH-A01 ARCH-A02 ARCH-A03 | |
| 格子 | 开发动作 · ③ 云函数:新建追加、入参禁传、重排原子 | 三件一起做 · 重排云函数是新建的部署单元 | ARCH-B01 ARCH-B03 ARCH-B05 | |
| 格子 | 开发动作 · ④ 批量场景在保存适配器里消费重排 | 即时场景跳过这一步,直接在页面调接口 | ARCH-E01 | |
| 格子 | 开发动作 · ⑤ 页面挂拖拽属性与权限,关掉排他项 | 权限取自权限声明 · 分页与列头排序同批关掉 | ARCH-C01 ARCH-C02 ARCH-C03 | |
| 格子 | 开发动作 · ⑥ 跑增量检测,再手验一遍拖拽 | 改动文件全列进去 · 断网回退与无权限两例手验 | ARCH-E02 | |
| 格子 | 本域当轮咬的闸 · 数据端两颗 | 三态契约 + 系统字段 | x-order:NS-DATA-0001x-order:NS-DATA-0002ARCH-A01 ARCH-A03 | |
| 格子 | 本域当轮咬的闸 · 服务端模板与禁逐行 | 两条标准写法 + 禁 ORM 逐行更新 | x-order:STD-SERVER-0001x-order:STD-SERVER-0002x-order:NS-SERVER-0003ARCH-B01 ARCH-B02 ARCH-B03 | |
| 格子 | 本域当轮咬的闸 · 适配器模板与闭环 | 三种标记任一 + 块内必须有真调用 | x-order:STD-ADMIN-0004x-order:NS-ADMIN-0012ARCH-E01 | |
| 格子 | 本域当轮咬的闸 · 页面模板、闭环与分页排他 | 拖拽与分页共存当场报红 | x-order:STD-ADMIN-0001x-order:NS-ADMIN-0002x-order:NS-ADMIN-0010ARCH-C01 ARCH-C02 | |
| 格子 | 同轮咬的外域闸 · 入参字段集与 repo 骨架 | 系统字段在对齐闸里被豁免 | x-api:NS-SERVER-0131x-api:STD-SERVER-0004ARCH-A03 ARCH-G03 | |
| 格子 | 同轮咬的外域闸 · 保存适配器骨架 | 本域只管其中排序那一跳 | x-detail:STD-ADMIN-0006ARCH-E01 | |
| 格子 | 同轮咬的外域闸 · 权限声明与分页开关 | 权限禁硬编码 · 分页开关必须显式 | x-auth:STD-ADMIN-0001x-curd:NS-ADMIN-0121ARCH-C01 ARCH-C02 | |
| 格子 | 同轮咬的外域闸 · 内核与上传包等值 | 预设住内核母本,上传包是装配产物 | x-deploy:NS-SERVER-0002ARCH-B01 | |
射程与普查
这一域的射程不是按模块圈的,是按一样东西会经过哪些地方圈的。域名里的 order 同时是两个意思 —— 排序号与订单单据,于是射程成了两条互不相交的链共用一个门牌:排序号那条从建表出发,穿过云函数的入参与数据层,一路走到界面上的一个拖拽手柄;订单那条从一条更新语句的条件段出发,一路走到客服念给客户听的那句话。两条链都不是任何一个目录圈得住的,所以适用面只能逐类文件点名,而不是指向某个模块 —— 读这一节时别去找「订单模块在哪」,本域从头到尾没有这样一个位置。
- 排序号的出生地数据表的模型定义与字段说明,主表、嵌套表、叶子表三类都在内 —— 这张表该不该有排序号、它是不是用户碰不到的系统字段,都在这里定下来
- 排序号唯一的写入口云函数的新建与更新入参校验,以及数据层的重排与追加。这一列只许从这里写进去,别处能写就是第二条轨,两条轨并存时顺序既不由拖拽决定也不由用户决定
- 排序号在界面上的每一处露面后台页面、类型契约、聚合层,以及详情页那几个承载拖拽的框架组件。列、表单、详情字段、参数类型,任何一处露出来,用户就会想去改它
- 订单钱域的收敛链路退款中状态的写入、对账补记的凭证取值、两张台账的取值范围,以及这条链上直达员工与客户屏幕的那些文字
- 结构性看不见判据读的是写法形态:更新语句拆成多行写、状态值写成参数而不是字面量、用逗号隐式联表,它一概读不出来;同样看不见的还有换个写法取入参、把列头排序写成比较函数、把接口调用提取到别的文件
- 判据够不着排序差分算得对不对、乐观更新失败后有没有真的退回原样、提示有没有真的弹出来、真机上拖拽手柄顺不顺手 —— 这些是运行时的事,静态判据只看得见代码长什么样
- 不归本域移动端整端一颗闸都没有,端上不存在重排这个动作,将来要做先走治理环立判据;入参的具体校验规则归接口域,权限标识归权限域,保存适配器的骨架归详情域,选项集的消费面登记归数据域,内核母本的装配归发布域
普查:射程内今天实际有多少东西
下面每一块都是机器当场数出来的,但它是快照、不随代码自动刷新 —— 每块顶上标着快照日期。
| 文件 | x-server/**/repo.js |
|---|---|
| 文件数 | 214 |
| 正则 | reorderByPk m |
| 命中文件 | 4 |
| 命中次数 | 8 |
快照 · 2026-09-16(不随代码自动刷新;刷新走 sync --census --date=YYYY-MM-DD)
| 文件 | x-server/**/repo.js |
|---|---|
| 文件数 | 214 |
| 正则 | appendNextOrderNo m |
| 命中文件 | 4 |
| 命中次数 | 8 |
快照 · 2026-09-16(不随代码自动刷新;刷新走 sync --census --date=YYYY-MM-DD)
| 文件 | x-admin/src/**/*.tsx |
|---|---|
| 文件数 | 163 |
| 正则 | dragSort= m |
| 命中文件 | 1 |
| 命中次数 | 1 |
快照 · 2026-09-16(不随代码自动刷新;刷新走 sync --census --date=YYYY-MM-DD)
| 文件 | x-admin/src/**/*.ts* |
|---|---|
| 文件数 | 940 |
| 正则 | X-RULE-BEGIN-STANDARD-x-order- m |
| 命中文件 | 6 |
| 命中次数 | 8 |
快照 · 2026-09-16(不随代码自动刷新;刷新走 sync --census --date=YYYY-MM-DD)
| 文件 | x-data/**/*.datasource.json |
|---|---|
| 文件数 | 61 |
| 正则 | orderNo m |
| 命中文件 | 27 |
| 命中次数 | 78 |
快照 · 2026-09-16(不随代码自动刷新;刷新走 sync --census --date=YYYY-MM-DD)
| 文件 | x-server/**/repo.js |
|---|---|
| 文件数 | 214 |
| 正则 | UPDATE order_item_node m |
| 命中文件 | 5 |
| 命中次数 | 14 |
快照 · 2026-09-16(不随代码自动刷新;刷新走 sync --census --date=YYYY-MM-DD)
设计机理:为什么长成这样
一、两条轴,不是一份规范里塞了两件事
本规范的全部闸分成两片:排序轴(数据表、云函数与后台三处各占一段)与订单钱域轴(NS-DATA-0003、NS-SERVER-0007、NS-SERVER-0008、NS-SERVER-0010)。两片的适用面不重叠、判据互不引用。钱域那四颗历史上落在本规范而非 x-api,是因为它们守的是钱域的状态机与文案这条轴,而 x-api 持的是链路不变量轴 —— 两轴正交共管同一批文件(2026-08-05 已把 wechatpay 目录的领域归属由单值改成数组,两个规范同时可达,详见「取舍与在案裁定」)。
二、白名单为什么是目录存在性,以及它的三个代理判据
「这个实体是拖拽专属吗」这个问题,全链路要问十次,而判据给出的答案来自四种不同的代理:
- 反查:枚举全部排序目录再比前缀与复数形(
NS-DATA-0002,V1.2.0 起):把表名去掉_base/_node/_leaf、下划线换连字符得到表前缀,再看枚举出来的前缀里有没有哪个等于它、或等于它加一个s。 - 正查:同级目录找兄弟(
NS-SERVER-0002/0004/0005/0006):只在当前云函数目录的同一个父目录下找那个兄弟目录。 - 反查:枚举全部排序目录再比前缀(
NS-ADMIN-0009,V1.1.0 起):先枚举x-server下所有{前缀}-order-update,再看有没有哪个前缀等于本模块名、或以「模块名-」起头。 - 文件里有没有那次调用(
NS-ADMIN-0004/0005/0006/0007):后台文件里出现xxxOrderUpdate(就算拖拽页。
四种代理在今天的库里结论一致,但它们分家的条件不同:把排序云函数与新建云函数放进不同父目录,只有「同级找兄弟」那一种失明(今天四个排序实体恰好都是兄弟布局,那是巧合不是保证);接口改名或调用被提取到别处,只有「文件里有没有那次调用」那一种失明。两种反查代理的失明条件最窄 —— 只有名字本身落在它们的匹配臂之外才看不见。正查曾是本域最大的成片盲区:表名或模块名与云函数前缀不同形(sop_step_node ↔ sop-steps-order-update)时正查恒落空,两颗闸因此长期半盲,V1.1.0 与 V1.2.0 先后把它们改成反查。这件事写进条款 ARCH-B06,并在「诚实边界」里列出今天的实测分布。
三、模板体系:两个服务端原子 + 五个后台载体
七条标准写法按宿主分工:服务端两条(重排、追加)各配一颗闭环闸;后台五条分别对应五种拖拽载体,每条也各配一颗闭环闸。全部是 if-exists 形态 —— 没挂标记就一行都不比,所以标准写法的真实射程等于它那颗闭环闸的射程。闭环闸这一侧有两种形态:锚在一文件一处的整文件模板或框架件上的五颗(两个服务端原子、三个详情页框架件)判「文件里有块」并做「块内必须有真节点」的反伪空块检查(重排块里要有预设调用、追加块里要有追加调用、染色块里要有派生),单挂一个空标记块过不了;锚在一个文件里能出现多处的写法上的两颗(后台页面的拖拽属性、保存适配器里的排序接口调用)V1.3.0 起改成逐处归属 —— 每一处都要落在一对标记块内,空块什么都掩护不了。
四、批量模式为什么要染色
五种载体里有三种是批量模式:拖完不落库,等用户点保存时与增删改一起提交。这带来一个即时模式没有的问题 —— 用户在保存前无法回答「我到底动过哪些行」。三条染色标准写法(步骤状态字段、内联子表派生、嵌套双层派生)解决的都是这一件事,并且共用同一套判定:拿当前位置与原始位置比,位置变了才算;新建行与已删行各走各的色;优先级固定为「已删除 > 新建 > 重排」。三处口径必须一致,否则同一个操作在不同表里染出不同颜色。机器守到哪要说实话:三条标准写法里只有两条(内联子表派生、嵌套外层派生)锁的是可运行的位置派生,测试床在同一份行变动夹具上对拍的也只有这两处;步骤编辑态那一条只锁一行类型契约,它的派生算法有意不模板化(见「取舍与在案裁定 · 排序差分算法有意不模板化」),物理上进不了对拍;嵌套表的「新建 / 已删优先」分支链与外层缓存依赖数组写在标记块外,闸也不看。所以「三处一致」今天是两处机器对拍 + 一处靠人(条款 ARCH-D01 / ARCH-D03 / ARCH-D04),判据 STD-ADMIN-0002 与 0005 各有一段「机器守到哪」写明同一件事。
条款总表
| 条款 | 标题 | 要求 | 守护 |
|---|---|---|---|
ARCH-A01 | 分页表、单查表、单条表里不许有排序号 | 禁止:x-data/** 下的 *_base / *_node / *_leaf 三类业务表(*_log / *_relation / *_dict 不在射程),凡读取形态是分页 B、单查 C 或单条表的,字段里出现 orderNo 或任何 *OrderNo 后缀字段(后缀按 ^[a-z][a-zA-Z0-9]*OrderNo$ 识别,裸 OrderNo 不算)。形态识别按固定次序:① .md 里出现「单记录」「单条记录」「全系统仅一条」「全系统只有一条」四词之一 → 单条表;② 否则 _node / _leaf → 全量 A;③ 否则 _base 拿表名去后缀、下划线换连字符,全树递归找 {前缀}-read 云函数的 controller.js,剥注释与字符串后 pageSize: z. 与 pageNumber: z. 同时在场 → 分页 B(只测出现与否,不看带不带 .optional);否则取文件里**第一个**匹配 xxxCode: z.string() 或 xxxId: z.string() 的字段,它不带 .optional → 单查 C;其余 → 全量 A。全量 A 与嵌套表反过来是「可选」:带不带排序号由排序需求决定。 | x-order:NS-DATA-0001 |
ARCH-A02 | 排序字段只能叫 orderNo,或以 OrderNo 结尾 | 必须:排序号字段命名为 orderNo;同一行需要两级排序时用 *OrderNo 后缀(camelCase 前缀 + OrderNo 结尾,如 groupOrderNo + paramOrderNo)。 | 无机器闸:射程类(判据按字段名字面识别排序字段,换个名字整条链上的闸同时失明,而失明与通过在报表上无法区分) |
ARCH-A03 | 拖拽表的排序号是系统字段,用户碰不到 | 必须:有对应 *-order-update 云函数的业务表,其 orderNo 字段在 .datasource.json 里标 "x-system": true,.md 字段表同步标注它由排序云函数维护。判据按表前缀反查:表名去掉 _base / _node / _leaf 后缀、下划线换连字符得到表前缀,再枚举 x-server 下全部带 package.json 的 {前缀}-order-update 目录,前缀**等于表前缀**或**等于表前缀的复数形**(尾部加 s)即判拖拽专属(supplier_base ↔ supplier-order-update、sop_step_node ↔ sop-steps-order-update)。 | x-order:NS-DATA-0002 |
ARCH-B01 | 重排只有一种写法:调 sys 预设的 reorderByPk | 必须:x-server/**/*-order-update/repo.js(排除 templates/、sys/ 与撞名的 refund-order-update/)里的重排写成两段 —— P1 从 ./sys/utils/order/presets/reorder-by-pk 引入 reorderByPk,P2 一行 return reorderByPk(db, '表名', '主键字段', orderedIds),四个参数顺序固定,表名是 snake_case 字符串字面量、主键是 camelCase 字符串字面量。这类文件只要存在就必须挂 STD-SERVER-0001 的标记,且标记块内必须真有 reorderByPk 调用 —— 空块不算。 | x-order:STD-SERVER-0001x-order:NS-SERVER-0001 |
ARCH-B02 | 重排禁逐行更新,必须一条 SQL 全量重写 | 禁止:*-order-update/repo.js(同样排除撞名的 refund-order-update/)里出现 ORM 的 .update( 或 .updateMany(;同样禁止的是「两样批量重写手段一个都没有」—— 剥掉注释与字符串之后的代码里必须至少出现 reorderByPk( 或 $runSQL( 之一,两者皆无照样报红。 | x-order:NS-SERVER-0003 |
ARCH-B03 | 新建行的排序号由 appendNextOrderNo 追加 | 必须:拖拽专属实体的 *-create/repo.js 写成两段 —— P1 从 ./sys/utils/order/presets/append-next 引入 appendNextOrderNo,P2 一行 record.orderNo = await appendNextOrderNo(db, '表名', 分组参数);赋值目标必须是 record.orderNo(其他变量名禁止),无分组传 {},有分组传 { 字段: 值 }。闭环闸的触发条件是「剥注释与字符串后文件里出现 orderNo 且同级兄弟目录有 {本函数前缀}-order-update/package.json」,触发即必须挂 STD-SERVER-0002 的标记,块内必须真有 appendNextOrderNo 调用。 | x-order:STD-SERVER-0002x-order:NS-SERVER-0002 |
ARCH-B04 | 拖拽专属的新建不许留「用户传了就用」的第二条轨 | 禁止:拖拽专属的 *-create/repo.js 里出现 if (params.orderNo 开头的双轨分支(判据按这一个形态匹配,剥注释与字符串后的代码视图)。 | x-order:NS-SERVER-0006 |
ARCH-B05 | 拖拽专属实体的新建与更新入参里不许有排序号 | 禁止:拖拽专属实体的 *-create/controller.js 与 *-update/controller.js 的 zod schema 里出现 orderNo: z. 形态的字段(*-order-update/controller.js 自身除外 —— 它就是排序接口本身,已在适用面排除)。两颗闸都按「同级兄弟目录里有没有 {本函数前缀}-order-update/package.json」判拖拽专属。 | x-order:NS-SERVER-0004x-order:NS-SERVER-0005 |
ARCH-B06 | 拖拽还是手工,开关就是那个云函数目录本身 | 必须:想让一张表从手工排序变成拖拽排序,就建 {实体前缀}-order-update 云函数目录;不想要拖拽,就不要建它。建与不建之间,全链路十颗闸同时改判。 | 无机器闸:射程类(拖拽专属与否由目录存在性代理,删掉或改名之后十颗闸集体静默,与「扫过了没问题」在报表上无法区分) |
ARCH-C01 | 后台的拖拽属性只有两种形态,且必须挂标记 | 必须:x-admin/src/**/*.tsx(xComponents 除外)里的拖拽属性写成 STD-ADMIN-0001 的两种形态之一 —— P1 是左卡列表的即时模式(dragSort 对象里写 onConfirm 与 permission,onConfirm 内调 xxxOrderUpdate({ orderedIds }),权限取自 AUTH_META.orderUpdate.id),P2 是行列表的 pro3 拖拽表格形态(写 dragSortKey 与 onDragSortEnd,权限在回调内用 access.canCallFunction(AUTH_META.orderUpdate.id) 自己判,因为这个组件没有权限属性)。两种形态的原子服务名都必须是 camelCase 且以 OrderUpdate 结尾。文件里**每一处** dragSort={{ 都必须落在一对 STD-ADMIN-0001 的标记块内(V1.3.0 起逐处归属:同页两个载体各配拖拽时,挂了一个块不能掩护另一处),且标记块内必须真有 dragSort={{ —— 挂个空块不算。 | x-order:STD-ADMIN-0001x-order:NS-ADMIN-0002 |
ARCH-C02 | 拖拽与分页互斥 | 禁止:同一个 .tsx(x-admin/src/**,xComponents 除外)里同时出现 dragSort={{ 与 usePagination={true}。 | x-order:NS-ADMIN-0010 |
ARCH-C03 | 拖拽页不许再给用户第二种排序入口 | 禁止:拖拽专属页面(文件里有 xxxOrderUpdate( 调用)的列配置里出现 sorter: true 或 sortField: 'orderNo';以及同一文件里 dragSort={{ 与 displayMode="list" 共存。 | x-order:NS-ADMIN-0005x-order:NS-ADMIN-0008 |
ARCH-C04 | 拖拽页不许把排序号画成一列 | 禁止:拖拽专属页面(xModules 与 xCore 下的 .tsx)的列配置里出现 dataIndex: 'orderNo'。 | x-order:NS-ADMIN-0004 |
ARCH-C05 | 拖拽页的表单与详情字段配置里也不许有排序号 | 禁止:拖拽专属页面的新建 / 编辑表单里出现 name='orderNo' 的录入控件;详情页的字段配置里出现 dataIndex: 'orderNo'。 | x-order:NS-ADMIN-0006x-order:NS-ADMIN-0007 |
ARCH-C06 | 拖拽专属实体的前端参数类型里不许有排序号 | 禁止:拖拽专属实体的 *CreateParams / *UpdateParams 类型里含 orderNo 字段(实体类型本身豁免 —— 它描述的是「读回来的行长什么样」,那一列确实存在)。 | x-order:NS-ADMIN-0009 |
ARCH-C07 | 组件里的拖拽计算收口到一个工具 | 必须:x-admin/src/xComponents/** 下的 .tsx 组件用了 @dnd-kit/ 拖拽库,就必须写一条 from '@/xTools/sortable' 的引入,由 resolveReorder 把拖拽事件换算成有序 id 数组。 | x-order:NS-ADMIN-0001 |
ARCH-D01 | 详情页步骤的编辑态拖拽有固定的字段契约 | 必须:use-detail-editable-steps.ts 导出 reorderedStepIds: string[] | null 这个状态字段(null 表示本次没拖过),由它派生出提交用的顺序(collectStepChanges 过滤掉临时新建行与已标删除行后产出 stepOrder,再经保存适配器调 sopStepsOrderUpdate({ orderedIds: stepOrder }) 落库);该文件必须挂 STD-ADMIN-0002 的标记,且标记块内必须真有 reorderedStepIds —— 空块不算。 | x-order:STD-ADMIN-0002x-order:NS-ADMIN-0003 |
ARCH-D02 | 内联子表的重排要染色,派生算法写死 | 必须:详情页内联子表(table.tsx)的行样式里含 isRowReordered 这个派生函数:它比对某一行在当前列表里的位置与在原始列表里的位置,位置变了才算重排;新建行(键以新建前缀起头)与已标删除的行直接返回否,各自走各自的染色。行样式的优先级固定为「已删除 > 新建 > 重排 > 无」。该文件里只要出现 sortableResolved 这个标识符,就必须挂 STD-ADMIN-0003 的标记,且块内必须真有 isRowReordered。 | x-order:STD-ADMIN-0003x-order:NS-ADMIN-0011 |
ARCH-D03 | 嵌套双层表的重排染色,外层内层各一份 | 必须:嵌套表(nested-table.tsx)的行状态派生里,外层与内层各加一个重排分支 —— 外层基于 originalKeyToIdx 比对当前外层索引,内层基于本组内的 origInnerKeyToIdx 比对当前内层索引,两者都是「映射里有这个键,且记录的位置与当前位置不同」双条件,命中后统一设成 modified(已修改)状态,排在字段修改分支之后。文件里只要出现 useSortable(,就必须把 STD-ADMIN-0005 的 P1 与 P2 两段标记都挂上,且 P1 块内必须真有 originalKeyToIdx、P2 块内必须真有 origInnerKeyToIdx。 | x-order:STD-ADMIN-0005x-order:NS-ADMIN-0013 |
ARCH-D04 | 排序差分的算法本体不模板化,只锚住它的字段名 | 必须:知道编辑态的排序差分算法(哪些行算「位置真的变了」、按什么顺序产出提交数组)有意不被模板化,本规范只焊住它对外的字段名与消费方式;改算法时自己对着原始顺序逐例核对,别指望闸会拦。 | 无机器闸:语义类(判据只逐字比对字段名与消费形态,算法本身算得对不对它看不见,且算错的表现是数据错位而非报错) |
ARCH-E01 | 子表的重排在保存适配器里落库 | 必须:保存适配器消费内联子表变更时,按 STD-ADMIN-0004 的形态写 —— 先判模式是 'inline-edit'、再判有重排数组(xxx.toReorder)、再判主表主键不是 NEW_ 起头的临时值,三个守卫齐了才调 xxxOrderUpdate({ orderedIds: 子表.toReorder }),并且用 unwrapApiResult 包住让失败抛出去。*.bff.ts 里**每一处** await xxxOrderUpdate( 调用(import / export 起头的行不算)都必须落在 STD-ADMIN-0001 / 0002 / 0004 三种标记之一的块内(V1.3.0 起逐处归属)。 | x-order:STD-ADMIN-0004x-order:NS-ADMIN-0012 |
ARCH-E02 | 拖不动、拖了没落库,都要让用户看得见 | 必须:即时模式下拖拽先动画后落库,接口失败时把顺序退回原样并给出提示;批量模式下排序随保存一起提交,失败时整次保存要报错,不许出现「保存成功但顺序没变」。 | 无机器闸:运行时类(乐观更新有没有回退、提示有没有弹、真机手感如何,都是运行时行为,静态判据看不见) |
ARCH-F01 | 进入退款中的订单行,除了转出状态不许再写 | 禁止:任何 UPDATE order_item_node 或 UPDATE order_refund_node,如果它的 WHERE 段能匹配到该表状态列等于退款中(等值或 IN 列表都算;订单行的状态列是 itemStatus,退款单行是 refundStatus),它的 SET 段里就必须包含**同一个状态列**的赋值 —— 只允许转出退款中,不允许「保持退款中、只改别的列」。形态域是 UPDATE <表> [别名] [INNER|LEFT|RIGHT|CROSS] JOIN … SET,联表写法与直写同等看见;判据把 SET 段与顶层 WHERE 段按括号深度分开,SET 右值里的子查询自带的 WHERE 不算。 | x-order:NS-SERVER-0007 |
ARCH-F02 | 员工和客户能看见的字,必须是人话 | 禁止:钱域的运行时字符串(台账备注、业务异常的提示语、批量结果里的失败说明)里出现工程黑话 —— 工程编号(F 加**恰好**两位数字:F54、F50a 算,后面紧跟第三位数字的商品型号如 F543 不算)与架构术语(不变式、实收锚、幂等、竞态、半程崩溃、存量黑洞、前滚、预登记、翻态、三步式、幻值、单语句、TOCTOU、CAS、Σ、attempt 已耗、payShareFen、直翻、翻单、行级)。 | x-order:NS-SERVER-0008 |
ARCH-F03 | 补记审计凭证时,退款单号只准取原值 | 禁止:对账补记那条路径里(order-payment-reconcile-update/service.js),在写退款台账的调用(writeRefundTxnLog()所在行往上数 15 行的窗口内出现 'RF' + 这样的单号拼接。 | x-order:NS-SERVER-0010 |
ARCH-F04 | 台账的取值范围,三个载体一起改 | 必须:两张台账表(订单状态台账 order_status_log、订单交易台账 order_transaction_log)的取值范围有三个声明载体 —— x-data/选项集清单.md(真相源,按 orderLogSource / orderTxnDirection 两个条目取「标识:\x\」行)、表 .md 的对应字段行(| source | / | direction |)、.datasource.json 里**该字段自己**的 description;加值或改值时三处一起改,任一处漏掉即违规。 | x-order:NS-DATA-0003 |
ARCH-G01 | 小程序端不在本规范射程内 | 必须:知道本规范的适用面只有数据表、云函数、后台三处;小程序端没有任何一颗闸。 | 无机器闸:射程类(本规范的适用面不含移动端,端上写什么都结构性看不见) |
ARCH-G02 | 新增以 order-update 结尾但不是排序的云函数,同批加排除 | 必须:新建一个名字以 -order-update 结尾、但语义不是「重排序号」的云函数时,同一批把它加进判据里那三处排除面(重排标准写法 STD-SERVER-0001、重排闭环兜底 NS-SERVER-0001、禁逐行更新 NS-SERVER-0003),并在架构页留痕。 | 无机器闸:流程类(判据靠目录名后缀圈射程,撞名只能逐例登记排除;有没有同批登记是流程事实,一次扫描看不出来) |
ARCH-G03 | 手工模式要么做完整,要么不做 | 必须:没有排序云函数的表走手工模式 —— 排序号字段不标系统字段、新建与更新的 zod 里要含它、前端表单要给出录入控件。三样要么齐,要么这张表就别有排序号。 | x-api:NS-SERVER-0131 |
判据实现:闸怎么咬
| 规则号 | 名称 | 认领条款 |
|---|---|---|
STD-SERVER-0001 | reorder调用模板 | ARCH-B01 |
STD-SERVER-0002 | append调用模板 | ARCH-B03 |
STD-ADMIN-0001 | dragSortProp模板 | ARCH-C01 |
STD-ADMIN-0002 | useDetailEditableSteps契约 | ARCH-D01 |
STD-ADMIN-0003 | DetailInlineTable拖拽染色契约 | ARCH-D02 |
STD-ADMIN-0004 | DetailBFFReorder消费模板 | ARCH-E01 |
STD-ADMIN-0005 | NestedTable双层reorder派生 | ARCH-D03 |
NS-DATA-0001 | 业务表 orderNo/*OrderNo 三态契约 | ARCH-A01 |
NS-DATA-0002 | 拖拽专属orderNoXSystem:true | ARCH-A03 |
NS-SERVER-0001 | STDSERVER0001闭环兜底 | ARCH-B01 |
NS-SERVER-0002 | STDSERVER0002闭环兜底 | ARCH-B03 |
NS-SERVER-0003 | 排序云函数repo禁逐行更新 | ARCH-B02 |
NS-SERVER-0004 | 拖拽专属*-create zod禁orderNo | ARCH-B05 |
NS-SERVER-0005 | 拖拽专属*-update zod禁orderNo | ARCH-B05 |
NS-SERVER-0006 | 拖拽专属*-create repo禁双轨 | ARCH-B04 |
NS-SERVER-0007 | refunding态原子性锁(对账时钟不可污染) | ARCH-F01 |
NS-SERVER-0008 | 员工可见文本人话律 | ARCH-F02 |
NS-SERVER-0010 | 补记路禁幻值单号复活 | ARCH-F03 |
NS-DATA-0003 | 台账值域声明双载体一致 | ARCH-F04 |
NS-ADMIN-0001 | xComponents拖拽强制import xTools/sortable | ARCH-C07 |
NS-ADMIN-0002 | STDADMIN0001闭环兜底 | ARCH-C01 |
NS-ADMIN-0003 | STDADMIN0002闭环兜底 | ARCH-D01 |
NS-ADMIN-0004 | 拖拽专属ProColumns禁orderNo列 | ARCH-C04 |
NS-ADMIN-0005 | 拖拽专属ProColumns禁sorter | ARCH-C03 |
NS-ADMIN-0006 | 拖拽专属form禁orderNo字段 | ARCH-C05 |
NS-ADMIN-0007 | 拖拽专属DetailSections禁orderNo | ARCH-C05 |
NS-ADMIN-0008 | dragSort与Sorter/list互斥 | ARCH-C03 |
NS-ADMIN-0009 | 拖拽专属*Params禁含orderNo | ARCH-C06 |
NS-ADMIN-0010 | dragSort与usePagination互斥 | ARCH-C02 |
NS-ADMIN-0011 | STDADMIN0003闭环兜底 | ARCH-D02 |
NS-ADMIN-0012 | STDADMIN0004闭环兜底 | ARCH-E01 |
NS-ADMIN-0013 | STDADMIN0005闭环兜底 | ARCH-D03 |
取舍与在案裁定
V4 放宽:读取形态与排序需求解耦(2026-06-19)
V3 要求「全量加载的嵌套表必须含排序号」,把两个正交问题焊在一起,结果是语义上明明属于「被父表拥有的子表」的表,为了不带排序号而伪装成主数据聚合根 —— 本末倒置。V4 拆开:排序号的有无由排序需求决定,拖拽、手工、派生排序(如按默认标记与更新时间)三者皆合法;放宽只发生在「可选」那一侧,分页 / 单查 / 单条禁含一个字没松。落地在条款 ARCH-A01。
撞名排除:退款退货单审批函数不是排序云函数(2026-08-09)
refund-order-update 更新的是「退款退货单」,与重排序号毫无关系,但它的目录名结构性地撞上 *-order-update 这个后缀。此前三颗闸(重排标准写法、重排闭环、禁逐行更新)把它扫进来,逼一个审批函数去挂重排模板的标记。裁定是实体化批排除:三处排除面同批登记,一处不漏。撞名不会因为谁更小心就消失,只能逐例登记 —— 条款 ARCH-G02 把这条流程写下来。
对账时钟保留最后更新时间,不改用台账时间
超时退款件的扫描用「行状态是退款中 + 最后更新时间早于截止点」当时钟。改查状态台账的最近一次翻态时间看似更干净(台账只追加、时间戳物理不可重置),但引入更严重的失败模式:翻状态与写台账分属两条语句而平台无跨表事务,中间崩溃就会出现「行是退款中、台账无记录」→ 子查询为空 → 谓词恒假 → 永久漏扫(活体探针实证过)。而最后更新时间与状态变更在同一条 UPDATE 内原子写入,永不缺失。裁定:保留现有时钟,并用 NS-SERVER-0007 把它的前提(进入退款中后除转出零写入)焊成物理闸 —— 普查时全库写入点全部满足这条不变量,但那是巧合而非强制。
人话律与备注四分类(2026-08-01 立)
台账备注与业务异常提示经订单事件流、工单流水直达客户与员工屏幕。立闸时实测约 30 条备注里 14 条以上含工程黑话。裁定:黑名单走枚举制(新黑话出现时按需扩,禁预防性泛化 —— 泛化必然误伤业务文案);工程归因锚移入代码注释;备注内容按四类处置(独立信息必须写清楚、事件复述保留、原始取证体改走日志、工程考古长文归表文档变更历史);SYS_500 行豁免是架构语义(工程师诊断通道)而非兜底。同日立法者自己的 4 行存量违规也一并改写 —— 闸只扫代码不扫库存量,这是它的诚实边界。
单号两条路刻意相反
补记路只准取原值(NS-SERVER-0010),恢复路恒重算绝不查表。看似矛盾,实则各自正确:补记写的是审计凭证,重算出的值可能是微信侧不存在的幻值(v1.5 前的 4 行 …N0 即此病),写进台账等于伪造;恢复路算出的单号要拿去问微信,问错了微信会告知不存在,可以自纠。裁定是把这条差异物理化,而不是统一成一种写法。
清单与代码消费面那一轴已收编退役(2026-08-09)
本规范原有的 NS-COMMON-0001(订单值域选项集三方一致)是「清单 ↔ 代码消费面」的一对一先例,2026-08-09 泛化成 x-data:NS-DATA-0215 通用闸,全部选项集统一治理,本规范那颗退役。台账值域三载体一致(NS-DATA-0003)作为特例保留 —— 它管的是「清单 ↔ 表文档字段行 ↔ 表定义字段说明」三个声明载体,与消费面那一轴正交。这也是本规范编号里 NS-COMMON 段空缺的原因。
四锚 fail-loud(2026-08-18)
台账值域那颗闸原本有四个静默点(清单文件缺失、条目锚失配、段内零值提取、表文档字段行锚失配),任一处锚漂移,检测就整个消失而报表照常显示通过 —— 典型的假牙。裁定:四处全部改成锚坏当场曝红,与 x-data:NS-DATA-0215 的锚有效性同哲学。
排序差分算法有意不模板化
详情页步骤的差分算法依赖运行时表单注册结果裁剪原始数据、业务形态多,物理上写不成逐行比对的模板(原则 15 的业务逻辑块豁免),且它属详情页编排域。裁定:本规范只焊住对外字段名与保存适配器的消费形态,算法本体归代码审查 —— 代价写在条款 ARCH-D04,算错的表现是数据错位而非报错。
行列表拖拽形态零业务消费者,但能力保留
标准写法 STD-ADMIN-0001 的 P2(pro3 拖拽表格)示例源自商品拖拽,而该功能已于 2026-07-14 按架构决策整体移除、排序云函数与本地代码全链清除。裁定:P2 能力保留、示例作为教学留在判据里,新增行列表拖拽时按它实例化,避免临时另发明一种写法。代价是这一段模板当前零活体,报表上与「扫过了没问题」无法区分 —— 记在「诚实边界」。
钱域文案面的领域归属改成共管(2026-08-05)
人话律那颗闸的支付网关目录 glob 曾经两种扫描模式都不可达:领域独占在聚合阶段剔除非属主规范,与扫描模式无关,所以它当时是一条死规则、支付文案面零闸。根治方式是把该目录的属主由单值改成数组(x-api 与 x-order 并列),两轴正交共管,语义同内核目录的三规范共享。现状是两种模式均可达。
V1.2.0:钱域那颗闸严堵到底,反查推广到数据端(2026-09-16)
V1.1.0 把三个缺口登记成了「诚实边界」留待拍板,用户口径是钱域有漏洞必须严堵、方案禁复杂化,于是同一天全部堵上,只升一次版。三处改动都不改判定语义、只扩它看得见的面:① 原子性锁的形态域容纳 UPDATE <表> [别名] [INNER|LEFT|RIGHT|CROSS] JOIN … SET —— 改前正则要求表名/别名后直接跟 SET,库里 2 处联表写法长期在视野外;② 守护落点补上 order_refund_node —— 对账时钟的真实落点在退款单行,改前本闸只守订单行、与后果链分家,两张表各用各的状态列(itemStatus / refundStatus);③ 数据端系统字段那颗正查改反查,容纳复数前缀,四张排序表全部进入射程。三处改完实测零新增违规(40 处钱域 UPDATE 里 18 处命中退款中、全部转出;四张表的排序号早已标系统字段)—— 堵的是将来,不是存量。
为什么不加第三处「时钟迁移」的选项:把对账时钟从 updatedAt 迁到独立来源是一次跨云函数的改造,而本轮要解决的问题只是「闸没看见该看的地方」。扩形态域与扩表名各是一行判据改动,配一张床就能钉死;迁时钟则要动业务代码、改扫描谓词、还要处理迁移期的双写 —— 那是「复杂化」,与用户口径相反。时钟本身的设计取舍(为何不用台账时间)仍按下方那一条,没有变。
V1.1.0:拖拽专属的判法从「正查同名」改成「反查前缀」(2026-09-16)
前端参数类型那颗闸此前把模块路径正则锁死成单层、又按「模块名 + -order-update」去正查目录,两者叠加后真正被判过的模块只剩 supplier 一个:多级模块(xModules/ecommerce/** 等 8 份 types)结构性出界,而 sop 的排序函数叫 sop-steps-order-update、正查恒落空。裁定:模块路径放开到任意层级;拖拽专属改为枚举 x-server 下全部 {前缀}-order-update 目录反查,前缀等于模块名或以「模块名-」起头即算,反向不成立(模块名比前缀长时不算,避免组件级子模块继承父模块的拖拽属性)。撞名的 refund-order-update 照样会被枚举进来,此处不加第四处排除:今天没有同名模块,而假阳是会报红的(可见),静默失明才是不可见的 —— 宁可留一个将来会炸出来的红,也不预先加一份要维护的名单。目录树遍历改用引擎注入的 tools.ignoredDirs,不再手抄跳过表。配套床见「测试床」节第一行。
规范名与内容的张力(登记)
本规范叫 x-order,内容主体却是拖拽排序;同时它又确实持有四颗订单钱域的闸。两件事共用一个 order 字而语义不同,读判据时极易误以为它是订单业务规范。本轮迁四件套不动判据一个字,仅在此登记这条张力:如果将来要拆,拆的应当是钱域那四颗(连同它们的适用面一起迁到钱域规范),而不是给排序轴改名。
测试床:凭什么信它在咬人
本域的闸全部有床,零待补。V1.1.0 改了参数类型那颗的射程,同批建了 x-test/x-order-ns-admin-0009-module-depth-tooth.test.js(10 例);V1.2.0 扩了原子性锁的形态域与守护落点、把系统字段那颗的正查改成反查,同批建了 x-test/x-order-ns-server-0007-ns-data-0002-money-clock-tooth.test.js(20 例)。2026-09-16 补床轮把余下 29 颗一次补齐,新建的床合计 230 例,全过。V1.3.0 判据整改轮三张床同批补样本(钱域 34 → 36、拖拽载体 24 → 27、保存适配器 20 → 23),十张床合计 268 例,全过。
三种臂,缺一不可。「形态」臂把样本喂给引擎真检测器(extractNsRuleDetector + buildDetectorTools);标准写法那七颗另有一条「模板」臂,走引擎真模板匹配器(checkStandardFormat,在系统临时目录落真文件 —— 引擎的 STANDARD 段是从磁盘读目标文件的,只喂内存字符串会静默得到零违规,立床当场踩到);「射程」臂把假工作区喂给引擎真选文件器(scanFilesByRule)验适用面与排除面 —— 本域绝大多数闸的路径过滤不在检测器体内,拿检测器去断言「某某目录不该咬」是问错了对象。所有床零复刻判据逻辑,假工作区一律建在系统临时目录、跑完即删,仓里零写盘。
七颗标准写法都是 if-exists —— 文件里一个标记都没有时它整体不适用。八张床各有一发把这条静默面写成断言(「写了拖拽却不挂标记 ⇒ 模板闸零违规」),因为这正是七颗闭环闸存在的全部理由:模板能不能被绕过,押在「出现特征就必须挂标记」+「挂了标记块里没有真节点也要咬」这两条上。每一颗闭环闸都配了反伪空块的那一发;V1.3.0 改成逐处归属的两颗(拖拽属性、保存适配器的排序接口调用)另各补「一处包住 + 一处裸写 ⇒ 恰咬 1 条且点名那一行」与「只写 BEGIN ⇒ 咬」两发 —— 文件级判定时这两种写法都是零违规。
按「守实现不守闸」口径不登记的相邻床有七张:x-test/order-reconcile/reconcile.test.js、x-test/order-refund-preview/preview.test.js、x-test/refund-apply-create/apply.test.js、x-test/refund-order-create/order-create.test.js、x-test/refund-order-update/refund-order-update.test.js、x-test/refund-self-cancel/self-cancel.test.js、x-test/dispatch-reopen/reopen.test.js —— 它们跑的是退款与对账的运行时行为(状态机、金额、幂等),确实与钱域那三颗闸守着同一批代码,但没有任何一例断言过判据的判定逻辑:闸判的是「这条 SQL 的形态合不合法」,床验的是「这次退款算得对不对」。两者同绿不互相担保。下面每一行写清那张床给它守的闸钉住了什么、以及哪些方向没验。
- 数据端两颗(2026-09-16 新建,27 例全过;同组的系统字段那颗归下面第四行的钱域床)。三态契约钉住的头一件事是那条静默路径:它先找同名读云函数推断读取形态再判,推不出形态就整体不报——床造了「读云函数缺席 + 表里有排序号 ⇒ 零违规」与「同一份内容加上分页读云函数 ⇒ 必咬」的对照组,把「不报」与「扫过了没问题」分开。另验分页 B / 单查 C / 单条表三种禁含形态各必咬、全量 A 与嵌套表含排序号不咬(V4 放宽)、后缀识别不许放宽(
orderNoSub/OrderNo/groupOrder三种近似名都不算)、读云函数把分页参数写在注释里不算分页表(剥注释视图)。台账值域专攻 2026-08-18 那次根治:四个锚(清单文件缺失、条目锚失配、段内零值、表文档字段行锚失配)各一发坏样本,断言全部当场曝红而不是静默;另验段切割不越界吃下一个选项集的值、字段定义键才是锚(顶部必填数组里的同名字符串不许抢锚)、词边界、两张台账各走各的选项集。没验的方向:值的语义说明文字不比对(判据自己声明归人工评审),以及「清单↔后台消费方」那一轴已收编到别的规范、不在本床射程。 - 服务端两个原子与它们的闭环(2026-09-16 新建,25 例全过)。两个标准写法各造一份合规件与五种偏差件:参数顺序换、表名写成变量、主键写成 snake_case、引入路径换成别的预设、两段只挂一段;追加那一条另验分组参数的两种形态(无分组的空对象与带字段的对象都合法)、赋值目标改名必咬、漏掉等待必咬。两颗闭环各验三发:缺标记必咬、标记齐全且块内有真调用不咬、挂了标记但块内是空的必咬;另加一发「把标记写进字符串字面量」,断言走私的标记不算数。射程臂验模板目录 / 内核目录 / 撞名的退款审批函数三处排除面各自生效。诚实边界:新建闭环那颗的「拖拽专属」判断靠同级兄弟目录查找,床里造了跨父目录的一发,断言此时它整体静默(附同内容摆成兄弟就必咬的对照组)——那是布局巧合不是保证。
- 服务端写入面四颗(2026-09-16 新建,30 例全过)。禁逐行更新那颗两臂各验:代码里写逐行调用必咬、注释与字符串里写不咬(剥注释剥字符串视图),以及第二臂「必须有批量写法」——两种合法批量写法各一发正例,把批量写法写进注释仍咬(防注释充数)。两颗入参禁传与禁双轨各验必咬 / 正例 / 注释不误伤 / 非拖拽专属不误伤;更新那颗另验排序接口自己被判据体内提前放行。本床的重点在最后两发:把排序云函数挪去别的父目录,断言三颗同时静默,再用同样三份内容摆成兄弟布局的对照组断言三颗全咬——这条同级兄弟查找的代理边界今天结论正确纯属布局巧合,现在它是可回归的事实。射程臂另验撞名的退款审批函数、模板目录、内核目录、以及排序接口自己的入口文件四处排除面。
- 钱域时钟与拖拽专属反查(V1.2.0 同批新建,20 例全过)。原子性锁那颗验两处扩容各一发反向样本:联表
INNER JOIN … SET命中退款中不转出必咬(改前恒绿)、退款单表order_refund_node命中退款中不转出必咬(改前整张表不在射程);另验LEFT与裸JOIN同在形态域、两张表各用各的状态列、非联表写法不退化、IN列表算命中、SET 右值子查询自带的 WHERE 不误认成顶层条件、别的表不进射程、别名以join起头仍识别为别名。系统字段那颗验复数两臂:三张复数前缀表去掉x-system必咬且报错点名真实云函数(改前三张全恒绿),同名的supplier_base不退化,反查不用startsWith泛匹配(sup_base不许中招)。两组各带真实盘面正例(钱域三个真实文件、四张真实排序表原样零违规)与前提断言(三个真实排序云函数目录在场)。 - 订单钱域另两颗 + 原子性锁的跨行边界(2026-09-16 新建;V1.3.0 起 36 例全过)。人话律逐词验黑名单(工程编号、十个架构术语、字段名类与动作类黑话、两个符号类)必咬,人话文案不咬,注释里的黑话不咬;两处豁免各配一对——诊断通道行放行 / 换个错误码立刻咬,数据库通道的 SQL 串放行 / 同一个词放进普通文案立刻咬(豁免被写宽就是静默放行真违规,这一对是唯一防线);词边界两侧各一发(
CASCADE不误伤 / 真写CAS必咬),微信官方枚举值不误伤,报错点名行号。单号那颗钉窗口边界:同行、上方第 1 行、第 15 行都必咬,第 16 行看不见(判据自认的边界,归代码审查);另验取原值的正确写法不咬、注释不误伤、没有台账写入就不判。原子性锁补了它 V1.2.0 时只写在散文里的两条边界:同一条 SQL 拆成两行写结构性不可见(两张表各一发,附单行必咬的对照组)、参数化状态值不可见。工程编号形态的右边界(V1.3.0 已修):补床轮如实钉过一处现状 —— 形态没写右侧边界,三位型号(如F543)被当成工程编号照咬;V1.3.0 改成「F 加恰好两位数字」,床里那一发翻成不咬,另补F50a仍咬(两位数字后跟字母还是工程编号)、F5432不咬两发反向样本。 - 后台拖拽载体与两颗守门(2026-09-16 新建;V1.3.0 起 27 例全过)。标准写法两种形态各造一组:即时模式缺权限项 / 缺回调 / 服务名不是约定后缀 / 权限硬编码各必咬;拖拽表格形态删掉权限判断必咬、主键槽写成 snake_case 必咬——后者全库零活体,这张床是它唯一被验过的地方。另验两种形态确为二选一(只挂其中一段都合法)。闭环验缺标记必咬、正例不咬、伪空块必咬、注释与字符串里的拖拽属性不误伤、以及单花括号形态不在射程(边界不是豁免);V1.3.0 起按逐处归属再验两发 —— 同页两个载体只包住一个 ⇒ 恰咬 1 条且点名那一行,只写 BEGIN 不写 END ⇒ 咬。工具收口验引了拖拽库没引工具必咬、引入路径必须精确(近似路径仍咬)、没用拖拽库不误伤;并把已知缺口写成事实:引了工具却一次都没调用、照旧手写位置计算时,这颗闸看不见。射程臂验三颗的互补关系(前两颗管业务页、排除框架组件,后一颗只管框架组件)。
- 参数类型那颗的射程床(V1.1.0 同批新建,10 例全过)。钉住的是改判据那一刻的两条病灶:多级模块(
xModules/ecommerce/sop)与前缀不同名的排序云函数(sop-steps-order-update)叠加后这颗闸曾近乎恒静默,床里那一发注入改前零违规、改后必咬。另验反查方向单向(模块名比前缀长时不算)、无排序云函数的单层与多级模块都不误伤、实体类型豁免仍在、组件级子模块不继承父模块、以及诚实边界里xTools根出射程这条现状。床头两条前提断言直接钉住supplier-order-update与sop-steps-order-update两个真实目录 —— 它们没了闸就该静默,届时先在这里炸。 - 后台排他六颗(2026-09-16 新建,40 例全过),假阳性风险最集中的一组。共同软肋①:前四颗靠「文件里有没有排序接口调用」认拖拽页,床造了「调用只出现在报错文案的字符串里」的样本,断言四颗全部不认它是拖拽页,并附同样四份内容改成真调用后四颗全咬的对照组。共同软肋②:后两颗是文件级共现判定,床造了「同一文件里两个互不相干的表格,一个拖拽一个分页」的样本,断言照咬——把「刻意从宽、不是误报」这条设计意图焊住,免得后人当误报去放宽,放宽之后真正混用的那一个就再也拦不住。列展示验行尾豁免标记逐列生效(标一列 / 不标一列,只报没标的那行)、且标在别的行不算数。详情字段验括号配平复位(块闭合之后的排序号列不误报——原实现永不复位会让整片文件假红)。三条已知边界写成事实:列头排序那颗看不见比较函数形态、表单那颗看不见非 ProForm 族控件、分页互斥那颗看不见变量形态。射程臂另验列展示那颗独有的「导出页整片出射程」排除面,其余五颗没有这条。补床轮跑出来的一处判据问题已销账:以引号字符串属性收尾的自闭合标签(
<ProFormDigit name="orderNo" />)当时表单那颗结构性看不见 —— 病根在共享的 JSX 标签解析原子(剥字符串后把/>里的/当成正则起点),不在本规范判据体内;2026-09-18 统筹修好引擎原子,床里那两发同批翻成必咬(单行与跨行各一发)。 - 详情页三种染色载体与各自闭环六颗(2026-09-16 新建,30 例全过)。三颗标准写法各造偏差件:步骤契约改字段名 / 去掉可为空那一支必咬;内联子表改派生函数名 / 删掉新建行守卫 / 删掉已删行守卫 / 把位置对比写反各必咬;嵌套双层改外层映射名 / 改内层映射名 / 少了防误判的那一半条件 / 只挂一段各必咬。三颗闭环各验缺标记必咬、正例不咬、伪空块必咬;嵌套那颗另验双段各判各的(只挂外层 ⇒ 只报内层缺失)。口径对拍(部分覆盖):用引擎原子从真实产品文件里取出两处可运行的位置派生,在同一份行变动夹具上对拍,断言「哪些行算动过」完全一致;另单独验内联子表那一处的新建行 / 已删行 / 非编辑态三道守卫真的生效。没覆盖到的两处:① 步骤编辑态的标准写法只是一条类型契约,模板里没有可运行的派生,物理上进不了对拍;② 嵌套表的「新建 / 已删优先」判断写在标记块外面的分支链里,不在被守护的块内,所以本床只对拍位置派生本身、不对拍优先级链,也没验「外层缓存依赖漏了原始数据」那条(模板里明写、但闸不看依赖数组)。射程臂验六颗三两成对、各自只认一个文件(同目录的隔壁文件都不认)。
- 保存适配器两颗(2026-09-16 新建;V1.3.0 起 23 例全过)。三个守卫各造一份缺项样本:缺模式守卫(别的模式跟着走会把没动过的顺序写回后端)、缺重排数组判空(没拖过就没有这个数组)、缺新建主表守卫(主表还没落库就给子表排序),三发全必咬;另验接口名不是约定后缀必咬、漏掉错误透传包裹必咬,以及表别名与父键变量确为槽位(换名字照样合规)。闭环验三种标记任一皆可(即时模式 / 步骤编辑态 / 内联子表,今天库里三种各有活体)、缺标记必咬、挂了空标记块而调用写在块外必咬、标记写进字符串字面量不算数;V1.3.0 起它逐处归属 —— 复合适配器里两处子表重排只包住一处 ⇒ 恰咬 1 条且点名那一行(文件级判定时这是零违规),只写 BEGIN 不写 END ⇒ 咬,旧的「块内必须有真调用」防线被逐处归属吸收(空块不再掩护任何调用)。一条边界写成事实:它逐行跳过以引入 / 导出起手的行,所以「单行导出箭头函数里整句调用」结构性看不见(附换行写就照咬的对照组)。射程臂验业务模块与框架组件的保存适配器都在射程里、原子服务文件与模板目录不在。
- 闸真的会咬造出违规样本喂给引擎里那颗真检测器,正例必红,且报错点名到具体位置
- 闸拆掉就不咬反向注入:临时改坏判据,对应那一发必须变绿 —— 这才证明闸没在空转
- 射程真的覆盖到问引擎真选文件器:该进门的进门,射程外的确实不进
- 判据写明的边界确实不咬把「刻意不管」的写法逐条钉成绿,防止后人误以为漏了
- 不证明床真测到了那颗闸架构层的元闸只验「床存在、内文写了闸号、真调了引擎」,验不了它测的是不是那一颗
- 不证明床被跑过点名与执行是两条独立的链:页面说「有床守着」,不等于哪个运行器真的扣了扳机
- 不证明判据是对的床按判据当下的语义写;判据本身理解错了,床会忠实地复现这个错误
诚实边界:守不住什么
本节是承诺不是待办:做不到的明说,删掉本节等于默认宣称全覆盖。这一域说「无机器闸」的条款分属射程、流程、语义与运行时几类,病根却是同一个:本域的闸认不出「排序」这件事本身,它认的是名字 —— 字段叫什么、云函数目录叫什么、接口调用叫什么。名字一改,整条链上认它的闸同时失明,而失明与「扫过了没问题」在报表上长得一模一样。另有一条看着像没有闸、其实由接口域的字段集对齐闸咬住一头(手工排序那条),不在本节重复承接。
条款书说「无机器闸」的那些,实际由谁兜底
ARCH-A02排序字段只能叫 orderNo,或以 OrderNo 结尾射程类 —— 全链路没有一处按语义认出「这是个排序字段」,数据端的三态契约、系统字段标记、云函数的入参禁传、前端的参数类型与列表单,全部按字面名字识别。取名叫 sort、seq、displayOrder 的字段在所有判据眼里与一个备注字段没有区别:它能待在分页表里、能进新建接口入参、能画成一列让用户随手改,一颗闸都不会响。兜底:建字段时就按这个名字命名,不为了「更好听」改名;由改表那一轮的人审接住。ARCH-B06拖拽还是手工,开关就是那个云函数目录本身射程类 —— 是不是拖拽专属,全靠「服务端有没有那个排序云函数目录」代理判定。好处是开关只有一处、不会出现登记说是拖拽而实际没有函数的分歧;代价是这个开关极其隐蔽,删掉或改名那个目录,认它的闸会一起静默,报表上不给任何提示。更细一层:认它的闸用了几种不同的代理判法(查同级兄弟目录、枚举目录反查前缀、看文件里有没有那个接口调用),它们什么时候一致、什么时候分家,直接决定哪几颗闸其实没在看这个实体。兜底:退掉拖拽时,同批回头逐处核对数据端的系统字段标记与前端的列、表单、参数类型 —— 那一刻闸已经不看它们了。ARCH-D04排序差分的算法本体不模板化,只锚住它的字段名语义类 —— 这是在案的边界登记,不是疏漏:差分算法要依赖运行时的表单注册结果去裁剪原始数据,业务形态又多,物理上写不成一份逐行比对的模板,所以判据把锚点放在字段名与消费形态上(一个字段名可以逐字比对,一段算法不是)。代价说清楚:算法本身写错(把没动过的行也塞进提交数组、顺序起点错位)在所有闸看来都是绿的,它只会在库里表现成每次保存都全量重排一遍这种没人会注意的浪费,或者更糟的错位。兜底:改这段算法时造几组真实数据逐例核对 —— 全没动、只动一行、动了又拖回原位、动的同时删一行、动的同时加一行,改完把契约两侧一起回看。ARCH-E02拖不动、拖了没落库,都要让用户看得见运行时类 —— 拖拽是这套后台里唯一一个「界面先变、库后变」的交互,失败模式因此格外隐蔽:动画已经播完,用户记忆里这件事已经做完了,静默失败要很久以后才被发现,通常是别人问「怎么顺序又不对了」。判据焊得住调用形态与错误包装,焊不住回退有没有真的发生、提示有没有真的弹出来、真机上手柄好不好用。兜底:改完拖拽相关代码,在本地把四件事逐一点一遍 —— 正常拖拽后刷新顺序仍是新的、断网拖拽会退回并提示、没有排序权限的账号拖不动、批量模式下拖完不保存就离开不会落库。ARCH-G01小程序端不在本规范射程内射程类 —— 适用面只有数据表、云函数、后台三处,移动端一颗闸都没有。这是业务事实的直接结果:端上没有重排这个动作,它拿到的是云函数按顺序返回的数组、照序渲染即可。写下这条是因为「没有闸」与「有闸而且都绿」在任何报表上长得一样。兜底:端上将来真要做排序,必须先走治理环加端、加判据、加条款,再写代码,不能默认后台那套规则自动适用;当前端上遇到顺序问题,先查云函数返回的顺序,不要在端上二次排序 —— 那会与后台拖拽的结果分叉。ARCH-G02新增以 order-update 结尾但不是排序的云函数,同批加排除流程类 —— 几颗闸靠目录名后缀圈定射程,而「订单」在中文业务里天然与 order 撞名:退款退货单的审批函数就叫这个后缀,它更新的是单据、与重排顺序毫无关系,曾被这几颗闸扫进来、逼着一个审批函数去挂重排模板的标记。撞名是结构性的,不会因为谁更小心就消失,能做的只是发现一例登记一例;而「有没有同批登记」是流程事实,一次扫描看不出来。兜底:命名时先避让,不是排序的函数别用这个后缀;避不开就走治理环改判据,三处排除一处不能漏,漏一处那颗闸会在这个函数上报一个永远修不掉的红。
闸射程内已知的失明点
射程事实(2026-09-16 实测)
- 本规范持两根互不相干的轴,本轮不拆。主体是拖拽排序全链路(本域的闸:STD 7 + NS-DATA 2 + NS-SERVER 6 + NS-ADMIN 13),另有四颗是订单钱域闸(
NS-SERVER-0007退款中态原子性锁、NS-SERVER-0008人话律、NS-SERVER-0010补记路单号、NS-DATA-0003台账值域三载体),它们与排序号毫无关系,只是共用一个order字。读判据时极易误以为整份规范是订单业务规范;要拆的话拆的应当是钱域那四颗(连同适用面一起迁到钱域规范),而不是给排序轴改名。本轮(V1.1.0)明确不拆,在此登记。 - 三端实扫面:
x-data52 个目标、x-server375 个、x-admin237 个,全部 0 违规。移动端零目标 —— 本规范没有任何一颗移动端闸,端上写什么都结构性看不见(条款 ARCH-G01)。 - 「拖拽专属」有四种代理判据,今天结论一致但分家条件各不相同。① 同级兄弟目录的四颗(新建闭环、两个入参禁传、禁双轨)在排序云函数与新建 / 更新云函数不在同一父目录时失明 —— 今天四个排序实体恰好都是兄弟布局,那是巧合不是保证;② 数据端系统字段那颗按表名推名后全树递归查,表名与函数名不同形即失明;③ 前端参数类型那颗(V1.1.0 起)枚举全部
{前缀}-order-update目录反查、前缀等于模块名或以「模块名-」起头即算,只有模块自身改名才失明;④ 靠「文件里有没有排序接口调用」的四颗(列、列头排序、表单、详情字段)在调用被改名或提取到别处时失明。四种全部静默,报表上与通过无法区分。 - 数据端系统字段那颗的半盲已销账(V1.2.0)。改前它把表名推成云函数名去正查,而真实函数名普遍用复数,四个排序实体里只有
supplier_base推得准,另外三张表结构性看不见(实测四张表的排序号字段都已标系统字段,所以没有既成后果)。病根与参数类型那颗 V1.1.0 修掉的是同一类,修法也一样:正查改反查。改后四张表全部被看见 —— 活体实证:从这三张表的orderNo删掉"x-system": true,改前零违规、改后三张全报红,且报错各自点名真实的复数云函数。 - 后台拖拽的活体只有一处。全库
dragSort属性只出现在x-admin/src/xModules/supplier/pages/supplier.tsx一个文件、一处;标准写法STD-ADMIN-0001的 P2(行列表拖拽表格)零活体(示例源已于 2026-07-14 全链清除,能力保留作教学)。也就是说两颗互斥闸(拖拽 × 分页、拖拽 × 列表形态)今天各自只有一个文件可能触发,其余时间它们与「扫过了没问题」长得一样。 - 本域标记分布:后台侧 6 个源文件带本规范的标准写法标记(详情页三个框架件 + supplier 页面 + 两个保存适配器),服务端侧 8 个(4 个新建 repo + 4 个重排 repo)。另有两处标记出现在
x-admin/src/.umi与.umi-production的构建产物快照里 —— 那是构建缓存对源码的复制,不在任何扫描面内,搜标记时会看见它们,不要当成第二处活体。 - 排序云函数目录今天有五个,其中
refund-order-update是撞名的退款退货单审批函数(三处排除面已登记),真正的排序云函数是supplier-order-update、supplier-contacts-order-update、supplier-certificates-order-update、sop-steps-order-update四个。V1.1.0 起参数类型那颗把全部五个目录都枚举进反查面,撞名的那个也在其中 —— 今天没有名叫refund的前端模块所以不出假阳,一旦出现就得在那里也加一处排除(条款 ARCH-G02 已写明)。 - 前端参数类型那颗的射程(V1.1.0 实测)。只认
xModules与xCore两个根下的services/{kebab-case}.types.ts,模块路径任意层级;两根下共 30 份*.types.ts全部在射程内(改前有 8 份因多级路径结构性出界)。x-admin/src/xTools/**的 8 份仍不在射程 —— 工具域不持有业务排序表、今天零orderNo,属登记而非守护,要纳入必须同批改判据与条款 ARCH-C06。 - 原子性锁的实证基线(V1.2.0 复测)。按判据适用面(215 个文件)实测:
UPDATE order_item_node16 处、UPDATE order_refund_node24 处,全为单行 SQL 字面量、全部落入闸的形态域(其中 2 处订单行是INNER JOIN … SET联表写法);命中退款中的 8 + 10 = 18 处全部转出,零违规。V1.1.0 登记的两条边界(「16 处里只有 14 处在形态域」、「守护落点与时钟分家」)已由 V1.2.0 两处扩容销账。 - 原子性锁的守护落点是一张两表白名单。
order_item_node与order_refund_node硬编码在判据里、各用各的状态列(itemStatus/refundStatus)。将来有新表进入这条收敛链路(比如按支付单粒度重构退款),不同批登记进去就结构性看不见 —— 这是枚举制换来的精确性所付的代价,与人话律黑名单同一取舍。另:联表只容纳JOIN一族(INNER/LEFT/RIGHT/CROSS与裸JOIN),UPDATE a, b SET …这种逗号隐式联表仍不识别(库里零此形态)。 - 数据端系统字段那颗的复数两臂(V1.2.0)。反查只认两臂 —— 「云函数前缀等于表前缀」与「等于表前缀加一个
s」;库里四个排序实体恰好都落在这两臂内(supplier同名,supplier-contact/supplier-certificate/sop-step各差一个s)。刻意不用startsWith泛匹配:泛匹配会把sup_base判成supplier-order-update的拖拽专属表,假阳会逼人去改一张本来正确的表。代价是-ies、不规则复数、以及多出一整段词的命名不在两臂内,那种命名下这颗闸看不见那张表 —— 所以条款 ARCH-A03 明写「命名时让两者只差一个s」。 - 七条标准写法全是
if-exists形态:只看挂了标记的文件。它们的真实射程等于各自闭环闸的射程,而不等于适用面。 - 七颗闭环里五颗仍按文件判「有没有块」,这是刻意的(V1.3.0 逐颗判过)。判据是「这种写法在一个文件里能不能出现多处」:重排与追加两颗锚在云函数
repo.js上,那是一文件一处的整文件模板;步骤契约、内联子表染色、嵌套双层染色三颗各锚一个框架件单文件,标记包的是那一处契约或派生,而触发标识符(reorderedStepIds、sortableResolved、useSortable()在同一个文件里还会出现在别的用法行上(2026-09-18 实测三个文件各 18 / 7 / 2 处)—— 把它们逐处归属反而会把用法行误判成裸节点。这五颗的文件级判定不构成绕过,配合反伪空块臂(块内必须有真节点)已经够用。另两颗(后台页面的dragSort={{、保存适配器里的await *OrderUpdate()一个文件里确实能出现多处,V1.3.0 已改成逐处归属。
判据自陈的静态不可判面
- 跨行拆写的 SQL 与参数化状态值:原子性锁那颗只认单行字面量,把语句拆成多行、或把状态值写成参数传入,它都看不见。今天库里全部是单行字面量,这是巧合不是保证。
- 变量拼进字符串的内容:人话律只看字面量,运行时拼接进去的黑话判不出来;黑名单是枚举制,新词出现前它不存在。
- 远距离赋值:单号那颗只看调用点上方 15 行,更远处的赋值归代码审查。
- 排序差分算法本身:判据只逐字比对字段名与消费形态,算法算得对不对看不见(条款 ARCH-D04)。
- 工具引了没用:组件拖拽收口那颗只认引入语句,引进来却自己另算一套判不出来。
- 运行时行为:乐观更新有没有回退、失败提示有没有弹、真机上拖拽手柄好不好用,静态判据全部看不见(条款 ARCH-E02)。
- 字段命名规避:排序号字段一旦不叫
orderNo也不以OrderNo结尾,整条链上的闸同时失明(条款 ARCH-A02)—— 这是本域最大的单点盲区,因为它一次性关掉十几颗闸而毫无信号。
本页与判据的分工
本页不复述判据的检测逻辑,只写结构、取舍与边界;每颗闸的判定细节以判据 .claude/skills/x-spec-checker/references/x-order-spec.md 为准,每条条款的「必须 / 禁止 / 为什么 / 怎么做」以条款书 .claude/rules/x-order-rule.md 为准。本页的条款总表、判据总表、两张泳道图与普查快照都是派生区,手改即红 —— 改原件后跑 meta.js --action=sync 重新生成。
本页自己的边界
上面讲的是治理面的边界。这一段讲这张页面本身 —— 架构页也是被治的东西,它同样有机器管不到的地方。
- 「周期性运维」一节不建,这是裁定不是遗漏:标准把它定为条件节,只有真存在「到点必须有人动手」的义务才建。本域治理对象是仓库内的文件;与本域相关的云端到期义务(密钥轮换之类)登记在部署域的那一节里,不在本页重复 —— 同一件事只写一处。
- 正文里的数字没有任何闸管:本页刻意不在散文里复述闸数、条款数与版本号,一律指向页首身份表与两张派生总表。但这是写页人的纪律,不是机器强制。
- 本页遵循《系统架构标准》的可机判面已被闸锁住(节名册与顺序、节编号属性、表达层在场),但标准里「不许发明第二套设计语言」「整页只有一种底色」「架构页不得有自己的页头」这三条判据够不着,靠写页时读标准与人审兜底。