@stalfh233/omc-cli 0.4.38 → 0.4.39

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
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  // T04:SQLite 警告过滤器必须保持第一个 import(先于任何拉起 omc-core/node:sqlite 的模块)。
3
3
  import "./sqlite-warning-filter.js";
4
+ import { spawnSync } from "node:child_process";
4
5
  import { createInterface } from "node:readline/promises";
5
6
  import { stdin, argv } from "node:process";
6
7
  import { createRequire } from "node:module";
@@ -113,6 +114,23 @@ async function cmdDoctor(store, environment, serviceCode) {
113
114
  const manifest = loadCoverageManifest();
114
115
  const steps = [];
115
116
  let ok = true;
117
+ // r45 Windows 实测:PowerShell 管道按 GBK(936) 解码 CLI 的 UTF-8 输出 → 全屏乱码,
118
+ // 且用户常误判为「OMC 输出坏了」。doctor 是入口体检,顺手检测活动代码页。
119
+ if (process.platform === "win32") {
120
+ try {
121
+ const chcp = spawnSync("chcp.com", [], { encoding: "utf8" });
122
+ const active = /([0-9]{3,5})\s*$/.exec((chcp.stdout || "").trim().split("\n").pop() ?? "")?.[1];
123
+ if (active && active !== "65001") {
124
+ steps.push(`编码 ⚠ 活动代码页 ${active}(非 65001)——PowerShell 管道会把 CLI 的 UTF-8 中文输出解成乱码;这是终端解码问题不是 OMC 故障。先 \`chcp 65001\` + \`[Console]::OutputEncoding=[Text.Encoding]::UTF8\` 再读 CLI 输出`);
125
+ }
126
+ else if (active === "65001") {
127
+ steps.push("编码 ok 活动代码页 65001(UTF-8,中文输出无乱码风险)");
128
+ }
129
+ }
130
+ catch {
131
+ // chcp 不可用(非传统控制台等)——跳过,不阻塞体检
132
+ }
133
+ }
116
134
  try {
117
135
  const resolved = store.resolveEnvironment(environment);
118
136
  steps.push(`配置 ok 环境=${resolved.name}(来源 ${resolved.source})`);
@@ -367,32 +385,35 @@ function resolvedDefaultEnvironment(store) {
367
385
  return "default";
368
386
  }
369
387
  }
370
- /**
371
- * Bounded JSON-path projection for `artifact get --jq`. Supports dotted
372
- * (`content.activities.0.name`) and slashed (`content/activities/0/name`)
373
- * segments. Not a general jq: a path walk only, so it can never evaluate code.
374
- */
375
388
  function projectJsonPath(value, path) {
376
- const segments = path.replace(/^\//, "").split(/[./]/).filter((segment) => segment.length > 0);
389
+ const normalized = path
390
+ .trim()
391
+ .replace(/^[.\/]+/, "")
392
+ .replace(/\[(\d+)\]/g, ".$1")
393
+ .replace(/\[(?:"([^"]+)"|'([^']+)')\]/g, (_all, dq, sq) => `.${dq || sq}`)
394
+ .replace(/\.{2,}/g, ".");
395
+ const segments = normalized.split(/[./]/).filter((segment) => segment.length > 0);
377
396
  let current = value;
378
397
  for (const segment of segments) {
379
398
  if (Array.isArray(current)) {
380
399
  const index = Number(segment);
381
400
  if (!Number.isInteger(index) || index < 0 || index >= current.length)
382
- return undefined;
401
+ return { missed: true, at: segment, available: `数组长度 ${current.length}(下标 0-${Math.max(current.length - 1, 0)})` };
383
402
  current = current[index];
384
403
  }
385
404
  else if (current && typeof current === "object") {
386
405
  const record = current;
387
- if (!Object.prototype.hasOwnProperty.call(record, segment))
388
- return undefined;
406
+ if (!Object.prototype.hasOwnProperty.call(record, segment)) {
407
+ const keys = Object.keys(record);
408
+ return { missed: true, at: segment, available: keys.length > 0 ? keys.slice(0, 12) : "(该层是空对象)" };
409
+ }
389
410
  current = record[segment];
390
411
  }
391
412
  else {
392
- return undefined;
413
+ return { missed: true, at: segment, available: `路径在第 ${segments.indexOf(segment) + 1} 段之前已到标量/undefined(前段类型 ${current === null ? "null" : typeof current})` };
393
414
  }
394
415
  }
395
- return current;
416
+ return { missed: false, value: current };
396
417
  }
397
418
  async function cmdArtifactGet(id, transport, options = {}) {
398
419
  try {
@@ -443,7 +464,9 @@ async function cmdArtifactGet(id, transport, options = {}) {
443
464
  }
444
465
  if (options.jq !== undefined) {
445
466
  const projected = projectJsonPath(artifact.content.toString("utf8") === "" ? undefined : content, options.jq);
446
- return emitTransportResult({ status: "ok", artifactId: id, sha256: artifact.sha256, path: options.jq, content: projected === undefined ? null : projected }, transport);
467
+ return emitTransportResult(projected.missed
468
+ ? { status: "ok", artifactId: id, sha256: artifact.sha256, path: options.jq, content: null, pathMiss: true, missedAt: projected.at, available: projected.available, hint: `路径未命中段 "${projected.at}"——available 是该层可用的键/范围;方括号下标(a[0])与点式(a.0)等价` }
469
+ : { status: "ok", artifactId: id, sha256: artifact.sha256, path: options.jq, content: projected.value ?? null }, transport);
447
470
  }
448
471
  const result = { status: "ok", artifactId: id, sha256: artifact.sha256, content };
449
472
  if (Buffer.byteLength(JSON.stringify(result), "utf8") > transport.maxOutputBytes)
@@ -1,6 +1,7 @@
1
- // 配方按 lane 分居维护(src/recipes/<lane>.ts);本文件是聚合接缝:保持原中央表的
2
- // 工具键序(消费方按工具名查找;顺序保留供可读性与 ticket-02 快照一致性),并在
3
- // 模块加载时对重复工具键 fail-fast(lane 各自注册后静默覆盖是拆分最大风险)。
1
+ // 配方按 lane 分居维护(src/recipes/<lane>.ts);本文件是聚合接缝:按 lane 分组顺序
2
+ // 合并(非原中央表字面量序——已核实全仓零 Object.keys/entries 枚举消费者,消费方一律
3
+ // 按工具名查找,键序无行为影响),并在模块加载时对重复工具键 fail-fast
4
+ // (lane 各自注册后静默覆盖是拆分最大风险)。
4
5
  import { MODEL_METADATA } from "./recipes/model.js";
5
6
  import { FORM_METADATA } from "./recipes/form.js";
6
7
  import { FIELD_METADATA } from "./recipes/field.js";
@@ -135,7 +135,9 @@ export function registerFieldLane(tools) {
135
135
  });
136
136
  return {
137
137
  schemaCode: args.schemaCode,
138
- published: args.published === true,
138
+ // r45: 这是"本次查询的面选择器"回显(draft/published),不是字段发布状态——
139
+ // 曾被误读为"字段未发布"。改名 face 消歧义;要查发布态用 field.publish 回读或详情面。
140
+ face: args.published === true ? "published" : "draft",
139
141
  ...(selector.length > 0 ? { selected: selector } : {}),
140
142
  ...(args.all !== true ? { businessOnly: true } : {}),
141
143
  fields: projected,
@@ -524,7 +524,7 @@ export function registerRuntimeDataLane(tools) {
524
524
  inputSchema: {
525
525
  environment: environmentArg,
526
526
  schemaCode: z.string(),
527
- bizObjectId: z.string({ required_error: "bizObjectId 必填(业务对象 id;参数名是 bizObjectId,不是 id。从 data.submit 读回的 objectId/sequenceNo 或 data.list 的 row.bizObjectId 取)" }),
527
+ bizObjectId: z.string({ required_error: "bizObjectId 必填(参数名就是 bizObjectId——不是 id 也不是 objectId,r44 两个 agent 都猜了 objectId;取值来自 data.submit 读回的 objectId/sequenceNo 或 data.list 的 row.bizObjectId)" }),
528
528
  full: z.boolean().optional().describe("返回未裁剪的完整业务对象(含 owner/creater 等系统字段;默认返回业务字段+身份的精简记录)"),
529
529
  capability: capabilityArg,
530
530
  },
@@ -38,7 +38,7 @@ const plainSubmit = Object.freeze({
38
38
  { code: "submit-biz-object-absent", action: "bizObjectId 在平台无行(304001)——回 data.save 重建草稿后再直提" },
39
39
  { code: "invalid-input", action: "带了 workItemId/workflowInstanceId 时必须同时带 bizObjectId(fail-closed)" },
40
40
  ],
41
- notes: "r23 复盘修正:本配方曾教先 save 再 submit 两步——正确路径是无 id 一调(业务约定:正式数据一律 data.submit)。Create/Update 规则只在 COMPLETED 分发(DomainServiceImpl.java:240-248);规则效果以提交读回/data.load 为准。data.save 定位=草稿/暂存",
41
+ notes: "r23 复盘修正:本配方曾教先 save 再 submit 两步——正确路径是无 id 一调(业务约定:正式数据一律 data.submit)。Create/Update 规则只在 COMPLETED 分发(DomainServiceImpl.java:240-248);规则效果以提交读回/data.load 为准(data.load 参数名=bizObjectId,直接用提交读回的 objectId)。data.save 定位=草稿/暂存",
42
42
  requiresEnvironmentDerivedIds: true,
43
43
  });
44
44
  const workflowSubmit = Object.freeze({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stalfh233/omc-cli",
3
- "version": "0.4.38",
3
+ "version": "0.4.39",
4
4
  "description": "CloudPivot 8.6 configuration capability CLI — governed, fail-closed, coverage-manifest bounded.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -50,9 +50,9 @@
50
50
  "access": "public"
51
51
  },
52
52
  "dependencies": {
53
- "@stalfh233/omc-fake-platform": "0.4.38",
53
+ "@stalfh233/omc-fake-platform": "0.4.39",
54
54
  "commander": "14.0.3",
55
- "omc-core": "0.4.38",
55
+ "omc-core": "0.4.39",
56
56
  "proper-lockfile": "4.1.2",
57
57
  "write-file-atomic": "6.0.0",
58
58
  "zod": "^3.23.8",