@stalfh233/omc-cli 0.4.20 → 0.4.22

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.
package/dist/cli.js CHANGED
@@ -1447,7 +1447,7 @@ const request = requestId();
1447
1447
  main().then((code) => {
1448
1448
  // Commands that own their stdout never grow a trailing envelope. `--version`/
1449
1449
  // `-V` are here because their short-circuit already wrote the bare version.
1450
- if (argv[2] === "call" || argv[2] === "artifact" || argv[2] === "commands" || argv[2] === "describe" || argv[2] === "contract" || argv[2] === "capabilities" || argv[2] === "capability" || argv[2] === "next" || argv[2] === "usage" || argv[2] === "intent" || argv[2] === "help" || argv[2] === "--version" || argv[2] === "-V") {
1450
+ if (argv[2] === "call" || argv[2] === "script" || argv[2] === "artifact" || argv[2] === "commands" || argv[2] === "describe" || argv[2] === "contract" || argv[2] === "capabilities" || argv[2] === "capability" || argv[2] === "next" || argv[2] === "usage" || argv[2] === "intent" || argv[2] === "help" || argv[2] === "--version" || argv[2] === "-V") {
1451
1451
  completeUsage(code);
1452
1452
  finish(code);
1453
1453
  return;
@@ -51,7 +51,7 @@ export function registerBusinessRuleLane(tools) {
51
51
  inputSchema: {
52
52
  environment: environmentArg,
53
53
  schemaCode: z.string().min(1),
54
- full: z.boolean().optional().describe("行内联完整字段(id/createdTime/creator/…,并跳过 detailFile 外置);默认行只有 code/name/enabled/status/ruleVersion/defaultRule——平台预置触发行(defaultRule:true)客户端自滤"),
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) => {
@@ -71,6 +71,9 @@ export function registerBusinessRuleLane(tools) {
71
71
  status: row.status,
72
72
  ...(row.ruleVersion !== undefined ? { ruleVersion: row.ruleVersion } : {}),
73
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 } : {}),
74
77
  ...(fullRows
75
78
  ? {
76
79
  id: row.id,
@@ -1405,6 +1405,11 @@ export function validateRuleNodeGraph(graph, ruleCode, schemaCode) {
1405
1405
  const endNodes = nodeRecords.filter((node) => node.nodeType === "END");
1406
1406
  if (startNodes.length !== 1)
1407
1407
  blockers.push({ code: "rule-graph-start-count", message: `必须恰好 1 个 START 节点(当前 ${startNodes.length})` });
1408
+ // r15 harness finding: a multi-node graph with ZERO routes saves fine but
1409
+ // the platform publish answers 550014 孤立节点 for every non-boundary node —
1410
+ // usually the caller passed the WRONG key (edges/from/to instead of
1411
+ // routes/preNode/postNode, which zod strips silently). Refuse locally, name
1412
+ // the right shape, save the publish round-trip.
1408
1413
  if (endNodes.length < 1)
1409
1414
  blockers.push({ code: "rule-graph-end-missing", message: "至少需要 1 个 END 节点" });
1410
1415
  const systemPersistenceTypes = new Set(["SYSTEM_CREATE", "SYSTEM_UPDATE"]);
@@ -458,8 +458,19 @@ export async function executeRuleSaveWrite(session, args) {
458
458
  validation: blockers,
459
459
  });
460
460
  }
461
- const nodes = preparedGraph.nodes ?? [];
462
- const routes = preparedGraph.routes ?? [];
461
+ const nodes = Array.isArray(preparedGraph.nodes) ? preparedGraph.nodes : [];
462
+ const routes = Array.isArray(preparedGraph.routes) ? preparedGraph.routes : [];
463
+ // r15 harness finding: a multi-node graph with ZERO routes SAVES fine but the
464
+ // platform publish answers 550014 孤立节点 for every non-boundary node — the
465
+ // usual cause is the WRONG edge key (edges/from/to instead of routes/
466
+ // preNode/postNode, silently stripped). Refuse at the save gate, name the
467
+ // right shape, save the publish round-trip.
468
+ if (nodes.length >= 2 && routes.length === 0)
469
+ throw new ToolRefusalError({
470
+ status: "refused",
471
+ blocker: "rule-graph-routes-empty",
472
+ message: `图有 ${nodes.length} 个节点但 0 条 routes——平台发布会判「孤立节点」(550014)。边用 routes:[{preNode:"Start",postNode:"UPDATE_1"},...](不是 edges/from/to,那会被静默剥掉)`,
473
+ });
463
474
  await assertCreateSelectionCompatibility(session, args.schemaCode, Array.isArray(nodes) ? nodes : []);
464
475
  await assertBizActionMappingFieldsExist(session, args.schemaCode, Array.isArray(nodes) ? nodes : []);
465
476
  // Ticket 96: phantom-schema gate — BEFORE the first businessrule wire call
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stalfh233/omc-cli",
3
- "version": "0.4.20",
3
+ "version": "0.4.22",
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.20",
54
+ "omc-core": "0.4.22",
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 两面读回。