@stalfh233/omc-cli 0.4.19 → 0.4.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -144,7 +144,7 @@ export const BUSINESSRULE_LANE_CONTRACT = Object.freeze({
144
144
  tools: Object.freeze({
145
145
  "rule.list": Object.freeze({
146
146
  scope: "latest rule business-field listing",
147
- description: "列出某模型的最新业务规则版本,回显 enabled/status/developmentMode/ruleVersion 等业务字段;服务端不过滤,客户端自行筛选。",
147
+ description: "列出某模型的最新业务规则版本。默认行=清单面(code/name/enabled/status/ruleVersion/defaultRule——defaultRule:true 是平台预置触发行,客户端自滤);id/createdTime/creator/developmentMode 等审计列走 full:true。服务端不过滤。",
148
148
  }),
149
149
  "rule.get": Object.freeze({
150
150
  scope: "rule node route readback",
@@ -51,28 +51,41 @@ export function registerBusinessRuleLane(tools) {
51
51
  inputSchema: {
52
52
  environment: environmentArg,
53
53
  schemaCode: z.string().min(1),
54
- full: z.boolean().optional().describe("内联完整规则列表;默认只返回摘要与 detailFile"),
54
+ full: z.boolean().optional().describe("行内联完整字段(id/createdTime/creator/…,并跳过 detailFile 外置);默认行只有 code/name/enabled/status/ruleVersion/defaultRule/latestPublished——平台预置触发行(defaultRule:true)客户端自滤"),
55
55
  capability: capabilityArg,
56
56
  },
57
57
  handler: async (ctx, args, self) => governedRead(ctx, self, args, async (session) => {
58
58
  const rows = wireRows((await wireCall(session, { path: ENDPOINTS.runtimeBusinessRuleListBySchemaCode, query: { schemaCode: args.schemaCode } })).data);
59
+ // N2 (r10 noise pass): the default row is the inventory face —
60
+ // code/name/state/publish-version/is-preset. The audit columns
61
+ // (id/createdTime/creator/developmentMode/templateType/…) only ride
62
+ // with full:true (the old 14-key row). rule.get resolves by business
63
+ // key (schemaCode+ruleCode), so the row id is rarely needed.
64
+ const fullRows = args.full === true;
59
65
  return {
60
66
  schemaCode: args.schemaCode,
61
67
  rules: rows.map((row) => ({
62
- id: row.id,
63
68
  code: row.code,
64
69
  name: row.name,
65
- schemaCode: row.schemaCode,
66
- bizRuleType: row.bizRuleType,
67
70
  enabled: row.enabled,
68
71
  status: row.status,
69
- developmentMode: row.developmentMode,
70
- ruleVersion: row.ruleVersion,
71
- latestPublished: row.latestPublished,
72
- templateType: row.templateType,
73
- defaultRule: row.defaultRule,
74
- createdTime: row.createdTime,
75
- creator: row.creater ?? row.creator,
72
+ ...(row.ruleVersion !== undefined ? { ruleVersion: row.ruleVersion } : {}),
73
+ ...(row.defaultRule !== undefined ? { defaultRule: row.defaultRule } : {}),
74
+ // ticket-80's update-mode readback teaches following the same-code
75
+ // latestPublished row — keep the flag on the default face (5 B).
76
+ ...(row.latestPublished !== undefined ? { latestPublished: row.latestPublished } : {}),
77
+ ...(fullRows
78
+ ? {
79
+ id: row.id,
80
+ schemaCode: row.schemaCode,
81
+ bizRuleType: row.bizRuleType,
82
+ developmentMode: row.developmentMode,
83
+ latestPublished: row.latestPublished,
84
+ templateType: row.templateType,
85
+ createdTime: row.createdTime,
86
+ creator: row.creater ?? row.creator,
87
+ }
88
+ : {}),
76
89
  })),
77
90
  };
78
91
  }, { full: args.full === true, target: `rule.list:${args.schemaCode}` }),
@@ -161,7 +161,7 @@ export const FIELD_LANE_CONTRACT = Object.freeze({
161
161
  tools: Object.freeze({
162
162
  "field.list": Object.freeze({
163
163
  scope: "create publish readback",
164
- description: "List draft/published fields of a model, each with its parsed options (readback face of the field family chain).",
164
+ description: "List draft/published fields of a model. 默认清单面:code/name/type(+typeName)/conditions 信号/shapeWarning——选项族整包 choices 不内联(实测选择字段 ~500B/行);验证 options/subSchema 用 code/fields 选择器或 full:true(readback face of the field family chain)。",
165
165
  }),
166
166
  "field.create": Object.freeze({
167
167
  scope: "create publish readback",
@@ -75,7 +75,7 @@ export function registerFieldLane(tools) {
75
75
  lane: FIELD_LANE,
76
76
  scope: FIELD_TOOLS["field.list"].scope,
77
77
  description: FIELD_TOOLS["field.list"].description,
78
- inputSchema: { environment: environmentArg, schemaCode: z.string(), published: z.boolean().default(false), code: z.string().optional(), fields: z.array(z.string()).optional(), all: z.boolean().optional().describe("默认只返业务字段(过滤 SYSTEM_FIELD_CODES 的 13 个平台字段:id/name/sequenceNo/createdTime/creater/sequenceStatus/…);true 连系统字段一起返"), capability: capabilityArg },
78
+ inputSchema: { environment: environmentArg, schemaCode: z.string(), published: z.boolean().default(false), code: z.string().optional(), fields: z.array(z.string()).optional(), full: z.boolean().optional().describe("行内联完整 options/subSchema;默认清单面只有 code/name/type/typeName(+conditions 信号/shapeWarning),验证 options 用 code/fields 选择器或 full:true"), all: z.boolean().optional().describe("默认只返业务字段(过滤 SYSTEM_FIELD_CODES 的 13 个平台字段:id/name/sequenceNo/createdTime/creater/sequenceStatus/…);true 连系统字段一起返"), capability: capabilityArg },
79
79
  handler: async (ctx, args, self) => governedRead(ctx, self, args, async (session) => {
80
80
  const rows = wireRows((await wireCall(session, { path: ENDPOINTS.fieldList, query: { schemaCode: args.schemaCode, isPublish: args.published ? "true" : "false" } })).data);
81
81
  const mapped = rows.map((row) => {
@@ -103,13 +103,44 @@ export function registerFieldLane(tools) {
103
103
  // (which token-diets to {count,sha256} past 4 KB) through an artifact.
104
104
  const selector = [args.code, ...(args.fields ?? [])].filter((entry) => typeof entry === "string" && entry.length > 0);
105
105
  const selected = selector.length > 0 ? mapped.filter((field) => selector.includes(String(field.code))) : mapped;
106
+ // N1 (r10 noise pass): the DEFAULT face is the inventory — code/name/
107
+ // type(+condition signal/shapeWarning). Options arrays (choices carry
108
+ // their full custom lists inline, ~500B per selection field measured)
109
+ // only echo for a code/fields selector or full:true. Same shape the
110
+ // >4KB window diet already served; promoted to the default so small
111
+ // models stop paying option bytes on inventory reads.
112
+ const detailed = selector.length > 0 || args.full === true;
106
113
  // Round 10: the default face is BUSINESS fields only — 13 of 21 fields on a
107
114
  // typical model are platform system fields, so a caller asking "what fields
108
115
  // does this model have" paid for noise it then had to filter. `all:true`
109
116
  // restores the previous full list (uses the SAME SYSTEM_FIELD_CODES set the
110
117
  // list-view/form scaffolds already filter with).
111
118
  const visible = args.all === true ? selected : selected.filter((field) => !SYSTEM_FIELD_CODES.has(String(field.code)));
112
- return { schemaCode: args.schemaCode, published: args.published === true, ...(selector.length > 0 ? { selected: selector } : {}), ...(args.all !== true ? { businessOnly: true } : {}), fields: visible };
119
+ const projected = detailed
120
+ ? visible
121
+ : visible.map((field) => {
122
+ const options = (field.options ?? {});
123
+ const conditions = Object.keys(FORM_CONDITION_OPTION_KEYS).filter((key) => {
124
+ const value = options[key];
125
+ return key === "readonlyFormula" ? value === true : typeof value === "string" && value.trim() !== "";
126
+ });
127
+ return {
128
+ code: field.code,
129
+ type: field.type,
130
+ ...(field.typeName !== undefined ? { typeName: field.typeName } : {}),
131
+ ...(field.name !== undefined ? { name: field.name } : {}),
132
+ ...(conditions.length > 0 ? { conditions } : {}),
133
+ ...(field.shapeWarning !== undefined ? { shapeWarning: field.shapeWarning } : {}),
134
+ };
135
+ });
136
+ return {
137
+ schemaCode: args.schemaCode,
138
+ published: args.published === true,
139
+ ...(selector.length > 0 ? { selected: selector } : {}),
140
+ ...(args.all !== true ? { businessOnly: true } : {}),
141
+ fields: projected,
142
+ ...(detailed ? {} : { inventory: true, hint: '字段详情(options/subSchema)用 code/fields 选择器或 full:true' }),
143
+ };
113
144
  }, {
114
145
  // Round 4: the default diet reduced the whole list to a count, so agents
115
146
  // fetched the 28 KB artifact just to read field codes (benchmark: 4×28 KB).
@@ -117,6 +148,11 @@ export function registerFieldLane(tools) {
117
148
  // warning). `options` stays out — use code/fields selector for that.
118
149
  target: `field.list:${args.schemaCode}:${args.published === true ? "published" : "draft"}`,
119
150
  compact: (result) => {
151
+ // N1: the handler's DEFAULT face is already the inventory projection;
152
+ // re-projecting here would strip the conditions signal (options are
153
+ // gone by design). Pass it through untouched.
154
+ if (result.inventory === true)
155
+ return result;
120
156
  const fields = Array.isArray(result.fields) ? result.fields : [];
121
157
  return {
122
158
  schemaCode: result.schemaCode,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stalfh233/omc-cli",
3
- "version": "0.4.19",
3
+ "version": "0.4.21",
4
4
  "description": "CloudPivot 8.6 configuration capability CLI — governed, fail-closed, coverage-manifest bounded.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -51,7 +51,7 @@
51
51
  },
52
52
  "dependencies": {
53
53
  "commander": "14.0.3",
54
- "omc-core": "0.4.19",
54
+ "omc-core": "0.4.21",
55
55
  "proper-lockfile": "4.1.2",
56
56
  "write-file-atomic": "6.0.0",
57
57
  "zod": "^3.23.8",
@@ -24,7 +24,7 @@ omc help omc-write-hazards
24
24
  ## 模型字段与关联
25
25
 
26
26
  - **code 定位写前先核在册**:`field.update` / `rule.node.update` 等按 code 定位的精确写,先 `model.inspect` / `field.list` 确认 code 在册;缺码即停并报"目标不存在 + 当前字段清单"——**别凭用户措辞假定 code 正确**(用户可能记错字段名),**也别擅自替换成语义相近的字段**(改错对象比不改更糟)。缺码 `field.update` 本就拒 301001,但写前先核能省一轮失败往返,并在草稿阶段就把"字段不存在"与"需求理解偏差"分清。
27
- - **改名核对以字段读为准**:`field.update` 改名后,`model.inspect` 聚合面的 `fields[].name` 可能仍是旧值(发布态快照/聚合缓存);核对显示名、options 一律用 `field.list` / `field.get` 或 `form.publish` 回读——两处读数不一致时以字段读为准,别误判"写入没生效"而重复写。
27
+ - **改名核对以字段读为准**:`field.update` 改名后,`model.inspect` 聚合面的 `fields[].name` 可能仍是旧值(发布态快照/聚合缓存);核对显示名用 `field.list`(默认清单面有 name);核对 options 用 `field.list` 的 `code` 选择器 / `field.get` 或 `form.publish` 回读——两处读数不一致时以字段读为准,别误判"写入没生效"而重复写。
28
28
  - `propertyEmpty` 默认 `false`。模型层保持可空;必填、只读、可见性在表单和流程节点配置。
29
29
  - 无映射关联单选 `WORK_SHEET` 使用 `mappings: ""`,不要用 `"[]"`。`"[]"` 是非空字符串,设计器会显示“已设置”,但弹窗没有映射行。
30
30
  - 有映射时传非空 JSON 数组字符串,并在 draft/published 两面读回。